webp-ffi 1.0.0-x86_64-linux-gnu
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +135 -0
- data/LICENSE.txt +22 -0
- data/README.md +308 -0
- data/ext/webp_ffi/Rakefile +3 -0
- data/ext/webp_ffi/build_config.rb +119 -0
- data/ext/webp_ffi/jpegdec.c +174 -0
- data/ext/webp_ffi/jpegdec.h +20 -0
- data/ext/webp_ffi/metadata.c +138 -0
- data/ext/webp_ffi/metadata.h +49 -0
- data/ext/webp_ffi/pngdec.c +389 -0
- data/ext/webp_ffi/pngdec.h +29 -0
- data/ext/webp_ffi/tiffdec.c +361 -0
- data/ext/webp_ffi/tiffdec.h +31 -0
- data/ext/webp_ffi/util.c +216 -0
- data/ext/webp_ffi/util.h +63 -0
- data/ext/webp_ffi/webp_ffi.c +618 -0
- data/ext/webp_ffi/webp_ffi.h +110 -0
- data/ext/webp_ffi/x86_64-linux/libwebp_ffi.so +0 -0
- data/ext/webp_ffi/x86_64-linux/licenses/libjpeg-turbo-LICENSE.md +147 -0
- data/ext/webp_ffi/x86_64-linux/licenses/libjpeg-turbo-README.ijg +260 -0
- data/ext/webp_ffi/x86_64-linux/licenses/libpng-LICENSE +134 -0
- data/ext/webp_ffi/x86_64-linux/licenses/libtiff-LICENSE.md +49 -0
- data/ext/webp_ffi/x86_64-linux/licenses/libwebp-COPYING +30 -0
- data/ext/webp_ffi/x86_64-linux/licenses/libwebp-PATENTS +23 -0
- data/ext/webp_ffi/x86_64-linux/licenses/zlib-LICENSE +22 -0
- data/ext/webp_ffi/x86_64-linux/versions.txt +5 -0
- data/lib/webp/c.rb +101 -0
- data/lib/webp/error.rb +71 -0
- data/lib/webp/info.rb +13 -0
- data/lib/webp/options.rb +171 -0
- data/lib/webp/version.rb +3 -0
- data/lib/webp/webp.rb +179 -0
- data/lib/webp-ffi.rb +1 -0
- data/lib/webp_ffi.rb +16 -0
- data/sig/webp.rbs +74 -0
- metadata +145 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#include "./jpegdec.h"
|
|
2
|
+
#include "./util.h"
|
|
3
|
+
|
|
4
|
+
#include <stdio.h>
|
|
5
|
+
#include <jpeglib.h>
|
|
6
|
+
#include <setjmp.h>
|
|
7
|
+
#include <stdlib.h>
|
|
8
|
+
#include <string.h>
|
|
9
|
+
|
|
10
|
+
struct my_error_mgr {
|
|
11
|
+
struct jpeg_error_mgr pub;
|
|
12
|
+
jmp_buf setjmp_buffer;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
static void my_error_exit(j_common_ptr dinfo) {
|
|
16
|
+
struct my_error_mgr* myerr = (struct my_error_mgr*) dinfo->err;
|
|
17
|
+
longjmp(myerr->setjmp_buffer, 1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// libjpeg prints errors and warnings to stderr by default. A library should
|
|
21
|
+
// stay quiet.
|
|
22
|
+
static void my_output_message(j_common_ptr dinfo) {
|
|
23
|
+
(void)dinfo;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Based on the metadata code in libwebp's imageio/jpegdec.c.
|
|
27
|
+
|
|
28
|
+
// An ICC profile can be split over several APP2 segments:
|
|
29
|
+
// "ICC_PROFILE\0", the 1-based sequence number, the segment count, then data.
|
|
30
|
+
static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
|
|
31
|
+
static const char kSignature[] = "ICC_PROFILE"; // 12 bytes with the '\0'
|
|
32
|
+
const size_t signature_length = sizeof(kSignature);
|
|
33
|
+
const size_t header_length = signature_length + 2;
|
|
34
|
+
const JOCTET* segments[256];
|
|
35
|
+
size_t lengths[256];
|
|
36
|
+
int expected_count = 0;
|
|
37
|
+
int found = 0;
|
|
38
|
+
size_t total_size = 0;
|
|
39
|
+
size_t offset = 0;
|
|
40
|
+
jpeg_saved_marker_ptr marker;
|
|
41
|
+
int i;
|
|
42
|
+
|
|
43
|
+
memset(lengths, 0, sizeof(lengths));
|
|
44
|
+
for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) {
|
|
45
|
+
if (marker->marker == JPEG_APP0 + 2 && marker->data_length > header_length &&
|
|
46
|
+
!memcmp(marker->data, kSignature, signature_length)) {
|
|
47
|
+
const int seq = marker->data[signature_length];
|
|
48
|
+
const int count = marker->data[signature_length + 1];
|
|
49
|
+
if (seq == 0 || count == 0 || seq > count) return 0;
|
|
50
|
+
if (expected_count == 0) expected_count = count;
|
|
51
|
+
if (count != expected_count || lengths[seq] != 0) return 0;
|
|
52
|
+
segments[seq] = marker->data + header_length;
|
|
53
|
+
lengths[seq] = marker->data_length - header_length;
|
|
54
|
+
total_size += lengths[seq];
|
|
55
|
+
++found;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (found == 0) return 1; // no profile
|
|
59
|
+
if (found != expected_count) return 0; // missing segments
|
|
60
|
+
|
|
61
|
+
iccp->bytes = (uint8_t*)malloc(total_size);
|
|
62
|
+
if (iccp->bytes == NULL) return 0;
|
|
63
|
+
for (i = 1; i <= expected_count; ++i) { // in sequence order
|
|
64
|
+
memcpy(iccp->bytes + offset, segments[i], lengths[i]);
|
|
65
|
+
offset += lengths[i];
|
|
66
|
+
}
|
|
67
|
+
iccp->size = total_size;
|
|
68
|
+
return 1;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// EXIF and XMP live in APP1 segments, after a signature that is not copied.
|
|
72
|
+
static int ExtractMetadataFromJPEG(j_decompress_ptr dinfo,
|
|
73
|
+
Metadata* const metadata) {
|
|
74
|
+
static const char kExifSignature[] = "Exif\0"; // "Exif\0\0", 6 bytes
|
|
75
|
+
static const char kXMPSignature[] = "http://ns.adobe.com/xap/1.0/"; // 29 bytes
|
|
76
|
+
jpeg_saved_marker_ptr marker;
|
|
77
|
+
|
|
78
|
+
if (!StoreICCP(dinfo, &metadata->iccp)) return 0;
|
|
79
|
+
for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) {
|
|
80
|
+
if (marker->marker != JPEG_APP0 + 1) continue;
|
|
81
|
+
if (marker->data_length > sizeof(kExifSignature) &&
|
|
82
|
+
!memcmp(marker->data, kExifSignature, sizeof(kExifSignature))) {
|
|
83
|
+
if (!MetadataCopy(marker->data + sizeof(kExifSignature),
|
|
84
|
+
marker->data_length - sizeof(kExifSignature),
|
|
85
|
+
&metadata->exif)) {
|
|
86
|
+
return 0;
|
|
87
|
+
}
|
|
88
|
+
} else if (marker->data_length > sizeof(kXMPSignature) &&
|
|
89
|
+
!memcmp(marker->data, kXMPSignature, sizeof(kXMPSignature))) {
|
|
90
|
+
if (!MetadataCopy(marker->data + sizeof(kXMPSignature),
|
|
91
|
+
marker->data_length - sizeof(kXMPSignature),
|
|
92
|
+
&metadata->xmp)) {
|
|
93
|
+
return 0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
int UtilReadJPEG(FILE* in_file, WebPPicture* const pic,
|
|
101
|
+
Metadata* const metadata) {
|
|
102
|
+
int ok = 0;
|
|
103
|
+
int stride, width, height;
|
|
104
|
+
size_t rgb_size;
|
|
105
|
+
// 'rgb' changes after setjmp(), so it must be volatile to keep its value
|
|
106
|
+
// when libjpeg jumps back to the error handler.
|
|
107
|
+
uint8_t* volatile rgb = NULL;
|
|
108
|
+
struct jpeg_decompress_struct dinfo;
|
|
109
|
+
struct my_error_mgr jerr;
|
|
110
|
+
JSAMPROW buffer[1];
|
|
111
|
+
|
|
112
|
+
dinfo.err = jpeg_std_error(&jerr.pub);
|
|
113
|
+
jerr.pub.error_exit = my_error_exit;
|
|
114
|
+
jerr.pub.output_message = my_output_message;
|
|
115
|
+
|
|
116
|
+
if (setjmp(jerr.setjmp_buffer)) {
|
|
117
|
+
Error:
|
|
118
|
+
jpeg_destroy_decompress(&dinfo);
|
|
119
|
+
goto End;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
jpeg_create_decompress(&dinfo);
|
|
123
|
+
jpeg_stdio_src(&dinfo, in_file);
|
|
124
|
+
if (metadata != NULL) {
|
|
125
|
+
jpeg_save_markers(&dinfo, JPEG_APP0 + 1, 0xffff); // EXIF and XMP
|
|
126
|
+
jpeg_save_markers(&dinfo, JPEG_APP0 + 2, 0xffff); // ICC profile
|
|
127
|
+
}
|
|
128
|
+
jpeg_read_header(&dinfo, TRUE);
|
|
129
|
+
if (metadata != NULL && !ExtractMetadataFromJPEG(&dinfo, metadata)) {
|
|
130
|
+
goto Error;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
dinfo.out_color_space = JCS_RGB;
|
|
134
|
+
dinfo.do_fancy_upsampling = TRUE;
|
|
135
|
+
|
|
136
|
+
jpeg_start_decompress(&dinfo);
|
|
137
|
+
|
|
138
|
+
if (dinfo.output_components != 3) {
|
|
139
|
+
goto Error;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (!UtilCheckImageSize(dinfo.output_width, dinfo.output_height,
|
|
143
|
+
dinfo.output_components, &stride, &rgb_size)) {
|
|
144
|
+
goto Error;
|
|
145
|
+
}
|
|
146
|
+
width = (int)dinfo.output_width;
|
|
147
|
+
height = (int)dinfo.output_height;
|
|
148
|
+
|
|
149
|
+
rgb = (uint8_t*)malloc(rgb_size);
|
|
150
|
+
if (rgb == NULL) {
|
|
151
|
+
goto Error;
|
|
152
|
+
}
|
|
153
|
+
buffer[0] = (JSAMPLE*)rgb;
|
|
154
|
+
|
|
155
|
+
while (dinfo.output_scanline < dinfo.output_height) {
|
|
156
|
+
if (jpeg_read_scanlines(&dinfo, buffer, 1) != 1) {
|
|
157
|
+
goto Error;
|
|
158
|
+
}
|
|
159
|
+
buffer[0] += stride;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
jpeg_finish_decompress(&dinfo);
|
|
163
|
+
jpeg_destroy_decompress(&dinfo);
|
|
164
|
+
|
|
165
|
+
// WebP conversion.
|
|
166
|
+
pic->width = width;
|
|
167
|
+
pic->height = height;
|
|
168
|
+
ok = WebPPictureImportRGB(pic, rgb, stride);
|
|
169
|
+
|
|
170
|
+
End:
|
|
171
|
+
free(rgb);
|
|
172
|
+
return ok;
|
|
173
|
+
}
|
|
174
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#include <stdio.h>
|
|
2
|
+
|
|
3
|
+
#include "webp/encode.h"
|
|
4
|
+
#include "webp/decode.h"
|
|
5
|
+
#include "./metadata.h"
|
|
6
|
+
|
|
7
|
+
#ifdef __cplusplus
|
|
8
|
+
extern "C" {
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
// Reads a JPEG from 'in_file', returning the decoded output in 'pic'.
|
|
12
|
+
// The output is RGB. When 'metadata' is not NULL, the ICC profile, EXIF and
|
|
13
|
+
// XMP data are copied into it.
|
|
14
|
+
// Returns true on success.
|
|
15
|
+
int UtilReadJPEG(FILE* in_file, struct WebPPicture* const pic,
|
|
16
|
+
Metadata* const metadata);
|
|
17
|
+
|
|
18
|
+
#ifdef __cplusplus
|
|
19
|
+
} // extern "C"
|
|
20
|
+
#endif
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#include <stdlib.h>
|
|
2
|
+
#include <string.h>
|
|
3
|
+
|
|
4
|
+
#include "./metadata.h"
|
|
5
|
+
|
|
6
|
+
#if defined(__cplusplus) || defined(c_plusplus)
|
|
7
|
+
extern "C" {
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
// Based on WriteWebPWithMetadata in libwebp's examples/cwebp.c.
|
|
11
|
+
|
|
12
|
+
#define TAG_SIZE 4
|
|
13
|
+
#define CHUNK_HEADER_SIZE 8
|
|
14
|
+
#define RIFF_HEADER_SIZE 12
|
|
15
|
+
#define VP8X_CHUNK_SIZE 18 // chunk header and 10 bytes of payload
|
|
16
|
+
#define MAX_RIFF_SIZE 0xfffffff6ULL // the RIFF size is a 32-bit even number
|
|
17
|
+
|
|
18
|
+
// VP8X flags
|
|
19
|
+
#define FLAG_ICCP 0x20
|
|
20
|
+
#define FLAG_ALPHA 0x10
|
|
21
|
+
#define FLAG_EXIF 0x08
|
|
22
|
+
#define FLAG_XMP 0x04
|
|
23
|
+
|
|
24
|
+
void MetadataInit(Metadata* const metadata) {
|
|
25
|
+
memset(metadata, 0, sizeof(*metadata));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static void PayloadFree(MetadataPayload* const payload) {
|
|
29
|
+
free(payload->bytes);
|
|
30
|
+
payload->bytes = NULL;
|
|
31
|
+
payload->size = 0;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
void MetadataFree(Metadata* const metadata) {
|
|
35
|
+
PayloadFree(&metadata->exif);
|
|
36
|
+
PayloadFree(&metadata->iccp);
|
|
37
|
+
PayloadFree(&metadata->xmp);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
int MetadataCopy(const void* const data, size_t size,
|
|
41
|
+
MetadataPayload* const payload) {
|
|
42
|
+
if (payload->bytes != NULL || data == NULL || size == 0) return 1;
|
|
43
|
+
payload->bytes = (uint8_t*)malloc(size);
|
|
44
|
+
if (payload->bytes == NULL) return 0;
|
|
45
|
+
memcpy(payload->bytes, data, size);
|
|
46
|
+
payload->size = size;
|
|
47
|
+
return 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
static int WriteLE(FILE* const out, uint32_t value, int bytes) {
|
|
51
|
+
uint8_t buffer[4];
|
|
52
|
+
int i;
|
|
53
|
+
for (i = 0; i < bytes; ++i) {
|
|
54
|
+
buffer[i] = (uint8_t)((value >> (8 * i)) & 0xff);
|
|
55
|
+
}
|
|
56
|
+
return fwrite(buffer, (size_t)bytes, 1, out) == 1;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Chunk payloads have an even size; odd ones get one zero byte of padding.
|
|
60
|
+
static uint64_t ChunkSize(const MetadataPayload* const payload) {
|
|
61
|
+
return CHUNK_HEADER_SIZE + (uint64_t)payload->size + (payload->size & 1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static int WriteChunk(FILE* const out, const char* const tag,
|
|
65
|
+
const MetadataPayload* const payload) {
|
|
66
|
+
const uint8_t zero = 0;
|
|
67
|
+
int ok = (fwrite(tag, TAG_SIZE, 1, out) == 1);
|
|
68
|
+
ok = ok && WriteLE(out, (uint32_t)payload->size, 4);
|
|
69
|
+
ok = ok && (fwrite(payload->bytes, payload->size, 1, out) == 1);
|
|
70
|
+
if (payload->size & 1) ok = ok && (fwrite(&zero, 1, 1, out) == 1);
|
|
71
|
+
return ok;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
int MetadataWriteWebP(FILE* const out, const uint8_t* webp, size_t webp_size,
|
|
75
|
+
int width, int height, const Metadata* const metadata,
|
|
76
|
+
int keep) {
|
|
77
|
+
const int write_exif = (keep & METADATA_EXIF) && metadata->exif.size > 0;
|
|
78
|
+
const int write_iccp = (keep & METADATA_ICC) && metadata->iccp.size > 0;
|
|
79
|
+
const int write_xmp = (keep & METADATA_XMP) && metadata->xmp.size > 0;
|
|
80
|
+
uint32_t flags = 0;
|
|
81
|
+
uint64_t metadata_size = 0;
|
|
82
|
+
uint64_t riff_size;
|
|
83
|
+
int has_vp8x;
|
|
84
|
+
int ok;
|
|
85
|
+
|
|
86
|
+
if (webp_size < RIFF_HEADER_SIZE + CHUNK_HEADER_SIZE) return 0;
|
|
87
|
+
if (!write_exif && !write_iccp && !write_xmp) {
|
|
88
|
+
return fwrite(webp, webp_size, 1, out) == 1;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (write_exif) { flags |= FLAG_EXIF; metadata_size += ChunkSize(&metadata->exif); }
|
|
92
|
+
if (write_iccp) { flags |= FLAG_ICCP; metadata_size += ChunkSize(&metadata->iccp); }
|
|
93
|
+
if (write_xmp) { flags |= FLAG_XMP; metadata_size += ChunkSize(&metadata->xmp); }
|
|
94
|
+
|
|
95
|
+
has_vp8x = !memcmp(webp + RIFF_HEADER_SIZE, "VP8X", TAG_SIZE);
|
|
96
|
+
riff_size = (uint64_t)webp_size - CHUNK_HEADER_SIZE +
|
|
97
|
+
(has_vp8x ? 0 : VP8X_CHUNK_SIZE) + metadata_size;
|
|
98
|
+
if (riff_size > MAX_RIFF_SIZE) return 0;
|
|
99
|
+
|
|
100
|
+
// "RIFF", the new size, then "WEBP"
|
|
101
|
+
ok = (fwrite(webp, TAG_SIZE, 1, out) == 1);
|
|
102
|
+
ok = ok && WriteLE(out, (uint32_t)riff_size, 4);
|
|
103
|
+
ok = ok && (fwrite(webp + CHUNK_HEADER_SIZE, TAG_SIZE, 1, out) == 1);
|
|
104
|
+
webp += RIFF_HEADER_SIZE;
|
|
105
|
+
webp_size -= RIFF_HEADER_SIZE;
|
|
106
|
+
|
|
107
|
+
if (has_vp8x) {
|
|
108
|
+
// lossy with alpha: the encoder already wrote a VP8X chunk, add our flags
|
|
109
|
+
uint8_t vp8x[VP8X_CHUNK_SIZE];
|
|
110
|
+
memcpy(vp8x, webp, VP8X_CHUNK_SIZE);
|
|
111
|
+
vp8x[CHUNK_HEADER_SIZE] |= (uint8_t)(flags & 0xff);
|
|
112
|
+
ok = ok && (fwrite(vp8x, VP8X_CHUNK_SIZE, 1, out) == 1);
|
|
113
|
+
webp += VP8X_CHUNK_SIZE;
|
|
114
|
+
webp_size -= VP8X_CHUNK_SIZE;
|
|
115
|
+
} else {
|
|
116
|
+
// lossless images keep their alpha bit in the VP8L header
|
|
117
|
+
if (!memcmp(webp, "VP8L", TAG_SIZE) && webp_size > CHUNK_HEADER_SIZE + 4 &&
|
|
118
|
+
(webp[CHUNK_HEADER_SIZE + 4] & (1 << 4))) {
|
|
119
|
+
flags |= FLAG_ALPHA;
|
|
120
|
+
}
|
|
121
|
+
ok = ok && (fwrite("VP8X", TAG_SIZE, 1, out) == 1);
|
|
122
|
+
ok = ok && WriteLE(out, VP8X_CHUNK_SIZE - CHUNK_HEADER_SIZE, 4);
|
|
123
|
+
ok = ok && WriteLE(out, flags, 4);
|
|
124
|
+
ok = ok && WriteLE(out, (uint32_t)(width - 1), 3);
|
|
125
|
+
ok = ok && WriteLE(out, (uint32_t)(height - 1), 3);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// the chunk order is fixed: ICCP, image data, EXIF, XMP
|
|
129
|
+
if (write_iccp) ok = ok && WriteChunk(out, "ICCP", &metadata->iccp);
|
|
130
|
+
ok = ok && (fwrite(webp, webp_size, 1, out) == 1);
|
|
131
|
+
if (write_exif) ok = ok && WriteChunk(out, "EXIF", &metadata->exif);
|
|
132
|
+
if (write_xmp) ok = ok && WriteChunk(out, "XMP ", &metadata->xmp);
|
|
133
|
+
return ok;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
#if defined(__cplusplus) || defined(c_plusplus)
|
|
137
|
+
} // extern "C"
|
|
138
|
+
#endif
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#ifndef _WEBP_FFI_METADATA_H_
|
|
2
|
+
#define _WEBP_FFI_METADATA_H_
|
|
3
|
+
|
|
4
|
+
#include <stddef.h>
|
|
5
|
+
#include <stdint.h>
|
|
6
|
+
#include <stdio.h>
|
|
7
|
+
|
|
8
|
+
#if defined(__cplusplus) || defined(c_plusplus)
|
|
9
|
+
extern "C" {
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
// Which metadata to copy from the input picture into the WebP file.
|
|
13
|
+
#define METADATA_EXIF 1
|
|
14
|
+
#define METADATA_ICC 2
|
|
15
|
+
#define METADATA_XMP 4
|
|
16
|
+
#define METADATA_ALL (METADATA_EXIF | METADATA_ICC | METADATA_XMP)
|
|
17
|
+
|
|
18
|
+
typedef struct {
|
|
19
|
+
uint8_t* bytes;
|
|
20
|
+
size_t size;
|
|
21
|
+
} MetadataPayload;
|
|
22
|
+
|
|
23
|
+
typedef struct {
|
|
24
|
+
MetadataPayload exif;
|
|
25
|
+
MetadataPayload iccp;
|
|
26
|
+
MetadataPayload xmp;
|
|
27
|
+
} Metadata;
|
|
28
|
+
|
|
29
|
+
void MetadataInit(Metadata* const metadata);
|
|
30
|
+
void MetadataFree(Metadata* const metadata);
|
|
31
|
+
|
|
32
|
+
// Copies 'size' bytes into an empty 'payload'. Returns 1 on success, or when
|
|
33
|
+
// the payload already holds data (the first copy wins). Returns 0 when out of
|
|
34
|
+
// memory.
|
|
35
|
+
int MetadataCopy(const void* const data, size_t size, MetadataPayload* const payload);
|
|
36
|
+
|
|
37
|
+
// Writes a complete WebP file to 'out': the encoder output 'webp' plus the
|
|
38
|
+
// metadata selected by 'keep' (METADATA_* flags), using the extended format
|
|
39
|
+
// (VP8X) when any metadata is written. 'width' and 'height' are the size of the
|
|
40
|
+
// encoded picture. Returns 1 on success.
|
|
41
|
+
int MetadataWriteWebP(FILE* const out, const uint8_t* webp, size_t webp_size,
|
|
42
|
+
int width, int height, const Metadata* const metadata,
|
|
43
|
+
int keep);
|
|
44
|
+
|
|
45
|
+
#if defined(__cplusplus) || defined(c_plusplus)
|
|
46
|
+
} // extern "C"
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
#endif /* _WEBP_FFI_METADATA_H_ */
|