just one sink_disc() for magicksave
we used to cut the input image into tiles, then sink_disc() for each one ... instead, make a single sink_disc() and chop in _generate simpler and faster
This commit is contained in:
parent
30b5c49d0b
commit
f41c1439c9
@ -57,13 +57,19 @@ typedef struct _VipsForeignSaveMagick {
|
||||
char *format;
|
||||
int quality;
|
||||
|
||||
Image *images;
|
||||
ImageInfo *image_info;
|
||||
ExceptionInfo *exception;
|
||||
|
||||
Image *current_image;
|
||||
char *map;
|
||||
StorageType storage_type;
|
||||
Image *images;
|
||||
Image *current_image;
|
||||
|
||||
int page_height;
|
||||
|
||||
/* The position of current_image in the output.
|
||||
*/
|
||||
VipsRect position;
|
||||
|
||||
} VipsForeignSaveMagick;
|
||||
|
||||
typedef VipsForeignSaveClass VipsForeignSaveMagickClass;
|
||||
@ -89,15 +95,48 @@ vips_foreign_save_magick_dispose( GObject *gobject )
|
||||
dispose( gobject );
|
||||
}
|
||||
|
||||
/* Move current_image on to the next image we will write.
|
||||
*/
|
||||
static int
|
||||
vips_foreign_save_magick_set_properties( VipsForeignSaveMagick *magick,
|
||||
Image *image, VipsImage *im )
|
||||
vips_foreign_save_magick_next_image( VipsForeignSaveMagick *magick )
|
||||
{
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( magick );
|
||||
VipsForeignSave *save = (VipsForeignSave *) magick;
|
||||
VipsImage *im = save->ready;
|
||||
|
||||
Image *image;
|
||||
int status;
|
||||
int number;
|
||||
const char *str;
|
||||
|
||||
g_assert( !magick->current_image );
|
||||
|
||||
if( magick->images == NULL ) {
|
||||
if( !(image = magick_acquire_image( magick->image_info,
|
||||
magick->exception )) )
|
||||
return( -1 );
|
||||
|
||||
magick->images = image;
|
||||
magick->position.top = 0;
|
||||
magick->position.left = 0;
|
||||
magick->position.width = im->Xsize;
|
||||
magick->position.height = magick->page_height;
|
||||
}
|
||||
else {
|
||||
image = GetLastImageInList( magick->images );
|
||||
magick_acquire_next_image( magick->image_info, image,
|
||||
magick->exception );
|
||||
if( GetNextImageInList( image ) == NULL )
|
||||
return( -1 );
|
||||
|
||||
image = SyncNextImageInList( image );
|
||||
magick->position.top += magick->page_height;
|
||||
}
|
||||
|
||||
if( !magick_set_image_size( image,
|
||||
im->Xsize, magick->page_height, magick->exception ) )
|
||||
return( -1 );
|
||||
|
||||
if( vips_image_get_typeof( im, "gif-delay" ) &&
|
||||
!vips_image_get_int( im, "gif-delay", &number ) )
|
||||
image->delay = (size_t) number;
|
||||
@ -120,96 +159,69 @@ vips_foreign_save_magick_set_properties( VipsForeignSaveMagick *magick,
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
magick->current_image = image;
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
/* We've written all the pixels to current_image ... finish it off ready to
|
||||
* move on.
|
||||
*/
|
||||
static void
|
||||
vips_foreign_save_magick_end_image( VipsForeignSaveMagick *magick )
|
||||
{
|
||||
if( magick->current_image ) {
|
||||
magick_inherit_exception( magick->exception,
|
||||
magick->current_image );
|
||||
magick->current_image = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Another block of pixels have arrived from libvips.
|
||||
*/
|
||||
static int
|
||||
magick_write_block( VipsRegion *region, VipsRect *area, void *a )
|
||||
vips_foreign_save_magick_write_block( VipsRegion *region, VipsRect *area,
|
||||
void *a )
|
||||
{
|
||||
VipsForeignSaveMagick *magick = (VipsForeignSaveMagick *) a;
|
||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( magick );
|
||||
|
||||
int status;
|
||||
void *p;
|
||||
VipsRect pixels;
|
||||
|
||||
p = VIPS_REGION_ADDR( region, area->left, area->top );
|
||||
pixels = region->valid;
|
||||
do {
|
||||
VipsRect hit;
|
||||
void *p;
|
||||
int status;
|
||||
|
||||
status = magick_import_pixels( magick->current_image,
|
||||
area->left, area->top, area->width, area->height,
|
||||
magick->map, magick->storage_type,
|
||||
p,
|
||||
magick->exception );
|
||||
|
||||
return( status == MagickFalse ? -1 : 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_save_magick_create_one( VipsForeignSaveMagick *magick,
|
||||
VipsImage *im )
|
||||
{
|
||||
Image *image;
|
||||
int status;
|
||||
|
||||
if( magick->images == NULL ) {
|
||||
if( !(image = magick_acquire_image( magick->image_info,
|
||||
magick->exception )) )
|
||||
if( !magick->current_image &&
|
||||
vips_foreign_save_magick_next_image( magick ) )
|
||||
return( -1 );
|
||||
|
||||
magick->images = image;
|
||||
}
|
||||
else {
|
||||
image = GetLastImageInList( magick->images );
|
||||
magick_acquire_next_image( magick->image_info, image,
|
||||
magick->exception );
|
||||
if( GetNextImageInList( image ) == NULL )
|
||||
vips_rect_intersectrect( &pixels, &magick->position, &hit );
|
||||
p = VIPS_REGION_ADDR( region, hit.left, hit.top );
|
||||
if( !magick_import_pixels( magick->current_image,
|
||||
hit.left, hit.top - magick->position.top,
|
||||
hit.width, hit.height,
|
||||
magick->map, magick->storage_type,
|
||||
p,
|
||||
magick->exception ) ) {
|
||||
magick_vips_error( class->nickname,
|
||||
magick->exception );
|
||||
return( -1 );
|
||||
}
|
||||
|
||||
image = SyncNextImageInList( image );
|
||||
}
|
||||
/* Have we filled the page.
|
||||
*/
|
||||
if( VIPS_RECT_BOTTOM( &hit ) ==
|
||||
VIPS_RECT_BOTTOM( &magick->position ) )
|
||||
vips_foreign_save_magick_end_image( magick );
|
||||
|
||||
if( !magick_set_image_size( image, im->Xsize, im->Ysize,
|
||||
magick->exception ) )
|
||||
return( -1 );
|
||||
if( vips_foreign_save_magick_set_properties( magick, image, im ) )
|
||||
return( -1 );
|
||||
pixels.top += hit.height;
|
||||
pixels.height -= hit.height;
|
||||
} while( pixels.height > 0 );
|
||||
|
||||
magick->current_image = image;
|
||||
status = vips_sink_disc( im, magick_write_block, magick );
|
||||
|
||||
magick_inherit_exception( magick->exception, image );
|
||||
|
||||
return( status );
|
||||
}
|
||||
|
||||
static int
|
||||
vips_foreign_save_magick_create( VipsForeignSaveMagick *magick, VipsImage *im )
|
||||
{
|
||||
int page_height;
|
||||
int status;
|
||||
int top;
|
||||
|
||||
page_height = 0;
|
||||
if( vips_image_get_typeof( im, VIPS_META_PAGE_HEIGHT ) &&
|
||||
vips_image_get_int( im, VIPS_META_PAGE_HEIGHT, &page_height ) )
|
||||
;
|
||||
if( page_height <= 0 )
|
||||
page_height = im->Ysize;
|
||||
|
||||
status = 0;
|
||||
for( top = 0; top < im->Ysize; top += page_height ) {
|
||||
VipsImage *x;
|
||||
|
||||
if( vips_crop( im, &x, 0, top, im->Xsize, page_height, NULL ) )
|
||||
return( -1 );
|
||||
|
||||
status = vips_foreign_save_magick_create_one( magick, x );
|
||||
|
||||
g_object_unref( x );
|
||||
|
||||
if( status )
|
||||
break;
|
||||
}
|
||||
|
||||
return( status );
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
static int
|
||||
@ -311,10 +323,17 @@ vips_foreign_save_magick_build( VipsObject *object )
|
||||
if( magick->quality > 0 )
|
||||
magick->image_info->quality = magick->quality;
|
||||
|
||||
if( vips_foreign_save_magick_create( magick, im ) ) {
|
||||
magick_vips_error( class->nickname, magick->exception );
|
||||
return( -1 );
|
||||
}
|
||||
magick->page_height = 0;
|
||||
if( vips_image_get_typeof( im, VIPS_META_PAGE_HEIGHT ) &&
|
||||
vips_image_get_int( im, VIPS_META_PAGE_HEIGHT,
|
||||
&magick->page_height ) )
|
||||
return( -1 );
|
||||
if( magick->page_height <= 0 )
|
||||
magick->page_height = im->Ysize;
|
||||
|
||||
if( vips_sink_disc( im,
|
||||
vips_foreign_save_magick_write_block, magick ) )
|
||||
return( -1 );
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user