1 /* load jpeg2000
2 *
3 * 18/3/20
4 * - from heifload.c
5 * 4/11/21
6 * - add untiled load
7 */
8
9 /*
10
11 This file is part of VIPS.
12
13 VIPS is free software; you can redistribute it and/or modify
14 it under the terms of the GNU Lesser General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 02110-1301 USA
27
28 */
29
30 /*
31
32 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
33
34 */
35
36 /*
37 #define DEBUG_VERBOSE
38 #define DEBUG
39 */
40
41 #ifdef HAVE_CONFIG_H
42 #include <config.h>
43 #endif /*HAVE_CONFIG_H*/
44 #include <vips/intl.h>
45
46 #include <stdio.h>
47 #include <stdlib.h>
48 #include <string.h>
49
50 #include <vips/vips.h>
51 #include <vips/debug.h>
52 #include <vips/internal.h>
53
54 #ifdef HAVE_LIBOPENJP2
55
56 #include <openjpeg.h>
57
58 #include "pforeign.h"
59
60 /* Surely enough ... does anyone do multispectral imaging with jp2k?
61 */
62 #define MAX_BANDS (100)
63
64 typedef struct _VipsForeignLoadJp2k {
65 VipsForeignLoad parent_object;
66
67 /* Source to load from (set by subclasses).
68 */
69 VipsSource *source;
70
71 /* Page set by user, then we translate that into shrink factor.
72 */
73 int page;
74 int shrink;
75
76 /* Decompress state.
77 */
78 opj_stream_t *stream; /* Source as an opj stream */
79 OPJ_CODEC_FORMAT format; /* libopenjp2 format */
80 opj_codec_t *codec; /* Decompress codec */
81 opj_dparameters_t parameters; /* Core decompress params */
82 opj_image_t *image; /* Read image to here */
83 opj_codestream_info_v2_t *info; /* Tile geometry */
84
85 /* Number of errors reported during load -- use this to block load of
86 * corrupted images.
87 */
88 int n_errors;
89
90 /* If we need to upsample tiles read from opj.
91 */
92 gboolean upsample;
93
94 /* If we need to do ycc->rgb conversion on load.
95 */
96 gboolean ycc_to_rgb;
97 } VipsForeignLoadJp2k;
98
99 typedef VipsForeignLoadClass VipsForeignLoadJp2kClass;
100
101 G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadJp2k, vips_foreign_load_jp2k,
102 VIPS_TYPE_FOREIGN_LOAD );
103
104 static void
vips_foreign_load_jp2k_dispose(GObject * gobject)105 vips_foreign_load_jp2k_dispose( GObject *gobject )
106 {
107 VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) gobject;
108
109 #ifdef DEBUG
110 printf( "vips_foreign_load_jp2k_dispose:\n" );
111 #endif /*DEBUG*/
112
113 /*
114 * FIXME ... do we need this? seems to just cause warnings
115 *
116 if( jp2k->codec &&
117 jp2k->stream )
118 opj_end_decompress( jp2k->codec, jp2k->stream );
119 *
120 */
121
122 if( jp2k->info )
123 opj_destroy_cstr_info( &jp2k->info );
124 VIPS_FREEF( opj_destroy_codec, jp2k->codec );
125 VIPS_FREEF( opj_stream_destroy, jp2k->stream );
126 VIPS_FREEF( opj_image_destroy, jp2k->image );
127 VIPS_UNREF( jp2k->source );
128
129 G_OBJECT_CLASS( vips_foreign_load_jp2k_parent_class )->
130 dispose( gobject );
131 }
132
133 static OPJ_SIZE_T
vips_foreign_load_jp2k_read_source(void * buffer,size_t length,void * client)134 vips_foreign_load_jp2k_read_source( void *buffer, size_t length, void *client )
135 {
136 VipsSource *source = VIPS_SOURCE( client );
137 gint64 bytes_read = vips_source_read( source, buffer, length );
138
139 /* openjpeg read uses -1 for both EOF and error return.
140 */
141 return( bytes_read == 0 ? -1 : bytes_read );
142 }
143
144 static OPJ_OFF_T
vips_foreign_load_jp2k_skip_source(OPJ_OFF_T n_bytes,void * client)145 vips_foreign_load_jp2k_skip_source( OPJ_OFF_T n_bytes, void *client )
146 {
147 VipsSource *source = VIPS_SOURCE( client );
148
149 if( vips_source_seek( source, n_bytes, SEEK_CUR ) == -1 )
150 /* openjpeg skip uses -1 for both end of stream and error.
151 */
152 return( -1 );
153
154 return( n_bytes );
155 }
156
157 static OPJ_BOOL
vips_foreign_load_jp2k_seek_source(OPJ_OFF_T position,void * client)158 vips_foreign_load_jp2k_seek_source( OPJ_OFF_T position, void *client )
159 {
160 VipsSource *source = VIPS_SOURCE( client );
161
162 if( vips_source_seek( source, position, SEEK_SET ) == -1 )
163 /* openjpeg seek uses FALSE for both end of stream and error.
164 */
165 return( OPJ_FALSE );
166
167 return( OPJ_TRUE );
168 }
169
170 /* Make a libopenjp2 stream that wraps a VipsSource.
171 */
172 static opj_stream_t *
vips_foreign_load_jp2k_stream(VipsSource * source)173 vips_foreign_load_jp2k_stream( VipsSource *source )
174 {
175 opj_stream_t *stream;
176
177 /* TRUE means a read stream.
178 */
179 if( !(stream = opj_stream_create( OPJ_J2K_STREAM_CHUNK_SIZE, TRUE )) )
180 return( NULL );
181
182 opj_stream_set_user_data( stream, source, NULL );
183 /* Unfortunately, jp2k requires the length, so pipe sources will have
184 * to buffer in memory.
185 */
186 opj_stream_set_user_data_length( stream,
187 vips_source_length( source ) );
188 opj_stream_set_read_function( stream,
189 vips_foreign_load_jp2k_read_source );
190 opj_stream_set_skip_function( stream,
191 vips_foreign_load_jp2k_skip_source );
192 opj_stream_set_seek_function( stream,
193 vips_foreign_load_jp2k_seek_source );
194
195 return( stream );
196 }
197
198 static int
vips_foreign_load_jp2k_build(VipsObject * object)199 vips_foreign_load_jp2k_build( VipsObject *object )
200 {
201 VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
202 VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) object;
203
204 #ifdef DEBUG
205 printf( "vips_foreign_load_jp2k_build:\n" );
206 #endif /*DEBUG*/
207
208 /* Default parameters.
209 */
210 jp2k->parameters.decod_format = -1;
211 jp2k->parameters.cod_format = -1;
212 opj_set_default_decoder_parameters( &jp2k->parameters );
213
214 /* Link the openjpeg stream to our VipsSource.
215 */
216 if( jp2k->source ) {
217 jp2k->stream = vips_foreign_load_jp2k_stream( jp2k->source );
218 if( !jp2k->stream ) {
219 vips_error( class->nickname,
220 "%s", _( "unable to create jp2k stream" ) );
221 return( -1 );
222 }
223 }
224
225 if( VIPS_OBJECT_CLASS( vips_foreign_load_jp2k_parent_class )->
226 build( object ) )
227 return( -1 );
228
229 return( 0 );
230 }
231
232 #define JP2_RFC3745_MAGIC "\x00\x00\x00\x0c\x6a\x50\x20\x20\x0d\x0a\x87\x0a"
233 #define JP2_MAGIC "\x0d\x0a\x87\x0a"
234 /* position 45: "\xff\x52" */
235 #define J2K_CODESTREAM_MAGIC "\xff\x4f\xff\x51"
236
237 /* Return the image format. OpenJPEG supports several different image types.
238 */
239 static OPJ_CODEC_FORMAT
vips_foreign_load_jp2k_get_format(VipsSource * source)240 vips_foreign_load_jp2k_get_format( VipsSource *source )
241 {
242 unsigned char *data;
243
244 if( vips_source_sniff_at_most( source, &data, 12 ) < 12 )
245 return( -1 );
246
247 /* There's also OPJ_CODEC_JPT for xxx.jpt files, but we don't support
248 * that.
249 */
250 if( memcmp( data, JP2_RFC3745_MAGIC, 12) == 0 ||
251 memcmp( data, JP2_MAGIC, 4 ) == 0 )
252 return( OPJ_CODEC_JP2 );
253 else if( memcmp( data, J2K_CODESTREAM_MAGIC, 4 ) == 0 )
254 return( OPJ_CODEC_J2K );
255 else
256 return( -1 );
257 }
258
259 static gboolean
vips_foreign_load_jp2k_is_a_source(VipsSource * source)260 vips_foreign_load_jp2k_is_a_source( VipsSource *source )
261 {
262 return( vips_foreign_load_jp2k_get_format( source ) != -1 );
263 }
264
265 static VipsForeignFlags
vips_foreign_load_jp2k_get_flags(VipsForeignLoad * load)266 vips_foreign_load_jp2k_get_flags( VipsForeignLoad *load )
267 {
268 return( VIPS_FOREIGN_PARTIAL );
269 }
270
271 static void
vips_foreign_load_jp2k_error_callback(const char * msg,void * client)272 vips_foreign_load_jp2k_error_callback( const char *msg, void *client )
273 {
274 VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) client;
275 VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( jp2k );
276
277 vips_error( class->nickname, "%s", msg );
278 jp2k->n_errors += 1;
279 }
280
281 /* The openjpeg info and warning callbacks are incredibly chatty.
282 */
283 static void
vips_foreign_load_jp2k_warning_callback(const char * msg,void * client)284 vips_foreign_load_jp2k_warning_callback( const char *msg, void *client )
285 {
286 #ifdef DEBUG
287 VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( client );
288
289 g_warning( "%s: %s", class->nickname, msg );
290 #endif /*DEBUG*/
291 }
292
293 /* The openjpeg info and warning callbacks are incredibly chatty.
294 */
295 static void
vips_foreign_load_jp2k_info_callback(const char * msg,void * client)296 vips_foreign_load_jp2k_info_callback( const char *msg, void *client )
297 {
298 #ifdef DEBUG
299 VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( client );
300
301 g_info( "%s: %s", class->nickname, msg );
302 #endif /*DEBUG*/
303 }
304
305 static void
vips_foreign_load_jp2k_attach_handlers(VipsForeignLoadJp2k * jp2k,opj_codec_t * codec)306 vips_foreign_load_jp2k_attach_handlers( VipsForeignLoadJp2k *jp2k,
307 opj_codec_t *codec )
308 {
309 opj_set_info_handler( codec,
310 vips_foreign_load_jp2k_info_callback, jp2k );
311 opj_set_warning_handler( codec,
312 vips_foreign_load_jp2k_warning_callback, jp2k );
313 opj_set_error_handler( codec,
314 vips_foreign_load_jp2k_error_callback, jp2k );
315 }
316
317 #ifdef DEBUG
318 static void
vips_foreign_load_jp2k_print_image(opj_image_t * image)319 vips_foreign_load_jp2k_print_image( opj_image_t *image )
320 {
321 printf( "image:\n" );
322 printf( "x0 = %u, y0 = %u, x1 = %u, y1 = %u, numcomps = %u, "
323 "color_space = %u\n",
324 image->x0, image->y0, image->x1, image->y1,
325 image->numcomps, image->color_space );
326 printf( "icc_profile_buf = %p, icc_profile_len = %x\n",
327 image->icc_profile_buf, image->icc_profile_len );
328 }
329
330 static void
vips_foreign_load_jp2k_print(VipsForeignLoadJp2k * jp2k)331 vips_foreign_load_jp2k_print( VipsForeignLoadJp2k *jp2k )
332 {
333 int i;
334
335 vips_foreign_load_jp2k_print_image( jp2k->image );
336
337 printf( "components:\n" );
338 for( i = 0; i < jp2k->image->numcomps; i++ ) {
339 opj_image_comp_t *this = &jp2k->image->comps[i];
340
341 printf( "%i) dx = %u, dy = %u, w = %u, h = %u, "
342 "x0 = %u, y0 = %u\n",
343 i, this->dx, this->dy, this->w, this->h,
344 this->x0, this->y0 );
345 printf( " prec = %x, bpp = %x, sgnd = %x, "
346 "resno_decoded = %u, factor = %u\n",
347 this->prec, this->bpp, this->sgnd,
348 this->resno_decoded, this->factor );
349 printf( " data = %p, alpha = %u\n",
350 this->data, this->alpha );
351 }
352
353 printf( "info:\n" );
354 printf( "tx0 = %u, ty0 = %d, tdx = %u, tdy = %u, tw = %u, th = %u\n",
355 jp2k->info->tx0, jp2k->info->ty0,
356 jp2k->info->tdx, jp2k->info->tdy,
357 jp2k->info->tw, jp2k->info->th );
358 printf( "nbcomps = %u, tile_info = %p\n",
359 jp2k->info->nbcomps, jp2k->info->tile_info );
360 if( jp2k->info->tw == 1 &&
361 jp2k->info->th == 1 )
362 printf( "untiled\n" );
363 }
364 #endif /*DEBUG*/
365
366 static int
vips_foreign_load_jp2k_set_header(VipsForeignLoadJp2k * jp2k,VipsImage * out)367 vips_foreign_load_jp2k_set_header( VipsForeignLoadJp2k *jp2k, VipsImage *out )
368 {
369 VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( jp2k );
370 opj_image_comp_t *first = &jp2k->image->comps[0];
371
372 VipsBandFormat format;
373 VipsInterpretation interpretation;
374
375 /* OpenJPEG only supports up to 31 bpp. Treat it as 32.
376 */
377 if( first->prec <= 8 )
378 format = first->sgnd ? VIPS_FORMAT_CHAR : VIPS_FORMAT_UCHAR;
379 else if( first->prec <= 16 )
380 format = first->sgnd ? VIPS_FORMAT_SHORT : VIPS_FORMAT_USHORT;
381 else
382 format = first->sgnd ? VIPS_FORMAT_INT : VIPS_FORMAT_UINT;
383
384 switch( jp2k->image->color_space ) {
385 case OPJ_CLRSPC_SYCC:
386 case OPJ_CLRSPC_EYCC:
387 /* Map these to RGB.
388 */
389 interpretation = vips_format_sizeof( format ) == 1 ?
390 VIPS_INTERPRETATION_sRGB :
391 VIPS_INTERPRETATION_RGB16;
392 jp2k->ycc_to_rgb = TRUE;
393 break;
394
395 case OPJ_CLRSPC_GRAY:
396 interpretation = vips_format_sizeof( format ) == 1 ?
397 VIPS_INTERPRETATION_B_W :
398 VIPS_INTERPRETATION_GREY16;
399 break;
400
401 case OPJ_CLRSPC_SRGB:
402 interpretation = vips_format_sizeof( format ) == 1 ?
403 VIPS_INTERPRETATION_sRGB :
404 VIPS_INTERPRETATION_RGB16;
405 break;
406
407 case OPJ_CLRSPC_CMYK:
408 interpretation = VIPS_INTERPRETATION_CMYK;
409 break;
410
411 case OPJ_CLRSPC_UNSPECIFIED:
412 /* Try to guess something sensible.
413 */
414 if( jp2k->image->numcomps < 3 )
415 interpretation = vips_format_sizeof( format ) == 1 ?
416 VIPS_INTERPRETATION_B_W :
417 VIPS_INTERPRETATION_GREY16;
418 else
419 interpretation = vips_format_sizeof( format ) == 1 ?
420 VIPS_INTERPRETATION_sRGB :
421 VIPS_INTERPRETATION_RGB16;
422
423 /* Unspecified with three bands and subsampling on bands 2 and
424 * 3 is usually YCC.
425 */
426 if( jp2k->image->numcomps == 3 &&
427 jp2k->image->comps[0].dx == 1 &&
428 jp2k->image->comps[0].dy == 1 &&
429 jp2k->image->comps[1].dx > 1 &&
430 jp2k->image->comps[1].dy > 1 &&
431 jp2k->image->comps[2].dx > 1 &&
432 jp2k->image->comps[2].dy > 1)
433 jp2k->ycc_to_rgb = TRUE;
434
435 break;
436
437 default:
438 vips_error( class->nickname,
439 _( "unsupported colourspace %d" ),
440 jp2k->image->color_space );
441 return( -1 );
442 }
443
444 /* Even though this is a tiled reader, we hint thinstrip since with
445 * the cache we are quite happy serving that if anything downstream
446 * would like it.
447 */
448 if( vips_image_pipelinev( out, VIPS_DEMAND_STYLE_THINSTRIP, NULL ) )
449 return( -1 );
450
451 vips_image_init_fields( out,
452 first->w, first->h, jp2k->image->numcomps, format,
453 VIPS_CODING_NONE, interpretation, 1.0, 1.0 );
454
455 /* openjpeg allows left and top of the coordinate grid to be
456 * non-zero. These are always in unshrunk coordinates.
457 */
458 out->Xoffset =
459 -VIPS_ROUND_INT( (double) jp2k->image->x0 / jp2k->shrink );
460 out->Yoffset =
461 -VIPS_ROUND_INT( (double) jp2k->image->y0 / jp2k->shrink );
462
463 if( jp2k->image->icc_profile_buf &&
464 jp2k->image->icc_profile_len > 0 )
465 vips_image_set_blob_copy( out, VIPS_META_ICC_NAME,
466 jp2k->image->icc_profile_buf,
467 jp2k->image->icc_profile_len );
468
469 /* Map number of layers in image to pages.
470 */
471 if( jp2k->info &&
472 jp2k->info->m_default_tile_info.tccp_info )
473 vips_image_set_int( out, VIPS_META_N_PAGES,
474 jp2k->info->m_default_tile_info.tccp_info->
475 numresolutions );
476
477 return( 0 );
478 }
479
480 static int
vips_foreign_load_jp2k_header(VipsForeignLoad * load)481 vips_foreign_load_jp2k_header( VipsForeignLoad *load )
482 {
483 VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( load );
484 VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) load;
485
486 opj_image_comp_t *first;
487 int i;
488
489 #ifdef DEBUG
490 printf( "vips_foreign_load_jp2k_header:\n" );
491 #endif /*DEBUG*/
492
493 jp2k->format = vips_foreign_load_jp2k_get_format( jp2k->source );
494 vips_source_rewind( jp2k->source );
495 if( !(jp2k->codec = opj_create_decompress( jp2k->format )) )
496 return( -1 );
497
498 vips_foreign_load_jp2k_attach_handlers( jp2k, jp2k->codec );
499
500 jp2k->shrink = 1 << jp2k->page;
501 jp2k->parameters.cp_reduce = jp2k->page;
502 if( !opj_setup_decoder( jp2k->codec, &jp2k->parameters ) )
503 return( -1 );
504
505 opj_codec_set_threads( jp2k->codec, vips_concurrency_get() );
506
507 if( !opj_read_header( jp2k->stream, jp2k->codec, &jp2k->image ) )
508 return( -1 );
509 if( !(jp2k->info = opj_get_cstr_info( jp2k->codec )) )
510 return( -1 );
511
512 #ifdef DEBUG
513 vips_foreign_load_jp2k_print( jp2k );
514 #endif /*DEBUG*/
515
516 /* We only allow images where all components have the same format.
517 */
518 if( jp2k->image->numcomps > MAX_BANDS ) {
519 vips_error( class->nickname,
520 "%s", _( "too many image bands" ) );
521 return( -1 );
522 }
523 if( jp2k->image->numcomps == 0 ) {
524 vips_error( class->nickname,
525 "%s", _( "no image components" ) );
526 return( -1 );
527 }
528 first = &jp2k->image->comps[0];
529 for( i = 1; i < jp2k->image->numcomps; i++ ) {
530 opj_image_comp_t *this = &jp2k->image->comps[i];
531
532 if( this->x0 != first->x0 ||
533 this->y0 != first->y0 ||
534 this->w * this->dx != first->w * first->dx ||
535 this->h * this->dy != first->h * first->dy ||
536 this->resno_decoded != first->resno_decoded ||
537 this->factor != first->factor ) {
538 vips_error( class->nickname,
539 "%s", _( "components differ in geometry" ) );
540 return( -1 );
541 }
542
543 if( this->prec != first->prec ||
544 this->bpp != first->bpp ||
545 this->sgnd != first->sgnd ) {
546 vips_error( class->nickname,
547 "%s", _( "components differ in precision" ) );
548 return( -1 );
549 }
550
551 /* If dx/dy are not 1, we'll need to upsample components during
552 * tile packing.
553 */
554 if( this->dx != first->dx ||
555 this->dy != first->dy ||
556 first->dx != 1 ||
557 first->dy != 1 )
558 jp2k->upsample = TRUE;
559 }
560
561 if( vips_foreign_load_jp2k_set_header( jp2k, load->out ) )
562 return( -1 );
563
564 VIPS_SETSTR( load->out->filename,
565 vips_connection_filename( VIPS_CONNECTION( jp2k->source ) ) );
566
567 return( 0 );
568 }
569
570 #define PACK( TYPE ) { \
571 TYPE *tq = (TYPE *) q; \
572 \
573 for( x = 0; x < length; x++ ) { \
574 for( i = 0; i < b; i++ ) \
575 tq[i] = planes[i][x]; \
576 \
577 tq += b; \
578 } \
579 }
580
581 #define PACK_UPSAMPLE( TYPE ) { \
582 TYPE *tq = (TYPE *) q; \
583 \
584 for( x = 0; x < length; x++ ) { \
585 for( i = 0; i < b; i++ ) { \
586 int dx = image->comps[i].dx; \
587 int pixel = planes[i][x / dx]; \
588 \
589 tq[i] = pixel; \
590 } \
591 \
592 tq += b; \
593 } \
594 }
595
596 /* Pack a line of openjpeg pixels into libvips format. left/top are the
597 * offsets into the opj image in pixel coordinates where we should start
598 * reading.
599 *
600 * Set upsample if any opj component is subsampled.
601 */
602 static void
vips_foreign_load_jp2k_pack(gboolean upsample,opj_image_t * image,VipsImage * im,VipsPel * q,int left,int top,int length)603 vips_foreign_load_jp2k_pack( gboolean upsample,
604 opj_image_t *image, VipsImage *im,
605 VipsPel *q, int left, int top, int length )
606 {
607 int *planes[MAX_BANDS];
608 int b = image->numcomps;
609
610 int x, i;
611
612 #ifdef DEBUG_VERBOSE
613 printf( "vips_foreign_load_jp2k_pack: "
614 "upsample = %d, left = %d, top = %d, length = %d\n",
615 upsample, left, top, length );
616 #endif /*DEBUG_VERBOSE*/
617
618 for( i = 0; i < b; i++ ) {
619 opj_image_comp_t *comp = &image->comps[i];
620
621 planes[i] = comp->data + (top / comp->dy) * comp->w +
622 (left / comp->dx);
623 }
624
625 if( upsample )
626 switch( im->BandFmt ) {
627 case VIPS_FORMAT_CHAR:
628 case VIPS_FORMAT_UCHAR:
629 PACK_UPSAMPLE( unsigned char );
630 break;
631
632 case VIPS_FORMAT_SHORT:
633 case VIPS_FORMAT_USHORT:
634 PACK_UPSAMPLE( unsigned short );
635 break;
636
637 case VIPS_FORMAT_INT:
638 case VIPS_FORMAT_UINT:
639 PACK_UPSAMPLE( unsigned int );
640 break;
641
642 default:
643 g_assert_not_reached();
644 break;
645 }
646 else
647 /* Fast no-upsample path.
648 */
649 switch( im->BandFmt ) {
650 case VIPS_FORMAT_CHAR:
651 case VIPS_FORMAT_UCHAR:
652 PACK( unsigned char );
653 break;
654
655 case VIPS_FORMAT_SHORT:
656 case VIPS_FORMAT_USHORT:
657 PACK( unsigned short );
658 break;
659
660 case VIPS_FORMAT_INT:
661 case VIPS_FORMAT_UINT:
662 PACK( unsigned int );
663 break;
664
665 default:
666 g_assert_not_reached();
667 break;
668 }
669 }
670
671 /* ycc->rgb coversion adapted from openjpeg src/bin/common/color.c
672 *
673 * See also https://en.wikipedia.org/wiki/YCbCr#JPEG_conversion
674 */
675 #define YCC_TO_RGB( TYPE ) { \
676 TYPE *tq = (TYPE *) q; \
677 \
678 for( x = 0; x < length; x++ ) { \
679 int y = tq[0]; \
680 int cb = tq[1] - offset; \
681 int cr = tq[2] - offset; \
682 \
683 int r, g, b; \
684 \
685 r = y + (int)(1.402 * (float)cr); \
686 tq[0] = VIPS_CLIP( 0, r, upb ); \
687 \
688 g = y - (int)(0.344 * (float)cb + 0.714 * (float)cr); \
689 tq[1] = VIPS_CLIP( 0, g, upb ); \
690 \
691 b = y + (int)(1.772 * (float)cb); \
692 tq[2] = VIPS_CLIP( 0, b, upb ); \
693 \
694 tq += 3; \
695 } \
696 }
697
698 /* YCC->RGB for a line of pels.
699 */
700 static void
vips_foreign_load_jp2k_ycc_to_rgb(opj_image_t * image,VipsImage * im,VipsPel * q,int length)701 vips_foreign_load_jp2k_ycc_to_rgb( opj_image_t *image, VipsImage *im,
702 VipsPel *q, int length )
703 {
704 int prec = image->comps[0].prec;
705 int offset = 1 << (prec - 1);
706 int upb = (1 << prec) - 1;
707
708 int x;
709
710 switch( im->BandFmt ) {
711 case VIPS_FORMAT_CHAR:
712 case VIPS_FORMAT_UCHAR:
713 YCC_TO_RGB( unsigned char );
714 break;
715
716 case VIPS_FORMAT_SHORT:
717 case VIPS_FORMAT_USHORT:
718 YCC_TO_RGB( unsigned short );
719 break;
720
721 case VIPS_FORMAT_INT:
722 case VIPS_FORMAT_UINT:
723 YCC_TO_RGB( unsigned int );
724 break;
725
726 default:
727 g_assert_not_reached();
728 break;
729 }
730 }
731
732 /* Read a tile from an untiled jp2k file.
733 */
734 static int
vips_foreign_load_jp2k_generate_untiled(VipsRegion * out,void * seq,void * a,void * b,gboolean * stop)735 vips_foreign_load_jp2k_generate_untiled( VipsRegion *out,
736 void *seq, void *a, void *b, gboolean *stop )
737 {
738 VipsForeignLoad *load = (VipsForeignLoad *) a;
739 VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) load;
740 VipsRect *r = &out->valid;
741
742 VipsRect opj;
743 VipsRect image;
744 int y;
745
746 #ifdef DEBUG_VERBOSE
747 printf( "vips_foreign_load_jp2k_generate_untiled: "
748 "left = %d, top = %d, width = %d, height = %d\n",
749 r->left, r->top, r->width, r->height );
750 #endif /*DEBUG_VERBOSE*/
751
752 /* If openjpeg has flagged an error, the library is not in a known
753 * state and it's not safe to call again.
754 */
755 if( jp2k->n_errors )
756 return( 0 );
757
758 /* Coordinates are always in the highest res level.
759 */
760 opj.left = r->left * jp2k->shrink;
761 opj.top = r->top * jp2k->shrink;
762 opj.width = r->width * jp2k->shrink;
763 opj.height = r->height * jp2k->shrink;
764
765 /* And must be clipped against the image size.
766 */
767 image.left = 0;
768 image.top = 0;
769 image.width = jp2k->info->tdx;
770 image.height = jp2k->info->tdy;
771 vips_rect_intersectrect( &opj, &image, &opj );
772
773 if( !opj_set_decode_area( jp2k->codec, jp2k->image,
774 opj.left, opj.top,
775 VIPS_RECT_RIGHT( &opj ), VIPS_RECT_BOTTOM( &opj ) ) )
776 return( -1 );
777
778 if( !opj_decode( jp2k->codec, jp2k->stream, jp2k->image ) )
779 return( -1 );
780
781 /* Unpack decoded pixels to buffer in vips layout.
782 */
783 for( y = 0; y < r->height; y++ ) {
784 VipsPel *q = VIPS_REGION_ADDR( out, r->left, r->top + y );
785
786 vips_foreign_load_jp2k_pack( jp2k->upsample,
787 jp2k->image, out->im, q, 0, y, r->width );
788
789 if( jp2k->ycc_to_rgb )
790 vips_foreign_load_jp2k_ycc_to_rgb( jp2k->image,
791 out->im, q, r->width );
792 }
793
794 /* jp2k files can't be truncated (they fail to open), so all we can
795 * spot is errors.
796 */
797 if( load->fail_on >= VIPS_FAIL_ON_ERROR &&
798 jp2k->n_errors > 0 )
799 return( -1 );
800
801 return( 0 );
802 }
803
804 /* Read a tile from the file. libvips tiles can be much larger or smaller than
805 * openjpeg tiles, so we must loop over the output region, painting in
806 * tiles from the file.
807 */
808 static int
vips_foreign_load_jp2k_generate_tiled(VipsRegion * out,void * seq,void * a,void * b,gboolean * stop)809 vips_foreign_load_jp2k_generate_tiled( VipsRegion *out,
810 void *seq, void *a, void *b, gboolean *stop )
811 {
812 VipsForeignLoad *load = (VipsForeignLoad *) a;
813 VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) load;
814 VipsRect *r = &out->valid;
815
816 /* jp2k get smaller with the layer size.
817 */
818 int tile_width = VIPS_ROUND_UINT(
819 (double) jp2k->info->tdx / jp2k->shrink );
820 int tile_height = VIPS_ROUND_UINT(
821 (double) jp2k->info->tdy / jp2k->shrink );
822
823 /* ... so tiles_across is always the same.
824 */
825 int tiles_across = jp2k->info->tw;
826
827 int x, y, z;
828
829 #ifdef DEBUG_VERBOSE
830 printf( "vips_foreign_load_jp2k_generate: "
831 "left = %d, top = %d, width = %d, height = %d\n",
832 r->left, r->top, r->width, r->height );
833 #endif /*DEBUG_VERBOSE*/
834
835 /* If openjpeg has flagged an error, the library is not in a known
836 * state and it's not safe to call again.
837 */
838 if( jp2k->n_errors )
839 return( 0 );
840
841 y = 0;
842 while( y < r->height ) {
843 VipsRect tile, hit;
844
845 /* Not necessary, but it stops static analyzers complaining
846 * about a used-before-set.
847 */
848 hit.height = 0;
849
850 x = 0;
851 while( x < r->width ) {
852 /* Tile the xy falls in, in tile numbers.
853 */
854 int tx = (r->left + x) / tile_width;
855 int ty = (r->top + y) / tile_height;
856
857 /* Pixel coordinates of the tile that xy falls in.
858 */
859 int xs = tx * tile_width;
860 int ys = ty * tile_height;
861
862 int tile_index = ty * tiles_across + tx;
863
864 /* Fetch the tile.
865 */
866 #ifdef DEBUG_VERBOSE
867 printf( " fetch tile %d\n", tile_index );
868 #endif /*DEBUG_VERBOSE*/
869 if( !opj_get_decoded_tile( jp2k->codec,
870 jp2k->stream, jp2k->image, tile_index ) )
871 return( -1 );
872
873 /* Intersect tile with request to get pixels we need
874 * to copy out.
875 */
876 tile.left = xs;
877 tile.top = ys;
878 tile.width = tile_width;
879 tile.height = tile_height;
880 vips_rect_intersectrect( &tile, r, &hit );
881
882 /* Unpack hit pixels to buffer in vips layout.
883 */
884 for( z = 0; z < hit.height; z++ ) {
885 VipsPel *q = VIPS_REGION_ADDR( out,
886 hit.left, hit.top + z );
887
888 vips_foreign_load_jp2k_pack( jp2k->upsample,
889 jp2k->image, out->im, q,
890 hit.left - tile.left,
891 hit.top - tile.top + z,
892 hit.width );
893
894 if( jp2k->ycc_to_rgb )
895 vips_foreign_load_jp2k_ycc_to_rgb(
896 jp2k->image, out->im, q,
897 hit.width );
898 }
899
900 x += hit.width;
901 }
902
903 /* This will be the same for all tiles in the row we've just
904 * done.
905 */
906 y += hit.height;
907 }
908
909 /* jp2k files can't be truncated (they fail to open), so all we can
910 * spot is errors.
911 */
912 if( load->fail_on >= VIPS_FAIL_ON_ERROR &&
913 jp2k->n_errors > 0 )
914 return( -1 );
915
916 return( 0 );
917 }
918
919 static int
vips_foreign_load_jp2k_load(VipsForeignLoad * load)920 vips_foreign_load_jp2k_load( VipsForeignLoad *load )
921 {
922 VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) load;
923 VipsImage **t = (VipsImage **)
924 vips_object_local_array( VIPS_OBJECT( load ), 3 );
925
926 int vips_tile_width;
927 int vips_tile_height;
928 int vips_tiles_across;
929
930 #ifdef DEBUG
931 printf( "vips_foreign_load_jp2k_load:\n" );
932 #endif /*DEBUG*/
933
934 t[0] = vips_image_new();
935 if( vips_foreign_load_jp2k_set_header( jp2k, t[0] ) )
936 return( -1 );
937
938 /* Untiled jp2k images need a different read API.
939 */
940 if( jp2k->info->tw == 1 &&
941 jp2k->info->th == 1 ) {
942 vips_tile_width = 512;
943 vips_tile_height = 512;
944 vips_tiles_across =
945 VIPS_ROUND_UP( t[0]->Xsize, vips_tile_width ) /
946 vips_tile_width;
947
948 if( vips_image_generate( t[0],
949 NULL, vips_foreign_load_jp2k_generate_untiled, NULL,
950 jp2k, NULL ) )
951 return( -1 );
952 }
953 else {
954 vips_tile_width = jp2k->info->tdx;
955 vips_tile_height = jp2k->info->tdy;
956 vips_tiles_across = jp2k->info->tw;
957
958 if( vips_image_generate( t[0],
959 NULL, vips_foreign_load_jp2k_generate_tiled, NULL,
960 jp2k, NULL ) )
961 return( -1 );
962 }
963
964 /* Copy to out, adding a cache. Enough tiles for two complete
965 * rows, plus 50%.
966 */
967 if( vips_tilecache( t[0], &t[1],
968 "tile_width", vips_tile_width,
969 "tile_height", vips_tile_height,
970 "max_tiles", 3 * vips_tiles_across,
971 NULL ) )
972 return( -1 );
973
974 if( vips_image_write( t[1], load->real ) )
975 return( -1 );
976
977 return( 0 );
978 }
979
980 static void
vips_foreign_load_jp2k_class_init(VipsForeignLoadJp2kClass * class)981 vips_foreign_load_jp2k_class_init( VipsForeignLoadJp2kClass *class )
982 {
983 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
984 VipsObjectClass *object_class = (VipsObjectClass *) class;
985 VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
986
987 gobject_class->dispose = vips_foreign_load_jp2k_dispose;
988 gobject_class->set_property = vips_object_set_property;
989 gobject_class->get_property = vips_object_get_property;
990
991 object_class->nickname = "jp2kload_base";
992 object_class->description = _( "load JPEG2000 image" );
993 object_class->build = vips_foreign_load_jp2k_build;
994
995 load_class->get_flags = vips_foreign_load_jp2k_get_flags;
996 load_class->header = vips_foreign_load_jp2k_header;
997 load_class->load = vips_foreign_load_jp2k_load;
998
999 VIPS_ARG_INT( class, "page", 20,
1000 _( "Page" ),
1001 _( "Load this page from the image" ),
1002 VIPS_ARGUMENT_OPTIONAL_INPUT,
1003 G_STRUCT_OFFSET( VipsForeignLoadJp2k, page ),
1004 0, 100000, 0 );
1005
1006 }
1007
1008 static void
vips_foreign_load_jp2k_init(VipsForeignLoadJp2k * jp2k)1009 vips_foreign_load_jp2k_init( VipsForeignLoadJp2k *jp2k )
1010 {
1011 }
1012
1013 typedef struct _VipsForeignLoadJp2kFile {
1014 VipsForeignLoadJp2k parent_object;
1015
1016 /* Filename for load.
1017 */
1018 char *filename;
1019
1020 } VipsForeignLoadJp2kFile;
1021
1022 typedef VipsForeignLoadJp2kClass VipsForeignLoadJp2kFileClass;
1023
1024 G_DEFINE_TYPE( VipsForeignLoadJp2kFile, vips_foreign_load_jp2k_file,
1025 vips_foreign_load_jp2k_get_type() );
1026
1027 static int
vips_foreign_load_jp2k_file_build(VipsObject * object)1028 vips_foreign_load_jp2k_file_build( VipsObject *object )
1029 {
1030 VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) object;
1031 VipsForeignLoadJp2kFile *file = (VipsForeignLoadJp2kFile *) object;
1032
1033 if( file->filename &&
1034 !(jp2k->source = vips_source_new_from_file( file->filename )) )
1035 return( -1 );
1036
1037 if( VIPS_OBJECT_CLASS( vips_foreign_load_jp2k_file_parent_class )->
1038 build( object ) )
1039 return( -1 );
1040
1041 return( 0 );
1042 }
1043
1044 const char *vips__jp2k_suffs[] =
1045 { ".j2k", ".jp2", ".jpt", ".j2c", ".jpc", NULL };
1046
1047 static int
vips_foreign_load_jp2k_is_a(const char * filename)1048 vips_foreign_load_jp2k_is_a( const char *filename )
1049 {
1050 VipsSource *source;
1051 gboolean result;
1052
1053 if( !(source = vips_source_new_from_file( filename )) )
1054 return( FALSE );
1055 result = vips_foreign_load_jp2k_is_a_source( source );
1056 VIPS_UNREF( source );
1057
1058 return( result );
1059 }
1060
1061 static void
vips_foreign_load_jp2k_file_class_init(VipsForeignLoadJp2kFileClass * class)1062 vips_foreign_load_jp2k_file_class_init(
1063 VipsForeignLoadJp2kFileClass *class )
1064 {
1065 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
1066 VipsObjectClass *object_class = (VipsObjectClass *) class;
1067 VipsForeignClass *foreign_class = (VipsForeignClass *) class;
1068 VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
1069
1070 gobject_class->set_property = vips_object_set_property;
1071 gobject_class->get_property = vips_object_get_property;
1072
1073 object_class->nickname = "jp2kload";
1074 object_class->build = vips_foreign_load_jp2k_file_build;
1075
1076 foreign_class->suffs = vips__jp2k_suffs;
1077
1078 load_class->is_a = vips_foreign_load_jp2k_is_a;
1079
1080 VIPS_ARG_STRING( class, "filename", 1,
1081 _( "Filename" ),
1082 _( "Filename to load from" ),
1083 VIPS_ARGUMENT_REQUIRED_INPUT,
1084 G_STRUCT_OFFSET( VipsForeignLoadJp2kFile, filename ),
1085 NULL );
1086
1087 }
1088
1089 static void
vips_foreign_load_jp2k_file_init(VipsForeignLoadJp2kFile * jp2k)1090 vips_foreign_load_jp2k_file_init( VipsForeignLoadJp2kFile *jp2k )
1091 {
1092 }
1093
1094 typedef struct _VipsForeignLoadJp2kBuffer {
1095 VipsForeignLoadJp2k parent_object;
1096
1097 /* Load from a buffer.
1098 */
1099 VipsArea *buf;
1100
1101 } VipsForeignLoadJp2kBuffer;
1102
1103 typedef VipsForeignLoadJp2kClass VipsForeignLoadJp2kBufferClass;
1104
1105 G_DEFINE_TYPE( VipsForeignLoadJp2kBuffer, vips_foreign_load_jp2k_buffer,
1106 vips_foreign_load_jp2k_get_type() );
1107
1108 static int
vips_foreign_load_jp2k_buffer_build(VipsObject * object)1109 vips_foreign_load_jp2k_buffer_build( VipsObject *object )
1110 {
1111 VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) object;
1112 VipsForeignLoadJp2kBuffer *buffer =
1113 (VipsForeignLoadJp2kBuffer *) object;
1114
1115 if( buffer->buf )
1116 if( !(jp2k->source = vips_source_new_from_memory(
1117 VIPS_AREA( buffer->buf )->data,
1118 VIPS_AREA( buffer->buf )->length )) )
1119 return( -1 );
1120
1121 if( VIPS_OBJECT_CLASS( vips_foreign_load_jp2k_file_parent_class )->
1122 build( object ) )
1123 return( -1 );
1124
1125 return( 0 );
1126 }
1127
1128 static gboolean
vips_foreign_load_jp2k_buffer_is_a(const void * buf,size_t len)1129 vips_foreign_load_jp2k_buffer_is_a( const void *buf, size_t len )
1130 {
1131 VipsSource *source;
1132 gboolean result;
1133
1134 if( !(source = vips_source_new_from_memory( buf, len )) )
1135 return( FALSE );
1136 result = vips_foreign_load_jp2k_is_a_source( source );
1137 VIPS_UNREF( source );
1138
1139 return( result );
1140 }
1141
1142 static void
vips_foreign_load_jp2k_buffer_class_init(VipsForeignLoadJp2kBufferClass * class)1143 vips_foreign_load_jp2k_buffer_class_init(
1144 VipsForeignLoadJp2kBufferClass *class )
1145 {
1146 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
1147 VipsObjectClass *object_class = (VipsObjectClass *) class;
1148 VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
1149
1150 gobject_class->set_property = vips_object_set_property;
1151 gobject_class->get_property = vips_object_get_property;
1152
1153 object_class->nickname = "jp2kload_buffer";
1154 object_class->build = vips_foreign_load_jp2k_buffer_build;
1155
1156 load_class->is_a_buffer = vips_foreign_load_jp2k_buffer_is_a;
1157
1158 VIPS_ARG_BOXED( class, "buffer", 1,
1159 _( "Buffer" ),
1160 _( "Buffer to load from" ),
1161 VIPS_ARGUMENT_REQUIRED_INPUT,
1162 G_STRUCT_OFFSET( VipsForeignLoadJp2kBuffer, buf ),
1163 VIPS_TYPE_BLOB );
1164
1165 }
1166
1167 static void
vips_foreign_load_jp2k_buffer_init(VipsForeignLoadJp2kBuffer * buffer)1168 vips_foreign_load_jp2k_buffer_init( VipsForeignLoadJp2kBuffer *buffer )
1169 {
1170 }
1171
1172 typedef struct _VipsForeignLoadJp2kSource {
1173 VipsForeignLoadJp2k parent_object;
1174
1175 /* Load from a source.
1176 */
1177 VipsSource *source;
1178
1179 } VipsForeignLoadJp2kSource;
1180
1181 typedef VipsForeignLoadJp2kClass VipsForeignLoadJp2kSourceClass;
1182
1183 G_DEFINE_TYPE( VipsForeignLoadJp2kSource, vips_foreign_load_jp2k_source,
1184 vips_foreign_load_jp2k_get_type() );
1185
1186 static int
vips_foreign_load_jp2k_source_build(VipsObject * object)1187 vips_foreign_load_jp2k_source_build( VipsObject *object )
1188 {
1189 VipsForeignLoadJp2k *jp2k = (VipsForeignLoadJp2k *) object;
1190 VipsForeignLoadJp2kSource *source =
1191 (VipsForeignLoadJp2kSource *) object;
1192
1193 if( source->source ) {
1194 jp2k->source = source->source;
1195 g_object_ref( jp2k->source );
1196 }
1197
1198 if( VIPS_OBJECT_CLASS(
1199 vips_foreign_load_jp2k_source_parent_class )->
1200 build( object ) )
1201 return( -1 );
1202
1203 return( 0 );
1204 }
1205
1206 static void
vips_foreign_load_jp2k_source_class_init(VipsForeignLoadJp2kSourceClass * class)1207 vips_foreign_load_jp2k_source_class_init(
1208 VipsForeignLoadJp2kSourceClass *class )
1209 {
1210 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
1211 VipsObjectClass *object_class = (VipsObjectClass *) class;
1212 VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
1213 VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
1214
1215 gobject_class->set_property = vips_object_set_property;
1216 gobject_class->get_property = vips_object_get_property;
1217
1218 object_class->nickname = "jp2kload_source";
1219 object_class->build = vips_foreign_load_jp2k_source_build;
1220
1221 operation_class->flags = VIPS_OPERATION_NOCACHE;
1222
1223 load_class->is_a_source = vips_foreign_load_jp2k_is_a_source;
1224
1225 VIPS_ARG_OBJECT( class, "source", 1,
1226 _( "Source" ),
1227 _( "Source to load from" ),
1228 VIPS_ARGUMENT_REQUIRED_INPUT,
1229 G_STRUCT_OFFSET( VipsForeignLoadJp2kSource, source ),
1230 VIPS_TYPE_SOURCE );
1231
1232 }
1233
1234 static void
vips_foreign_load_jp2k_source_init(VipsForeignLoadJp2kSource * jp2k)1235 vips_foreign_load_jp2k_source_init(
1236 VipsForeignLoadJp2kSource *jp2k )
1237 {
1238 }
1239
1240 static void
warning_callback(const char * msg G_GNUC_UNUSED,void * data G_GNUC_UNUSED)1241 warning_callback( const char *msg G_GNUC_UNUSED, void *data G_GNUC_UNUSED )
1242 {
1243 /* There are a lot of warnings ...
1244 */
1245 }
1246
1247 static void
error_callback(const char * msg,void * data)1248 error_callback( const char *msg, void *data )
1249 {
1250 printf( "OpenJPEG: %s", msg );
1251 vips_error( "OpenJPEG", "%s", msg );
1252 }
1253
1254 typedef struct _TileDecompress {
1255 VipsSource *source;
1256 opj_stream_t *stream;
1257 opj_codec_t *codec;
1258 opj_image_t *image;
1259 } TileDecompress;
1260
1261 static void
vips__foreign_load_jp2k_decompress_free(TileDecompress * decompress)1262 vips__foreign_load_jp2k_decompress_free( TileDecompress *decompress )
1263 {
1264 VIPS_FREEF( opj_destroy_codec, decompress->codec );
1265 VIPS_FREEF( opj_image_destroy, decompress->image );
1266 VIPS_FREEF( opj_stream_destroy, decompress->stream );
1267 VIPS_UNREF( decompress->source );
1268 }
1269
1270 /* Called from tiff2vips to decode a jp2k-compressed tile.
1271 *
1272 * width/height is the tile size. If this is an edge tile, and smaller than
1273 * this, we still write a full-size tile and our caller will clip.
1274 */
1275 int
vips__foreign_load_jp2k_decompress(VipsImage * out,int width,int height,gboolean ycc_to_rgb,void * from,size_t from_length,void * to,size_t to_length)1276 vips__foreign_load_jp2k_decompress( VipsImage *out,
1277 int width, int height, gboolean ycc_to_rgb,
1278 void *from, size_t from_length,
1279 void *to, size_t to_length )
1280 {
1281 size_t pel_size = VIPS_IMAGE_SIZEOF_PEL( out );
1282 size_t line_size = pel_size * width;
1283
1284 TileDecompress decompress = { 0 };
1285 opj_dparameters_t parameters;
1286 int i;
1287 gboolean upsample;
1288 VipsPel *q;
1289 int y;
1290
1291 #ifdef DEBUG
1292 printf( "vips__foreign_load_jp2k_decompress: width = %d, height = %d, "
1293 "ycc_to_rgb = %d, from_length = %zd, to_length = %zd\n",
1294 width, height, ycc_to_rgb, from_length, to_length );
1295 #endif /*DEBUG*/
1296
1297 /* Our ycc->rgb only works for exactly 3 bands.
1298 */
1299 ycc_to_rgb = ycc_to_rgb && out->Bands == 3;
1300
1301 decompress.codec = opj_create_decompress( OPJ_CODEC_J2K );
1302 opj_set_default_decoder_parameters( ¶meters );
1303 opj_setup_decoder( decompress.codec, ¶meters );
1304 opj_set_warning_handler( decompress.codec, warning_callback, NULL );
1305 opj_set_error_handler( decompress.codec, error_callback, NULL );
1306
1307 decompress.source = vips_source_new_from_memory( from, from_length );
1308 decompress.stream = vips_foreign_load_jp2k_stream( decompress.source );
1309 if( !opj_read_header( decompress.stream,
1310 decompress.codec, &decompress.image ) ) {
1311 vips_error( "jp2kload", "%s", ( "header error" ) );
1312 vips__foreign_load_jp2k_decompress_free( &decompress );
1313 return( -1 );
1314 }
1315
1316 if( decompress.image->x1 > width ||
1317 decompress.image->y1 > height ||
1318 line_size * height > to_length ) {
1319 vips_error( "jp2kload", "%s", ( "bad dimensions" ) );
1320 vips__foreign_load_jp2k_decompress_free( &decompress );
1321 return( -1 );
1322 }
1323
1324 if( !opj_decode( decompress.codec,
1325 decompress.stream, decompress.image ) ) {
1326 vips_error( "jp2kload", "%s", ( "decode error" ) );
1327 vips__foreign_load_jp2k_decompress_free( &decompress );
1328 return( -1 );
1329 }
1330
1331 /* Do any components need upsampling?
1332 */
1333 upsample = FALSE;
1334 for( i = 0; i < decompress.image->numcomps; i++ ) {
1335 opj_image_comp_t *this = &decompress.image->comps[i];
1336
1337 if( this->dx > 1 ||
1338 this->dy > 1 )
1339 upsample = TRUE;
1340 }
1341
1342 /* Unpack hit pixels to buffer in vips layout.
1343 */
1344 q = to;
1345 for( y = 0; y < height; y++ ) {
1346 vips_foreign_load_jp2k_pack( upsample,
1347 decompress.image, out, q,
1348 0, y, width );
1349
1350 if( ycc_to_rgb )
1351 vips_foreign_load_jp2k_ycc_to_rgb(
1352 decompress.image, out, q,
1353 width );
1354
1355 q += line_size;
1356 }
1357
1358 vips__foreign_load_jp2k_decompress_free( &decompress );
1359
1360 return( 0 );
1361 }
1362
1363 #else /*!HAVE_LIBOPENJP2*/
1364
1365 int
vips__foreign_load_jp2k_decompress(VipsImage * out,int width,int height,gboolean ycc_to_rgb,void * from,size_t from_length,void * to,size_t to_length)1366 vips__foreign_load_jp2k_decompress( VipsImage *out,
1367 int width, int height, gboolean ycc_to_rgb,
1368 void *from, size_t from_length,
1369 void *to, size_t to_length )
1370 {
1371 vips_error( "jp2k",
1372 "%s", _( "libvips built without JPEG2000 support" ) );
1373 return( -1 );
1374 }
1375
1376 #endif /*HAVE_LIBOPENJP2*/
1377
1378 /**
1379 * vips_jp2kload:
1380 * @filename: file to load
1381 * @out: (out): decompressed image
1382 * @...: %NULL-terminated list of optional named arguments
1383 *
1384 * Optional arguments:
1385 *
1386 * * @page: %gint, load this page
1387 * * @fail_on: #VipsFailOn, types of read error to fail on
1388 *
1389 * Read a JPEG2000 image. The loader supports 8, 16 and 32-bit int pixel
1390 * values, signed and unsigned. It supports greyscale, RGB, YCC, CMYK and
1391 * multispectral colour spaces. It will read any ICC profile on the image.
1392 *
1393 * It will only load images where all channels have the same format.
1394 *
1395 * Use @page to set the page to load, where page 0 is the base resolution
1396 * image and higher-numbered pages are x2 reductions. Use the metadata item
1397 * "n-pages" to find the number of pyramid layers.
1398 *
1399 * Use @fail_on to set the type of error that will cause load to fail. By
1400 * default, loaders are permissive, that is, #VIPS_FAIL_ON_NONE.
1401 *
1402 * See also: vips_image_new_from_file().
1403 *
1404 * Returns: 0 on success, -1 on error.
1405 */
1406 int
vips_jp2kload(const char * filename,VipsImage ** out,...)1407 vips_jp2kload( const char *filename, VipsImage **out, ... )
1408 {
1409 va_list ap;
1410 int result;
1411
1412 va_start( ap, out );
1413 result = vips_call_split( "jp2kload", ap, filename, out );
1414 va_end( ap );
1415
1416 return( result );
1417 }
1418
1419 /**
1420 * vips_jp2kload_buffer:
1421 * @buf: (array length=len) (element-type guint8): memory area to load
1422 * @len: (type gsize): size of memory area
1423 * @out: (out): image to write
1424 * @...: %NULL-terminated list of optional named arguments
1425 *
1426 * Optional arguments:
1427 *
1428 * * @page: %gint, load this page
1429 * * @fail_on: #VipsFailOn, types of read error to fail on
1430 *
1431 * Exactly as vips_jp2kload(), but read from a buffer.
1432 *
1433 * You must not free the buffer while @out is active. The
1434 * #VipsObject::postclose signal on @out is a good place to free.
1435 *
1436 * Returns: 0 on success, -1 on error.
1437 */
1438 int
vips_jp2kload_buffer(void * buf,size_t len,VipsImage ** out,...)1439 vips_jp2kload_buffer( void *buf, size_t len, VipsImage **out, ... )
1440 {
1441 va_list ap;
1442 VipsBlob *blob;
1443 int result;
1444
1445 /* We don't take a copy of the data or free it.
1446 */
1447 blob = vips_blob_new( NULL, buf, len );
1448
1449 va_start( ap, out );
1450 result = vips_call_split( "jp2kload_buffer", ap, blob, out );
1451 va_end( ap );
1452
1453 vips_area_unref( VIPS_AREA( blob ) );
1454
1455 return( result );
1456 }
1457
1458 /**
1459 * vips_jp2kload_source:
1460 * @source: source to load from
1461 * @out: (out): decompressed image
1462 * @...: %NULL-terminated list of optional named arguments
1463 *
1464 * Optional arguments:
1465 *
1466 * * @page: %gint, load this page
1467 * * @fail_on: #VipsFailOn, types of read error to fail on
1468 *
1469 * Exactly as vips_jp2kload(), but read from a source.
1470 *
1471 * Returns: 0 on success, -1 on error.
1472 */
1473 int
vips_jp2kload_source(VipsSource * source,VipsImage ** out,...)1474 vips_jp2kload_source( VipsSource *source, VipsImage **out, ... )
1475 {
1476 va_list ap;
1477 int result;
1478
1479 va_start( ap, out );
1480 result = vips_call_split( "jp2kload_source", ap, source, out );
1481 va_end( ap );
1482
1483 return( result );
1484 }
1485