A Survey of Gaussian Convolution Algorithms
imageio.c
Go to the documentation of this file.
1 
42 #include "imageio.h"
43 #include <string.h>
44 #include <ctype.h>
45 
46 #ifdef USE_LIBPNG
47 #include <png.h>
48 #if PNG_LIBPNG_VER < 10400
49 /* For compatibility with older libpng */
50 #define png_set_expand_gray_1_2_4_to_8 png_set_gray_1_2_4_to_8
51 #endif
52 #endif
53 #ifdef USE_LIBTIFF
54 #include <tiffio.h>
55 #endif
56 #ifdef USE_LIBJPEG
57 #include <jpeglib.h>
58 #include <setjmp.h>
59 #endif
60 
62 #define FILE_BUFFER_CAPACITY (1024*4)
63 
64 #define ROUNDCLAMPF(x) ((x < 0.0f) ? 0 : \
65  ((x > 1.0f) ? 255 : (uint8_t)(255.0f*(x) + 0.5f)))
66 #define ROUNDCLAMP(x) ((x < 0.0) ? 0 : \
67  ((x > 1.0) ? 255 : (uint8_t)(255.0*(x) + 0.5)))
68 
69 
71 static int string_ends_with(const char *string, const char *suffix)
72 {
73  unsigned string_length = strlen(string), suffix_length = strlen(suffix);
74  unsigned i;
75 
76  if (string_length < suffix_length)
77  return 0;
78 
79  string += string_length - suffix_length;
80 
81  for (i = 0; i < suffix_length; ++i)
82  if (tolower(string[i]) != tolower(suffix[i]))
83  return 0;
84 
85  return 1;
86 }
87 
88 
90 static void fill_image(uint32_t *image, int width, int height, uint32_t color)
91 {
92  int x, y;
93 
94  if (image)
95  for (y = 0; y < height; ++y, image += width)
96  for (x = 0; x < width; ++x)
97  image[x] = color;
98 }
99 
100 
115 static uint32_t *get_image_palette(int *num_colors, int *use_color,
116  int *use_alpha, const uint32_t *image, int width, int height)
117 {
118  const int max_colors = 256;
119  uint32_t *palette = NULL;
120  uint32_t pixel;
121  int x, y, i, red, green, blue, alpha;
122 
123 
124  if (!use_color || !num_colors || !use_alpha)
125  return NULL;
126  else if (!image
127  || !(palette = (uint32_t *)malloc(sizeof(uint32_t)*max_colors)))
128  {
129  *num_colors = -1;
130  *use_color = *use_alpha = 1;
131  return NULL;
132  }
133 
134  *num_colors = *use_color = *use_alpha = 0;
135 
136  for (y = 0; y < height; ++y)
137  {
138  for (x = 0; x < width; ++x)
139  {
140  pixel = *(image++);
141  red = ((uint8_t *)&pixel)[0];
142  green = ((uint8_t *)&pixel)[1];
143  blue = ((uint8_t *)&pixel)[2];
144  alpha = ((uint8_t *)&pixel)[3];
145 
146  if (red != green || red != blue) /* Check color */
147  *use_color = 1;
148 
149  if (alpha != 255) /* Check alpha */
150  *use_alpha = 1;
151 
152  /* Check palette colors (if *num_colors != -1) */
153  for (i = 0; i < *num_colors; ++i)
154  if (pixel == palette[i])
155  break;
156 
157  if (i == *num_colors)
158  {
159  if (i < max_colors)
160  { /* Add new color to palette */
161  palette[i] = pixel;
162  (*num_colors)++;
163  }
164  else
165  { /* Maximum size for palette exceeded */
166  free(palette);
167  palette = NULL;
168  *num_colors = -1; /* Don't check palette colors */
169  }
170  }
171  }
172  }
173 
174  return palette;
175 }
176 
177 
179 static uint16_t read_u16_le(FILE *file)
180 {
181  uint16_t w;
182  w = (uint16_t) getc(file);
183  w |= ((uint16_t) getc(file) << 8);
184  return w;
185 }
186 
187 
189 static uint32_t read_u32_le(FILE *file)
190 {
191  uint32_t dw;
192  dw = (uint32_t) getc(file);
193  dw |= ((uint32_t) getc(file) << 8);
194  dw |= ((uint32_t) getc(file) << 16);
195  dw |= ((uint32_t) getc(file) << 24);
196  return dw;
197 }
198 
199 
201 static void write_u16_le(uint16_t w, FILE *file)
202 {
203  putc(w & 0xFF, file);
204  putc((w & 0xFF00) >> 8, file);
205 }
206 
207 
209 static void write_u32_le(uint32_t dw, FILE *file)
210 {
211  putc(dw & 0xFF, file);
212  putc((dw & 0xFF00) >> 8, file);
213  putc((dw & 0xFF0000) >> 16, file);
214  putc((dw & 0xFF000000) >> 24, file);
215 }
216 
217 
219 static int read_bmp_1bpp(uint32_t *image, int width, int height,
220  FILE *file, const uint32_t *palette)
221 {
222  int row_padding = (-(width + 7) / 8) & 3;
223  int x, y, bit;
224  unsigned code;
225 
226  image += ((long int)width) * ((long int)height - 1);
227 
228  for (y = height; y; --y, image -= width)
229  {
230  if (feof(file))
231  return 0;
232 
233  for (x = 0; x < width;)
234  {
235  code = getc(file);
236 
237  for (bit = 7; bit >= 0 && x < width; --bit, code <<= 1)
238  image[x++] = palette[(code & 0x80) ? 1:0];
239  }
240 
241  for (x = row_padding; x; --x)
242  getc(file); /* Skip padding bytes at the end of the row */
243  }
244 
245  return 1;
246 }
247 
248 
250 static int read_bmp_4bpp(uint32_t *image, int width, int height,
251  FILE *file, const uint32_t *palette)
252 {
253  int row_padding = (-(width + 1) / 2) & 3;
254  int x, y;
255  unsigned code;
256 
257  image += ((long int)width) * ((long int)height - 1);
258 
259  for (y = height; y; --y, image -= width)
260  {
261  if (feof(file))
262  return 0;
263 
264  for (x = 0; x < width;)
265  {
266  code = getc(file);
267  image[x++] = palette[(code & 0xF0) >> 4];
268 
269  if (x < width)
270  image[x++] = palette[code & 0x0F];
271  }
272 
273  for (x = row_padding; x; --x)
274  getc(file); /* Skip padding bytes at the end of the row */
275  }
276 
277  return 1;
278 }
279 
280 
282 static int read_bmp_4bpp_rle(uint32_t *image, int width, int height,
283  FILE *file, const uint32_t *palette)
284 {
285  int x, y, dy, k;
286  unsigned count, value;
287  uint32_t color_high, color_low;
288 
289  fill_image(image, width, height, palette[0]);
290  image += ((long int)width) * ((long int)height - 1);
291 
292  for (x = 0, y = height; y;)
293  {
294  if (feof(file))
295  return 0;
296 
297  count = getc(file);
298  value = getc(file);
299 
300  if (!count)
301  { /* count = 0 is the escape code */
302  switch (value)
303  {
304  case 0: /* End of line */
305  image -= width;
306  x = 0;
307  y--;
308  break;
309  case 1: /* End of bitmap */
310  return 1;
311  case 2: /* Delta */
312  x += getc(file);
313  dy = getc(file);
314  y -= dy;
315  image -= dy*width;
316 
317  if (x >= width || y < 0)
318  return 0;
319  break;
320  default:
321  /* Read a run of uncompressed data (value = length of run) */
322  count = k = value;
323 
324  if (x >= width)
325  return 0;
326 
327  do
328  {
329  value = getc(file);
330  image[x++] = palette[(value & 0xF0) >> 4];
331 
332  if (x >= width)
333  break;
334 
335  if (--k)
336  {
337  image[x++] = palette[value & 0x0F];
338  k--;
339 
340  if (x >= width)
341  break;
342  }
343  }while (k);
344 
345  if (((count + 1)/2) & 1)
346  getc(file); /* Padding for word align */
347  }
348  }
349  else
350  { /* Run of pixels (count = length of run) */
351  color_high = palette[(value & 0xF0) >> 4];
352  color_low = palette[value & 0xF];
353 
354  if (x >= width)
355  return 0;
356 
357  do
358  {
359  image[x++] = color_high;
360  count--;
361 
362  if (x >= width)
363  break;
364 
365  if (count)
366  {
367  image[x++] = color_low;
368  count--;
369 
370  if (x >= width)
371  break;
372  }
373  }while (count);
374  }
375  }
376 
377  return 1;
378 }
379 
380 
382 static int read_bmp_8bpp(uint32_t *image, int width, int height,
383  FILE *file, const uint32_t *palette)
384 {
385  int row_padding = (-width) & 3;
386  int x, y;
387 
388  image += ((long int)width) * ((long int)height - 1);
389 
390  for (y = height; y; --y, image -= width)
391  {
392  if (feof(file))
393  return 0;
394 
395  for (x = 0; x < width; ++x)
396  image[x] = palette[getc(file) & 0xFF];
397 
398  for (x = row_padding; x; --x)
399  getc(file); /* Skip padding bytes at the end of the row */
400  }
401 
402  return 1;
403 }
404 
405 
407 static int read_bmp_8bpp_rle(uint32_t *image, int width, int height,
408  FILE *file, const uint32_t *palette)
409 {
410  int x, y, dy, k;
411  unsigned count, value;
412  uint32_t color;
413 
414  fill_image(image, width, height, palette[0]);
415  image += ((long int)width) * ((long int)height - 1);
416 
417  for (x = 0, y = height; y;)
418  {
419  if (feof(file))
420  return 0;
421 
422  count = getc(file);
423  value = getc(file);
424 
425  if (!count)
426  { /* count = 0 is the escape code */
427  switch (value)
428  {
429  case 0: /* End of line */
430  image -= width;
431  x = 0;
432  y--;
433  break;
434  case 1: /* End of bitmap */
435  return 1;
436  case 2: /* Delta */
437  x += getc(file);
438  dy = getc(file);
439  y -= dy;
440  image -= dy*width;
441 
442  if (x >= width || y < 0)
443  return 0;
444  break;
445  default:
446  /* Read a run of uncompressed data (value = length of run) */
447  count = k = value;
448 
449  do
450  {
451  if (x >= width)
452  break;
453 
454  image[x++] = palette[getc(file) & 0xFF];
455  }while (--k);
456 
457  if (count&1)
458  getc(file); /* Padding for word align */
459  }
460  }
461  else
462  { /* Run of pixels equal to value (count = length of run) */
463  color = palette[value & 0xFF];
464 
465  do
466  {
467  if (x >= width)
468  break;
469 
470  image[x++] = color;
471  }while (--count);
472  }
473  }
474 
475  return 1;
476 }
477 
478 
480 static int read_bmp_24bpp(uint32_t *image, int width, int height, FILE *file)
481 {
482  uint8_t *image_ptr = (uint8_t *)image;
483  int row_padding = (-3*width) & 3;
484  int x, y;
485 
486  width <<= 2;
487  image_ptr += ((long int)width)*((long int)height - 1);
488 
489  for (y = height; y; --y, image_ptr -= width)
490  {
491  if (feof(file))
492  return 0;
493 
494  for (x = 0; x < width; x += 4)
495  {
496  image_ptr[x+3] = 255; /* Set alpha */
497  image_ptr[x+2] = getc(file); /* Read blue component */
498  image_ptr[x+1] = getc(file); /* Read green component */
499  image_ptr[x+0] = getc(file); /* Read red component */
500  }
501 
502  for (x = row_padding; x; --x)
503  getc(file); /* Skip padding bytes at the end of the row */
504  }
505 
506  return 1;
507 }
508 
510 static void get_mask_shifts(uint32_t mask, int *left_shift, int *right_shift)
511 {
512  int shift = 0, bitcount = 0;
513 
514  if (!mask)
515  {
516  *left_shift = 0;
517  *right_shift = 0;
518  return;
519  }
520 
521  while (!(mask & 1)) /* Find the first true bit */
522  {
523  mask >>= 1;
524  ++shift;
525  }
526 
527  /* Adjust the result for scaling to 8-bit quantities */
528  while (mask & 1) /* count the number of true bits */
529  {
530  mask >>= 1;
531  ++bitcount;
532  }
533 
534  /* Compute a signed shift (right is positive) */
535  shift += bitcount - 8;
536 
537  if (shift >= 0)
538  {
539  *left_shift = 0;
540  *right_shift = shift;
541  }
542  else
543  {
544  *left_shift = -shift;
545  *right_shift = 0;
546  }
547 }
548 
550 static int read_bmp_16bpp(uint32_t *image, int width, int height, FILE *file,
551  uint32_t redmask, uint32_t greenmask,
552  uint32_t bluemask, uint32_t alphamask)
553 {
554  uint8_t *image_ptr = (uint8_t *)image;
555  uint32_t code;
556  int row_padding = (-2 * width) & 3;
557  int redleft_shift, greenleft_shift, blueleft_shift, alphaleft_shift;
558  int redright_shift, greenright_shift, blueright_shift, alpharight_shift;
559  int x, y;
560 
561  get_mask_shifts(redmask, &redleft_shift, &redright_shift);
562  get_mask_shifts(greenmask, &greenleft_shift, &greenright_shift);
563  get_mask_shifts(bluemask, &blueleft_shift, &blueright_shift);
564  get_mask_shifts(alphamask, &alphaleft_shift, &alpharight_shift);
565  width <<= 2;
566  image_ptr += ((long int)width) * ((long int)height - 1);
567 
568  for (y = height; y; --y, image_ptr -= width)
569  {
570  if (feof(file))
571  return 0;
572 
573  for (x = 0; x < width; x += 4)
574  {
575  code = read_u16_le(file);
576  /* By the Windows 4.x BMP specification, masks must be contiguous
577  <http://www.fileformat.info/format/bmp/egff.htm>. So we can
578  decode bitfields by bitshifting and bitwise AND. */
579  image_ptr[x + 3] = ((code & alphamask) >> alpharight_shift)
580  << alphaleft_shift;
581  image_ptr[x + 2] = ((code & bluemask ) >> blueright_shift )
582  << blueleft_shift;
583  image_ptr[x + 1] = ((code & greenmask) >> greenright_shift)
584  << greenleft_shift;
585  image_ptr[x + 0] = ((code & redmask ) >> redright_shift )
586  << redleft_shift;
587  }
588 
589  for (x = row_padding; x; --x)
590  getc(file); /* Skip padding bytes at the end of the row */
591  }
592 
593  return 1;
594 }
595 
596 
598 static int read_bmp_32bpp(uint32_t *image, int width, int height, FILE *file,
599  uint32_t redmask, uint32_t greenmask,
600  uint32_t bluemask, uint32_t alphamask)
601 {
602  uint8_t *image_ptr;
603  uint32_t code;
604  int redleft_shift, greenleft_shift, blueleft_shift, alphaleft_shift;
605  int redright_shift, greenright_shift, blueright_shift, alpharight_shift;
606  int x, y;
607 
608  get_mask_shifts(redmask, &redleft_shift, &redright_shift);
609  get_mask_shifts(greenmask, &greenleft_shift, &greenright_shift);
610  get_mask_shifts(bluemask, &blueleft_shift, &blueright_shift);
611  get_mask_shifts(alphamask, &alphaleft_shift, &alpharight_shift);
612  width <<= 2;
613  image_ptr = (uint8_t *)image + ((long int)width)*((long int)height - 1);
614 
615  for (y = height; y; --y, image_ptr -= width)
616  {
617  if (feof(file))
618  return 0;
619 
620  for (x = 0; x < width; x += 4)
621  {
622  code = read_u32_le(file);
623  image_ptr[x + 3] = ((code & alphamask) >> alpharight_shift)
624  << alphaleft_shift;
625  image_ptr[x + 2] = ((code & bluemask ) >> blueright_shift )
626  << blueleft_shift;
627  image_ptr[x + 1] = ((code & greenmask) >> greenright_shift)
628  << greenleft_shift;
629  image_ptr[x + 0] = ((code & redmask ) >> redright_shift )
630  << redleft_shift;
631  }
632  }
633 
634  return 1;
635 }
636 
650 static int read_bmp(uint32_t **image, int *width, int *height, FILE *file)
651 {
652  uint32_t *palette = NULL;
653  uint8_t *palette_ptr;
654  long int image_data_offset, info_size;
655  unsigned i, num_planes, bits_per_pixel, compression, num_colors;
656  uint32_t redmask, greenmask, bluemask, alphamask;
657  int success = 0, os2bmp;
658  uint8_t magic[2];
659 
660  *image = NULL;
661  *width = *height = 0;
662  fseek(file, 0, SEEK_SET);
663 
664  magic[0] = getc(file);
665  magic[1] = getc(file);
666 
667  if (!(magic[0] == 0x42 && magic[1] == 0x4D) /* Verify the magic numbers */
668  || fseek(file, 8, SEEK_CUR)) /* Skip the reserved fields */
669  {
670  fprintf(stderr, "Invalid BMP header.\n");
671  goto fail;
672  }
673 
674  image_data_offset = read_u32_le(file);
675  info_size = read_u32_le(file);
676 
677  /* Read the info header */
678  if (info_size < 12)
679  {
680  fprintf(stderr, "Invalid BMP info header.\n");
681  goto fail;
682  }
683 
684  if ((os2bmp = (info_size == 12))) /* This is an OS/2 V1 infoheader */
685  {
686  *width = (int)read_u16_le(file);
687  *height = (int)read_u16_le(file);
688  num_planes = (unsigned)read_u16_le(file);
689  bits_per_pixel = (unsigned)read_u16_le(file);
690  compression = 0;
691  num_colors = 0;
692  redmask = 0x00FF0000;
693  greenmask = 0x0000FF00;
694  bluemask = 0x000000FF;
695  alphamask = 0xFF000000;
696  }
697  else
698  {
699  *width = abs((int)read_u32_le(file));
700  *height = abs((int)read_u32_le(file));
701  num_planes = (unsigned)read_u16_le(file);
702  bits_per_pixel = (unsigned)read_u16_le(file);
703  compression = (unsigned)read_u32_le(file);
704  fseek(file, 12, SEEK_CUR);
705  num_colors = (unsigned)read_u32_le(file);
706  fseek(file, 4, SEEK_CUR);
707  redmask = read_u32_le(file);
708  greenmask = read_u32_le(file);
709  bluemask = read_u32_le(file);
710  alphamask = read_u32_le(file);
711  }
712 
713  /* Check for problems or unsupported compression modes */
714  if (*width > MAX_IMAGE_SIZE || *height > MAX_IMAGE_SIZE)
715  {
716  fprintf(stderr, "image dimensions exceed MAX_IMAGE_SIZE.\n");
717  goto fail;
718  }
719 
720  if (feof(file) || num_planes != 1 || compression > 3)
721  goto fail;
722 
723  /* Allocate the image data */
724  if (!(*image = (uint32_t *)malloc(
725  sizeof(uint32_t)*((long int)*width)*((long int)*height))))
726  goto fail;
727 
728  /* Read palette */
729  if (bits_per_pixel <= 8)
730  {
731  fseek(file, 14 + info_size, SEEK_SET);
732 
733  if (!num_colors)
734  num_colors = 1 << bits_per_pixel;
735 
736  if (!(palette = (uint32_t *)malloc(sizeof(uint32_t)*256)))
737  goto fail;
738 
739  for (i = 0, palette_ptr = (uint8_t *)palette; i < num_colors; ++i)
740  {
741  palette_ptr[3] = 255; /* Set alpha */
742  palette_ptr[2] = getc(file); /* Read blue component */
743  palette_ptr[1] = getc(file); /* Read green component */
744  palette_ptr[0] = getc(file); /* Read red component */
745  palette_ptr += 4;
746 
747  if (!os2bmp)
748  getc(file); /* Skip extra byte (for non-OS/2 bitmaps) */
749  }
750 
751  /* Fill the rest of the palette with the first color */
752  for (; i < 256; ++i)
753  palette[i] = palette[0];
754  }
755 
756  if (fseek(file, image_data_offset, SEEK_SET) || feof(file))
757  {
758  fprintf(stderr, "file error.\n");
759  goto fail;
760  }
761 
762  /*** Read the bitmap image data ***/
763  switch (compression)
764  {
765  case 0: /* Uncompressed data */
766  switch (bits_per_pixel)
767  {
768  case 1: /* Read 1-bit uncompressed indexed data */
769  success = read_bmp_1bpp(
770  *image, *width, *height, file, palette);
771  break;
772  case 4: /* Read 4-bit uncompressed indexed data */
773  success = read_bmp_4bpp(
774  *image, *width, *height, file, palette);
775  break;
776  case 8: /* Read 8-bit uncompressed indexed data */
777  success = read_bmp_8bpp(
778  *image, *width, *height, file, palette);
779  break;
780  case 24: /* Read 24-bit BGR image data */
781  success = read_bmp_24bpp(*image, *width, *height, file);
782  break;
783  case 16: /* Read 16-bit data */
784  success = read_bmp_16bpp(*image, *width, *height, file,
785  0x001F << 10, 0x001F << 5, 0x0001F, 0);
786  break;
787  case 32: /* Read 32-bit BGRA image data */
788  success = read_bmp_32bpp(*image, *width, *height, file,
789  0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
790  break;
791  }
792  break;
793  case 1: /* 8-bit RLE */
794  if (bits_per_pixel == 8)
795  success = read_bmp_8bpp_rle(
796  *image, *width, *height, file, palette);
797  break;
798  case 2: /* 4-bit RLE */
799  if (bits_per_pixel == 4)
800  success = read_bmp_4bpp_rle(
801  *image, *width, *height, file, palette);
802  break;
803  case 3: /* bitfields data */
804  switch (bits_per_pixel)
805  {
806  case 16: /* Read 16-bit bitfields data */
807  success = read_bmp_16bpp(*image, *width, *height, file,
808  redmask, greenmask, bluemask, alphamask);
809  break;
810  case 32: /* Read 32-bit bitfields data */
811  success = read_bmp_32bpp(*image, *width, *height, file,
812  redmask, greenmask, bluemask, alphamask);
813  break;
814  }
815  break;
816  }
817 
818  if (!success)
819  fprintf(stderr, "Error reading BMP data.\n");
820 
821 fail: /* There was a problem, clean up and exit */
822  if (palette)
823  free(palette);
824 
825  if (!success && *image)
826  free(*image);
827 
828  return success;
829 }
830 
831 
853 static int write_bmp(const uint32_t *image, int width, int height, FILE *file)
854 {
855  const uint8_t *image_ptr = (uint8_t *)image;
856  uint32_t *palette = NULL;
857  uint32_t pixel;
858  long int imageSize;
859  int use_palette, num_colors, use_color, use_alpha;
860  int x, y, i, row_padding, success = 0;
861 
862 
863  if (!image)
864  return 0;
865 
866  palette = get_image_palette(&num_colors, &use_color, &use_alpha,
867  image, width, height);
868 
869  /* Decide whether to use 8-bit palette or 24-bit RGB format */
870  if (palette && 2*num_colors < width*height)
871  use_palette = 1;
872  else
873  use_palette = num_colors = 0;
874 
875  /* Tell file to use buffering */
876  setvbuf(file, 0, _IOFBF, FILE_BUFFER_CAPACITY);
877 
878  if (use_palette)
879  {
880  row_padding = (-width)&3;
881  imageSize = (width + row_padding)*((long int)height);
882  }
883  else
884  {
885  row_padding = (-3*width)&3;
886  imageSize = (3*width + row_padding)*((long int)height);
887  }
888 
889  /*** Write the header ***/
890 
891  /* Write the BMP header */
892  putc(0x42, file); /* Magic numbers */
893  putc(0x4D, file);
894 
895  /* filesize */
896  write_u32_le(54 + 4*num_colors + imageSize, file);
897 
898  write_u32_le(0, file); /* Reserved fields */
899  write_u32_le(54 + 4*num_colors, file); /* Image data offset */
900 
901  /* Write the infoheader */
902  write_u32_le(40, file); /* infoheader size */
903  write_u32_le(width, file); /* Image width */
904  write_u32_le(height, file); /* Image height */
905  write_u16_le(1, file); /* Number of colorplanes */
906  write_u16_le((use_palette) ? 8:24, file); /* Bits per pixel */
907  write_u32_le(0, file); /* Compression method (none) */
908  write_u32_le(imageSize, file); /* Image size */
909  write_u32_le(2835, file); /* HResolution (2835=72dpi) */
910  write_u32_le(2835, file); /* VResolution */
911 
912  /* Number of colors */
913  write_u32_le((!use_palette || num_colors == 256) ? 0:num_colors, file);
914 
915  write_u32_le(0, file); /* Important colors */
916 
917  if (ferror(file))
918  {
919  fprintf(stderr, "Error during write to file.\n");
920  goto fail;
921  }
922 
923  if (use_palette)
924  { /* Write the palette */
925  for (i = 0; i < num_colors; ++i)
926  {
927  pixel = palette[i];
928  putc(((uint8_t *)&pixel)[2], file); /* Blue */
929  putc(((uint8_t *)&pixel)[1], file); /* Green */
930  putc(((uint8_t *)&pixel)[0], file); /* Red */
931  putc(0, file); /* Unused */
932  }
933  }
934 
935  /* Write the image data */
936  width <<= 2;
937  image_ptr += ((long int)width)*((long int)height - 1);
938 
939  for (y = height; y; --y, image_ptr -= width)
940  {
941  if (use_palette)
942  { /* 8-bit palette image data */
943  for (x = 0; x < width; x += 4)
944  {
945  pixel = *((uint32_t *)(image_ptr + x));
946 
947  for (i = 0; i < num_colors; ++i)
948  if (pixel == palette[i])
949  break;
950 
951  putc(i, file);
952  }
953  }
954  else
955  { /* 24-bit RGB image data */
956  for (x = 0; x < width; x += 4)
957  {
958  putc(image_ptr[x+2], file); /* Write blue component */
959  putc(image_ptr[x+1], file); /* Write green component */
960  putc(image_ptr[x+0], file); /* Write red component */
961  }
962  }
963 
964  for (x = row_padding; x; --x) /* Write row padding */
965  putc(0, file);
966  }
967 
968  if (ferror(file))
969  {
970  fprintf(stderr, "Error during write to file.\n");
971  goto fail;
972  }
973 
974  success = 1;
975 fail:
976  if (palette)
977  free(palette);
978  return success;
979 }
980 
981 
982 #ifdef USE_LIBJPEG
983 
989 typedef struct{
990  struct jpeg_error_mgr pub;
991  jmp_buf jmpbuf;
992 } hooked_jerr;
993 
994 
996 METHODDEF(void) jerr_exit(j_common_ptr cinfo)
997 {
998  hooked_jerr *jerr = (hooked_jerr *) cinfo->err;
999  (*cinfo->err->output_message)(cinfo);
1000  longjmp(jerr->jmpbuf, 1);
1001 }
1002 
1003 
1018 static int read_jpeg(uint32_t **image, int *width, int *height, FILE *file)
1019 {
1020  struct jpeg_decompress_struct cinfo;
1021  hooked_jerr jerr;
1022  JSAMPARRAY buffer;
1023  uint8_t *image_ptr;
1024  unsigned i, row_size;
1025 
1026  *image = NULL;
1027  *width = *height = 0;
1028  cinfo.err = jpeg_std_error(&jerr.pub);
1029  jerr.pub.error_exit = jerr_exit;
1030 
1031  if (setjmp(jerr.jmpbuf))
1032  { /* If this code is reached, libjpeg has signaled an error. */
1033  goto fail;
1034  }
1035 
1036  jpeg_create_decompress(&cinfo);
1037  jpeg_stdio_src(&cinfo, file);
1038  jpeg_read_header(&cinfo, 1);
1039  cinfo.out_color_space = JCS_RGB; /* Ask for RGB image data. */
1040  jpeg_start_decompress(&cinfo);
1041  *width = (int)cinfo.output_width;
1042  *height = (int)cinfo.output_height;
1043 
1044  if (*width > MAX_IMAGE_SIZE || *height > MAX_IMAGE_SIZE)
1045  {
1046  fprintf(stderr, "image dimensions exceed MAX_IMAGE_SIZE.\n");
1047  jpeg_abort_decompress(&cinfo);
1048  goto fail;
1049  }
1050 
1051  /* Allocate image memory */
1052  if (!(*image = (uint32_t *)malloc(sizeof(uint32_t)
1053  * ((size_t)*width) * ((size_t)*height))))
1054  {
1055  jpeg_abort_decompress(&cinfo);
1056  goto fail;
1057  }
1058 
1059  /* Allocate a one-row-high array that will go away when done. */
1060  row_size = cinfo.output_width * cinfo.output_components;
1061  buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo,
1062  JPOOL_IMAGE, row_size, 1);
1063  image_ptr = (uint8_t *)*image;
1064 
1065  while (cinfo.output_scanline < cinfo.output_height)
1066  for (jpeg_read_scanlines(&cinfo, buffer, 1), i = 0;
1067  i < row_size; i += 3)
1068  {
1069  *(image_ptr++) = buffer[0][i]; /* Red */
1070  *(image_ptr++) = buffer[0][i + 1]; /* Green */
1071  *(image_ptr++) = buffer[0][i + 2]; /* Blue */
1072  *(image_ptr++) = 0xFF;
1073  }
1074 
1075  jpeg_finish_decompress(&cinfo);
1076  jpeg_destroy_decompress(&cinfo);
1077  return 1;
1078 
1079 fail:
1080  if (*image)
1081  free(*image);
1082 
1083  *width = *height = 0;
1084  jpeg_destroy_decompress(&cinfo);
1085  return 0;
1086 }
1087 
1088 
1107 static int write_jpeg(const uint32_t *const image,
1108  int width, int height, FILE *file, int quality)
1109 {
1110  struct jpeg_compress_struct cinfo;
1111  hooked_jerr jerr;
1112  uint8_t *buffer = NULL, *image_ptr;
1113  unsigned i, row_size;
1114 
1115  if (!image)
1116  return 0;
1117 
1118  cinfo.err = jpeg_std_error(&jerr.pub);
1119  jerr.pub.error_exit = jerr_exit;
1120 
1121  if (setjmp(jerr.jmpbuf))
1122  goto fail; /* libjpeg has signaled an error. */
1123 
1124  jpeg_create_compress(&cinfo);
1125  jpeg_stdio_dest(&cinfo, file);
1126  cinfo.image_width = width;
1127  cinfo.image_height = height;
1128  cinfo.input_components = 3;
1129  cinfo.in_color_space = JCS_RGB;
1130  jpeg_set_defaults(&cinfo);
1131  jpeg_set_quality(&cinfo, (quality < 100) ? quality : 100, 1);
1132  jpeg_start_compress(&cinfo, 1);
1133 
1134  row_size = 3 * width;
1135  image_ptr = (uint8_t *)image;
1136 
1137  if (!(buffer = (uint8_t *)malloc(row_size)))
1138  goto fail;
1139 
1140  while (cinfo.next_scanline < cinfo.image_height)
1141  {
1142  for (i = 0; i < row_size; i += 3)
1143  {
1144  buffer[i] = image_ptr[0]; /* Red */
1145  buffer[i + 1] = image_ptr[1]; /* Green */
1146  buffer[i + 2] = image_ptr[2]; /* Blue */
1147  image_ptr += 4;
1148  }
1149 
1150  jpeg_write_scanlines(&cinfo, &buffer, 1);
1151  }
1152 
1153  if (buffer)
1154  free(buffer);
1155 
1156  jpeg_finish_compress(&cinfo);
1157  jpeg_destroy_compress(&cinfo);
1158  return 1;
1159 fail:
1160  if (buffer)
1161  free(buffer);
1162 
1163  jpeg_destroy_compress(&cinfo);
1164  return 0;
1165 }
1166 #endif /* USE_LIBJPEG */
1167 
1168 
1169 #ifdef USE_LIBPNG
1170 
1183 static int read_png(uint32_t **image, int *width, int *height, FILE *file)
1184 {
1185  png_bytep *row_pointers;
1186  png_byte header[8];
1187  png_structp png;
1188  png_infop info;
1189  png_uint_32 png_width, png_height;
1190  int bit_depth, color_type, interlace_type;
1191  unsigned row;
1192 
1193  *image = NULL;
1194  *width = *height = 0;
1195 
1196  /* Check that file is a PNG file. */
1197  if (fread(header, 1, 8, file) != 8 || png_sig_cmp(header, 0, 8))
1198  return 0;
1199 
1200  /* Read the info header. */
1201  if (!(png = png_create_read_struct(
1202  PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))
1203  || !(info = png_create_info_struct(png)))
1204  {
1205  if (png)
1206  png_destroy_read_struct(&png, (png_infopp)NULL, (png_infopp)NULL);
1207 
1208  return 0;
1209  }
1210 
1211  if (setjmp(png_jmpbuf(png)))
1212  goto fail; /* libpng has signaled an error. */
1213 
1214  png_init_io(png, file);
1215  png_set_sig_bytes(png, 8);
1216  png_set_user_limits(png, MAX_IMAGE_SIZE, MAX_IMAGE_SIZE);
1217  png_read_info(png, info);
1218  png_get_IHDR(png, info, &png_width, &png_height, &bit_depth, &color_type,
1219  &interlace_type, (int*)NULL, (int*)NULL);
1220  *width = (int)png_width;
1221  *height = (int)png_height;
1222 
1223  /* Tell libpng to convert everything to 32-bit RGBA. */
1224  if (color_type == PNG_COLOR_TYPE_PALETTE)
1225  png_set_palette_to_rgb(png);
1226  if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
1227  png_set_expand_gray_1_2_4_to_8(png);
1228  if (color_type == PNG_COLOR_TYPE_GRAY
1229  || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1230  png_set_gray_to_rgb(png);
1231  if (png_get_valid(png, info, PNG_INFO_tRNS))
1232  png_set_tRNS_to_alpha(png);
1233 
1234  png_set_strip_16(png);
1235  png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
1236 
1237  png_set_interlace_handling(png);
1238  png_read_update_info(png, info);
1239 
1240  /* Allocate image memory and row pointers. */
1241  if (!(*image = (uint32_t *)malloc(sizeof(uint32_t)
1242  *((size_t)*width)*((size_t)*height)))
1243  || !(row_pointers = (png_bytep *)malloc(sizeof(png_bytep)
1244  *png_height)))
1245  goto fail;
1246 
1247  for (row = 0; row < png_height; ++row)
1248  row_pointers[row] = (png_bytep)(*image + png_width*row);
1249 
1250  /* Read the image data. */
1251  png_read_image(png, row_pointers);
1252  free(row_pointers);
1253  png_destroy_read_struct(&png, &info, (png_infopp)NULL);
1254  return 1;
1255 
1256 fail:
1257  if (*image)
1258  free(*image);
1259 
1260  *width = *height = 0;
1261  png_destroy_read_struct(&png, &info, (png_infopp)NULL);
1262  return 0;
1263 }
1264 
1265 
1286 static int write_png(const uint32_t *const image,
1287  int width, int height, FILE *file)
1288 {
1289  const uint32_t *image_ptr;
1290  uint32_t *palette = NULL;
1291  uint8_t *row_buffer;
1292  png_structp png;
1293  png_infop info;
1294  png_color png_palette[256];
1295  png_byte png_trans[256];
1296  uint32_t pixel;
1297  int png_color_type, num_colors, use_color, use_alpha;
1298  int x, y, i, success = 0;
1299 
1300 
1301  if (!image)
1302  return 0;
1303 
1304  if (!(row_buffer = (uint8_t *)malloc(4*width)))
1305  return 0;
1306 
1307  if (!(png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
1308  NULL, NULL, NULL))
1309  || !(info = png_create_info_struct(png)))
1310  {
1311  if (png)
1312  png_destroy_write_struct(&png, (png_infopp)NULL);
1313 
1314  free(row_buffer);
1315  return 0;
1316  }
1317 
1318  if (setjmp(png_jmpbuf(png)))
1319  { /* If this code is reached, libpng has signaled an error. */
1320  goto fail;
1321  }
1322 
1323  /* Configure PNG output */
1324  png_init_io(png, file);
1325  png_set_compression_level(png, 9);
1326 
1327  palette = get_image_palette(&num_colors, &use_color, &use_alpha,
1328  image, width, height);
1329 
1330  /* The image is written according to the analysis of get_image_palette. */
1331  if (palette && use_color)
1332  png_color_type = PNG_COLOR_TYPE_PALETTE;
1333  else if (use_alpha)
1334  png_color_type = PNG_COLOR_TYPE_RGB_ALPHA;
1335  else if (use_color)
1336  png_color_type = PNG_COLOR_TYPE_RGB;
1337  else
1338  png_color_type = PNG_COLOR_TYPE_GRAY;
1339 
1340  png_set_IHDR(png, info, width, height, 8, png_color_type,
1341  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
1342 
1343  if (png_color_type == PNG_COLOR_TYPE_PALETTE)
1344  {
1345  for (i = 0; i < num_colors; ++i)
1346  {
1347  pixel = palette[i];
1348  png_palette[i].red = ((uint8_t *)&pixel)[0];
1349  png_palette[i].green = ((uint8_t *)&pixel)[1];
1350  png_palette[i].blue = ((uint8_t *)&pixel)[2];
1351  png_trans[i] = ((uint8_t *)&pixel)[3];
1352  }
1353 
1354  png_set_PLTE(png, info, png_palette, num_colors);
1355 
1356  if (use_alpha)
1357  png_set_tRNS(png, info, png_trans, num_colors, NULL);
1358  }
1359 
1360  png_write_info(png, info);
1361 
1362  for (y = 0, image_ptr = image; y < height; ++y, image_ptr += width)
1363  {
1364  switch (png_color_type)
1365  {
1366  case PNG_COLOR_TYPE_RGB_ALPHA:
1367  png_write_row(png, (png_bytep)image_ptr);
1368  break;
1369  case PNG_COLOR_TYPE_RGB:
1370  for (x = 0; x < width; ++x)
1371  {
1372  pixel = image_ptr[x];
1373  row_buffer[3 * x + 0] = ((uint8_t *)&pixel)[0];
1374  row_buffer[3 * x + 1] = ((uint8_t *)&pixel)[1];
1375  row_buffer[3 * x + 2] = ((uint8_t *)&pixel)[2];
1376  }
1377 
1378  png_write_row(png, (png_bytep)row_buffer);
1379  break;
1380  case PNG_COLOR_TYPE_GRAY:
1381  for (x = 0; x < width; ++x)
1382  {
1383  pixel = image_ptr[x];
1384  row_buffer[x] = ((uint8_t *)&pixel)[0];
1385  }
1386 
1387  png_write_row(png, (png_bytep)row_buffer);
1388  break;
1389  case PNG_COLOR_TYPE_PALETTE:
1390  for (x = 0; x < width; ++x)
1391  {
1392  pixel = image_ptr[x];
1393 
1394  for (i = 0; i < num_colors; ++i)
1395  if (pixel == palette[i])
1396  break;
1397 
1398  row_buffer[x] = i;
1399  }
1400 
1401  png_write_row(png, (png_bytep)row_buffer);
1402  break;
1403  }
1404  }
1405 
1406  png_write_end(png, info);
1407  success = 1;
1408 fail:
1409  if (palette)
1410  free(palette);
1411  png_destroy_write_struct(&png, &info);
1412  free(row_buffer);
1413  return success;
1414 }
1415 #endif /* USE_LIBPNG */
1416 
1417 
1418 #ifdef USE_LIBTIFF
1419 
1432 static int read_tiff(uint32_t **image, int *width, int *height,
1433  const char *filename, unsigned directory)
1434 {
1435  TIFF *tiff;
1436  uint32 image_width, image_height;
1437 
1438  *image = NULL;
1439  *width = *height = 0;
1440 
1441  if (!(tiff = TIFFOpen(filename, "r")))
1442  {
1443  fprintf(stderr, "TIFFOpen failed to open file.\n");
1444  return 0;
1445  }
1446 
1447  TIFFSetDirectory(tiff, directory);
1448  TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &image_width);
1449  TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &image_height);
1450  *width = (int)image_width;
1451  *height = (int)image_height;
1452 
1453  if (*width > MAX_IMAGE_SIZE || *height > MAX_IMAGE_SIZE)
1454  {
1455  fprintf(stderr, "Image dimensions exceed MAX_IMAGE_SIZE.\n");
1456  goto fail;
1457  }
1458 
1459  if (!(*image = (uint32_t *)malloc(
1460  sizeof(uint32_t)*image_width*image_height)))
1461  goto fail;
1462 
1463  if (!TIFFReadRGBAImageOriented(tiff, image_width, image_height,
1464  (uint32 *)*image, ORIENTATION_TOPLEFT, 1))
1465  goto fail;
1466 
1467  TIFFClose(tiff);
1468  return 1;
1469 
1470 fail:
1471  if (*image)
1472  free(*image);
1473 
1474  *width = *height = 0;
1475  TIFFClose(tiff);
1476  return 0;
1477 }
1478 
1479 
1493 static int write_tiff(const uint32_t *image, int width, int height,
1494  const char *filename)
1495 {
1496  TIFF *tiff;
1497  uint16 alpha = EXTRASAMPLE_ASSOCALPHA;
1498 
1499  if (!image)
1500  return 0;
1501 
1502  if (!(tiff = TIFFOpen(filename, "w")))
1503  {
1504  fprintf(stderr, "TIFFOpen failed to open file.\n");
1505  return 0;
1506  }
1507 
1508  if (TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width) != 1
1509  || TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height) != 1
1510  || TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4) != 1
1511  || TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB) != 1
1512  || TIFFSetField(tiff, TIFFTAG_EXTRASAMPLES, 1, &alpha) != 1
1513  || TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8) != 1
1514  || TIFFSetField(tiff, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT) != 1
1515  || TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG) != 1
1516  /* compression can be COMPRESSION_NONE, COMPRESSION_DEFLATE,
1517  COMPRESSION_LZW, or COMPRESSION_JPEG */
1518  || TIFFSetField(tiff, TIFFTAG_COMPRESSION, COMPRESSION_LZW) != 1)
1519  {
1520  fprintf(stderr, "TIFFSetField failed.\n");
1521  TIFFClose(tiff);
1522  return 0;
1523  }
1524 
1525  if (TIFFWriteEncodedStrip(tiff, 0, (tdata_t)image,
1526  4 * ((size_t)width) * ((size_t)height)) < 0)
1527  {
1528  fprintf(stderr, "Error writing data to file.\n");
1529  TIFFClose(tiff);
1530  return 0;
1531  }
1532 
1533  TIFFClose(tiff);
1534  return 1;
1535 }
1536 #endif /* USE_LIBTIFF */
1537 
1538 
1540 static void *convert_to_format(uint32_t *src, int width, int height,
1541  unsigned format)
1542 {
1543  const int num_pixels = width * height;
1544  const int num_channels = (format & IMAGEIO_GRAYSCALE) ?
1545  1 : ((format & IMAGEIO_STRIP_ALPHA) ? 3 : 4);
1546  const int channel_stride = (format & IMAGEIO_PLANAR) ? num_pixels : 1;
1547  const int channel_stride2 = 2 * channel_stride;
1548  const int channel_stride3 = 3 * channel_stride;
1549  double *dest_f64;
1550  float *dest_f32;
1551  uint8_t *dest_u8;
1552  uint32_t pixel;
1553  int order[4] = {0, 1, 2, 3};
1554  int i, x, y, pixel_stride, row_stride;
1555 
1556 
1557  pixel_stride = (format & IMAGEIO_PLANAR) ? 1 : num_channels;
1558 
1559  if (format & IMAGEIO_COLUMNMAJOR)
1560  {
1561  row_stride = pixel_stride;
1562  pixel_stride *= height;
1563  }
1564  else
1565  row_stride = width * pixel_stride;
1566 
1567  if (format & IMAGEIO_BGRFLIP)
1568  {
1569  order[0] = 2;
1570  order[2] = 0;
1571  }
1572 
1573  if ((format & IMAGEIO_AFLIP) && !(format & IMAGEIO_STRIP_ALPHA))
1574  {
1575  order[3] = order[2];
1576  order[2] = order[1];
1577  order[1] = order[0];
1578  order[0] = 3;
1579  }
1580 
1581  switch (format & (IMAGEIO_U8 | IMAGEIO_SINGLE | IMAGEIO_DOUBLE))
1582  {
1583  case IMAGEIO_U8: /* Destination type is uint8_t. */
1584  if (!(dest_u8 = (uint8_t *)malloc(
1585  sizeof(uint8_t)*num_channels*num_pixels)))
1586  return NULL;
1587 
1588  switch (num_channels)
1589  {
1590  case 1: /* Convert RGBA U8 to grayscale U8. */
1591  for (y = 0; y < height; ++y, src += width)
1592  for (x = 0, i = row_stride * y;
1593  x < width;
1594  ++x, i += pixel_stride)
1595  {
1596  pixel = src[x];
1597  dest_u8[i] = (uint8_t)(0.299f * ((uint8_t *)&pixel)[0]
1598  + 0.587f * ((uint8_t *)&pixel)[1]
1599  + 0.114f * ((uint8_t *)&pixel)[2] + 0.5f);
1600  }
1601  break;
1602  case 3: /* Convert RGBA U8 to RGB (or BGR) U8. */
1603  for (y = 0; y < height; ++y, src += width)
1604  for (x = 0, i = row_stride * y;
1605  x < width;
1606  ++x, i += pixel_stride)
1607  {
1608  pixel = src[x];
1609  dest_u8[i] =
1610  ((uint8_t *)&pixel)[order[0]];
1611  dest_u8[i + channel_stride] =
1612  ((uint8_t *)&pixel)[order[1]];
1613  dest_u8[i + channel_stride2] =
1614  ((uint8_t *)&pixel)[order[2]];
1615  }
1616  break;
1617  case 4: /* Convert RGBA U8 to RGBA (or BGRA, ARGB, or ABGR) U8. */
1618  for (y = 0; y < height; ++y, src += width)
1619  for (x = 0, i = row_stride * y;
1620  x < width;
1621  ++x, i += pixel_stride)
1622  {
1623  pixel = src[x];
1624  dest_u8[i] =
1625  ((uint8_t *)&pixel)[order[0]];
1626  dest_u8[i + channel_stride] =
1627  ((uint8_t *)&pixel)[order[1]];
1628  dest_u8[i + channel_stride2] =
1629  ((uint8_t *)&pixel)[order[2]];
1630  dest_u8[i + channel_stride3] =
1631  ((uint8_t *)&pixel)[order[3]];
1632  }
1633  break;
1634  }
1635  return dest_u8;
1636  case IMAGEIO_SINGLE: /* Destination type is float. */
1637  if (!(dest_f32 = (float *)malloc(
1638  sizeof(float) * num_channels*num_pixels)))
1639  return NULL;
1640 
1641  switch (num_channels)
1642  {
1643  case 1: /* Convert RGBA U8 to grayscale float. */
1644  for (y = 0; y < height; ++y, src += width)
1645  for (x = 0, i = row_stride * y;
1646  x < width; ++x,
1647  i += pixel_stride)
1648  {
1649  pixel = src[x];
1650  dest_f32[i] = 1.172549019607843070675535e-3f
1651  * ((uint8_t *)&pixel)[0]
1652  + 2.301960784313725357840079e-3f
1653  * ((uint8_t *)&pixel)[1]
1654  + 4.470588235294117808150007e-4f
1655  * ((uint8_t *)&pixel)[2];
1656  }
1657  break;
1658  case 3: /* Convert RGBA U8 to RGB (or BGR) float. */
1659  for (y = 0; y < height; ++y, src += width)
1660  for (x = 0, i = row_stride * y;
1661  x < width;
1662  ++x, i += pixel_stride)
1663  {
1664  pixel = src[x];
1665  dest_f32[i] =
1666  ((uint8_t *)&pixel)[order[0]] / 255.0f;
1667  dest_f32[i + channel_stride] =
1668  ((uint8_t *)&pixel)[order[1]] / 255.0f;
1669  dest_f32[i + channel_stride2] =
1670  ((uint8_t *)&pixel)[order[2]] / 255.0f;
1671  }
1672  break;
1673  case 4: /* Convert RGBA U8 to RGBA (or BGRA, ARGB, or ABGR) float. */
1674  for (y = 0; y < height; ++y, src += width)
1675  for (x = 0, i = row_stride * y;
1676  x < width;
1677  ++x, i += pixel_stride)
1678  {
1679  pixel = src[x];
1680  dest_f32[i] =
1681  ((uint8_t *)&pixel)[order[0]] / 255.0f;
1682  dest_f32[i + channel_stride] =
1683  ((uint8_t *)&pixel)[order[1]] / 255.0f;
1684  dest_f32[i + channel_stride2] =
1685  ((uint8_t *)&pixel)[order[2]] / 255.0f;
1686  dest_f32[i + channel_stride3] =
1687  ((uint8_t *)&pixel)[order[3]] / 255.0f;
1688  }
1689  break;
1690  }
1691  return dest_f32;
1692  case IMAGEIO_DOUBLE: /* Destination type is double. */
1693  if (!(dest_f64 = (double *)
1694  malloc(sizeof(double)*num_channels*num_pixels)))
1695  return NULL;
1696 
1697  switch (num_channels)
1698  {
1699  case 1: /* Convert RGBA U8 to grayscale double. */
1700  for (y = 0; y < height; ++y, src += width)
1701  for (x = 0, i = row_stride * y;
1702  x < width;
1703  ++x, i += pixel_stride)
1704  {
1705  pixel = src[x];
1706  dest_f64[i] = 1.172549019607843070675535e-3
1707  * ((uint8_t *)&pixel)[0]
1708  + 2.301960784313725357840079e-3
1709  * ((uint8_t *)&pixel)[1]
1710  + 4.470588235294117808150007e-4
1711  * ((uint8_t *)&pixel)[2];
1712  }
1713  break;
1714  case 3: /* Convert RGBA U8 to RGB (or BGR) double. */
1715  for (y = 0; y < height; ++y, src += width)
1716  for (x = 0, i = row_stride * y;
1717  x < width;
1718  ++x, i += pixel_stride)
1719  {
1720  pixel = src[x];
1721  dest_f64[i] =
1722  ((uint8_t *)&pixel)[order[0]] / 255.0;
1723  dest_f64[i + channel_stride] =
1724  ((uint8_t *)&pixel)[order[1]] / 255.0;
1725  dest_f64[i + channel_stride2] =
1726  ((uint8_t *)&pixel)[order[2]] / 255.0;
1727  }
1728  break;
1729  case 4: /* Convert RGBA U8 to RGBA (or BGRA, ARGB, or ABGR) double. */
1730  for (y = 0; y < height; ++y, src += width)
1731  for (x = 0, i = row_stride * y;
1732  x < width;
1733  ++x, i += pixel_stride)
1734  {
1735  pixel = src[x];
1736  dest_f64[i] =
1737  ((uint8_t *)&pixel)[order[0]] / 255.0;
1738  dest_f64[i + channel_stride] =
1739  ((uint8_t *)&pixel)[order[1]] / 255.0;
1740  dest_f64[i + channel_stride2] =
1741  ((uint8_t *)&pixel)[order[2]] / 255.0;
1742  dest_f64[i + channel_stride3] =
1743  ((uint8_t *)&pixel)[order[3]] / 255.0;
1744  }
1745  break;
1746  }
1747  return dest_f64;
1748  default:
1749  return NULL;
1750  }
1751 }
1752 
1753 
1755 static uint32_t *convert_from_format(void *src, int width, int height,
1756  unsigned format)
1757 {
1758  const int num_pixels = width * height;
1759  const int num_channels = (format & IMAGEIO_GRAYSCALE) ?
1760  1 : ((format & IMAGEIO_STRIP_ALPHA) ? 3 : 4);
1761  const int channel_stride = (format & IMAGEIO_PLANAR) ? num_pixels : 1;
1762  const int channel_stride2 = 2 * channel_stride;
1763  const int channel_stride3 = 3 * channel_stride;
1764  double *src_f64 = (double *)src;
1765  float *src_f32 = (float *)src;
1766  uint8_t *src_u8 = (uint8_t *)src;
1767  uint8_t *dest, *dest_ptr;
1768  int order[4] = {0, 1, 2, 3};
1769  int i, x, y, pixel_stride, row_stride;
1770 
1771  if (!(dest = (uint8_t *)malloc(sizeof(uint32_t)*num_pixels)))
1772  return NULL;
1773 
1774  dest_ptr = dest;
1775  pixel_stride = (format & IMAGEIO_PLANAR) ? 1 : num_channels;
1776 
1777  if (format & IMAGEIO_COLUMNMAJOR)
1778  {
1779  row_stride = pixel_stride;
1780  pixel_stride *= height;
1781  }
1782  else
1783  row_stride = width*pixel_stride;
1784 
1785  if (format & IMAGEIO_BGRFLIP)
1786  {
1787  order[0] = 2;
1788  order[2] = 0;
1789  }
1790 
1791  if ((format & IMAGEIO_AFLIP) && !(format & IMAGEIO_STRIP_ALPHA))
1792  {
1793  order[3] = order[2];
1794  order[2] = order[1];
1795  order[1] = order[0];
1796  order[0] = 3;
1797  }
1798 
1799  switch (format & (IMAGEIO_U8 | IMAGEIO_SINGLE | IMAGEIO_DOUBLE))
1800  {
1801  case IMAGEIO_U8: /* Source type is uint8_t. */
1802  switch (num_channels)
1803  {
1804  case 1: /* Convert grayscale U8 to RGBA U8. */
1805  for (y = 0; y < height; ++y, dest_ptr += 4 * width)
1806  for (x = 0, i = row_stride * y;
1807  x < width;
1808  ++x, i += pixel_stride)
1809  {
1810  dest_ptr[4 * x] =
1811  dest_ptr[4 * x + 1] =
1812  dest_ptr[4 * x + 2] = src_u8[i];
1813  dest_ptr[4 * x + 3] = 255;
1814  }
1815  break;
1816  case 3: /* Convert RGB (or BGR) U8 to RGBA U8. */
1817  for (y = 0; y < height; ++y, dest_ptr += 4 * width)
1818  for (x = 0, i = row_stride * y;
1819  x < width;
1820  ++x, i += pixel_stride)
1821  {
1822  dest_ptr[4 * x + order[0]] = src_u8[i];
1823  dest_ptr[4 * x + order[1]] = src_u8[i + channel_stride];
1824  dest_ptr[4 * x + order[2]] = src_u8[i + channel_stride2];
1825  dest_ptr[4 * x + 3] = 255;
1826  }
1827  break;
1828  case 4: /* Convert RGBA U8 to RGBA (or BGRA, ARGB, or ABGR) U8. */
1829  for (y = 0; y < height; ++y, dest_ptr += 4 * width)
1830  for (x = 0, i = row_stride * y;
1831  x < width;
1832  ++x, i += pixel_stride)
1833  {
1834  dest_ptr[4 * x + order[0]] = src_u8[i];
1835  dest_ptr[4 * x + order[1]] = src_u8[i + channel_stride];
1836  dest_ptr[4 * x + order[2]] = src_u8[i + channel_stride2];
1837  dest_ptr[4 * x + order[3]] = src_u8[i + channel_stride3];
1838  }
1839  break;
1840  }
1841  break;
1842  case IMAGEIO_SINGLE: /* Source type is float. */
1843  switch (num_channels)
1844  {
1845  case 1: /* Convert grayscale float to RGBA U8. */
1846  for (y = 0; y < height; ++y, dest_ptr += 4 * width)
1847  for (x = 0, i = row_stride * y;
1848  x < width;
1849  ++x, i += pixel_stride)
1850  {
1851  dest_ptr[4 * x] =
1852  dest_ptr[4 * x + 1] =
1853  dest_ptr[4 * x + 2] = ROUNDCLAMPF(src_f32[i]);
1854  dest_ptr[4 * x + 3] = 255;
1855  }
1856  break;
1857  case 3: /* Convert RGBA U8 to RGB (or BGR) float. */
1858  for (y = 0; y < height; ++y, dest_ptr += 4 * width)
1859  for (x = 0, i = row_stride * y;
1860  x < width;
1861  ++x, i += pixel_stride)
1862  {
1863  dest_ptr[4 * x + order[0]] =
1864  ROUNDCLAMPF(src_f32[i]);
1865  dest_ptr[4 * x + order[1]] =
1866  ROUNDCLAMPF(src_f32[i + channel_stride]);
1867  dest_ptr[4 * x + order[2]] =
1868  ROUNDCLAMPF(src_f32[i + channel_stride2]);
1869  dest_ptr[4 * x + 3] = 255;
1870  }
1871  break;
1872  case 4: /* Convert RGBA U8 to RGBA (or BGRA, ARGB, or ABGR) float. */
1873  for (y = 0; y < height; ++y, dest_ptr += 4 * width)
1874  for (x = 0, i = row_stride * y;
1875  x < width;
1876  ++x, i += pixel_stride)
1877  {
1878  dest_ptr[4 * x + order[0]] =
1879  ROUNDCLAMPF(src_f32[i]);
1880  dest_ptr[4 * x + order[1]] =
1881  ROUNDCLAMPF(src_f32[i + channel_stride]);
1882  dest_ptr[4 * x + order[2]] =
1883  ROUNDCLAMPF(src_f32[i + channel_stride2]);
1884  dest_ptr[4 * x + order[3]] =
1885  ROUNDCLAMPF(src_f32[i + channel_stride3]);
1886  }
1887  break;
1888  }
1889  break;
1890  case IMAGEIO_DOUBLE: /* Source type is double. */
1891  switch (num_channels)
1892  {
1893  case 1: /* Convert grayscale double to RGBA U8. */
1894  for (y = 0; y < height; ++y, dest_ptr += 4 * width)
1895  for (x = 0, i = row_stride * y;
1896  x < width;
1897  ++x, i += pixel_stride)
1898  {
1899  dest_ptr[4 * x] =
1900  dest_ptr[4 * x + 1] =
1901  dest_ptr[4 * x + 2] = ROUNDCLAMP(src_f64[i]);
1902  dest_ptr[4 * x + 3] = 255;
1903  }
1904  break;
1905  case 3: /* Convert RGB (or BGR) double to RGBA U8. */
1906  for (y = 0; y < height; ++y, dest_ptr += 4 * width)
1907  for (x = 0, i = row_stride * y;
1908  x < width;
1909  ++x, i += pixel_stride)
1910  {
1911  dest_ptr[4 * x + order[0]] =
1912  ROUNDCLAMP(src_f64[i]);
1913  dest_ptr[4 * x + order[1]] =
1914  ROUNDCLAMP(src_f64[i + channel_stride]);
1915  dest_ptr[4 * x + order[2]] =
1916  ROUNDCLAMP(src_f64[i + channel_stride2]);
1917  dest_ptr[4 * x + 3] = 255;;
1918  }
1919  break;
1920  case 4: /* Convert RGBA (or BGRA, ARGB, or ABGR) double to RGBA U8. */
1921  for (y = 0; y < height; ++y, dest_ptr += 4 * width)
1922  for (x = 0, i = row_stride * y;
1923  x < width;
1924  ++x, i += pixel_stride)
1925  {
1926  dest_ptr[4 * x + order[0]] =
1927  ROUNDCLAMP(src_f64[i]);
1928  dest_ptr[4 * x + order[1]] =
1929  ROUNDCLAMP(src_f64[i + channel_stride]);
1930  dest_ptr[4 * x + order[2]] =
1931  ROUNDCLAMP(src_f64[i + channel_stride2]);
1932  dest_ptr[4 * x + order[3]] =
1933  ROUNDCLAMP(src_f64[i + channel_stride3]);
1934  }
1935  break;
1936  }
1937  break;
1938  default:
1939  return NULL;
1940  }
1941 
1942  return (uint32_t *)dest;
1943 }
1944 
1945 
1955 int identify_image_type(char *type, const char *filename)
1956 {
1957  FILE *file;
1958  uint32_t magic;
1959 
1960  type[0] = '\0';
1961 
1962  if (!(file = fopen(filename, "rb")))
1963  return 0;
1964 
1965  /* Determine the file format by reading the first 4 bytes */
1966  magic = ((uint32_t)getc(file));
1967  magic |= ((uint32_t)getc(file)) << 8;
1968  magic |= ((uint32_t)getc(file)) << 16;
1969  magic |= ((uint32_t)getc(file)) << 24;
1970 
1971  /* Test for errors */
1972  if (ferror(file))
1973  {
1974  fclose(file);
1975  return 0;
1976  }
1977 
1978  fclose(file);
1979 
1980  if ((magic & 0x0000FFFFL) == 0x00004D42L) /* BMP */
1981  strcpy(type, "BMP");
1982  else if ((magic & 0x00FFFFFFL) == 0x00FFD8FFL) /* JPEG/JFIF */
1983  strcpy(type, "JPEG");
1984  else if (magic == 0x474E5089L) /* PNG */
1985  strcpy(type, "PNG");
1986  else if (magic == 0x002A4949L || magic == 0x2A004D4DL) /* TIFF */
1987  strcpy(type, "TIFF");
1988  else if (magic == 0x38464947L) /* GIF */
1989  strcpy(type, "GIF");
1990  else if (magic == 0x474E4D8AL) /* MNG */
1991  strcpy(type, "MNG");
1992  else if ((magic & 0xF0FF00FFL) == 0x0001000AL /* PCX */
1993  && ((magic >> 8) & 0xFF) < 6)
1994  strcpy(type, "PCX");
1995  else
1996  return 0;
1997 
1998  return 1;
1999 }
2000 
2001 
2083 void *read_image(int *width, int *height,
2084  const char *filename, unsigned format)
2085 {
2086  void *image = NULL;
2087  uint32_t *image_u8 = NULL;
2088  FILE *file;
2089  char type[8];
2090 
2091 
2092  identify_image_type(type, filename);
2093 
2094  if (!(file = fopen(filename, "rb")))
2095  {
2096  fprintf(stderr, "Unable to open file \"%s\".\n", filename);
2097  return 0;
2098  }
2099 
2100  if (!strcmp(type, "BMP"))
2101  {
2102  if (!read_bmp(&image_u8, width, height, file))
2103  fprintf(stderr, "Failed to read \"%s\".\n", filename);
2104  }
2105  else if (!strcmp(type, "JPEG"))
2106  {
2107 #ifdef USE_LIBJPEG
2108  if (!(read_jpeg(&image_u8, width, height, file)))
2109  fprintf(stderr, "Failed to read \"%s\".\n", filename);
2110 #else
2111  fprintf(stderr, "file \"%s\" is a JPEG image.\n"
2112  "Compile with USE_LIBJPEG to enable JPEG reading.\n",
2113  filename);
2114 #endif
2115  }
2116  else if (!strcmp(type, "PNG"))
2117  {
2118 #ifdef USE_LIBPNG
2119  if (!(read_png(&image_u8, width, height, file)))
2120  fprintf(stderr, "Failed to read \"%s\".\n", filename);
2121 #else
2122  fprintf(stderr, "file \"%s\" is a PNG image.\n"
2123  "Compile with USE_LIBPNG to enable PNG reading.\n",
2124  filename);
2125 #endif
2126  }
2127  else if (!strcmp(type, "TIFF"))
2128  {
2129 #ifdef USE_LIBTIFF
2130  fclose(file);
2131 
2132  if (!(read_tiff(&image_u8, width, height, filename, 0)))
2133  fprintf(stderr, "Failed to read \"%s\".\n", filename);
2134 
2135  file = NULL;
2136 #else
2137  fprintf(stderr, "file \"%s\" is a TIFF image.\n"
2138  "Compile with USE_LIBTIFF to enable TIFF reading.\n",
2139  filename);
2140 #endif
2141  }
2142  else
2143  {
2144  /* File format is unsupported. */
2145  if (type[0])
2146  fprintf(stderr, "file \"%s\" is a %s image.", filename, type);
2147  else
2148  fprintf(stderr,
2149  "file \"%s\" is an unrecognized format.", filename);
2150  fprintf(stderr, "\nSorry, only "
2151  READIMAGE_FORMATS_SUPPORTED " reading is supported.\n");
2152  }
2153 
2154  if (file)
2155  fclose(file);
2156 
2157  if (image_u8 && format)
2158  {
2159  image = convert_to_format(image_u8, *width, *height, format);
2160  free(image_u8);
2161  }
2162  else
2163  image = image_u8;
2164 
2165  return image;
2166 }
2167 
2168 
2188 int write_image(void *image, int width, int height,
2189  const char *filename, unsigned format, int quality)
2190 {
2191  FILE *file;
2192  uint32_t *image_u8;
2193  enum {BMP_FORMAT, JPEG_FORMAT, PNG_FORMAT, TIFF_FORMAT} fileformat;
2194  int success = 0;
2195 
2196  if (!image || width <= 0 || height <= 0)
2197  {
2198  fprintf(stderr, "Null image.\n");
2199  fprintf(stderr, "Failed to write \"%s\".\n", filename);
2200  return 0;
2201  }
2202 
2203  if (string_ends_with(filename, ".bmp"))
2204  fileformat = BMP_FORMAT;
2205  else if (string_ends_with(filename, ".jpg")
2206  || string_ends_with(filename, ".jpeg"))
2207  {
2208  fileformat = JPEG_FORMAT;
2209 #ifndef USE_LIBJPEG
2210  fprintf(stderr, "Failed to write \"%s\".\n", filename);
2211  fprintf(stderr, "Compile with USE_LIBJPEG to enable JPEG writing.\n");
2212  return 0;
2213 #endif
2214  }
2215  else if (string_ends_with(filename, ".png"))
2216  {
2217  fileformat = PNG_FORMAT;
2218 #ifndef USE_LIBPNG
2219  fprintf(stderr, "Failed to write \"%s\".\n", filename);
2220  fprintf(stderr, "Compile with USE_LIBPNG to enable PNG writing.\n");
2221  return 0;
2222 #endif
2223  }
2224  else if (string_ends_with(filename, ".tif")
2225  || string_ends_with(filename, ".tiff"))
2226  {
2227  fileformat = TIFF_FORMAT;
2228 #ifndef USE_LIBTIFF
2229  fprintf(stderr, "Failed to write \"%s\".\n", filename);
2230  fprintf(stderr, "Compile with USE_LIBTIFF to enable TIFF writing.\n");
2231  return 0;
2232 #endif
2233  }
2234  else
2235  {
2236  fprintf(stderr, "Failed to write \"%s\".\n", filename);
2237 
2238  if (string_ends_with(filename, ".gif"))
2239  fprintf(stderr, "GIF is not supported. ");
2240  else if (string_ends_with(filename, ".mng"))
2241  fprintf(stderr, "MNG is not supported. ");
2242  else if (string_ends_with(filename, ".pcx"))
2243  fprintf(stderr, "PCX is not supported. ");
2244  else
2245  fprintf(stderr, "Unable to determine format from extension.\n");
2246 
2247  fprintf(stderr, "Sorry, only "
2248  WRITEIMAGE_FORMATS_SUPPORTED " writing is supported.\n");
2249  return 0;
2250  }
2251 
2252  if (!(file = fopen(filename, "wb")))
2253  {
2254  fprintf(stderr, "Unable to write to file \"%s\".\n", filename);
2255  return 0;
2256  }
2257 
2258  if (!(image_u8 = convert_from_format(image, width, height, format)))
2259  return 0;
2260 
2261  switch (fileformat)
2262  {
2263  case BMP_FORMAT:
2264  success = write_bmp(image_u8, width, height, file);
2265  break;
2266  case JPEG_FORMAT:
2267 #ifdef USE_LIBJPEG
2268  success = write_jpeg(image_u8, width, height, file, quality);
2269 #else
2270  /* Dummy operation to avoid unused variable warning if compiled
2271  without libjpeg. Note that execution returns above if
2272  format == JPEG_FORMAT and USE_LIBJPEG is undefined. */
2273  success = quality;
2274 #endif
2275  break;
2276  case PNG_FORMAT:
2277 #ifdef USE_LIBPNG
2278  success = write_png(image_u8, width, height, file);
2279 #endif
2280  break;
2281  case TIFF_FORMAT:
2282 #ifdef USE_LIBTIFF
2283  fclose(file);
2284  success = write_tiff(image_u8, width, height, filename);
2285  file = NULL;
2286 #endif
2287  break;
2288  }
2289 
2290  if (!success)
2291  fprintf(stderr, "Failed to write \"%s\".\n", filename);
2292 
2293  free(image_u8);
2294 
2295  if (file)
2296  fclose(file);
2297 
2298  return success;
2299 }