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