static ILboolean ReadIndexed(ILimage* image, PSDHEAD *Head) { ILuint ColorMode, ResourceSize, MiscInfo, i, j, NumEnt; ILushort Compressed; ILubyte * Palette = NULL; ILubyte * Resources = NULL; SIO * io = &image->io; ILushort ChannelNum; ColorMode = GetBigUInt(io); // Skip over the 'color mode data section' if (ColorMode % 3 != 0) { iSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } Palette = (ILubyte*)ialloc(ColorMode); if (Palette == NULL) return IL_FALSE; if (SIOread(io, Palette, 1, ColorMode) != ColorMode) goto cleanup_error; ResourceSize = GetBigUInt(io); // Read the 'image resources section' Resources = (ILubyte*)ialloc(ResourceSize); if (Resources == NULL) { return IL_FALSE; } if (SIOread(io, Resources, 1, ResourceSize) != ResourceSize) goto cleanup_error; MiscInfo = GetBigUInt(io); if (SIOeof(io)) goto cleanup_error; SIOseek(io, MiscInfo, IL_SEEK_CUR); Compressed = GetBigUShort(io); if (SIOeof(io)) goto cleanup_error; if (Head->Channels != 1 || Head->Depth != 8) { iSetError(IL_FORMAT_NOT_SUPPORTED); goto cleanup_error; } ChannelNum = Head->Channels; if (!iTexImage(image, Head->Width, Head->Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) goto cleanup_error; image->Pal.Palette = (ILubyte*)ialloc(ColorMode); if (image->Pal.Palette == NULL) { goto cleanup_error; } image->Pal.PalSize = ColorMode; image->Pal.PalType = IL_PAL_RGB24; NumEnt = image->Pal.PalSize / 3; for (i = 0, j = 0; i < image->Pal.PalSize; i += 3, j++) { image->Pal.Palette[i ] = Palette[j]; image->Pal.Palette[i+1] = Palette[j+NumEnt]; image->Pal.Palette[i+2] = Palette[j+NumEnt*2]; } ifree(Palette); Palette = NULL; if (!PsdGetData(image, Head, image->Data, (ILboolean)Compressed, ChannelNum)) goto cleanup_error; ParseResources(image, ResourceSize, Resources); ifree(Resources); Resources = NULL; return IL_TRUE; cleanup_error: ifree(Palette); ifree(Resources); return IL_FALSE; }
// Internal function used to load the ROT. ILboolean iLoadRotInternal(void) { ILubyte Form[4], FormName[4]; ILuint FormLen, Width, Height, Format, Channels, CompSize; ILuint MipSize, MipLevel, MipWidth, MipHeight; ILenum FormatIL; ILimage *Image; ILboolean BaseCreated = IL_FALSE; ILubyte *CompData = NULL; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } // The first entry in the file must be 'FORM', 0x20 in a big endian integer and then 'HEAD'. iread(Form, 1, 4); FormLen = GetBigUInt(); iread(FormName, 1, 4); if (strncmp(Form, "FORM", 4) || FormLen != 0x14 || strncmp(FormName, "HEAD", 4)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Next follows the width, height and format in the header. Width = GetLittleUInt(); Height = GetLittleUInt(); Format = GetLittleUInt(); //@TODO: More formats. switch (Format) { case ROT_RGBA32: // 32-bit RGBA format Channels = 4; FormatIL = IL_RGBA; break; case ROT_DXT1: // DXT1 (no alpha) Channels = 4; FormatIL = IL_RGBA; break; case ROT_DXT3: // DXT3 case ROT_DXT5: // DXT5 Channels = 4; FormatIL = IL_RGBA; // Allocates the maximum needed (the first width/height given in the file). CompSize = ((Width + 3) / 4) * ((Height + 3) / 4) * 16; CompData = ialloc(CompSize); if (CompData == NULL) return IL_FALSE; break; default: ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } if (Width == 0 || Height == 0) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } //@TODO: Find out what this is. GetLittleUInt(); // Skip this for the moment. This appears to be the number of channels. // Next comes 'FORM', a length and 'MIPS'. iread(Form, 1, 4); FormLen = GetBigUInt(); iread(FormName, 1, 4); //@TODO: Not sure if the FormLen has to be anything specific here. if (strncmp(Form, "FORM", 4) || strncmp(FormName, "MIPS", 4)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } //@TODO: Can these mipmap levels be in any order? Some things may be easier if the answer is no. Image = iCurImage; do { // Then we have 'FORM' again. iread(Form, 1, 4); // This is the size of the mipmap data. MipSize = GetBigUInt(); iread(FormName, 1, 4); if (strncmp(Form, "FORM", 4)) { if (!BaseCreated) { // Our file is malformed. ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // We have reached the end of the mipmap data. break; } if (strncmp(FormName, "MLVL", 4)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Next is the mipmap attributes (level number, width, height and length) MipLevel = GetLittleUInt(); MipWidth = GetLittleUInt(); MipHeight = GetLittleUInt(); MipSize = GetLittleUInt(); // This is the same as the previous size listed -20 (for attributes). // Lower level mipmaps cannot be larger than the main image. if (MipWidth > Width || MipHeight > Height || MipSize > CompSize) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Just create our images here. if (!BaseCreated) { if (!ilTexImage(MipWidth, MipHeight, 1, Channels, FormatIL, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; BaseCreated = IL_TRUE; } else { Image->Mipmaps = ilNewImageFull(MipWidth, MipHeight, 1, Channels, FormatIL, IL_UNSIGNED_BYTE, NULL); Image = Image->Mipmaps; } switch (Format) { case ROT_RGBA32: // 32-bit RGBA format if (iread(Image->Data, Image->SizeOfData, 1) != 1) return IL_FALSE; break; case ROT_DXT1: // Allocates the size of the compressed data. CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 8; if (CompSize != MipSize) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } CompData = ialloc(CompSize); if (CompData == NULL) return IL_FALSE; // Read in the DXT1 data... if (iread(CompData, CompSize, 1) != 1) return IL_FALSE; // ...and decompress it. if (!DecompressDXT1(Image, CompData)) { ifree(CompData); return IL_FALSE; } if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { Image->DxtcSize = CompSize; Image->DxtcData = CompData; Image->DxtcFormat = IL_DXT1; CompData = NULL; } break; case ROT_DXT3: // Allocates the size of the compressed data. CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 16; if (CompSize != MipSize) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } CompData = ialloc(CompSize); if (CompData == NULL) return IL_FALSE; // Read in the DXT3 data... if (iread(CompData, MipSize, 1) != 1) return IL_FALSE; // ...and decompress it. if (!DecompressDXT3(Image, CompData)) { ifree(CompData); return IL_FALSE; } if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { Image->DxtcSize = CompSize; Image->DxtcData = CompData; Image->DxtcFormat = IL_DXT3; CompData = NULL; } break; case ROT_DXT5: // Allocates the size of the compressed data. CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 16; if (CompSize != MipSize) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } CompData = ialloc(CompSize); if (CompData == NULL) return IL_FALSE; // Read in the DXT5 data... if (iread(CompData, MipSize, 1) != 1) return IL_FALSE; // ...and decompress it. if (!DecompressDXT5(Image, CompData)) { ifree(CompData); return IL_FALSE; } // Keeps a copy if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { Image->DxtcSize = CompSize; Image->DxtcData = CompData; Image->DxtcFormat = IL_DXT5; CompData = NULL; } break; } ifree(CompData); // Free it if it was not saved. } while (!ieof()); //@TODO: Is there any other condition that should end this? return ilFixImage(); }
ILboolean iLoadIffInternal(void) { iff_chunk chunkInfo; // -- Header info. ILuint width, height; ILuint flags, compress; ILushort tiles; ILenum format; ILubyte bpp; ILboolean tileImageDataFound; // -- Initialize the top of the chunk stack. chunkDepth = -1; // -- File should begin with a FOR4 chunk of type CIMG chunkInfo = iff_begin_read_chunk(); if (chunkInfo.chunkType != IFF_TAG_CIMG) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } /* * Read the image header * OK, we have a FOR4 of type CIMG, look for the following tags * FVER * TBHD bitmap header, definition of size, etc. * AUTH * DATE */ while (1) { chunkInfo = iff_begin_read_chunk(); // -- Right now, the only info we need about the image is in TBHD // -- so search this level until we find it. if( chunkInfo.tag == IFF_TAG_TBHD ) { // -- Header chunk found width = GetBigUInt(); height = GetBigUInt(); GetBigShort(); // -- Don't support GetBigShort(); // -- Don't support flags = GetBigUInt(); GetBigShort(); // -- Don't support tiles = GetBigUShort(); compress = GetBigUInt(); iff_end_read_chunk(); if( compress > 1 ) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } break; } else iff_end_read_chunk(); } /* END find TBHD while loop */ if (!(flags & RGB_FLAG)) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } if (flags & ALPHA_FLAG) { format = IL_RGBA; bpp = 4; } else { format = IL_RGB; bpp = 3; } if (!ilTexImage(width, height, 1, bpp, format, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; tileImageDataFound = IL_FALSE; while (!tileImageDataFound) { ILuint tileImage; ILuint tileZ; chunkInfo = iff_begin_read_chunk(); /* * OK, we have a FOR4 of type TBMP, (embedded FOR4) * look for the following tags * RGBA color data, RLE compressed tiles of 32 bbp data * ZBUF z-buffer data, 32 bit float values * CLPZ depth map specific, clipping planes, 2 float values * ESXY depth map specific, eye x-y ratios, 2 float values * HIST * VERS * FOR4 <size> BLUR (twice embedded FOR4) */ if (chunkInfo.chunkType != IFF_TAG_TBMP) { iff_end_read_chunk(); continue; } tileImageDataFound = IL_TRUE; tileImage = 0; // Si no RGBA, tileImage = tiles... if (flags & ZBUFFER_FLAG) tileZ = 0; else tileZ = tiles; // Read tiles while ( (tileImage < tiles) || (tileZ < tiles)) { char *tileData; ILushort x1, x2, y1, y2, tile_width, tile_height; ILuint remainingDataSize; ILushort tile_area; ILuint tileCompressed; chunkInfo = iff_begin_read_chunk(); if ((chunkInfo.tag != IFF_TAG_RGBA) && (chunkInfo.tag != IFF_TAG_ZBUF)) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } x1 = GetBigUShort(); y1 = GetBigUShort(); x2 = GetBigUShort(); y2 = GetBigUShort(); remainingDataSize = chunkInfo.size - 4*sizeof(ILushort); tile_width = x2 - x1 + 1; tile_height = y2 - y1 + 1; tile_area = tile_width * tile_height; if ((ILint)remainingDataSize >= (tile_width * tile_height * bpp)) tileCompressed = 0; else tileCompressed = 1; if (chunkInfo.tag == IFF_TAG_RGBA) { if (tileCompressed) { char *data = iff_read_data(remainingDataSize); if (data) { tileData = iff_decompress_tile_rle(tile_width, tile_height, bpp, data, remainingDataSize); ifree(data); } } else { tileData = iffReadUncompressedTile(tile_width, tile_height, bpp); } if (tileData) { // Dump RGBA data to our data structure ILushort i; ILuint base; base = bpp*(width * y1 + x1); for (i = 0; i < tile_height; i++) { memcpy(&iCurImage->Data[base + bpp*i*width], &tileData[bpp*i*tile_width], tile_width*bpp*sizeof(char)); } ifree(tileData); tileData = NULL; iff_end_read_chunk(); tileImage++; } else return IL_FALSE; } else if (chunkInfo.tag == IFF_TAG_ZBUF) { tileZ++; iff_end_read_chunk(); } } } //ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); // Why was this here? return ilFixImage(); }
ILboolean ReadCMYK(ILimage* image, PSDHEAD *Head) { ILuint ColorMode, ResourceSize, MiscInfo, Size, i, j; ILushort Compressed; ILenum Format, Type; ILubyte *Resources = NULL, *KChannel = NULL; ILushort ChannelNum; ColorMode = GetBigUInt(&image->io); // Skip over the 'color mode data section' image->io.seek(&image->io, ColorMode, IL_SEEK_CUR); ResourceSize = GetBigUInt(&image->io); // Read the 'image resources section' Resources = (ILubyte*)ialloc(ResourceSize); if (Resources == NULL) { return IL_FALSE; } if (image->io.read(&image->io, Resources, 1, ResourceSize) != ResourceSize) goto cleanup_error; MiscInfo = GetBigUInt(&image->io); image->io.seek(&image->io, MiscInfo, IL_SEEK_CUR); Compressed = GetBigUShort(&image->io); switch (Head->Channels) { case 4: Format = IL_RGB; ChannelNum = 4; Head->Channels = 3; break; case 5: Format = IL_RGBA; ChannelNum = 5; Head->Channels = 4; break; default: il2SetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } switch (Head->Depth) { case 8: Type = IL_UNSIGNED_BYTE; break; case 16: Type = IL_UNSIGNED_SHORT; break; default: il2SetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } if (!il2TexImage(image, Head->Width, Head->Height, 1, (ILubyte)Head->Channels, Format, Type, NULL)) goto cleanup_error; if (!PsdGetData(image, Head, image->Data, (ILboolean)Compressed, ChannelNum)) goto cleanup_error; Size = image->Bpc * image->Width * image->Height; KChannel = (ILubyte*)ialloc(Size); if (KChannel == NULL) goto cleanup_error; if (!GetSingleChannel(image, Head, KChannel, (ILboolean)Compressed)) goto cleanup_error; if (Format == IL_RGB) { for (i = 0, j = 0; i < image->SizeOfData; i += 3, j++) { image->Data[i ] = (image->Data[i ] * KChannel[j]) >> 8; image->Data[i+1] = (image->Data[i+1] * KChannel[j]) >> 8; image->Data[i+2] = (image->Data[i+2] * KChannel[j]) >> 8; } } else { // IL_RGBA // The KChannel array really holds the alpha channel on this one. for (i = 0, j = 0; i < image->SizeOfData; i += 4, j++) {
ILboolean ReadRGB(ILimage* image, PSDHEAD *Head) { ILuint ColorMode, ResourceSize, MiscInfo; ILushort Compressed; ILenum Format, Type; ILubyte *Resources = NULL; ILushort ChannelNum; ColorMode = GetBigUInt(&image->io); // Skip over the 'color mode data section' image->io.seek(&image->io, ColorMode, IL_SEEK_CUR); ResourceSize = GetBigUInt(&image->io); // Read the 'image resources section' Resources = (ILubyte*)ialloc(ResourceSize); if (Resources == NULL) return IL_FALSE; if (image->io.read(&image->io, Resources, 1, ResourceSize) != ResourceSize) goto cleanup_error; MiscInfo = GetBigUInt(&image->io); image->io.seek(&image->io, MiscInfo, IL_SEEK_CUR); Compressed = GetBigUShort(&image->io); ChannelNum = Head->Channels; if (Head->Channels == 3) { Format = IL_RGB; } else if (Head->Channels == 4) { Format = IL_RGBA; } else if (Head->Channels >= 5) { // Additional channels are accumulated as a single alpha channel, since // if an image does not have a layer set as the "background", but also // has a real alpha channel, there will be 5 channels (or more). Format = IL_RGBA; } else { il2SetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } switch (Head->Depth) { case 8: Type = IL_UNSIGNED_BYTE; break; case 16: Type = IL_UNSIGNED_SHORT; break; default: il2SetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } if (!il2TexImage(image, Head->Width, Head->Height, 1, (Format==IL_RGB) ? 3 : 4, Format, Type, NULL)) goto cleanup_error; if (!PsdGetData(image, Head, image->Data, (ILboolean)Compressed, ChannelNum)) goto cleanup_error; if (!ParseResources(image, ResourceSize, Resources)) goto cleanup_error; ifree(Resources); return IL_TRUE; cleanup_error: ifree(Resources); return IL_FALSE; }
ILboolean ReadIndexed(ILimage* image, PSDHEAD *Head) { ILuint ColorMode, ResourceSize, MiscInfo, NumEnt; ILushort Compressed; ILubyte *Palette = NULL, *Resources = NULL; ILushort ChannelNum; ColorMode = GetBigUInt(&image->io); // Skip over the 'color mode data section' if (ColorMode % 3 != 0) { il2SetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } Palette = (ILubyte*)ialloc(ColorMode); if (Palette == NULL) return IL_FALSE; if (image->io.read(&image->io, Palette, 1, ColorMode) != ColorMode) goto cleanup_error; ResourceSize = GetBigUInt(&image->io); // Read the 'image resources section' Resources = (ILubyte*)ialloc(ResourceSize); if (Resources == NULL) { return IL_FALSE; } if (image->io.read(&image->io, Resources, 1, ResourceSize) != ResourceSize) goto cleanup_error; MiscInfo = GetBigUInt(&image->io); if (image->io.eof(&image->io)) goto cleanup_error; image->io.seek(&image->io, MiscInfo, IL_SEEK_CUR); Compressed = GetBigUShort(&image->io); if (image->io.eof(&image->io)) goto cleanup_error; if (Head->Channels != 1 || Head->Depth != 8) { il2SetError(IL_FORMAT_NOT_SUPPORTED); goto cleanup_error; } ChannelNum = Head->Channels; if (!il2TexImage(image, Head->Width, Head->Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) goto cleanup_error; if (!image->Pal.use(ColorMode/3, NULL, IL_PAL_RGB24)) { goto cleanup_error; } NumEnt = image->Pal.getNumCols(); for (ILuint j = 0; j < NumEnt; j++) { image->Pal.setRGB(j, Palette[j], Palette[j+NumEnt], Palette[j+NumEnt*2]); } ifree(Palette); Palette = NULL; if (!PsdGetData(image, Head, image->Data, (ILboolean)Compressed, ChannelNum)) goto cleanup_error; ParseResources(image, ResourceSize, Resources); ifree(Resources); Resources = NULL; return IL_TRUE; cleanup_error: ifree(Palette); ifree(Resources); return IL_FALSE; }