add jp2k load left-justification
We were loading 12-bit images as 0-4095 pixels, which then looked very dark as RGB16. This patch left-justifies bits to fill 0-55, 0-65535 etc. as required.
This commit is contained in:
parent
ce54b4e5ad
commit
1496984a7a
@ -4,6 +4,8 @@
|
|||||||
* - from heifload.c
|
* - from heifload.c
|
||||||
* 4/11/21
|
* 4/11/21
|
||||||
* - add untiled load
|
* - add untiled load
|
||||||
|
* 17/1/22
|
||||||
|
* - left-justify bits for eg. 12-bit read
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -268,14 +270,16 @@ vips_foreign_load_jp2k_get_flags( VipsForeignLoad *load )
|
|||||||
return( VIPS_FOREIGN_PARTIAL );
|
return( VIPS_FOREIGN_PARTIAL );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The openjpeg info and warning callbacks are incredibly chatty.
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
vips_foreign_load_jp2k_error_callback( const char *msg, void *client )
|
vips_foreign_load_jp2k_info_callback( const char *msg, void *client )
|
||||||
{
|
{
|
||||||
VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) client;
|
#ifdef DEBUG
|
||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( jp2k );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( client );
|
||||||
|
|
||||||
vips_error( class->nickname, "%s", msg );
|
g_info( "%s: %s", class->nickname, msg );
|
||||||
jp2k->n_errors += 1;
|
#endif /*DEBUG*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The openjpeg info and warning callbacks are incredibly chatty.
|
/* The openjpeg info and warning callbacks are incredibly chatty.
|
||||||
@ -290,16 +294,18 @@ vips_foreign_load_jp2k_warning_callback( const char *msg, void *client )
|
|||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The openjpeg info and warning callbacks are incredibly chatty.
|
|
||||||
*/
|
|
||||||
static void
|
static void
|
||||||
vips_foreign_load_jp2k_info_callback( const char *msg, void *client )
|
vips_foreign_load_jp2k_error_callback( const char *msg, void *client )
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) client;
|
||||||
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( client );
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( jp2k );
|
||||||
|
|
||||||
g_info( "%s: %s", class->nickname, msg );
|
#ifdef DEBUG
|
||||||
|
printf( "%s: %s", class->nickname, msg );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
vips_error( class->nickname, "%s", msg );
|
||||||
|
jp2k->n_errors += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -342,7 +348,7 @@ vips_foreign_load_jp2k_print( VipsForeignLoadJp2k *jp2k )
|
|||||||
"x0 = %u, y0 = %u\n",
|
"x0 = %u, y0 = %u\n",
|
||||||
i, this->dx, this->dy, this->w, this->h,
|
i, this->dx, this->dy, this->w, this->h,
|
||||||
this->x0, this->y0 );
|
this->x0, this->y0 );
|
||||||
printf( " prec = %x, bpp = %x, sgnd = %x, "
|
printf( " prec = %d, bpp = %x, sgnd = %x, "
|
||||||
"resno_decoded = %u, factor = %u\n",
|
"resno_decoded = %u, factor = %u\n",
|
||||||
this->prec, this->bpp, this->sgnd,
|
this->prec, this->bpp, this->sgnd,
|
||||||
this->resno_decoded, this->factor );
|
this->resno_decoded, this->factor );
|
||||||
@ -729,6 +735,51 @@ vips_foreign_load_jp2k_ycc_to_rgb( opj_image_t *image, VipsImage *im,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define LSHIFT( TYPE ) { \
|
||||||
|
TYPE *tq = (TYPE *) q; \
|
||||||
|
\
|
||||||
|
for( x = 0; x < n_elements; x++ ) \
|
||||||
|
tq[x] = VIPS_LSHIFT_INT( tq[x], shift ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Left-justify to the libvips pixel bits. We need 12 bit precision images
|
||||||
|
* (for example) to fill 0-65535.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
vips_foreign_load_jp2k_ljust( opj_image_t *image, VipsImage *im,
|
||||||
|
VipsPel *q, int length )
|
||||||
|
{
|
||||||
|
int prec = image->comps[0].prec;
|
||||||
|
int shift = VIPS_IMAGE_SIZEOF_ELEMENT( im ) * 8 - prec;
|
||||||
|
|
||||||
|
if( shift != 0 ) {
|
||||||
|
int n_elements = length * im->Bands;
|
||||||
|
|
||||||
|
int x;
|
||||||
|
|
||||||
|
switch( im->BandFmt ) {
|
||||||
|
case VIPS_FORMAT_CHAR:
|
||||||
|
case VIPS_FORMAT_UCHAR:
|
||||||
|
LSHIFT( unsigned char );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_FORMAT_SHORT:
|
||||||
|
case VIPS_FORMAT_USHORT:
|
||||||
|
LSHIFT( unsigned short );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VIPS_FORMAT_INT:
|
||||||
|
case VIPS_FORMAT_UINT:
|
||||||
|
LSHIFT( unsigned int );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Read a tile from an untiled jp2k file.
|
/* Read a tile from an untiled jp2k file.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
@ -789,6 +840,9 @@ vips_foreign_load_jp2k_generate_untiled( VipsRegion *out,
|
|||||||
if( jp2k->ycc_to_rgb )
|
if( jp2k->ycc_to_rgb )
|
||||||
vips_foreign_load_jp2k_ycc_to_rgb( jp2k->image,
|
vips_foreign_load_jp2k_ycc_to_rgb( jp2k->image,
|
||||||
out->im, q, r->width );
|
out->im, q, r->width );
|
||||||
|
|
||||||
|
vips_foreign_load_jp2k_ljust( jp2k->image,
|
||||||
|
out->im, q, r->width );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* jp2k files can't be truncated (they fail to open), so all we can
|
/* jp2k files can't be truncated (they fail to open), so all we can
|
||||||
@ -895,6 +949,9 @@ vips_foreign_load_jp2k_generate_tiled( VipsRegion *out,
|
|||||||
vips_foreign_load_jp2k_ycc_to_rgb(
|
vips_foreign_load_jp2k_ycc_to_rgb(
|
||||||
jp2k->image, out->im, q,
|
jp2k->image, out->im, q,
|
||||||
hit.width );
|
hit.width );
|
||||||
|
|
||||||
|
vips_foreign_load_jp2k_ljust( jp2k->image,
|
||||||
|
out->im, q, hit.width );
|
||||||
}
|
}
|
||||||
|
|
||||||
x += hit.width;
|
x += hit.width;
|
||||||
@ -1237,17 +1294,33 @@ vips_foreign_load_jp2k_source_init(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
info_callback( const char *msg G_GNUC_UNUSED, void *data G_GNUC_UNUSED )
|
||||||
|
{
|
||||||
|
/* There's a lot of info as well ...
|
||||||
|
*/
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "info_callback: %s\n", msg );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
warning_callback( const char *msg G_GNUC_UNUSED, void *data G_GNUC_UNUSED )
|
warning_callback( const char *msg G_GNUC_UNUSED, void *data G_GNUC_UNUSED )
|
||||||
{
|
{
|
||||||
/* There are a lot of warnings ...
|
/* There are a lot of warnings ...
|
||||||
*/
|
*/
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf( "warning_callback: %s\n", msg );
|
||||||
|
#endif /*DEBUG*/
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
error_callback( const char *msg, void *data )
|
error_callback( const char *msg, void *data )
|
||||||
{
|
{
|
||||||
printf( "OpenJPEG: %s", msg );
|
#ifdef DEBUG
|
||||||
|
printf( "error_callback: %s\n", msg );
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
vips_error( "OpenJPEG", "%s", msg );
|
vips_error( "OpenJPEG", "%s", msg );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1298,14 +1371,16 @@ vips__foreign_load_jp2k_decompress( VipsImage *out,
|
|||||||
*/
|
*/
|
||||||
ycc_to_rgb = ycc_to_rgb && out->Bands == 3;
|
ycc_to_rgb = ycc_to_rgb && out->Bands == 3;
|
||||||
|
|
||||||
decompress.codec = opj_create_decompress( OPJ_CODEC_J2K );
|
|
||||||
opj_set_default_decoder_parameters( ¶meters );
|
opj_set_default_decoder_parameters( ¶meters );
|
||||||
opj_setup_decoder( decompress.codec, ¶meters );
|
decompress.codec = opj_create_decompress( OPJ_CODEC_J2K );
|
||||||
|
opj_set_info_handler( decompress.codec, info_callback, NULL );
|
||||||
opj_set_warning_handler( decompress.codec, warning_callback, NULL );
|
opj_set_warning_handler( decompress.codec, warning_callback, NULL );
|
||||||
opj_set_error_handler( decompress.codec, error_callback, NULL );
|
opj_set_error_handler( decompress.codec, error_callback, NULL );
|
||||||
|
opj_setup_decoder( decompress.codec, ¶meters );
|
||||||
|
|
||||||
decompress.source = vips_source_new_from_memory( from, from_length );
|
decompress.source = vips_source_new_from_memory( from, from_length );
|
||||||
decompress.stream = vips_foreign_load_jp2k_stream( decompress.source );
|
decompress.stream = vips_foreign_load_jp2k_stream( decompress.source );
|
||||||
|
|
||||||
if( !opj_read_header( decompress.stream,
|
if( !opj_read_header( decompress.stream,
|
||||||
decompress.codec, &decompress.image ) ) {
|
decompress.codec, &decompress.image ) ) {
|
||||||
vips_error( "jp2kload", "%s", ( "header error" ) );
|
vips_error( "jp2kload", "%s", ( "header error" ) );
|
||||||
@ -1352,6 +1427,9 @@ vips__foreign_load_jp2k_decompress( VipsImage *out,
|
|||||||
decompress.image, out, q,
|
decompress.image, out, q,
|
||||||
width );
|
width );
|
||||||
|
|
||||||
|
vips_foreign_load_jp2k_ljust( decompress.image,
|
||||||
|
out, q, width );
|
||||||
|
|
||||||
q += line_size;
|
q += line_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user