1 /*
2 FLIF - Free Lossless Image Format
3
4 Copyright 2010-2016, Jon Sneyers & Pieter Wuille
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 */
18
19 #include <stdio.h>
20
21 #include "flif-interface-private_dec.hpp"
22 #include "flif-interface_common.cpp"
23
24 #include <functional>
25
FLIF_DECODER()26 FLIF_DECODER::FLIF_DECODER()
27 : options(FLIF_DEFAULT_OPTIONS)
28 , callback(NULL)
29 , user_data(NULL)
30 , first_quality(0)
31 , working(false)
32 { options.crc_check = 0; options.keep_palette = 1; }
33
34
decode_file(const char * filename)35 int32_t FLIF_DECODER::decode_file(const char* filename) {
36 FILE *file = fopen(filename,"rb");
37 if(!file)
38 return 0;
39
40 return decode_filepointer(file, filename);
41 }
42
decode_filepointer(FILE * file,const char * filename)43 int32_t FLIF_DECODER::decode_filepointer(FILE *file, const char *filename) {
44 internal_images.clear();
45 images.clear();
46
47 FileIO fio(file, filename);
48
49 working = true;
50 metadata_options md_default = {
51 true, // icc
52 true, // exif
53 true, // xmp
54 };
55 if(!flif_decode(fio, internal_images, reinterpret_cast<callback_t>(callback), user_data, first_quality, images, options, md_default, 0))
56 { working = false; return 0; }
57 working = false;
58
59 images.clear();
60 for (Image& image : internal_images) images.emplace_back(std::move(image));
61
62 return 1;
63 }
64
decode_memory(const void * buffer,size_t buffer_size_bytes)65 int32_t FLIF_DECODER::decode_memory(const void* buffer, size_t buffer_size_bytes) {
66 internal_images.clear();
67 images.clear();
68
69 BlobReader reader(reinterpret_cast<const uint8_t*>(buffer), buffer_size_bytes);
70
71 working = true;
72 metadata_options md_default = {
73 true, // icc
74 true, // exif
75 true, // xmp
76 };
77 if(!flif_decode(reader, internal_images, reinterpret_cast<callback_t>(callback), user_data, first_quality, images, options, md_default, 0))
78 { working = false; return 0; }
79 working = false;
80
81 images.clear();
82 for (Image& image : internal_images) images.emplace_back(std::move(image));
83 return 1;
84 }
85
abort()86 int32_t FLIF_DECODER::abort() {
87 if (working) {
88 if (images.size() > 0) images[0].abort_decoding();
89 return 1;
90 } else return 0;
91 }
92
num_images()93 size_t FLIF_DECODER::num_images() {
94 return images.size();
95 }
96
num_loops()97 int32_t FLIF_DECODER::num_loops() {
98 return 0; // TODO: return actual loop count of the animation
99 }
100
get_image(size_t index)101 FLIF_IMAGE* FLIF_DECODER::get_image(size_t index) {
102 if(index >= images.size())
103 return 0;
104 if(index >= requested_images.size()) requested_images.resize(images.size());
105 if (!requested_images[index].get()) requested_images[index].reset( new FLIF_IMAGE());
106 if (images[index].rows() || images[index].metadata.size() > 0) {
107 requested_images[index]->image = std::move(images[index]); // moves and invalidates images[index]
108 }
109 return requested_images[index].get();
110 }
111
112
113 //=============================================================================
114
115
FLIF_INFO()116 FLIF_INFO::FLIF_INFO()
117 : width(0)
118 , height(0)
119 , channels(0)
120 , bit_depth(0)
121 , num_images(0)
122 { }
123
124
125 //=============================================================================
126
127 /*!
128 Notes about the C interface:
129
130 Only use types known to C.
131 Use types that are unambiguous across all compilers, like uint32_t.
132 Each function must have it's call convention set.
133 Exceptions must be caught no matter what.
134
135 */
136
137 //=============================================================================
138
139
140 extern "C" {
141
flif_create_decoder()142 FLIF_DLLEXPORT FLIF_DECODER* FLIF_API flif_create_decoder() {
143 try
144 {
145 std::unique_ptr<FLIF_DECODER> decoder(new FLIF_DECODER());
146 return decoder.release();
147 }
148 catch(...) {}
149 return 0;
150 }
151
flif_abort_decoder(FLIF_DECODER * decoder)152 FLIF_DLLEXPORT int32_t FLIF_API flif_abort_decoder(FLIF_DECODER* decoder) {
153 try {
154 return decoder->abort();
155 } catch(...) {}
156 return 0;
157 }
flif_destroy_decoder(FLIF_DECODER * decoder)158 FLIF_DLLEXPORT void FLIF_API flif_destroy_decoder(FLIF_DECODER* decoder) {
159 // delete should never let exceptions out
160 delete decoder;
161 decoder = NULL;
162 }
163
flif_decoder_set_crc_check(FLIF_DECODER * decoder,int32_t crc_check)164 FLIF_DLLEXPORT void FLIF_API flif_decoder_set_crc_check(FLIF_DECODER* decoder, int32_t crc_check) {
165 decoder->options.crc_check = crc_check;
166 }
167
flif_decoder_set_quality(FLIF_DECODER * decoder,int32_t quality)168 FLIF_DLLEXPORT void FLIF_API flif_decoder_set_quality(FLIF_DECODER* decoder, int32_t quality) {
169 decoder->options.quality = quality;
170 }
171
flif_decoder_set_scale(FLIF_DECODER * decoder,uint32_t scale)172 FLIF_DLLEXPORT void FLIF_API flif_decoder_set_scale(FLIF_DECODER* decoder, uint32_t scale) {
173 decoder->options.scale = scale;
174 }
175
flif_decoder_set_resize(FLIF_DECODER * decoder,uint32_t rw,uint32_t rh)176 FLIF_DLLEXPORT void FLIF_API flif_decoder_set_resize(FLIF_DECODER* decoder, uint32_t rw, uint32_t rh) {
177 decoder->options.resize_width = rw;
178 decoder->options.resize_height = rh;
179 }
180
flif_decoder_set_fit(FLIF_DECODER * decoder,uint32_t rw,uint32_t rh)181 FLIF_DLLEXPORT void FLIF_API flif_decoder_set_fit(FLIF_DECODER* decoder, uint32_t rw, uint32_t rh) {
182 decoder->options.resize_width = rw;
183 decoder->options.resize_height = rh;
184 decoder->options.fit = 1;
185 }
186
flif_decoder_set_callback(FLIF_DECODER * decoder,callback_t callback,void * user_data)187 FLIF_DLLEXPORT void FLIF_API flif_decoder_set_callback(FLIF_DECODER* decoder, callback_t callback, void *user_data) {
188 try
189 {
190 decoder->callback = (void*) callback;
191 decoder->user_data = user_data;
192 }
193 catch(...) {}
194 }
195
flif_decoder_set_first_callback_quality(FLIF_DECODER * decoder,int32_t quality)196 FLIF_DLLEXPORT void FLIF_API flif_decoder_set_first_callback_quality(FLIF_DECODER* decoder, int32_t quality) {
197 try
198 {
199 decoder->first_quality = quality;
200 }
201 catch(...) {}
202 }
203
204
205 /*!
206 * \return non-zero if the function succeeded
207 */
flif_decoder_decode_file(FLIF_DECODER * decoder,const char * filename)208 FLIF_DLLEXPORT int32_t FLIF_API flif_decoder_decode_file(FLIF_DECODER* decoder, const char* filename) {
209 try
210 {
211 return decoder->decode_file(filename);
212 }
213 catch(...) {}
214 return 0;
215 }
216
217 /*!
218 * The filename here is used for error messages.
219 * It would be helpful to pass an actual filename here, but a non-NULL dummy one can be used instead.
220 * \return non-zero if the function succeeded
221 */
flif_decoder_decode_filepointer(FLIF_DECODER * decoder,FILE * filepointer,const char * filename)222 FLIF_DLLEXPORT int32_t FLIF_API flif_decoder_decode_filepointer(FLIF_DECODER* decoder, FILE* filepointer, const char *filename) {
223 try
224 {
225 return decoder->decode_filepointer(filepointer, filename);
226 }
227 catch(...) {}
228 return 0;
229 }
230
231 /*!
232 * \return non-zero if the function succeeded
233 */
flif_decoder_decode_memory(FLIF_DECODER * decoder,const void * buffer,size_t buffer_size_bytes)234 FLIF_DLLEXPORT int32_t FLIF_API flif_decoder_decode_memory(FLIF_DECODER* decoder, const void* buffer, size_t buffer_size_bytes) {
235 try
236 {
237 return decoder->decode_memory(buffer, buffer_size_bytes);
238 }
239 catch(...) {}
240 return 0;
241 }
242
flif_decoder_num_images(FLIF_DECODER * decoder)243 FLIF_DLLEXPORT size_t FLIF_API flif_decoder_num_images(FLIF_DECODER* decoder) {
244 try
245 {
246 return decoder->num_images();
247 }
248 catch(...) {}
249 return 0;
250 }
251
flif_decoder_num_loops(FLIF_DECODER * decoder)252 FLIF_DLLEXPORT int32_t FLIF_API flif_decoder_num_loops(FLIF_DECODER* decoder) {
253 try
254 {
255 return decoder->num_loops();
256 }
257 catch(...) {}
258 return 0;
259 }
260
flif_decoder_get_image(FLIF_DECODER * decoder,size_t index)261 FLIF_DLLEXPORT FLIF_IMAGE* FLIF_API flif_decoder_get_image(FLIF_DECODER* decoder, size_t index) {
262 try
263 {
264 return decoder->get_image(index);
265 }
266 catch(...) {}
267 return 0;
268 }
269
flif_decoder_generate_preview(void * context)270 FLIF_DLLEXPORT void FLIF_API flif_decoder_generate_preview(void *context) {
271 try
272 {
273 auto func = (std::function<void ()> *) context;
274 (*func)();
275 }
276 catch(...) {}
277 }
278
279
flif_read_info_from_memory(const void * buffer,size_t buffer_size_bytes)280 FLIF_DLLEXPORT FLIF_INFO* FLIF_API flif_read_info_from_memory(const void* buffer, size_t buffer_size_bytes) {
281 try
282 {
283 std::unique_ptr<FLIF_INFO> info(new FLIF_INFO());
284
285 BlobReader reader(reinterpret_cast<const uint8_t*>(buffer), buffer_size_bytes);
286
287 callback_t callback = NULL;
288 void *user_data = NULL;
289 int first_quality = 0;
290 Images images;
291
292 metadata_options md_default = {
293 true, // icc
294 true, // exif
295 true, // xmp
296 };
297 flif_options options = FLIF_DEFAULT_OPTIONS;
298
299 if(flif_decode(reader, images, reinterpret_cast<callback_t>(callback), user_data, first_quality, images, options, md_default, info.get()))
300 {
301 return info.release();
302 }
303 }
304 catch(...) {}
305 return 0;
306 }
307
flif_destroy_info(FLIF_INFO * info)308 FLIF_DLLEXPORT void FLIF_API flif_destroy_info(FLIF_INFO* info) {
309 try
310 {
311 delete info;
312 }
313 catch(...) {}
314 }
315
flif_info_get_width(FLIF_INFO * info)316 FLIF_DLLEXPORT uint32_t FLIF_API flif_info_get_width(FLIF_INFO* info) {
317 try
318 {
319 return info->width;
320 }
321 catch(...) {}
322 return 0;
323 }
324
flif_info_get_height(FLIF_INFO * info)325 FLIF_DLLEXPORT uint32_t FLIF_API flif_info_get_height(FLIF_INFO* info) {
326 try
327 {
328 return info->height;
329 }
330 catch(...) {}
331 return 0;
332 }
333
flif_info_get_nb_channels(FLIF_INFO * info)334 FLIF_DLLEXPORT uint8_t FLIF_API flif_info_get_nb_channels(FLIF_INFO* info) {
335 try
336 {
337 return info->channels;
338 }
339 catch(...) {}
340 return 0;
341 }
342
flif_info_get_depth(FLIF_INFO * info)343 FLIF_DLLEXPORT uint8_t FLIF_API flif_info_get_depth(FLIF_INFO* info) {
344 try
345 {
346 return info->bit_depth;
347 }
348 catch(...) {}
349 return 0;
350 }
351
flif_info_num_images(FLIF_INFO * info)352 FLIF_DLLEXPORT size_t FLIF_API flif_info_num_images(FLIF_INFO* info) {
353 try
354 {
355 return info->num_images;
356 }
357 catch(...) {}
358 return 0;
359 }
360
361
362 } // extern "C"
363