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