1 /* load tiff from a file
2 *
3 * 5/12/11
4 * - from tiffload.c
5 * 27/1/17
6 * - add get_flags for buffer loader
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
38 */
39
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif /*HAVE_CONFIG_H*/
43 #include <vips/intl.h>
44
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48
49 #include <vips/vips.h>
50 #include <vips/buf.h>
51 #include <vips/internal.h>
52
53 #include "pforeign.h"
54
55 #ifdef HAVE_TIFF
56
57 typedef struct _VipsForeignLoadTiff {
58 VipsForeignLoad parent_object;
59
60 /* Set by subclasses.
61 */
62 VipsSource *source;
63
64 /* Load this page.
65 */
66 int page;
67
68 /* Load this many pages.
69 */
70 int n;
71
72 /* Select subifd index. -1 for main image.
73 */
74 int subifd;
75
76 /* Autorotate using orientation tag.
77 */
78 gboolean autorotate;
79
80 } VipsForeignLoadTiff;
81
82 typedef VipsForeignLoadClass VipsForeignLoadTiffClass;
83
84 G_DEFINE_ABSTRACT_TYPE( VipsForeignLoadTiff, vips_foreign_load_tiff,
85 VIPS_TYPE_FOREIGN_LOAD );
86
87 static void
vips_foreign_load_tiff_dispose(GObject * gobject)88 vips_foreign_load_tiff_dispose( GObject *gobject )
89 {
90 VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) gobject;
91
92 VIPS_UNREF( tiff->source );
93
94 G_OBJECT_CLASS( vips_foreign_load_tiff_parent_class )->
95 dispose( gobject );
96 }
97
98 static VipsForeignFlags
vips_foreign_load_tiff_get_flags_source(VipsSource * source)99 vips_foreign_load_tiff_get_flags_source( VipsSource *source )
100 {
101 VipsForeignFlags flags;
102
103 flags = 0;
104 if( vips__istifftiled_source( source ) )
105 flags |= VIPS_FOREIGN_PARTIAL;
106 else
107 flags |= VIPS_FOREIGN_SEQUENTIAL;
108
109 return( flags );
110 }
111
112 static VipsForeignFlags
vips_foreign_load_tiff_get_flags_filename(const char * filename)113 vips_foreign_load_tiff_get_flags_filename( const char *filename )
114 {
115 VipsSource *source;
116 VipsForeignFlags flags;
117
118 if( !(source = vips_source_new_from_file( filename )) )
119 return( 0 );
120 flags = vips_foreign_load_tiff_get_flags_source( source );
121 VIPS_UNREF( source );
122
123 return( flags );
124 }
125
126 static VipsForeignFlags
vips_foreign_load_tiff_get_flags(VipsForeignLoad * load)127 vips_foreign_load_tiff_get_flags( VipsForeignLoad *load )
128 {
129 VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
130
131 return( vips_foreign_load_tiff_get_flags_source( tiff->source ) );
132 }
133
134 static int
vips_foreign_load_tiff_header(VipsForeignLoad * load)135 vips_foreign_load_tiff_header( VipsForeignLoad *load )
136 {
137 VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
138
139 if( vips__tiff_read_header_source( tiff->source, load->out,
140 tiff->page, tiff->n, tiff->autorotate, tiff->subifd,
141 load->fail_on ) )
142 return( -1 );
143
144 return( 0 );
145 }
146
147 static int
vips_foreign_load_tiff_load(VipsForeignLoad * load)148 vips_foreign_load_tiff_load( VipsForeignLoad *load )
149 {
150 VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) load;
151
152 if( vips__tiff_read_source( tiff->source, load->real,
153 tiff->page, tiff->n, tiff->autorotate, tiff->subifd,
154 load->fail_on ) )
155 return( -1 );
156
157 return( 0 );
158 }
159
160 static void
vips_foreign_load_tiff_class_init(VipsForeignLoadTiffClass * class)161 vips_foreign_load_tiff_class_init( VipsForeignLoadTiffClass *class )
162 {
163 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
164 VipsObjectClass *object_class = (VipsObjectClass *) class;
165 VipsForeignClass *foreign_class = (VipsForeignClass *) class;
166 VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
167
168 /* Other libraries may be using libtiff, we want to capture tiff
169 * warning and error as soon as we can.
170 *
171 * This class init will be triggered during startup.
172 */
173 vips__tiff_init();
174
175 gobject_class->dispose = vips_foreign_load_tiff_dispose;
176 gobject_class->set_property = vips_object_set_property;
177 gobject_class->get_property = vips_object_get_property;
178
179 object_class->nickname = "tiffload_base";
180 object_class->description = _( "load tiff" );
181
182 /* We are fast, but must test after openslideload.
183 */
184 foreign_class->priority = 50;
185
186 load_class->get_flags_filename =
187 vips_foreign_load_tiff_get_flags_filename;
188 load_class->get_flags = vips_foreign_load_tiff_get_flags;
189 load_class->header = vips_foreign_load_tiff_header;
190 load_class->load = vips_foreign_load_tiff_load;
191
192 VIPS_ARG_INT( class, "page", 20,
193 _( "Page" ),
194 _( "Load this page from the image" ),
195 VIPS_ARGUMENT_OPTIONAL_INPUT,
196 G_STRUCT_OFFSET( VipsForeignLoadTiff, page ),
197 0, 100000, 0 );
198
199 VIPS_ARG_INT( class, "n", 21,
200 _( "n" ),
201 _( "Load this many pages" ),
202 VIPS_ARGUMENT_OPTIONAL_INPUT,
203 G_STRUCT_OFFSET( VipsForeignLoadTiff, n ),
204 -1, 100000, 1 );
205
206 VIPS_ARG_BOOL( class, "autorotate", 22,
207 _( "Autorotate" ),
208 _( "Rotate image using orientation tag" ),
209 VIPS_ARGUMENT_OPTIONAL_INPUT,
210 G_STRUCT_OFFSET( VipsForeignLoadTiff, autorotate ),
211 FALSE );
212
213 VIPS_ARG_INT( class, "subifd", 21,
214 _( "subifd" ),
215 _( "Select subifd index" ),
216 VIPS_ARGUMENT_OPTIONAL_INPUT,
217 G_STRUCT_OFFSET( VipsForeignLoadTiff, subifd ),
218 -1, 100000, -1 );
219
220 }
221
222 static void
vips_foreign_load_tiff_init(VipsForeignLoadTiff * tiff)223 vips_foreign_load_tiff_init( VipsForeignLoadTiff *tiff )
224 {
225 tiff->page = 0;
226 tiff->n = 1;
227 tiff->subifd = -1;
228 }
229
230 typedef struct _VipsForeignLoadTiffSource {
231 VipsForeignLoadTiff parent_object;
232
233 /* Load from a source.
234 */
235 VipsSource *source;
236
237 } VipsForeignLoadTiffSource;
238
239 typedef VipsForeignLoadTiffClass VipsForeignLoadTiffSourceClass;
240
241 G_DEFINE_TYPE( VipsForeignLoadTiffSource, vips_foreign_load_tiff_source,
242 vips_foreign_load_tiff_get_type() );
243
244 static int
vips_foreign_load_tiff_source_build(VipsObject * object)245 vips_foreign_load_tiff_source_build( VipsObject *object )
246 {
247 VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) object;
248 VipsForeignLoadTiffSource *source =
249 (VipsForeignLoadTiffSource *) object;
250
251 if( source->source ) {
252 tiff->source = source->source;
253 g_object_ref( tiff->source );
254 }
255
256 if( VIPS_OBJECT_CLASS( vips_foreign_load_tiff_source_parent_class )->
257 build( object ) )
258 return( -1 );
259
260 return( 0 );
261 }
262
263 static gboolean
vips_foreign_load_tiff_source_is_a_source(VipsSource * source)264 vips_foreign_load_tiff_source_is_a_source( VipsSource *source )
265 {
266 return( vips__istiff_source( source ) );
267 }
268
269 static void
vips_foreign_load_tiff_source_class_init(VipsForeignLoadTiffSourceClass * class)270 vips_foreign_load_tiff_source_class_init(
271 VipsForeignLoadTiffSourceClass *class )
272 {
273 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
274 VipsObjectClass *object_class = (VipsObjectClass *) class;
275 VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class );
276 VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
277
278 gobject_class->set_property = vips_object_set_property;
279 gobject_class->get_property = vips_object_get_property;
280
281 object_class->nickname = "tiffload_source";
282 object_class->description = _( "load tiff from source" );
283 object_class->build = vips_foreign_load_tiff_source_build;
284
285 operation_class->flags = VIPS_OPERATION_NOCACHE;
286
287 load_class->is_a_source = vips_foreign_load_tiff_source_is_a_source;
288
289 VIPS_ARG_OBJECT( class, "source", 1,
290 _( "Source" ),
291 _( "Source to load from" ),
292 VIPS_ARGUMENT_REQUIRED_INPUT,
293 G_STRUCT_OFFSET( VipsForeignLoadTiffSource, source ),
294 VIPS_TYPE_SOURCE );
295
296 }
297
298 static void
vips_foreign_load_tiff_source_init(VipsForeignLoadTiffSource * source)299 vips_foreign_load_tiff_source_init( VipsForeignLoadTiffSource *source )
300 {
301 }
302
303 typedef struct _VipsForeignLoadTiffFile {
304 VipsForeignLoadTiff parent_object;
305
306 /* Filename for load.
307 */
308 char *filename;
309
310 } VipsForeignLoadTiffFile;
311
312 typedef VipsForeignLoadTiffClass VipsForeignLoadTiffFileClass;
313
314 G_DEFINE_TYPE( VipsForeignLoadTiffFile, vips_foreign_load_tiff_file,
315 vips_foreign_load_tiff_get_type() );
316
317 static int
vips_foreign_load_tiff_file_build(VipsObject * object)318 vips_foreign_load_tiff_file_build( VipsObject *object )
319 {
320 VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) object;
321 VipsForeignLoadTiffFile *file = (VipsForeignLoadTiffFile *) object;
322
323 if( file->filename &&
324 !(tiff->source =
325 vips_source_new_from_file( file->filename )) )
326 return( -1 );
327
328 if( VIPS_OBJECT_CLASS( vips_foreign_load_tiff_file_parent_class )->
329 build( object ) )
330 return( -1 );
331
332 return( 0 );
333 }
334
335 static gboolean
vips_foreign_load_tiff_file_is_a(const char * filename)336 vips_foreign_load_tiff_file_is_a( const char *filename )
337 {
338 VipsSource *source;
339 gboolean result;
340
341 if( !(source = vips_source_new_from_file( filename )) )
342 return( FALSE );
343 result = vips_foreign_load_tiff_source_is_a_source( source );
344 VIPS_UNREF( source );
345
346 return( result );
347 }
348
349 const char *vips__foreign_tiff_suffs[] = { ".tif", ".tiff", NULL };
350
351 static void
vips_foreign_load_tiff_file_class_init(VipsForeignLoadTiffFileClass * class)352 vips_foreign_load_tiff_file_class_init( VipsForeignLoadTiffFileClass *class )
353 {
354 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
355 VipsObjectClass *object_class = (VipsObjectClass *) class;
356 VipsForeignClass *foreign_class = (VipsForeignClass *) class;
357 VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
358
359 gobject_class->set_property = vips_object_set_property;
360 gobject_class->get_property = vips_object_get_property;
361
362 object_class->nickname = "tiffload";
363 object_class->description = _( "load tiff from file" );
364 object_class->build = vips_foreign_load_tiff_file_build;
365
366 foreign_class->suffs = vips__foreign_tiff_suffs;
367
368 load_class->is_a = vips_foreign_load_tiff_file_is_a;
369
370 VIPS_ARG_STRING( class, "filename", 1,
371 _( "Filename" ),
372 _( "Filename to load from" ),
373 VIPS_ARGUMENT_REQUIRED_INPUT,
374 G_STRUCT_OFFSET( VipsForeignLoadTiffFile, filename ),
375 NULL );
376 }
377
378 static void
vips_foreign_load_tiff_file_init(VipsForeignLoadTiffFile * file)379 vips_foreign_load_tiff_file_init( VipsForeignLoadTiffFile *file )
380 {
381 }
382
383 typedef struct _VipsForeignLoadTiffBuffer {
384 VipsForeignLoadTiff parent_object;
385
386 /* Load from a buffer.
387 */
388 VipsBlob *blob;
389
390 } VipsForeignLoadTiffBuffer;
391
392 typedef VipsForeignLoadTiffClass VipsForeignLoadTiffBufferClass;
393
394 G_DEFINE_TYPE( VipsForeignLoadTiffBuffer, vips_foreign_load_tiff_buffer,
395 vips_foreign_load_tiff_get_type() );
396
397 static int
vips_foreign_load_tiff_buffer_build(VipsObject * object)398 vips_foreign_load_tiff_buffer_build( VipsObject *object )
399 {
400 VipsForeignLoadTiff *tiff = (VipsForeignLoadTiff *) object;
401 VipsForeignLoadTiffBuffer *buffer =
402 (VipsForeignLoadTiffBuffer *) object;
403
404 if( buffer->blob &&
405 !(tiff->source = vips_source_new_from_memory(
406 VIPS_AREA( buffer->blob )->data,
407 VIPS_AREA( buffer->blob )->length )) )
408 return( -1 );
409
410 if( VIPS_OBJECT_CLASS( vips_foreign_load_tiff_buffer_parent_class )->
411 build( object ) )
412 return( -1 );
413
414 return( 0 );
415 }
416
417 static gboolean
vips_foreign_load_tiff_buffer_is_a_buffer(const void * buf,size_t len)418 vips_foreign_load_tiff_buffer_is_a_buffer( const void *buf, size_t len )
419 {
420 VipsSource *source;
421 gboolean result;
422
423 if( !(source = vips_source_new_from_memory( buf, len )) )
424 return( FALSE );
425 result = vips_foreign_load_tiff_source_is_a_source( source );
426 VIPS_UNREF( source );
427
428 return( result );
429 }
430
431 static void
vips_foreign_load_tiff_buffer_class_init(VipsForeignLoadTiffBufferClass * class)432 vips_foreign_load_tiff_buffer_class_init(
433 VipsForeignLoadTiffBufferClass *class )
434 {
435 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
436 VipsObjectClass *object_class = (VipsObjectClass *) class;
437 VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
438
439 gobject_class->set_property = vips_object_set_property;
440 gobject_class->get_property = vips_object_get_property;
441
442 object_class->nickname = "tiffload_buffer";
443 object_class->description = _( "load tiff from buffer" );
444 object_class->build = vips_foreign_load_tiff_buffer_build;
445
446 load_class->is_a_buffer = vips_foreign_load_tiff_buffer_is_a_buffer;
447
448 VIPS_ARG_BOXED( class, "buffer", 1,
449 _( "Buffer" ),
450 _( "Buffer to load from" ),
451 VIPS_ARGUMENT_REQUIRED_INPUT,
452 G_STRUCT_OFFSET( VipsForeignLoadTiffBuffer, blob ),
453 VIPS_TYPE_BLOB );
454 }
455
456 static void
vips_foreign_load_tiff_buffer_init(VipsForeignLoadTiffBuffer * buffer)457 vips_foreign_load_tiff_buffer_init( VipsForeignLoadTiffBuffer *buffer )
458 {
459 }
460
461 #endif /*HAVE_TIFF*/
462
463 /**
464 * vips_tiffload:
465 * @filename: file to load
466 * @out: (out): decompressed image
467 * @...: %NULL-terminated list of optional named arguments
468 *
469 * Optional arguments:
470 *
471 * * @page: %gint, load this page
472 * * @n: %gint, load this many pages
473 * * @autorotate: %gboolean, use orientation tag to rotate the image
474 * during load
475 * * @subifd: %gint, select this subifd index
476 *
477 * Read a TIFF file into a VIPS image. It is a full baseline TIFF 6 reader,
478 * with extensions for tiled images, multipage images, XYZ and LAB colour
479 * space, pyramidal images and JPEG compression, including CMYK and YCbCr.
480 *
481 * @page means load this page from the file. By default the first page (page
482 * 0) is read.
483 *
484 * @n means load this many pages. By default a single page is read. All the
485 * pages must have the same dimensions, and they are loaded as a tall, thin
486 * "toilet roll" image. The #VIPS_META_PAGE_HEIGHT metadata
487 * tag gives the height in pixels of each page. Use -1 to load all pages.
488 *
489 * Setting @autorotate to %TRUE will make the loader interpret the
490 * orientation tag and automatically rotate the image appropriately during
491 * load.
492 *
493 * If @autorotate is %FALSE, the metadata field #VIPS_META_ORIENTATION is set
494 * to the value of the orientation tag. Applications may read and interpret
495 * this field
496 * as they wish later in processing. See vips_autorot(). Save
497 * operations will use #VIPS_META_ORIENTATION, if present, to set the
498 * orientation of output images.
499 *
500 * If @autorotate is TRUE, the image will be rotated upright during load and
501 * no metadata attached. This can be very slow.
502 *
503 * If @subifd is -1 (the default), the main image is selected for each page.
504 * If it is 0 or greater and there is a SUBIFD tag, the indexed SUBIFD is
505 * selected. This can be used to read lower resolution layers from
506 * bioformats-style image pyramids.
507 *
508 * Any ICC profile is read and attached to the VIPS image as
509 * #VIPS_META_ICC_NAME. Any XMP metadata is read and attached to the image
510 * as #VIPS_META_XMP_NAME. Any IPTC is attached as #VIPS_META_IPTC_NAME. The
511 * image description is
512 * attached as #VIPS_META_IMAGEDESCRIPTION. Data in the photoshop tag is
513 * attached as #VIPS_META_PHOTOSHOP_NAME.
514 *
515 * See also: vips_image_new_from_file(), vips_autorot().
516 *
517 * Returns: 0 on success, -1 on error.
518 */
519 int
vips_tiffload(const char * filename,VipsImage ** out,...)520 vips_tiffload( const char *filename, VipsImage **out, ... )
521 {
522 va_list ap;
523 int result;
524
525 va_start( ap, out );
526 result = vips_call_split( "tiffload", ap, filename, out );
527 va_end( ap );
528
529 return( result );
530 }
531
532 /**
533 * vips_tiffload_buffer:
534 * @buf: (array length=len) (element-type guint8): memory area to load
535 * @len: (type gsize): size of memory area
536 * @out: (out): image to write
537 * @...: %NULL-terminated list of optional named arguments
538 *
539 * Optional arguments:
540 *
541 * * @page: %gint, load this page
542 * * @n: %gint, load this many pages
543 * * @autorotate: %gboolean, use orientation tag to rotate the image
544 * during load
545 * * @subifd: %gint, select this subifd index
546 *
547 * Read a TIFF-formatted memory block into a VIPS image. Exactly as
548 * vips_tiffload(), but read from a memory source.
549 *
550 * You must not free the buffer while @out is active. The
551 * #VipsObject::postclose signal on @out is a good place to free.
552 *
553 * See also: vips_tiffload().
554 *
555 * Returns: 0 on success, -1 on error.
556 */
557 int
vips_tiffload_buffer(void * buf,size_t len,VipsImage ** out,...)558 vips_tiffload_buffer( void *buf, size_t len, VipsImage **out, ... )
559 {
560 va_list ap;
561 VipsBlob *blob;
562 int result;
563
564 /* We don't take a copy of the data or free it.
565 */
566 blob = vips_blob_new( NULL, buf, len );
567
568 va_start( ap, out );
569 result = vips_call_split( "tiffload_buffer", ap, blob, out );
570 va_end( ap );
571
572 vips_area_unref( VIPS_AREA( blob ) );
573
574 return( result );
575 }
576
577 /**
578 * vips_tiffload_source:
579 * @source: source to load
580 * @out: (out): image to write
581 * @...: %NULL-terminated list of optional named arguments
582 *
583 * Optional arguments:
584 *
585 * * @page: %gint, load this page
586 * * @n: %gint, load this many pages
587 * * @autorotate: %gboolean, use orientation tag to rotate the image
588 * during load
589 * * @subifd: %gint, select this subifd index
590 *
591 * Exactly as vips_tiffload(), but read from a source.
592 *
593 * See also: vips_tiffload().
594 *
595 * Returns: 0 on success, -1 on error.
596 */
597 int
vips_tiffload_source(VipsSource * source,VipsImage ** out,...)598 vips_tiffload_source( VipsSource *source, VipsImage **out, ... )
599 {
600 va_list ap;
601 int result;
602
603 va_start( ap, out );
604 result = vips_call_split( "tiffload_source", ap, source, out );
605 va_end( ap );
606
607 return( result );
608 }
609