44 #if PNG_LIBPNG_VER < 10400 
   46 #define png_set_expand_gray_1_2_4_to_8  png_set_gray_1_2_4_to_8 
   58 #define FILE_BUFFER_CAPACITY    (1024*4) 
   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))) 
   69     unsigned i, StringLength = strlen(String), SuffixLength = strlen(Suffix);
 
   71     if(StringLength < SuffixLength)
 
   74     String += StringLength - SuffixLength;
 
   76     for(i = 0; i < SuffixLength; i++)
 
   77         if(tolower(String[i]) != tolower(Suffix[i]))
 
   85 static void FillImage(uint32_t *Image, 
int Width, 
int Height, uint32_t Color)
 
   90         for(y = 0; y < Height; y++, Image += Width)
 
   91             for(x = 0; x < Width; x++)
 
  111     const uint32_t *Image, 
int Width, 
int Height)
 
  113     const int MaxColors = 256;
 
  114     uint32_t *Palette = NULL;
 
  116     int x, y, i, Red, Green, Blue, Alpha;
 
  119     if(!UseColor || !NumColors || !UseAlpha)
 
  122         || !(Palette = (uint32_t *)
Malloc(
sizeof(uint32_t)*MaxColors)))
 
  125         *UseColor = *UseAlpha = 1;
 
  129     *NumColors = *UseColor = *UseAlpha = 0;
 
  131     for(y = 0; y < Height; y++)
 
  133         for(x = 0; x < Width; x++)
 
  136             Red = ((uint8_t *)&Pixel)[0];
 
  137             Green = ((uint8_t *)&Pixel)[1];
 
  138             Blue = ((uint8_t *)&Pixel)[2];
 
  139             Alpha = ((uint8_t *)&Pixel)[3];
 
  141             if(Red != Green || Red != Blue)     
 
  148             for(i = 0; i < *NumColors; i++)
 
  149                 if(Pixel == Palette[i])
 
  177     w = (uint16_t) getc(File);
 
  178     w |= ((uint16_t) getc(File) << 8);
 
  187     dw = (uint32_t) getc(File);
 
  188     dw |= ((uint32_t) getc(File) << 8);
 
  189     dw |= ((uint32_t) getc(File) << 16);
 
  190     dw |= ((uint32_t) getc(File) << 24);
 
  198     putc(w & 0xFF, File);
 
  199     putc((w & 0xFF00) >> 8, File);
 
  206     putc(dw & 0xFF, File);
 
  207     putc((dw & 0xFF00) >> 8, File);
 
  208     putc((dw & 0xFF0000) >> 16, File);
 
  209     putc((dw & 0xFF000000) >> 24, File);
 
  214 static int ReadBmp1Bit(uint32_t *Image, 
int Width, 
int Height, FILE *File, 
const uint32_t *Palette)
 
  216     int RowPadding = (-(Width+7)/8)&3;
 
  220     Image += ((
long int)Width)*((
long int)Height - 1);
 
  222     for(y = Height; y; y--, Image -= Width)
 
  227         for(x = 0; x < Width;)
 
  231             for(Bit = 7; Bit >= 0 && x < Width; Bit--, Code <<= 1)
 
  232                 Image[x++] = Palette[(Code & 0x80) ? 1:0];
 
  235         for(x = RowPadding; x; x--)
 
  244 static int ReadBmp4Bit(uint32_t *Image, 
int Width, 
int Height, FILE *File, 
const uint32_t *Palette)
 
  246     int RowPadding = (-(Width+1)/2)&3;
 
  250     Image += ((
long int)Width)*((
long int)Height - 1);
 
  252     for(y = Height; y; y--, Image -= Width)
 
  257         for(x = 0; x < Width;)
 
  260             Image[x++] = Palette[(Code & 0xF0) >> 4];
 
  263                 Image[x++] = Palette[Code & 0x0F];
 
  266         for(x = RowPadding; x; x--)
 
  275 static int ReadBmp4BitRle(uint32_t *Image, 
int Width, 
int Height, FILE *File, 
const uint32_t *Palette)
 
  278     unsigned Count, Value;
 
  279     uint32_t ColorH, ColorL;
 
  281     FillImage(Image, Width, Height, Palette[0]);
 
  282     Image += ((
long int)Width)*((
long int)Height - 1);
 
  284     for(x = 0, y = Height; y;)
 
  309                 if(x >= Width || y < 0)
 
  321                     Image[x++] = Palette[(Value & 0xF0) >> 4];
 
  328                         Image[x++] = Palette[Value & 0x0F];
 
  336                 if(((Count + 1)/2) & 1)
 
  342             ColorH = Palette[(Value & 0xF0) >> 4];
 
  343             ColorL = Palette[Value & 0xF];
 
  373 static int ReadBmp8Bit(uint32_t *Image, 
int Width, 
int Height, FILE *File, 
const uint32_t *Palette)
 
  375     int RowPadding = (-Width)&3;
 
  378     Image += ((
long int)Width)*((
long int)Height - 1);
 
  380     for(y = Height; y; y--, Image -= Width)
 
  385         for(x = 0; x < Width; x++)
 
  386             Image[x] = Palette[getc(File) & 0xFF];
 
  388         for(x = RowPadding; x; x--)
 
  397 static int ReadBmp8BitRle(uint32_t *Image, 
int Width, 
int Height, FILE *File, 
const uint32_t *Palette)
 
  400     unsigned Count, Value;
 
  403     FillImage(Image, Width, Height, Palette[0]);
 
  404     Image += ((
long int)Width)*((
long int)Height - 1);
 
  406     for(x = 0, y = Height; y;)
 
  431                 if(x >= Width || y < 0)
 
  442                     Image[x++] = Palette[getc(File) & 0xFF];
 
  451             Color = Palette[Value & 0xFF];
 
  468 static int ReadBmp24Bit(uint32_t *Image, 
int Width, 
int Height, FILE *File)
 
  470     uint8_t *ImagePtr = (uint8_t *)Image;
 
  471     int RowPadding = (-3*Width)&3;
 
  476     ImagePtr += ((
long int)Width)*((
long int)Height - 1);
 
  478     for(y = Height; y; y--, ImagePtr -= Width)
 
  483         for(x = 0; x < Width; x += 4)
 
  486             ImagePtr[x+2] = getc(File); 
 
  487             ImagePtr[x+1] = getc(File); 
 
  488             ImagePtr[x+0] = getc(File); 
 
  491         for(x = RowPadding; x; x--)
 
  501     int Shift = 0, BitCount = 0;
 
  524     Shift += BitCount - 8;
 
  539 static int ReadBmp16Bit(uint32_t *Image, 
int Width, 
int Height, FILE *File,
 
  540     uint32_t RedMask, uint32_t GreenMask, uint32_t BlueMask, uint32_t AlphaMask)
 
  542     uint8_t *ImagePtr = (uint8_t *)Image;
 
  544     int RowPadding = (-2*Width)&3;
 
  545     int RedLeftShift, GreenLeftShift, BlueLeftShift, AlphaLeftShift;
 
  546     int RedRightShift, GreenRightShift, BlueRightShift, AlphaRightShift;
 
  554     ImagePtr += ((
long int)Width)*((
long int)Height - 1);
 
  556     for(y = Height; y; y--, ImagePtr -= Width)
 
  561         for(x = 0; x < Width; x += 4)
 
  567             ImagePtr[x+3] = ((Code & AlphaMask) >> AlphaRightShift) << AlphaLeftShift;
 
  568             ImagePtr[x+2] = ((Code & BlueMask ) >> BlueRightShift ) << BlueLeftShift;
 
  569             ImagePtr[x+1] = ((Code & GreenMask) >> GreenRightShift) << GreenLeftShift;
 
  570             ImagePtr[x+0] = ((Code & RedMask  ) >> RedRightShift  ) << RedLeftShift;
 
  573         for(x = RowPadding; x; x--)
 
  582 static int ReadBmp32Bit(uint32_t *Image, 
int Width, 
int Height, FILE *File,
 
  583     uint32_t RedMask, uint32_t GreenMask, uint32_t BlueMask, uint32_t AlphaMask)
 
  587     int RedLeftShift, GreenLeftShift, BlueLeftShift, AlphaLeftShift;
 
  588     int RedRightShift, GreenRightShift, BlueRightShift, AlphaRightShift;
 
  596     ImagePtr = (uint8_t *)Image + ((
long int)Width)*((
long int)Height - 1);
 
  598     for(y = Height; y; y--, ImagePtr -= Width)
 
  603         for(x = 0; x < Width; x += 4)
 
  609             ImagePtr[x+3] = ((Code & AlphaMask) >> AlphaRightShift) << AlphaLeftShift;
 
  610             ImagePtr[x+2] = ((Code & BlueMask ) >> BlueRightShift ) << BlueLeftShift;
 
  611             ImagePtr[x+1] = ((Code & GreenMask) >> GreenRightShift) << GreenLeftShift;
 
  612             ImagePtr[x+0] = ((Code & RedMask  ) >> RedRightShift  ) << RedLeftShift;
 
  632 static int ReadBmp(uint32_t **Image, 
int *Width, 
int *Height, FILE *File)
 
  634     uint32_t *Palette = NULL;
 
  636     long int ImageDataOffset, InfoSize;
 
  637     unsigned i, NumPlanes, BitsPerPixel, Compression, NumColors;
 
  638     uint32_t RedMask, GreenMask, BlueMask, AlphaMask;
 
  639     int Success = 0, Os2Bmp;
 
  643     *Width = *Height = 0;
 
  644     fseek(File, 0, SEEK_SET);
 
  646     Magic[0] = getc(File);
 
  647     Magic[1] = getc(File);
 
  649     if(!(Magic[0] == 0x42 && Magic[1] == 0x4D) 
 
  650         || fseek(File, 8, SEEK_CUR))         
 
  666     if((Os2Bmp = (InfoSize == 12)))  
 
  674         RedMask = 0x00FF0000;
 
  675         GreenMask = 0x0000FF00;
 
  676         BlueMask = 0x000000FF;
 
  677         AlphaMask = 0xFF000000;
 
  686         fseek(File, 12, SEEK_CUR);
 
  688         fseek(File, 4, SEEK_CUR);
 
  698         ErrorMessage(
"Image dimensions exceed MAX_IMAGE_SIZE.\n");
 
  702     if(feof(File) || NumPlanes != 1 || Compression > 3)
 
  706     if(!(*Image = (uint32_t *)
Malloc(
sizeof(uint32_t)*((
long int)*Width)*((
long int)*Height))))
 
  710     if(BitsPerPixel <= 8)
 
  712         fseek(File, 14 + InfoSize, SEEK_SET);
 
  715             NumColors = 1 << BitsPerPixel;
 
  717         if(!(Palette = (uint32_t *)
Malloc(
sizeof(uint32_t)*256)))
 
  720         for(i = 0, PalettePtr = (uint8_t *)Palette; i < NumColors; i++)
 
  723             PalettePtr[2] = getc(File);   
 
  724             PalettePtr[1] = getc(File);   
 
  725             PalettePtr[0] = getc(File);   
 
  733             Palette[i] = Palette[0];
 
  736     if(fseek(File, ImageDataOffset, SEEK_SET) || feof(File))
 
  749                 Success = 
