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