/src/libvips/libvips/foreign/jpegload.c
Line | Count | Source |
1 | | /* load jpeg from a file |
2 | | * |
3 | | * 24/11/11 |
4 | | * - wrap a class around the jpeg writer |
5 | | * 29/11/11 |
6 | | * - split to make load, load from buffer and load from file |
7 | | * 24/7/21 |
8 | | * - add fail_on support |
9 | | */ |
10 | | |
11 | | /* |
12 | | |
13 | | This file is part of VIPS. |
14 | | |
15 | | VIPS is free software; you can redistribute it and/or modify |
16 | | it under the terms of the GNU Lesser General Public License as published by |
17 | | the Free Software Foundation; either version 2 of the License, or |
18 | | (at your option) any later version. |
19 | | |
20 | | This program is distributed in the hope that it will be useful, |
21 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | | GNU Lesser General Public License for more details. |
24 | | |
25 | | You should have received a copy of the GNU Lesser General Public License |
26 | | along with this program; if not, write to the Free Software |
27 | | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
28 | | 02110-1301 USA |
29 | | |
30 | | */ |
31 | | |
32 | | /* |
33 | | |
34 | | These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk |
35 | | |
36 | | */ |
37 | | |
38 | | #ifdef HAVE_CONFIG_H |
39 | | #include <config.h> |
40 | | #endif /*HAVE_CONFIG_H*/ |
41 | | #include <glib/gi18n-lib.h> |
42 | | |
43 | | #include <stdio.h> |
44 | | #include <stdlib.h> |
45 | | #include <string.h> |
46 | | #include <setjmp.h> |
47 | | |
48 | | #include <vips/vips.h> |
49 | | #include <vips/buf.h> |
50 | | #include <vips/internal.h> |
51 | | |
52 | | #include "pforeign.h" |
53 | | |
54 | | #ifdef HAVE_JPEG |
55 | | |
56 | | #ifdef HAVE_EXIF |
57 | | #ifdef UNTAGGED_EXIF |
58 | | #include <exif-data.h> |
59 | | #include <exif-loader.h> |
60 | | #include <exif-ifd.h> |
61 | | #include <exif-utils.h> |
62 | | #else /*!UNTAGGED_EXIF*/ |
63 | | #include <libexif/exif-data.h> |
64 | | #include <libexif/exif-loader.h> |
65 | | #include <libexif/exif-ifd.h> |
66 | | #include <libexif/exif-utils.h> |
67 | | #endif /*UNTAGGED_EXIF*/ |
68 | | #endif /*HAVE_EXIF*/ |
69 | | |
70 | | typedef struct _VipsForeignLoadJpeg { |
71 | | VipsForeignLoad parent_object; |
72 | | |
73 | | /* Set by subclasses. |
74 | | */ |
75 | | VipsSource *source; |
76 | | |
77 | | /* Remove DoS limits. |
78 | | */ |
79 | | gboolean unlimited; |
80 | | |
81 | | /* Shrink by this much during load. |
82 | | */ |
83 | | int shrink; |
84 | | |
85 | | /* Autorotate using exif orientation tag. |
86 | | */ |
87 | | gboolean autorotate; |
88 | | |
89 | | } VipsForeignLoadJpeg; |
90 | | |
91 | | typedef VipsForeignLoadClass VipsForeignLoadJpegClass; |
92 | | |
93 | 117 | G_DEFINE_ABSTRACT_TYPE(VipsForeignLoadJpeg, vips_foreign_load_jpeg, |
94 | 117 | VIPS_TYPE_FOREIGN_LOAD); |
95 | 117 | |
96 | 117 | static void |
97 | 117 | vips_foreign_load_jpeg_dispose(GObject *gobject) |
98 | 75.3k | { |
99 | 75.3k | VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) gobject; |
100 | | |
101 | 75.3k | VIPS_UNREF(jpeg->source); |
102 | | |
103 | 75.3k | G_OBJECT_CLASS(vips_foreign_load_jpeg_parent_class)->dispose(gobject); |
104 | 75.3k | } |
105 | | |
106 | | static int |
107 | | vips_foreign_load_jpeg_build(VipsObject *object) |
108 | 75.3k | { |
109 | 75.3k | VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) object; |
110 | | |
111 | 75.3k | if (jpeg->shrink != 1 && |
112 | 769 | jpeg->shrink != 2 && |
113 | 292 | jpeg->shrink != 4 && |
114 | 259 | jpeg->shrink != 8) { |
115 | 1 | vips_error("VipsFormatLoadJpeg", |
116 | 1 | _("bad shrink factor %d"), jpeg->shrink); |
117 | 1 | return -1; |
118 | 1 | } |
119 | | |
120 | 75.3k | return VIPS_OBJECT_CLASS(vips_foreign_load_jpeg_parent_class) |
121 | 75.3k | ->build(object); |
122 | 75.3k | } |
123 | | |
124 | | static VipsForeignFlags |
125 | | vips_foreign_load_jpeg_get_flags(VipsForeignLoad *load) |
126 | 75.3k | { |
127 | 75.3k | return VIPS_FOREIGN_SEQUENTIAL; |
128 | 75.3k | } |
129 | | |
130 | | static VipsForeignFlags |
131 | | vips_foreign_load_jpeg_get_flags_filename(const char *filename) |
132 | 0 | { |
133 | 0 | return VIPS_FOREIGN_SEQUENTIAL; |
134 | 0 | } |
135 | | |
136 | | static int |
137 | | vips_foreign_load_jpeg_header(VipsForeignLoad *load) |
138 | 75.3k | { |
139 | 75.3k | VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) load; |
140 | | |
141 | 75.3k | if (vips__jpeg_read_source(jpeg->source, |
142 | 75.3k | load->out, TRUE, jpeg->shrink, load->fail_on, |
143 | 75.3k | jpeg->autorotate, jpeg->unlimited)) |
144 | 8.43k | return -1; |
145 | | |
146 | 66.8k | return 0; |
147 | 75.3k | } |
148 | | |
149 | | static int |
150 | | vips_foreign_load_jpeg_load(VipsForeignLoad *load) |
151 | 56.0k | { |
152 | 56.0k | VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) load; |
153 | | |
154 | 56.0k | if (vips__jpeg_read_source(jpeg->source, |
155 | 56.0k | load->real, FALSE, jpeg->shrink, load->fail_on, |
156 | 56.0k | jpeg->autorotate, jpeg->unlimited)) |
157 | 35.8k | return -1; |
158 | | |
159 | 20.1k | return 0; |
160 | 56.0k | } |
161 | | |
162 | | static void |
163 | | vips_foreign_load_jpeg_class_init(VipsForeignLoadJpegClass *class) |
164 | 19 | { |
165 | 19 | GObjectClass *gobject_class = G_OBJECT_CLASS(class); |
166 | 19 | VipsObjectClass *object_class = (VipsObjectClass *) class; |
167 | 19 | VipsForeignClass *foreign_class = (VipsForeignClass *) class; |
168 | 19 | VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; |
169 | | |
170 | 19 | gobject_class->dispose = vips_foreign_load_jpeg_dispose; |
171 | 19 | gobject_class->set_property = vips_object_set_property; |
172 | 19 | gobject_class->get_property = vips_object_get_property; |
173 | | |
174 | 19 | object_class->nickname = "jpegload_base"; |
175 | 19 | object_class->description = _("load jpeg"); |
176 | 19 | object_class->build = vips_foreign_load_jpeg_build; |
177 | | |
178 | | /* We are fast at is_a(), so high priority. |
179 | | */ |
180 | 19 | foreign_class->priority = 150; |
181 | | |
182 | 19 | load_class->get_flags_filename = vips_foreign_load_jpeg_get_flags_filename; |
183 | 19 | load_class->get_flags = vips_foreign_load_jpeg_get_flags; |
184 | 19 | load_class->header = vips_foreign_load_jpeg_header; |
185 | 19 | load_class->load = vips_foreign_load_jpeg_load; |
186 | | |
187 | 19 | VIPS_ARG_INT(class, "shrink", 20, |
188 | 19 | _("Shrink"), |
189 | 19 | _("Shrink factor on load"), |
190 | 19 | VIPS_ARGUMENT_OPTIONAL_INPUT, |
191 | 19 | G_STRUCT_OFFSET(VipsForeignLoadJpeg, shrink), |
192 | 19 | 1, 8, 1); |
193 | | |
194 | 19 | VIPS_ARG_BOOL(class, "autorotate", 21, |
195 | 19 | _("Autorotate"), |
196 | 19 | _("Rotate image using exif orientation"), |
197 | 19 | VIPS_ARGUMENT_OPTIONAL_INPUT, |
198 | 19 | G_STRUCT_OFFSET(VipsForeignLoadJpeg, autorotate), |
199 | 19 | FALSE); |
200 | | |
201 | | #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION |
202 | | VIPS_ARG_BOOL(class, "unlimited", 22, |
203 | | _("Unlimited"), |
204 | | _("Remove all denial of service limits"), |
205 | | VIPS_ARGUMENT_OPTIONAL_INPUT, |
206 | | G_STRUCT_OFFSET(VipsForeignLoadJpeg, unlimited), |
207 | | FALSE); |
208 | | #endif |
209 | 19 | } |
210 | | |
211 | | static void |
212 | | vips_foreign_load_jpeg_init(VipsForeignLoadJpeg *jpeg) |
213 | 75.4k | { |
214 | 75.4k | jpeg->shrink = 1; |
215 | 75.4k | jpeg->unlimited = vips_unlimited_get(); |
216 | 75.4k | } |
217 | | |
218 | | typedef struct _VipsForeignLoadJpegSource { |
219 | | VipsForeignLoadJpeg parent_object; |
220 | | |
221 | | VipsSource *source; |
222 | | |
223 | | } VipsForeignLoadJpegSource; |
224 | | |
225 | | typedef VipsForeignLoadJpegClass VipsForeignLoadJpegSourceClass; |
226 | | |
227 | 39 | G_DEFINE_TYPE(VipsForeignLoadJpegSource, vips_foreign_load_jpeg_source, |
228 | 39 | vips_foreign_load_jpeg_get_type()); |
229 | 39 | |
230 | 39 | static int |
231 | 39 | vips_foreign_load_jpeg_source_build(VipsObject *object) |
232 | 805 | { |
233 | 805 | VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) object; |
234 | 805 | VipsForeignLoadJpegSource *source = (VipsForeignLoadJpegSource *) object; |
235 | | |
236 | 805 | if (source->source) { |
237 | 805 | jpeg->source = source->source; |
238 | 805 | g_object_ref(jpeg->source); |
239 | 805 | } |
240 | | |
241 | 805 | return VIPS_OBJECT_CLASS(vips_foreign_load_jpeg_source_parent_class) |
242 | 805 | ->build(object); |
243 | 805 | } |
244 | | |
245 | | static gboolean |
246 | | vips_foreign_load_jpeg_source_is_a_source(VipsSource *source) |
247 | 475k | { |
248 | 475k | return vips__isjpeg_source(source); |
249 | 475k | } |
250 | | |
251 | | static void |
252 | | vips_foreign_load_jpeg_source_class_init( |
253 | | VipsForeignLoadJpegSourceClass *class) |
254 | 19 | { |
255 | 19 | GObjectClass *gobject_class = G_OBJECT_CLASS(class); |
256 | 19 | VipsObjectClass *object_class = (VipsObjectClass *) class; |
257 | 19 | VipsOperationClass *operation_class = VIPS_OPERATION_CLASS(class); |
258 | 19 | VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; |
259 | | |
260 | 19 | gobject_class->set_property = vips_object_set_property; |
261 | 19 | gobject_class->get_property = vips_object_get_property; |
262 | | |
263 | 19 | object_class->nickname = "jpegload_source"; |
264 | 19 | object_class->description = _("load image from jpeg source"); |
265 | 19 | object_class->build = vips_foreign_load_jpeg_source_build; |
266 | | |
267 | 19 | operation_class->flags |= VIPS_OPERATION_NOCACHE; |
268 | | |
269 | 19 | load_class->is_a_source = vips_foreign_load_jpeg_source_is_a_source; |
270 | | |
271 | 19 | VIPS_ARG_OBJECT(class, "source", 1, |
272 | 19 | _("Source"), |
273 | 19 | _("Source to load from"), |
274 | 19 | VIPS_ARGUMENT_REQUIRED_INPUT, |
275 | 19 | G_STRUCT_OFFSET(VipsForeignLoadJpegSource, source), |
276 | 19 | VIPS_TYPE_SOURCE); |
277 | 19 | } |
278 | | |
279 | | static void |
280 | | vips_foreign_load_jpeg_source_init(VipsForeignLoadJpegSource *source) |
281 | 873 | { |
282 | 873 | } |
283 | | |
284 | | typedef struct _VipsForeignLoadJpegFile { |
285 | | VipsForeignLoadJpeg parent_object; |
286 | | |
287 | | char *filename; |
288 | | |
289 | | } VipsForeignLoadJpegFile; |
290 | | |
291 | | typedef VipsForeignLoadJpegClass VipsForeignLoadJpegFileClass; |
292 | | |
293 | 39 | G_DEFINE_TYPE(VipsForeignLoadJpegFile, vips_foreign_load_jpeg_file, |
294 | 39 | vips_foreign_load_jpeg_get_type()); |
295 | 39 | |
296 | 39 | static int |
297 | 39 | vips_foreign_load_jpeg_file_build(VipsObject *object) |
298 | 5.55k | { |
299 | 5.55k | VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) object; |
300 | 5.55k | VipsForeignLoadJpegFile *file = (VipsForeignLoadJpegFile *) object; |
301 | | |
302 | 5.55k | if (file->filename && |
303 | 5.55k | !(jpeg->source = vips_source_new_from_file(file->filename))) |
304 | 0 | return -1; |
305 | | |
306 | 5.55k | return VIPS_OBJECT_CLASS(vips_foreign_load_jpeg_file_parent_class) |
307 | 5.55k | ->build(object); |
308 | 5.55k | } |
309 | | |
310 | | static gboolean |
311 | | vips_foreign_load_jpeg_file_is_a(const char *filename) |
312 | 38.4k | { |
313 | 38.4k | VipsSource *source; |
314 | | |
315 | 38.4k | if (!(source = vips_source_new_from_file(filename))) |
316 | 0 | return FALSE; |
317 | 38.4k | gboolean is_a = vips_foreign_load_jpeg_source_is_a_source(source); |
318 | 38.4k | VIPS_UNREF(source); |
319 | | |
320 | 38.4k | return is_a; |
321 | 38.4k | } |
322 | | |
323 | | static void |
324 | | vips_foreign_load_jpeg_file_class_init(VipsForeignLoadJpegFileClass *class) |
325 | 19 | { |
326 | 19 | GObjectClass *gobject_class = G_OBJECT_CLASS(class); |
327 | 19 | VipsObjectClass *object_class = (VipsObjectClass *) class; |
328 | 19 | VipsForeignClass *foreign_class = (VipsForeignClass *) class; |
329 | 19 | VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; |
330 | | |
331 | 19 | gobject_class->set_property = vips_object_set_property; |
332 | 19 | gobject_class->get_property = vips_object_get_property; |
333 | | |
334 | 19 | object_class->nickname = "jpegload"; |
335 | 19 | object_class->description = _("load jpeg from file"); |
336 | 19 | object_class->build = vips_foreign_load_jpeg_file_build; |
337 | | |
338 | 19 | foreign_class->suffs = vips__jpeg_suffs; |
339 | | |
340 | 19 | load_class->is_a = vips_foreign_load_jpeg_file_is_a; |
341 | | |
342 | 19 | VIPS_ARG_STRING(class, "filename", 1, |
343 | 19 | _("Filename"), |
344 | 19 | _("Filename to load from"), |
345 | 19 | VIPS_ARGUMENT_REQUIRED_INPUT, |
346 | 19 | G_STRUCT_OFFSET(VipsForeignLoadJpegFile, filename), |
347 | 19 | NULL); |
348 | 19 | } |
349 | | |
350 | | static void |
351 | | vips_foreign_load_jpeg_file_init(VipsForeignLoadJpegFile *file) |
352 | 5.55k | { |
353 | 5.55k | } |
354 | | |
355 | | typedef struct _VipsForeignLoadJpegBuffer { |
356 | | VipsForeignLoadJpeg parent_object; |
357 | | |
358 | | VipsBlob *blob; |
359 | | |
360 | | } VipsForeignLoadJpegBuffer; |
361 | | |
362 | | typedef VipsForeignLoadJpegClass VipsForeignLoadJpegBufferClass; |
363 | | |
364 | 39 | G_DEFINE_TYPE(VipsForeignLoadJpegBuffer, vips_foreign_load_jpeg_buffer, |
365 | 39 | vips_foreign_load_jpeg_get_type()); |
366 | 39 | |
367 | 39 | static int |
368 | 39 | vips_foreign_load_jpeg_buffer_build(VipsObject *object) |
369 | 68.9k | { |
370 | 68.9k | VipsForeignLoadJpeg *jpeg = (VipsForeignLoadJpeg *) object; |
371 | 68.9k | VipsForeignLoadJpegBuffer *buffer = (VipsForeignLoadJpegBuffer *) object; |
372 | | |
373 | 68.9k | if (buffer->blob && |
374 | 68.9k | !(jpeg->source = vips_source_new_from_memory( |
375 | 68.9k | VIPS_AREA(buffer->blob)->data, |
376 | 68.9k | VIPS_AREA(buffer->blob)->length))) |
377 | 0 | return -1; |
378 | | |
379 | 68.9k | return VIPS_OBJECT_CLASS(vips_foreign_load_jpeg_buffer_parent_class) |
380 | 68.9k | ->build(object); |
381 | 68.9k | } |
382 | | |
383 | | static gboolean |
384 | | vips_foreign_load_jpeg_buffer_is_a_buffer(const void *buf, size_t len) |
385 | 424k | { |
386 | 424k | VipsSource *source; |
387 | 424k | gboolean result; |
388 | | |
389 | 424k | if (!(source = vips_source_new_from_memory(buf, len))) |
390 | 0 | return FALSE; |
391 | 424k | result = vips_foreign_load_jpeg_source_is_a_source(source); |
392 | 424k | VIPS_UNREF(source); |
393 | | |
394 | 424k | return result; |
395 | 424k | } |
396 | | |
397 | | static void |
398 | | vips_foreign_load_jpeg_buffer_class_init( |
399 | | VipsForeignLoadJpegBufferClass *class) |
400 | 19 | { |
401 | 19 | GObjectClass *gobject_class = G_OBJECT_CLASS(class); |
402 | 19 | VipsObjectClass *object_class = (VipsObjectClass *) class; |
403 | 19 | VipsForeignLoadClass *load_class = (VipsForeignLoadClass *) class; |
404 | | |
405 | 19 | gobject_class->set_property = vips_object_set_property; |
406 | 19 | gobject_class->get_property = vips_object_get_property; |
407 | | |
408 | 19 | object_class->nickname = "jpegload_buffer"; |
409 | 19 | object_class->description = _("load jpeg from buffer"); |
410 | 19 | object_class->build = vips_foreign_load_jpeg_buffer_build; |
411 | | |
412 | 19 | load_class->is_a_buffer = vips_foreign_load_jpeg_buffer_is_a_buffer; |
413 | | |
414 | 19 | VIPS_ARG_BOXED(class, "buffer", 1, |
415 | 19 | _("Buffer"), |
416 | 19 | _("Buffer to load from"), |
417 | 19 | VIPS_ARGUMENT_REQUIRED_INPUT, |
418 | 19 | G_STRUCT_OFFSET(VipsForeignLoadJpegBuffer, blob), |
419 | 19 | VIPS_TYPE_BLOB); |
420 | 19 | } |
421 | | |
422 | | static void |
423 | | vips_foreign_load_jpeg_buffer_init(VipsForeignLoadJpegBuffer *buffer) |
424 | 69.0k | { |
425 | 69.0k | } |
426 | | |
427 | | #endif /*HAVE_JPEG*/ |
428 | | |
429 | | /** |
430 | | * vips_jpegload: |
431 | | * @filename: file to load |
432 | | * @out: (out): decompressed image |
433 | | * @...: `NULL`-terminated list of optional named arguments |
434 | | * |
435 | | * Read a JPEG file into a VIPS image. It can read most 8-bit JPEG images, |
436 | | * including CMYK and YCbCr. |
437 | | * |
438 | | * @shrink means shrink by this integer factor during load. Possible values |
439 | | * are 1, 2, 4 and 8. Shrinking during read is very much faster than |
440 | | * decompressing the whole image and then shrinking later. |
441 | | * |
442 | | * Use @fail_on to set the type of error that will cause load to fail. By |
443 | | * default, loaders are permissive, that is, [enum@Vips.FailOn.NONE]. |
444 | | * |
445 | | * Setting @autorotate to `TRUE` will make the loader interpret the |
446 | | * orientation tag and automatically rotate the image appropriately during |
447 | | * load. |
448 | | * |
449 | | * If @autorotate is `FALSE`, the metadata field [const@META_ORIENTATION] is set |
450 | | * to the value of the orientation tag. Applications may read and interpret |
451 | | * this field |
452 | | * as they wish later in processing. See [method@Image.autorot]. Save |
453 | | * operations will use [const@META_ORIENTATION], if present, to set the |
454 | | * orientation of output images. |
455 | | * |
456 | | * Example: |
457 | | * |
458 | | * ```c |
459 | | * vips_jpegload("fred.jpg", &out, |
460 | | * "shrink", 8, |
461 | | * "fail_on", VIPS_FAIL_ON_TRUNCATED, |
462 | | * NULL); |
463 | | * ``` |
464 | | * |
465 | | * Any embedded ICC profiles are ignored: you always just get the RGB from |
466 | | * the file. Instead, the embedded profile will be attached to the image as |
467 | | * [const@META_ICC_NAME]. You need to use something like |
468 | | * [method@Image.icc_import] to get CIE values from the file. |
469 | | * |
470 | | * EXIF metadata is attached as [const@META_EXIF_NAME], IPTC as |
471 | | * [const@META_IPTC_NAME], and XMP as [const@META_XMP_NAME]. |
472 | | * |
473 | | * The int metadata item "jpeg-multiscan" is set to the result of |
474 | | * `jpeg_has_multiple_scans()`. Interlaced jpeg images need a large amount of |
475 | | * memory to load, so this field gives callers a chance to handle these |
476 | | * images differently. |
477 | | * |
478 | | * The string-valued field "jpeg-chroma-subsample" gives the chroma subsample |
479 | | * in standard notation. 4:4:4 means no subsample, 4:2:0 means YCbCr with |
480 | | * Cb and Cr subsampled horizontally and vertically, 4:4:4:4 means a CMYK |
481 | | * image with no subsampling. |
482 | | * |
483 | | * The EXIF thumbnail, if present, is attached to the image as |
484 | | * "jpeg-thumbnail-data". See [method@Image.get_blob]. |
485 | | * |
486 | | * ::: tip "Optional arguments" |
487 | | * * @shrink: `gint`, shrink by this much on load |
488 | | * * @fail_on: [enum@FailOn], types of read error to fail on |
489 | | * * @autorotate: `gboolean`, use exif Orientation tag to rotate the image |
490 | | * during load |
491 | | * |
492 | | * ::: seealso |
493 | | * [ctor@Image.jpegload_buffer], [method@Image.autorot]. |
494 | | * |
495 | | * Returns: 0 on success, -1 on error. |
496 | | */ |
497 | | int |
498 | | vips_jpegload(const char *filename, VipsImage **out, ...) |
499 | 0 | { |
500 | 0 | va_list ap; |
501 | 0 | int result; |
502 | |
|
503 | 0 | va_start(ap, out); |
504 | 0 | result = vips_call_split("jpegload", ap, filename, out); |
505 | 0 | va_end(ap); |
506 | |
|
507 | 0 | return result; |
508 | 0 | } |
509 | | |
510 | | /** |
511 | | * vips_jpegload_buffer: |
512 | | * @buf: (array length=len) (element-type guint8): memory area to load |
513 | | * @len: (type gsize): size of memory area |
514 | | * @out: (out): image to write |
515 | | * @...: `NULL`-terminated list of optional named arguments |
516 | | * |
517 | | * Read a JPEG-formatted memory block into a VIPS image. Exactly as |
518 | | * [ctor@Image.jpegload], but read from a memory buffer. |
519 | | * |
520 | | * You must not free the buffer while @out is active. The |
521 | | * [signal@Object::postclose] signal on @out is a good place to free. |
522 | | * |
523 | | * ::: tip "Optional arguments" |
524 | | * * @shrink: `gint`, shrink by this much on load |
525 | | * * @fail_on: [enum@FailOn], types of read error to fail on |
526 | | * * @autorotate: `gboolean`, use exif Orientation tag to rotate the image |
527 | | * during load |
528 | | * |
529 | | * ::: seealso |
530 | | * [ctor@Image.jpegload]. |
531 | | * |
532 | | * Returns: 0 on success, -1 on error. |
533 | | */ |
534 | | int |
535 | | vips_jpegload_buffer(void *buf, size_t len, VipsImage **out, ...) |
536 | 377 | { |
537 | 377 | va_list ap; |
538 | 377 | VipsBlob *blob; |
539 | 377 | int result; |
540 | | |
541 | | /* We don't take a copy of the data or free it. |
542 | | */ |
543 | 377 | blob = vips_blob_new(NULL, buf, len); |
544 | | |
545 | 377 | va_start(ap, out); |
546 | 377 | result = vips_call_split("jpegload_buffer", ap, blob, out); |
547 | 377 | va_end(ap); |
548 | | |
549 | 377 | vips_area_unref(VIPS_AREA(blob)); |
550 | | |
551 | 377 | return result; |
552 | 377 | } |
553 | | |
554 | | /** |
555 | | * vips_jpegload_source: |
556 | | * @source: source to load |
557 | | * @out: (out): image to write |
558 | | * @...: `NULL`-terminated list of optional named arguments |
559 | | * |
560 | | * Read a JPEG-formatted memory block into a VIPS image. Exactly as |
561 | | * [ctor@Image.jpegload], but read from a source. |
562 | | * |
563 | | * ::: tip "Optional arguments" |
564 | | * * @shrink: `gint`, shrink by this much on load |
565 | | * * @fail_on: [enum@FailOn], types of read error to fail on |
566 | | * * @autorotate: `gboolean`, use exif Orientation tag to rotate the image |
567 | | * during load |
568 | | * |
569 | | * ::: seealso |
570 | | * [ctor@Image.jpegload]. |
571 | | * |
572 | | * Returns: 0 on success, -1 on error. |
573 | | */ |
574 | | int |
575 | | vips_jpegload_source(VipsSource *source, VipsImage **out, ...) |
576 | 0 | { |
577 | 0 | va_list ap; |
578 | 0 | int result; |
579 | |
|
580 | 0 | va_start(ap, out); |
581 | 0 | result = vips_call_split("jpegload_source", ap, source, out); |
582 | 0 | va_end(ap); |
583 | |
|
584 | 0 | return result; |
585 | 0 | } |