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