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 #pragma once
20 #include "flif-interface-private_common.hpp"
21 
FLIF_IMAGE()22 FLIF_IMAGE::FLIF_IMAGE() { }
23 
24 #pragma pack(push,1)
25 struct FLIF_RGB {
26 	uint8_t r, g, b;
27 };
28 struct FLIF_RGBA {
29     uint8_t r,g,b,a;
30 };
31 struct FLIF_RGBA16 {
32     uint16_t r,g,b,a;
33 };
34 #pragma pack(pop)
35 
write_row_RGBA8(uint32_t row,const void * buffer,size_t buffer_size_bytes)36 void FLIF_IMAGE::write_row_RGBA8(uint32_t row, const void* buffer, size_t buffer_size_bytes) {
37     if(buffer_size_bytes < image.cols() * sizeof(FLIF_RGBA))
38         return;
39 
40     const FLIF_RGBA* buffer_rgba = reinterpret_cast<const FLIF_RGBA*>(buffer);
41 
42     if(image.numPlanes() >= 3) {
43         for (size_t c = 0; c < (size_t) image.cols(); c++) {
44             image.set(0, row, c, buffer_rgba[c].r);
45             image.set(1, row, c, buffer_rgba[c].g);
46             image.set(2, row, c, buffer_rgba[c].b);
47         }
48     }
49     if(image.numPlanes() >= 4) {
50         for (size_t c = 0; c < (size_t) image.cols(); c++) {
51             image.set(3, row, c, buffer_rgba[c].a);
52         }
53     }
54 }
55 
write_row_RGB8(uint32_t row,const void * buffer,size_t buffer_size_bytes)56 void FLIF_IMAGE::write_row_RGB8(uint32_t row, const void * buffer, size_t buffer_size_bytes)
57 {
58 	if (buffer_size_bytes < image.cols() * sizeof(FLIF_RGB))
59 		return;
60 
61 	const FLIF_RGB* buffer_rgb = reinterpret_cast<const FLIF_RGB*>(buffer);
62 
63 	if (image.numPlanes() >= 3) {
64 		for (size_t c = 0; c < (size_t)image.cols(); c++) {
65 			image.set(0, row, c, buffer_rgb[c].r);
66 			image.set(1, row, c, buffer_rgb[c].g);
67 			image.set(2, row, c, buffer_rgb[c].b);
68 		}
69 	}
70 	if (image.numPlanes() >= 4) {
71 		for (size_t c = 0; c < (size_t)image.cols(); c++) {
72 			image.set(3, row, c, 0xFF); // fully opaque
73 		}
74 	}
75 }
76 
write_row_GRAY8(uint32_t row,const void * buffer,size_t buffer_size_bytes)77 void FLIF_IMAGE::write_row_GRAY8(uint32_t row, const void * buffer, size_t buffer_size_bytes)
78 {
79 	if (buffer_size_bytes < image.cols() * sizeof(uint8_t))
80 		return;
81 
82 	const uint8_t* buffer_gray = reinterpret_cast<const uint8_t*>(buffer);
83 
84 	if (image.numPlanes() >= 1) {
85 		for (size_t c = 0; c < (size_t)image.cols(); c++) {
86 			image.set(0, row, c, buffer_gray[c]);
87 		}
88 	}
89 	if (image.numPlanes() >= 3) {
90 		for (size_t c = 0; c < (size_t)image.cols(); c++) {
91 			image.set(1, row, c, buffer_gray[c]);
92 			image.set(2, row, c, buffer_gray[c]);
93 		}
94 	}
95 	if (image.numPlanes() >= 4) {
96 		for (size_t c = 0; c < (size_t)image.cols(); c++) {
97 			image.set(3, row, c, 0xFF); // fully opaque
98 		}
99 	}
100 }
101 
write_row_GRAY16(uint32_t row,const void * buffer,size_t buffer_size_bytes)102 void FLIF_IMAGE::write_row_GRAY16(uint32_t row, const void * buffer, size_t buffer_size_bytes)
103 {
104 	if (buffer_size_bytes < image.cols() * sizeof(uint16_t))
105 		return;
106 
107 	const uint16_t* buffer_gray = reinterpret_cast<const uint16_t*>(buffer);
108 
109 	if (image.numPlanes() >= 1) {
110 		for (size_t c = 0; c < (size_t)image.cols(); c++) {
111 			image.set(0, row, c, buffer_gray[c]);
112 		}
113 	}
114 	if (image.numPlanes() >= 3) {
115 		for (size_t c = 0; c < (size_t)image.cols(); c++) {
116 			image.set(1, row, c, buffer_gray[c]);
117 			image.set(2, row, c, buffer_gray[c]);
118 		}
119 	}
120 	if (image.numPlanes() >= 4) {
121 		for (size_t c = 0; c < (size_t)image.cols(); c++) {
122 			image.set(3, row, c, 0xFF); // fully opaque
123 		}
124 	}
125 }
126 
write_row_PALETTE8(uint32_t row,const void * buffer,size_t buffer_size_bytes)127 void FLIF_IMAGE::write_row_PALETTE8(uint32_t row, const void * buffer, size_t buffer_size_bytes)
128 {
129 	if (buffer_size_bytes < image.cols() * sizeof(uint8_t))
130 		return;
131 
132 	const uint8_t* buffer_gray = reinterpret_cast<const uint8_t*>(buffer);
133 
134 	if (image.numPlanes() >= 4) {
135 		for (size_t c = 0; c < (size_t)image.cols(); c++) {
136 			image.set(0, row, c, 0);
137 			image.set(1, row, c, buffer_gray[c]);
138 			image.set(2, row, c, 0);
139 			image.set(3, row, c, 1);
140 		}
141 	}
142 }
143 
read_row_RGBA8(uint32_t row,void * buffer,size_t buffer_size_bytes)144 void FLIF_IMAGE::read_row_RGBA8(uint32_t row, void* buffer, size_t buffer_size_bytes) {
145     if(buffer_size_bytes < image.cols() * sizeof(FLIF_RGBA))
146         return;
147 
148     FLIF_RGBA* buffer_rgba = reinterpret_cast<FLIF_RGBA*>(buffer);
149     int rshift = 0;
150     int mult = 1;
151     ColorVal m=image.max(0);
152     while (m > 0xFF) { rshift++; m = m >> 1; } // in case the image has bit depth higher than 8
153     if ((m != 0) && m < 0xFF) mult = 0xFF / m;
154     if (image.palette) {
155       assert(image.numPlanes() >= 3);
156       // always color
157       for (size_t c = 0; c < (size_t) image.cols(); c++) {
158             buffer_rgba[c].r = ((image.palette_image->operator()(0, 0, image(1, row, c)) >> rshift) * mult) & 0xFF;
159             buffer_rgba[c].g = ((image.palette_image->operator()(1, 0, image(1, row, c)) >> rshift) * mult) & 0xFF;
160             buffer_rgba[c].b = ((image.palette_image->operator()(2, 0, image(1, row, c)) >> rshift) * mult) & 0xFF;
161       }
162       if (image.numPlanes() >= 4) {
163         for (size_t c = 0; c < (size_t) image.cols(); c++) {
164             buffer_rgba[c].a = ((image.palette_image->operator()(3, 0, image(1, row, c)) >> rshift) * mult) & 0xFF;
165         }
166       } else {
167         for (size_t c = 0; c < (size_t) image.cols(); c++) {
168             buffer_rgba[c].a = 0xFF;  // fully opaque
169         }
170       }
171     } else {
172       if (image.numPlanes() >= 3) {
173         // color
174         for (size_t c = 0; c < (size_t) image.cols(); c++) {
175             buffer_rgba[c].r = ((image(0, row, c) >> rshift) * mult) & 0xFF;
176             buffer_rgba[c].g = ((image(1, row, c) >> rshift) * mult) & 0xFF;
177             buffer_rgba[c].b = ((image(2, row, c) >> rshift) * mult) & 0xFF;
178         }
179       } else {
180         // grayscale
181         for (size_t c = 0; c < (size_t) image.cols(); c++) {
182             buffer_rgba[c].r =
183             buffer_rgba[c].g =
184             buffer_rgba[c].b = ((image(0, row, c) >> rshift) * mult) & 0xFF;
185         }
186       }
187       if (image.numPlanes() >= 4) {
188         for (size_t c = 0; c < (size_t) image.cols(); c++) {
189             buffer_rgba[c].a = ((image(3, row, c) >> rshift) * mult) & 0xFF;
190         }
191       } else {
192         for (size_t c = 0; c < (size_t) image.cols(); c++) {
193             buffer_rgba[c].a = 0xFF;  // fully opaque
194         }
195       }
196     }
197 }
198 
read_row_GRAY8(uint32_t row,void * buffer,size_t buffer_size_bytes)199 void FLIF_IMAGE::read_row_GRAY8(uint32_t row, void* buffer, size_t buffer_size_bytes) {
200     if(buffer_size_bytes < image.cols()) return;
201 
202     uint8_t* buffer_gray = reinterpret_cast<uint8_t*>(buffer);
203     int rshift = 0;
204     int mult = 1;
205     ColorVal m=image.max(0);
206     while (m > 0xFF) { rshift++; m = m >> 1; } // in case the image has bit depth higher than 8
207     if ((m != 0) && m < 0xFF) mult = 0xFF / m;
208 
209     for (size_t c = 0; c < (size_t) image.cols(); c++) {
210             buffer_gray[c] = ((image(0, row, c) >> rshift) * mult) & 0xFF;
211     }
212 }
213 
read_row_GRAY16(uint32_t row,void * buffer,size_t buffer_size_bytes)214 void FLIF_IMAGE::read_row_GRAY16(uint32_t row, void* buffer, size_t buffer_size_bytes) {
215     if(buffer_size_bytes < image.cols()) return;
216 
217     uint16_t* buffer_gray = reinterpret_cast<uint16_t*>(buffer);
218     int rshift = 0;
219     int mult = 1;
220 
221     for (size_t c = 0; c < (size_t) image.cols(); c++) {
222             buffer_gray[c] = ((image(0, row, c) >> rshift) * mult);
223     }
224 }
225 
read_row_PALETTE8(uint32_t row,void * buffer,size_t buffer_size_bytes)226 void FLIF_IMAGE::read_row_PALETTE8(uint32_t row, void* buffer, size_t buffer_size_bytes) {
227     if(buffer_size_bytes < image.cols()) return;
228 
229     assert(image.palette);
230 
231     uint8_t* buffer_gray = reinterpret_cast<uint8_t*>(buffer);
232     for (size_t c = 0; c < (size_t) image.cols(); c++) {
233             buffer_gray[c] = image(1, row, c) & 0xFF;
234     }
235 }
236 
237 
write_row_RGBA16(uint32_t row,const void * buffer,size_t buffer_size_bytes)238 void FLIF_IMAGE::write_row_RGBA16(uint32_t row, const void* buffer, size_t buffer_size_bytes) {
239     if(buffer_size_bytes < image.cols() * sizeof(FLIF_RGBA16))
240         return;
241 
242     const FLIF_RGBA16* buffer_rgba = reinterpret_cast<const FLIF_RGBA16*>(buffer);
243 
244     if(image.numPlanes() >= 3) {
245         for (size_t c = 0; c < (size_t) image.cols(); c++) {
246             image.set(0, row, c, buffer_rgba[c].r);
247             image.set(1, row, c, buffer_rgba[c].g);
248             image.set(2, row, c, buffer_rgba[c].b);
249         }
250     }
251     if(image.numPlanes() >= 4) {
252         for (size_t c = 0; c < (size_t) image.cols(); c++) {
253             image.set(3, row, c, buffer_rgba[c].a);
254         }
255     }
256 }
257 
read_row_RGBA16(uint32_t row,void * buffer,size_t buffer_size_bytes)258 void FLIF_IMAGE::read_row_RGBA16(uint32_t row, void* buffer, size_t buffer_size_bytes) {
259     if(buffer_size_bytes < image.cols() * sizeof(FLIF_RGBA16))
260         return;
261 
262     FLIF_RGBA16* buffer_rgba = reinterpret_cast<FLIF_RGBA16*>(buffer);
263     int rshift = 0;
264     int mult = 1;
265     ColorVal m=image.max(0);
266     while (m > 0xFFFF) { rshift++; m = m >> 1; } // in the unlikely case that the image has bit depth higher than 16
267     if ((m != 0) && m < 0xFFFF) mult = 0xFFFF / m;
268 
269     if(image.numPlanes() >= 3) {
270         // color
271         for (size_t c = 0; c < (size_t) image.cols(); c++) {
272             buffer_rgba[c].r = (image(0, row, c) >> rshift) * mult;
273             buffer_rgba[c].g = (image(1, row, c) >> rshift) * mult;
274             buffer_rgba[c].b = (image(2, row, c) >> rshift) * mult;
275         }
276     } else {
277         // grayscale
278         for (size_t c = 0; c < (size_t) image.cols(); c++) {
279             buffer_rgba[c].r =
280             buffer_rgba[c].g =
281             buffer_rgba[c].b = (image(0, row, c) >> rshift) * mult;
282         }
283     }
284     if(image.numPlanes() >= 4) {
285         for (size_t c = 0; c < (size_t) image.cols(); c++) {
286             buffer_rgba[c].a = (image(3, row, c) >> rshift) * mult;
287         }
288     } else {
289         for (size_t c = 0; c < (size_t) image.cols(); c++) {
290             buffer_rgba[c].a = 0xFFFF;  // fully opaque
291         }
292     }
293 }
294 
295 //=============================================================================
296 
297 /*!
298 Notes about the C interface:
299 
300 Only use types known to C.
301 Use types that are unambiguous across all compilers, like uint32_t.
302 Each function must have it's call convention set.
303 Exceptions must be caught no matter what.
304 
305 */
306 
307 //=============================================================================
308 
309 
310 extern "C" {
311 
flif_create_image(uint32_t width,uint32_t height)312 FLIF_DLLEXPORT FLIF_IMAGE* FLIF_API flif_create_image(uint32_t width, uint32_t height) {
313     try
314     {
315         std::unique_ptr<FLIF_IMAGE> image(new FLIF_IMAGE());
316         image->image.init(width, height, 0, 255, 4);
317         return image.release();
318     }
319     catch(...) {}
320     return 0;
321 }
322 
flif_create_image_RGB(uint32_t width,uint32_t height)323 FLIF_DLLEXPORT FLIF_IMAGE* FLIF_API flif_create_image_RGB(uint32_t width, uint32_t height) {
324     try
325     {
326         std::unique_ptr<FLIF_IMAGE> image(new FLIF_IMAGE());
327         image->image.init(width, height, 0, 255, 3);
328         return image.release();
329     }
330     catch(...) {}
331     return 0;
332 }
333 
flif_create_image_GRAY(uint32_t width,uint32_t height)334 FLIF_DLLEXPORT FLIF_IMAGE* FLIF_API flif_create_image_GRAY(uint32_t width, uint32_t height) {
335     try
336     {
337         std::unique_ptr<FLIF_IMAGE> image(new FLIF_IMAGE());
338         image->image.init(width, height, 0, 255, 1);
339         return image.release();
340     }
341     catch(...) {}
342     return 0;
343 }
344 
flif_create_image_GRAY16(uint32_t width,uint32_t height)345 FLIF_DLLEXPORT FLIF_IMAGE* FLIF_API flif_create_image_GRAY16(uint32_t width, uint32_t height) {
346     try
347     {
348         std::unique_ptr<FLIF_IMAGE> image(new FLIF_IMAGE());
349         image->image.init(width, height, 0, 65535, 1);
350         return image.release();
351     }
352     catch(...) {}
353     return 0;
354 }
355 
flif_create_image_PALETTE(uint32_t width,uint32_t height)356 FLIF_DLLEXPORT FLIF_IMAGE* FLIF_API flif_create_image_PALETTE(uint32_t width, uint32_t height) {
357     try
358     {
359         std::unique_ptr<FLIF_IMAGE> image(new FLIF_IMAGE());
360         image->image.semi_init(width, height, 0, 255, 4);
361         image->image.make_constant_plane(0,0);
362         image->image.make_constant_plane(2,0);
363         image->image.make_constant_plane(3,1);
364         image->image.real_init(true);
365         image->image.palette = true;
366         return image.release();
367     }
368     catch(...) {}
369     return 0;
370 }
371 
flif_create_image_HDR(uint32_t width,uint32_t height)372 FLIF_DLLEXPORT FLIF_IMAGE* FLIF_API flif_create_image_HDR(uint32_t width, uint32_t height) {
373     try
374     {
375         std::unique_ptr<FLIF_IMAGE> image(new FLIF_IMAGE());
376 #ifdef SUPPORT_HDR
377         image->image.init(width, height, 0, 65535, 4);
378 #else
379         image->image.init(width, height, 0, 255, 4);
380 #endif
381         return image.release();
382     }
383     catch(...) {}
384     return 0;
385 }
386 
flif_import_image_RGBA(uint32_t width,uint32_t height,const void * rgba,uint32_t rgba_stride)387 FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_import_image_RGBA(uint32_t width, uint32_t height, const void* rgba, uint32_t rgba_stride) {
388 	try
389 	{
390 		const int number_components = 4;
391 		if (width == 0 || height == 0 || rgba_stride < width*number_components)
392 			return 0;
393 		std::unique_ptr<FLIF_IMAGE> image(new FLIF_IMAGE());
394 		image->image.init(width, height, 0, 255, number_components);
395 		const uint8_t* buffer = static_cast<const uint8_t*>(rgba);
396 		for (uint32_t row = 0; row < height; ++row) {
397 			image->write_row_RGBA8(row, buffer, width*number_components);
398 			buffer += rgba_stride;
399 		}
400 		return image.release();
401 	}
402 	catch (...) {}
403 	return 0;
404 }
405 
flif_import_image_RGB(uint32_t width,uint32_t height,const void * rgb,uint32_t rgb_stride)406 FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_import_image_RGB(uint32_t width, uint32_t height, const void* rgb, uint32_t rgb_stride) {
407 	try
408 	{
409 		const int number_components = 3;
410 		if (width == 0 || height == 0 || rgb_stride < width*number_components)
411 			return 0;
412 		std::unique_ptr<FLIF_IMAGE> image(new FLIF_IMAGE());
413 		image->image.init(width, height, 0, 255, number_components);
414 		const uint8_t* buffer = static_cast<const uint8_t*>(rgb);
415 		for (uint32_t row = 0; row < height; ++row) {
416 			image->write_row_RGB8(row, buffer, width*number_components);
417 			buffer += rgb_stride;
418 		}
419 		return image.release();
420 	}
421 	catch (...) {}
422 	return 0;
423 }
424 
flif_import_image_GRAY(uint32_t width,uint32_t height,const void * gray,uint32_t gray_stride)425 FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_import_image_GRAY(uint32_t width, uint32_t height, const void* gray, uint32_t gray_stride) {
426 	try
427 	{
428 		const int number_components = 1;
429 		if (width == 0 || height == 0 || gray_stride < width*number_components)
430 			return 0;
431 		std::unique_ptr<FLIF_IMAGE> image(new FLIF_IMAGE());
432 		image->image.init(width, height, 0, 255, number_components);
433 		const uint8_t* buffer = static_cast<const uint8_t*>(gray);
434 		for (uint32_t row = 0; row < height; ++row) {
435 			image->write_row_GRAY8(row, buffer, width*number_components);
436 			buffer += gray_stride;
437 		}
438 		return image.release();
439 	}
440 	catch (...) {}
441 	return 0;
442 }
443 
flif_import_image_GRAY16(uint32_t width,uint32_t height,const void * gray,uint32_t gray_stride)444 FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_import_image_GRAY16(uint32_t width, uint32_t height, const void* gray, uint32_t gray_stride) {
445 	try
446 	{
447 		const int number_components = 1;
448 		if (width == 0 || height == 0 || gray_stride < width*number_components)
449 			return 0;
450 		std::unique_ptr<FLIF_IMAGE> image(new FLIF_IMAGE());
451 		image->image.init(width, height, 0, 65535, number_components);
452 		const uint16_t* buffer = static_cast<const uint16_t*>(gray);
453 		for (uint32_t row = 0; row < height; ++row) {
454 			image->write_row_GRAY16(row, buffer, (width * number_components * sizeof(uint16_t)));
455 			buffer += gray_stride;
456 		}
457 		return image.release();
458 	}
459 	catch (...) {}
460 	return 0;
461 }
462 
flif_import_image_PALETTE(uint32_t width,uint32_t height,const void * gray,uint32_t gray_stride)463 FLIF_DLLIMPORT FLIF_IMAGE* FLIF_API flif_import_image_PALETTE(uint32_t width, uint32_t height, const void* gray, uint32_t gray_stride) {
464 	try
465 	{
466 		const int number_components = 1;
467 		if (width == 0 || height == 0 || gray_stride < width*number_components)
468 			return 0;
469 		std::unique_ptr<FLIF_IMAGE> image(new FLIF_IMAGE());
470 		image->image.semi_init(width, height, 0, 255, 4);
471 		image->image.make_constant_plane(0,0);
472 		image->image.make_constant_plane(2,0);
473 		image->image.make_constant_plane(3,1);
474 		image->image.real_init(true);
475 		image->image.palette = true;
476 		const uint8_t* buffer = static_cast<const uint8_t*>(gray);
477 		for (uint32_t row = 0; row < height; ++row) {
478 			image->write_row_PALETTE8(row, buffer, width*number_components);
479 			buffer += gray_stride;
480 		}
481 		return image.release();
482 	}
483 	catch (...) {}
484 	return 0;
485 }
486 
flif_destroy_image(FLIF_IMAGE * image)487 FLIF_DLLEXPORT void FLIF_API flif_destroy_image(FLIF_IMAGE* image) {
488     // delete should never let exceptions out
489     delete image;
490 }
491 
flif_image_get_width(FLIF_IMAGE * image)492 FLIF_DLLEXPORT uint32_t FLIF_API flif_image_get_width(FLIF_IMAGE* image) {
493     try
494     {
495         return image->image.cols();
496     }
497     catch(...) {}
498     return 0;
499 }
500 
flif_image_get_height(FLIF_IMAGE * image)501 FLIF_DLLEXPORT uint32_t FLIF_API flif_image_get_height(FLIF_IMAGE* image) {
502     try
503     {
504         return image->image.rows();
505     }
506     catch(...) {}
507     return 0;
508 }
509 
flif_image_get_depth(FLIF_IMAGE * image)510 FLIF_DLLEXPORT uint8_t FLIF_API flif_image_get_depth(FLIF_IMAGE* image) {
511     try
512     {
513         return ( image->image.max(0) > 0xFF ? 16 : 8 );
514     }
515     catch(...) {}
516     return 0;
517 }
518 
flif_image_get_nb_channels(FLIF_IMAGE * image)519 FLIF_DLLEXPORT uint8_t FLIF_API flif_image_get_nb_channels(FLIF_IMAGE* image) {
520     try
521     {
522         int nb = image->image.numPlanes();
523         if (nb > 4) nb = 4; // there could be an extra plane for FRA
524         return nb;
525     }
526     catch(...) {}
527     return 0;
528 }
529 
flif_image_get_palette_size(FLIF_IMAGE * image)530 FLIF_DLLEXPORT uint32_t FLIF_API flif_image_get_palette_size(FLIF_IMAGE* image) {
531     try
532     {
533         uint32_t nb = 0;
534         if (image->image.palette && image->image.palette_image) nb = image->image.palette_image->cols();
535         return nb;
536     }
537     catch(...) {}
538     return 0;
539 }
540 
flif_image_get_palette(FLIF_IMAGE * image,void * buffer)541 FLIF_DLLEXPORT void FLIF_API flif_image_get_palette(FLIF_IMAGE* image, void* buffer) {
542     try
543     {
544         int nb = 0;
545         if (image->image.palette && image->image.palette_image) nb = image->image.palette_image->cols();
546         FLIF_RGBA* buffer_rgba = reinterpret_cast<FLIF_RGBA*>(buffer);
547         for (int i=0; i<nb; i++) {
548             buffer_rgba[i].r = image->image.palette_image->operator()(0,0,i);
549             buffer_rgba[i].g = image->image.palette_image->operator()(1,0,i);
550             buffer_rgba[i].b = image->image.palette_image->operator()(2,0,i);
551             if(image->image.numPlanes() >= 4) {
552               buffer_rgba[i].a = image->image.palette_image->operator()(3,0,i);
553             } else {
554               buffer_rgba[i].a = 255;
555             }
556         }
557     }
558     catch(...) {}
559 }
560 
flif_image_set_palette(FLIF_IMAGE * image,const void * buffer,uint32_t palette_size)561 FLIF_DLLEXPORT void FLIF_API flif_image_set_palette(FLIF_IMAGE* image, const void* buffer, uint32_t palette_size) {
562     try
563     {
564         int nb = palette_size;
565         image->image.palette = true;
566         image->image.palette_image = std::make_shared<Image>(nb,1,0,255,4);
567         const FLIF_RGBA* buffer_rgba = reinterpret_cast<const FLIF_RGBA*>(buffer);
568         for (int i=0; i<nb; i++) {
569             image->image.palette_image->set(0,0,i,buffer_rgba[i].r);
570             image->image.palette_image->set(1,0,i,buffer_rgba[i].g);
571             image->image.palette_image->set(2,0,i,buffer_rgba[i].b);
572             image->image.palette_image->set(3,0,i,buffer_rgba[i].a);
573         }
574     }
575     catch(...) {}
576 }
577 
flif_image_get_frame_delay(FLIF_IMAGE * image)578 FLIF_DLLEXPORT uint32_t FLIF_API flif_image_get_frame_delay(FLIF_IMAGE* image) {
579     try
580     {
581         return image->image.frame_delay;
582     }
583     catch(...) {}
584     return 0;
585 }
586 
flif_image_set_frame_delay(FLIF_IMAGE * image,uint32_t delay)587 FLIF_DLLEXPORT void FLIF_API flif_image_set_frame_delay(FLIF_IMAGE* image, uint32_t delay) {
588     try
589     {
590         image->image.frame_delay = delay;
591     }
592     catch(...) {}
593 }
594 
flif_image_set_metadata(FLIF_IMAGE * image,const char * chunkname,const unsigned char * data,size_t length)595 FLIF_DLLEXPORT void FLIF_API flif_image_set_metadata(FLIF_IMAGE* image, const char* chunkname, const unsigned char* data, size_t length) {
596     try
597     {
598         image->image.set_metadata(chunkname, data, length);
599     }
600     catch(...) {}
601 }
602 
flif_image_get_metadata(FLIF_IMAGE * image,const char * chunkname,unsigned char ** data,size_t * length)603 FLIF_DLLIMPORT uint8_t FLIF_API flif_image_get_metadata(FLIF_IMAGE* image, const char* chunkname, unsigned char** data, size_t* length){
604     uint8_t ret = 0;
605     try
606     {
607         ret = image->image.get_metadata(chunkname, data, length);
608     }
609     catch(...) {}
610 
611     return ret;
612 }
613 
flif_image_free_metadata(FLIF_IMAGE * image,unsigned char * data)614 FLIF_DLLIMPORT void FLIF_API flif_image_free_metadata(FLIF_IMAGE* image, unsigned char* data){
615     try
616     {
617         image->image.free_metadata(data);
618     }
619     catch(...) {}
620 }
621 
flif_image_write_row_RGBA8(FLIF_IMAGE * image,uint32_t row,const void * buffer,size_t buffer_size_bytes)622 FLIF_DLLEXPORT void FLIF_API flif_image_write_row_RGBA8(FLIF_IMAGE* image, uint32_t row, const void* buffer, size_t buffer_size_bytes) {
623     try
624     {
625         image->write_row_RGBA8(row, buffer, buffer_size_bytes);
626     }
627     catch(...) {}
628 }
629 
flif_image_read_row_RGBA8(FLIF_IMAGE * image,uint32_t row,void * buffer,size_t buffer_size_bytes)630 FLIF_DLLEXPORT void FLIF_API flif_image_read_row_RGBA8(FLIF_IMAGE* image, uint32_t row, void* buffer, size_t buffer_size_bytes) {
631     try
632     {
633         image->read_row_RGBA8(row, buffer, buffer_size_bytes);
634     }
635     catch(...) {}
636 }
637 
flif_image_write_row_GRAY8(FLIF_IMAGE * image,uint32_t row,const void * buffer,size_t buffer_size_bytes)638 FLIF_DLLEXPORT void FLIF_API flif_image_write_row_GRAY8(FLIF_IMAGE* image, uint32_t row, const void* buffer, size_t buffer_size_bytes) {
639     try
640     {
641         image->write_row_GRAY8(row, buffer, buffer_size_bytes);
642     }
643     catch(...) {}
644 }
645 
flif_image_write_row_GRAY16(FLIF_IMAGE * image,uint32_t row,const void * buffer,size_t buffer_size_bytes)646 FLIF_DLLEXPORT void FLIF_API flif_image_write_row_GRAY16(FLIF_IMAGE* image, uint32_t row, const void* buffer, size_t buffer_size_bytes) {
647     try
648     {
649         image->write_row_GRAY16(row, buffer, buffer_size_bytes);
650     }
651     catch(...) {}
652 }
653 
flif_image_read_row_GRAY8(FLIF_IMAGE * image,uint32_t row,void * buffer,size_t buffer_size_bytes)654 FLIF_DLLEXPORT void FLIF_API flif_image_read_row_GRAY8(FLIF_IMAGE* image, uint32_t row, void* buffer, size_t buffer_size_bytes) {
655     try
656     {
657         image->read_row_GRAY8(row, buffer, buffer_size_bytes);
658     }
659     catch(...) {}
660 }
661 
flif_image_read_row_GRAY16(FLIF_IMAGE * image,uint32_t row,void * buffer,size_t buffer_size_bytes)662 FLIF_DLLEXPORT void FLIF_API flif_image_read_row_GRAY16(FLIF_IMAGE* image, uint32_t row, void* buffer, size_t buffer_size_bytes) {
663     try
664     {
665         image->read_row_GRAY16(row, buffer, buffer_size_bytes);
666     }
667     catch(...) {}
668 }
669 
flif_image_write_row_PALETTE8(FLIF_IMAGE * image,uint32_t row,const void * buffer,size_t buffer_size_bytes)670 FLIF_DLLEXPORT void FLIF_API flif_image_write_row_PALETTE8(FLIF_IMAGE* image, uint32_t row, const void* buffer, size_t buffer_size_bytes) {
671     try
672     {
673         image->write_row_PALETTE8(row, buffer, buffer_size_bytes);
674     }
675     catch(...) {}
676 }
677 
flif_image_read_row_PALETTE8(FLIF_IMAGE * image,uint32_t row,void * buffer,size_t buffer_size_bytes)678 FLIF_DLLEXPORT void FLIF_API flif_image_read_row_PALETTE8(FLIF_IMAGE* image, uint32_t row, void* buffer, size_t buffer_size_bytes) {
679     try
680     {
681         image->read_row_PALETTE8(row, buffer, buffer_size_bytes);
682     }
683     catch(...) {}
684 }
685 
flif_image_write_row_RGBA16(FLIF_IMAGE * image,uint32_t row,const void * buffer,size_t buffer_size_bytes)686 FLIF_DLLEXPORT void FLIF_API flif_image_write_row_RGBA16(FLIF_IMAGE* image, uint32_t row, const void* buffer, size_t buffer_size_bytes) {
687     try
688     {
689         image->write_row_RGBA16(row, buffer, buffer_size_bytes);
690     }
691     catch(...) {}
692 }
693 
flif_image_read_row_RGBA16(FLIF_IMAGE * image,uint32_t row,void * buffer,size_t buffer_size_bytes)694 FLIF_DLLEXPORT void FLIF_API flif_image_read_row_RGBA16(FLIF_IMAGE* image, uint32_t row, void* buffer, size_t buffer_size_bytes) {
695     try
696     {
697         image->read_row_RGBA16(row, buffer, buffer_size_bytes);
698     }
699     catch(...) {}
700 }
701 
flif_free_memory(void * buffer)702 FLIF_DLLEXPORT void FLIF_API flif_free_memory(void* buffer) {
703     delete [] reinterpret_cast<uint8_t*>(buffer);
704 }
705 
706 } // extern "C"
707