forked from imgproxy/imgproxy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vips.c
754 lines (630 loc) · 18.7 KB
/
vips.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
#include "vips.h"
#include <string.h>
#define VIPS_SUPPORT_SMARTCROP \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 5))
#define VIPS_SUPPORT_HASALPHA \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 5))
#define VIPS_SUPPORT_GIF \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 3))
#define VIPS_SUPPORT_SVG \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 3))
#define VIPS_SUPPORT_TIFF \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 6))
#define VIPS_SUPPORT_MAGICK \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 7))
#define VIPS_SUPPORT_PNG_QUANTIZATION \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 7))
#define VIPS_SUPPORT_WEBP_SCALE_ON_LOAD \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
#define VIPS_SUPPORT_WEBP_ANIMATION \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
#define VIPS_SUPPORT_ARRAY_HEADERS \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 9))
#define VIPS_SUPPORT_HEIF \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
#define VIPS_SUPPORT_AVIF \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 9))
#define VIPS_SUPPORT_AVIF_SPEED \
(VIPS_MAJOR_VERSION > 8 || \
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION > 10) || \
(VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 10 && VIPS_MICRO_VERSION >= 2))
#define VIPS_SUPPORT_COMPOSITE \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 6))
#define VIPS_SUPPORT_FIND_TRIM \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 6))
#define VIPS_SUPPORT_PNG_BITDEPTH \
(VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 10))
#define EXIF_ORIENTATION "exif-ifd0-Orientation"
#if (VIPS_MAJOR_VERSION > 8 || (VIPS_MAJOR_VERSION == 8 && VIPS_MINOR_VERSION >= 8))
#define VIPS_BLOB_DATA_TYPE const void *
#else
#define VIPS_BLOB_DATA_TYPE void *
#endif
int
vips_initialize() {
return vips_init("imgproxy");
}
void
clear_image(VipsImage **in) {
if (G_IS_OBJECT(*in)) g_clear_object(in);
}
void
g_free_go(void **buf) {
g_free(*buf);
}
void
swap_and_clear(VipsImage **in, VipsImage *out) {
clear_image(in);
*in = out;
}
int
vips_type_find_load_go(int imgtype) {
switch (imgtype)
{
case (JPEG):
return vips_type_find("VipsOperation", "jpegload_buffer");
case (PNG):
return vips_type_find("VipsOperation", "pngload_buffer");
case (WEBP):
return vips_type_find("VipsOperation", "webpload_buffer");
case (GIF):
return vips_type_find("VipsOperation", "gifload_buffer");
case (SVG):
return vips_type_find("VipsOperation", "svgload_buffer");
case (HEIC):
return vips_type_find("VipsOperation", "heifload_buffer");
case (AVIF):
return vips_type_find("VipsOperation", "heifload_buffer");
case (BMP):
return vips_type_find("VipsOperation", "magickload_buffer");
case (TIFF):
return vips_type_find("VipsOperation", "tiffload_buffer");
}
return 0;
}
int
vips_type_find_save_go(int imgtype) {
switch (imgtype)
{
case (JPEG):
return vips_type_find("VipsOperation", "jpegsave_buffer");
case (PNG):
return vips_type_find("VipsOperation", "pngsave_buffer");
case (WEBP):
return vips_type_find("VipsOperation", "webpsave_buffer");
case (GIF):
return vips_type_find("VipsOperation", "magicksave_buffer");
#if VIPS_SUPPORT_AVIF
case (AVIF):
return vips_type_find("VipsOperation", "heifsave_buffer");
#endif
case (ICO):
return vips_type_find("VipsOperation", "pngsave_buffer");
case (BMP):
return vips_type_find("VipsOperation", "magicksave_buffer");
case (TIFF):
return vips_type_find("VipsOperation", "tiffsave_buffer");
}
return 0;
}
int
vips_jpegload_go(void *buf, size_t len, int shrink, VipsImage **out) {
if (shrink > 1)
return vips_jpegload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, "shrink", shrink, NULL);
return vips_jpegload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL);
}
int
vips_pngload_go(void *buf, size_t len, VipsImage **out) {
return vips_pngload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL);
}
int
vips_webpload_go(void *buf, size_t len, double scale, int pages, VipsImage **out) {
return vips_webpload_buffer(
buf, len, out,
"access", VIPS_ACCESS_SEQUENTIAL,
#if VIPS_SUPPORT_WEBP_SCALE_ON_LOAD
"scale", scale,
#else
"shrink", (int)(1.0 / scale),
#endif
#if VIPS_SUPPORT_WEBP_ANIMATION
"n", pages,
#endif
NULL
);
}
int
vips_gifload_go(void *buf, size_t len, int pages, VipsImage **out) {
#if VIPS_SUPPORT_GIF
return vips_gifload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, "n", pages, NULL);
#else
vips_error("vips_gifload_go", "Loading GIF is not supported (libvips 8.3+ reuired)");
return 1;
#endif
}
int
vips_svgload_go(void *buf, size_t len, double scale, VipsImage **out) {
#if VIPS_SUPPORT_SVG
// libvips limits the minimal scale to 0.001, so we have to scale down dpi
// for lower scale values
double dpi = 72.0;
if (scale < 0.001) {
dpi *= VIPS_MAX(scale / 0.001, 0.001);
scale = 0.001;
}
return vips_svgload_buffer(
buf, len, out,
"access", VIPS_ACCESS_SEQUENTIAL,
"scale", scale,
"dpi", dpi,
NULL
);
#else
vips_error("vips_svgload_go", "Loading SVG is not supported (libvips 8.5+ reuired)");
return 1;
#endif
}
int
vips_heifload_go(void *buf, size_t len, VipsImage **out) {
#if VIPS_SUPPORT_HEIF
return vips_heifload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL);
#else
vips_error("vips_heifload_go", "Loading HEIF is not supported (libvips 8.8+ reuired)");
return 1;
#endif
}
int
vips_bmpload_go(void *buf, size_t len, VipsImage **out) {
#if VIPS_SUPPORT_MAGICK
return vips_magickload_buffer(buf, len, out, NULL);
#else
vips_error("vips_bmpload_go", "Loading BMP is not supported");
return 1;
#endif
}
int
vips_tiffload_go(void *buf, size_t len, VipsImage **out) {
#if VIPS_SUPPORT_TIFF
return vips_tiffload_buffer(buf, len, out, "access", VIPS_ACCESS_SEQUENTIAL, NULL);
#else
vips_error("vips_tiffload_go", "Loading TIFF is not supported (libvips 8.6+ reuired)");
return 1;
#endif
}
int
vips_get_orientation(VipsImage *image) {
#ifdef VIPS_META_ORIENTATION
int orientation;
if (
vips_image_get_typeof(image, VIPS_META_ORIENTATION) == G_TYPE_INT &&
vips_image_get_int(image, VIPS_META_ORIENTATION, &orientation) == 0
) return orientation;
#else
const char *orientation;
if (
vips_image_get_typeof(image, EXIF_ORIENTATION) == VIPS_TYPE_REF_STRING &&
vips_image_get_string(image, EXIF_ORIENTATION, &orientation) == 0
) return atoi(orientation);
#endif
return 1;
}
int
vips_support_smartcrop() {
return VIPS_SUPPORT_SMARTCROP;
}
VipsBandFormat
vips_band_format(VipsImage *in) {
return in->BandFmt;
}
gboolean
vips_support_webp_animation() {
return VIPS_SUPPORT_WEBP_ANIMATION;
}
gboolean
vips_is_animated(VipsImage * in) {
return( vips_image_get_typeof(in, "page-height") != G_TYPE_INVALID &&
vips_image_get_typeof(in, "gif-delay") != G_TYPE_INVALID &&
vips_image_get_typeof(in, "gif-loop") != G_TYPE_INVALID );
}
int
vips_image_get_array_int_go(VipsImage *image, const char *name, int **out, int *n) {
#if VIPS_SUPPORT_ARRAY_HEADERS
return vips_image_get_array_int(image, name, out, n);
#else
vips_error("vips_image_get_array_int_go", "Array headers are not supported (libvips 8.9+ reuired)");
return 1;
#endif
}
void
vips_image_set_array_int_go(VipsImage *image, const char *name, const int *array, int n) {
#if VIPS_SUPPORT_ARRAY_HEADERS
vips_image_set_array_int(image, name, array, n);
#endif
}
gboolean
vips_image_hasalpha_go(VipsImage * in) {
#if VIPS_SUPPORT_HASALPHA
return vips_image_hasalpha(in);
#else
return( in->Bands == 2 ||
(in->Bands == 4 && in->Type != VIPS_INTERPRETATION_CMYK) ||
in->Bands > 4 );
#endif
}
int
vips_addalpha_go(VipsImage *in, VipsImage **out) {
return vips_addalpha(in, out, NULL);
}
int
vips_copy_go(VipsImage *in, VipsImage **out) {
return vips_copy(in, out, NULL);
}
int
vips_cast_go(VipsImage *in, VipsImage **out, VipsBandFormat format) {
return vips_cast(in, out, format, NULL);
}
int
vips_rad2float_go(VipsImage *in, VipsImage **out) {
return vips_rad2float(in, out, NULL);
}
int
vips_resize_go(VipsImage *in, VipsImage **out, double scale) {
return vips_resize(in, out, scale, NULL);
}
int
vips_resize_with_premultiply(VipsImage *in, VipsImage **out, double scale) {
VipsBandFormat format;
VipsImage *tmp1, *tmp2;
format = vips_band_format(in);
if (vips_premultiply(in, &tmp1, NULL))
return 1;
if (vips_resize(tmp1, &tmp2, scale, NULL)) {
clear_image(&tmp1);
return 1;
}
swap_and_clear(&tmp1, tmp2);
if (vips_unpremultiply(tmp1, &tmp2, NULL)) {
clear_image(&tmp1);
return 1;
}
swap_and_clear(&tmp1, tmp2);
if (vips_cast(tmp1, out, format, NULL)) {
clear_image(&tmp1);
return 1;
}
clear_image(&tmp1);
return 0;
}
int
vips_icc_is_srgb_iec61966(VipsImage *in) {
VIPS_BLOB_DATA_TYPE data;
size_t data_len;
// 1998-12-01
static char date[] = { 7, 206, 0, 2, 0, 9 };
// 2.1
static char version[] = { 2, 16, 0, 0 };
// The image had no profile and built-in CMYK was imported.
// Vips gives us an invalid data pointer when the built-in profile was imported,
// so we check this mark before receiving an actual profile.
// if (vips_image_get_typeof(in, "icc-cmyk-no-profile"))
// return FALSE;
if (vips_image_get_blob(in, VIPS_META_ICC_NAME, &data, &data_len))
return FALSE;
// Less than header size
if (data_len < 128)
return FALSE;
// Predict it is sRGB IEC61966 2.1 by checking some header fields
return ((memcmp(data + 48, "IEC ", 4) == 0) && // Device manufacturer
(memcmp(data + 52, "sRGB", 4) == 0) && // Device model
(memcmp(data + 80, "HP ", 4) == 0) && // Profile creator
(memcmp(data + 24, date, 6) == 0) && // Date of creation
(memcmp(data + 8, version, 4) == 0)); // Version
}
int
vips_has_embedded_icc(VipsImage *in) {
return vips_image_get_typeof(in, VIPS_META_ICC_NAME) != 0;
}
int
vips_icc_import_go(VipsImage *in, VipsImage **out) {
return vips_icc_import(in, out, "embedded", TRUE, "pcs", VIPS_PCS_XYZ, NULL);
}
int
vips_icc_export_go(VipsImage *in, VipsImage **out) {
return vips_icc_export(in, out, NULL);
}
int
vips_icc_export_srgb(VipsImage *in, VipsImage **out) {
return vips_icc_export(in, out, "output_profile", "sRGB", NULL);
}
int
vips_icc_transform_go(VipsImage *in, VipsImage **out) {
return vips_icc_transform(in, out, "sRGB", "embedded", TRUE, "pcs", VIPS_PCS_XYZ, NULL);
}
int
vips_icc_remove(VipsImage *in, VipsImage **out) {
if (vips_copy(in, out, NULL)) return 1;
vips_image_remove(*out, VIPS_META_ICC_NAME);
return 0;
}
int
vips_colourspace_go(VipsImage *in, VipsImage **out, VipsInterpretation cs) {
return vips_colourspace(in, out, cs, NULL);
}
int
vips_rot_go(VipsImage *in, VipsImage **out, VipsAngle angle) {
return vips_rot(in, out, angle, NULL);
}
int
vips_flip_horizontal_go(VipsImage *in, VipsImage **out) {
return vips_flip(in, out, VIPS_DIRECTION_HORIZONTAL, NULL);
}
int
vips_smartcrop_go(VipsImage *in, VipsImage **out, int width, int height) {
#if VIPS_SUPPORT_SMARTCROP
return vips_smartcrop(in, out, width, height, NULL);
#else
vips_error("vips_smartcrop_go", "Smart crop is not supported (libvips 8.5+ reuired)");
return 1;
#endif
}
int
vips_gaussblur_go(VipsImage *in, VipsImage **out, double sigma) {
return vips_gaussblur(in, out, sigma, NULL);
}
int
vips_sharpen_go(VipsImage *in, VipsImage **out, double sigma) {
return vips_sharpen(in, out, "sigma", sigma, NULL);
}
int
vips_flatten_go(VipsImage *in, VipsImage **out, double r, double g, double b) {
VipsArrayDouble *bg = vips_array_double_newv(3, r, g, b);
int res = vips_flatten(in, out, "background", bg, NULL);
vips_area_unref((VipsArea *)bg);
return res;
}
int
vips_extract_area_go(VipsImage *in, VipsImage **out, int left, int top, int width, int height) {
return vips_extract_area(in, out, left, top, width, height, NULL);
}
int
vips_trim(VipsImage *in, VipsImage **out, double threshold,
gboolean smart, double r, double g, double b,
gboolean equal_hor, gboolean equal_ver) {
#if VIPS_SUPPORT_FIND_TRIM
VipsImage *tmp;
if (vips_image_hasalpha(in)) {
if (vips_flatten_go(in, &tmp, 255.0, 0, 255.0))
return 1;
} else {
if (vips_copy(in, &tmp, NULL))
return 1;
}
double *bg;
int bgn;
VipsArrayDouble *bga;
if (smart) {
if (vips_getpoint(tmp, &bg, &bgn, 0, 0, NULL)) {
clear_image(&tmp);
return 1;
}
bga = vips_array_double_new(bg, bgn);
} else {
bga = vips_array_double_newv(3, r, g, b);
bg = 0;
}
int left, right, top, bot, width, height, diff;
if (vips_find_trim(tmp, &left, &top, &width, &height, "background", bga, "threshold", threshold, NULL)) {
clear_image(&tmp);
vips_area_unref((VipsArea *)bga);
g_free(bg);
return 1;
}
if (equal_hor) {
right = in->Xsize - left - width;
diff = right - left;
if (diff > 0) {
width += diff;
} else if (diff < 0) {
left = right;
width -= diff;
}
}
if (equal_ver) {
bot = in->Ysize - top - height;
diff = bot - top;
if (diff > 0) {
height += diff;
} else if (diff < 0) {
top = bot;
height -= diff;
}
}
clear_image(&tmp);
vips_area_unref((VipsArea *)bga);
g_free(bg);
if (width == 0 || height == 0) {
return vips_copy(in, out, NULL);
}
return vips_extract_area(in, out, left, top, width, height, NULL);
#else
vips_error("vips_trim", "Trim is not supported (libvips 8.6+ reuired)");
return 1;
#endif
}
int
vips_replicate_go(VipsImage *in, VipsImage **out, int width, int height) {
VipsImage *tmp;
if (vips_replicate(in, &tmp, 1 + width / in->Xsize, 1 + height / in->Ysize, NULL))
return 1;
if (vips_extract_area(tmp, out, 0, 0, width, height, NULL)) {
clear_image(&tmp);
return 1;
}
clear_image(&tmp);
return 0;
}
int
vips_embed_go(VipsImage *in, VipsImage **out, int x, int y, int width, int height, double *bg, int bgn) {
VipsArrayDouble *bga = vips_array_double_new(bg, bgn);
int ret = vips_embed(
in, out, x, y, width, height,
"extend", VIPS_EXTEND_BACKGROUND,
"background", bga,
NULL
);
vips_area_unref((VipsArea *)bga);
return ret;
}
int
vips_ensure_alpha(VipsImage *in, VipsImage **out) {
if (vips_image_hasalpha_go(in)) {
return vips_copy(in, out, NULL);
}
return vips_bandjoin_const1(in, out, 255, NULL);
}
int
vips_apply_watermark(VipsImage *in, VipsImage *watermark, VipsImage **out, double opacity) {
#if VIPS_SUPPORT_COMPOSITE
VipsImage *base = vips_image_new();
VipsImage **t = (VipsImage **) vips_object_local_array(VIPS_OBJECT(base), 5);
if (opacity < 1) {
if (
vips_extract_band(watermark, &t[0], 0, "n", watermark->Bands - 1, NULL) ||
vips_extract_band(watermark, &t[1], watermark->Bands - 1, "n", 1, NULL) ||
vips_linear1(t[1], &t[2], opacity, 0, NULL) ||
vips_bandjoin2(t[0], t[2], &t[3], NULL)
) {
clear_image(&base);
return 1;
}
} else {
if (vips_copy(watermark, &t[3], NULL)) {
clear_image(&base);
return 1;
}
}
int res =
vips_composite2(in, t[3], &t[4], VIPS_BLEND_MODE_OVER, "compositing_space", in->Type, NULL) ||
vips_cast(t[4], out, vips_image_get_format(in), NULL);
clear_image(&base);
return res;
#else
vips_error("vips_apply_watermark", "Watermarking is not supported (libvips 8.6+ reuired)");
return 1;
#endif
}
int
vips_arrayjoin_go(VipsImage **in, VipsImage **out, int n) {
return vips_arrayjoin(in, out, n, "across", 1, NULL);
}
int
vips_strip(VipsImage *in, VipsImage **out) {
static double default_resolution = 72.0 / 25.4;
if (vips_copy(
in, out,
"xres", default_resolution,
"yres", default_resolution,
NULL
)) return 1;
gchar **fields = vips_image_get_fields(in);
for (int i = 0; fields[i] != NULL; i++) {
gchar *name = fields[i];
if (strcmp(name, VIPS_META_ICC_NAME) == 0) continue;
vips_image_remove(*out, name);
}
g_strfreev(fields);
return 0;
}
int
vips_jpegsave_go(VipsImage *in, void **buf, size_t *len, int quality, int interlace) {
return vips_jpegsave_buffer(
in, buf, len,
"Q", quality,
"optimize_coding", TRUE,
"interlace", interlace,
NULL
);
}
int
vips_pngsave_go(VipsImage *in, void **buf, size_t *len, int interlace, int quantize, int colors) {
if (!quantize)
return vips_pngsave_buffer(
in, buf, len,
"filter", VIPS_FOREIGN_PNG_FILTER_NONE,
"interlace", interlace,
NULL
);
int bitdepth = 1;
if (colors > 16) bitdepth = 8;
else if (colors > 4) bitdepth = 4;
else if (colors > 2) bitdepth = 2;
return vips_pngsave_buffer(
in, buf, len,
"filter", VIPS_FOREIGN_PNG_FILTER_NONE,
"interlace", interlace,
#if VIPS_SUPPORT_PNG_BITDEPTH
"palette", quantize,
"bitdepth", bitdepth,
#elif VIPS_SUPPORT_PNG_QUANTIZATION // VIPS_SUPPORT_PNG_BITDEPTH
"palette", quantize,
"colours", colors,
#endif // VIPS_SUPPORT_PNG_QUANTIZATION
NULL
);
}
int
vips_webpsave_go(VipsImage *in, void **buf, size_t *len, int quality) {
return vips_webpsave_buffer(
in, buf, len,
"Q", quality,
NULL
);
}
int
vips_gifsave_go(VipsImage *in, void **buf, size_t *len) {
#if VIPS_SUPPORT_MAGICK
return vips_magicksave_buffer(in, buf, len, "format", "gif", NULL);
#else
vips_error("vips_gifsave_go", "Saving GIF is not supported (libvips 8.7+ reuired)");
return 1;
#endif
}
int
vips_tiffsave_go(VipsImage *in, void **buf, size_t *len, int quality) {
#if VIPS_SUPPORT_TIFF
return vips_tiffsave_buffer(in, buf, len, "Q", quality, NULL);
#else
vips_error("vips_tiffsave_go", "Saving TIFF is not supported (libvips 8.6+ reuired)");
return 1;
#endif
}
int
vips_avifsave_go(VipsImage *in, void **buf, size_t *len, int quality, int speed) {
#if VIPS_SUPPORT_AVIF
return vips_heifsave_buffer(
in, buf, len,
"Q", quality,
"compression", VIPS_FOREIGN_HEIF_COMPRESSION_AV1,
#if VIPS_SUPPORT_AVIF_SPEED
"speed", speed,
#endif
NULL);
#else
vips_error("vips_avifsave_go", "Saving AVIF is not supported (libvips 8.9+ reuired)");
return 1;
#endif
}
int
vips_bmpsave_go(VipsImage *in, void **buf, size_t *len) {
#if VIPS_SUPPORT_MAGICK
return vips_magicksave_buffer(in, buf, len, "format", "bmp", NULL);
#else
vips_error("vips_bmpsave_go", "Saving BMP is not supported");
return 1;
#endif
}
void
vips_cleanup() {
vips_error_clear();
vips_thread_shutdown();
}