1 /* foreign file formats base class
2 *
3 * 7/2/12
4 * - add support for sequential reads
5 * 18/6/12
6 * - flatten alpha with vips_flatten()
7 * 28/5/13
8 * - auto rshift down to 8 bits during save
9 * 19/1/14
10 * - pack and unpack rad to scrgb
11 * 18/8/14
12 * - fix conversion to 16-bit RGB, thanks John
13 * 18/6/15
14 * - forward progress signals from load
15 * 23/5/16
16 * - remove max-alpha stuff, this is now automatic
17 * 12/6/17
18 * - transform cmyk->rgb if there's an embedded profile
19 * 16/6/17
20 * - add page_height
21 * 1/1/18
22 * - META_SEQ support moved here
23 * 5/3/18
24 * - block _start if one start fails, see #893
25 * 1/4/18
26 * - drop incompatible ICC profiles before save
27 * 24/7/21
28 * - add fail-on
29 */
30
31 /*
32
33 This file is part of VIPS.
34
35 VIPS is free software; you can redistribute it and/or modify
36 it under the terms of the GNU Lesser General Public License as published by
37 the Free Software Foundation; either version 2 of the License, or
38 (at your option) any later version.
39
40 This program is distributed in the hope that it will be useful,
41 but WITHOUT ANY WARRANTY; without even the implied warranty of
42 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 GNU Lesser General Public License for more details.
44
45 You should have received a copy of the GNU Lesser General Public License
46 along with this program; if not, write to the Free Software
47 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
48 02110-1301 USA
49
50 */
51
52 /*
53
54 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
55
56 */
57
58 /*
59 #define DEBUG
60 */
61
62 #ifdef HAVE_CONFIG_H
63 #include <config.h>
64 #endif /*HAVE_CONFIG_H*/
65 #include <vips/intl.h>
66
67 #include <stdio.h>
68 #include <stdlib.h>
69
70 #include <vips/vips.h>
71 #include <vips/internal.h>
72 #include <vips/debug.h>
73
74 #include "pforeign.h"
75
76 /**
77 * SECTION: foreign
78 * @short_description: load and save images in a variety of formats
79 * @stability: Stable
80 * @see_also: <link linkend="libvips-image">image</link>
81 * @include: vips/vips.h
82 * @title: VipsForeign
83 *
84 * This set of operations load and save images in a variety of formats.
85 *
86 * The operations share a base class that offers a simple way to search for a
87 * subclass of #VipsForeign which can load a certain file (see
88 * vips_foreign_find_load()) or buffer (see vips_foreign_find_load_buffer()),
89 * or which could be used to save an image to a
90 * certain file type (see vips_foreign_find_save() and
91 * vips_foreign_find_save_buffer()). You can then run these
92 * operations using vips_call() and friends to perform the load or save.
93 *
94 * vips_image_write_to_file() and vips_image_new_from_file() and friends use
95 * these functions to automate file load and save.
96 *
97 * You can also invoke the operations directly, for example:
98 *
99 * |[
100 * vips_tiffsave (my_image, "frank.anything",
101 * "compression", VIPS_FOREIGN_TIFF_COMPRESSION_JPEG,
102 * NULL);
103 * ]|
104 *
105 * To add support for a new file format to vips, simply define a new subclass
106 * of #VipsForeignLoad or #VipsForeignSave.
107 *
108 * If you define a new operation which is a subclass of #VipsForeign, support
109 * for it automatically appears in all VIPS user-interfaces. It will also be
110 * transparently supported by vips_image_new_from_file() and friends.
111 *
112 * VIPS comes with VipsForeign for TIFF, JPEG, PNG, Analyze, PPM, OpenEXR, CSV,
113 * Matlab, Radiance, RAW, FITS, WebP, SVG, PDF, GIF and VIPS. It also includes
114 * import filters which can load with libMagick and with OpenSlide.
115 *
116 * ## Writing a new loader
117 *
118 * Add a new loader to VIPS by subclassing #VipsForeignLoad. Subclasses need to
119 * implement at least @header().
120 *
121 * @header() must set at least the header fields of @out. @load(), if defined,
122 * must load the pixels to @real.
123 *
124 * The suffix list is used to select a format to save a file in, and to pick a
125 * loader if you don't define is_a().
126 *
127 * You should also define @nickname and @description in #VipsObject.
128 *
129 * As a complete example, here's code for a PNG loader, minus the actual
130 * calls to libpng.
131 *
132 * |[
133 * typedef struct _VipsForeignLoadPng {
134 * VipsForeignLoad parent_object;
135 *
136 * char *filename;
137 * } VipsForeignLoadPng;
138 *
139 * typedef VipsForeignLoadClass VipsForeignLoadPngClass;
140 *
141 * G_DEFINE_TYPE( VipsForeignLoadPng, vips_foreign_load_png,
142 * VIPS_TYPE_FOREIGN_LOAD );
143 *
144 * static VipsForeignFlags
145 * vips_foreign_load_png_get_flags_filename( const char *filename )
146 * {
147 * VipsForeignFlags flags;
148 *
149 * flags = 0;
150 * if( vips__png_isinterlaced( filename ) )
151 * flags = VIPS_FOREIGN_PARTIAL;
152 * else
153 * flags = VIPS_FOREIGN_SEQUENTIAL;
154 *
155 * return( flags );
156 * }
157 *
158 * static VipsForeignFlags
159 * vips_foreign_load_png_get_flags( VipsForeignLoad *load )
160 * {
161 * VipsForeignLoadPng *png = (VipsForeignLoadPng *) load;
162 *
163 * return( vips_foreign_load_png_get_flags_filename( png->filename ) );
164 * }
165 *
166 * static int
167 * vips_foreign_load_png_header( VipsForeignLoad *load )
168 * {
169 * VipsForeignLoadPng *png = (VipsForeignLoadPng *) load;
170 *
171 * if( vips__png_header( png->filename, load->out ) )
172 * return( -1 );
173 *
174 * return( 0 );
175 * }
176 *
177 * static int
178 * vips_foreign_load_png_load( VipsForeignLoad *load )
179 * {
180 * VipsForeignLoadPng *png = (VipsForeignLoadPng *) load;
181 *
182 * if( vips__png_read( png->filename, load->real ) )
183 * return( -1 );
184 *
185 * return( 0 );
186 * }
187 *
188 * static void
189 * vips_foreign_load_png_class_init( VipsForeignLoadPngClass *class )
190 * {
191 * GObjectClass *gobject_class = G_OBJECT_CLASS( class );
192 * VipsObjectClass *object_class = (VipsObjectClass *) class;
193 * VipsForeignClass *foreign_class = (VipsForeignClass *) class;
194 * VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class;
195 *
196 * gobject_class->set_property = vips_object_set_property;
197 * gobject_class->get_property = vips_object_get_property;
198 *
199 * object_class->nickname = "pngload";
200 * object_class->description = _( "load png from file" );
201 *
202 * foreign_class->suffs = vips__png_suffs;
203 *
204 * load_class->is_a = vips__png_ispng;
205 * load_class->get_flags_filename =
206 * vips_foreign_load_png_get_flags_filename;
207 * load_class->get_flags = vips_foreign_load_png_get_flags;
208 * load_class->header = vips_foreign_load_png_header;
209 * load_class->load = vips_foreign_load_png_load;
210 *
211 * VIPS_ARG_STRING( class, "filename", 1,
212 * _( "Filename" ),
213 * _( "Filename to load from" ),
214 * VIPS_ARGUMENT_REQUIRED_INPUT,
215 * G_STRUCT_OFFSET( VipsForeignLoadPng, filename ),
216 * NULL );
217 * }
218 *
219 * static void
220 * vips_foreign_load_png_init( VipsForeignLoadPng *png )
221 * {
222 * }
223 * ]|
224 *
225 * ## Writing a new saver
226 *
227 * Call your saver in the class' @build() method after chaining up. The
228 * prepared image should be ready for you to save in @ready.
229 *
230 * As a complete example, here's the code for the CSV saver, minus the calls
231 * to the actual save routines.
232 *
233 * |[
234 * typedef struct _VipsForeignSaveCsv {
235 * VipsForeignSave parent_object;
236 *
237 * char *filename;
238 * const char *separator;
239 * } VipsForeignSaveCsv;
240 *
241 * typedef VipsForeignSaveClass VipsForeignSaveCsvClass;
242 *
243 * G_DEFINE_TYPE( VipsForeignSaveCsv, vips_foreign_save_csv,
244 * VIPS_TYPE_FOREIGN_SAVE );
245 *
246 * static int
247 * vips_foreign_save_csv_build( VipsObject *object )
248 * {
249 * VipsForeignSave *save = (VipsForeignSave *) object;
250 * VipsForeignSaveCsv *csv = (VipsForeignSaveCsv *) object;
251 *
252 * if( VIPS_OBJECT_CLASS( vips_foreign_save_csv_parent_class )->
253 * build( object ) )
254 * return( -1 );
255 *
256 * if( vips__csv_write( save->ready, csv->filename, csv->separator ) )
257 * return( -1 );
258 *
259 * return( 0 );
260 * }
261 *
262 * static void
263 * vips_foreign_save_csv_class_init( VipsForeignSaveCsvClass *class )
264 * {
265 * GObjectClass *gobject_class = G_OBJECT_CLASS( class );
266 * VipsObjectClass *object_class = (VipsObjectClass *) class;
267 * VipsForeignClass *foreign_class = (VipsForeignClass *) class;
268 * VipsForeignSaveClass *save_class = (VipsForeignSaveClass *) class;
269 *
270 * gobject_class->set_property = vips_object_set_property;
271 * gobject_class->get_property = vips_object_get_property;
272 *
273 * object_class->nickname = "csvsave";
274 * object_class->description = _( "save image to csv file" );
275 * object_class->build = vips_foreign_save_csv_build;
276 *
277 * foreign_class->suffs = vips__foreign_csv_suffs;
278 *
279 * save_class->saveable = VIPS_SAVEABLE_MONO;
280 * // no need to define ->format_table, we don't want the input
281 * // cast for us
282 *
283 * VIPS_ARG_STRING( class, "filename", 1,
284 * _( "Filename" ),
285 * _( "Filename to save to" ),
286 * VIPS_ARGUMENT_REQUIRED_INPUT,
287 * G_STRUCT_OFFSET( VipsForeignSaveCsv, filename ),
288 * NULL );
289 *
290 * VIPS_ARG_STRING( class, "separator", 13,
291 * _( "Separator" ),
292 * _( "Separator characters" ),
293 * VIPS_ARGUMENT_OPTIONAL_INPUT,
294 * G_STRUCT_OFFSET( VipsForeignSaveCsv, separator ),
295 * "\t" );
296 * }
297 *
298 * static void
299 * vips_foreign_save_csv_init( VipsForeignSaveCsv *csv )
300 * {
301 * csv->separator = g_strdup( "\t" );
302 * }
303 * ]|
304 */
305
306 /* Use this to link images to the load operation that made them.
307 */
308 static GQuark vips__foreign_load_operation = 0;
309
310 /**
311 * VipsForeignFlags:
312 * @VIPS_FOREIGN_NONE: no flags set
313 * @VIPS_FOREIGN_PARTIAL: the image may be read lazilly
314 * @VIPS_FOREIGN_BIGENDIAN: image pixels are most-significant byte first
315 * @VIPS_FOREIGN_SEQUENTIAL: top-to-bottom lazy reading
316 *
317 * Some hints about the image loader.
318 *
319 * #VIPS_FOREIGN_PARTIAL means that the image can be read directly from the
320 * file without needing to be unpacked to a temporary image first.
321 *
322 * #VIPS_FOREIGN_SEQUENTIAL means that the loader supports lazy reading, but
323 * only top-to-bottom (sequential) access. Formats like PNG can read sets of
324 * scanlines, for example, but only in order.
325 *
326 * If neither PARTIAL or SEQUENTIAL is set, the loader only supports whole
327 * image read. Setting both PARTIAL and SEQUENTIAL is an error.
328 *
329 * #VIPS_FOREIGN_BIGENDIAN means that image pixels are most-significant byte
330 * first. Depending on the native byte order of the host machine, you may
331 * need to swap bytes. See vips_copy().
332 */
333
334 G_DEFINE_ABSTRACT_TYPE( VipsForeign, vips_foreign, VIPS_TYPE_OPERATION );
335
336 static void
vips_foreign_summary_class(VipsObjectClass * object_class,VipsBuf * buf)337 vips_foreign_summary_class( VipsObjectClass *object_class, VipsBuf *buf )
338 {
339 VipsForeignClass *class = VIPS_FOREIGN_CLASS( object_class );
340
341 VIPS_OBJECT_CLASS( vips_foreign_parent_class )->
342 summary_class( object_class, buf );
343
344 if( class->suffs ) {
345 const char **p;
346
347 vips_buf_appends( buf, " (" );
348 for( p = class->suffs; *p; p++ ) {
349 vips_buf_appendf( buf, "%s", *p );
350 if( p[1] )
351 vips_buf_appends( buf, ", " );
352 }
353 vips_buf_appends( buf, ")" );
354 }
355
356 vips_buf_appendf( buf, ", priority=%d", class->priority );
357
358 }
359
360 static void
vips_foreign_class_init(VipsForeignClass * class)361 vips_foreign_class_init( VipsForeignClass *class )
362 {
363 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
364 VipsObjectClass *object_class = (VipsObjectClass *) class;
365
366 gobject_class->set_property = vips_object_set_property;
367 gobject_class->get_property = vips_object_get_property;
368
369 object_class->nickname = "foreign";
370 object_class->description = _( "load and save image files" );
371 object_class->summary_class = vips_foreign_summary_class;
372 }
373
374 static void
vips_foreign_init(VipsForeign * object)375 vips_foreign_init( VipsForeign *object )
376 {
377 }
378
379 /* To iterate over supported files we build a temp list of subclasses of
380 * VipsForeign, sort by priority, iterate, and free.
381 */
382
383 static void *
file_add_class(VipsForeignClass * class,GSList ** files)384 file_add_class( VipsForeignClass *class, GSList **files )
385 {
386 /* We exclude "rawload" as it has a different API.
387 */
388 if( !vips_isprefix( "rawload", VIPS_OBJECT_CLASS( class )->nickname ) )
389 /* Append so we don't reverse the list of files. Sort will
390 * not reorder items of equal priority.
391 */
392 *files = g_slist_append( *files, class );
393
394 return( NULL );
395 }
396
397 static gint
file_compare(VipsForeignClass * a,VipsForeignClass * b,void * user_data)398 file_compare( VipsForeignClass *a, VipsForeignClass *b, void *user_data )
399 {
400 return( b->priority - a->priority );
401 }
402
403 /**
404 * vips_foreign_map:
405 * @base: base class to search below (eg. "VipsForeignLoad")
406 * @fn: (scope call): function to apply to each #VipsForeignClass
407 * @a: user data
408 * @b: user data
409 *
410 * Apply a function to every #VipsForeignClass that VIPS knows about. Foreigns
411 * are presented to the function in priority order.
412 *
413 * Like all VIPS map functions, if @fn returns %NULL, iteration continues. If
414 * it returns non-%NULL, iteration terminates and that value is returned. The
415 * map function returns %NULL if all calls return %NULL.
416 *
417 * See also: vips_slist_map().
418 *
419 * Returns: (transfer none): the result of iteration
420 */
421 void *
vips_foreign_map(const char * base,VipsSListMap2Fn fn,void * a,void * b)422 vips_foreign_map( const char *base, VipsSListMap2Fn fn, void *a, void *b )
423 {
424 GSList *files;
425 void *result;
426
427 files = NULL;
428 (void) vips_class_map_all( g_type_from_name( base ),
429 (VipsClassMapFn) file_add_class, (void *) &files );
430
431 files = g_slist_sort( files, (GCompareFunc) file_compare );
432 #ifdef DEBUG
433 {
434 GSList *p;
435
436 printf( "vips_foreign_map: search order\n" );
437 for( p = files; p; p = p->next ) {
438 VipsForeignClass *class = (VipsForeignClass *) p->data;
439
440 printf( "\t%s\n", VIPS_OBJECT_CLASS( class )->nickname );
441 }
442 }
443 #endif /*DEBUG*/
444 result = vips_slist_map2( files, fn, a, b );
445
446 g_slist_free( files );
447
448 return( result );
449 }
450
451 /* Abstract base class for image load.
452 */
453
454 G_DEFINE_ABSTRACT_TYPE( VipsForeignLoad, vips_foreign_load, VIPS_TYPE_FOREIGN );
455
456 static void
vips_foreign_load_dispose(GObject * gobject)457 vips_foreign_load_dispose( GObject *gobject )
458 {
459 VipsForeignLoad *load = VIPS_FOREIGN_LOAD( gobject );
460
461 VIPS_UNREF( load->real );
462
463 G_OBJECT_CLASS( vips_foreign_load_parent_class )->dispose( gobject );
464 }
465
466 static void
vips_foreign_load_summary_class(VipsObjectClass * object_class,VipsBuf * buf)467 vips_foreign_load_summary_class( VipsObjectClass *object_class, VipsBuf *buf )
468 {
469 VipsForeignLoadClass *class = VIPS_FOREIGN_LOAD_CLASS( object_class );
470
471 VIPS_OBJECT_CLASS( vips_foreign_load_parent_class )->
472 summary_class( object_class, buf );
473
474 if( !G_TYPE_IS_ABSTRACT( G_TYPE_FROM_CLASS( class ) ) ) {
475 if( class->is_a )
476 vips_buf_appends( buf, ", is_a" );
477 if( class->is_a_buffer )
478 vips_buf_appends( buf, ", is_a_buffer" );
479 if( class->is_a_source )
480 vips_buf_appends( buf, ", is_a_source" );
481 if( class->get_flags )
482 vips_buf_appends( buf, ", get_flags" );
483 if( class->get_flags_filename )
484 vips_buf_appends( buf, ", get_flags_filename" );
485 if( class->header )
486 vips_buf_appends( buf, ", header" );
487 if( class->load )
488 vips_buf_appends( buf, ", load" );
489
490 /* You can omit ->load(), you must not omit ->header().
491 */
492 g_assert( class->header );
493 }
494 }
495
496 /* Can this VipsForeign open this file?
497 */
498 static void *
vips_foreign_find_load_sub(VipsForeignLoadClass * load_class,const char * filename,void * b)499 vips_foreign_find_load_sub( VipsForeignLoadClass *load_class,
500 const char *filename, void *b )
501 {
502 VipsObjectClass *object_class = VIPS_OBJECT_CLASS( load_class );
503 VipsForeignClass *class = VIPS_FOREIGN_CLASS( load_class );
504
505 /* Ignore the buffer and source loaders.
506 */
507 if( vips_ispostfix( object_class->nickname, "_buffer" ) ||
508 vips_ispostfix( object_class->nickname, "_source" ) )
509 return( NULL );
510
511 #ifdef DEBUG
512 printf( "vips_foreign_find_load_sub: %s\n",
513 VIPS_OBJECT_CLASS( class )->nickname );
514 #endif /*DEBUG*/
515
516 /* Try to sniff the filetype from the first few bytes, if we can,
517 * otherwise fall back to checking the filename suffix.
518 */
519 if( load_class->is_a ) {
520 if( load_class->is_a( filename ) )
521 return( load_class );
522
523 #ifdef DEBUG
524 printf( "vips_foreign_find_load_sub: is_a failed\n" );
525 #endif /*DEBUG*/
526 }
527 else if( class->suffs ) {
528 if( vips_filename_suffix_match( filename, class->suffs ) )
529 return( load_class );
530 }
531 else
532 g_warning( "loader %s has no is_a method and no suffix list",
533 object_class->nickname );
534
535 return( NULL );
536 }
537
538 /**
539 * vips_foreign_find_load:
540 * @filename: file to find a loader for
541 *
542 * Searches for an operation you could use to load @filename. Any trailing
543 * options on @filename are stripped and ignored.
544 *
545 * See also: vips_foreign_find_load_buffer(), vips_image_new_from_file().
546 *
547 * Returns: the name of an operation on success, %NULL on error
548 */
549 const char *
vips_foreign_find_load(const char * name)550 vips_foreign_find_load( const char *name )
551 {
552 char filename[VIPS_PATH_MAX];
553 char option_string[VIPS_PATH_MAX];
554 VipsForeignLoadClass *load_class;
555
556 vips__filename_split8( name, filename, option_string );
557
558 /* Very common, so make a better error message for this case.
559 */
560 if( !vips_existsf( "%s", filename ) ) {
561 vips_error( "VipsForeignLoad",
562 _( "file \"%s\" does not exist" ), name );
563 return( NULL );
564 }
565 if( vips_isdirf( "%s", filename ) ) {
566 vips_error( "VipsForeignLoad",
567 _( "\"%s\" is a directory" ), name );
568 return( NULL );
569 }
570
571 if( !(load_class = (VipsForeignLoadClass *) vips_foreign_map(
572 "VipsForeignLoad",
573 (VipsSListMap2Fn) vips_foreign_find_load_sub,
574 (void *) filename, NULL )) ) {
575 vips_error( "VipsForeignLoad",
576 _( "\"%s\" is not a known file format" ), name );
577 return( NULL );
578 }
579
580 #ifdef DEBUG
581 printf( "vips_foreign_find_load: selected %s\n",
582 VIPS_OBJECT_CLASS( load_class )->nickname );
583 #endif /*DEBUG*/
584
585 return( G_OBJECT_CLASS_NAME( load_class ) );
586 }
587
588 /* Kept for compat with earlier version of the vip8 API. Use
589 * vips_image_new_from_file() now.
590 */
591
592 int
vips_foreign_load(const char * name,VipsImage ** out,...)593 vips_foreign_load( const char *name, VipsImage **out, ... )
594 {
595 char filename[VIPS_PATH_MAX];
596 char option_string[VIPS_PATH_MAX];
597 const char *operation_name;
598 va_list ap;
599 int result;
600
601 vips__filename_split8( name, filename, option_string );
602 if( !(operation_name = vips_foreign_find_load( filename )) )
603 return( -1 );
604
605 va_start( ap, out );
606 result = vips_call_split_option_string( operation_name, option_string,
607 ap, filename, out );
608 va_end( ap );
609
610 return( result );
611 }
612
613 /* Can this VipsForeign open this buffer?
614 */
615 static void *
vips_foreign_find_load_buffer_sub(VipsForeignLoadClass * load_class,const void ** buf,size_t * len)616 vips_foreign_find_load_buffer_sub( VipsForeignLoadClass *load_class,
617 const void **buf, size_t *len )
618 {
619 VipsObjectClass *object_class = VIPS_OBJECT_CLASS( load_class );
620
621 /* Skip non-buffer loaders.
622 */
623 if( !vips_ispostfix( object_class->nickname, "_buffer" ) )
624 return( NULL );
625
626 if( load_class->is_a_buffer ) {
627 if( load_class->is_a_buffer( *buf, *len ) )
628 return( load_class );
629 }
630 else
631 g_warning( "loader %s has no is_a_buffer method",
632 object_class->nickname );
633
634 return( NULL );
635 }
636
637 /**
638 * vips_foreign_find_load_buffer:
639 * @data: (array length=size) (element-type guint8) (transfer none): start of
640 * memory buffer
641 * @size: (type gsize): number of bytes in @data
642 *
643 * Searches for an operation you could use to load a memory buffer. To see the
644 * range of buffer loaders supported by your vips, try something like:
645 *
646 * vips -l | grep load_buffer
647 *
648 * See also: vips_image_new_from_buffer().
649 *
650 * Returns: (transfer none): the name of an operation on success, %NULL on
651 * error.
652 */
653 const char *
vips_foreign_find_load_buffer(const void * data,size_t size)654 vips_foreign_find_load_buffer( const void *data, size_t size )
655 {
656 VipsForeignLoadClass *load_class;
657
658 if( !(load_class = (VipsForeignLoadClass *) vips_foreign_map(
659 "VipsForeignLoad",
660 (VipsSListMap2Fn) vips_foreign_find_load_buffer_sub,
661 &data, &size )) ) {
662 vips_error( "VipsForeignLoad",
663 "%s", _( "buffer is not in a known format" ) );
664 return( NULL );
665 }
666
667 return( G_OBJECT_CLASS_NAME( load_class ) );
668 }
669
670 /* Can this VipsForeign open this source?
671 */
672 static void *
vips_foreign_find_load_source_sub(void * item,void * a,void * b)673 vips_foreign_find_load_source_sub( void *item, void *a, void *b )
674 {
675 VipsObjectClass *object_class = VIPS_OBJECT_CLASS( item );
676 VipsForeignLoadClass *load_class = VIPS_FOREIGN_LOAD_CLASS( item );
677 VipsSource *source = VIPS_SOURCE( a );
678
679 /* Skip non-source loaders.
680 */
681 if( !vips_ispostfix( object_class->nickname, "_source" ) )
682 return( NULL );
683
684 if( load_class->is_a_source ) {
685 /* We may have done a _read() rather than a _sniff() in one of
686 * the is_a testers. Always rewind.
687 */
688 (void) vips_source_rewind( source );
689
690 if( load_class->is_a_source( source ) )
691 return( load_class );
692 }
693 else
694 g_warning( "loader %s has no is_a_source method",
695 object_class->nickname );
696
697 return( NULL );
698 }
699
700 /**
701 * vips_foreign_find_load_source:
702 * @source: source to load from
703 *
704 * Searches for an operation you could use to load a source. To see the
705 * range of source loaders supported by your vips, try something like:
706 *
707 * vips -l | grep load_source
708 *
709 * See also: vips_image_new_from_source().
710 *
711 * Returns: (transfer none): the name of an operation on success, %NULL on
712 * error.
713 */
714 const char *
vips_foreign_find_load_source(VipsSource * source)715 vips_foreign_find_load_source( VipsSource *source )
716 {
717 VipsForeignLoadClass *load_class;
718
719 if( !(load_class = (VipsForeignLoadClass *) vips_foreign_map(
720 "VipsForeignLoad",
721 vips_foreign_find_load_source_sub,
722 source, NULL )) ) {
723 vips_error( "VipsForeignLoad",
724 "%s", _( "source is not in a known format" ) );
725 return( NULL );
726 }
727
728 /* All source loaders should be NOCACHE.
729 */
730 g_assert( VIPS_OPERATION_CLASS( load_class )->flags &
731 VIPS_OPERATION_NOCACHE );
732
733 return( G_OBJECT_CLASS_NAME( load_class ) );
734 }
735
736 /**
737 * vips_foreign_is_a:
738 * @loader: name of loader to use for test
739 * @filename: file to test
740 *
741 * Return %TRUE if @filename can be loaded by @loader. @loader is something
742 * like "tiffload" or "VipsForeignLoadTiff".
743 *
744 * Returns: %TRUE if @filename can be loaded by @loader.
745 */
746 gboolean
vips_foreign_is_a(const char * loader,const char * filename)747 vips_foreign_is_a( const char *loader, const char *filename )
748 {
749 const VipsObjectClass *class;
750 VipsForeignLoadClass *load_class;
751
752 if( !(class = vips_class_find( "VipsForeignLoad", loader )) )
753 return( FALSE );
754 load_class = VIPS_FOREIGN_LOAD_CLASS( class );
755 if( load_class->is_a &&
756 load_class->is_a( filename ) )
757 return( TRUE );
758
759 return( FALSE );
760 }
761
762 /**
763 * vips_foreign_is_a_buffer:
764 * @loader: name of loader to use for test
765 * @data: (array length=size) (element-type guint8): pointer to the buffer to test
766 * @size: (type gsize): size of the buffer to test
767 *
768 * Return %TRUE if @data can be loaded by @loader. @loader is something
769 * like "tiffload_buffer" or "VipsForeignLoadTiffBuffer".
770 *
771 * Returns: %TRUE if @data can be loaded by @loader.
772 */
773 gboolean
vips_foreign_is_a_buffer(const char * loader,const void * data,size_t size)774 vips_foreign_is_a_buffer( const char *loader, const void *data, size_t size )
775 {
776 const VipsObjectClass *class;
777 VipsForeignLoadClass *load_class;
778
779 if( !(class = vips_class_find( "VipsForeignLoad", loader )) )
780 return( FALSE );
781 load_class = VIPS_FOREIGN_LOAD_CLASS( class );
782 if( load_class->is_a_buffer &&
783 load_class->is_a_buffer( data, size ) )
784 return( TRUE );
785
786 return( FALSE );
787 }
788
789 /**
790 * vips_foreign_is_a_source:
791 * @loader: name of loader to use for test
792 * @source: source to test
793 *
794 * Return %TRUE if @source can be loaded by @loader. @loader is something
795 * like "tiffload_source" or "VipsForeignLoadTiffSource".
796 *
797 * Returns: %TRUE if @data can be loaded by @source.
798 */
799 gboolean
vips_foreign_is_a_source(const char * loader,VipsSource * source)800 vips_foreign_is_a_source( const char *loader, VipsSource *source )
801 {
802 const VipsObjectClass *class;
803 VipsForeignLoadClass *load_class;
804
805 if( !(class = vips_class_find( "VipsForeignLoad", loader )) )
806 return( FALSE );
807 load_class = VIPS_FOREIGN_LOAD_CLASS( class );
808 if( load_class->is_a_source &&
809 load_class->is_a_source( source ) )
810 return( TRUE );
811
812 return( FALSE );
813 }
814
815 /**
816 * vips_foreign_flags:
817 * @loader: name of loader to use for test
818 * @filename: file to test
819 *
820 * Return the flags for @filename using @loader.
821 * @loader is something like "tiffload" or "VipsForeignLoadTiff".
822 *
823 * Returns: the flags for @filename.
824 */
825 VipsForeignFlags
vips_foreign_flags(const char * loader,const char * filename)826 vips_foreign_flags( const char *loader, const char *filename )
827 {
828 const VipsObjectClass *class;
829
830 if( (class = vips_class_find( "VipsForeignLoad", loader )) ) {
831 VipsForeignLoadClass *load_class =
832 VIPS_FOREIGN_LOAD_CLASS( class );
833
834 if( load_class->get_flags_filename )
835 return( load_class->get_flags_filename( filename ) );
836 }
837
838 return( 0 );
839 }
840
841 static VipsObject *
vips_foreign_load_new_from_string(const char * string)842 vips_foreign_load_new_from_string( const char *string )
843 {
844 const char *file_op;
845 GType type;
846 VipsForeignLoad *load;
847
848 if( !(file_op = vips_foreign_find_load( string )) )
849 return( NULL );
850 type = g_type_from_name( file_op );
851 g_assert( type );
852
853 load = VIPS_FOREIGN_LOAD( g_object_new( type, NULL ) );
854 g_object_set( load,
855 "filename", string,
856 NULL );
857
858 return( VIPS_OBJECT( load ) );
859 }
860
861 static VipsImage *
vips_foreign_load_temp(VipsForeignLoad * load)862 vips_foreign_load_temp( VipsForeignLoad *load )
863 {
864 const guint64 disc_threshold = vips_get_disc_threshold();
865 const guint64 image_size = VIPS_IMAGE_SIZEOF_IMAGE( load->out );
866
867 /* ->memory used to be called ->disc and default TRUE. If it's been
868 * forced FALSE, set memory TRUE.
869 */
870 if( !load->disc )
871 load->memory = TRUE;
872
873 if( load->memory ) {
874 #ifdef DEBUG
875 printf( "vips_foreign_load_temp: forced memory temp\n" );
876 #endif /*DEBUG*/
877
878 return( vips_image_new_memory() );
879 }
880
881 /* If this is a partial operation, we can open directly.
882 */
883 if( load->flags & VIPS_FOREIGN_PARTIAL ) {
884 #ifdef DEBUG
885 printf( "vips_foreign_load_temp: partial temp\n" );
886 #endif /*DEBUG*/
887
888 return( vips_image_new() );
889 }
890
891 /* If it can do sequential access and it's been requested, we can open
892 * directly.
893 */
894 if( (load->flags & VIPS_FOREIGN_SEQUENTIAL) &&
895 load->access != VIPS_ACCESS_RANDOM ) {
896 #ifdef DEBUG
897 printf( "vips_foreign_load_temp: partial sequential temp\n" );
898 #endif /*DEBUG*/
899
900 return( vips_image_new() );
901 }
902
903 /* We open via disc if the uncompressed image will be larger than
904 * vips_get_disc_threshold()
905 */
906 if( image_size > disc_threshold ) {
907 #ifdef DEBUG
908 printf( "vips_foreign_load_temp: disc temp\n" );
909 #endif /*DEBUG*/
910
911 return( vips_image_new_temp_file( "%s.v" ) );
912 }
913
914 #ifdef DEBUG
915 printf( "vips_foreign_load_temp: fallback memory temp\n" );
916 #endif /*DEBUG*/
917
918 /* Otherwise, fall back to a memory buffer.
919 */
920 return( vips_image_new_memory() );
921
922 }
923
924 /* Check two images for compatibility: their geometries need to match.
925 */
926 static gboolean
vips_foreign_load_iscompat(VipsImage * a,VipsImage * b)927 vips_foreign_load_iscompat( VipsImage *a, VipsImage *b )
928 {
929 if( a->Xsize != b->Xsize ||
930 a->Ysize != b->Ysize ||
931 a->Bands != b->Bands ||
932 a->Coding != b->Coding ||
933 a->BandFmt != b->BandFmt ) {
934 vips_error( "VipsForeignLoad",
935 "%s", _( "images do not match" ) );
936 return( FALSE );
937 }
938
939 return( TRUE );
940 }
941
942 /* Our start function ... do the lazy open, if necessary, and return a region
943 * on the new image.
944 */
945 static void *
vips_foreign_load_start(VipsImage * out,void * a,void * b)946 vips_foreign_load_start( VipsImage *out, void *a, void *b )
947 {
948 VipsForeignLoad *load = VIPS_FOREIGN_LOAD( b );
949 VipsForeignLoadClass *class = VIPS_FOREIGN_LOAD_GET_CLASS( load );
950
951 /* If this start has failed before in another thread, we can fail now.
952 */
953 if( load->error )
954 return( NULL );
955
956 if( !load->real ) {
957 if( !(load->real = vips_foreign_load_temp( load )) )
958 return( NULL );
959
960 #ifdef DEBUG
961 printf( "vips_foreign_load_start: triggering ->load()\n" );
962 #endif /*DEBUG*/
963
964 /* Read the image in. This may involve a long computation and
965 * will finish with load->real holding the decompressed image.
966 *
967 * We want our caller to be able to see this computation on
968 * @out, so eval signals on ->real need to appear on ->out.
969 */
970 load->real->progress_signal = load->out;
971
972 /* Note the load object on the image. Loaders can use
973 * this to signal invalidate if they hit a load error. See
974 * vips_foreign_load_invalidate() below.
975 */
976 g_object_set_qdata( G_OBJECT( load->real ),
977 vips__foreign_load_operation, load );
978
979 /* Load the image and check the result.
980 *
981 * ->header() read the header into @out, load will read the
982 * image into @real. They must match exactly in size, bands,
983 * format and coding for the copy to work.
984 *
985 * Some versions of ImageMagick give different results between
986 * Ping and Load for some formats, for example.
987 *
988 * If the load fails, we need to stop
989 */
990 if( class->load( load ) ||
991 vips_image_pio_input( load->real ) ||
992 !vips_foreign_load_iscompat( load->real, out ) ) {
993 vips_operation_invalidate( VIPS_OPERATION( load ) );
994 load->error = TRUE;
995
996 return( NULL );
997 }
998
999 /* We have to tell vips that out depends on real. We've set
1000 * the demand hint below, but not given an input there.
1001 */
1002 if( vips_image_pipelinev( load->out, load->out->dhint,
1003 load->real, NULL ) )
1004 return( NULL );
1005 }
1006
1007 return( vips_region_new( load->real ) );
1008 }
1009
1010 /* Just pointer-copy.
1011 */
1012 static int
vips_foreign_load_generate(VipsRegion * or,void * seq,void * a,void * b,gboolean * stop)1013 vips_foreign_load_generate( VipsRegion *or,
1014 void *seq, void *a, void *b, gboolean *stop )
1015 {
1016 VipsRegion *ir = (VipsRegion *) seq;
1017
1018 VipsRect *r = &or->valid;
1019
1020 /* Ask for input we need.
1021 */
1022 if( vips_region_prepare( ir, r ) )
1023 return( -1 );
1024
1025 /* Attach output region to that.
1026 */
1027 if( vips_region_region( or, ir, r, r->left, r->top ) )
1028 return( -1 );
1029
1030 return( 0 );
1031 }
1032
1033 static int
vips_foreign_load_build(VipsObject * object)1034 vips_foreign_load_build( VipsObject *object )
1035 {
1036 VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object );
1037 VipsForeignLoad *load = VIPS_FOREIGN_LOAD( object );
1038 VipsForeignLoadClass *fclass = VIPS_FOREIGN_LOAD_GET_CLASS( object );
1039
1040 VipsForeignFlags flags;
1041 gboolean sequential;
1042
1043 #ifdef DEBUG
1044 printf( "vips_foreign_load_build:\n" );
1045 #endif /*DEBUG*/
1046
1047 flags = 0;
1048 if( fclass->get_flags )
1049 flags |= fclass->get_flags( load );
1050
1051 if( (flags & VIPS_FOREIGN_PARTIAL) &&
1052 (flags & VIPS_FOREIGN_SEQUENTIAL) ) {
1053 g_warning( "%s",
1054 _( "VIPS_FOREIGN_PARTIAL and VIPS_FOREIGN_SEQUENTIAL "
1055 "both set -- using SEQUENTIAL" ) );
1056 flags ^= VIPS_FOREIGN_PARTIAL;
1057 }
1058
1059 g_object_set( load, "flags", flags, NULL );
1060
1061 /* Seq access has been requested and the loader supports seq.
1062 */
1063 sequential = (load->flags & VIPS_FOREIGN_SEQUENTIAL) &&
1064 load->access != VIPS_ACCESS_RANDOM;
1065
1066 /* We must block caching of seq loads.
1067 */
1068 if( sequential )
1069 load->nocache = TRUE;
1070
1071 /* The deprecated "fail" field sets fail_on warning.
1072 */
1073 if( vips_object_argument_isset( object, "fail" ) &&
1074 !vips_object_argument_isset( object, "fail_on" ) )
1075 load->fail_on = load->fail ?
1076 VIPS_FAIL_ON_WARNING : VIPS_FAIL_ON_NONE;
1077
1078 if( VIPS_OBJECT_CLASS( vips_foreign_load_parent_class )->
1079 build( object ) )
1080 return( -1 );
1081
1082 if( load->sequential )
1083 g_warning( "%s",
1084 _( "ignoring deprecated \"sequential\" mode -- "
1085 "please use \"access\" instead" ) );
1086
1087 g_object_set( object, "out", vips_image_new(), NULL );
1088
1089 vips_image_set_string( load->out,
1090 VIPS_META_LOADER, class->nickname );
1091
1092 #ifdef DEBUG
1093 printf( "vips_foreign_load_build: triggering ->header()\n" );
1094 #endif /*DEBUG*/
1095
1096 /* Read the header into @out.
1097 */
1098 if( fclass->header &&
1099 fclass->header( load ) )
1100 return( -1 );
1101
1102 /* If there's no ->load() method then the header read has done
1103 * everything. Otherwise, it's just set fields and we must also
1104 * load pixels.
1105 *
1106 * Delay the load until the first pixel is requested by doing the work
1107 * in the start function of the copy.
1108 */
1109 if( fclass->load ) {
1110 #ifdef DEBUG
1111 printf( "vips_foreign_load_build: delaying read ...\n" );
1112 #endif /*DEBUG*/
1113
1114 /* ->header() should set the dhint. It'll default to the safe
1115 * SMALLTILE if header() did not set it.
1116 */
1117 if( vips_image_pipelinev( load->out, load->out->dhint, NULL ) )
1118 return( -1 );
1119
1120 /* Then 'start' creates the real image and 'gen' fetches
1121 * pixels for @out from @real on demand.
1122 */
1123 if( vips_image_generate( load->out,
1124 vips_foreign_load_start,
1125 vips_foreign_load_generate,
1126 vips_stop_one,
1127 NULL, load ) )
1128 return( -1 );
1129 }
1130
1131 /* Tell downstream if we are reading sequentially.
1132 */
1133 if( sequential )
1134 vips_image_set_area( load->out,
1135 VIPS_META_SEQUENTIAL, NULL, NULL );
1136
1137 return( 0 );
1138 }
1139
1140 static VipsOperationFlags
vips_foreign_load_operation_get_flags(VipsOperation * operation)1141 vips_foreign_load_operation_get_flags( VipsOperation *operation )
1142 {
1143 VipsForeignLoad *load = VIPS_FOREIGN_LOAD( operation );
1144
1145 VipsOperationFlags flags;
1146
1147 flags = VIPS_OPERATION_CLASS( vips_foreign_load_parent_class )->
1148 get_flags( operation );
1149 if( load->nocache )
1150 flags |= VIPS_OPERATION_NOCACHE;
1151
1152 return( flags );
1153 }
1154
1155 static void
vips_foreign_load_class_init(VipsForeignLoadClass * class)1156 vips_foreign_load_class_init( VipsForeignLoadClass *class )
1157 {
1158 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
1159 VipsObjectClass *object_class = (VipsObjectClass *) class;
1160 VipsOperationClass *operation_class = (VipsOperationClass *) class;
1161
1162 gobject_class->dispose = vips_foreign_load_dispose;
1163 gobject_class->set_property = vips_object_set_property;
1164 gobject_class->get_property = vips_object_get_property;
1165
1166 object_class->build = vips_foreign_load_build;
1167 object_class->summary_class = vips_foreign_load_summary_class;
1168 object_class->new_from_string = vips_foreign_load_new_from_string;
1169 object_class->nickname = "fileload";
1170 object_class->description = _( "file loaders" );
1171
1172 operation_class->get_flags = vips_foreign_load_operation_get_flags;
1173
1174 VIPS_ARG_IMAGE( class, "out", 2,
1175 _( "Output" ),
1176 _( "Output image" ),
1177 VIPS_ARGUMENT_REQUIRED_OUTPUT,
1178 G_STRUCT_OFFSET( VipsForeignLoad, out ) );
1179
1180 VIPS_ARG_FLAGS( class, "flags", 106,
1181 _( "Flags" ),
1182 _( "Flags for this file" ),
1183 VIPS_ARGUMENT_OPTIONAL_OUTPUT,
1184 G_STRUCT_OFFSET( VipsForeignLoad, flags ),
1185 VIPS_TYPE_FOREIGN_FLAGS, VIPS_FOREIGN_NONE );
1186
1187 VIPS_ARG_BOOL( class, "memory", 107,
1188 _( "Memory" ),
1189 _( "Force open via memory" ),
1190 VIPS_ARGUMENT_OPTIONAL_INPUT,
1191 G_STRUCT_OFFSET( VipsForeignLoad, memory ),
1192 FALSE );
1193
1194 VIPS_ARG_ENUM( class, "access", 108,
1195 _( "Access" ),
1196 _( "Required access pattern for this file" ),
1197 VIPS_ARGUMENT_OPTIONAL_INPUT,
1198 G_STRUCT_OFFSET( VipsForeignLoad, access ),
1199 VIPS_TYPE_ACCESS, VIPS_ACCESS_RANDOM );
1200
1201 VIPS_ARG_ENUM( class, "fail-on", 109,
1202 _( "Fail on" ),
1203 _( "Error level to fail on" ),
1204 VIPS_ARGUMENT_OPTIONAL_INPUT,
1205 G_STRUCT_OFFSET( VipsForeignLoad, fail_on ),
1206 VIPS_TYPE_FAIL_ON, VIPS_FAIL_ON_NONE );
1207
1208 VIPS_ARG_BOOL( class, "sequential", 110,
1209 _( "Sequential" ),
1210 _( "Sequential read only" ),
1211 VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
1212 G_STRUCT_OFFSET( VipsForeignLoad, sequential ),
1213 FALSE );
1214
1215 VIPS_ARG_BOOL( class, "fail", 111,
1216 _( "Fail" ),
1217 _( "Fail on first warning" ),
1218 VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
1219 G_STRUCT_OFFSET( VipsForeignLoad, fail ),
1220 FALSE );
1221
1222 VIPS_ARG_BOOL( class, "disc", 112,
1223 _( "Disc" ),
1224 _( "Open to disc" ),
1225 VIPS_ARGUMENT_OPTIONAL_INPUT | VIPS_ARGUMENT_DEPRECATED,
1226 G_STRUCT_OFFSET( VipsForeignLoad, disc ),
1227 TRUE );
1228
1229 }
1230
1231 static void
vips_foreign_load_init(VipsForeignLoad * load)1232 vips_foreign_load_init( VipsForeignLoad *load )
1233 {
1234 load->disc = TRUE;
1235 load->access = VIPS_ACCESS_RANDOM;
1236 load->fail_on = VIPS_FAIL_ON_NONE;
1237 }
1238
1239 /*
1240 * Loaders can call this
1241 */
1242
1243 /**
1244 * vips_foreign_load_invalidate: (method)
1245 * @image: image to invalidate
1246 *
1247 * Loaders can call this on the image they are making if they see a read error
1248 * from the load library. It signals "invalidate" on the load operation and
1249 * will cause it to be dropped from cache.
1250 *
1251 * If we know a file will cause a read error, we don't want to cache the
1252 * failing operation, we want to make sure the image will really be opened
1253 * again if our caller tries again. For example, a broken file might be
1254 * replaced by a working one.
1255 */
1256 void
vips_foreign_load_invalidate(VipsImage * image)1257 vips_foreign_load_invalidate( VipsImage *image )
1258 {
1259 VipsOperation *operation;
1260
1261 #ifdef DEBUG
1262 printf( "vips_foreign_load_invalidate: %p\n", image );
1263 #endif /*DEBUG*/
1264
1265 if( (operation = g_object_get_qdata( G_OBJECT( image ),
1266 vips__foreign_load_operation )) ) {
1267 vips_operation_invalidate( operation );
1268 }
1269 }
1270
1271 /* Abstract base class for image savers.
1272 */
1273
1274 G_DEFINE_ABSTRACT_TYPE( VipsForeignSave, vips_foreign_save, VIPS_TYPE_FOREIGN );
1275
1276 static void
vips_foreign_save_dispose(GObject * gobject)1277 vips_foreign_save_dispose( GObject *gobject )
1278 {
1279 VipsForeignSave *save = VIPS_FOREIGN_SAVE( gobject );
1280
1281 VIPS_UNREF( save->ready );
1282
1283 G_OBJECT_CLASS( vips_foreign_save_parent_class )->dispose( gobject );
1284 }
1285
1286 static void
vips_foreign_save_summary_class(VipsObjectClass * object_class,VipsBuf * buf)1287 vips_foreign_save_summary_class( VipsObjectClass *object_class, VipsBuf *buf )
1288 {
1289 VipsForeignSaveClass *class = VIPS_FOREIGN_SAVE_CLASS( object_class );
1290
1291 VIPS_OBJECT_CLASS( vips_foreign_save_parent_class )->
1292 summary_class( object_class, buf );
1293
1294 vips_buf_appendf( buf, ", %s",
1295 vips_enum_nick( VIPS_TYPE_SAVEABLE, class->saveable ) );
1296 }
1297
1298 static VipsObject *
vips_foreign_save_new_from_string(const char * string)1299 vips_foreign_save_new_from_string( const char *string )
1300 {
1301 const char *file_op;
1302 GType type;
1303 VipsForeignSave *save;
1304
1305 if( !(file_op = vips_foreign_find_save( string )) )
1306 return( NULL );
1307 type = g_type_from_name( file_op );
1308 g_assert( type );
1309
1310 save = VIPS_FOREIGN_SAVE( g_object_new( type, NULL ) );
1311 g_object_set( save,
1312 "filename", string,
1313 NULL );
1314
1315 return( VIPS_OBJECT( save ) );
1316 }
1317
1318 /* Convert an image for saving.
1319 */
1320 int
vips__foreign_convert_saveable(VipsImage * in,VipsImage ** ready,VipsSaveable saveable,VipsBandFormat * format,VipsCoding * coding,VipsArrayDouble * background)1321 vips__foreign_convert_saveable( VipsImage *in, VipsImage **ready,
1322 VipsSaveable saveable, VipsBandFormat *format, VipsCoding *coding,
1323 VipsArrayDouble *background )
1324 {
1325 /* in holds a reference to the output of our chain as we build it.
1326 */
1327 g_object_ref( in );
1328
1329 /* For coded images, can this class save the coding we are in now?
1330 * Nothing to do.
1331 */
1332 if( in->Coding != VIPS_CODING_NONE &&
1333 coding[in->Coding] ) {
1334 *ready = in;
1335 return( 0 );
1336 }
1337
1338 /* For uncoded images, if this saver supports ANY bands and this
1339 * format we have nothing to do.
1340 */
1341 if( in->Coding == VIPS_CODING_NONE &&
1342 saveable == VIPS_SAVEABLE_ANY &&
1343 format[in->BandFmt] == in->BandFmt ) {
1344 *ready = in;
1345 return( 0 );
1346 }
1347
1348 /* Otherwise ... we need to decode and then (possibly) recode at the
1349 * end.
1350 */
1351
1352 /* If this is an VIPS_CODING_LABQ, we can go straight to RGB.
1353 */
1354 if( in->Coding == VIPS_CODING_LABQ ) {
1355 VipsImage *out;
1356
1357 if( vips_LabQ2sRGB( in, &out, NULL ) ) {
1358 g_object_unref( in );
1359 return( -1 );
1360 }
1361 g_object_unref( in );
1362
1363 in = out;
1364 }
1365
1366 /* If this is an VIPS_CODING_RAD, we unpack to float. This could be
1367 * scRGB or XYZ.
1368 */
1369 if( in->Coding == VIPS_CODING_RAD ) {
1370 VipsImage *out;
1371
1372 if( vips_rad2float( in, &out, NULL ) ) {
1373 g_object_unref( in );
1374 return( -1 );
1375 }
1376 g_object_unref( in );
1377
1378 in = out;
1379 }
1380
1381 /* If the saver supports RAD, we need to go to scRGB or XYZ.
1382 */
1383 if( coding[VIPS_CODING_RAD] ) {
1384 if( in->Type != VIPS_INTERPRETATION_scRGB &&
1385 in->Type != VIPS_INTERPRETATION_XYZ ) {
1386 VipsImage *out;
1387
1388 if( vips_colourspace( in, &out,
1389 VIPS_INTERPRETATION_scRGB, NULL ) ) {
1390 g_object_unref( in );
1391 return( -1 );
1392 }
1393 g_object_unref( in );
1394
1395 in = out;
1396 }
1397 }
1398
1399 /* If this image is CMYK and the saver is RGB-only, use lcms to try to
1400 * import to XYZ.
1401 */
1402 if( in->Type == VIPS_INTERPRETATION_CMYK &&
1403 in->Bands >= 4 &&
1404 (saveable == VIPS_SAVEABLE_RGB ||
1405 saveable == VIPS_SAVEABLE_RGBA ||
1406 saveable == VIPS_SAVEABLE_RGBA_ONLY) ) {
1407 VipsImage *out;
1408
1409 if( vips_icc_import( in, &out,
1410 "pcs", VIPS_PCS_XYZ,
1411 "embedded", TRUE,
1412 "input_profile", "cmyk",
1413 NULL ) ) {
1414 g_object_unref( in );
1415 return( -1 );
1416 }
1417 g_object_unref( in );
1418
1419 in = out;
1420 }
1421
1422 /* If this is something other than CMYK or RAD, and it's not already
1423 * an RGB image, eg. maybe a LAB image, we need to transform
1424 * to RGB.
1425 */
1426 if( !coding[VIPS_CODING_RAD] &&
1427 in->Bands >= 3 &&
1428 in->Type != VIPS_INTERPRETATION_CMYK &&
1429 in->Type != VIPS_INTERPRETATION_sRGB &&
1430 in->Type != VIPS_INTERPRETATION_RGB16 &&
1431 in->Type != VIPS_INTERPRETATION_scRGB &&
1432 vips_colourspace_issupported( in ) &&
1433 (saveable == VIPS_SAVEABLE_RGB ||
1434 saveable == VIPS_SAVEABLE_RGBA ||
1435 saveable == VIPS_SAVEABLE_RGBA_ONLY ||
1436 saveable == VIPS_SAVEABLE_RGB_CMYK) ) {
1437 VipsImage *out;
1438 VipsInterpretation interpretation;
1439
1440 /* Do we make RGB or RGB16? We don't want to squash a 16-bit
1441 * RGB down to 8 bits if the saver supports 16.
1442 */
1443 if( vips_band_format_is8bit( format[in->BandFmt] ) )
1444 interpretation = VIPS_INTERPRETATION_sRGB;
1445 else
1446 interpretation = VIPS_INTERPRETATION_RGB16;
1447
1448 if( vips_colourspace( in, &out, interpretation, NULL ) ) {
1449 g_object_unref( in );
1450 return( -1 );
1451 }
1452 g_object_unref( in );
1453
1454 in = out;
1455 }
1456
1457 /* VIPS_SAVEABLE_RGBA_ONLY does not support mono types ... convert
1458 * to sRGB.
1459 */
1460 if( !coding[VIPS_CODING_RAD] &&
1461 in->Bands < 3 &&
1462 vips_colourspace_issupported( in ) &&
1463 saveable == VIPS_SAVEABLE_RGBA_ONLY ) {
1464 VipsImage *out;
1465 VipsInterpretation interpretation;
1466
1467 /* Do we make RGB or RGB16? We don't want to squash a 16-bit
1468 * RGB down to 8 bits if the saver supports 16.
1469 */
1470 if( vips_band_format_is8bit( format[in->BandFmt] ) )
1471 interpretation = VIPS_INTERPRETATION_sRGB;
1472 else
1473 interpretation = VIPS_INTERPRETATION_RGB16;
1474
1475 if( vips_colourspace( in, &out, interpretation, NULL ) ) {
1476 g_object_unref( in );
1477 return( -1 );
1478 }
1479 g_object_unref( in );
1480
1481 in = out;
1482 }
1483
1484 /* Get the bands right. We must do this after all colourspace
1485 * transforms, since they can change the number of bands.
1486 */
1487 if( in->Coding == VIPS_CODING_NONE ) {
1488 /* Do we need to flatten out an alpha channel? There needs to
1489 * be an alpha there now, and this writer needs to not support
1490 * alpha.
1491 */
1492 if( (in->Bands == 2 ||
1493 (in->Bands == 4 &&
1494 in->Type != VIPS_INTERPRETATION_CMYK)) &&
1495 (saveable == VIPS_SAVEABLE_MONO ||
1496 saveable == VIPS_SAVEABLE_RGB ||
1497 saveable == VIPS_SAVEABLE_RGB_CMYK) ) {
1498 VipsImage *out;
1499
1500 if( vips_flatten( in, &out,
1501 "background", background,
1502 NULL ) ) {
1503 g_object_unref( in );
1504 return( -1 );
1505 }
1506 g_object_unref( in );
1507
1508 in = out;
1509 }
1510
1511 /* Other alpha removal strategies ... just drop the extra
1512 * bands.
1513 */
1514
1515 else if( in->Bands > 3 &&
1516 (saveable == VIPS_SAVEABLE_RGB ||
1517 (saveable == VIPS_SAVEABLE_RGB_CMYK &&
1518 in->Type != VIPS_INTERPRETATION_CMYK)) ) {
1519 VipsImage *out;
1520
1521 /* Don't let 4 bands though unless the image really is
1522 * a CMYK.
1523 *
1524 * Consider a RGBA png being saved as JPG. We can
1525 * write CMYK jpg, but we mustn't do that for RGBA
1526 * images.
1527 */
1528 if( vips_extract_band( in, &out, 0,
1529 "n", 3,
1530 NULL ) ) {
1531 g_object_unref( in );
1532 return( -1 );
1533 }
1534 g_object_unref( in );
1535
1536 in = out;
1537 }
1538 else if( in->Bands > 4 &&
1539 ((saveable == VIPS_SAVEABLE_RGB_CMYK &&
1540 in->Type == VIPS_INTERPRETATION_CMYK) ||
1541 saveable == VIPS_SAVEABLE_RGBA ||
1542 saveable == VIPS_SAVEABLE_RGBA_ONLY) ) {
1543 VipsImage *out;
1544
1545 if( vips_extract_band( in, &out, 0,
1546 "n", 4,
1547 NULL ) ) {
1548 g_object_unref( in );
1549 return( -1 );
1550 }
1551 g_object_unref( in );
1552
1553 in = out;
1554 }
1555 else if( in->Bands > 1 &&
1556 saveable == VIPS_SAVEABLE_MONO ) {
1557 VipsImage *out;
1558
1559 if( vips_extract_band( in, &out, 0, NULL ) ) {
1560 g_object_unref( in );
1561 return( -1 );
1562 }
1563 g_object_unref( in );
1564
1565 in = out;
1566 }
1567
1568 /* Else we have VIPS_SAVEABLE_ANY and we don't chop bands down.
1569 */
1570 }
1571
1572 /* Handle the ushort interpretations.
1573 *
1574 * RGB16 and GREY16 use 0-65535 for black-white. If we have an image
1575 * tagged like this, and it has more than 8 bits (we leave crazy uchar
1576 * images tagged as RGB16 alone), we'll need to get it ready for the
1577 * saver.
1578 */
1579 if( (in->Type == VIPS_INTERPRETATION_RGB16 ||
1580 in->Type == VIPS_INTERPRETATION_GREY16) &&
1581 !vips_band_format_is8bit( in->BandFmt ) ) {
1582 /* If the saver supports ushort, cast to ushort. It may be
1583 * float at the moment, for example.
1584 *
1585 * If the saver does not support ushort, automatically shift
1586 * it down. This is the behaviour we want for saving an RGB16
1587 * image as JPG, for example.
1588 */
1589 if( format[VIPS_FORMAT_USHORT] == VIPS_FORMAT_USHORT ) {
1590 VipsImage *out;
1591
1592 if( vips_cast( in, &out, VIPS_FORMAT_USHORT, NULL ) ) {
1593 g_object_unref( in );
1594 return( -1 );
1595 }
1596 g_object_unref( in );
1597
1598 in = out;
1599 }
1600 else {
1601 VipsImage *out;
1602
1603 if( vips_rshift_const1( in, &out, 8, NULL ) ) {
1604 g_object_unref( in );
1605 return( -1 );
1606 }
1607 g_object_unref( in );
1608
1609 in = out;
1610
1611 /* That could have produced an int image ... make sure
1612 * we are now uchar.
1613 */
1614 if( vips_cast( in, &out, VIPS_FORMAT_UCHAR, NULL ) ) {
1615 g_object_unref( in );
1616 return( -1 );
1617 }
1618 g_object_unref( in );
1619
1620 in = out;
1621 }
1622 }
1623
1624 /* Cast to the output format.
1625 */
1626 {
1627 VipsImage *out;
1628
1629 if( vips_cast( in, &out, format[in->BandFmt], NULL ) ) {
1630 g_object_unref( in );
1631 return( -1 );
1632 }
1633 g_object_unref( in );
1634
1635 in = out;
1636 }
1637
1638 /* Does this class want a coded image? Search the coding table for the
1639 * first one.
1640 */
1641 if( coding[VIPS_CODING_NONE] ) {
1642 /* Already NONE, nothing to do.
1643 */
1644 }
1645 else if( coding[VIPS_CODING_LABQ] ) {
1646 VipsImage *out;
1647
1648 if( vips_Lab2LabQ( in, &out, NULL ) ) {
1649 g_object_unref( in );
1650 return( -1 );
1651 }
1652 g_object_unref( in );
1653
1654 in = out;
1655 }
1656 else if( coding[VIPS_CODING_RAD] ) {
1657 VipsImage *out;
1658
1659 if( vips_float2rad( in, &out, NULL ) ) {
1660 g_object_unref( in );
1661 return( -1 );
1662 }
1663 g_object_unref( in );
1664
1665 in = out;
1666 }
1667
1668 /* Some format libraries, like libpng, will throw a hard error if the
1669 * profile is inappropriate for this image type. With profiles inherited
1670 * from a source image, this can happen all the time, so we
1671 * want to silently drop the profile in this case.
1672 */
1673 if( vips_image_get_typeof( in, VIPS_META_ICC_NAME ) ) {
1674 const void *data;
1675 size_t length;
1676
1677 if( !vips_image_get_blob( in, VIPS_META_ICC_NAME,
1678 &data, &length ) &&
1679 !vips_icc_is_compatible_profile( in, data, length ) ) {
1680 VipsImage *out;
1681
1682 if( vips_copy( in, &out, NULL ) ) {
1683 g_object_unref( in );
1684 return( -1 );
1685 }
1686 g_object_unref( in );
1687
1688 in = out;
1689
1690 vips_image_remove( in, VIPS_META_ICC_NAME );
1691 }
1692 }
1693
1694 *ready = in;
1695
1696 return( 0 );
1697 }
1698
1699 static int
vips_foreign_save_build(VipsObject * object)1700 vips_foreign_save_build( VipsObject *object )
1701 {
1702 VipsForeignSave *save = VIPS_FOREIGN_SAVE( object );
1703
1704 if( save->in ) {
1705 VipsForeignSaveClass *class =
1706 VIPS_FOREIGN_SAVE_GET_CLASS( save );
1707 VipsImage *ready;
1708
1709 if( vips__foreign_convert_saveable( save->in, &ready,
1710 class->saveable, class->format_table, class->coding,
1711 save->background ) )
1712 return( -1 );
1713
1714 if( save->page_height ) {
1715 VipsImage *x;
1716
1717 if( vips_copy( ready, &x, NULL ) ) {
1718 VIPS_UNREF( ready );
1719 return( -1 );
1720 }
1721 VIPS_UNREF( ready );
1722 ready = x;
1723
1724 vips_image_set_int( ready,
1725 VIPS_META_PAGE_HEIGHT, save->page_height );
1726 }
1727
1728 VIPS_UNREF( save->ready );
1729 save->ready = ready;
1730 }
1731
1732 if( VIPS_OBJECT_CLASS( vips_foreign_save_parent_class )->
1733 build( object ) )
1734 return( -1 );
1735
1736 return( 0 );
1737 }
1738
1739 #define UC VIPS_FORMAT_UCHAR
1740 #define C VIPS_FORMAT_CHAR
1741 #define US VIPS_FORMAT_USHORT
1742 #define S VIPS_FORMAT_SHORT
1743 #define UI VIPS_FORMAT_UINT
1744 #define I VIPS_FORMAT_INT
1745 #define F VIPS_FORMAT_FLOAT
1746 #define X VIPS_FORMAT_COMPLEX
1747 #define D VIPS_FORMAT_DOUBLE
1748 #define DX VIPS_FORMAT_DPCOMPLEX
1749
1750 static int vips_foreign_save_format_table[10] = {
1751 // UC C US S UI I F X D DX
1752 UC, C, US, S, UI, I, F, X, D, DX
1753 };
1754
1755 static void
vips_foreign_save_class_init(VipsForeignSaveClass * class)1756 vips_foreign_save_class_init( VipsForeignSaveClass *class )
1757 {
1758 GObjectClass *gobject_class = G_OBJECT_CLASS( class );
1759 VipsObjectClass *object_class = (VipsObjectClass *) class;
1760 VipsOperationClass *operation_class = (VipsOperationClass *) class;
1761
1762 int i;
1763
1764 gobject_class->dispose = vips_foreign_save_dispose;
1765 gobject_class->set_property = vips_object_set_property;
1766 gobject_class->get_property = vips_object_get_property;
1767
1768 object_class->build = vips_foreign_save_build;
1769 object_class->summary_class = vips_foreign_save_summary_class;
1770 object_class->new_from_string = vips_foreign_save_new_from_string;
1771 object_class->nickname = "filesave";
1772 object_class->description = _( "file savers" );
1773
1774 /* All savers are sequential by definition. Things like tiled tiff
1775 * write and interlaced png write, which are not, add extra caches
1776 * on their input.
1777 */
1778 operation_class->flags |= VIPS_OPERATION_SEQUENTIAL;
1779
1780 /* Must not cache savers.
1781 */
1782 operation_class->flags |= VIPS_OPERATION_NOCACHE;
1783
1784 /* Default to no coding allowed.
1785 */
1786 for( i = 0; i < VIPS_CODING_LAST; i++ )
1787 class->coding[i] = FALSE;
1788 class->coding[VIPS_CODING_NONE] = TRUE;
1789
1790 /* Default to no cast on save.
1791 */
1792 class->format_table = vips_foreign_save_format_table;
1793
1794 VIPS_ARG_IMAGE( class, "in", 0,
1795 _( "Input" ),
1796 _( "Image to save" ),
1797 VIPS_ARGUMENT_REQUIRED_INPUT,
1798 G_STRUCT_OFFSET( VipsForeignSave, in ) );
1799
1800 VIPS_ARG_BOOL( class, "strip", 100,
1801 _( "Strip" ),
1802 _( "Strip all metadata from image" ),
1803 VIPS_ARGUMENT_OPTIONAL_INPUT,
1804 G_STRUCT_OFFSET( VipsForeignSave, strip ),
1805 FALSE );
1806
1807 VIPS_ARG_BOXED( class, "background", 101,
1808 _( "Background" ),
1809 _( "Background value" ),
1810 VIPS_ARGUMENT_OPTIONAL_INPUT,
1811 G_STRUCT_OFFSET( VipsForeignSave, background ),
1812 VIPS_TYPE_ARRAY_DOUBLE );
1813
1814 VIPS_ARG_INT( class, "page_height", 102,
1815 _( "Page height" ),
1816 _( "Set page height for multipage save" ),
1817 VIPS_ARGUMENT_OPTIONAL_INPUT,
1818 G_STRUCT_OFFSET( VipsForeignSave, page_height ),
1819 0, VIPS_MAX_COORD, 0 );
1820
1821 }
1822
1823 static void
vips_foreign_save_init(VipsForeignSave * save)1824 vips_foreign_save_init( VipsForeignSave *save )
1825 {
1826 save->background = vips_array_double_newv( 1, 0.0 );
1827 }
1828
1829 /* Can we write this filename with this class?
1830 */
1831 static void *
vips_foreign_find_save_sub(VipsForeignSaveClass * save_class,const char * filename,void * b)1832 vips_foreign_find_save_sub( VipsForeignSaveClass *save_class,
1833 const char *filename, void *b )
1834 {
1835 VipsObjectClass *object_class = VIPS_OBJECT_CLASS( save_class );
1836 VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class );
1837
1838 const char **p;
1839
1840 /* All savers needs suffs defined since we use the suff to pick the
1841 * saver.
1842 */
1843 if( !class->suffs )
1844 g_warning( "no suffix defined for %s", object_class->nickname );
1845
1846 /* Skip non-file savers.
1847 */
1848 if( vips_ispostfix( object_class->nickname, "_buffer" ) ||
1849 vips_ispostfix( object_class->nickname, "_target" ) )
1850 return( NULL );
1851
1852 /* vips_foreign_find_save() has already removed any options from the
1853 * end of the filename, so we can test directly against the suffix.
1854 */
1855 for( p = class->suffs; *p; p++ )
1856 if( vips_iscasepostfix( filename, *p ) )
1857 return( save_class );
1858
1859 return( NULL );
1860 }
1861
1862 /**
1863 * vips_foreign_find_save:
1864 * @filename: name to find a saver for
1865 *
1866 * Searches for an operation you could use to write to @filename.
1867 * Any trailing options on @filename are stripped and ignored.
1868 *
1869 * See also: vips_foreign_find_save_buffer(), vips_image_write_to_file().
1870 *
1871 * Returns: the name of an operation on success, %NULL on error
1872 */
1873 const char *
vips_foreign_find_save(const char * name)1874 vips_foreign_find_save( const char *name )
1875 {
1876 char filename[VIPS_PATH_MAX];
1877 char option_string[VIPS_PATH_MAX];
1878 VipsForeignSaveClass *save_class;
1879
1880 vips__filename_split8( name, filename, option_string );
1881
1882 if( !(save_class = (VipsForeignSaveClass *) vips_foreign_map(
1883 "VipsForeignSave",
1884 (VipsSListMap2Fn) vips_foreign_find_save_sub,
1885 (void *) filename, NULL )) ) {
1886 vips_error( "VipsForeignSave",
1887 _( "\"%s\" is not a known file format" ), name );
1888
1889 return( NULL );
1890 }
1891
1892 return( G_OBJECT_CLASS_NAME( save_class ) );
1893 }
1894
1895 static void *
vips_foreign_get_suffixes_count_cb(VipsForeignSaveClass * save_class,void * a,void * b)1896 vips_foreign_get_suffixes_count_cb( VipsForeignSaveClass *save_class,
1897 void *a, void *b )
1898 {
1899 VipsForeignClass *foreign_class = VIPS_FOREIGN_CLASS( save_class );
1900 int *n_fields = (int *) a;
1901
1902 int i;
1903
1904 if( foreign_class->suffs )
1905 for( i = 0; foreign_class->suffs[i]; i++ )
1906 *n_fields += 1;
1907
1908 return( NULL );
1909 }
1910
1911 static void *
vips_foreign_get_suffixes_add_cb(VipsForeignSaveClass * save_class,void * a,void * b)1912 vips_foreign_get_suffixes_add_cb( VipsForeignSaveClass *save_class,
1913 void *a, void *b )
1914 {
1915 VipsForeignClass *foreign_class = VIPS_FOREIGN_CLASS( save_class );
1916 gchar ***p = (gchar ***) a;
1917
1918 int i;
1919
1920 if( foreign_class->suffs )
1921 for( i = 0; foreign_class->suffs[i]; i++ ) {
1922 **p = g_strdup( foreign_class->suffs[i] );
1923 *p += 1;
1924 }
1925
1926 return( NULL );
1927 }
1928
1929 /**
1930 * vips_foreign_get_suffixes: (method)
1931 *
1932 * Get a %NULL-terminated array listing all the supported suffixes.
1933 *
1934 * This is not the same as all the supported file types, since libvips
1935 * detects image format for load by testing the first few bytes.
1936 *
1937 * Use vips_foreign_find_load() to detect type for a specific file.
1938 *
1939 * Free the return result with g_strfreev().
1940 *
1941 * Returns: (transfer full): all supported file extensions, as a
1942 * %NULL-terminated array.
1943 */
1944 gchar **
vips_foreign_get_suffixes(void)1945 vips_foreign_get_suffixes( void )
1946 {
1947 int n_suffs;
1948 gchar **suffs;
1949 gchar **p;
1950
1951 n_suffs = 0;
1952 (void) vips_foreign_map(
1953 "VipsForeignSave",
1954 (VipsSListMap2Fn) vips_foreign_get_suffixes_count_cb,
1955 &n_suffs, NULL );
1956
1957 suffs = g_new0( gchar *, n_suffs + 1 );
1958 p = suffs;
1959 (void) vips_foreign_map(
1960 "VipsForeignSave",
1961 (VipsSListMap2Fn) vips_foreign_get_suffixes_add_cb,
1962 &p, NULL );
1963
1964 return( suffs );
1965 }
1966
1967 /* Kept for early vips8 API compat.
1968 */
1969
1970 int
vips_foreign_save(VipsImage * in,const char * name,...)1971 vips_foreign_save( VipsImage *in, const char *name, ... )
1972 {
1973 char filename[VIPS_PATH_MAX];
1974 char option_string[VIPS_PATH_MAX];
1975 const char *operation_name;
1976 va_list ap;
1977 int result;
1978
1979 vips__filename_split8( name, filename, option_string );
1980
1981 if( !(operation_name = vips_foreign_find_save( filename )) )
1982 return( -1 );
1983
1984 va_start( ap, name );
1985 result = vips_call_split_option_string( operation_name, option_string,
1986 ap, in, filename );
1987 va_end( ap );
1988
1989 return( result );
1990 }
1991
1992 /* Can this class write this filetype to a target?
1993 */
1994 static void *
vips_foreign_find_save_target_sub(VipsForeignSaveClass * save_class,const char * suffix,void * b)1995 vips_foreign_find_save_target_sub( VipsForeignSaveClass *save_class,
1996 const char *suffix, void *b )
1997 {
1998 VipsObjectClass *object_class = VIPS_OBJECT_CLASS( save_class );
1999 VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class );
2000
2001 /* All concrete savers needs suffs, since we use the suff to pick the
2002 * saver.
2003 */
2004 if( !G_TYPE_IS_ABSTRACT( G_TYPE_FROM_CLASS( class ) ) &&
2005 !class->suffs )
2006 g_warning( "no suffix defined for %s", object_class->nickname );
2007
2008 if( !G_TYPE_IS_ABSTRACT( G_TYPE_FROM_CLASS( class ) ) &&
2009 class->suffs &&
2010 vips_ispostfix( object_class->nickname, "_target" ) &&
2011 vips_filename_suffix_match( suffix, class->suffs ) )
2012 return( save_class );
2013
2014 return( NULL );
2015 }
2016
2017 /**
2018 * vips_foreign_find_save_target:
2019 * @suffix: format to find a saver for
2020 *
2021 * Searches for an operation you could use to write to a target in @suffix
2022 * format.
2023 *
2024 * See also: vips_image_write_to_buffer().
2025 *
2026 * Returns: the name of an operation on success, %NULL on error
2027 */
2028 const char *
vips_foreign_find_save_target(const char * name)2029 vips_foreign_find_save_target( const char *name )
2030 {
2031 char suffix[VIPS_PATH_MAX];
2032 char option_string[VIPS_PATH_MAX];
2033 VipsForeignSaveClass *save_class;
2034
2035 vips__filename_split8( name, suffix, option_string );
2036
2037 if( !(save_class = (VipsForeignSaveClass *) vips_foreign_map(
2038 "VipsForeignSave",
2039 (VipsSListMap2Fn) vips_foreign_find_save_target_sub,
2040 (void *) suffix, NULL )) ) {
2041 vips_error( "VipsForeignSave",
2042 _( "\"%s\" is not a known target format" ), name );
2043
2044 return( NULL );
2045 }
2046
2047 return( G_OBJECT_CLASS_NAME( save_class ) );
2048 }
2049
2050 /* Can we write this buffer with this file type?
2051 */
2052 static void *
vips_foreign_find_save_buffer_sub(VipsForeignSaveClass * save_class,const char * suffix,void * b)2053 vips_foreign_find_save_buffer_sub( VipsForeignSaveClass *save_class,
2054 const char *suffix, void *b )
2055 {
2056 VipsObjectClass *object_class = VIPS_OBJECT_CLASS( save_class );
2057 VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class );
2058
2059 /* All concrete savers needs suffs, since we use the suff to pick the
2060 * saver.
2061 */
2062 if( !G_TYPE_IS_ABSTRACT( G_TYPE_FROM_CLASS( class ) ) &&
2063 !class->suffs )
2064 g_warning( "no suffix defined for %s", object_class->nickname );
2065
2066 if( !G_TYPE_IS_ABSTRACT( G_TYPE_FROM_CLASS( class ) ) &&
2067 class->suffs &&
2068 vips_ispostfix( object_class->nickname, "_buffer" ) &&
2069 vips_filename_suffix_match( suffix, class->suffs ) )
2070 return( save_class );
2071
2072 return( NULL );
2073 }
2074
2075 /**
2076 * vips_foreign_find_save_buffer:
2077 * @suffix: name to find a saver for
2078 *
2079 * Searches for an operation you could use to write to a buffer in @suffix
2080 * format.
2081 *
2082 * See also: vips_image_write_to_buffer().
2083 *
2084 * Returns: the name of an operation on success, %NULL on error
2085 */
2086 const char *
vips_foreign_find_save_buffer(const char * name)2087 vips_foreign_find_save_buffer( const char *name )
2088 {
2089 char suffix[VIPS_PATH_MAX];
2090 char option_string[VIPS_PATH_MAX];
2091 VipsForeignSaveClass *save_class;
2092
2093 vips__filename_split8( name, suffix, option_string );
2094
2095 if( !(save_class = (VipsForeignSaveClass *) vips_foreign_map(
2096 "VipsForeignSave",
2097 (VipsSListMap2Fn) vips_foreign_find_save_buffer_sub,
2098 (void *) suffix, NULL )) ) {
2099 vips_error( "VipsForeignSave",
2100 _( "\"%s\" is not a known buffer format" ), name );
2101
2102 return( NULL );
2103 }
2104
2105 return( G_OBJECT_CLASS_NAME( save_class ) );
2106 }
2107
2108 /* C API wrappers for loadable modules go here.
2109 */
2110
2111 /**
2112 * vips_heifload:
2113 * @filename: file to load
2114 * @out: (out): decompressed image
2115 * @...: %NULL-terminated list of optional named arguments
2116 *
2117 * Optional arguments:
2118 *
2119 * * @page: %gint, page (top-level image number) to read
2120 * * @n: %gint, load this many pages
2121 * * @thumbnail: %gboolean, fetch thumbnail instead of image
2122 *
2123 * Read a HEIF image file into a VIPS image.
2124 *
2125 * Use @page to select a page to render, numbering from zero. If neither @n
2126 * nor @page are set, @page defaults to the primary page, otherwise to 0.
2127 *
2128 * Use @n to select the number of pages to render. The default is 1. Pages are
2129 * rendered in a vertical column. Set to -1 to mean "until the end of the
2130 * document". Use vips_grid() to reorganise pages.
2131 *
2132 * HEIF images have a primary image. The metadata item `heif-primary` gives
2133 * the page number of the primary.
2134 *
2135 * If @thumbnail is %TRUE, then fetch a stored thumbnail rather than the
2136 * image.
2137 *
2138 * See also: vips_image_new_from_file().
2139 *
2140 * Returns: 0 on success, -1 on error.
2141 */
2142 int
vips_heifload(const char * filename,VipsImage ** out,...)2143 vips_heifload( const char *filename, VipsImage **out, ... )
2144 {
2145 va_list ap;
2146 int result;
2147
2148 va_start( ap, out );
2149 result = vips_call_split( "heifload", ap, filename, out );
2150 va_end( ap );
2151
2152 return( result );
2153 }
2154
2155 /**
2156 * vips_heifload_buffer:
2157 * @buf: (array length=len) (element-type guint8): memory area to load
2158 * @len: (type gsize): size of memory area
2159 * @out: (out): image to write
2160 * @...: %NULL-terminated list of optional named arguments
2161 *
2162 * Optional arguments:
2163 *
2164 * * @page: %gint, page (top-level image number) to read
2165 * * @n: %gint, load this many pages
2166 * * @thumbnail: %gboolean, fetch thumbnail instead of image
2167 *
2168 * Read a HEIF image file into a VIPS image.
2169 * Exactly as vips_heifload(), but read from a memory buffer.
2170 *
2171 * You must not free the buffer while @out is active. The
2172 * #VipsObject::postclose signal on @out is a good place to free.
2173 *
2174 * See also: vips_heifload().
2175 *
2176 * Returns: 0 on success, -1 on error.
2177 */
2178 int
vips_heifload_buffer(void * buf,size_t len,VipsImage ** out,...)2179 vips_heifload_buffer( void *buf, size_t len, VipsImage **out, ... )
2180 {
2181 va_list ap;
2182 VipsBlob *blob;
2183 int result;
2184
2185 /* We don't take a copy of the data or free it.
2186 */
2187 blob = vips_blob_new( NULL, buf, len );
2188
2189 va_start( ap, out );
2190 result = vips_call_split( "heifload_buffer", ap, blob, out );
2191 va_end( ap );
2192
2193 vips_area_unref( VIPS_AREA( blob ) );
2194
2195 return( result );
2196 }
2197
2198 /**
2199 * vips_heifload_source:
2200 * @source: source to load from
2201 * @out: (out): image to write
2202 * @...: %NULL-terminated list of optional named arguments
2203 *
2204 * Optional arguments:
2205 *
2206 * * @page: %gint, page (top-level image number) to read
2207 * * @n: %gint, load this many pages
2208 * * @thumbnail: %gboolean, fetch thumbnail instead of image
2209 *
2210 * Exactly as vips_heifload(), but read from a source.
2211 *
2212 * See also: vips_heifload().
2213 *
2214 * Returns: 0 on success, -1 on error.
2215 */
2216 int
vips_heifload_source(VipsSource * source,VipsImage ** out,...)2217 vips_heifload_source( VipsSource *source, VipsImage **out, ... )
2218 {
2219 va_list ap;
2220 int result;
2221
2222 va_start( ap, out );
2223 result = vips_call_split( "heifload_source", ap, source, out );
2224 va_end( ap );
2225
2226 return( result );
2227 }
2228
2229 /**
2230 * vips_heifsave: (method)
2231 * @in: image to save
2232 * @filename: file to write to
2233 * @...: %NULL-terminated list of optional named arguments
2234 *
2235 * Optional arguments:
2236 *
2237 * * @Q: %gint, quality factor
2238 * * @lossless: %gboolean, enable lossless encoding
2239 * * @compression: #VipsForeignHeifCompression, write with this compression
2240 * * @effort: %gint, encoding effort
2241 * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode
2242 *
2243 * Write a VIPS image to a file in HEIF format.
2244 *
2245 * Use @Q to set the compression factor. Default 50, which seems to be roughly
2246 * what the iphone uses. Q 30 gives about the same quality as JPEG Q 75.
2247 *
2248 * Set @lossless %TRUE to switch to lossless compression.
2249 *
2250 * Use @compression to set the encoder e.g. HEVC, AVC, AV1. It defaults to AV1
2251 * if the target filename ends with ".avif", otherwise HEVC.
2252 *
2253 * Use @effort to control the CPU effort spent improving compression.
2254 * This is currently only applicable to AV1 encoders. Defaults to 4, 0 is
2255 * fastest, 9 is slowest.
2256 *
2257 * Chroma subsampling is normally automatically disabled for Q >= 90. You can
2258 * force the subsampling mode with @subsample_mode.
2259 *
2260 * See also: vips_image_write_to_file(), vips_heifload().
2261 *
2262 * Returns: 0 on success, -1 on error.
2263 */
2264 int
vips_heifsave(VipsImage * in,const char * filename,...)2265 vips_heifsave( VipsImage *in, const char *filename, ... )
2266 {
2267 va_list ap;
2268 int result;
2269
2270 va_start( ap, filename );
2271 result = vips_call_split( "heifsave", ap, in, filename );
2272 va_end( ap );
2273
2274 return( result );
2275 }
2276
2277 /**
2278 * vips_heifsave_buffer: (method)
2279 * @in: image to save
2280 * @buf: (array length=len) (element-type guint8): return output buffer here
2281 * @len: (type gsize): return output length here
2282 * @...: %NULL-terminated list of optional named arguments
2283 *
2284 * Optional arguments:
2285 *
2286 * * @Q: %gint, quality factor
2287 * * @lossless: %gboolean, enable lossless encoding
2288 * * @compression: #VipsForeignHeifCompression, write with this compression
2289 * * @effort: %gint, encoding effort
2290 * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode
2291 *
2292 * As vips_heifsave(), but save to a memory buffer.
2293 *
2294 * The address of the buffer is returned in @obuf, the length of the buffer in
2295 * @olen. You are responsible for freeing the buffer with g_free() when you
2296 * are done with it.
2297 *
2298 * See also: vips_heifsave(), vips_image_write_to_file().
2299 *
2300 * Returns: 0 on success, -1 on error.
2301 */
2302 int
vips_heifsave_buffer(VipsImage * in,void ** buf,size_t * len,...)2303 vips_heifsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
2304 {
2305 va_list ap;
2306 VipsArea *area;
2307 int result;
2308
2309 area = NULL;
2310
2311 va_start( ap, len );
2312 result = vips_call_split( "heifsave_buffer", ap, in, &area );
2313 va_end( ap );
2314
2315 if( !result &&
2316 area ) {
2317 if( buf ) {
2318 *buf = area->data;
2319 area->free_fn = NULL;
2320 }
2321 if( len )
2322 *len = area->length;
2323
2324 vips_area_unref( area );
2325 }
2326
2327 return( result );
2328 }
2329
2330 /**
2331 * vips_heifsave_target: (method)
2332 * @in: image to save
2333 * @target: save image to this target
2334 * @...: %NULL-terminated list of optional named arguments
2335 *
2336 * Optional arguments:
2337 *
2338 * * @Q: %gint, quality factor
2339 * * @lossless: %gboolean, enable lossless encoding
2340 * * @compression: #VipsForeignHeifCompression, write with this compression
2341 * * @effort: %gint, encoding effort
2342 * * @subsample_mode: #VipsForeignSubsample, chroma subsampling mode
2343 *
2344 * As vips_heifsave(), but save to a target.
2345 *
2346 * See also: vips_heifsave(), vips_image_write_to_target().
2347 *
2348 * Returns: 0 on success, -1 on error.
2349 */
2350 int
vips_heifsave_target(VipsImage * in,VipsTarget * target,...)2351 vips_heifsave_target( VipsImage *in, VipsTarget *target, ... )
2352 {
2353 va_list ap;
2354 int result;
2355
2356 va_start( ap, target );
2357 result = vips_call_split( "heifsave_target", ap, in, target );
2358 va_end( ap );
2359
2360 return( result );
2361 }
2362
2363 /**
2364 * vips_jxlload:
2365 * @filename: file to load
2366 * @out: (out): decompressed image
2367 * @...: %NULL-terminated list of optional named arguments
2368 *
2369 * Read a JPEG-XL image.
2370 *
2371 * The JPEG-XL loader and saver are experimental features and may change
2372 * in future libvips versions.
2373 *
2374 * See also: vips_image_new_from_file().
2375 *
2376 * Returns: 0 on success, -1 on error.
2377 */
2378 int
vips_jxlload(const char * filename,VipsImage ** out,...)2379 vips_jxlload( const char *filename, VipsImage **out, ... )
2380 {
2381 va_list ap;
2382 int result;
2383
2384 va_start( ap, out );
2385 result = vips_call_split( "jxlload", ap, filename, out );
2386 va_end( ap );
2387
2388 return( result );
2389 }
2390
2391 /**
2392 * vips_jxlload_buffer:
2393 * @buf: (array length=len) (element-type guint8): memory area to load
2394 * @len: (type gsize): size of memory area
2395 * @out: (out): image to write
2396 * @...: %NULL-terminated list of optional named arguments
2397 *
2398 * Exactly as vips_jxlload(), but read from a buffer.
2399 *
2400 * Returns: 0 on success, -1 on error.
2401 */
2402 int
vips_jxlload_buffer(void * buf,size_t len,VipsImage ** out,...)2403 vips_jxlload_buffer( void *buf, size_t len, VipsImage **out, ... )
2404 {
2405 va_list ap;
2406 VipsBlob *blob;
2407 int result;
2408
2409 /* We don't take a copy of the data or free it.
2410 */
2411 blob = vips_blob_new( NULL, buf, len );
2412
2413 va_start( ap, out );
2414 result = vips_call_split( "jxlload_buffer", ap, blob, out );
2415 va_end( ap );
2416
2417 vips_area_unref( VIPS_AREA( blob ) );
2418
2419 return( result );
2420 }
2421
2422 /**
2423 * vips_jxlload_source:
2424 * @source: source to load from
2425 * @out: (out): decompressed image
2426 * @...: %NULL-terminated list of optional named arguments
2427 *
2428 * Exactly as vips_jxlload(), but read from a source.
2429 *
2430 * Returns: 0 on success, -1 on error.
2431 */
2432 int
vips_jxlload_source(VipsSource * source,VipsImage ** out,...)2433 vips_jxlload_source( VipsSource *source, VipsImage **out, ... )
2434 {
2435 va_list ap;
2436 int result;
2437
2438 va_start( ap, out );
2439 result = vips_call_split( "jxlload_source", ap, source, out );
2440 va_end( ap );
2441
2442 return( result );
2443 }
2444
2445 /**
2446 * vips_jxlsave: (method)
2447 * @in: image to save
2448 * @filename: file to write to
2449 * @...: %NULL-terminated list of optional named arguments
2450 *
2451 * Optional arguments:
2452 *
2453 * * @tier: %gint, decode speed tier
2454 * * @distance: %gdouble, maximum encoding error
2455 * * @effort: %gint, encoding effort
2456 * * @lossless: %gboolean, enables lossless compression
2457 * * @Q: %gint, quality setting
2458 *
2459 * Write a VIPS image to a file in JPEG-XL format.
2460 *
2461 * The JPEG-XL loader and saver are experimental features and may change
2462 * in future libvips versions.
2463 *
2464 * @tier sets the overall decode speed the encoder will target. Minimum is 0
2465 * (highest quality), and maximum is 4 (lowest quality). Default is 0.
2466 *
2467 * @distance sets the target maximum encoding error. Minimum is 0
2468 * (highest quality), and maximum is 15 (lowest quality). Default is 1.0
2469 * (visually lossless).
2470 *
2471 * As a convenience, you can also use @Q to set @distance. @Q uses
2472 * approximately the same scale as regular JPEG.
2473 *
2474 * Set @lossless to enable lossless compresion.
2475 *
2476 * Returns: 0 on success, -1 on error.
2477 */
2478 int
vips_jxlsave(VipsImage * in,const char * filename,...)2479 vips_jxlsave( VipsImage *in, const char *filename, ... )
2480 {
2481 va_list ap;
2482 int result;
2483
2484 va_start( ap, filename );
2485 result = vips_call_split( "jxlsave", ap, in, filename );
2486 va_end( ap );
2487
2488 return( result );
2489 }
2490
2491 /**
2492 * vips_jxlsave_buffer: (method)
2493 * @in: image to save
2494 * @buf: (array length=len) (element-type guint8): return output buffer here
2495 * @len: (type gsize): return output length here
2496 * @...: %NULL-terminated list of optional named arguments
2497 *
2498 * Optional arguments:
2499 *
2500 * * @tier: %gint, decode speed tier
2501 * * @distance: %gdouble, maximum encoding error
2502 * * @effort: %gint, encoding effort
2503 * * @lossless: %gboolean, enables lossless compression
2504 * * @Q: %gint, quality setting
2505 *
2506 * As vips_jxlsave(), but save to a memory buffer.
2507 *
2508 * See also: vips_jxlsave(), vips_image_write_to_target().
2509 *
2510 * Returns: 0 on success, -1 on error.
2511 */
2512 int
vips_jxlsave_buffer(VipsImage * in,void ** buf,size_t * len,...)2513 vips_jxlsave_buffer( VipsImage *in, void **buf, size_t *len, ... )
2514 {
2515 va_list ap;
2516 VipsArea *area;
2517 int result;
2518
2519 area = NULL;
2520
2521 va_start( ap, len );
2522 result = vips_call_split( "jxlsave_buffer", ap, in, &area );
2523 va_end( ap );
2524
2525 if( !result &&
2526 area ) {
2527 if( buf ) {
2528 *buf = area->data;
2529 area->free_fn = NULL;
2530 }
2531 if( len )
2532 *len = area->length;
2533
2534 vips_area_unref( area );
2535 }
2536
2537 return( result );
2538 }
2539
2540 /**
2541 * vips_jxlsave_target: (method)
2542 * @in: image to save
2543 * @target: save image to this target
2544 * @...: %NULL-terminated list of optional named arguments
2545 *
2546 * Optional arguments:
2547 *
2548 * * @tier: %gint, decode speed tier
2549 * * @distance: %gdouble, maximum encoding error
2550 * * @effort: %gint, encoding effort
2551 * * @lossless: %gboolean, enables lossless compression
2552 * * @Q: %gint, quality setting
2553 *
2554 * As vips_jxlsave(), but save to a target.
2555 *
2556 * See also: vips_jxlsave(), vips_image_write_to_target().
2557 *
2558 * Returns: 0 on success, -1 on error.
2559 */
2560 int
vips_jxlsave_target(VipsImage * in,VipsTarget * target,...)2561 vips_jxlsave_target( VipsImage *in, VipsTarget *target, ... )
2562 {
2563 va_list ap;
2564 int result;
2565
2566 va_start( ap, target );
2567 result = vips_call_split( "jxlsave_target", ap, in, target );
2568 va_end( ap );
2569
2570 return( result );
2571 }
2572
2573 /**
2574 * vips_pdfload:
2575 * @filename: file to load
2576 * @out: (out): output image
2577 * @...: %NULL-terminated list of optional named arguments
2578 *
2579 * Optional arguments:
2580 *
2581 * * @page: %gint, load this page, numbered from zero
2582 * * @n: %gint, load this many pages
2583 * * @dpi: %gdouble, render at this DPI
2584 * * @scale: %gdouble, scale render by this factor
2585 * * @background: #VipsArrayDouble background colour
2586 *
2587 * Render a PDF file into a VIPS image.
2588 *
2589 * The output image is always RGBA --- CMYK PDFs will be
2590 * converted. If you need CMYK bitmaps, you should use vips_magickload()
2591 * instead.
2592 *
2593 * Use @page to select a page to render, numbering from zero.
2594 *
2595 * Use @n to select the number of pages to render. The default is 1. Pages are
2596 * rendered in a vertical column, with each individual page aligned to the
2597 * left. Set to -1 to mean "until the end of the document". Use vips_grid()
2598 * to change page layout.
2599 *
2600 * Use @dpi to set the rendering resolution. The default is 72. Additionally,
2601 * you can scale by setting @scale. If you set both, they combine.
2602 *
2603 * Use @background to set the background RGBA colour. The default is 255
2604 * (solid white), use eg. 0 for a transparent background.
2605 *
2606 * The operation fills a number of header fields with metadata, for example
2607 * "pdf-author". They may be useful.
2608 *
2609 * This function only reads the image header and does not render any pixel
2610 * data. Rendering occurs when pixels are accessed.
2611 *
2612 * See also: vips_image_new_from_file(), vips_magickload().
2613 *
2614 * Returns: 0 on success, -1 on error.
2615 */
2616 int
vips_pdfload(const char * filename,VipsImage ** out,...)2617 vips_pdfload( const char *filename, VipsImage **out, ... )
2618 {
2619 va_list ap;
2620 int result;
2621
2622 va_start( ap, out );
2623 result = vips_call_split( "pdfload", ap, filename, out );
2624 va_end( ap );
2625
2626 return( result );
2627 }
2628
2629 /**
2630 * vips_pdfload_buffer:
2631 * @buf: (array length=len) (element-type guint8): memory area to load
2632 * @len: (type gsize): size of memory area
2633 * @out: (out): image to write
2634 * @...: %NULL-terminated list of optional named arguments
2635 *
2636 * Optional arguments:
2637 *
2638 * * @page: %gint, load this page, numbered from zero
2639 * * @n: %gint, load this many pages
2640 * * @dpi: %gdouble, render at this DPI
2641 * * @scale: %gdouble, scale render by this factor
2642 * * @background: #VipsArrayDouble background colour
2643 *
2644 * Read a PDF-formatted memory buffer into a VIPS image. Exactly as
2645 * vips_pdfload(), but read from memory.
2646 *
2647 * You must not free the buffer while @out is active. The
2648 * #VipsObject::postclose signal on @out is a good place to free.
2649 *
2650 * See also: vips_pdfload().
2651 *
2652 * Returns: 0 on success, -1 on error.
2653 */
2654 int
vips_pdfload_buffer(void * buf,size_t len,VipsImage ** out,...)2655 vips_pdfload_buffer( void *buf, size_t len, VipsImage **out, ... )
2656 {
2657 va_list ap;
2658 VipsBlob *blob;
2659 int result;
2660
2661 /* We don't take a copy of the data or free it.
2662 */
2663 blob = vips_blob_new( NULL, buf, len );
2664
2665 va_start( ap, out );
2666 result = vips_call_split( "pdfload_buffer", ap, blob, out );
2667 va_end( ap );
2668
2669 vips_area_unref( VIPS_AREA( blob ) );
2670
2671 return( result );
2672 }
2673
2674 /**
2675 * vips_pdfload_source:
2676 * @source: source to load from
2677 * @out: (out): image to write
2678 * @...: %NULL-terminated list of optional named arguments
2679 *
2680 * Optional arguments:
2681 *
2682 * * @page: %gint, load this page, numbered from zero
2683 * * @n: %gint, load this many pages
2684 * * @dpi: %gdouble, render at this DPI
2685 * * @scale: %gdouble, scale render by this factor
2686 * * @background: #VipsArrayDouble background colour
2687 *
2688 * Exactly as vips_pdfload(), but read from a source.
2689 *
2690 * See also: vips_pdfload()
2691 *
2692 * Returns: 0 on success, -1 on error.
2693 */
2694 int
vips_pdfload_source(VipsSource * source,VipsImage ** out,...)2695 vips_pdfload_source( VipsSource *source, VipsImage **out, ... )
2696 {
2697 va_list ap;
2698 int result;
2699
2700 va_start( ap, out );
2701 result = vips_call_split( "pdfload_source", ap, source, out );
2702 va_end( ap );
2703
2704 return( result );
2705 }
2706
2707 /**
2708 * vips_openslideload:
2709 * @filename: file to load
2710 * @out: (out): decompressed image
2711 * @...: %NULL-terminated list of optional named arguments
2712 *
2713 * Optional arguments:
2714 *
2715 * * @level: %gint, load this level
2716 * * @associated: %gchararray, load this associated image
2717 * * @attach_associated: %gboolean, attach all associated images as metadata
2718 * * @autocrop: %gboolean, crop to image bounds
2719 *
2720 * Read a virtual slide supported by the OpenSlide library into a VIPS image.
2721 * OpenSlide supports images in Aperio, Hamamatsu, MIRAX, Sakura, Trestle,
2722 * and Ventana formats.
2723 *
2724 * To facilitate zooming, virtual slide formats include multiple scaled-down
2725 * versions of the high-resolution image. These are typically called
2726 * "levels". By default, vips_openslideload() reads the highest-resolution
2727 * level (level 0). Set @level to the level number you want.
2728 *
2729 * In addition to the slide image itself, virtual slide formats sometimes
2730 * include additional images, such as a scan of the slide's barcode.
2731 * OpenSlide calls these "associated images". To read an associated image,
2732 * set @associated to the image's name.
2733 * A slide's associated images are listed in the
2734 * "slide-associated-images" metadata item.
2735 *
2736 * If you set @attach_associated, then all associated images are attached as
2737 * metadata items. Use vips_image_get_image() on @out to retrieve them. Images
2738 * are attached as "openslide-associated-XXXXX", where XXXXX is the name of the
2739 * associated image.
2740 *
2741 * The output of this operator is always RGBA.
2742 *
2743 * See also: vips_image_new_from_file().
2744 *
2745 * Returns: 0 on success, -1 on error.
2746 */
2747 int
vips_openslideload(const char * filename,VipsImage ** out,...)2748 vips_openslideload( const char *filename, VipsImage **out, ... )
2749 {
2750 va_list ap;
2751 int result;
2752
2753 va_start( ap, out );
2754 result = vips_call_split( "openslideload", ap, filename, out );
2755 va_end( ap );
2756
2757 return( result );
2758 }
2759
2760 /**
2761 * vips_openslideload_source:
2762 * @source: source to load from
2763 * @out: (out): decompressed image
2764 * @...: %NULL-terminated list of optional named arguments
2765 *
2766 * Optional arguments:
2767 *
2768 * * @level: %gint, load this level
2769 * * @associated: %gchararray, load this associated image
2770 * * @attach_associated: %gboolean, attach all associated images as metadata
2771 * * @autocrop: %gboolean, crop to image bounds
2772 *
2773 * Exactly as vips_openslideload(), but read from a source.
2774 *
2775 * Returns: 0 on success, -1 on error.
2776 */
2777 int
vips_openslideload_source(VipsSource * source,VipsImage ** out,...)2778 vips_openslideload_source( VipsSource *source, VipsImage **out, ... )
2779 {
2780 va_list ap;
2781 int result;
2782
2783 va_start( ap, out );
2784 result = vips_call_split( "openslideload_source", ap, source, out );
2785 va_end( ap );
2786
2787 return( result );
2788 }
2789
2790 /* Called from iofuncs to init all operations in this dir. Use a plugin system
2791 * instead?
2792 */
2793 void
vips_foreign_operation_init(void)2794 vips_foreign_operation_init( void )
2795 {
2796 extern GType vips_foreign_load_rad_file_get_type( void );
2797 extern GType vips_foreign_load_rad_buffer_get_type( void );
2798 extern GType vips_foreign_load_rad_source_get_type( void );
2799 extern GType vips_foreign_save_rad_file_get_type( void );
2800 extern GType vips_foreign_save_rad_buffer_get_type( void );
2801 extern GType vips_foreign_save_rad_target_get_type( void );
2802
2803 extern GType vips_foreign_load_mat_get_type( void );
2804
2805 extern GType vips_foreign_load_ppm_file_get_type( void );
2806 extern GType vips_foreign_load_ppm_source_get_type( void );
2807 extern GType vips_foreign_save_ppm_file_get_type( void );
2808 extern GType vips_foreign_save_pbm_target_get_type( void );
2809 extern GType vips_foreign_save_pgm_target_get_type( void );
2810 extern GType vips_foreign_save_ppm_target_get_type( void );
2811 extern GType vips_foreign_save_pfm_target_get_type( void );
2812
2813 extern GType vips_foreign_load_png_file_get_type( void );
2814 extern GType vips_foreign_load_png_buffer_get_type( void );
2815 extern GType vips_foreign_load_png_source_get_type( void );
2816 extern GType vips_foreign_save_png_file_get_type( void );
2817 extern GType vips_foreign_save_png_buffer_get_type( void );
2818 extern GType vips_foreign_save_png_target_get_type( void );
2819
2820 extern GType vips_foreign_load_csv_file_get_type( void );
2821 extern GType vips_foreign_load_csv_source_get_type( void );
2822 extern GType vips_foreign_save_csv_file_get_type( void );
2823 extern GType vips_foreign_save_csv_target_get_type( void );
2824
2825 extern GType vips_foreign_load_matrix_file_get_type( void );
2826 extern GType vips_foreign_load_matrix_source_get_type( void );
2827 extern GType vips_foreign_save_matrix_file_get_type( void );
2828 extern GType vips_foreign_save_matrix_target_get_type( void );
2829 extern GType vips_foreign_print_matrix_get_type( void );
2830
2831 extern GType vips_foreign_load_fits_file_get_type( void );
2832 extern GType vips_foreign_load_fits_source_get_type( void );
2833 extern GType vips_foreign_save_fits_get_type( void );
2834
2835 extern GType vips_foreign_load_analyze_get_type( void );
2836
2837 extern GType vips_foreign_load_openexr_get_type( void );
2838
2839 extern GType vips_foreign_load_openslide_file_get_type( void );
2840 extern GType vips_foreign_load_openslide_source_get_type( void );
2841
2842 extern GType vips_foreign_load_vips_file_get_type( void );
2843 extern GType vips_foreign_load_vips_source_get_type( void );
2844 extern GType vips_foreign_save_vips_file_get_type( void );
2845 extern GType vips_foreign_save_vips_target_get_type( void );
2846
2847 extern GType vips_foreign_load_jpeg_file_get_type( void );
2848 extern GType vips_foreign_load_jpeg_buffer_get_type( void );
2849 extern GType vips_foreign_load_jpeg_source_get_type( void );
2850 extern GType vips_foreign_save_jpeg_file_get_type( void );
2851 extern GType vips_foreign_save_jpeg_buffer_get_type( void );
2852 extern GType vips_foreign_save_jpeg_target_get_type( void );
2853 extern GType vips_foreign_save_jpeg_mime_get_type( void );
2854
2855 extern GType vips_foreign_load_tiff_file_get_type( void );
2856 extern GType vips_foreign_load_tiff_buffer_get_type( void );
2857 extern GType vips_foreign_load_tiff_source_get_type( void );
2858 extern GType vips_foreign_save_tiff_file_get_type( void );
2859 extern GType vips_foreign_save_tiff_buffer_get_type( void );
2860
2861 extern GType vips_foreign_load_raw_get_type( void );
2862 extern GType vips_foreign_save_raw_get_type( void );
2863 extern GType vips_foreign_save_raw_fd_get_type( void );
2864
2865 extern GType vips_foreign_load_magick_file_get_type( void );
2866 extern GType vips_foreign_load_magick_buffer_get_type( void );
2867 extern GType vips_foreign_load_magick7_file_get_type( void );
2868 extern GType vips_foreign_load_magick7_buffer_get_type( void );
2869 extern GType vips_foreign_save_magick_file_get_type( void );
2870 extern GType vips_foreign_save_magick_bmp_file_get_type( void );
2871 extern GType vips_foreign_save_magick_buffer_get_type( void );
2872 extern GType vips_foreign_save_magick_bmp_buffer_get_type( void );
2873
2874 extern GType vips_foreign_save_dz_file_get_type( void );
2875 extern GType vips_foreign_save_dz_buffer_get_type( void );
2876
2877 extern GType vips_foreign_load_webp_file_get_type( void );
2878 extern GType vips_foreign_load_webp_buffer_get_type( void );
2879 extern GType vips_foreign_load_webp_source_get_type( void );
2880 extern GType vips_foreign_save_webp_file_get_type( void );
2881 extern GType vips_foreign_save_webp_buffer_get_type( void );
2882 extern GType vips_foreign_save_webp_target_get_type( void );
2883
2884 extern GType vips_foreign_load_pdf_file_get_type( void );
2885 extern GType vips_foreign_load_pdf_buffer_get_type( void );
2886 extern GType vips_foreign_load_pdf_source_get_type( void );
2887
2888 extern GType vips_foreign_load_svg_file_get_type( void );
2889 extern GType vips_foreign_load_svg_buffer_get_type( void );
2890 extern GType vips_foreign_load_svg_source_get_type( void );
2891
2892 extern GType vips_foreign_load_jp2k_file_get_type( void );
2893 extern GType vips_foreign_load_jp2k_buffer_get_type( void );
2894 extern GType vips_foreign_load_jp2k_source_get_type( void );
2895 extern GType vips_foreign_save_jp2k_file_get_type( void );
2896 extern GType vips_foreign_save_jp2k_buffer_get_type( void );
2897 extern GType vips_foreign_save_jp2k_target_get_type( void );
2898
2899 extern GType vips_foreign_load_jxl_file_get_type( void );
2900 extern GType vips_foreign_load_jxl_buffer_get_type( void );
2901 extern GType vips_foreign_load_jxl_source_get_type( void );
2902 extern GType vips_foreign_save_jxl_file_get_type( void );
2903 extern GType vips_foreign_save_jxl_buffer_get_type( void );
2904 extern GType vips_foreign_save_jxl_target_get_type( void );
2905
2906 extern GType vips_foreign_load_heif_file_get_type( void );
2907 extern GType vips_foreign_load_heif_buffer_get_type( void );
2908 extern GType vips_foreign_load_heif_source_get_type( void );
2909 extern GType vips_foreign_save_heif_file_get_type( void );
2910 extern GType vips_foreign_save_heif_buffer_get_type( void );
2911 extern GType vips_foreign_save_heif_target_get_type( void );
2912 extern GType vips_foreign_save_avif_target_get_type( void );
2913
2914 extern GType vips_foreign_load_nifti_file_get_type( void );
2915 extern GType vips_foreign_load_nifti_source_get_type( void );
2916 extern GType vips_foreign_save_nifti_get_type( void );
2917
2918 extern GType vips_foreign_load_nsgif_file_get_type( void );
2919 extern GType vips_foreign_load_nsgif_buffer_get_type( void );
2920 extern GType vips_foreign_load_nsgif_source_get_type( void );
2921
2922 extern GType vips_foreign_save_cgif_file_get_type( void );
2923 extern GType vips_foreign_save_cgif_buffer_get_type( void );
2924 extern GType vips_foreign_save_cgif_target_get_type( void );
2925
2926 vips_foreign_load_csv_file_get_type();
2927 vips_foreign_load_csv_source_get_type();
2928 vips_foreign_save_csv_file_get_type();
2929 vips_foreign_save_csv_target_get_type();
2930
2931 vips_foreign_load_matrix_file_get_type();
2932 vips_foreign_load_matrix_source_get_type();
2933 vips_foreign_save_matrix_file_get_type();
2934 vips_foreign_save_matrix_target_get_type();
2935 vips_foreign_print_matrix_get_type();
2936
2937 vips_foreign_load_raw_get_type();
2938 vips_foreign_save_raw_get_type();
2939 vips_foreign_save_raw_fd_get_type();
2940
2941 vips_foreign_load_vips_file_get_type();
2942 vips_foreign_load_vips_source_get_type();
2943 vips_foreign_save_vips_file_get_type();
2944 vips_foreign_save_vips_target_get_type();
2945
2946 #ifdef HAVE_ANALYZE
2947 vips_foreign_load_analyze_get_type();
2948 #endif /*HAVE_ANALYZE*/
2949
2950 #ifdef HAVE_PPM
2951 vips_foreign_load_ppm_file_get_type();
2952 vips_foreign_load_ppm_source_get_type();
2953 vips_foreign_save_ppm_file_get_type();
2954 vips_foreign_save_pbm_target_get_type();
2955 vips_foreign_save_pgm_target_get_type();
2956 vips_foreign_save_ppm_target_get_type();
2957 vips_foreign_save_pfm_target_get_type();
2958 #endif /*HAVE_PPM*/
2959
2960 #ifdef HAVE_RADIANCE
2961 vips_foreign_load_rad_file_get_type();
2962 vips_foreign_load_rad_buffer_get_type();
2963 vips_foreign_load_rad_source_get_type();
2964 vips_foreign_save_rad_file_get_type();
2965 vips_foreign_save_rad_buffer_get_type();
2966 vips_foreign_save_rad_target_get_type();
2967 #endif /*HAVE_RADIANCE*/
2968
2969 #if defined(HAVE_POPPLER) && !defined(POPPLER_MODULE)
2970 vips_foreign_load_pdf_file_get_type();
2971 vips_foreign_load_pdf_buffer_get_type();
2972 vips_foreign_load_pdf_source_get_type();
2973 #endif /*defined(HAVE_POPPLER) && !defined(POPPLER_MODULE)*/
2974
2975 #ifdef HAVE_PDFIUM
2976 vips_foreign_load_pdf_file_get_type();
2977 vips_foreign_load_pdf_buffer_get_type();
2978 vips_foreign_load_pdf_source_get_type();
2979 #endif /*HAVE_PDFIUM*/
2980
2981 #ifdef HAVE_RSVG
2982 vips_foreign_load_svg_file_get_type();
2983 vips_foreign_load_svg_buffer_get_type();
2984 vips_foreign_load_svg_source_get_type();
2985 #endif /*HAVE_RSVG*/
2986
2987 #if defined(HAVE_LIBJXL) && !defined(LIBJXL_MODULE)
2988 vips_foreign_load_jxl_file_get_type();
2989 vips_foreign_load_jxl_buffer_get_type();
2990 vips_foreign_load_jxl_source_get_type();
2991 vips_foreign_save_jxl_file_get_type();
2992 vips_foreign_save_jxl_buffer_get_type();
2993 vips_foreign_save_jxl_target_get_type();
2994 #endif /*defined(HAVE_LIBJXL) && !defined(LIBJXL_MODULE)*/
2995
2996 #ifdef HAVE_LIBOPENJP2
2997 vips_foreign_load_jp2k_file_get_type();
2998 vips_foreign_load_jp2k_buffer_get_type();
2999 vips_foreign_load_jp2k_source_get_type();
3000 vips_foreign_save_jp2k_file_get_type();
3001 vips_foreign_save_jp2k_buffer_get_type();
3002 vips_foreign_save_jp2k_target_get_type();
3003 #endif /*HAVE_LIBOPENJP2*/
3004
3005 #ifdef HAVE_NSGIF
3006 vips_foreign_load_nsgif_file_get_type();
3007 vips_foreign_load_nsgif_buffer_get_type();
3008 vips_foreign_load_nsgif_source_get_type();
3009 #endif /*HAVE_NSGIF*/
3010
3011 #ifdef HAVE_CGIF
3012 vips_foreign_save_cgif_file_get_type();
3013 vips_foreign_save_cgif_buffer_get_type();
3014 vips_foreign_save_cgif_target_get_type();
3015 #endif /*HAVE_CGIF*/
3016
3017 #ifdef HAVE_GSF
3018 vips_foreign_save_dz_file_get_type();
3019 vips_foreign_save_dz_buffer_get_type();
3020 #endif /*HAVE_GSF*/
3021
3022 #ifdef HAVE_PNG
3023 vips_foreign_load_png_file_get_type();
3024 vips_foreign_load_png_buffer_get_type();
3025 vips_foreign_load_png_source_get_type();
3026 vips_foreign_save_png_file_get_type();
3027 vips_foreign_save_png_buffer_get_type();
3028 vips_foreign_save_png_target_get_type();
3029 #endif /*HAVE_PNG*/
3030
3031 #ifdef HAVE_SPNG
3032 vips_foreign_load_png_file_get_type();
3033 vips_foreign_load_png_buffer_get_type();
3034 vips_foreign_load_png_source_get_type();
3035 #endif /*HAVE_SPNG*/
3036
3037 #ifdef HAVE_MATIO
3038 vips_foreign_load_mat_get_type();
3039 #endif /*HAVE_MATIO*/
3040
3041 #ifdef HAVE_JPEG
3042 vips_foreign_load_jpeg_file_get_type();
3043 vips_foreign_load_jpeg_buffer_get_type();
3044 vips_foreign_load_jpeg_source_get_type();
3045 vips_foreign_save_jpeg_file_get_type();
3046 vips_foreign_save_jpeg_buffer_get_type();
3047 vips_foreign_save_jpeg_target_get_type();
3048 vips_foreign_save_jpeg_mime_get_type();
3049 #endif /*HAVE_JPEG*/
3050
3051 #ifdef HAVE_LIBWEBP
3052 vips_foreign_load_webp_file_get_type();
3053 vips_foreign_load_webp_buffer_get_type();
3054 vips_foreign_load_webp_source_get_type();
3055 vips_foreign_save_webp_file_get_type();
3056 vips_foreign_save_webp_buffer_get_type();
3057 vips_foreign_save_webp_target_get_type();
3058 #endif /*HAVE_LIBWEBP*/
3059
3060 #ifdef HAVE_TIFF
3061 vips_foreign_load_tiff_file_get_type();
3062 vips_foreign_load_tiff_buffer_get_type();
3063 vips_foreign_load_tiff_source_get_type();
3064 vips_foreign_save_tiff_file_get_type();
3065 vips_foreign_save_tiff_buffer_get_type();
3066 #endif /*HAVE_TIFF*/
3067
3068 #if defined(HAVE_OPENSLIDE) && !defined(OPENSLIDE_MODULE)
3069 vips_foreign_load_openslide_file_get_type();
3070 vips_foreign_load_openslide_source_get_type();
3071 #endif /*defined(HAVE_OPENSLIDE) && !defined(OPENSLIDE_MODULE)*/
3072
3073 #if defined(ENABLE_MAGICKLOAD) && !defined(MAGICK_MODULE)
3074 #ifdef HAVE_MAGICK6
3075 vips_foreign_load_magick_file_get_type();
3076 vips_foreign_load_magick_buffer_get_type();
3077 #endif /*HAVE_MAGICK6*/
3078
3079 #ifdef HAVE_MAGICK7
3080 vips_foreign_load_magick7_file_get_type();
3081 vips_foreign_load_magick7_buffer_get_type();
3082 #endif /*HAVE_MAGICK7*/
3083 #endif /*defined(ENABLE_MAGICKLOAD) && !defined(MAGICK_MODULE)*/
3084
3085 #if defined(ENABLE_MAGICKSAVE) && !defined(MAGICK_MODULE)
3086 vips_foreign_save_magick_file_get_type();
3087 vips_foreign_save_magick_bmp_file_get_type();
3088 vips_foreign_save_magick_buffer_get_type();
3089 vips_foreign_save_magick_bmp_buffer_get_type();
3090 #endif /*defined(ENABLE_MAGICKSAVE) && !defined(MAGICK_MODULE)*/
3091
3092 #ifdef HAVE_CFITSIO
3093 vips_foreign_load_fits_file_get_type();
3094 vips_foreign_load_fits_source_get_type();
3095 vips_foreign_save_fits_get_type();
3096 #endif /*HAVE_CFITSIO*/
3097
3098 #ifdef HAVE_OPENEXR
3099 vips_foreign_load_openexr_get_type();
3100 #endif /*HAVE_OPENEXR*/
3101
3102 #ifdef HAVE_NIFTI
3103 vips_foreign_load_nifti_file_get_type();
3104 vips_foreign_load_nifti_source_get_type();
3105 vips_foreign_save_nifti_get_type();
3106 #endif /*HAVE_NIFTI*/
3107
3108 #if defined(HAVE_HEIF_DECODER) && !defined(HEIF_MODULE)
3109 vips_foreign_load_heif_file_get_type();
3110 vips_foreign_load_heif_buffer_get_type();
3111 vips_foreign_load_heif_source_get_type();
3112 #endif /*defined(HAVE_HEIF_DECODER) && !defined(HEIF_MODULE)*/
3113
3114 #if defined(HAVE_HEIF_ENCODER) && !defined(HEIF_MODULE)
3115 vips_foreign_save_heif_file_get_type();
3116 vips_foreign_save_heif_buffer_get_type();
3117 vips_foreign_save_heif_target_get_type();
3118 vips_foreign_save_avif_target_get_type();
3119 #endif /*defined(HAVE_HEIF_ENCODER) && !defined(HEIF_MODULE)*/
3120
3121 vips__foreign_load_operation =
3122 g_quark_from_static_string( "vips-foreign-load-operation" );
3123 }
3124