fix matlab block test

This commit is contained in:
John Cupitt 2022-07-30 12:36:56 +01:00
parent cf97ea3ea1
commit d17fd9b640
2 changed files with 115 additions and 115 deletions

View File

@ -7,7 +7,7 @@
/* /*
This file is part of VIPS. This file is part of VIPS.
VIPS is free software; you can redistribute it and/or modify VIPS is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or the Free Software Foundation; either version 2 of the License, or
@ -107,7 +107,7 @@ typedef struct _VipsForeignSaveJp2k {
*/ */
gboolean subsample; gboolean subsample;
/* If we converto RGB to YCC during save. /* If we convert RGB to YCC during save.
*/ */
gboolean save_as_ycc; gboolean save_as_ycc;
@ -118,7 +118,7 @@ typedef struct _VipsForeignSaveJp2k {
typedef VipsForeignSaveClass VipsForeignSaveJp2kClass; typedef VipsForeignSaveClass VipsForeignSaveJp2kClass;
G_DEFINE_ABSTRACT_TYPE( VipsForeignSaveJp2k, vips_foreign_save_jp2k, G_DEFINE_ABSTRACT_TYPE( VipsForeignSaveJp2k, vips_foreign_save_jp2k,
VIPS_TYPE_FOREIGN_SAVE ); VIPS_TYPE_FOREIGN_SAVE );
static void static void
@ -160,25 +160,25 @@ vips_foreign_save_jp2k_target( VipsTarget *target )
/* FALSE means a write stream. /* FALSE means a write stream.
*/ */
if( !(stream = opj_stream_create( OPJ_J2K_STREAM_CHUNK_SIZE, FALSE )) ) if( !(stream = opj_stream_create( OPJ_J2K_STREAM_CHUNK_SIZE, FALSE )) )
return( NULL ); return( NULL );
opj_stream_set_user_data( stream, target, NULL ); opj_stream_set_user_data( stream, target, NULL );
opj_stream_set_write_function( stream, opj_stream_set_write_function( stream,
vips_foreign_save_jp2k_write_target ); vips_foreign_save_jp2k_write_target );
return( stream ); return( stream );
} }
static void static void
vips_foreign_save_jp2k_error_callback( const char *msg, void *client ) vips_foreign_save_jp2k_error_callback( const char *msg, void *client )
{ {
vips_error( "jp2ksave", "%s", msg ); vips_error( "jp2ksave", "%s", msg );
} }
/* The openjpeg info and warning callbacks are incredibly chatty. /* The openjpeg info and warning callbacks are incredibly chatty.
*/ */
static void static void
vips_foreign_save_jp2k_warning_callback( const char *msg, void *client ) vips_foreign_save_jp2k_warning_callback( const char *msg, void *client )
{ {
#ifdef DEBUG #ifdef DEBUG
@ -186,7 +186,7 @@ vips_foreign_save_jp2k_warning_callback( const char *msg, void *client )
#endif /*DEBUG*/ #endif /*DEBUG*/
} }
static void static void
vips_foreign_save_jp2k_info_callback( const char *msg, void *client ) vips_foreign_save_jp2k_info_callback( const char *msg, void *client )
{ {
#ifdef DEBUG #ifdef DEBUG
@ -199,9 +199,9 @@ vips_foreign_save_jp2k_attach_handlers( opj_codec_t *codec )
{ {
opj_set_info_handler( codec, opj_set_info_handler( codec,
vips_foreign_save_jp2k_info_callback, NULL ); vips_foreign_save_jp2k_info_callback, NULL );
opj_set_warning_handler( codec, opj_set_warning_handler( codec,
vips_foreign_save_jp2k_warning_callback, NULL ); vips_foreign_save_jp2k_warning_callback, NULL );
opj_set_error_handler( codec, opj_set_error_handler( codec,
vips_foreign_save_jp2k_error_callback, NULL ); vips_foreign_save_jp2k_error_callback, NULL );
} }
@ -233,8 +233,8 @@ vips_foreign_save_jp2k_attach_handlers( opj_codec_t *codec )
/* In-place RGB->YCC for a line of pels. /* In-place RGB->YCC for a line of pels.
*/ */
static void static void
vips_foreign_save_jp2k_rgb_to_ycc( VipsRegion *region, vips_foreign_save_jp2k_rgb_to_ycc( VipsRegion *region,
VipsRect *tile, int prec ) VipsRect *tile, int prec )
{ {
VipsImage *im = region->im; VipsImage *im = region->im;
int offset = 1 << (prec - 1); int offset = 1 << (prec - 1);
@ -245,7 +245,7 @@ vips_foreign_save_jp2k_rgb_to_ycc( VipsRegion *region,
g_assert( im->Bands == 3 ); g_assert( im->Bands == 3 );
for( y = 0; y < tile->height; y++ ) { for( y = 0; y < tile->height; y++ ) {
VipsPel *q = VIPS_REGION_ADDR( region, VipsPel *q = VIPS_REGION_ADDR( region,
tile->left, tile->top + y ); tile->left, tile->top + y );
switch( im->BandFmt ) { switch( im->BandFmt ) {
@ -330,14 +330,14 @@ vips_foreign_save_jp2k_unpack_subsample( VipsRegion *region, VipsRect *tile,
/* The number of pixels we write for this component. No /* The number of pixels we write for this component. No
* padding. * padding.
*/ */
int output_width = VIPS_ROUND_UINT( int output_width = VIPS_ROUND_UINT(
(double) tile->width / comp->dx ); (double) tile->width / comp->dx );
int output_height = VIPS_ROUND_UINT( int output_height = VIPS_ROUND_UINT(
(double) tile->height / comp->dy );; (double) tile->height / comp->dy );;
for( y = 0; y < output_height; y++ ) { for( y = 0; y < output_height; y++ ) {
VipsPel *p = i * sizeof_element + VipsPel *p = i * sizeof_element +
VIPS_REGION_ADDR( region, VIPS_REGION_ADDR( region,
tile->left, tile->top + y * comp->dy ); tile->left, tile->top + y * comp->dy );
/* Shrink a line of pels to q. /* Shrink a line of pels to q.
@ -400,11 +400,11 @@ vips_foreign_save_jp2k_unpack( VipsRegion *region, VipsRect *tile,
int x, y, i; int x, y, i;
for( y = 0; y < tile->height; y++ ) { for( y = 0; y < tile->height; y++ ) {
VipsPel *p = VIPS_REGION_ADDR( region, VipsPel *p = VIPS_REGION_ADDR( region,
tile->left, tile->top + y ); tile->left, tile->top + y );
for( i = 0; i < b; i++ ) { for( i = 0; i < b; i++ ) {
VipsPel *q = tile_buffer + VipsPel *q = tile_buffer +
i * sizeof_tile + y * sizeof_line; i * sizeof_tile + y * sizeof_line;
switch( im->BandFmt ) { switch( im->BandFmt ) {
@ -447,9 +447,9 @@ vips_foreign_save_jp2k_sizeof_tile( VipsForeignSaveJp2k *jp2k, VipsRect *tile )
/* The number of pixels we write for this component. Round to /* The number of pixels we write for this component. Round to
* nearest, and we may have to write half-pixels at the edges. * nearest, and we may have to write half-pixels at the edges.
*/ */
int output_width = VIPS_ROUND_UINT( int output_width = VIPS_ROUND_UINT(
(double) tile->width / comp->dx ); (double) tile->width / comp->dx );
int output_height = VIPS_ROUND_UINT( int output_height = VIPS_ROUND_UINT(
(double) tile->height / comp->dy );; (double) tile->height / comp->dy );;
size += output_width * output_height * sizeof_element; size += output_width * output_height * sizeof_element;
@ -479,25 +479,25 @@ vips_foreign_save_jp2k_write_tiles( VipsForeignSaveJp2k *jp2k )
tile.height = jp2k->tile_height; tile.height = jp2k->tile_height;
vips_rect_intersectrect( &tile, &jp2k->strip->valid, &tile ); vips_rect_intersectrect( &tile, &jp2k->strip->valid, &tile );
if( jp2k->save_as_ycc ) if( jp2k->save_as_ycc )
vips_foreign_save_jp2k_rgb_to_ycc( jp2k->strip, vips_foreign_save_jp2k_rgb_to_ycc( jp2k->strip,
&tile, jp2k->image->comps[0].prec ); &tile, jp2k->image->comps[0].prec );
if( jp2k->subsample ) if( jp2k->subsample )
vips_foreign_save_jp2k_unpack_subsample( jp2k->strip, vips_foreign_save_jp2k_unpack_subsample( jp2k->strip,
&tile, jp2k->image, &tile, jp2k->image,
jp2k->tile_buffer, jp2k->accumulate ); jp2k->tile_buffer, jp2k->accumulate );
else else
vips_foreign_save_jp2k_unpack( jp2k->strip, vips_foreign_save_jp2k_unpack( jp2k->strip,
&tile, jp2k->image, &tile, jp2k->image,
jp2k->tile_buffer ); jp2k->tile_buffer );
sizeof_tile = sizeof_tile =
vips_foreign_save_jp2k_sizeof_tile( jp2k, &tile ); vips_foreign_save_jp2k_sizeof_tile( jp2k, &tile );
tile_index = tiles_across * tile.top / jp2k->tile_height + tile_index = tiles_across * tile.top / jp2k->tile_height +
x / jp2k->tile_width; x / jp2k->tile_width;
if( !opj_write_tile( jp2k->codec, tile_index, if( !opj_write_tile( jp2k->codec, tile_index,
(VipsPel *) jp2k->tile_buffer, sizeof_tile, (VipsPel *) jp2k->tile_buffer, sizeof_tile,
jp2k->stream ) ) jp2k->stream ) )
return( -1 ); return( -1 );
} }
@ -506,14 +506,14 @@ vips_foreign_save_jp2k_write_tiles( VipsForeignSaveJp2k *jp2k )
} }
static int static int
vips_foreign_save_jp2k_write_block( VipsRegion *region, VipsRect *area, vips_foreign_save_jp2k_write_block( VipsRegion *region, VipsRect *area,
void *a ) void *a )
{ {
VipsForeignSaveJp2k *jp2k = (VipsForeignSaveJp2k *) a; VipsForeignSaveJp2k *jp2k = (VipsForeignSaveJp2k *) a;
VipsForeignSave *save = (VipsForeignSave *) jp2k; VipsForeignSave *save = (VipsForeignSave *) jp2k;
#ifdef DEBUG_VERBOSE #ifdef DEBUG_VERBOSE
printf( "vips_foreign_save_jp2k_write_block: y = %d, nlines = %d\n", printf( "vips_foreign_save_jp2k_write_block: y = %d, nlines = %d\n",
area->top, area->height ); area->top, area->height );
#endif /*DEBUG_VERBOSE*/ #endif /*DEBUG_VERBOSE*/
@ -525,20 +525,20 @@ vips_foreign_save_jp2k_write_block( VipsRegion *region, VipsRect *area,
VipsRect image; VipsRect image;
/* The intersection with the strip is the fresh pixels we /* The intersection with the strip is the fresh pixels we
* have. * have.
*/ */
vips_rect_intersectrect( area, to, &hit ); vips_rect_intersectrect( area, to, &hit );
/* Write the new pixels into the strip. /* Write the new pixels into the strip.
*/ */
vips_region_copy( region, jp2k->strip, vips_region_copy( region, jp2k->strip,
&hit, hit.left, hit.top ); &hit, hit.left, hit.top );
/* Have we failed to reach the bottom of the strip? We must /* Have we failed to reach the bottom of the strip? We must
* have run out of fresh pixels, so we are done. * have run out of fresh pixels, so we are done.
*/ */
if( VIPS_RECT_BOTTOM( &hit ) != if( VIPS_RECT_BOTTOM( &hit ) !=
VIPS_RECT_BOTTOM( &jp2k->strip->valid ) ) VIPS_RECT_BOTTOM( &jp2k->strip->valid ) )
break; break;
/* We have reached the bottom of the strip. Write this line of /* We have reached the bottom of the strip. Write this line of
@ -578,7 +578,7 @@ vips_foreign_save_jp2k_write_block( VipsRegion *region, VipsRect *area,
* that always allocates memory for each channel, and we don't want that when * that always allocates memory for each channel, and we don't want that when
* we are doing tiled write. * we are doing tiled write.
*/ */
static opj_image_t * static opj_image_t *
vips_opj_image_create( OPJ_UINT32 numcmpts, vips_opj_image_create( OPJ_UINT32 numcmpts,
opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc, opj_image_cmptparm_t *cmptparms, OPJ_COLOR_SPACE clrspc,
gboolean allocate ) gboolean allocate )
@ -610,7 +610,7 @@ vips_opj_image_create( OPJ_UINT32 numcmpts,
comp->sgnd = cmptparms[compno].sgnd; comp->sgnd = cmptparms[compno].sgnd;
if( comp->h != 0 && if( comp->h != 0 &&
(OPJ_SIZE_T) comp->w > SIZE_MAX / comp->h / (OPJ_SIZE_T) comp->w > SIZE_MAX / comp->h /
sizeof( OPJ_INT32 ) ) { sizeof( OPJ_INT32 ) ) {
opj_image_destroy( image ); opj_image_destroy( image );
return( NULL ); return( NULL );
@ -619,7 +619,7 @@ vips_opj_image_create( OPJ_UINT32 numcmpts,
/* Allocation is optional. /* Allocation is optional.
*/ */
if( allocate ) { if( allocate ) {
size_t bytes = (size_t) comp->w * comp->h * size_t bytes = (size_t) comp->w * comp->h *
sizeof( OPJ_INT32 ); sizeof( OPJ_INT32 );
comp->data = (OPJ_INT32*) opj_image_data_alloc( bytes ); comp->data = (OPJ_INT32*) opj_image_data_alloc( bytes );
@ -635,8 +635,8 @@ vips_opj_image_create( OPJ_UINT32 numcmpts,
} }
static opj_image_t * static opj_image_t *
vips_foreign_save_jp2k_new_image( VipsImage *im, vips_foreign_save_jp2k_new_image( VipsImage *im,
int width, int height, int width, int height,
gboolean subsample, gboolean save_as_ycc, gboolean allocate ) gboolean subsample, gboolean save_as_ycc, gboolean allocate )
{ {
OPJ_COLOR_SPACE color_space; OPJ_COLOR_SPACE color_space;
@ -709,7 +709,7 @@ vips_foreign_save_jp2k_new_image( VipsImage *im,
comps[i].sgnd = !vips_band_format_isuint( im->BandFmt ); comps[i].sgnd = !vips_band_format_isuint( im->BandFmt );
} }
image = vips_opj_image_create( im->Bands, comps, color_space, image = vips_opj_image_create( im->Bands, comps, color_space,
allocate ); allocate );
image->x1 = width; image->x1 = width;
image->y1 = height; image->y1 = height;
@ -722,14 +722,14 @@ vips_foreign_save_jp2k_new_image( VipsImage *im,
return( image ); return( image );
} }
/* Compression profile derived from the BM's recommenadations, see: /* Compression profile derived from the BM's recommendations, see:
* *
* https://purl.pt/24107/1/iPres2013_PDF/An%20Analysis%20of%20Contemporary%20JPEG2000%20Codecs%20for%20Image%20Format%20Migration.pdf * https://purl.pt/24107/1/iPres2013_PDF/An%20Analysis%20of%20Contemporary%20JPEG2000%20Codecs%20for%20Image%20Format%20Migration.pdf
* *
* Some of these settings (eg. numresolution) are overridden later. * Some of these settings (eg. numresolution) are overridden later.
*/ */
static void static void
vips_foreign_save_jp2k_set_profile( opj_cparameters_t *parameters, vips_foreign_save_jp2k_set_profile( opj_cparameters_t *parameters,
gboolean lossless, int Q ) gboolean lossless, int Q )
{ {
if( lossless ) if( lossless )
@ -758,7 +758,7 @@ vips_foreign_save_jp2k_set_profile( opj_cparameters_t *parameters,
parameters->csty = 1; parameters->csty = 1;
parameters->res_spec = 7; parameters->res_spec = 7;
for( i = 0; i < parameters->res_spec; i++ ) { for( i = 0; i < parameters->res_spec; i++ ) {
parameters->prch_init[i] = 256; parameters->prch_init[i] = 256;
parameters->prcw_init[i] = 256; parameters->prcw_init[i] = 256;
parameters->tcp_distoratio[i] = Q + 10 * i; parameters->tcp_distoratio[i] = Q + 10 * i;
@ -815,17 +815,17 @@ vips_foreign_save_jp2k_build( VipsObject *object )
break; break;
} }
if( jp2k->subsample ) if( jp2k->subsample )
jp2k->save_as_ycc = TRUE; jp2k->save_as_ycc = TRUE;
/* Set parameters for compressor. /* Set parameters for compressor.
*/ */
opj_set_default_encoder_parameters( &jp2k->parameters ); opj_set_default_encoder_parameters( &jp2k->parameters );
/* Set compression profile. /* Set compression profile.
*/ */
vips_foreign_save_jp2k_set_profile( &jp2k->parameters, vips_foreign_save_jp2k_set_profile( &jp2k->parameters,
jp2k->lossless, jp2k->Q ); jp2k->lossless, jp2k->Q );
/* Always tile. /* Always tile.
*/ */
@ -840,11 +840,11 @@ vips_foreign_save_jp2k_build( VipsObject *object )
/* Number of layers to write. Smallest layer is c. 2^5 on the smallest /* Number of layers to write. Smallest layer is c. 2^5 on the smallest
* axis. * axis.
*/ */
jp2k->parameters.numresolution = VIPS_MAX( 1, jp2k->parameters.numresolution = VIPS_MAX( 1,
log( VIPS_MIN( save->ready->Xsize, save->ready->Ysize ) ) / log( VIPS_MIN( save->ready->Xsize, save->ready->Ysize ) ) /
log( 2 ) - 5 ); log( 2 ) - 5 );
#ifdef DEBUG #ifdef DEBUG
printf( "vips_foreign_save_jp2k_build: numresolutions = %d\n", printf( "vips_foreign_save_jp2k_build: numresolutions = %d\n",
jp2k->parameters.numresolution ); jp2k->parameters.numresolution );
#endif /*DEBUG*/ #endif /*DEBUG*/
@ -853,14 +853,14 @@ vips_foreign_save_jp2k_build( VipsObject *object )
jp2k->codec = opj_create_compress( OPJ_CODEC_J2K ); jp2k->codec = opj_create_compress( OPJ_CODEC_J2K );
vips_foreign_save_jp2k_attach_handlers( jp2k->codec ); vips_foreign_save_jp2k_attach_handlers( jp2k->codec );
/* FALSE means don't alloc memory for image planes (we write in /* FALSE means don't alloc memory for image planes (we write in
* tiles, not whole images). * tiles, not whole images).
*/ */
if( !(jp2k->image = vips_foreign_save_jp2k_new_image( save->ready, if( !(jp2k->image = vips_foreign_save_jp2k_new_image( save->ready,
save->ready->Xsize, save->ready->Ysize, save->ready->Xsize, save->ready->Ysize,
jp2k->subsample, jp2k->save_as_ycc, FALSE )) ) jp2k->subsample, jp2k->save_as_ycc, FALSE )) )
return( -1 ); return( -1 );
if( !opj_setup_encoder( jp2k->codec, &jp2k->parameters, jp2k->image ) ) if( !opj_setup_encoder( jp2k->codec, &jp2k->parameters, jp2k->image ) )
return( -1 ); return( -1 );
opj_codec_set_threads( jp2k->codec, vips_concurrency_get() ); opj_codec_set_threads( jp2k->codec, vips_concurrency_get() );
@ -898,10 +898,10 @@ vips_foreign_save_jp2k_build( VipsObject *object )
strip_position.top = 0; strip_position.top = 0;
strip_position.width = save->ready->Xsize; strip_position.width = save->ready->Xsize;
strip_position.height = jp2k->tile_height; strip_position.height = jp2k->tile_height;
if( vips_region_buffer( jp2k->strip, &strip_position ) ) if( vips_region_buffer( jp2k->strip, &strip_position ) )
return( -1 ); return( -1 );
/* Write data. /* Write data.
*/ */
if( vips_sink_disc( save->ready, if( vips_sink_disc( save->ready,
vips_foreign_save_jp2k_write_block, jp2k ) ) vips_foreign_save_jp2k_write_block, jp2k ) )
@ -935,26 +935,26 @@ vips_foreign_save_jp2k_class_init( VipsForeignSaveJp2kClass *class )
save_class->saveable = VIPS_SAVEABLE_ANY; save_class->saveable = VIPS_SAVEABLE_ANY;
VIPS_ARG_INT( class, "tile_width", 11, VIPS_ARG_INT( class, "tile_width", 11,
_( "Tile width" ), _( "Tile width" ),
_( "Tile width in pixels" ), _( "Tile width in pixels" ),
VIPS_ARGUMENT_OPTIONAL_INPUT, VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJp2k, tile_width ), G_STRUCT_OFFSET( VipsForeignSaveJp2k, tile_width ),
1, 32768, 512 ); 1, 32768, 512 );
VIPS_ARG_INT( class, "tile_height", 12, VIPS_ARG_INT( class, "tile_height", 12,
_( "Tile height" ), _( "Tile height" ),
_( "Tile height in pixels" ), _( "Tile height in pixels" ),
VIPS_ARGUMENT_OPTIONAL_INPUT, VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJp2k, tile_height ), G_STRUCT_OFFSET( VipsForeignSaveJp2k, tile_height ),
1, 32768, 512 ); 1, 32768, 512 );
VIPS_ARG_BOOL( class, "lossless", 13, VIPS_ARG_BOOL( class, "lossless", 13,
_( "Lossless" ), _( "Lossless" ),
_( "Enable lossless compression" ), _( "Enable lossless compression" ),
VIPS_ARGUMENT_OPTIONAL_INPUT, VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJp2k, lossless ), G_STRUCT_OFFSET( VipsForeignSaveJp2k, lossless ),
FALSE ); FALSE );
VIPS_ARG_ENUM( class, "subsample_mode", 19, VIPS_ARG_ENUM( class, "subsample_mode", 19,
_( "Subsample mode" ), _( "Subsample mode" ),
@ -962,10 +962,10 @@ vips_foreign_save_jp2k_class_init( VipsForeignSaveJp2kClass *class )
VIPS_ARGUMENT_OPTIONAL_INPUT, VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJp2k, subsample_mode ), G_STRUCT_OFFSET( VipsForeignSaveJp2k, subsample_mode ),
VIPS_TYPE_FOREIGN_SUBSAMPLE, VIPS_TYPE_FOREIGN_SUBSAMPLE,
VIPS_FOREIGN_SUBSAMPLE_AUTO ); VIPS_FOREIGN_SUBSAMPLE_OFF );
VIPS_ARG_INT( class, "Q", 14, VIPS_ARG_INT( class, "Q", 14,
_( "Q" ), _( "Q" ),
_( "Q factor" ), _( "Q factor" ),
VIPS_ARGUMENT_OPTIONAL_INPUT, VIPS_ARGUMENT_OPTIONAL_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJp2k, Q ), G_STRUCT_OFFSET( VipsForeignSaveJp2k, Q ),
@ -983,7 +983,7 @@ vips_foreign_save_jp2k_init( VipsForeignSaveJp2k *jp2k )
*/ */
jp2k->Q = 48; jp2k->Q = 48;
jp2k->subsample_mode = VIPS_FOREIGN_SUBSAMPLE_AUTO; jp2k->subsample_mode = VIPS_FOREIGN_SUBSAMPLE_OFF;
} }
typedef struct _VipsForeignSaveJp2kFile { typedef struct _VipsForeignSaveJp2kFile {
@ -991,13 +991,13 @@ typedef struct _VipsForeignSaveJp2kFile {
/* Filename for save. /* Filename for save.
*/ */
char *filename; char *filename;
} VipsForeignSaveJp2kFile; } VipsForeignSaveJp2kFile;
typedef VipsForeignSaveJp2kClass VipsForeignSaveJp2kFileClass; typedef VipsForeignSaveJp2kClass VipsForeignSaveJp2kFileClass;
G_DEFINE_TYPE( VipsForeignSaveJp2kFile, vips_foreign_save_jp2k_file, G_DEFINE_TYPE( VipsForeignSaveJp2kFile, vips_foreign_save_jp2k_file,
vips_foreign_save_jp2k_get_type() ); vips_foreign_save_jp2k_get_type() );
static int static int
@ -1028,10 +1028,10 @@ vips_foreign_save_jp2k_file_class_init( VipsForeignSaveJp2kFileClass *class )
object_class->nickname = "jp2ksave"; object_class->nickname = "jp2ksave";
object_class->build = vips_foreign_save_jp2k_file_build; object_class->build = vips_foreign_save_jp2k_file_build;
VIPS_ARG_STRING( class, "filename", 1, VIPS_ARG_STRING( class, "filename", 1,
_( "Filename" ), _( "Filename" ),
_( "Filename to load from" ), _( "Filename to load from" ),
VIPS_ARGUMENT_REQUIRED_INPUT, VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJp2kFile, filename ), G_STRUCT_OFFSET( VipsForeignSaveJp2kFile, filename ),
NULL ); NULL );
@ -1053,14 +1053,14 @@ typedef struct _VipsForeignSaveJp2kBuffer {
typedef VipsForeignSaveJp2kClass VipsForeignSaveJp2kBufferClass; typedef VipsForeignSaveJp2kClass VipsForeignSaveJp2kBufferClass;
G_DEFINE_TYPE( VipsForeignSaveJp2kBuffer, vips_foreign_save_jp2k_buffer, G_DEFINE_TYPE( VipsForeignSaveJp2kBuffer, vips_foreign_save_jp2k_buffer,
vips_foreign_save_jp2k_get_type() ); vips_foreign_save_jp2k_get_type() );
static int static int
vips_foreign_save_jp2k_buffer_build( VipsObject *object ) vips_foreign_save_jp2k_buffer_build( VipsObject *object )
{ {
VipsForeignSaveJp2k *jp2k = (VipsForeignSaveJp2k *) object; VipsForeignSaveJp2k *jp2k = (VipsForeignSaveJp2k *) object;
VipsForeignSaveJp2kBuffer *buffer = VipsForeignSaveJp2kBuffer *buffer =
(VipsForeignSaveJp2kBuffer *) object; (VipsForeignSaveJp2kBuffer *) object;
VipsBlob *blob; VipsBlob *blob;
@ -1080,7 +1080,7 @@ vips_foreign_save_jp2k_buffer_build( VipsObject *object )
} }
static void static void
vips_foreign_save_jp2k_buffer_class_init( vips_foreign_save_jp2k_buffer_class_init(
VipsForeignSaveJp2kBufferClass *class ) VipsForeignSaveJp2kBufferClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
@ -1092,10 +1092,10 @@ vips_foreign_save_jp2k_buffer_class_init(
object_class->nickname = "jp2ksave_buffer"; object_class->nickname = "jp2ksave_buffer";
object_class->build = vips_foreign_save_jp2k_buffer_build; object_class->build = vips_foreign_save_jp2k_buffer_build;
VIPS_ARG_BOXED( class, "buffer", 1, VIPS_ARG_BOXED( class, "buffer", 1,
_( "Buffer" ), _( "Buffer" ),
_( "Buffer to save to" ), _( "Buffer to save to" ),
VIPS_ARGUMENT_REQUIRED_OUTPUT, VIPS_ARGUMENT_REQUIRED_OUTPUT,
G_STRUCT_OFFSET( VipsForeignSaveJp2kBuffer, buf ), G_STRUCT_OFFSET( VipsForeignSaveJp2kBuffer, buf ),
VIPS_TYPE_BLOB ); VIPS_TYPE_BLOB );
@ -1114,14 +1114,14 @@ typedef struct _VipsForeignSaveJp2kTarget {
typedef VipsForeignSaveJp2kClass VipsForeignSaveJp2kTargetClass; typedef VipsForeignSaveJp2kClass VipsForeignSaveJp2kTargetClass;
G_DEFINE_TYPE( VipsForeignSaveJp2kTarget, vips_foreign_save_jp2k_target, G_DEFINE_TYPE( VipsForeignSaveJp2kTarget, vips_foreign_save_jp2k_target,
vips_foreign_save_jp2k_get_type() ); vips_foreign_save_jp2k_get_type() );
static int static int
vips_foreign_save_jp2k_target_build( VipsObject *object ) vips_foreign_save_jp2k_target_build( VipsObject *object )
{ {
VipsForeignSaveJp2k *jp2k = (VipsForeignSaveJp2k *) object; VipsForeignSaveJp2k *jp2k = (VipsForeignSaveJp2k *) object;
VipsForeignSaveJp2kTarget *target = VipsForeignSaveJp2kTarget *target =
(VipsForeignSaveJp2kTarget *) object; (VipsForeignSaveJp2kTarget *) object;
if( target->target ) { if( target->target ) {
@ -1137,7 +1137,7 @@ vips_foreign_save_jp2k_target_build( VipsObject *object )
} }
static void static void
vips_foreign_save_jp2k_target_class_init( vips_foreign_save_jp2k_target_class_init(
VipsForeignSaveJp2kTargetClass *class ) VipsForeignSaveJp2kTargetClass *class )
{ {
GObjectClass *gobject_class = G_OBJECT_CLASS( class ); GObjectClass *gobject_class = G_OBJECT_CLASS( class );
@ -1152,7 +1152,7 @@ vips_foreign_save_jp2k_target_class_init(
VIPS_ARG_OBJECT( class, "target", 1, VIPS_ARG_OBJECT( class, "target", 1,
_( "Target" ), _( "Target" ),
_( "Target to save to" ), _( "Target to save to" ),
VIPS_ARGUMENT_REQUIRED_INPUT, VIPS_ARGUMENT_REQUIRED_INPUT,
G_STRUCT_OFFSET( VipsForeignSaveJp2kTarget, target ), G_STRUCT_OFFSET( VipsForeignSaveJp2kTarget, target ),
VIPS_TYPE_TARGET ); VIPS_TYPE_TARGET );
@ -1176,7 +1176,7 @@ typedef struct _TileCompress {
* subsampling. * subsampling.
*/ */
static void static void
vips_foreign_save_jp2k_unpack_subsample_image( VipsRegion *region, vips_foreign_save_jp2k_unpack_subsample_image( VipsRegion *region,
VipsRect *tile, opj_image_t *image, VipsPel *accumulate ) VipsRect *tile, opj_image_t *image, VipsPel *accumulate )
{ {
VipsImage *im = region->im; VipsImage *im = region->im;
@ -1193,14 +1193,14 @@ vips_foreign_save_jp2k_unpack_subsample_image( VipsRegion *region,
/* The number of pixels we write for this component. Lines /* The number of pixels we write for this component. Lines
* align to scanlines on comp. * align to scanlines on comp.
*/ */
int output_width = VIPS_ROUND_UINT( int output_width = VIPS_ROUND_UINT(
(double) comp->w / comp->dx ); (double) comp->w / comp->dx );
int output_height = VIPS_ROUND_UINT( int output_height = VIPS_ROUND_UINT(
(double) comp->h / comp->dy ); (double) comp->h / comp->dy );
for( y = 0; y < output_height; y++ ) { for( y = 0; y < output_height; y++ ) {
VipsPel *p = i * sizeof_element + VipsPel *p = i * sizeof_element +
VIPS_REGION_ADDR( region, VIPS_REGION_ADDR( region,
tile->left, tile->top + y * comp->dy ); tile->left, tile->top + y * comp->dy );
/* Shrink a line of pels to q. /* Shrink a line of pels to q.
@ -1253,12 +1253,12 @@ vips_foreign_save_jp2k_unpack_image( VipsRegion *region, VipsRect *tile,
int x, y, i; int x, y, i;
for( y = 0; y < tile->height; y++ ) { for( y = 0; y < tile->height; y++ ) {
VipsPel *p = VIPS_REGION_ADDR( region, VipsPel *p = VIPS_REGION_ADDR( region,
tile->left, tile->top + y ); tile->left, tile->top + y );
for( i = 0; i < b; i++ ) { for( i = 0; i < b; i++ ) {
opj_image_comp_t *comp = &image->comps[i]; opj_image_comp_t *comp = &image->comps[i];
int *q = comp->data + y * comp->w; int *q = comp->data + y * comp->w;
switch( im->BandFmt ) { switch( im->BandFmt ) {
case VIPS_FORMAT_CHAR: case VIPS_FORMAT_CHAR:
@ -1294,14 +1294,14 @@ vips__foreign_load_jp2k_compress_free( TileCompress *compress )
} }
/* Compress area @tile within @region and write to @target as a @tile_width by /* Compress area @tile within @region and write to @target as a @tile_width by
* @tile_height jp2k compressed image. This is called from eg. vips2tiff to * @tile_height jp2k compressed image. This is called from eg. vips2tiff to
* write jp2k-compressed tiles. * write jp2k-compressed tiles.
* *
* You'd think we could reuse things like the encoder between calls but ... * You'd think we could reuse things like the encoder between calls but ...
* nope, openjpeg does not allow that. * nope, openjpeg does not allow that.
*/ */
int int
vips__foreign_load_jp2k_compress( VipsRegion *region, vips__foreign_load_jp2k_compress( VipsRegion *region,
VipsRect *tile, VipsTarget *target, VipsRect *tile, VipsTarget *target,
int tile_width, int tile_height, int tile_width, int tile_height,
gboolean save_as_ycc, gboolean subsample, gboolean lossless, int Q ) gboolean save_as_ycc, gboolean subsample, gboolean lossless, int Q )
@ -1321,7 +1321,7 @@ vips__foreign_load_jp2k_compress( VipsRegion *region,
/* Set compression profile. /* Set compression profile.
*/ */
vips_foreign_save_jp2k_set_profile( &parameters, lossless, Q ); vips_foreign_save_jp2k_set_profile( &parameters, lossless, Q );
/* Makes three band images smaller, somehow. /* Makes three band images smaller, somehow.
*/ */
@ -1339,7 +1339,7 @@ vips__foreign_load_jp2k_compress( VipsRegion *region,
/* We need a line of sums for chroma subsample. At worst, gint64. /* We need a line of sums for chroma subsample. At worst, gint64.
*/ */
sizeof_line = sizeof( gint64 ) * tile->width; sizeof_line = sizeof( gint64 ) * tile->width;
if( !(compress.accumulate = if( !(compress.accumulate =
VIPS_ARRAY( NULL, sizeof_line, VipsPel )) ) { VIPS_ARRAY( NULL, sizeof_line, VipsPel )) ) {
vips__foreign_load_jp2k_compress_free( &compress ); vips__foreign_load_jp2k_compress_free( &compress );
return( -1 ); return( -1 );
@ -1347,7 +1347,7 @@ vips__foreign_load_jp2k_compress( VipsRegion *region,
compress.codec = opj_create_compress( OPJ_CODEC_J2K ); compress.codec = opj_create_compress( OPJ_CODEC_J2K );
vips_foreign_save_jp2k_attach_handlers( compress.codec ); vips_foreign_save_jp2k_attach_handlers( compress.codec );
if( !opj_setup_encoder( compress.codec, if( !opj_setup_encoder( compress.codec,
&parameters, compress.image ) ) { &parameters, compress.image ) ) {
vips__foreign_load_jp2k_compress_free( &compress ); vips__foreign_load_jp2k_compress_free( &compress );
return( -1 ); return( -1 );
@ -1355,26 +1355,26 @@ vips__foreign_load_jp2k_compress( VipsRegion *region,
opj_codec_set_threads( compress.codec, vips_concurrency_get() ); opj_codec_set_threads( compress.codec, vips_concurrency_get() );
if( save_as_ycc ) if( save_as_ycc )
vips_foreign_save_jp2k_rgb_to_ycc( region, vips_foreign_save_jp2k_rgb_to_ycc( region,
tile, compress.image->comps[0].prec ); tile, compress.image->comps[0].prec );
/* we need to unpack to the int arrays on comps[i].data /* we need to unpack to the int arrays on comps[i].data
*/ */
if( subsample ) if( subsample )
vips_foreign_save_jp2k_unpack_subsample_image( region, vips_foreign_save_jp2k_unpack_subsample_image( region,
tile, compress.image, tile, compress.image,
compress.accumulate ); compress.accumulate );
else else
vips_foreign_save_jp2k_unpack_image( region, vips_foreign_save_jp2k_unpack_image( region,
tile, compress.image ); tile, compress.image );
if( !(compress.stream = vips_foreign_save_jp2k_target( target )) ) { if( !(compress.stream = vips_foreign_save_jp2k_target( target )) ) {
vips__foreign_load_jp2k_compress_free( &compress ); vips__foreign_load_jp2k_compress_free( &compress );
return( -1 ); return( -1 );
} }
if( !opj_start_compress( compress.codec, if( !opj_start_compress( compress.codec,
compress.image, compress.stream ) ) { compress.image, compress.stream ) ) {
vips__foreign_load_jp2k_compress_free( &compress ); vips__foreign_load_jp2k_compress_free( &compress );
return( -1 ); return( -1 );
@ -1395,12 +1395,12 @@ vips__foreign_load_jp2k_compress( VipsRegion *region,
#else /*!HAVE_LIBOPENJP2*/ #else /*!HAVE_LIBOPENJP2*/
int int
vips__foreign_load_jp2k_compress( VipsRegion *region, vips__foreign_load_jp2k_compress( VipsRegion *region,
VipsRect *tile, VipsTarget *target, VipsRect *tile, VipsTarget *target,
int tile_width, int tile_height, int tile_width, int tile_height,
gboolean save_as_ycc, gboolean subsample, gboolean lossless, int Q ) gboolean save_as_ycc, gboolean subsample, gboolean lossless, int Q )
{ {
vips_error( "jp2k", vips_error( "jp2k",
"%s", _( "libvips built without JPEG2000 support" ) ); "%s", _( "libvips built without JPEG2000 support" ) );
return( -1 ); return( -1 );
} }
@ -1409,8 +1409,8 @@ vips__foreign_load_jp2k_compress( VipsRegion *region,
/** /**
* vips_jp2ksave: (method) * vips_jp2ksave: (method)
* @in: image to save * @in: image to save
* @filename: file to write to * @filename: file to write to
* @...: %NULL-terminated list of optional named arguments * @...: %NULL-terminated list of optional named arguments
* *
* Optional arguments: * Optional arguments:
@ -1421,7 +1421,7 @@ vips__foreign_load_jp2k_compress( VipsRegion *region,
* * @tile_height: %gint for tile size * * @tile_height: %gint for tile size
* * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode
* *
* Write a VIPS image to a file in JPEG2000 format. * Write a VIPS image to a file in JPEG2000 format.
* The saver supports 8, 16 and 32-bit int pixel * The saver supports 8, 16 and 32-bit int pixel
* values, signed and unsigned. It supports greyscale, RGB, CMYK and * values, signed and unsigned. It supports greyscale, RGB, CMYK and
* multispectral images. * multispectral images.
@ -1433,8 +1433,8 @@ vips__foreign_load_jp2k_compress( VipsRegion *region,
* *
* Use @tile_width and @tile_height to set the tile size. The default is 512. * Use @tile_width and @tile_height to set the tile size. The default is 512.
* *
* Chroma subsampling is normally automatically disabled for Q >= 90. You can * Chroma subsampling is normally disabled for compatibility. Set
* force the subsampling mode with @subsample_mode. * @subsample_mode to auto to enable chroma subsample for Q < 90.
* *
* This operation always writes a pyramid. * This operation always writes a pyramid.
* *
@ -1457,7 +1457,7 @@ vips_jp2ksave( VipsImage *in, const char *filename, ... )
/** /**
* vips_jp2ksave_buffer: (method) * vips_jp2ksave_buffer: (method)
* @in: image to save * @in: image to save
* @buf: (array length=len) (element-type guint8): return output buffer here * @buf: (array length=len) (element-type guint8): return output buffer here
* @len: (type gsize): return output length here * @len: (type gsize): return output length here
* @...: %NULL-terminated list of optional named arguments * @...: %NULL-terminated list of optional named arguments
@ -1483,19 +1483,19 @@ vips_jp2ksave_buffer( VipsImage *in, void **buf, size_t *len, ... )
VipsArea *area; VipsArea *area;
int result; int result;
area = NULL; area = NULL;
va_start( ap, len ); va_start( ap, len );
result = vips_call_split( "jp2ksave_buffer", ap, in, &area ); result = vips_call_split( "jp2ksave_buffer", ap, in, &area );
va_end( ap ); va_end( ap );
if( !result && if( !result &&
area ) { area ) {
if( buf ) { if( buf ) {
*buf = area->data; *buf = area->data;
area->free_fn = NULL; area->free_fn = NULL;
} }
if( len ) if( len )
*len = area->length; *len = area->length;
vips_area_unref( area ); vips_area_unref( area );
@ -1506,7 +1506,7 @@ vips_jp2ksave_buffer( VipsImage *in, void **buf, size_t *len, ... )
/** /**
* vips_jp2ksave_target: (method) * vips_jp2ksave_target: (method)
* @in: image to save * @in: image to save
* @target: save image to this target * @target: save image to this target
* @...: %NULL-terminated list of optional named arguments * @...: %NULL-terminated list of optional named arguments
* *

View File

@ -204,7 +204,7 @@ if test_supported matload; then
# test blocked and untrusted # test blocked and untrusted
printf "testing VIPS_BLOCK_UNTRUSTED with matio ... " printf "testing VIPS_BLOCK_UNTRUSTED with matio ... "
export VIPS_BLOCK_UNTRUSTED=1 export VIPS_BLOCK_UNTRUSTED=1
if vips matload $matlab $tmp/block.png; then if $vips copy $matlab $tmp/block.png; then
echo "failed to block matload" echo "failed to block matload"
exit 1 exit 1
fi fi