works!
This commit is contained in:
parent
eda3762fba
commit
a2d512af73
@ -1,6 +1,7 @@
|
|||||||
19/3/12 started 7.29.0
|
19/3/12 started 7.29.0
|
||||||
- better PNG alpha handling
|
- better PNG alpha handling
|
||||||
- sanity-check PNG read geometry
|
- sanity-check PNG read geometry
|
||||||
|
- add dzsave, save in deep zoom format
|
||||||
|
|
||||||
13/3/12 started 7.28.2
|
13/3/12 started 7.28.2
|
||||||
- xres/yres tiffsave args were broken
|
- xres/yres tiffsave args were broken
|
||||||
|
63
acinclude.m4
63
acinclude.m4
@ -501,3 +501,66 @@ $2])
|
|||||||
CPPFLAGS="$save_CPPFLAGS"
|
CPPFLAGS="$save_CPPFLAGS"
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl @synopsis AC_FUNC_MKDIR
|
||||||
|
dnl
|
||||||
|
dnl Check whether mkdir() is mkdir or _mkdir, and whether it takes one
|
||||||
|
dnl or two arguments.
|
||||||
|
dnl
|
||||||
|
dnl This macro can define HAVE_MKDIR, HAVE__MKDIR, and
|
||||||
|
dnl MKDIR_TAKES_ONE_ARG, which are expected to be used as follows:
|
||||||
|
dnl
|
||||||
|
dnl #if HAVE_MKDIR
|
||||||
|
dnl # if MKDIR_TAKES_ONE_ARG
|
||||||
|
dnl /* MinGW32 */
|
||||||
|
dnl # define mkdir(a, b) mkdir(a)
|
||||||
|
dnl # endif
|
||||||
|
dnl #else
|
||||||
|
dnl # if HAVE__MKDIR
|
||||||
|
dnl /* plain Windows 32 */
|
||||||
|
dnl # define mkdir(a, b) _mkdir(a)
|
||||||
|
dnl # else
|
||||||
|
dnl # error "Don't know how to create a directory on this system."
|
||||||
|
dnl # endif
|
||||||
|
dnl #endif
|
||||||
|
dnl
|
||||||
|
dnl @category C
|
||||||
|
dnl @author Alexandre Duret-Lutz <adl@gnu.org>
|
||||||
|
dnl @version 2003-12-28
|
||||||
|
dnl @license GPLWithACException
|
||||||
|
|
||||||
|
AC_DEFUN([AC_FUNC_MKDIR],
|
||||||
|
[AC_CHECK_FUNCS([mkdir _mkdir])
|
||||||
|
AC_CACHE_CHECK([whether mkdir takes one argument],
|
||||||
|
[ac_cv_mkdir_takes_one_arg],
|
||||||
|
[AC_TRY_COMPILE([
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#if HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif
|
||||||
|
], [mkdir (".");],
|
||||||
|
[ac_cv_mkdir_takes_one_arg=yes], [ac_cv_mkdir_takes_one_arg=no])])
|
||||||
|
if test x"$ac_cv_mkdir_takes_one_arg" = xyes; then
|
||||||
|
AC_DEFINE([MKDIR_TAKES_ONE_ARG], 1,
|
||||||
|
[Define if mkdir takes only one argument.])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Note:
|
||||||
|
dnl =====
|
||||||
|
dnl I have not implemented the following suggestion because I don't have
|
||||||
|
dnl access to such a broken environment to test the macro. So I'm just
|
||||||
|
dnl appending the comments here in case you have, and want to fix
|
||||||
|
dnl AC_FUNC_MKDIR that way.
|
||||||
|
dnl
|
||||||
|
dnl |Thomas E. Dickey (dickey@herndon4.his.com) said:
|
||||||
|
dnl | it doesn't cover the problem areas (compilers that mistreat mkdir
|
||||||
|
dnl | may prototype it in dir.h and dirent.h, for instance).
|
||||||
|
dnl |
|
||||||
|
dnl |Alexandre:
|
||||||
|
dnl | Would it be sufficient to check for these headers and #include
|
||||||
|
dnl | them in the AC_TRY_COMPILE block? (and is AC_HEADER_DIRENT
|
||||||
|
dnl | suitable for this?)
|
||||||
|
dnl |
|
||||||
|
dnl |Thomas:
|
||||||
|
dnl | I think that might be a good starting point (with the set of recommended
|
||||||
|
dnl | ifdef's and includes for AC_HEADER_DIRENT, of course).
|
||||||
|
@ -62,6 +62,7 @@ struct _Layer {
|
|||||||
VipsImage *image; /* The image we build */
|
VipsImage *image; /* The image we build */
|
||||||
|
|
||||||
VipsRegion *strip; /* The current strip of pixels */
|
VipsRegion *strip; /* The current strip of pixels */
|
||||||
|
VipsRegion *copy; /* Pixels we copy to the next strip */
|
||||||
|
|
||||||
int sub; /* Subsample factor for this layer */
|
int sub; /* Subsample factor for this layer */
|
||||||
int n; /* Layer number ... 0 for smallest */
|
int n; /* Layer number ... 0 for smallest */
|
||||||
@ -96,6 +97,7 @@ static void
|
|||||||
layer_free( Layer *layer )
|
layer_free( Layer *layer )
|
||||||
{
|
{
|
||||||
VIPS_FREEF( g_object_unref, layer->strip );
|
VIPS_FREEF( g_object_unref, layer->strip );
|
||||||
|
VIPS_FREEF( g_object_unref, layer->copy );
|
||||||
VIPS_FREEF( g_object_unref, layer->image );
|
VIPS_FREEF( g_object_unref, layer->image );
|
||||||
|
|
||||||
VIPS_FREEF( layer_free, layer->below );
|
VIPS_FREEF( layer_free, layer->below );
|
||||||
@ -122,6 +124,9 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above, int w, int h )
|
|||||||
VipsRect strip;
|
VipsRect strip;
|
||||||
|
|
||||||
layer->dz = dz;
|
layer->dz = dz;
|
||||||
|
layer->image = NULL;
|
||||||
|
layer->strip = NULL;
|
||||||
|
layer->copy = NULL;
|
||||||
|
|
||||||
if( !above )
|
if( !above )
|
||||||
/* Top of pyramid.
|
/* Top of pyramid.
|
||||||
@ -134,13 +139,20 @@ pyramid_build( VipsForeignSaveDz *dz, Layer *above, int w, int h )
|
|||||||
layer->above = above;
|
layer->above = above;
|
||||||
|
|
||||||
layer->image = vips_image_new();
|
layer->image = vips_image_new();
|
||||||
if( vips_image_copy_fields( layer->image, save->in ) ) {
|
if( vips_image_copy_fields( layer->image, save->ready ) ) {
|
||||||
layer_free( layer );
|
layer_free( layer );
|
||||||
return( NULL );
|
return( NULL );
|
||||||
}
|
}
|
||||||
layer->image->Xsize = w;
|
layer->image->Xsize = w;
|
||||||
layer->image->Ysize = h;
|
layer->image->Ysize = h;
|
||||||
layer->strip = vips_region_new( save->in );
|
layer->strip = vips_region_new( layer->image );
|
||||||
|
layer->copy = vips_region_new( layer->image );
|
||||||
|
|
||||||
|
/* The regions will get used in the bg thread callback, so make sure
|
||||||
|
* we don't own them.
|
||||||
|
*/
|
||||||
|
vips__region_no_ownership( layer->strip );
|
||||||
|
vips__region_no_ownership( layer->copy );
|
||||||
|
|
||||||
/* Build a line of tiles here.
|
/* Build a line of tiles here.
|
||||||
*/
|
*/
|
||||||
@ -194,10 +206,8 @@ static void
|
|||||||
shrink_region_labpack( VipsRegion *from, VipsRegion *to )
|
shrink_region_labpack( VipsRegion *from, VipsRegion *to )
|
||||||
{
|
{
|
||||||
int ls = VIPS_REGION_LSKIP( from );
|
int ls = VIPS_REGION_LSKIP( from );
|
||||||
int ps = VIPS_IMAGE_SIZEOF_PEL( from->im );
|
|
||||||
int nb = from->im->Bands;
|
|
||||||
|
|
||||||
int x, y, z;
|
int x, y;
|
||||||
VipsRect target;
|
VipsRect target;
|
||||||
|
|
||||||
/* Calculate output size and position.
|
/* Calculate output size and position.
|
||||||
@ -215,7 +225,7 @@ shrink_region_labpack( VipsRegion *from, VipsRegion *to )
|
|||||||
|
|
||||||
/* Ignore the extra bits for speed.
|
/* Ignore the extra bits for speed.
|
||||||
*/
|
*/
|
||||||
for( x = 0; x < out.width; x++ ) {
|
for( x = 0; x < target.width; x++ ) {
|
||||||
signed char *sp = (signed char *) p;
|
signed char *sp = (signed char *) p;
|
||||||
unsigned char *up = (unsigned char *) p;
|
unsigned char *up = (unsigned char *) p;
|
||||||
|
|
||||||
@ -357,8 +367,10 @@ strip_save( Layer *layer )
|
|||||||
tile.height = dz->tile_height + dz->overlap;
|
tile.height = dz->tile_height + dz->overlap;
|
||||||
vips_rect_intersectrect( &tile, &strip->valid, &tile );
|
vips_rect_intersectrect( &tile, &strip->valid, &tile );
|
||||||
|
|
||||||
|
/* Extract relative to the strip top-left corner.
|
||||||
|
*/
|
||||||
if( vips_extract_area( image, &extr,
|
if( vips_extract_area( image, &extr,
|
||||||
tile.left, tile.top, tile.width, tile.height, NULL ) ) {
|
tile.left, 0, tile.width, tile.height, NULL ) ) {
|
||||||
g_object_unref( image );
|
g_object_unref( image );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
@ -368,7 +380,7 @@ strip_save( Layer *layer )
|
|||||||
x, y,
|
x, y,
|
||||||
dz->suffix );
|
dz->suffix );
|
||||||
|
|
||||||
if( vips_image_write_file( extr, vips_buf_all( &buf ) ) ) {
|
if( vips_image_write_to_file( extr, vips_buf_all( &buf ) ) ) {
|
||||||
g_object_unref( image );
|
g_object_unref( image );
|
||||||
g_object_unref( extr );
|
g_object_unref( extr );
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -391,10 +403,12 @@ static int
|
|||||||
strip_arrived( Layer *layer )
|
strip_arrived( Layer *layer )
|
||||||
{
|
{
|
||||||
VipsForeignSaveDz *dz = layer->dz;
|
VipsForeignSaveDz *dz = layer->dz;
|
||||||
|
VipsForeignSave *save = VIPS_FOREIGN_SAVE( dz );
|
||||||
Layer *below = layer->below;
|
Layer *below = layer->below;
|
||||||
|
|
||||||
VipsRect target;
|
VipsRect target;
|
||||||
VipsRect new_strip;
|
VipsRect new_strip;
|
||||||
|
VipsRect overlap;
|
||||||
|
|
||||||
if( strip_save( layer ) )
|
if( strip_save( layer ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -410,36 +424,45 @@ strip_arrived( Layer *layer )
|
|||||||
*/
|
*/
|
||||||
if( !vips_rect_isempty( &target ) &&
|
if( !vips_rect_isempty( &target ) &&
|
||||||
below ) {
|
below ) {
|
||||||
VipsRect overlap;
|
|
||||||
VipsRect overlap;
|
|
||||||
|
|
||||||
/* Shrink into place.
|
/* Shrink into place.
|
||||||
*/
|
*/
|
||||||
if( dz->image->Coding == VIPS_CODING_NONE )
|
if( save->ready->Coding == VIPS_CODING_NONE )
|
||||||
shrink_region( layer->strip, below->strip,
|
shrink_region( layer->strip, below->strip );
|
||||||
target.left, target.top );
|
|
||||||
else
|
else
|
||||||
shrink_region_labpack( layer->strip, below->strip,
|
shrink_region_labpack( layer->strip, below->strip );
|
||||||
target.left, target.top );
|
|
||||||
|
|
||||||
/* If we've filled the strip of the layer below, recurse.
|
/* If we've filled the strip of the layer below, recurse.
|
||||||
*/
|
*/
|
||||||
if( VIPS_RECT_BOTTOM( &target ) ==
|
if( VIPS_RECT_BOTTOM( &target ) ==
|
||||||
VIPS_RECT_BOTTOM( &below->strip.valid ) &&
|
VIPS_RECT_BOTTOM( &below->strip->valid ) &&
|
||||||
strip_arrived( below ) )
|
strip_arrived( below ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Move our strip down the image. We need to keep ->overlap pixels from
|
/* Move our strip down the image.
|
||||||
* the end of the region.
|
|
||||||
*/
|
*/
|
||||||
new_strip.left = 0;
|
new_strip.left = 0;
|
||||||
new_strip.top = layer->region->valid.top + layer->region->valid.height;
|
new_strip.top = layer->strip->valid.top + layer->strip->valid.height;
|
||||||
new_strip.width = layer->image->Xsize;
|
new_strip.width = layer->image->Xsize;
|
||||||
new_strip.height = dz->tile_height + dz->overlap;
|
new_strip.height = dz->tile_height + dz->overlap;
|
||||||
|
|
||||||
|
vips_rect_intersectrect( &new_strip, &layer->strip->valid, &overlap );
|
||||||
|
if( !vips_rect_isempty( &overlap ) ) {
|
||||||
|
/* There are some pixels we need to copy over.
|
||||||
|
*/
|
||||||
|
if( vips_region_buffer( layer->copy, &overlap ) )
|
||||||
|
return( -1 );
|
||||||
|
vips_region_copy( layer->strip, layer->copy,
|
||||||
|
&overlap, overlap.left, overlap.top );
|
||||||
|
}
|
||||||
|
|
||||||
if( vips_region_buffer( layer->strip, &new_strip ) )
|
if( vips_region_buffer( layer->strip, &new_strip ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
|
if( !vips_rect_isempty( &overlap ) )
|
||||||
|
vips_region_copy( layer->copy, layer->strip,
|
||||||
|
&overlap, overlap.left, overlap.top );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,7 +481,7 @@ pyramid_strip( VipsRegion *region, VipsRect *area, void *a )
|
|||||||
|
|
||||||
/* Write what we can into the current top strip.
|
/* Write what we can into the current top strip.
|
||||||
*/
|
*/
|
||||||
vips_rect_intersectrect( area, &dz->layer->strip.valid,
|
vips_rect_intersectrect( area, &dz->layer->strip->valid,
|
||||||
&overlap );
|
&overlap );
|
||||||
vips_region_copy( region, dz->layer->strip,
|
vips_region_copy( region, dz->layer->strip,
|
||||||
&overlap, overlap.left, overlap.top );
|
&overlap, overlap.left, overlap.top );
|
||||||
@ -466,7 +489,7 @@ pyramid_strip( VipsRegion *region, VipsRect *area, void *a )
|
|||||||
/* If we've filled the strip, write.
|
/* If we've filled the strip, write.
|
||||||
*/
|
*/
|
||||||
if( VIPS_RECT_BOTTOM( &overlap ) ==
|
if( VIPS_RECT_BOTTOM( &overlap ) ==
|
||||||
VIPS_RECT_BOTTOM( &dz->layer->strip.valid ) &&
|
VIPS_RECT_BOTTOM( &dz->layer->strip->valid ) &&
|
||||||
strip_arrived( dz->layer ) )
|
strip_arrived( dz->layer ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
@ -482,8 +505,6 @@ vips_foreign_save_dz_build( VipsObject *object )
|
|||||||
VipsForeignSave *save = (VipsForeignSave *) object;
|
VipsForeignSave *save = (VipsForeignSave *) object;
|
||||||
VipsForeignSaveDz *dz = (VipsForeignSaveDz *) object;
|
VipsForeignSaveDz *dz = (VipsForeignSaveDz *) object;
|
||||||
|
|
||||||
char *p;
|
|
||||||
|
|
||||||
if( VIPS_OBJECT_CLASS( vips_foreign_save_dz_parent_class )->
|
if( VIPS_OBJECT_CLASS( vips_foreign_save_dz_parent_class )->
|
||||||
build( object ) )
|
build( object ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
@ -500,15 +521,23 @@ vips_foreign_save_dz_build( VipsObject *object )
|
|||||||
return( -1 );
|
return( -1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( dz->overlap >= dz->tile_width ||
|
||||||
|
dz->overlap >= dz->tile_height ) {
|
||||||
|
vips_error( "dzsave",
|
||||||
|
"%s", _( "overlap must be less than tile "
|
||||||
|
"width and height" ) ) ;
|
||||||
|
return( -1 );
|
||||||
|
}
|
||||||
|
|
||||||
/* Build the skeleton of the image pyramid.
|
/* Build the skeleton of the image pyramid.
|
||||||
*/
|
*/
|
||||||
if( !(dz->layer = pyramid_build( dz,
|
if( !(dz->layer = pyramid_build( dz,
|
||||||
NULL, save->read->Xsize, save->read->Ysize )) )
|
NULL, save->ready->Xsize, save->ready->Ysize )) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
if( pyramid_mkdir( dz ) )
|
if( pyramid_mkdir( dz ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
if( vips_sink_disc( save->read, pyramid_strip, dz ) )
|
if( vips_sink_disc( save->ready, pyramid_strip, dz ) )
|
||||||
return( -1 );
|
return( -1 );
|
||||||
|
|
||||||
return( 0 );
|
return( 0 );
|
||||||
@ -532,6 +561,8 @@ static int bandfmt_dz[10] = {
|
|||||||
UC, C, US, S, UI, I, F, F, D, D
|
UC, C, US, S, UI, I, F, F, D, D
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *dz_suffs[] = { ".dz", NULL };
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class )
|
vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class )
|
||||||
{
|
{
|
||||||
@ -548,6 +579,8 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class )
|
|||||||
object_class->description = _( "save image to deep zoom format" );
|
object_class->description = _( "save image to deep zoom format" );
|
||||||
object_class->build = vips_foreign_save_dz_build;
|
object_class->build = vips_foreign_save_dz_build;
|
||||||
|
|
||||||
|
foreign_class->suffs = dz_suffs;
|
||||||
|
|
||||||
save_class->saveable = VIPS_SAVEABLE_ANY;
|
save_class->saveable = VIPS_SAVEABLE_ANY;
|
||||||
save_class->format_table = bandfmt_dz;
|
save_class->format_table = bandfmt_dz;
|
||||||
save_class->coding[VIPS_CODING_LABQ] = TRUE;
|
save_class->coding[VIPS_CODING_LABQ] = TRUE;
|
||||||
@ -571,7 +604,7 @@ vips_foreign_save_dz_class_init( VipsForeignSaveDzClass *class )
|
|||||||
_( "Tile overlap in pixels" ),
|
_( "Tile overlap in pixels" ),
|
||||||
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
VIPS_ARGUMENT_OPTIONAL_INPUT,
|
||||||
G_STRUCT_OFFSET( VipsForeignSaveDz, overlap ),
|
G_STRUCT_OFFSET( VipsForeignSaveDz, overlap ),
|
||||||
1, 1024, 1 );
|
0, 1024, 0 );
|
||||||
|
|
||||||
VIPS_ARG_INT( class, "tile_width", 11,
|
VIPS_ARG_INT( class, "tile_width", 11,
|
||||||
_( "Tile width" ),
|
_( "Tile width" ),
|
||||||
@ -593,7 +626,7 @@ static void
|
|||||||
vips_foreign_save_dz_init( VipsForeignSaveDz *dz )
|
vips_foreign_save_dz_init( VipsForeignSaveDz *dz )
|
||||||
{
|
{
|
||||||
VIPS_SETSTR( dz->suffix, ".jpg" );
|
VIPS_SETSTR( dz->suffix, ".jpg" );
|
||||||
dz->overlap = 1;
|
dz->overlap = 0;
|
||||||
dz->tile_width = 128;
|
dz->tile_width = 128;
|
||||||
dz->tile_height = 128;
|
dz->tile_height = 128;
|
||||||
}
|
}
|
||||||
|
@ -2331,7 +2331,7 @@ vips_matload( const char *filename, VipsImage **out, ... )
|
|||||||
* Returns: 0 on success, -1 on error.
|
* Returns: 0 on success, -1 on error.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
vips_dzsave( VIpsImage *in, const char *dirname, ... )
|
vips_dzsave( VipsImage *in, const char *dirname, ... )
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
int result;
|
int result;
|
||||||
|
@ -1199,7 +1199,7 @@ vips_mkdirf( const char *name, ... )
|
|||||||
|
|
||||||
/* Try that.
|
/* Try that.
|
||||||
*/
|
*/
|
||||||
if( !mkdir( buf1, 0755 ) ) {
|
if( mkdir( buf1, 0755 ) ) {
|
||||||
vips_error( "mkdirf",
|
vips_error( "mkdirf",
|
||||||
_( "unable to create directory \"%s\", %s" ),
|
_( "unable to create directory \"%s\", %s" ),
|
||||||
buf1, strerror( errno ) );
|
buf1, strerror( errno ) );
|
||||||
|
Loading…
Reference in New Issue
Block a user