ReadBmp1Bit(*Image, *Width, *Height, File, Palette);
 
  752                 Success = 
ReadBmp4Bit(*Image, *Width, *Height, File, Palette);
 
  755                 Success = 
ReadBmp8Bit(*Image, *Width, *Height, File, Palette);
 
  762                     0x001F << 10, 0x001F << 5, 0x0001F, 0);
 
  766                     0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000);
 
  771             if(BitsPerPixel == 8)
 
  775             if(BitsPerPixel == 4)
 
  783                     RedMask, GreenMask, BlueMask, AlphaMask);
 
  787                     RedMask, GreenMask, BlueMask, AlphaMask);
 
  800     if(!Success && *Image)
 
  828 static int WriteBmp(
const uint32_t *Image, 
int Width, 
int Height, FILE *File)
 
  830     const uint8_t *ImagePtr = (uint8_t *)Image;
 
  831     uint32_t *Palette = NULL;
 
  834     int UsePalette, NumColors, UseColor, UseAlpha;
 
  835     int x, y, i, RowPadding, Success = 0;
 
  842         Image, Width, Height);
 
  845     if(Palette && 2*NumColors < Width*Height)
 
  848         UsePalette = NumColors = 0;
 
  855         RowPadding = (-Width)&3;
 
  856         ImageSize = (Width + RowPadding)*((
long int)Height);
 
  860         RowPadding = (-3*Width)&3;
 
  861         ImageSize = (3*Width + RowPadding)*((
long int)Height);
 
  888     WriteDWordLE((!UsePalette || NumColors == 256) ? 0:NumColors, File);
 
  900         for(i = 0; i < NumColors; i++)
 
  903             putc(((uint8_t *)&Pixel)[2], File);     
 
  904             putc(((uint8_t *)&Pixel)[1], File);     
 
  905             putc(((uint8_t *)&Pixel)[0], File);     
 
  912     ImagePtr += ((
long int)Width)*((
long int)Height - 1);
 
  914     for(y = Height; y; y--, ImagePtr -= Width)
 
  918             for(x = 0; x < Width; x += 4)
 
  920                 Pixel = *((uint32_t *)(ImagePtr + x));
 
  922                 for(i = 0; i < NumColors; i++)
 
  923                     if(Pixel == Palette[i])
 
  931             for(x = 0; x < Width; x += 4)
 
  933                 putc(ImagePtr[x+2], File);  
 
  934                 putc(ImagePtr[x+1], File);  
 
  935                 putc(ImagePtr[x+0], File);  
 
  939         for(x = RowPadding; x; x--)         
 
  965     struct jpeg_error_mgr pub;
 
  971 METHODDEF(
void) JerrExit(j_common_ptr cinfo)
 
  973     hooked_jerr *Jerr = (hooked_jerr *) cinfo->err;
 
  974     (*cinfo->err->output_message)(cinfo);
 
  975     longjmp(Jerr->jmpbuf, 1);
 
  992 static int ReadJpeg(uint32_t **Image, 
int *Width, 
int *Height, FILE *File)
 
  994     struct jpeg_decompress_struct cinfo;
 
 1001     *Width = *Height = 0;
 
 1002     cinfo.err = jpeg_std_error(&Jerr.pub);
 
 1003     Jerr.pub.error_exit = JerrExit;
 
 1005     if(setjmp(Jerr.jmpbuf))
 
 1008     jpeg_create_decompress(&cinfo);
 
 1009     jpeg_stdio_src(&cinfo, File);
 
 1010     jpeg_read_header(&cinfo, 1);
 
 1011     cinfo.out_color_space = JCS_RGB;   
 
 1012     jpeg_start_decompress(&cinfo);
 
 1013     *Width = (int)cinfo.output_width;
 
 1014     *Height = (
int)cinfo.output_height;
 
 1018         ErrorMessage(
"Image dimensions exceed MAX_IMAGE_SIZE.\n");
 
 1019         jpeg_abort_decompress(&cinfo);
 
 1024     if(!(*Image = (uint32_t *)
Malloc(
sizeof(uint32_t)
 
 1025         *((
size_t)*Width)*((
size_t)*Height))))
 
 1027         jpeg_abort_decompress(&cinfo);
 
 1032     RowSize = cinfo.output_width * cinfo.output_components;
 
 1033     Buffer = (*cinfo.mem->alloc_sarray) ((j_common_ptr) &cinfo,
 
 1034         JPOOL_IMAGE, RowSize, 1);
 
 1035     ImagePtr = (uint8_t *)*Image;
 
 1037     while(cinfo.output_scanline < cinfo.output_height)
 
 1038         for(jpeg_read_scanlines(&cinfo, Buffer, 1), i = 0; i < RowSize; i += 3)
 
 1040             *(ImagePtr++) = Buffer[0][i];   
 
 1041             *(ImagePtr++) = Buffer[0][i+1]; 
 
 1042             *(ImagePtr++) = Buffer[0][i+2]; 
 
 1043             *(ImagePtr++) = 0xFF;
 
 1046     jpeg_finish_decompress(&cinfo);
 
 1047     jpeg_destroy_decompress(&cinfo);
 
 1054     *Width = *Height = 0;
 
 1055     jpeg_destroy_decompress(&cinfo);
 
 1078 static int WriteJpeg(
const uint32_t *Image, 
int Width, 
int Height,
 
 1079     FILE *File, 
int Quality)
 
 1081     struct jpeg_compress_struct cinfo;
 
 1083     uint8_t *Buffer = 0, *ImagePtr;
 
 1084     unsigned i, RowSize;
 
 1090     cinfo.err = jpeg_std_error(&Jerr.pub);
 
 1091     Jerr.pub.error_exit = JerrExit;
 
 1093     if(setjmp(Jerr.jmpbuf))
 
 1096     jpeg_create_compress(&cinfo);
 
 1097     jpeg_stdio_dest(&cinfo, File);
 
 1098     cinfo.image_width = Width;
 
 1099     cinfo.image_height = Height;
 
 1100     cinfo.input_components = 3;
 
 1101     cinfo.in_color_space = JCS_RGB;
 
 1102     jpeg_set_defaults(&cinfo);
 
 1103     jpeg_set_quality(&cinfo, (Quality < 100) ? Quality : 100, 1);
 
 1104     jpeg_start_compress(&cinfo, 1);
 
 1107     ImagePtr = (uint8_t *)Image;
 
 1109     if(!(Buffer = (uint8_t *)
Malloc(RowSize)))
 
 1112     while(cinfo.next_scanline < cinfo.image_height)
 
 1114         for(i = 0; i < RowSize; i += 3)
 
 1116             Buffer[i] = ImagePtr[0];   
 
 1117             Buffer[i+1] = ImagePtr[1]; 
 
 1118             Buffer[i+2] = ImagePtr[2]; 
 
 1122         jpeg_write_scanlines(&cinfo, &Buffer, 1);
 
 1128     jpeg_finish_compress(&cinfo);
 
 1129     jpeg_destroy_compress(&cinfo);
 
 1135     jpeg_destroy_compress(&cinfo);
 
 1155 static int ReadPng(uint32_t **Image, 
int *Width, 
int *Height, FILE *File)
 
 1157     png_bytep *RowPointers;
 
 1161     png_uint_32 PngWidth, PngHeight;
 
 1162     int BitDepth, ColorType, InterlaceType;
 
 1166     *Width = *Height = 0;
 
 1169     if(fread(Header, 1, 8, File) != 8 || png_sig_cmp(Header, 0, 8))
 
 1173     if(!(Png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL))
 
 1174         || !(Info = png_create_info_struct(Png)))
 
 1177             png_destroy_read_struct(&Png, (png_infopp)NULL, (png_infopp)NULL);
 
 1182     if(setjmp(png_jmpbuf(Png)))
 
 1185     png_init_io(Png, File);
 
 1186     png_set_sig_bytes(Png, 8);
 
 1188     png_read_info(Png, Info);
 
 1189     png_get_IHDR(Png, Info, &PngWidth, &PngHeight, &BitDepth, &ColorType,
 
 1190         &InterlaceType, (
int*)NULL, (
int*)NULL);
 
 1191     *Width = (int)PngWidth;
 
 1192     *Height = (int)PngHeight;
 
 1195     if(ColorType == PNG_COLOR_TYPE_PALETTE)
 
 1196         png_set_palette_to_rgb(Png);
 
 1197     if(ColorType == PNG_COLOR_TYPE_GRAY && BitDepth < 8)
 
 1198         png_set_expand_gray_1_2_4_to_8(Png);
 
 1199     if(ColorType == PNG_COLOR_TYPE_GRAY || ColorType == PNG_COLOR_TYPE_GRAY_ALPHA)
 
 1200         png_set_gray_to_rgb(Png);
 
 1201     if(png_get_valid(Png, Info, PNG_INFO_tRNS))
 
 1202         png_set_tRNS_to_alpha(Png);
 
 1204     png_set_strip_16(Png);
 
 1205     png_set_filler(Png, 0xFF, PNG_FILLER_AFTER);
 
 1207     png_set_interlace_handling(Png);
 
 1208     png_read_update_info(Png, Info);
 
 1211     if(!(*Image = (uint32_t *)
Malloc(
sizeof(uint32_t)
 
 1212         *((
size_t)*Width)*((
size_t)*Height)))
 
 1213         || !(RowPointers = (png_bytep *)
Malloc(
sizeof(png_bytep)
 
 1217     for(Row = 0; Row < PngHeight; Row++)
 
 1218         RowPointers[Row] = (png_bytep)(*Image + PngWidth*Row);
 
 1221     png_read_image(Png, RowPointers);
 
 1223     png_destroy_read_struct(&Png, &Info, (png_infopp)NULL);
 
 1230     *Width = *Height = 0;
 
 1231     png_destroy_read_struct(&Png, &Info, (png_infopp)NULL);
 
 1256 static int WritePng(
const uint32_t *Image, 
int Width, 
int Height, FILE *File)
 
 1258     const uint32_t *ImagePtr;
 
 1259     uint32_t *Palette = NULL;
 
 1263     png_color PngPalette[256];
 
 1264     png_byte PngTrans[256];
 
 1266     int PngColorType, NumColors, UseColor, UseAlpha;
 
 1267     int x, y, i, Success = 0;
 
 1273     if(!(RowBuffer = (uint8_t *)
Malloc(4*Width)))
 
 1276     if(!(Png = png_create_write_struct(PNG_LIBPNG_VER_STRING,
 
 1278         || !(Info = png_create_info_struct(Png)))
 
 1281             png_destroy_write_struct(&Png, (png_infopp)NULL);
 
 1287     if(setjmp(png_jmpbuf(Png)))
 
 1293     png_init_io(Png, File);
 
 1294     png_set_compression_level(Png, Z_BEST_COMPRESSION);
 
 1297         Image, Width, Height);
 
 1300     if(Palette && UseColor)
 
 1301         PngColorType = PNG_COLOR_TYPE_PALETTE;
 
 1303         PngColorType = PNG_COLOR_TYPE_RGB_ALPHA;
 
 1305         PngColorType = PNG_COLOR_TYPE_RGB;
 
 1307         PngColorType = PNG_COLOR_TYPE_GRAY;
 
 1309     png_set_IHDR(Png, Info, Width, Height, 8, PngColorType,
 
 1310         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
 
 1312     if(PngColorType == PNG_COLOR_TYPE_PALETTE)
 
 1314         for(i = 0; i < NumColors; i++)
 
 1317             PngPalette[i].red = ((uint8_t *)&Pixel)[0];
 
 1318             PngPalette[i].green = ((uint8_t *)&Pixel)[1];
 
 1319             PngPalette[i].blue = ((uint8_t *)&Pixel)[2];
 
 1320             PngTrans[i] = ((uint8_t *)&Pixel)[3];
 
 1323         png_set_PLTE(Png, Info, PngPalette, NumColors);
 
 1326             png_set_tRNS(Png, Info, PngTrans, NumColors, NULL);
 
 1329     png_write_info(Png, Info);
 
 1331     for(y = 0, ImagePtr = Image; y < Height; y++, ImagePtr += Width)
 
 1333         switch(PngColorType)
 
 1335         case PNG_COLOR_TYPE_RGB_ALPHA:
 
 1336             png_write_row(Png, (png_bytep)ImagePtr);
 
 1338         case PNG_COLOR_TYPE_RGB:
 
 1339             for(x = 0; x < Width; x++)
 
 1341                 Pixel = ImagePtr[x];
 
 1342                 RowBuffer[3*x + 0] = ((uint8_t *)&Pixel)[0];
 
 1343                 RowBuffer[3*x + 1] = ((uint8_t *)&Pixel)[1];
 
 1344                 RowBuffer[3*x + 2] = ((uint8_t *)&Pixel)[2];
 
 1347             png_write_row(Png, (png_bytep)RowBuffer);
 
 1349         case PNG_COLOR_TYPE_GRAY:
 
 1350             for(x = 0; x < Width; x++)
 
 1352                 Pixel = ImagePtr[x];
 
 1353                 RowBuffer[x] = ((uint8_t *)&Pixel)[0];
 
 1356             png_write_row(Png, (png_bytep)RowBuffer);
 
 1358         case PNG_COLOR_TYPE_PALETTE:
 
 1359             for(x = 0; x < Width; x++)
 
 1361                 Pixel = ImagePtr[x];
 
 1363                 for(i = 0; i < NumColors; i++)
 
 1364                     if(Pixel == Palette[i])
 
 1370             png_write_row(Png, (png_bytep)RowBuffer);
 
 1375     png_write_end(Png, Info);
 
 1380     png_destroy_write_struct(&Png, &Info);
 
 1401 static int ReadTiff(uint32_t **Image, 
int *Width, 
int *Height,
 
 1402     const char *FileName, 
unsigned Directory)
 
 1405     uint32 ImageWidth, ImageHeight;
 
 1408     *Width = *Height = 0;
 
 1410     if(!(Tiff = TIFFOpen(FileName, 
"r")))
 
 1416     TIFFSetDirectory(Tiff, Directory);
 
 1417     TIFFGetField(Tiff, TIFFTAG_IMAGEWIDTH, &ImageWidth);
 
 1418     TIFFGetField(Tiff, TIFFTAG_IMAGELENGTH, &ImageHeight);
 
 1419     *Width = (int)ImageWidth;
 
 1420     *Height = (int)ImageHeight;
 
 1424         ErrorMessage(
"Image dimensions exceed MAX_IMAGE_SIZE.\n");
 
 1428     if(!(*Image = (uint32_t *)
Malloc(
sizeof(uint32_t)*ImageWidth*ImageHeight)))
 
 1431     if(!TIFFReadRGBAImageOriented(Tiff, ImageWidth, ImageHeight,
 
 1432         (uint32 *)*Image, ORIENTATION_TOPLEFT, 1))
 
 1442     *Width = *Height = 0;
 
 1461 static int WriteTiff(
const uint32_t *Image, 
int Width, 
int Height,
 
 1462     const char *FileName)
 
 1465     uint16 Alpha = EXTRASAMPLE_ASSOCALPHA;
 
 1470     if(!(Tiff = TIFFOpen(FileName, 
"w")))
 
 1476     if(TIFFSetField(Tiff, TIFFTAG_IMAGEWIDTH, Width) != 1
 
 1477         || TIFFSetField(Tiff, TIFFTAG_IMAGELENGTH, Height) != 1
 
 1478         || TIFFSetField(Tiff, TIFFTAG_SAMPLESPERPIXEL, 4) != 1
 
 1479         || TIFFSetField(Tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB) != 1
 
 1480         || TIFFSetField(Tiff, TIFFTAG_EXTRASAMPLES, 1, &Alpha) != 1
 
 1481         || TIFFSetField(Tiff, TIFFTAG_BITSPERSAMPLE, 8) != 1
 
 1482         || TIFFSetField(Tiff, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT) != 1
 
 1483         || TIFFSetField(Tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG) != 1
 
 1486         || TIFFSetField(Tiff, TIFFTAG_COMPRESSION, COMPRESSION_LZW) != 1)
 
 1493     if(TIFFWriteEncodedStrip(Tiff, 0, (tdata_t)Image,
 
 1494         4*((
size_t)Width)*((
size_t)Height)) < 0)
 
 1511     const int NumPixels = Width*Height;
 
 1512     const int NumChannels = (Format & IMAGEIO_GRAYSCALE) ?
 
 1513         1 : ((Format & IMAGEIO_STRIP_ALPHA) ? 3 : 4);
 
 1514     const int ChannelStride = (Format & IMAGEIO_PLANAR) ? NumPixels : 1;
 
 1515     const int ChannelStride2 = 2*ChannelStride;
 
 1516     const int ChannelStride3 = 3*ChannelStride;
 
 1521     int Order[4] = {0, 1, 2, 3};
 
 1522     int i, x, y, PixelStride, RowStride;
 
 1525     PixelStride = (Format & IMAGEIO_PLANAR) ? 1 : NumChannels;
 
 1527     if(Format & IMAGEIO_COLUMNMAJOR)
 
 1529         RowStride = PixelStride;
 
 1530         PixelStride *= Height;
 
 1533         RowStride = Width*PixelStride;
 
 1535     if(Format & IMAGEIO_BGRFLIP)
 
 1541     if((Format & IMAGEIO_AFLIP) && !(Format & IMAGEIO_STRIP_ALPHA))
 
 1543         Order[3] = Order[2];
 
 1544         Order[2] = Order[1];
 
 1545         Order[1] = Order[0];
 
 1549     switch(Format & (IMAGEIO_U8 | IMAGEIO_SINGLE | IMAGEIO_DOUBLE))
 
 1552         if(!(DestU8  = (uint8_t *)
Malloc(
sizeof(uint8_t)*NumChannels*NumPixels)))
 
 1558             for(y = 0; y < Height; y++, Src += Width)
 
 1559                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1562                     DestU8[i] = (uint8_t)(0.299f*((uint8_t *)&Pixel)[0]
 
 1563                         + 0.587f*((uint8_t *)&Pixel)[1]
 
 1564                         + 0.114f*((uint8_t *)&Pixel)[2] + 0.5f);
 
 1568             for(y = 0; y < Height; y++, Src += Width)
 
 1569                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1572                     DestU8[i] = ((uint8_t *)&Pixel)[Order[0]];
 
 1573                     DestU8[i + ChannelStride] = ((uint8_t *)&Pixel)[Order[1]];
 
 1574                     DestU8[i + ChannelStride2] = ((uint8_t *)&Pixel)[Order[2]];
 
 1578             for(y = 0; y < Height; y++, Src += Width)
 
 1579                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1582                     DestU8[i] = ((uint8_t *)&Pixel)[Order[0]];
 
 1583                     DestU8[i + ChannelStride] = ((uint8_t *)&Pixel)[Order[1]];
 
 1584                     DestU8[i + ChannelStride2] = ((uint8_t *)&Pixel)[Order[2]];
 
 1585                     DestU8[i + ChannelStride3] = ((uint8_t *)&Pixel)[Order[3]];
 
 1590     case IMAGEIO_SINGLE:  
 
 1591         if(!(DestF = (
float *)
Malloc(
sizeof(
float)*NumChannels*NumPixels)))
 
 1597             for(y = 0; y < Height; y++, Src += Width)
 
 1598                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1601                     DestF[i] = 1.172549019607843070675535e-3f*((uint8_t *)&Pixel)[0]
 
 1602                         + 2.301960784313725357840079e-3f*((uint8_t *)&Pixel)[1]
 
 1603                         + 4.470588235294117808150007e-4f*((uint8_t *)&Pixel)[2];
 
 1607             for(y = 0; y < Height; y++, Src += Width)
 
 1608                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1611                     DestF[i] = ((uint8_t *)&Pixel)[Order[0]]/255.0f;
 
 1612                     DestF[i + ChannelStride] = ((uint8_t *)&Pixel)[Order[1]]/255.0f;
 
 1613                     DestF[i + ChannelStride2] = ((uint8_t *)&Pixel)[Order[2]]/255.0f;
 
 1617             for(y = 0; y < Height; y++, Src += Width)
 
 1618                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1621                     DestF[i] = ((uint8_t *)&Pixel)[Order[0]]/255.0f;
 
 1622                     DestF[i + ChannelStride] = ((uint8_t *)&Pixel)[Order[1]]/255.0f;
 
 1623                     DestF[i + ChannelStride2] = ((uint8_t *)&Pixel)[Order[2]]/255.0f;
 
 1624                     DestF[i + ChannelStride3] = ((uint8_t *)&Pixel)[Order[3]]/255.0f;
 
 1629     case IMAGEIO_DOUBLE:  
 
 1630         if(!(DestD = (
double *)
Malloc(
sizeof(
double)*NumChannels*NumPixels)))
 
 1636             for(y = 0; y < Height; y++, Src += Width)
 
 1637                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1640                     DestD[i] = 1.172549019607843070675535e-3*((uint8_t *)&Pixel)[0]
 
 1641                         + 2.301960784313725357840079e-3*((uint8_t *)&Pixel)[1]
 
 1642                         + 4.470588235294117808150007e-4*((uint8_t *)&Pixel)[2];
 
 1646             for(y = 0; y < Height; y++, Src += Width)
 
 1647                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1650                     DestD[i] = ((uint8_t *)&Pixel)[Order[0]]/255.0;
 
 1651                     DestD[i + ChannelStride] = ((uint8_t *)&Pixel)[Order[1]]/255.0;
 
 1652                     DestD[i + ChannelStride2] = ((uint8_t *)&Pixel)[Order[2]]/255.0;
 
 1656             for(y = 0; y < Height; y++, Src += Width)
 
 1657                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1660                     DestD[i] = ((uint8_t *)&Pixel)[Order[0]]/255.0;
 
 1661                     DestD[i + ChannelStride] = ((uint8_t *)&Pixel)[Order[1]]/255.0;
 
 1662                     DestD[i + ChannelStride2] = ((uint8_t *)&Pixel)[Order[2]]/255.0;
 
 1663                     DestD[i + ChannelStride3] = ((uint8_t *)&Pixel)[Order[3]]/255.0;
 
 1678     const int NumPixels = Width*Height;
 
 1679     const int NumChannels = (Format & IMAGEIO_GRAYSCALE) ?
 
 1680         1 : ((Format & IMAGEIO_STRIP_ALPHA) ? 3 : 4);
 
 1681     const int ChannelStride = (Format & IMAGEIO_PLANAR) ? NumPixels : 1;
 
 1682     const int ChannelStride2 = 2*ChannelStride;
 
 1683     const int ChannelStride3 = 3*ChannelStride;
 
 1684     double *SrcD = (
double *)Src;
 
 1685     float *SrcF = (
float *)Src;
 
 1686     uint8_t *SrcU8 = (uint8_t *)Src;
 
 1687     uint8_t *Dest, *DestPtr;
 
 1688     int Order[4] = {0, 1, 2, 3};
 
 1689     int i, x, y, PixelStride, RowStride;
 
 1692     if(!(Dest = (uint8_t *)
Malloc(
sizeof(uint32_t)*NumPixels)))
 
 1696     PixelStride = (Format & IMAGEIO_PLANAR) ? 1 : NumChannels;
 
 1698     if(Format & IMAGEIO_COLUMNMAJOR)
 
 1700         RowStride = PixelStride;
 
 1701         PixelStride *= Height;
 
 1704         RowStride = Width*PixelStride;
 
 1706     if(Format & IMAGEIO_BGRFLIP)
 
 1712     if((Format & IMAGEIO_AFLIP) && !(Format & IMAGEIO_STRIP_ALPHA))
 
 1714         Order[3] = Order[2];
 
 1715         Order[2] = Order[1];
 
 1716         Order[1] = Order[0];
 
 1720     switch(Format & (IMAGEIO_U8 | IMAGEIO_SINGLE | IMAGEIO_DOUBLE))
 
 1726             for(y = 0; y < Height; y++, DestPtr += 4*Width)
 
 1727                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1731                     DestPtr[4*x + 2] = SrcU8[i];
 
 1732                     DestPtr[4*x + 3] = 255;
 
 1736             for(y = 0; y < Height; y++, DestPtr += 4*Width)
 
 1737                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1739                     DestPtr[4*x + Order[0]] = SrcU8[i];
 
 1740                     DestPtr[4*x + Order[1]] = SrcU8[i + ChannelStride];
 
 1741                     DestPtr[4*x + Order[2]] = SrcU8[i + ChannelStride2];
 
 1742                     DestPtr[4*x + 3] = 255;
 
 1746             for(y = 0; y < Height; y++, DestPtr += 4*Width)
 
 1747                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1749                     DestPtr[4*x + Order[0]] = SrcU8[i];
 
 1750                     DestPtr[4*x + Order[1]] = SrcU8[i + ChannelStride];
 
 1751                     DestPtr[4*x + Order[2]] = SrcU8[i + ChannelStride2];
 
 1752                     DestPtr[4*x + Order[3]] = SrcU8[i + ChannelStride3];
 
 1757     case IMAGEIO_SINGLE:  
 
 1761             for(y = 0; y < Height; y++, DestPtr += 4*Width)
 
 1762                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1766                     DestPtr[4*x + 2] = ROUNDCLAMPF(SrcF[i]);
 
 1767                     DestPtr[4*x + 3] = 255;
 
 1771             for(y = 0; y < Height; y++, DestPtr += 4*Width)
 
 1772                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1774                     DestPtr[4*x + Order[0]] = ROUNDCLAMPF(SrcF[i]);
 
 1775                     DestPtr[4*x + Order[1]] = ROUNDCLAMPF(SrcF[i + ChannelStride]);
 
 1776                     DestPtr[4*x + Order[2]] = ROUNDCLAMPF(SrcF[i + ChannelStride2]);
 
 1777                     DestPtr[4*x + 3] = 255;
 
 1781             for(y = 0; y < Height; y++, DestPtr += 4*Width)
 
 1782                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1784                     DestPtr[4*x + Order[0]] = ROUNDCLAMPF(SrcF[i]);
 
 1785                     DestPtr[4*x + Order[1]] = ROUNDCLAMPF(SrcF[i + ChannelStride]);
 
 1786                     DestPtr[4*x + Order[2]] = ROUNDCLAMPF(SrcF[i + ChannelStride2]);
 
 1787                     DestPtr[4*x + Order[3]] = ROUNDCLAMPF(SrcF[i + ChannelStride3]);
 
 1792     case IMAGEIO_DOUBLE:  
 
 1796             for(y = 0; y < Height; y++, DestPtr += 4*Width)
 
 1797                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1801                     DestPtr[4*x + 2] = ROUNDCLAMP(SrcD[i]);
 
 1802                     DestPtr[4*x + 3] = 255;
 
 1806             for(y = 0; y < Height; y++, DestPtr += 4*Width)
 
 1807                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1809                     DestPtr[4*x + Order[0]] = ROUNDCLAMP(SrcD[i]);
 
 1810                     DestPtr[4*x + Order[1]] = ROUNDCLAMP(SrcD[i + ChannelStride]);
 
 1811                     DestPtr[4*x + Order[2]] = ROUNDCLAMP(SrcD[i + ChannelStride2]);
 
 1812                     DestPtr[4*x + 3] = 255;;
 
 1816             for(y = 0; y < Height; y++, DestPtr += 4*Width)
 
 1817                 for(x = 0, i = RowStride*y; x < Width; x++, i += PixelStride)
 
 1819                     DestPtr[4*x + Order[0]] = ROUNDCLAMP(SrcD[i]);
 
 1820                     DestPtr[4*x + Order[1]] = ROUNDCLAMP(SrcD[i + ChannelStride]);
 
 1821                     DestPtr[4*x + Order[2]] = ROUNDCLAMP(SrcD[i + ChannelStride2]);
 
 1822                     DestPtr[4*x + Order[3]] = ROUNDCLAMP(SrcD[i + ChannelStride3]);
 
 1831     return (uint32_t *)Dest;
 
 1852     if(!(File = fopen(FileName, 
"rb")))
 
 1856     Magic = ((uint32_t)getc(File));
 
 1857     Magic |= ((uint32_t)getc(File)) << 8;
 
 1858     Magic |= ((uint32_t)getc(File)) << 16;
 
 1859     Magic |= ((uint32_t)getc(File)) << 24;
 
 1870     if((Magic & 0x0000FFFFL) == 0x00004D42L)                
 
 1871         strcpy(Type, 
"BMP");
 
 1872     else if((Magic & 0x00FFFFFFL) == 0x00FFD8FFL)           
 
 1873         strcpy(Type, 
"JPEG");
 
 1874     else if(Magic == 0x474E5089L)                           
 
 1875         strcpy(Type, 
"PNG");
 
 1876     else if(Magic == 0x002A4949L || Magic == 0x2A004D4DL)   
 
 1877         strcpy(Type, 
"TIFF");
 
 1878     else if(Magic == 0x38464947L)                           
 
 1879         strcpy(Type, 
"GIF");
 
 1880     else if(Magic == 0x474E4D8AL)                           
 
 1881         strcpy(Type, 
"MNG");
 
 1882     else if((Magic & 0xF0FF00FFL) == 0x0001000AL            
 
 1883         && ((Magic >> 8) & 0xFF) < 6)
 
 1884         strcpy(Type, 
"PCX");
 
 1974     const char *FileName, 
unsigned Format)
 
 1977     uint32_t *ImageU8 = NULL;
 
 1984     if(!(File = fopen(FileName, 
"rb")))
 
 1986         ErrorMessage(
"Unable to open file \"%s\".\n", FileName);
 
 1990     if(!strcmp(Type, 
"BMP"))
 
 1992         if(!
ReadBmp(&ImageU8, Width, Height, File))
 
 1995     else if(!strcmp(Type, 
"JPEG"))
 
 1998         if(!(ReadJpeg(&ImageU8, Width, Height, File)))
 
 2002                      "Compile with USE_LIBJPEG to enable JPEG reading.\n",
 
 2006     else if(!strcmp(Type, 
"PNG"))
 
 2009         if(!(ReadPng(&ImageU8, Width, Height, File)))
 
 2013                      "Compile with USE_LIBPNG to enable PNG reading.\n",
 
 2017     else if(!strcmp(Type, 
"TIFF"))
 
 2022         if(!(ReadTiff(&ImageU8, Width, Height, FileName, 0)))
 
 2028                      "Compile with USE_LIBTIFF to enable TIFF reading.\n",
 
 2036             ErrorMessage(
"File \"%s\" is a %s image.", FileName, Type);
 
 2038             ErrorMessage(
"File \"%s\" is an unrecognized format.", FileName);
 
 2045     if(ImageU8 && Format)
 
 2077     const char *FileName, 
unsigned Format, 
int Quality)
 
 2081     enum {BMP_FORMAT, JPEG_FORMAT, PNG_FORMAT, TIFF_FORMAT} FileFormat;
 
 2084     if(!Image || Width <= 0 || Height <= 0)
 
 2092         FileFormat = BMP_FORMAT;
 
 2096         FileFormat = JPEG_FORMAT;
 
 2099         ErrorMessage(
"Compile with USE_LIBJPEG to enable JPEG writing.\n");
 
 2105         FileFormat = PNG_FORMAT;
 
 2108         ErrorMessage(
"Compile with USE_LIBPNG to enable PNG writing.\n");
 
 2115         FileFormat = TIFF_FORMAT;
 
 2118         ErrorMessage(
"Compile with USE_LIBTIFF to enable TIFF writing.\n");
 
 2133             ErrorMessage(
"Unable to determine format from extension.\n");
 
 2139     if(!(File = fopen(FileName, 
"wb")))
 
 2141         ErrorMessage(
"Unable to write to file \"%s\".\n", FileName);
 
 2151         Success = 
WriteBmp(ImageU8, Width, Height, File);
 
 2155         Success = WriteJpeg(ImageU8, Width, Height, File, Quality);
 
 2165         Success = WritePng(ImageU8, Width, Height, File);
 
 2171         Success = WriteTiff(ImageU8, Width, Height, FileName);