1 /*
2 
3  rl2png -- PNG related functions
4 
5  version 0.1, 2013 March 29
6 
7  Author: Sandro Furieri a.furieri@lqt.it
8 
9  -----------------------------------------------------------------------------
10 
11  Version: MPL 1.1/GPL 2.0/LGPL 2.1
12 
13  The contents of this file are subject to the Mozilla Public License Version
14  1.1 (the "License"); you may not use this file except in compliance with
15  the License. You may obtain a copy of the License at
16  http://www.mozilla.org/MPL/
17 
18 Software distributed under the License is distributed on an "AS IS" basis,
19 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
20 for the specific language governing rights and limitations under the
21 License.
22 
23 The Original Code is the SpatiaLite library
24 
25 The Initial Developer of the Original Code is Alessandro Furieri
26 
27 Portions created by the Initial Developer are Copyright (C) 2008-2013
28 the Initial Developer. All Rights Reserved.
29 
30 Alternatively, the contents of this file may be used under the terms of
31 either the GNU General Public License Version 2 or later (the "GPL"), or
32 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 in which case the provisions of the GPL or the LGPL are applicable instead
34 of those above. If you wish to allow use of your version of this file only
35 under the terms of either the GPL or the LGPL, and not to allow others to
36 use your version of this file under the terms of the MPL, indicate your
37 decision by deleting the provisions above and replace them with the notice
38 and other provisions required by the GPL or the LGPL. If you do not delete
39 the provisions above, a recipient may use your version of this file under
40 the terms of any one of the MPL, the GPL or the LGPL.
41 
42 */
43 
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <string.h>
47 
48 #include <png.h>
49 
50 #include "config.h"
51 
52 #ifdef LOADABLE_EXTENSION
53 #include "rasterlite2/sqlite.h"
54 #endif
55 
56 #include "rasterlite2/rasterlite2.h"
57 #include "rasterlite2_private.h"
58 
59 struct png_memory_buffer
60 {
61     unsigned char *buffer;
62     size_t size;
63     size_t off;
64 };
65 
66 static void
rl2_png_read_data(png_structp png_ptr,png_bytep data,png_size_t length)67 rl2_png_read_data (png_structp png_ptr, png_bytep data, png_size_t length)
68 {
69     struct png_memory_buffer *p = png_get_io_ptr (png_ptr);
70     size_t rd = length;
71     if (p->off + length > p->size)
72 	rd = p->size - p->off;
73     if (rd != 0)
74       {
75 	  /* copy bytes into buffer */
76 	  memcpy (data, p->buffer + p->off, rd);
77 	  p->off += rd;
78       }
79     if (rd != length)
80 	png_error (png_ptr, "Read Error: truncated data");
81 }
82 
83 static void
rl2_png_write_data(png_structp png_ptr,png_bytep data,png_size_t length)84 rl2_png_write_data (png_structp png_ptr, png_bytep data, png_size_t length)
85 {
86     struct png_memory_buffer *p = png_get_io_ptr (png_ptr);
87     size_t nsize = p->size + length;
88 
89     /* allocate or grow buffer */
90     if (p->buffer)
91 	p->buffer = realloc (p->buffer, nsize);
92     else
93 	p->buffer = malloc (nsize);
94 
95     if (!p->buffer)
96 	png_error (png_ptr, "Write Error");
97 
98     /* copy new bytes to end of buffer */
99     memcpy (p->buffer + p->size, data, length);
100     p->size += length;
101 }
102 
103 static void
rl2_png_flush(png_structp png_ptr)104 rl2_png_flush (png_structp png_ptr)
105 {
106 /* just silencing stupid compiler warnings */
107     if (png_ptr == NULL)
108 	png_ptr = NULL;
109 }
110 
111 static int
compress_palette_png(const unsigned char * pixels,unsigned int width,unsigned int height,rl2PalettePtr plt,unsigned char sample_type,unsigned char ** png,int * png_size)112 compress_palette_png (const unsigned char *pixels, unsigned int width,
113 		      unsigned int height, rl2PalettePtr plt,
114 		      unsigned char sample_type, unsigned char **png,
115 		      int *png_size)
116 {
117 /* compressing a PNG image of the PALETTE type */
118     png_structp png_ptr;
119     png_infop info_ptr;
120     int bit_depth;
121     png_bytep *row_pointers = NULL;
122     png_bytep p_out;
123     unsigned int row;
124     unsigned int col;
125     png_color palette[256];
126     unsigned short num_entries;
127     unsigned char *red = NULL;
128     unsigned char *green = NULL;
129     unsigned char *blue = NULL;
130     int i;
131     const unsigned char *p_in;
132     struct png_memory_buffer membuf;
133     membuf.buffer = NULL;
134     membuf.size = 0;
135 
136     png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
137     if (!png_ptr)
138 	return RL2_ERROR;
139     info_ptr = png_create_info_struct (png_ptr);
140     if (!info_ptr)
141       {
142 	  png_destroy_write_struct (&png_ptr, NULL);
143 	  return RL2_ERROR;
144       }
145     if (setjmp (png_jmpbuf (png_ptr)))
146       {
147 	  goto error;
148       }
149 
150     png_set_write_fn (png_ptr, &membuf, rl2_png_write_data, rl2_png_flush);
151     switch (sample_type)
152       {
153       case RL2_SAMPLE_1_BIT:
154 	  bit_depth = 1;
155 	  break;
156       case RL2_SAMPLE_2_BIT:
157 	  bit_depth = 2;
158 	  break;
159       case RL2_SAMPLE_4_BIT:
160 	  bit_depth = 4;
161 	  break;
162       case RL2_SAMPLE_UINT8:
163 	  bit_depth = 8;
164 	  break;
165       };
166     png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth,
167 		  PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
168 		  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
169 /* setting the palette */
170     if (plt == NULL)
171 	goto error;
172     if (rl2_get_palette_colors (plt, &num_entries, &red, &green, &blue)
173 	!= RL2_OK)
174 	goto error;
175     for (i = 0; i < num_entries; i++)
176       {
177 	  palette[i].red = *(red + i);
178 	  palette[i].green = *(green + i);
179 	  palette[i].blue = *(blue + i);
180       }
181     png_set_PLTE (png_ptr, info_ptr, palette, num_entries);
182     png_write_info (png_ptr, info_ptr);
183     png_set_packing (png_ptr);
184     row_pointers = malloc (sizeof (png_bytep) * height);
185     if (row_pointers == NULL)
186 	goto error;
187     for (row = 0; row < height; ++row)
188 	row_pointers[row] = NULL;
189     p_in = pixels;
190     for (row = 0; row < height; row++)
191       {
192 	  if ((row_pointers[row] = malloc (width)) == NULL)
193 	      goto error;
194 	  p_out = row_pointers[row];
195 	  for (col = 0; col < width; col++)
196 	      *p_out++ = *p_in++;
197       }
198     png_write_image (png_ptr, row_pointers);
199     png_write_end (png_ptr, info_ptr);
200     for (row = 0; row < height; ++row)
201 	free (row_pointers[row]);
202     free (row_pointers);
203     png_destroy_write_struct (&png_ptr, &info_ptr);
204     if (red != NULL)
205 	rl2_free (red);
206     if (green != NULL)
207 	rl2_free (green);
208     if (blue != NULL)
209 	rl2_free (blue);
210     *png = membuf.buffer;
211     *png_size = membuf.size;
212     return RL2_OK;
213 
214   error:
215     png_destroy_write_struct (&png_ptr, &info_ptr);
216     for (row = 0; row < height; ++row)
217 	free (row_pointers[row]);
218     free (row_pointers);
219     if (membuf.buffer != NULL)
220 	free (membuf.buffer);
221     if (red != NULL)
222 	rl2_free (red);
223     if (green != NULL)
224 	rl2_free (green);
225     if (blue != NULL)
226 	rl2_free (blue);
227     return RL2_ERROR;
228 }
229 
230 static int
compress_grayscale_png(const unsigned char * pixels,const unsigned char * mask,double opacity,unsigned int width,unsigned int height,unsigned char sample_type,unsigned char pixel_type,unsigned char ** png,int * png_size)231 compress_grayscale_png (const unsigned char *pixels, const unsigned char *mask,
232 			double opacity, unsigned int width,
233 			unsigned int height, unsigned char sample_type,
234 			unsigned char pixel_type, unsigned char **png,
235 			int *png_size)
236 {
237 /* compressing a PNG image of the GRAYSCALE type */
238     png_structp png_ptr;
239     png_infop info_ptr;
240     int bit_depth;
241     png_bytep *row_pointers = NULL;
242     png_bytep p_out;
243     unsigned int row;
244     unsigned int col;
245     const unsigned char *p_in;
246     const unsigned char *p_mask;
247     int nBands;
248     int type;
249     int is_monochrome = 0;
250     unsigned char alpha = 255;
251     struct png_memory_buffer membuf;
252     membuf.buffer = NULL;
253     membuf.size = 0;
254 
255     if (opacity < 0.0)
256 	opacity = 0.0;
257     if (opacity > 1.0)
258 	opacity = 1.0;
259     if (opacity < 1.0)
260 	alpha = (unsigned char) (255.0 * opacity);
261 
262     if (pixel_type == RL2_PIXEL_MONOCHROME)
263 	is_monochrome = 1;
264 
265     png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
266     if (!png_ptr)
267 	return RL2_ERROR;
268     info_ptr = png_create_info_struct (png_ptr);
269     if (!info_ptr)
270       {
271 	  png_destroy_write_struct (&png_ptr, NULL);
272 	  return RL2_ERROR;
273       }
274     if (setjmp (png_jmpbuf (png_ptr)))
275       {
276 	  goto error;
277       }
278 
279     png_set_write_fn (png_ptr, &membuf, rl2_png_write_data, rl2_png_flush);
280     switch (sample_type)
281       {
282       case RL2_SAMPLE_1_BIT:
283 	  bit_depth = 1;
284 	  break;
285       case RL2_SAMPLE_2_BIT:
286 	  bit_depth = 2;
287 	  break;
288       case RL2_SAMPLE_4_BIT:
289 	  bit_depth = 4;
290 	  break;
291       case RL2_SAMPLE_UINT8:
292 	  bit_depth = 8;
293 	  break;
294       };
295     p_mask = mask;
296     type = PNG_COLOR_TYPE_GRAY;
297     nBands = 1;
298     if (p_mask != NULL && sample_type == RL2_SAMPLE_UINT8)
299       {
300 	  type = PNG_COLOR_TYPE_GRAY_ALPHA;
301 	  nBands = 2;
302       }
303     png_set_IHDR (png_ptr, info_ptr, width, height, bit_depth,
304 		  type, PNG_INTERLACE_NONE,
305 		  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
306     png_write_info (png_ptr, info_ptr);
307     png_set_packing (png_ptr);
308     row_pointers = malloc (sizeof (png_bytep) * height);
309     if (row_pointers == NULL)
310 	goto error;
311     for (row = 0; row < height; ++row)
312 	row_pointers[row] = NULL;
313     p_in = pixels;
314     for (row = 0; row < height; row++)
315       {
316 	  if ((row_pointers[row] = malloc (width * nBands)) == NULL)
317 	      goto error;
318 	  p_out = row_pointers[row];
319 	  for (col = 0; col < width; col++)
320 	    {
321 		if (is_monochrome)
322 		  {
323 		      if (*p_in++ != 0)
324 			  *p_out++ = 255;
325 		      else
326 			  *p_out++ = 0;
327 		  }
328 		else
329 		    *p_out++ = *p_in++;
330 		if (type == PNG_COLOR_TYPE_GRAY_ALPHA)
331 		  {
332 		      /* ALPHA channel */
333 		      int transparent = *p_mask++;
334 		      transparent = !transparent;
335 		      if (transparent)
336 			  *p_out++ = 0;
337 		      else
338 			  *p_out++ = alpha;
339 		  }
340 	    }
341       }
342 
343     png_write_image (png_ptr, row_pointers);
344     png_write_end (png_ptr, info_ptr);
345     for (row = 0; row < height; ++row)
346 	free (row_pointers[row]);
347     free (row_pointers);
348     png_destroy_write_struct (&png_ptr, &info_ptr);
349     *png = membuf.buffer;
350     *png_size = membuf.size;
351     return RL2_OK;
352 
353   error:
354     png_destroy_write_struct (&png_ptr, &info_ptr);
355     for (row = 0; row < height; ++row)
356 	free (row_pointers[row]);
357     free (row_pointers);
358     if (membuf.buffer != NULL)
359 	free (membuf.buffer);
360     return RL2_ERROR;
361 }
362 
363 static int
compress_rgb_png(const unsigned char * pixels,const unsigned char * mask,double opacity,unsigned int width,unsigned int height,unsigned char ** png,int * png_size)364 compress_rgb_png (const unsigned char *pixels, const unsigned char *mask,
365 		  double opacity, unsigned int width, unsigned int height,
366 		  unsigned char **png, int *png_size)
367 {
368 /* compressing a PNG image of the RGB type */
369     png_structp png_ptr;
370     png_infop info_ptr;
371     png_bytep *row_pointers = NULL;
372     png_bytep p_out;
373     unsigned int row;
374     unsigned int col;
375     const unsigned char *p_in;
376     const unsigned char *p_mask;
377     int nBands;
378     int type;
379     unsigned char alpha = 255;
380     struct png_memory_buffer membuf;
381     membuf.buffer = NULL;
382     membuf.size = 0;
383 
384     if (opacity < 0.0)
385 	opacity = 0.0;
386     if (opacity > 1.0)
387 	opacity = 1.0;
388     if (opacity < 1.0)
389 	alpha = (unsigned char) (255.0 * opacity);
390 
391     png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
392     if (!png_ptr)
393 	return RL2_ERROR;
394     info_ptr = png_create_info_struct (png_ptr);
395     if (!info_ptr)
396       {
397 	  png_destroy_write_struct (&png_ptr, NULL);
398 	  return RL2_ERROR;
399       }
400     if (setjmp (png_jmpbuf (png_ptr)))
401       {
402 	  goto error;
403       }
404 
405     png_set_write_fn (png_ptr, &membuf, rl2_png_write_data, rl2_png_flush);
406     p_mask = mask;
407     type = PNG_COLOR_TYPE_RGB;
408     nBands = 3;
409     if (p_mask != NULL)
410       {
411 	  type = PNG_COLOR_TYPE_RGB_ALPHA;
412 	  nBands = 4;
413       }
414     png_set_IHDR (png_ptr, info_ptr, width, height, 8,
415 		  type, PNG_INTERLACE_NONE,
416 		  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
417     png_write_info (png_ptr, info_ptr);
418     row_pointers = malloc (sizeof (png_bytep) * height);
419     if (row_pointers == NULL)
420 	goto error;
421     for (row = 0; row < height; ++row)
422 	row_pointers[row] = NULL;
423     p_in = pixels;
424     for (row = 0; row < height; row++)
425       {
426 	  if ((row_pointers[row] = malloc (width * nBands)) == NULL)
427 	      goto error;
428 	  p_out = row_pointers[row];
429 	  for (col = 0; col < width; col++)
430 	    {
431 		*p_out++ = *p_in++;
432 		*p_out++ = *p_in++;
433 		*p_out++ = *p_in++;
434 		if (p_mask != NULL)
435 		  {
436 		      /* ALPHA channel */
437 		      int transparent = *p_mask++;
438 		      transparent = !transparent;
439 		      if (transparent)
440 			  *p_out++ = 0;
441 		      else
442 			  *p_out++ = alpha;
443 		  }
444 	    }
445       }
446     png_write_image (png_ptr, row_pointers);
447     png_write_end (png_ptr, info_ptr);
448     for (row = 0; row < height; ++row)
449 	free (row_pointers[row]);
450     free (row_pointers);
451     png_destroy_write_struct (&png_ptr, &info_ptr);
452     *png = membuf.buffer;
453     *png_size = membuf.size;
454     return RL2_OK;
455 
456   error:
457     png_destroy_write_struct (&png_ptr, &info_ptr);
458     for (row = 0; row < height; ++row)
459 	free (row_pointers[row]);
460     free (row_pointers);
461     if (membuf.buffer != NULL)
462 	free (membuf.buffer);
463     return RL2_ERROR;
464 }
465 
466 static int
check_png_compatibility(unsigned char sample_type,unsigned char pixel_type,unsigned char num_samples)467 check_png_compatibility (unsigned char sample_type, unsigned char pixel_type,
468 			 unsigned char num_samples)
469 {
470 /* checks for PNG compatibility */
471     switch (sample_type)
472       {
473       case RL2_SAMPLE_1_BIT:
474       case RL2_SAMPLE_2_BIT:
475       case RL2_SAMPLE_4_BIT:
476       case RL2_SAMPLE_UINT8:
477 	  break;
478       default:
479 	  return RL2_ERROR;
480       };
481     switch (pixel_type)
482       {
483       case RL2_PIXEL_MONOCHROME:
484       case RL2_PIXEL_PALETTE:
485       case RL2_PIXEL_GRAYSCALE:
486       case RL2_PIXEL_RGB:
487 	  break;
488       default:
489 	  return RL2_ERROR;
490       };
491     if (pixel_type == RL2_PIXEL_MONOCHROME)
492       {
493 	  switch (sample_type)
494 	    {
495 	    case RL2_SAMPLE_1_BIT:
496 		break;
497 	    default:
498 		return RL2_ERROR;
499 	    };
500 	  if (num_samples != 1)
501 	      return RL2_ERROR;
502       }
503     if (pixel_type == RL2_PIXEL_PALETTE)
504       {
505 	  switch (sample_type)
506 	    {
507 	    case RL2_SAMPLE_1_BIT:
508 	    case RL2_SAMPLE_2_BIT:
509 	    case RL2_SAMPLE_4_BIT:
510 	    case RL2_SAMPLE_UINT8:
511 		break;
512 	    default:
513 		return RL2_ERROR;
514 	    };
515 	  if (num_samples != 1)
516 	      return RL2_ERROR;
517       }
518     if (pixel_type == RL2_PIXEL_GRAYSCALE)
519       {
520 	  switch (sample_type)
521 	    {
522 	    case RL2_SAMPLE_2_BIT:
523 	    case RL2_SAMPLE_4_BIT:
524 	    case RL2_SAMPLE_UINT8:
525 		break;
526 	    default:
527 		return RL2_ERROR;
528 	    };
529 	  if (num_samples != 1)
530 	      return RL2_ERROR;
531       }
532     if (pixel_type == RL2_PIXEL_RGB)
533       {
534 	  switch (sample_type)
535 	    {
536 	    case RL2_SAMPLE_UINT8:
537 		break;
538 	    default:
539 		return RL2_ERROR;
540 	    };
541 	  if (num_samples != 3)
542 	      return RL2_ERROR;
543       }
544     return RL2_OK;
545 }
546 
547 RL2_DECLARE int
rl2_section_to_png(rl2SectionPtr scn,const char * path)548 rl2_section_to_png (rl2SectionPtr scn, const char *path)
549 {
550 /* attempting to save a raster section into a PNG file */
551     int blob_size;
552     unsigned char *blob;
553     rl2RasterPtr rst;
554     int ret;
555 
556     if (scn == NULL)
557 	return RL2_ERROR;
558     rst = rl2_get_section_raster (scn);
559     if (rst == NULL)
560 	return RL2_ERROR;
561 /* attempting to export as a PNG image */
562     if (rl2_raster_to_png (rst, &blob, &blob_size) != RL2_OK)
563 	return RL2_ERROR;
564     ret = rl2_blob_to_file (path, blob, blob_size);
565     free (blob);
566     if (ret != RL2_OK)
567 	return RL2_ERROR;
568     return RL2_OK;
569 }
570 
571 RL2_DECLARE int
rl2_raster_to_png(rl2RasterPtr rst,unsigned char ** png,int * png_size)572 rl2_raster_to_png (rl2RasterPtr rst, unsigned char **png, int *png_size)
573 {
574 /* creating a PNG image from a raster */
575     rl2PrivRasterPtr raster = (rl2PrivRasterPtr) rst;
576     rl2PalettePtr plt;
577     unsigned char sample_type;
578     unsigned char pixel_type;
579     unsigned char num_samples;
580     unsigned char *blob;
581     int blob_size;
582     if (rst == NULL)
583 	return RL2_ERROR;
584     if (rl2_get_raster_type (rst, &sample_type, &pixel_type, &num_samples) !=
585 	RL2_OK)
586 	return RL2_ERROR;
587     if (check_png_compatibility (sample_type, pixel_type, num_samples) !=
588 	RL2_OK)
589 	return RL2_ERROR;
590     plt = rl2_get_raster_palette (rst);
591 
592     if (rl2_data_to_png
593 	(raster->rasterBuffer, raster->maskBuffer, 1.0, plt, raster->width,
594 	 raster->height, sample_type, pixel_type, &blob, &blob_size) != RL2_OK)
595 	return RL2_ERROR;
596     *png = blob;
597     *png_size = blob_size;
598     return RL2_OK;
599 }
600 
601 RL2_DECLARE int
rl2_rgb_to_png(unsigned int width,unsigned int height,const unsigned char * rgb,unsigned char ** png,int * png_size)602 rl2_rgb_to_png (unsigned int width, unsigned int height,
603 		const unsigned char *rgb, unsigned char **png, int *png_size)
604 {
605 /* creating a PNG image from an RGB buffer */
606     unsigned char *blob;
607     int blob_size;
608     if (rgb == NULL)
609 	return RL2_ERROR;
610 
611     if (rl2_data_to_png
612 	(rgb, NULL, 1.0, NULL, width, height, RL2_SAMPLE_UINT8, RL2_PIXEL_RGB,
613 	 &blob, &blob_size) != RL2_OK)
614 	return RL2_ERROR;
615     *png = blob;
616     *png_size = blob_size;
617     return RL2_OK;
618 }
619 
620 RL2_DECLARE int
rl2_rgb_alpha_to_png(unsigned int width,unsigned int height,const unsigned char * rgb,const unsigned char * alpha,unsigned char ** png,int * png_size,double opacity)621 rl2_rgb_alpha_to_png (unsigned int width, unsigned int height,
622 		      const unsigned char *rgb, const unsigned char *alpha,
623 		      unsigned char **png, int *png_size, double opacity)
624 {
625 /* creating a PNG image from two distinct RGB + Alpha buffer */
626     unsigned char *blob;
627     int blob_size;
628     if (rgb == NULL || alpha == NULL)
629 	return RL2_ERROR;
630 
631     if (rl2_data_to_png
632 	(rgb, alpha, opacity, NULL, width, height, RL2_SAMPLE_UINT8,
633 	 RL2_PIXEL_RGB, &blob, &blob_size) != RL2_OK)
634 	return RL2_ERROR;
635     *png = blob;
636     *png_size = blob_size;
637     return RL2_OK;
638 }
639 
640 RL2_DECLARE int
rl2_gray_to_png(unsigned int width,unsigned int height,const unsigned char * gray,unsigned char ** png,int * png_size)641 rl2_gray_to_png (unsigned int width, unsigned int height,
642 		 const unsigned char *gray, unsigned char **png, int *png_size)
643 {
644 /* creating a PNG image from a Grayscale buffer */
645     unsigned char *blob;
646     int blob_size;
647     if (gray == NULL)
648 	return RL2_ERROR;
649 
650     if (rl2_data_to_png
651 	(gray, NULL, 1.0, NULL, width, height, RL2_SAMPLE_UINT8,
652 	 RL2_PIXEL_GRAYSCALE, &blob, &blob_size) != RL2_OK)
653 	return RL2_ERROR;
654     *png = blob;
655     *png_size = blob_size;
656     return RL2_OK;
657 }
658 
659 RL2_DECLARE int
rl2_gray_alpha_to_png(unsigned int width,unsigned int height,const unsigned char * gray,const unsigned char * alpha,unsigned char ** png,int * png_size,double opacity)660 rl2_gray_alpha_to_png (unsigned int width, unsigned int height,
661 		       const unsigned char *gray, const unsigned char *alpha,
662 		       unsigned char **png, int *png_size, double opacity)
663 {
664 /* creating a PNG image from two distinct Grayscale + Alpha buffer */
665     unsigned char *blob;
666     int blob_size;
667     if (gray == NULL)
668 	return RL2_ERROR;
669 
670     if (rl2_data_to_png
671 	(gray, alpha, opacity, NULL, width, height, RL2_SAMPLE_UINT8,
672 	 RL2_PIXEL_GRAYSCALE, &blob, &blob_size) != RL2_OK)
673 	return RL2_ERROR;
674     *png = blob;
675     *png_size = blob_size;
676     return RL2_OK;
677 }
678 
679 RL2_PRIVATE int
rl2_data_to_png(const unsigned char * pixels,const unsigned char * mask,double opacity,rl2PalettePtr plt,unsigned int width,unsigned int height,unsigned char sample_type,unsigned char pixel_type,unsigned char ** png,int * png_size)680 rl2_data_to_png (const unsigned char *pixels, const unsigned char *mask,
681 		 double opacity, rl2PalettePtr plt, unsigned int width,
682 		 unsigned int height, unsigned char sample_type,
683 		 unsigned char pixel_type, unsigned char **png, int *png_size)
684 {
685 /* encoding a PNG image */
686     int ret;
687     unsigned char *blob;
688     int blob_size;
689 
690     if (pixels == NULL)
691 	return RL2_ERROR;
692     switch (pixel_type)
693       {
694       case RL2_PIXEL_PALETTE:
695 	  ret =
696 	      compress_palette_png (pixels, width, height, plt, sample_type,
697 				    &blob, &blob_size);
698 	  break;
699       case RL2_PIXEL_MONOCHROME:
700       case RL2_PIXEL_GRAYSCALE:
701 	  ret =
702 	      compress_grayscale_png (pixels, mask, opacity, width, height,
703 				      sample_type, pixel_type, &blob,
704 				      &blob_size);
705 	  break;
706       case RL2_PIXEL_RGB:
707 	  ret =
708 	      compress_rgb_png (pixels, mask, opacity, width, height, &blob,
709 				&blob_size);
710 	  break;
711       };
712     if (ret != RL2_OK)
713 	return RL2_ERROR;
714     *png = blob;
715     *png_size = blob_size;
716     return RL2_OK;
717 }
718 
719 RL2_DECLARE rl2SectionPtr
rl2_section_from_png(const char * path)720 rl2_section_from_png (const char *path)
721 {
722 /* attempting to create a raster section from a PNG file */
723     int blob_size;
724     unsigned char *blob;
725     rl2SectionPtr scn;
726     rl2RasterPtr rst;
727 
728 /* attempting to create a raster */
729     if (rl2_blob_from_file (path, &blob, &blob_size) != RL2_OK)
730 	return NULL;
731     rst = rl2_raster_from_png (blob, blob_size);
732     free (blob);
733     if (rst == NULL)
734 	return NULL;
735 
736 /* creating the raster section */
737     scn =
738 	rl2_create_section (path, RL2_COMPRESSION_PNG, RL2_TILESIZE_UNDEFINED,
739 			    RL2_TILESIZE_UNDEFINED, rst);
740     return scn;
741 }
742 
743 RL2_DECLARE rl2RasterPtr
rl2_raster_from_png(const unsigned char * blob,int blob_size)744 rl2_raster_from_png (const unsigned char *blob, int blob_size)
745 {
746 /* attempting to create a raster from a PNG image */
747     rl2RasterPtr rst = NULL;
748     unsigned int width;
749     unsigned int height;
750     unsigned char sample_type;
751     unsigned char pixel_type;
752     unsigned char nBands;
753     unsigned char *data = NULL;
754     int data_size;
755     unsigned char *mask = NULL;
756     int mask_sz;
757     rl2PalettePtr palette = NULL;
758 
759     if (rl2_decode_png
760 	(blob, blob_size, &width, &height, &sample_type, &pixel_type, &nBands,
761 	 &data, &data_size, &mask, &mask_sz, &palette) != RL2_OK)
762 	goto error;
763     rst =
764 	rl2_create_raster (width, height, sample_type, pixel_type, nBands, data,
765 			   data_size, palette, mask, mask_sz, NULL);
766     if (rst == NULL)
767 	goto error;
768     return rst;
769 
770   error:
771     if (data != NULL)
772 	free (data);
773     if (mask != NULL)
774 	free (mask);
775     if (palette != NULL)
776 	rl2_destroy_palette (palette);
777     return NULL;
778 }
779 
780 RL2_PRIVATE int
rl2_decode_png(const unsigned char * blob,int blob_size,unsigned int * xwidth,unsigned int * xheight,unsigned char * xsample_type,unsigned char * xpixel_type,unsigned char * num_bands,unsigned char ** pixels,int * pixels_sz,unsigned char ** xmask,int * xmask_sz,rl2PalettePtr * xpalette)781 rl2_decode_png (const unsigned char *blob, int blob_size,
782 		unsigned int *xwidth, unsigned int *xheight,
783 		unsigned char *xsample_type, unsigned char *xpixel_type,
784 		unsigned char *num_bands, unsigned char **pixels,
785 		int *pixels_sz, unsigned char **xmask, int *xmask_sz,
786 		rl2PalettePtr * xpalette)
787 {
788 /* attempting to decode a PNG image - raw block */
789     png_uint_32 width;
790     png_uint_32 height;
791     png_uint_32 rowbytes;
792     int bit_depth;
793     int color_type;
794     int interlace_type;
795     png_structp png_ptr;
796     png_infop info_ptr;
797     struct png_memory_buffer membuf;
798     unsigned char sample_type = RL2_SAMPLE_UNKNOWN;
799     unsigned char pixel_type = RL2_PIXEL_UNKNOWN;
800     int nBands;
801     int i;
802     png_colorp palette;
803     int red[256];
804     int green[256];
805     int blue[256];
806     int alpha[256];
807     unsigned char *data = NULL;
808     unsigned char *p_data;
809     unsigned char *mask = NULL;
810     int mask_sz = 0;
811     unsigned char *p_mask = NULL;
812     int data_size;
813     png_bytep image_data = NULL;
814     png_bytepp row_pointers = NULL;
815     unsigned int row;
816     unsigned int col;
817     rl2PalettePtr rl_palette = NULL;
818     int nPalette = 0;
819     png_bytep transp;
820     int nTransp;
821     png_color_16p transpValues;
822     int has_alpha = 0;
823 
824     if (blob == NULL || blob_size == 0)
825 	return RL2_ERROR;
826     png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
827     if (!png_ptr)
828 	return RL2_ERROR;
829     info_ptr = png_create_info_struct (png_ptr);
830     if (!info_ptr)
831       {
832 	  png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
833 	  return RL2_ERROR;
834       }
835     if (setjmp (png_jmpbuf (png_ptr)))
836       {
837 	  goto error;
838       }
839 
840     membuf.buffer = (unsigned char *) blob;
841     membuf.size = blob_size;
842     membuf.off = 0;
843     png_set_read_fn (png_ptr, &membuf, rl2_png_read_data);
844     png_read_info (png_ptr, info_ptr);
845     png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
846 		  &interlace_type, NULL, NULL);
847     switch (bit_depth)
848       {
849       case 1:
850 	  sample_type = RL2_SAMPLE_1_BIT;
851 	  break;
852       case 2:
853 	  sample_type = RL2_SAMPLE_2_BIT;
854 	  break;
855       case 4:
856 	  sample_type = RL2_SAMPLE_4_BIT;
857 	  break;
858       case 8:
859 	  sample_type = RL2_SAMPLE_UINT8;
860 	  break;
861       };
862     if (bit_depth < 8)
863 	png_set_packing (png_ptr);
864     switch (color_type)
865       {
866       case PNG_COLOR_TYPE_PALETTE:
867 	  pixel_type = RL2_PIXEL_PALETTE;
868 	  nBands = 1;
869 	  png_get_PLTE (png_ptr, info_ptr, &palette, &nPalette);
870 	  for (i = 0; i < nPalette; i++)
871 	    {
872 		red[i] = palette[i].red;
873 		green[i] = palette[i].green;
874 		blue[i] = palette[i].blue;
875 		alpha[i] = 255;
876 	    }
877 	  break;
878       case PNG_COLOR_TYPE_GRAY:
879       case PNG_COLOR_TYPE_GRAY_ALPHA:
880 	  pixel_type = RL2_PIXEL_GRAYSCALE;
881 	  if (sample_type == RL2_SAMPLE_1_BIT)
882 	      pixel_type = RL2_PIXEL_MONOCHROME;
883 	  nBands = 1;
884 	  break;
885       case PNG_COLOR_TYPE_RGB:
886       case PNG_COLOR_TYPE_RGB_ALPHA:
887 	  pixel_type = RL2_PIXEL_RGB;
888 	  nBands = 3;
889 	  break;
890       };
891     if (pixel_type == RL2_PIXEL_PALETTE)
892       {
893 	  if (png_get_tRNS (png_ptr, info_ptr, &transp, &nTransp, &transpValues)
894 	      == PNG_INFO_tRNS)
895 	    {
896 		/* a Transparency palette is defined */
897 		int i;
898 		for (i = 0; i < nTransp; i++)
899 		    *(alpha + i) = *(transp + i);
900 		has_alpha = 1;
901 	    }
902       }
903 /* creating the raster data */
904     data_size = width * height * nBands;
905     data = malloc (data_size);
906     if (data == NULL)
907 	goto error;
908     p_data = data;
909     if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA
910 	|| color_type == PNG_COLOR_TYPE_RGB_ALPHA || has_alpha)
911       {
912 	  /* creating a transparency mask */
913 	  mask_sz = width * height;
914 	  mask = malloc (mask_sz);
915 	  if (mask == NULL)
916 	      goto error;
917 	  p_mask = mask;
918       }
919     png_read_update_info (png_ptr, info_ptr);
920     rowbytes = png_get_rowbytes (png_ptr, info_ptr);
921     image_data = malloc (rowbytes * height);
922     if (!image_data)
923 	goto error;
924     row_pointers = malloc (height * sizeof (png_bytep));
925     if (!row_pointers)
926 	goto error;
927     for (row = 0; row < height; row++)
928 	row_pointers[row] = image_data + (row * rowbytes);
929     png_read_image (png_ptr, row_pointers);
930     png_read_end (png_ptr, NULL);
931     png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
932     switch (color_type)
933       {
934       case PNG_COLOR_TYPE_RGB:
935 	  for (row = 0; row < height; row++)
936 	    {
937 		png_bytep p_in = row_pointers[row];
938 		for (col = 0; col < width; col++)
939 		  {
940 		      *p_data++ = *p_in++;
941 		      *p_data++ = *p_in++;
942 		      *p_data++ = *p_in++;
943 		  }
944 	    }
945 	  break;
946       case PNG_COLOR_TYPE_RGB_ALPHA:
947 	  for (row = 0; row < height; row++)
948 	    {
949 		png_bytep p_in = row_pointers[row];
950 		for (col = 0; col < width; col++)
951 		  {
952 		      *p_data++ = *p_in++;
953 		      *p_data++ = *p_in++;
954 		      *p_data++ = *p_in++;
955 		      if (p_mask != NULL)
956 			{
957 			    if (*p_in++ < 128)
958 				*p_mask++ = 0;
959 			    else
960 				*p_mask++ = 1;
961 			}
962 		      else
963 			  p_in++;
964 		  }
965 	    }
966 	  break;
967       case PNG_COLOR_TYPE_GRAY:
968 	  for (row = 0; row < height; row++)
969 	    {
970 		png_bytep p_in = row_pointers[row];
971 		for (col = 0; col < width; col++)
972 		  {
973 		      unsigned char val = *p_in++;
974 		      switch (sample_type)
975 			{
976 			case RL2_SAMPLE_1_BIT:
977 			case RL2_SAMPLE_2_BIT:
978 			case RL2_SAMPLE_4_BIT:
979 			case RL2_SAMPLE_UINT8:
980 			    break;
981 			default:
982 			    val = 0;
983 			};
984 		      *p_data++ = val;
985 		  }
986 	    }
987 	  break;
988       case PNG_COLOR_TYPE_GRAY_ALPHA:
989 	  for (row = 0; row < height; row++)
990 	    {
991 		png_bytep p_in = row_pointers[row];
992 		for (col = 0; col < width; col++)
993 		  {
994 		      *p_data++ = *p_in++;
995 		      if (p_mask != NULL)
996 			{
997 			    if (*p_in++ < 128)
998 				*p_mask++ = 0;
999 			    else
1000 				*p_mask++ = 1;
1001 			}
1002 		      else
1003 			  p_in++;
1004 		  }
1005 	    }
1006 	  break;
1007       default:			/* palette */
1008 	  for (row = 0; row < height; row++)
1009 	    {
1010 		png_bytep p_in = row_pointers[row];
1011 		for (col = 0; col < width; col++)
1012 		  {
1013 		      *p_data++ = *p_in;
1014 		      if (p_mask != NULL)
1015 			{
1016 			    if (alpha[*p_in] < 128)
1017 				*p_mask++ = 0;
1018 			    else
1019 				*p_mask++ = 1;
1020 			}
1021 		      p_in++;
1022 		  }
1023 	    }
1024 	  break;
1025       };
1026 
1027     free (image_data);
1028     free (row_pointers);
1029 /* creating the raster */
1030     if (nPalette > 0)
1031       {
1032 	  rl_palette = rl2_create_palette (nPalette);
1033 	  if (rl_palette == NULL)
1034 	      goto error;
1035 	  for (i = 0; i < nPalette; i++)
1036 	      rl2_set_palette_color (rl_palette, i, red[i], green[i], blue[i]);
1037       }
1038     *xwidth = width;
1039     *xheight = height;
1040     *xsample_type = sample_type;
1041     *xpixel_type = pixel_type;
1042     *num_bands = nBands;
1043     *pixels = data;
1044     *pixels_sz = data_size;
1045     *xmask = mask;
1046     *xmask_sz = mask_sz;
1047     *xpalette = rl_palette;
1048     return RL2_OK;
1049 
1050   error:
1051     png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
1052     free (image_data);
1053     if (mask != NULL)
1054 	free (mask);
1055     free (row_pointers);
1056     return RL2_ERROR;
1057 }
1058