Merge branch 'master' into blender2.8
[blender.git] / source / blender / imbuf / intern / png.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/imbuf/intern/png.c
29  *  \ingroup imbuf
30  *
31  * \todo Save floats as 16 bits per channel, currently readonly.
32  */
33
34 #include "png.h"
35
36 #include "BLI_utildefines.h"
37 #include "BLI_fileops.h"
38 #include "BLI_math.h"
39
40 #include "BKE_global.h"
41 #include "BKE_idprop.h"
42
43 #include "MEM_guardedalloc.h"
44
45 #include "IMB_imbuf_types.h"
46 #include "IMB_imbuf.h"
47
48 #include "IMB_allocimbuf.h"
49 #include "IMB_metadata.h"
50 #include "IMB_filetype.h"
51
52 #include "IMB_colormanagement.h"
53 #include "IMB_colormanagement_intern.h"
54
55 typedef struct PNGReadStruct {
56         const unsigned char *data;
57         unsigned int size;
58         unsigned int seek;
59 } PNGReadStruct;
60
61 static void ReadData(png_structp png_ptr, png_bytep data, png_size_t length);
62 static void WriteData(png_structp png_ptr, png_bytep data, png_size_t length);
63 static void Flush(png_structp png_ptr);
64
65 BLI_INLINE unsigned short UPSAMPLE_8_TO_16(const unsigned char _val)
66 {
67         return (_val << 8) + _val;
68 }
69
70 int imb_is_a_png(const unsigned char *mem)
71 {
72         int ret_val = 0;
73
74         if (mem) {
75 #if (PNG_LIBPNG_VER_MAJOR == 1) && (PNG_LIBPNG_VER_MINOR == 2)
76                 /* Older version of libpng doesn't use const pointer to memory. */
77                 ret_val = !png_sig_cmp((png_bytep)mem, 0, 8);
78 #else
79                 ret_val = !png_sig_cmp(mem, 0, 8);
80 #endif
81         }
82         return(ret_val);
83 }
84
85 static void Flush(png_structp png_ptr) 
86 {
87         (void)png_ptr;
88 }
89
90 static void WriteData(png_structp png_ptr, png_bytep data, png_size_t length)
91 {
92         ImBuf *ibuf = (ImBuf *) png_get_io_ptr(png_ptr);
93
94         /* if buffer is to small increase it. */
95         while (ibuf->encodedsize + length > ibuf->encodedbuffersize) {
96                 imb_enlargeencodedbufferImBuf(ibuf);
97         }
98
99         memcpy(ibuf->encodedbuffer + ibuf->encodedsize, data, length);
100         ibuf->encodedsize += length;
101 }
102
103 static void ReadData(png_structp png_ptr, png_bytep data, png_size_t length)
104 {
105         PNGReadStruct *rs = (PNGReadStruct *) png_get_io_ptr(png_ptr);
106
107         if (rs) {
108                 if (length <= rs->size - rs->seek) {
109                         memcpy(data, rs->data + rs->seek, length);
110                         rs->seek += length;
111                         return;
112                 }
113         }
114
115         printf("Reached EOF while decoding PNG\n");
116         longjmp(png_jmpbuf(png_ptr), 1);
117 }
118
119 static float channel_colormanage_noop(float value)
120 {
121         return value;
122 }
123
124 /* wrap to avoid macro calling functions multiple times */
125 BLI_INLINE unsigned short ftoshort(float val)
126 {
127         return unit_float_to_ushort_clamp(val);
128 }
129
130 int imb_savepng(struct ImBuf *ibuf, const char *name, int flags)
131 {
132         png_structp png_ptr;
133         png_infop info_ptr;
134
135         unsigned char *pixels = NULL;
136         unsigned char *from, *to;
137         unsigned short *pixels16 = NULL, *to16;
138         float *from_float, from_straight[4];
139         png_bytepp row_pointers = NULL;
140         int i, bytesperpixel, color_type = PNG_COLOR_TYPE_GRAY;
141         FILE *fp = NULL;
142
143         bool is_16bit  = (ibuf->foptions.flag & PNG_16BIT) != 0;
144         bool has_float = (ibuf->rect_float != NULL);
145         int channels_in_float = ibuf->channels ? ibuf->channels : 4;
146
147         float (*chanel_colormanage_cb)(float);
148         size_t num_bytes;
149
150         /* use the jpeg quality setting for compression */
151         int compression;
152         compression = (int)(((float)(ibuf->foptions.quality) / 11.1111f));
153         compression = compression < 0 ? 0 : (compression > 9 ? 9 : compression);
154
155         if (ibuf->float_colorspace || (ibuf->colormanage_flag & IMB_COLORMANAGE_IS_DATA)) {
156                 /* float buffer was managed already, no need in color space conversion */
157                 chanel_colormanage_cb = channel_colormanage_noop;
158         }
159         else {
160                 /* standard linear-to-srgb conversion if float buffer wasn't managed */
161                 chanel_colormanage_cb = linearrgb_to_srgb;
162         }
163
164         /* for prints */
165         if (flags & IB_mem)
166                 name = "<memory>";
167
168         bytesperpixel = (ibuf->planes + 7) >> 3;
169         if ((bytesperpixel > 4) || (bytesperpixel == 2)) {
170                 printf("imb_savepng: Unsupported bytes per pixel: %d for file: '%s'\n", bytesperpixel, name);
171                 return (0);
172         }
173
174         png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
175                                           NULL, NULL, NULL);
176         if (png_ptr == NULL) {
177                 printf("imb_savepng: Cannot png_create_write_struct for file: '%s'\n", name);
178                 return 0;
179         }
180
181         info_ptr = png_create_info_struct(png_ptr);
182         if (info_ptr == NULL) {
183                 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
184                 printf("imb_savepng: Cannot png_create_info_struct for file: '%s'\n", name);
185                 return 0;
186         }
187
188         if (setjmp(png_jmpbuf(png_ptr))) {
189                 png_destroy_write_struct(&png_ptr, &info_ptr);
190                 printf("imb_savepng: Cannot setjmp for file: '%s'\n", name);
191                 return 0;
192         }
193
194         /* copy image data */
195         num_bytes = ((size_t)ibuf->x) * ibuf->y * bytesperpixel;
196         if (is_16bit)
197                 pixels16 = MEM_mallocN(num_bytes * sizeof(unsigned short), "png 16bit pixels");
198         else
199                 pixels = MEM_mallocN(num_bytes * sizeof(unsigned char), "png 8bit pixels");
200
201         if (pixels == NULL && pixels16 == NULL) {
202                 png_destroy_write_struct(&png_ptr, &info_ptr);
203                 printf("imb_savepng: Cannot allocate pixels array of %dx%d, %d bytes per pixel for file: '%s'\n", ibuf->x, ibuf->y, bytesperpixel, name);
204                 return 0;
205         }
206
207         from = (unsigned char *) ibuf->rect;
208         to = pixels;
209         from_float = ibuf->rect_float;
210         to16 = pixels16;
211
212         switch (bytesperpixel) {
213                 case 4:
214                         color_type = PNG_COLOR_TYPE_RGBA;
215                         if (is_16bit) {
216                                 if (has_float) {
217                                         if (channels_in_float == 4) {
218                                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
219                                                         premul_to_straight_v4_v4(from_straight, from_float);
220                                                         to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0]));
221                                                         to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1]));
222                                                         to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2]));
223                                                         to16[3] = ftoshort(chanel_colormanage_cb(from_straight[3]));
224                                                         to16 += 4; from_float += 4;
225                                                 }
226                                         }
227                                         else if (channels_in_float == 3) {
228                                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
229                                                         to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
230                                                         to16[1] = ftoshort(chanel_colormanage_cb(from_float[1]));
231                                                         to16[2] = ftoshort(chanel_colormanage_cb(from_float[2]));
232                                                         to16[3] = 65535;
233                                                         to16 += 4; from_float += 3;
234                                                 }
235                                         }
236                                         else {
237                                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
238                                                         to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
239                                                         to16[2] = to16[1] = to16[0];
240                                                         to16[3] = 65535;
241                                                         to16 += 4; from_float++;
242                                                 }
243                                         }
244                                 }
245                                 else {
246                                         for (i = ibuf->x * ibuf->y; i > 0; i--) {
247                                                 to16[0] = UPSAMPLE_8_TO_16(from[0]);
248                                                 to16[1] = UPSAMPLE_8_TO_16(from[1]);
249                                                 to16[2] = UPSAMPLE_8_TO_16(from[2]);
250                                                 to16[3] = UPSAMPLE_8_TO_16(from[3]);
251                                                 to16 += 4; from += 4;
252                                         }
253                                 }
254                         }
255                         else {
256                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
257                                         to[0] = from[0];
258                                         to[1] = from[1];
259                                         to[2] = from[2];
260                                         to[3] = from[3];
261                                         to += 4; from += 4;
262                                 }
263                         }
264                         break;
265                 case 3:
266                         color_type = PNG_COLOR_TYPE_RGB;
267                         if (is_16bit) {
268                                 if (has_float) {
269                                         if (channels_in_float == 4) {
270                                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
271                                                         premul_to_straight_v4_v4(from_straight, from_float);
272                                                         to16[0] = ftoshort(chanel_colormanage_cb(from_straight[0]));
273                                                         to16[1] = ftoshort(chanel_colormanage_cb(from_straight[1]));
274                                                         to16[2] = ftoshort(chanel_colormanage_cb(from_straight[2]));
275                                                         to16 += 3; from_float += 4;
276                                                 }
277                                         }
278                                         else if (channels_in_float == 3) {
279                                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
280                                                         to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
281                                                         to16[1] = ftoshort(chanel_colormanage_cb(from_float[1]));
282                                                         to16[2] = ftoshort(chanel_colormanage_cb(from_float[2]));
283                                                         to16 += 3; from_float += 3;
284                                                 }
285                                         }
286                                         else {
287                                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
288                                                         to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
289                                                         to16[2] = to16[1] = to16[0];
290                                                         to16 += 3; from_float++;
291                                                 }
292                                         }
293                                 }
294                                 else {
295                                         for (i = ibuf->x * ibuf->y; i > 0; i--) {
296                                                 to16[0] = UPSAMPLE_8_TO_16(from[0]);
297                                                 to16[1] = UPSAMPLE_8_TO_16(from[1]);
298                                                 to16[2] = UPSAMPLE_8_TO_16(from[2]);
299                                                 to16 += 3; from += 4;
300                                         }
301                                 }
302                         }
303                         else {
304                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
305                                         to[0] = from[0];
306                                         to[1] = from[1];
307                                         to[2] = from[2];
308                                         to += 3; from += 4;
309                                 }
310                         }
311                         break;
312                 case 1:
313                         color_type = PNG_COLOR_TYPE_GRAY;
314                         if (is_16bit) {
315                                 if (has_float) {
316                                         float rgb[3];
317                                         if (channels_in_float == 4) {
318                                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
319                                                         premul_to_straight_v4_v4(from_straight, from_float);
320                                                         rgb[0] = chanel_colormanage_cb(from_straight[0]);
321                                                         rgb[1] = chanel_colormanage_cb(from_straight[1]);
322                                                         rgb[2] = chanel_colormanage_cb(from_straight[2]);
323                                                         to16[0] = ftoshort(IMB_colormanagement_get_luminance(rgb));
324                                                         to16++; from_float += 4;
325                                                 }
326                                         }
327                                         else if (channels_in_float == 3) {
328                                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
329                                                         rgb[0] = chanel_colormanage_cb(from_float[0]);
330                                                         rgb[1] = chanel_colormanage_cb(from_float[1]);
331                                                         rgb[2] = chanel_colormanage_cb(from_float[2]);
332                                                         to16[0] = ftoshort(IMB_colormanagement_get_luminance(rgb));
333                                                         to16++; from_float += 3;
334                                                 }
335                                         }
336                                         else {
337                                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
338                                                         to16[0] = ftoshort(chanel_colormanage_cb(from_float[0]));
339                                                         to16++; from_float++;
340                                                 }
341                                         }
342                                 }
343                                 else {
344                                         for (i = ibuf->x * ibuf->y; i > 0; i--) {
345                                                 to16[0] = UPSAMPLE_8_TO_16(from[0]);
346                                                 to16++; from += 4;
347                                         }
348                                 }
349                         }
350                         else {
351                                 for (i = ibuf->x * ibuf->y; i > 0; i--) {
352                                         to[0] = from[0];
353                                         to++; from += 4;
354                                 }
355                         }
356                         break;
357         }
358
359         if (flags & IB_mem) {
360                 /* create image in memory */
361                 imb_addencodedbufferImBuf(ibuf);
362                 ibuf->encodedsize = 0;
363
364                 png_set_write_fn(png_ptr,
365                                  (png_voidp) ibuf,
366                                  WriteData,
367                                  Flush);
368         }
369         else {
370                 fp = BLI_fopen(name, "wb");
371                 if (!fp) {
372                         png_destroy_write_struct(&png_ptr, &info_ptr);
373                         if (pixels)
374                                 MEM_freeN(pixels);
375                         if (pixels16)
376                                 MEM_freeN(pixels16);
377                         printf("imb_savepng: Cannot open file for writing: '%s'\n", name);
378                         return 0;
379                 }
380                 png_init_io(png_ptr, fp);
381         }
382
383 #if 0
384         png_set_filter(png_ptr, 0,
385                        PNG_FILTER_NONE  | PNG_FILTER_VALUE_NONE  |
386                        PNG_FILTER_SUB   | PNG_FILTER_VALUE_SUB   |
387                        PNG_FILTER_UP    | PNG_FILTER_VALUE_UP    |
388                        PNG_FILTER_AVG   | PNG_FILTER_VALUE_AVG   |
389                        PNG_FILTER_PAETH | PNG_FILTER_VALUE_PAETH |
390                        PNG_ALL_FILTERS);
391 #endif
392
393         png_set_compression_level(png_ptr, compression);
394
395         /* png image settings */
396         png_set_IHDR(png_ptr,
397                      info_ptr,
398                      ibuf->x,
399                      ibuf->y,
400                      is_16bit ? 16 : 8,
401                      color_type,
402                      PNG_INTERLACE_NONE,
403                      PNG_COMPRESSION_TYPE_DEFAULT,
404                      PNG_FILTER_TYPE_DEFAULT);
405
406         /* image text info */
407         if (ibuf->metadata) {
408                 png_text *metadata;
409                 IDProperty *prop;
410
411                 int num_text = 0;
412
413                 for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) {
414                         if (prop->type == IDP_STRING) {
415                                 num_text++;
416                         }
417                 }
418                 
419                 metadata = MEM_callocN(num_text * sizeof(png_text), "png_metadata");
420                 num_text = 0;
421                 for (prop = ibuf->metadata->data.group.first; prop; prop = prop->next) {
422                         if (prop->type == IDP_STRING) {
423                                 metadata[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
424                                 metadata[num_text].key = prop->name;
425                                 metadata[num_text].text = IDP_String(prop);
426                                 num_text++;
427                         }
428                 }
429                 
430                 png_set_text(png_ptr, info_ptr, metadata, num_text);
431                 MEM_freeN(metadata);
432
433         }
434
435         if (ibuf->ppm[0] > 0.0 && ibuf->ppm[1] > 0.0) {
436                 png_set_pHYs(png_ptr, info_ptr, (unsigned int)(ibuf->ppm[0] + 0.5), (unsigned int)(ibuf->ppm[1] + 0.5), PNG_RESOLUTION_METER);
437         }
438
439         /* write the file header information */
440         png_write_info(png_ptr, info_ptr);
441
442 #ifdef __LITTLE_ENDIAN__
443         png_set_swap(png_ptr);
444 #endif
445
446         /* allocate memory for an array of row-pointers */
447         row_pointers = (png_bytepp) MEM_mallocN(ibuf->y * sizeof(png_bytep), "row_pointers");
448         if (row_pointers == NULL) {
449                 printf("imb_savepng: Cannot allocate row-pointers array for file '%s'\n", name);
450                 png_destroy_write_struct(&png_ptr, &info_ptr);
451                 if (pixels)
452                         MEM_freeN(pixels);
453                 if (pixels16)
454                         MEM_freeN(pixels16);
455                 if (fp) {
456                         fclose(fp);
457                 }
458                 return 0;
459         }
460
461         /* set the individual row-pointers to point at the correct offsets */
462         if (is_16bit) {
463                 for (i = 0; i < ibuf->y; i++) {
464                         row_pointers[ibuf->y - 1 - i] = (png_bytep)
465                                                         ((unsigned short *)pixels16 + (((size_t)i) * ibuf->x) * bytesperpixel);
466                 }
467         }
468         else {
469                 for (i = 0; i < ibuf->y; i++) {
470                         row_pointers[ibuf->y - 1 - i] = (png_bytep)
471                                                         ((unsigned char *)pixels + (((size_t)i) * ibuf->x) * bytesperpixel * sizeof(unsigned char));
472                 }
473         }
474
475         /* write out the entire image data in one call */
476         png_write_image(png_ptr, row_pointers);
477
478         /* write the additional chunks to the PNG file (not really needed) */
479         png_write_end(png_ptr, info_ptr);
480
481         /* clean up */
482         if (pixels)
483                 MEM_freeN(pixels);
484         if (pixels16)
485                 MEM_freeN(pixels16);
486         MEM_freeN(row_pointers);
487         png_destroy_write_struct(&png_ptr, &info_ptr);
488
489         if (fp) {
490                 fflush(fp);
491                 fclose(fp);
492         }
493
494         return(1);
495 }
496
497 static void imb_png_warning(png_structp UNUSED(png_ptr), png_const_charp message)
498 {
499         /* We suppress iCCP warnings. That's how Blender always used to behave,
500          * and with new libpng it became too much picky, giving a warning on
501          * the splash screen even.
502          */
503         if ((G.debug & G_DEBUG) == 0 && STREQLEN(message, "iCCP", 4)) {
504                 return;
505         }
506         fprintf(stderr, "libpng warning: %s\n", message);
507 }
508
509 static void imb_png_error(png_structp UNUSED(png_ptr), png_const_charp message)
510 {
511         fprintf(stderr, "libpng error: %s\n", message);
512 }
513
514 ImBuf *imb_loadpng(const unsigned char *mem, size_t size, int flags, char colorspace[IM_MAX_SPACE])
515 {
516         struct ImBuf *ibuf = NULL;
517         png_structp png_ptr;
518         png_infop info_ptr;
519         unsigned char *pixels = NULL;
520         unsigned short *pixels16 = NULL;
521         png_bytepp row_pointers = NULL;
522         png_uint_32 width, height;
523         int bit_depth, color_type;
524         PNGReadStruct ps;
525
526         unsigned char *from, *to;
527         unsigned short *from16;
528         float *to_float;
529         unsigned int channels;
530
531         if (imb_is_a_png(mem) == 0) return(NULL);
532
533         /* both 8 and 16 bit PNGs are default to standard byte colorspace */
534         colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
535
536         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,
537                                          NULL, NULL, NULL);
538         if (png_ptr == NULL) {
539                 printf("Cannot png_create_read_struct\n");
540                 return NULL;
541         }
542
543         png_set_error_fn(png_ptr, NULL, imb_png_error, imb_png_warning);
544
545         info_ptr = png_create_info_struct(png_ptr);
546         if (info_ptr == NULL) {
547                 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, 
548                                         (png_infopp)NULL);
549                 printf("Cannot png_create_info_struct\n");
550                 return NULL;
551         }
552
553         ps.size = size; /* XXX, 4gig limit! */
554         ps.data = mem;
555         ps.seek = 0;
556
557         png_set_read_fn(png_ptr, (void *) &ps, ReadData);
558
559         if (setjmp(png_jmpbuf(png_ptr))) {
560                 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
561                 if (pixels) MEM_freeN(pixels);
562                 if (pixels16) MEM_freeN(pixels16);
563                 if (row_pointers) MEM_freeN(row_pointers);
564                 if (ibuf) IMB_freeImBuf(ibuf);
565                 return NULL;
566         }
567
568         // png_set_sig_bytes(png_ptr, 8);
569
570         png_read_info(png_ptr, info_ptr);
571         png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, 
572                      &color_type, NULL, NULL, NULL);
573
574         channels = png_get_channels(png_ptr, info_ptr);
575
576         switch (color_type) {
577                 case PNG_COLOR_TYPE_RGB:
578                 case PNG_COLOR_TYPE_RGB_ALPHA:
579                         break;
580                 case PNG_COLOR_TYPE_PALETTE:
581                         png_set_palette_to_rgb(png_ptr);
582                         if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
583                                 channels = 4;
584                         }
585                         else {
586                                 channels = 3;
587                         }
588                         break;
589                 case PNG_COLOR_TYPE_GRAY:
590                 case PNG_COLOR_TYPE_GRAY_ALPHA:
591                         if (bit_depth < 8) {
592                                 png_set_expand(png_ptr);
593                                 bit_depth = 8;
594                                 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
595                                         /* PNG_COLOR_TYPE_GRAY may also have alpha 'values', like with palette. */
596                                         channels = 2;
597                                 }
598                         }
599                         break;
600                 default:
601                         printf("PNG format not supported\n");
602                         longjmp(png_jmpbuf(png_ptr), 1);
603         }
604         
605         ibuf = IMB_allocImBuf(width, height, 8 * channels, 0);
606
607         if (ibuf) {
608                 ibuf->ftype = IMB_FTYPE_PNG;
609                 if (bit_depth == 16)
610                         ibuf->foptions.flag |= PNG_16BIT;
611
612                 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_pHYs)) {
613                         int unit_type;
614                         png_uint_32 xres, yres;
615
616                         if (png_get_pHYs(png_ptr, info_ptr, &xres, &yres, &unit_type)) {
617                                 if (unit_type == PNG_RESOLUTION_METER) {
618                                         ibuf->ppm[0] = xres;
619                                         ibuf->ppm[1] = yres;
620                                 }
621                         }
622                 }
623         }
624         else {
625                 printf("Couldn't allocate memory for PNG image\n");
626         }
627
628         if (ibuf && ((flags & IB_test) == 0)) {
629                 if (bit_depth == 16) {
630                         imb_addrectfloatImBuf(ibuf);
631                         png_set_swap(png_ptr);
632
633                         pixels16 = imb_alloc_pixels(ibuf->x, ibuf->y, channels, sizeof(png_uint_16), "pixels");
634                         if (pixels16 == NULL || ibuf->rect_float == NULL) {
635                                 printf("Cannot allocate pixels array\n");
636                                 longjmp(png_jmpbuf(png_ptr), 1);
637                         }
638
639                         /* allocate memory for an array of row-pointers */
640                         row_pointers = (png_bytepp) MEM_mallocN((size_t)ibuf->y * sizeof(png_uint_16p), "row_pointers");
641                         if (row_pointers == NULL) {
642                                 printf("Cannot allocate row-pointers array\n");
643                                 longjmp(png_jmpbuf(png_ptr), 1);
644                         }
645
646                         /* set the individual row-pointers to point at the correct offsets */
647                         for (size_t i = 0; i < ibuf->y; i++) {
648                                 row_pointers[ibuf->y - 1 - i] = (png_bytep)
649                                                                 ((png_uint_16 *)pixels16 + (i * ibuf->x) * channels);
650                         }
651
652                         png_read_image(png_ptr, row_pointers);
653
654                         /* copy image data */
655
656                         to_float = ibuf->rect_float;
657                         from16 = pixels16;
658
659                         switch (channels) {
660                                 case 4:
661                                         for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) {
662                                                 to_float[0] = from16[0] / 65535.0;
663                                                 to_float[1] = from16[1] / 65535.0;
664                                                 to_float[2] = from16[2] / 65535.0;
665                                                 to_float[3] = from16[3] / 65535.0;
666                                                 to_float += 4; from16 += 4;
667                                         }
668                                         break;
669                                 case 3:
670                                         for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) {
671                                                 to_float[0] = from16[0] / 65535.0;
672                                                 to_float[1] = from16[1] / 65535.0;
673                                                 to_float[2] = from16[2] / 65535.0;
674                                                 to_float[3] = 1.0;
675                                                 to_float += 4; from16 += 3;
676                                         }
677                                         break;
678                                 case 2:
679                                         for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) {
680                                                 to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0;
681                                                 to_float[3] = from16[1] / 65535.0;
682                                                 to_float += 4; from16 += 2;
683                                         }
684                                         break;
685                                 case 1:
686                                         for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) {
687                                                 to_float[0] = to_float[1] = to_float[2] = from16[0] / 65535.0;
688                                                 to_float[3] = 1.0;
689                                                 to_float += 4; from16++;
690                                         }
691                                         break;
692                         }
693                 }
694                 else {
695                         imb_addrectImBuf(ibuf);
696
697                         pixels = imb_alloc_pixels(ibuf->x, ibuf->y, channels, sizeof(unsigned char), "pixels");
698                         if (pixels == NULL || ibuf->rect == NULL) {
699                                 printf("Cannot allocate pixels array\n");
700                                 longjmp(png_jmpbuf(png_ptr), 1);
701                         }
702
703                         /* allocate memory for an array of row-pointers */
704                         row_pointers = (png_bytepp) MEM_mallocN((size_t)ibuf->y * sizeof(png_bytep), "row_pointers");
705                         if (row_pointers == NULL) {
706                                 printf("Cannot allocate row-pointers array\n");
707                                 longjmp(png_jmpbuf(png_ptr), 1);
708                         }
709
710                         /* set the individual row-pointers to point at the correct offsets */
711                         for (int i = 0; i < ibuf->y; i++) {
712                                 row_pointers[ibuf->y - 1 - i] = (png_bytep)
713                                                                 ((unsigned char *)pixels + (((size_t)i) * ibuf->x) * channels * sizeof(unsigned char));
714                         }
715
716                         png_read_image(png_ptr, row_pointers);
717
718                         /* copy image data */
719
720                         to = (unsigned char *) ibuf->rect;
721                         from = pixels;
722
723                         switch (channels) {
724                                 case 4:
725                                         for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) {
726                                                 to[0] = from[0];
727                                                 to[1] = from[1];
728                                                 to[2] = from[2];
729                                                 to[3] = from[3];
730                                                 to += 4; from += 4;
731                                         }
732                                         break;
733                                 case 3:
734                                         for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) {
735                                                 to[0] = from[0];
736                                                 to[1] = from[1];
737                                                 to[2] = from[2];
738                                                 to[3] = 0xff;
739                                                 to += 4; from += 3;
740                                         }
741                                         break;
742                                 case 2:
743                                         for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) {
744                                                 to[0] = to[1] = to[2] = from[0];
745                                                 to[3] = from[1];
746                                                 to += 4; from += 2;
747                                         }
748                                         break;
749                                 case 1:
750                                         for (size_t i = (size_t)ibuf->x * (size_t)ibuf->y; i > 0; i--) {
751                                                 to[0] = to[1] = to[2] = from[0];
752                                                 to[3] = 0xff;
753                                                 to += 4; from++;
754                                         }
755                                         break;
756                         }
757                 }
758
759                 if (flags & IB_metadata) {
760                         png_text *text_chunks;
761                         int count = png_get_text(png_ptr, info_ptr, &text_chunks, NULL);
762                         IMB_metadata_ensure(&ibuf->metadata);
763                         for (int i = 0; i < count; i++) {
764                                 IMB_metadata_set_field(ibuf->metadata, text_chunks[i].key, text_chunks[i].text);
765                                 ibuf->flags |= IB_metadata;
766                         }
767                 }
768
769                 png_read_end(png_ptr, info_ptr);
770         }
771
772         /* clean up */
773         if (pixels)
774                 MEM_freeN(pixels);
775         if (pixels16)
776                 MEM_freeN(pixels16);
777         if (row_pointers)
778                 MEM_freeN(row_pointers);
779         png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
780
781         return(ibuf);
782 }
783