ILboolean iGetOS2Head(OS2_HEAD * const Header) { if (iread(Header, sizeof(OS2_HEAD), 1) != 1) return IL_FALSE; UShort(&Header->bfType); UInt(&Header->biSize); Short(&Header->xHotspot); Short(&Header->yHotspot); UInt(&Header->DataOff); UInt(&Header->cbFix); //2003-09-01 changed to UShort according to MSDN UShort(&Header->cx); UShort(&Header->cy); UShort(&Header->cPlanes); UShort(&Header->cBitCount); iseek((ILint)Header->cbFix - 12, IL_SEEK_CUR); // Skip rest of header, if any. return IL_TRUE; }
ILvoid iUnCache() { //changed 2003-09-01: //make iUnCache smart enough to return if //no cache is used if(!UseCache) return; if (iread == iReadLump) return; CacheSize = 0; CachePos = 0; if (Cache) { ifree(Cache); Cache = NULL; } UseCache = IL_FALSE; iseek(CacheStartPos + CacheBytesRead, IL_SEEK_SET); return; }
ILboolean ilIsValidJpgF(ILHANDLE File) { ILuint FirstPos; ILboolean bRet; iSetInputFile(File); FirstPos = itell(); bRet = iIsValidJpg(); iseek(FirstPos, IL_SEEK_SET); return bRet; }
ILboolean ilLoadJpegF(ILHANDLE File) { ILboolean bRet; ILuint FirstPos; iSetInputFile(File); FirstPos = itell(); bRet = iLoadJpegInternal(); iseek(FirstPos, IL_SEEK_SET); return bRet; }
UTXIMPORTTABLE *GetUtxImportTable(UTXHEADER *Header) { UTXIMPORTTABLE *ImportTable; ILuint i; // Go to the name table. iseek(Header->ImportOffset, IL_SEEK_SET); // Allocate the name table. ImportTable = (UTXIMPORTTABLE*)ialloc(Header->ImportCount * sizeof(UTXIMPORTTABLE)); if (ImportTable == NULL) return NULL; for (i = 0; i < Header->ImportCount; i++) { ImportTable[i].ClassPackage = UtxReadCompactInteger(); ImportTable[i].ClassName = UtxReadCompactInteger(); ImportTable[i].Package = GetLittleUInt(); ImportTable[i].ObjectName = UtxReadCompactInteger(); ChangeObjectReference(&ImportTable[i].Package, &ImportTable[i].PackageImported); } return ImportTable; }
ILboolean GetImages(ILpal *GlobalPal, GIFHEAD *GifHead) { IMAGEDESC ImageDesc, OldImageDesc; GFXCONTROL Gfx; ILboolean BaseImage = IL_TRUE; ILimage *Image = iCurImage, *TempImage = NULL; ILuint NumImages = 0, i; ILint input; Gfx.Used = IL_TRUE; while (!ieof()) { ILubyte DisposalMethod = 1; i = itell(); if (!SkipExtensions(&Gfx)) goto error_clean; i = itell(); if (!Gfx.Used) DisposalMethod = (Gfx.Packed & 0x1C) >> 2; //read image descriptor ImageDesc.Separator = igetc(); if (ImageDesc.Separator != 0x2C) //end of image break; ImageDesc.OffX = GetLittleUShort(); ImageDesc.OffY = GetLittleUShort(); ImageDesc.Width = GetLittleUShort(); ImageDesc.Height = GetLittleUShort(); ImageDesc.ImageInfo = igetc(); if (ieof()) { ilGetError(); // Gets rid of the IL_FILE_READ_ERROR that inevitably results. break; } if (!BaseImage) { NumImages++; Image->Next = ilNewImage(iCurImage->Width, iCurImage->Height, 1, 1, 1); if (Image->Next == NULL) goto error_clean; //20040612: DisposalMethod controls how the new images data is to be combined //with the old image. 0 means that it doesn't matter how they are combined, //1 means keep the old image, 2 means set to background color, 3 is //load the image that was in place before the current (this is not implemented //here! (TODO?)) if (DisposalMethod == 2 || DisposalMethod == 3) //Note that this is actually wrong, too: If the image has a local //color table, we should really search for the best fit of the //background color table and use that index (?). Furthermore, //we should only memset the part of the image that is not read //later (if we are sure that no parts of the read image are transparent). if (!Gfx.Used && Gfx.Packed & 0x1) memset(Image->Next->Data, Gfx.Transparent, Image->SizeOfData); else memset(Image->Next->Data, GifHead->Background, Image->SizeOfData); else if (DisposalMethod == 1 || DisposalMethod == 0) memcpy(Image->Next->Data, Image->Data, Image->SizeOfData); //Interlacing has to be removed after the image was copied (line above) if (OldImageDesc.ImageInfo & (1 << 6)) { // Image is interlaced. if (!RemoveInterlace(Image)) goto error_clean; } Image = Image->Next; Image->Format = IL_COLOUR_INDEX; Image->Origin = IL_ORIGIN_UPPER_LEFT; } else { BaseImage = IL_FALSE; if (!Gfx.Used && Gfx.Packed & 0x1) memset(Image->Data, Gfx.Transparent, Image->SizeOfData); else memset(Image->Data, GifHead->Background, Image->SizeOfData); //memset(Image->Data, GifHead->Background, Image->SizeOfData); } Image->OffX = ImageDesc.OffX; Image->OffY = ImageDesc.OffY; // Check to see if the image has its own palette. if (ImageDesc.ImageInfo & (1 << 7)) { if (!iGetPalette(ImageDesc.ImageInfo, &Image->Pal)) { goto error_clean; } } else { if (!iCopyPalette(&Image->Pal, GlobalPal)) { goto error_clean; } } if (!GifGetData(Image->Data + ImageDesc.OffX + ImageDesc.OffY*Image->Width, Image->SizeOfData, ImageDesc.Width, ImageDesc.Height, Image->Width, &Gfx)) { ilSetError(IL_ILLEGAL_FILE_VALUE); goto error_clean; } // See if there was a valid graphics control extension. if (!Gfx.Used) { Gfx.Used = IL_TRUE; Image->Duration = Gfx.Delay * 10; // We want it in milliseconds. // See if a transparent colour is defined. if (Gfx.Packed & 1) { if (!ConvertTransparent(Image, Gfx.Transparent)) { goto error_clean; } } } i = itell(); // Terminates each block. if((input = igetc()) == IL_EOF) goto error_clean; if (input != 0x00) iseek(-1, IL_SEEK_CUR); // break; OldImageDesc = ImageDesc; } //Deinterlace last image if (OldImageDesc.ImageInfo & (1 << 6)) { // Image is interlaced. if (!RemoveInterlace(Image)) goto error_clean; } iCurImage->NumNext = NumImages; if (BaseImage) // Was not able to load any images in... return IL_FALSE; return IL_TRUE; error_clean: Image = iCurImage->Next; while (Image) { TempImage = Image; Image = Image->Next; ilCloseImage(TempImage); } return IL_FALSE; }
ILboolean ReadIndexed(PSDHEAD *Head) { ILuint ColorMode, ResourceSize, MiscInfo, i, j, NumEnt; ILushort Compressed; ILubyte *Palette = NULL, *Resources = NULL; ColorMode = GetBigUInt(); // Skip over the 'color mode data section' if (ColorMode % 3 != 0) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } Palette = (ILubyte*)ialloc(ColorMode); if (Palette == NULL) return IL_FALSE; if (iread(Palette, 1, ColorMode) != ColorMode) goto cleanup_error; ResourceSize = GetBigUInt(); // Read the 'image resources section' Resources = (ILubyte*)ialloc(ResourceSize); if (Resources == NULL) { return IL_FALSE; } if (iread(Resources, 1, ResourceSize) != ResourceSize) goto cleanup_error; MiscInfo = GetBigUInt(); if (ieof()) goto cleanup_error; iseek(MiscInfo, IL_SEEK_CUR); Compressed = GetBigUShort(); if (ieof()) goto cleanup_error; if (Head->Channels != 1 || Head->Depth != 8) { ilSetError(IL_FORMAT_NOT_SUPPORTED); goto cleanup_error; } ChannelNum = Head->Channels; if (!ilTexImage(Head->Width, Head->Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) goto cleanup_error; iCurImage->Pal.Palette = (ILubyte*)ialloc(ColorMode); if (iCurImage->Pal.Palette == NULL) { goto cleanup_error; } iCurImage->Pal.PalSize = ColorMode; iCurImage->Pal.PalType = IL_PAL_RGB24; NumEnt = iCurImage->Pal.PalSize / 3; for (i = 0, j = 0; i < iCurImage->Pal.PalSize; i += 3, j++) { iCurImage->Pal.Palette[i ] = Palette[j]; iCurImage->Pal.Palette[i+1] = Palette[j+NumEnt]; iCurImage->Pal.Palette[i+2] = Palette[j+NumEnt*2]; } ifree(Palette); Palette = NULL; if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed)) goto cleanup_error; ParseResources(ResourceSize, Resources); ifree(Resources); Resources = NULL; return IL_TRUE; cleanup_error: ifree(Palette); ifree(Resources); return IL_FALSE; }
// From the DTE sources (mostly by Denton Woods with corrections by Randy Heit) ILboolean iLoadDoomInternal() { ILshort width, height, graphic_header[2], column_loop, row_loop; ILint column_offset, pointer_position, first_pos; ILubyte post, topdelta, length; ILubyte *NewData; ILuint i; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } first_pos = itell(); // Needed to go back to the offset table width = GetLittleShort(); height = GetLittleShort(); graphic_header[0] = GetLittleShort(); // Not even used graphic_header[1] = GetLittleShort(); // Not even used if (!ilTexImage(width, height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; iCurImage->Pal.Palette = (ILubyte*)ialloc(IL_DOOMPAL_SIZE); if (iCurImage->Pal.Palette == NULL) { return IL_FALSE; } iCurImage->Pal.PalSize = IL_DOOMPAL_SIZE; iCurImage->Pal.PalType = IL_PAL_RGB24; memcpy(iCurImage->Pal.Palette, ilDefaultDoomPal, IL_DOOMPAL_SIZE); // 247 is always the transparent colour (usually cyan) memset(iCurImage->Data, 247, iCurImage->SizeOfData); for (column_loop = 0; column_loop < width; column_loop++) { column_offset = GetLittleInt(); pointer_position = itell(); iseek(first_pos + column_offset, IL_SEEK_SET); while (1) { if (iread(&topdelta, 1, 1) != 1) return IL_FALSE; if (topdelta == 255) break; if (iread(&length, 1, 1) != 1) return IL_FALSE; if (iread(&post, 1, 1) != 1) return IL_FALSE; // Skip extra byte for scaling for (row_loop = 0; row_loop < length; row_loop++) { if (iread(&post, 1, 1) != 1) return IL_FALSE; if (row_loop + topdelta < height) iCurImage->Data[(row_loop+topdelta) * width + column_loop] = post; } iread(&post, 1, 1); // Skip extra scaling byte } iseek(pointer_position, IL_SEEK_SET); } // Converts palette entry 247 (cyan) to transparent. if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { NewData = (ILubyte*)ialloc(iCurImage->SizeOfData * 4); if (NewData == NULL) { return IL_FALSE; } for (i = 0; i < iCurImage->SizeOfData; i++) { NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; NewData[i * 4] = iCurImage->Pal.Palette[iCurImage->Data[i]]; NewData[i * 4 + 3] = iCurImage->Data[i] != 247 ? 255 : 0; } if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, 4, IL_RGBA, iCurImage->Type, NewData)) { ifree(NewData); return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; ifree(NewData); } ilFixImage(); return IL_TRUE; }
ILboolean iLoadPcdInternal() { ILubyte VertOrientation; ILuint Width, Height, i, Total, x, CurPos = 0; ILubyte *Y1=NULL, *Y2=NULL, *CbCr=NULL, r = 0, g = 0, b = 0; ILuint PicNum; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } iseek(72, IL_SEEK_CUR); if (iread(&VertOrientation, 1, 1) != 1) return IL_FALSE; iseek(-72, IL_SEEK_CUR); // Can't rewind PicNum = iGetInt(IL_PCD_PICNUM); switch (PicNum) { case 0: iseek(0x02000, IL_SEEK_CUR); Width = 192; Height = 128; break; case 1: iseek(0x0b800, IL_SEEK_CUR); Width = 384; Height = 256; break; case 2: iseek(0x30000, IL_SEEK_CUR); Width = 768; Height = 512; break; default: ilSetError(IL_INVALID_PARAM); return IL_FALSE; } if (itell() == IL_EOF) // Supposed to have data here. return IL_FALSE; Y1 = (ILubyte*)ialloc(Width); Y2 = (ILubyte*)ialloc(Width); CbCr = (ILubyte*)ialloc(Width); if (Y1 == NULL || Y2 == NULL || CbCr == NULL) { ifree(Y1); ifree(Y2); ifree(CbCr); return IL_FALSE; } if (!ilTexImage(Width, Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; Total = Height >> 1; for (i = 0; i < Total; i++) { iread(Y1, 1, Width); iread(Y2, 1, Width); if (iread(CbCr, 1, Width) != Width) { // Only really need to check the last one. ifree(Y1); ifree(Y2); ifree(CbCr); return IL_FALSE; } for (x = 0; x < Width; x++) { YCbCr2RGB(Y1[x], CbCr[x / 2], CbCr[(Width / 2) + (x / 2)], &r, &g, &b); iCurImage->Data[CurPos++] = r; iCurImage->Data[CurPos++] = g; iCurImage->Data[CurPos++] = b; } for (x = 0; x < Width; x++) { YCbCr2RGB(Y2[x], CbCr[x / 2], CbCr[(Width / 2) + (x / 2)], &r, &g, &b); iCurImage->Data[CurPos++] = r; iCurImage->Data[CurPos++] = g; iCurImage->Data[CurPos++] = b; } } ifree(Y1); ifree(Y2); ifree(CbCr); // Not sure how it is...the documentation is hard to understand if ((VertOrientation & 0x3F) != 8) iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; else iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; return ilFixImage(); }
ILboolean iLoadSunInternal(void) { SUNHEAD Header; BITFILE *File; ILuint i, j, Padding, Offset, BytesRead; ILubyte PaddingData[16]; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } //@TODO: Right now, iGetSunHead cannot fail. if (!iGetSunHead(&Header) || !iCheckSun(&Header)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } switch (Header.Depth) { case 1: //@TODO: Find a file to test this on. File = bfile(iGetFile()); if (File == NULL) return IL_FALSE; if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; if (Header.ColorMapLength != 0) { // Data should be an index into the color map, but the color map should only be RGB (6 bytes, 2 entries). if (Header.ColorMapLength != 6) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } } iCurImage->Pal.Palette = (ILubyte*)ialloc(6); // Just need 2 entries in the color map. if (Header.ColorMapLength == 0) { // Create the color map iCurImage->Pal.Palette[0] = 0x00; // Entry for black iCurImage->Pal.Palette[1] = 0x00; iCurImage->Pal.Palette[2] = 0x00; iCurImage->Pal.Palette[3] = 0xFF; // Entry for white iCurImage->Pal.Palette[4] = 0xFF; iCurImage->Pal.Palette[5] = 0xFF; } else { iread(iCurImage->Pal.Palette, 1, 6); // Read in the color map. } iCurImage->Pal.PalSize = 6; iCurImage->Pal.PalType = IL_PAL_RGB24; Padding = (16 - (iCurImage->Width % 16)) % 16; // Has to be aligned on a 16-bit boundary. The rest is padding. // Reads the bits for (i = 0; i < iCurImage->Height; i++) { bread(&iCurImage->Data[iCurImage->Width * i], 1, iCurImage->Width, File); //bseek(File, BitPadding, IL_SEEK_CUR); //@TODO: This function does not work correctly. bread(PaddingData, 1, Padding, File); // Skip padding bits. } break; case 8: if (Header.ColorMapType == IL_SUN_NO_MAP) { // Greyscale image if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; } else { // Colour-mapped image if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; iCurImage->Pal.Palette = (ILubyte*)ialloc(Header.ColorMapLength); // Allocate color map. if (iCurImage->Pal.Palette == NULL) return IL_FALSE; if (iread(iCurImage->Pal.Palette, 1, Header.ColorMapLength) != Header.ColorMapLength) { // Read color map. ilSetError(IL_FILE_READ_ERROR); return IL_FALSE; } iCurImage->Pal.PalSize = Header.ColorMapLength; iCurImage->Pal.PalType = IL_PAL_RGB24; } if (Header.Type != IL_SUN_BYTE_ENC) { // Regular uncompressed image data Padding = (2 - (iCurImage->Bps % 2)) % 2; // Must be padded on a 16-bit boundary (2 bytes) for (i = 0; i < Header.Height; i++) { iread(iCurImage->Data + i * Header.Width, 1, iCurImage->Bps); if (Padding) // Only possible for padding to be 0 or 1. igetc(); } } else { // RLE image data for (i = 0; i < iCurImage->Height; i++) { BytesRead = iSunGetRle(iCurImage->Data + iCurImage->Bps * i, iCurImage->Bps); if (BytesRead % 2) // Each scanline must be aligned on a 2-byte boundary. igetc(); // Skip padding } } break; case 24: if (Header.ColorMapLength > 0) // Ignore any possible colormaps. iseek(Header.ColorMapLength, IL_SEEK_CUR); if (Header.Type == IL_SUN_RGB) { if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; } else { if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; } if (Header.Type != IL_SUN_BYTE_ENC) { // Regular uncompressed image data Padding = (2 - (iCurImage->Bps % 2)) % 2; // Must be padded on a 16-bit boundary (2 bytes) for (i = 0; i < Header.Height; i++) { iread(iCurImage->Data + i * Header.Width * 3, 1, iCurImage->Bps); if (Padding) // Only possible for padding to be 0 or 1. igetc(); } } else { // RLE image data for (i = 0; i < iCurImage->Height; i++) { BytesRead = iSunGetRle(iCurImage->Data + iCurImage->Bps * i, iCurImage->Bps); if (BytesRead % 2) // Each scanline must be aligned on a 2-byte boundary. igetc(); // Skip padding } } break; case 32: if (Header.ColorMapLength > 0) // Ignore any possible colormaps. iseek(Header.ColorMapLength, IL_SEEK_CUR); if (Header.Type == IL_SUN_RGB) { if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; } else { if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; } // There is no padding at the end of each scanline. Offset = 0; for (i = 0; i < Header.Height; i++) { for (j = 0; j < Header.Width; j++) { igetc(); // There is a pad byte before each pixel. iCurImage->Data[Offset] = igetc(); iCurImage->Data[Offset+1] = igetc(); iCurImage->Data[Offset+2] = igetc(); } } break; default: // Should have already been checked with iGetSunHead. return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; return ilFixImage(); }
ILboolean ReadLayerBlock(ILuint BlockLen) { BLOCKHEAD Block; LAYERINFO_CHUNK LayerInfo; LAYERBITMAP_CHUNK Bitmap; ILuint ChunkSize, Padding, i, j; ILushort NumChars; BlockLen; // Layer sub-block header if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) return IL_FALSE; if (Header.MajorVersion == 3) Block.BlockLen = GetLittleUInt(); else UInt(&Block.BlockLen); if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { return IL_FALSE; } if (Block.BlockID != PSP_LAYER_BLOCK) return IL_FALSE; if (Header.MajorVersion == 3) { iseek(256, IL_SEEK_CUR); // We don't care about the name of the layer. iread(&LayerInfo, sizeof(LayerInfo), 1); if (iread(&Bitmap, sizeof(Bitmap), 1) != 1) return IL_FALSE; } else { // Header.MajorVersion >= 4 ChunkSize = GetLittleUInt(); NumChars = GetLittleUShort(); iseek(NumChars, IL_SEEK_CUR); // We don't care about the layer's name. ChunkSize -= (2 + 4 + NumChars); if (iread(&LayerInfo, IL_MIN(sizeof(LayerInfo), ChunkSize), 1) != 1) return IL_FALSE; // Can have new entries in newer versions of the spec (5.0). Padding = (ChunkSize) - sizeof(LayerInfo); if (Padding > 0) iseek(Padding, IL_SEEK_CUR); ChunkSize = GetLittleUInt(); if (iread(&Bitmap, sizeof(Bitmap), 1) != 1) return IL_FALSE; Padding = (ChunkSize - 4) - sizeof(Bitmap); if (Padding > 0) iseek(Padding, IL_SEEK_CUR); } Channels = (ILubyte**)ialloc(sizeof(ILubyte*) * Bitmap.NumChannels); if (Channels == NULL) { return IL_FALSE; } NumChannels = Bitmap.NumChannels; for (i = 0; i < NumChannels; i++) { Channels[i] = GetChannel(); if (Channels[i] == NULL) { for (j = 0; j < i; j++) ifree(Channels[j]); return IL_FALSE; } } return IL_TRUE; }
ILboolean iLoadBlp1() { BLP1HEAD Header; ILubyte *DataAndAlpha, *Palette; ILuint i; ILimage *Image = iCurImage; ILboolean BaseCreated = IL_FALSE; #ifndef IL_NO_JPG ILubyte *JpegHeader, *JpegData; ILuint JpegHeaderSize; #endif//IL_NO_JPG if (!iGetBlp1Head(&Header)) return IL_FALSE; if (!iCheckBlp1(&Header)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } //@TODO: Remove this. i = 0; switch (Header.Compression) { case BLP_TYPE_JPG: #ifdef IL_NO_JPG // We can only do the Jpeg decoding if we do not have IL_NO_JPEG defined. return IL_FALSE; #else JpegHeaderSize = GetLittleUInt(); JpegHeader = (ILubyte*)ialloc(JpegHeaderSize); if (JpegHeader == NULL) return IL_FALSE; // Read the shared Jpeg header. if (iread(JpegHeader, 1, JpegHeaderSize) != JpegHeaderSize) { ifree(JpegHeader); return IL_FALSE; } //for (i = 0; i < 16; i++) { // Possible maximum of 16 mipmaps //@TODO: Check return value? iseek(Header.MipOffsets[i], IL_SEEK_SET); JpegData = (ILubyte*)ialloc(JpegHeaderSize + Header.MipLengths[i]); if (JpegData == NULL) { ifree(JpegHeader); return IL_FALSE; } memcpy(JpegData, JpegHeader, JpegHeaderSize); if (iread(JpegData + JpegHeaderSize, Header.MipLengths[i], 1) != 1) return IL_FALSE; // Just send the data straight to the Jpeg loader. if (!ilLoadJpegL(JpegData, JpegHeaderSize + Header.MipLengths[i])) return IL_FALSE; // The image data is in BGR(A) order, even though it is Jpeg-compressed. if (Image->Format == IL_RGBA) Image->Format = IL_BGRA; if (Image->Format == IL_RGB) Image->Format = IL_BGR; ifree(JpegData); //} ifree(JpegHeader); #endif//IL_NO_JPG break; case BLP_RAW: switch (Header.PictureType) { // There is no alpha list, so we just read like a normal indexed image. case BLP_RAW_NO_ALPHA: for (i = 0; i < 16; i++) { // Possible maximum of 16 mipmaps if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; Image = iCurImage; BaseCreated = IL_TRUE; // We have a BGRA palette. Image->Pal.Palette = (ILubyte*)ialloc(256 * 4); if (Image->Pal.Palette == NULL) return IL_FALSE; Image->Pal.PalSize = 1024; Image->Pal.PalType = IL_PAL_BGRA32; // Read in the palette ... if (iread(Image->Pal.Palette, 1, 1024) != 1024) return IL_FALSE; } else { if (Image->Width == 1 && Image->Height == 1) // Already at the smallest mipmap (1x1), so we are done. break; if (Header.MipOffsets[i] == 0 || Header.MipLengths[i] == 0) // No more mipmaps in the file. break; Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 1, IL_COLOR_INDEX, IL_UNSIGNED_BYTE, NULL); if (Image->Mipmaps == NULL) return IL_FALSE; // Copy the palette from the first image before we change our Image pointer. Image->Mipmaps->Pal.Palette = (ILubyte*)ialloc(256 * 4); if (Image->Mipmaps->Pal.Palette == NULL) return IL_FALSE; Image->Mipmaps->Pal.PalSize = 1024; Image->Mipmaps->Pal.PalType = IL_PAL_BGRA32; memcpy(Image->Mipmaps->Pal.Palette, Image->Pal.Palette, 1024); // Move to the next mipmap in the linked list. Image = Image->Mipmaps; } // The origin should be in the upper left. Image->Origin = IL_ORIGIN_UPPER_LEFT; // Seek to the data and read it. iseek(Header.MipOffsets[i], IL_SEEK_SET); if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) return IL_FALSE; } break; // These cases are identical and have an alpha list following the image data. case BLP_RAW_PLUS_ALPHA1: case BLP_RAW_PLUS_ALPHA2: // Create the image. if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; DataAndAlpha = (ILubyte*)ialloc(Header.Width * Header.Height); Palette = (ILubyte*)ialloc(256 * 4); if (DataAndAlpha == NULL || Palette == NULL) { ifree(DataAndAlpha); ifree(Palette); return IL_FALSE; } // Read in the data and the palette. if (iread(Palette, 1, 1024) != 1024) { ifree(Palette); return IL_FALSE; } // Seek to the data and read it. iseek(Header.MipOffsets[i], IL_SEEK_SET); if (iread(DataAndAlpha, Header.Width * Header.Height, 1) != 1) { ifree(DataAndAlpha); ifree(Palette); return IL_FALSE; } // Convert the color-indexed data to BGRX. for (i = 0; i < Header.Width * Header.Height; i++) { Image->Data[i*4] = Palette[DataAndAlpha[i]*4]; Image->Data[i*4+1] = Palette[DataAndAlpha[i]*4+1]; Image->Data[i*4+2] = Palette[DataAndAlpha[i]*4+2]; } // Read in the alpha list. if (iread(DataAndAlpha, Header.Width * Header.Height, 1) != 1) { ifree(DataAndAlpha); ifree(Palette); return IL_FALSE; } // Finally put the alpha data into the image data. for (i = 0; i < Header.Width * Header.Height; i++) { Image->Data[i*4+3] = DataAndAlpha[i]; } ifree(DataAndAlpha); ifree(Palette); break; } break; //default: // Should already be checked by iCheckBlp1. } // Set the origin (always upper left). Image->Origin = IL_ORIGIN_UPPER_LEFT; return ilFixImage(); }
// Internal function to uncompress the .pcx (all .pcx files are rle compressed) ILboolean iUncompressPcx(PCXHEAD *Header) { //changed decompression loop 2003-09-01 //From the pcx spec: "There should always //be a decoding break at the end of each scan line. //But there will not be a decoding break at the end of //each plane within each scan line." //This is now handled correctly (hopefully ;) ) ILubyte ByteHead, Colour, *ScanLine /* For all planes */; ILuint ScanLineSize; ILuint c, i, x, y; if (Header->Bpp < 8) { /*ilSetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE;*/ return iUncompressSmall(Header); } if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; switch (iCurImage->Bpp) { case 1: iCurImage->Format = IL_COLOUR_INDEX; iCurImage->Pal.PalType = IL_PAL_RGB24; iCurImage->Pal.PalSize = 256 * 3; // Need to find out for sure... iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); if (iCurImage->Pal.Palette == NULL) { return IL_FALSE; } break; //case 2: // No 16-bit images in the pcx format! case 3: iCurImage->Format = IL_RGB; iCurImage->Pal.Palette = NULL; iCurImage->Pal.PalSize = 0; iCurImage->Pal.PalType = IL_PAL_NONE; break; case 4: iCurImage->Format = IL_RGBA; iCurImage->Pal.Palette = NULL; iCurImage->Pal.PalSize = 0; iCurImage->Pal.PalType = IL_PAL_NONE; break; default: ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } ScanLineSize = iCurImage->Bpp*Header->Bps; ScanLine = (ILubyte*)ialloc(ScanLineSize); if (ScanLine == NULL) { return IL_FALSE; } //changed 2003-09-01 //having the decoding code twice is error-prone, //so I made iUnCache() smart enough to grasp //if iPreCache() wasn't called and call it //anyways. if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) iPreCache(iCurImage->SizeOfData / 4); for (y = 0; y < iCurImage->Height; y++) { x = 0; //read scanline while (x < ScanLineSize) { if (iread(&ByteHead, 1, 1) != 1) { iUnCache(); goto file_read_error; } if ((ByteHead & 0xC0) == 0xC0) { ByteHead &= 0x3F; if (iread(&Colour, 1, 1) != 1) { iUnCache(); goto file_read_error; } if (x + ByteHead > ScanLineSize) { iUnCache(); goto file_read_error; } for (i = 0; i < ByteHead; i++) { ScanLine[x++] = Colour; } } else { ScanLine[x++] = ByteHead; } } //convert plane-separated scanline into index, rgb or rgba pixels. //there might be a padding byte at the end of each scanline... for (x = 0; x < iCurImage->Width; x++) { for(c = 0; c < iCurImage->Bpp; c++) { iCurImage->Data[y * iCurImage->Bps + x * iCurImage->Bpp + c] = ScanLine[x + c * Header->Bps]; } } } iUnCache(); // Read in the palette if (Header->Version == 5 && iCurImage->Bpp == 1) { x = itell(); if (iread(&ByteHead, 1, 1) == 0) { // If true, assume that we have a luminance image. ilGetError(); // Get rid of the IL_FILE_READ_ERROR. iCurImage->Format = IL_LUMINANCE; if (iCurImage->Pal.Palette) ifree(iCurImage->Pal.Palette); iCurImage->Pal.PalSize = 0; iCurImage->Pal.PalType = IL_PAL_NONE; } else { if (ByteHead != 12) // Some Quake2 .pcx files don't have this byte for some reason. iseek(-1, IL_SEEK_CUR); if (iread(iCurImage->Pal.Palette, 1, iCurImage->Pal.PalSize) != iCurImage->Pal.PalSize) goto file_read_error; } } ifree(ScanLine); return IL_TRUE; file_read_error: ifree(ScanLine); //added 2003-09-01 ilSetError(IL_FILE_READ_ERROR); return IL_FALSE; }
// Internal function used to load the icon. ILboolean iLoadIcnsInternal() { ICNSHEAD Header; ICNSDATA Entry; ILimage *Image = NULL; ILboolean BaseCreated = IL_FALSE; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } iread(Header.Head, 4, 1); Header.Size = GetBigInt(); if (strncmp(Header.Head, "icns", 4)) // First 4 bytes have to be 'icns'. return IL_FALSE; while ((ILint)itell() < Header.Size && !ieof()) { iread(Entry.ID, 4, 1); Entry.Size = GetBigInt(); if (!strncmp(Entry.ID, "it32", 4)) // 128x128 24-bit { if (iIcnsReadData(&BaseCreated, IL_FALSE, 128, &Entry, &Image) == IL_FALSE) goto icns_error; } else if (!strncmp(Entry.ID, "t8mk", 4)) // 128x128 alpha mask { if (iIcnsReadData(&BaseCreated, IL_TRUE, 128, &Entry, &Image) == IL_FALSE) goto icns_error; } else if (!strncmp(Entry.ID, "ih32", 4)) // 48x48 24-bit { if (iIcnsReadData(&BaseCreated, IL_FALSE, 48, &Entry, &Image) == IL_FALSE) goto icns_error; } else if (!strncmp(Entry.ID, "h8mk", 4)) // 48x48 alpha mask { if (iIcnsReadData(&BaseCreated, IL_TRUE, 48, &Entry, &Image) == IL_FALSE) goto icns_error; } else if (!strncmp(Entry.ID, "il32", 4)) // 32x32 24-bit { if (iIcnsReadData(&BaseCreated, IL_FALSE, 32, &Entry, &Image) == IL_FALSE) goto icns_error; } else if (!strncmp(Entry.ID, "l8mk", 4)) // 32x32 alpha mask { if (iIcnsReadData(&BaseCreated, IL_TRUE, 32, &Entry, &Image) == IL_FALSE) goto icns_error; } else if (!strncmp(Entry.ID, "is32", 4)) // 16x16 24-bit { if (iIcnsReadData(&BaseCreated, IL_FALSE, 16, &Entry, &Image) == IL_FALSE) goto icns_error; } else if (!strncmp(Entry.ID, "s8mk", 4)) // 16x16 alpha mask { if (iIcnsReadData(&BaseCreated, IL_TRUE, 16, &Entry, &Image) == IL_FALSE) goto icns_error; } #ifndef IL_NO_JP2 else if (!strncmp(Entry.ID, "ic09", 4)) // 512x512 JPEG2000 encoded - Uses JasPer { if (iIcnsReadData(&BaseCreated, IL_FALSE, 512, &Entry, &Image) == IL_FALSE) goto icns_error; } else if (!strncmp(Entry.ID, "ic08", 4)) // 256x256 JPEG2000 encoded - Uses JasPer { if (iIcnsReadData(&BaseCreated, IL_FALSE, 256, &Entry, &Image) == IL_FALSE) goto icns_error; } #endif//IL_NO_JP2 else // Not a valid format or one that we can use { iseek(Entry.Size - 8, IL_SEEK_CUR); } } return ilFixImage(); icns_error: return IL_FALSE; }
// Internal function used to load the BLP. ILboolean iLoadBlpInternal(void) { BLP2HEAD Header; ILubyte *CompData; ILimage *Image; ILuint Mip, j, x, CompSize, AlphaSize, AlphaOff; ILint y; ILboolean BaseCreated = IL_FALSE; ILubyte *DataAndAlpha = NULL, *Palette = NULL, AlphaMask; //, *JpegHeader, *JpegData; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (!iGetBlp2Head(&Header)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } if (!iCheckBlp2(&Header)) { goto check_blp1; } //@TODO: Remove this! if (Header.Type != BLP_TYPE_DXTC_RAW) return IL_FALSE; switch (Header.Compression) { case BLP_RAW: for (Mip = 0; Mip < 16; Mip++) { // Possible maximum of 16 mipmaps if (BaseCreated) { if (Header.HasMips == 0) // Does not have mipmaps, so we are done. break; if (Image->Width == 1 && Image->Height == 1) // Already at the smallest mipmap (1x1), so we are done. break; if (Header.MipOffsets[Mip] == 0 || Header.MipLengths == 0) // No more mipmaps in the file. break; } switch (Header.AlphaBits) { case 0: if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; Image = iCurImage; BaseCreated = IL_TRUE; Image->Pal.Palette = (ILubyte*)ialloc(256 * 4); // 256 entries of ARGB8888 values (1024). if (Image->Pal.Palette == NULL) return IL_FALSE; Image->Pal.PalSize = 1024; Image->Pal.PalType = IL_PAL_BGRA32; //@TODO: Find out if this is really BGRA data. if (iread(Image->Pal.Palette, 1, 1024) != 1024) // Read in the palette. return IL_FALSE; } else { Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL); if (Image->Mipmaps == NULL) return IL_FALSE; // Copy the palette from the first image before we change our Image pointer. iCopyPalette(&Image->Mipmaps->Pal, &Image->Pal); // Move to the next mipmap in the linked list. Image = Image->Mipmaps; } // The origin should be in the upper left. Image->Origin = IL_ORIGIN_UPPER_LEFT; // These two should be the same (tells us how much data is in the file for this mipmap level). if (Header.MipLengths[Mip] != Image->SizeOfData) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Finally read in the image data. iseek(Header.MipOffsets[Mip], IL_SEEK_SET); if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) return IL_FALSE; break; case 1: if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; Image = iCurImage; BaseCreated = IL_TRUE; Palette = (ILubyte*)ialloc(256 * 4); if (Palette == NULL) return IL_FALSE; // Read in the palette. if (iread(Palette, 1, 1024) != 1024) { ifree(Palette); return IL_FALSE; } // We only allocate this once and reuse this buffer with every mipmap (since successive ones are smaller). DataAndAlpha = (ILubyte*)ialloc(Image->Width * Image->Height); if (DataAndAlpha == NULL) { ifree(DataAndAlpha); ifree(Palette); return IL_FALSE; } } else { Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL); if (Image->Mipmaps == NULL) return IL_FALSE; // Move to the next mipmap in the linked list. Image = Image->Mipmaps; } // The origin should be in the upper left. Image->Origin = IL_ORIGIN_UPPER_LEFT; // Determine the size of the alpha data following the color indices. AlphaSize = Image->Width * Image->Height / 8; if (AlphaSize == 0) AlphaSize = 1; // Should never be 0. // These two should be the same (tells us how much data is in the file for this mipmap level). if (Header.MipLengths[Mip] != Image->SizeOfData / 4 + AlphaSize) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Seek to the data and read it. iseek(Header.MipOffsets[Mip], IL_SEEK_SET); if (iread(DataAndAlpha, Image->Width * Image->Height, 1) != 1) { ifree(DataAndAlpha); ifree(Palette); return IL_FALSE; } // Convert the color-indexed data to BGRX. for (j = 0; j < Image->Width * Image->Height; j++) { Image->Data[j*4] = Palette[DataAndAlpha[j]*4]; Image->Data[j*4+1] = Palette[DataAndAlpha[j]*4+1]; Image->Data[j*4+2] = Palette[DataAndAlpha[j]*4+2]; } // Read in the alpha list. if (iread(DataAndAlpha, AlphaSize, 1) != 1) { ifree(DataAndAlpha); ifree(Palette); return IL_FALSE; } AlphaMask = 0x01; // Lowest bit AlphaOff = 0; // The really strange thing about this alpha data is that it is upside-down when compared to the // regular color-indexed data, so we have to flip it. for (y = Image->Height - 1; y >= 0; y--) { for (x = 0; x < Image->Width; x++) { if (AlphaMask == 0) { // Shifting it past the highest bit makes it 0, since we only have 1 byte. AlphaOff++; // Move along the alpha buffer. AlphaMask = 0x01; // Reset the alpha mask. } // This is just 1-bit alpha, so it is either on or off. Image->Data[Image->Bps * y + x * 4 + 3] = DataAndAlpha[AlphaOff] & AlphaMask ? 0xFF : 0x00; AlphaMask <<= 1; } } break; default: //@TODO: Accept any other alpha values? ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } } // Done, so we can finally free these two. ifree(DataAndAlpha); ifree(Palette); break; case BLP_DXTC: for (Mip = 0; Mip < 16; Mip++) { // Possible maximum of 16 mipmaps //@TODO: Other formats //if (Header.AlphaBits == 0) // if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) // return IL_FALSE; if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; Image = iCurImage; BaseCreated = IL_TRUE; } else { if (Header.HasMips == 0) // Does not have mipmaps, so we are done. break; if (Image->Width == 1 && Image->Height == 1) // Already at the smallest mipmap (1x1), so we are done. break; if (Header.MipOffsets[Mip] == 0 || Header.MipLengths[Mip] == 0) // No more mipmaps in the file. break; //@TODO: Other formats // ilNewImageFull automatically changes widths and heights of 0 to 1, so we do not have to worry about it. Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); if (Image->Mipmaps == NULL) return IL_FALSE; Image = Image->Mipmaps; } // The origin should be in the upper left. Image->Origin = IL_ORIGIN_UPPER_LEFT; //@TODO: Only do the allocation once. CompData = (ILubyte*)ialloc(Header.MipLengths[Mip]); if (CompData == NULL) return IL_FALSE; // Read in the compressed mipmap data. iseek(Header.MipOffsets[Mip], IL_SEEK_SET); if (iread(CompData, 1, Header.MipLengths[Mip]) != Header.MipLengths[Mip]) { ifree(CompData); return IL_FALSE; } switch (Header.AlphaBits) { case 0: // DXT1 without alpha case 1: // DXT1 with alpha // Check to make sure that the MipLength reported is the size needed, so that // DecompressDXT1 does not crash. CompSize = ((Image->Width + 3) / 4) * ((Image->Height + 3) / 4) * 8; if (CompSize != Header.MipLengths[Mip]) { ilSetError(IL_INVALID_FILE_HEADER); ifree(CompData); return IL_FALSE; } if (!DecompressDXT1(Image, CompData)) { ifree(CompData); return IL_FALSE; } break; case 8: // Check to make sure that the MipLength reported is the size needed, so that // DecompressDXT3/5 do not crash. CompSize = ((Image->Width + 3) / 4) * ((Image->Height + 3) / 4) * 16; if (CompSize != Header.MipLengths[Mip]) { ifree(CompData); ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } switch (Header.AlphaType) { case 0: // All three of case 1: // these refer to case 8: // DXT3... if (!DecompressDXT3(Image, CompData)) { ifree(CompData); return IL_FALSE; } break; case 7: // DXT5 compression if (!DecompressDXT5(Image, CompData)) { ifree(CompData); return IL_FALSE; } break; //default: // Should already be checked by iCheckBlp2. } break; //default: // Should already be checked by iCheckBlp2. } //@TODO: Save DXTC data. ifree(CompData); } break; //default: } return ilFixImage(); check_blp1: iseek(-148, IL_SEEK_CUR); // Go back the size of the BLP2 header, since we tried reading it. return iLoadBlp1(); }
ILboolean iReadRleSgi(iSgiHeader *Head) { #ifdef __LITTLE_ENDIAN__ ILuint ixTable; #endif ILuint ChanInt = 0; ILuint ixPlane, ixHeight,ixPixel, RleOff, RleLen; ILuint *OffTable=NULL, *LenTable=NULL, TableSize, Cur; ILubyte **TempData=NULL; if (!iNewSgi(Head)) return IL_FALSE; TableSize = Head->YSize * Head->ZSize; OffTable = (ILuint*)ialloc(TableSize * sizeof(ILuint)); LenTable = (ILuint*)ialloc(TableSize * sizeof(ILuint)); if (OffTable == NULL || LenTable == NULL) goto cleanup_error; if (iread(OffTable, TableSize * sizeof(ILuint), 1) != 1) goto cleanup_error; if (iread(LenTable, TableSize * sizeof(ILuint), 1) != 1) goto cleanup_error; #ifdef __LITTLE_ENDIAN__ // Fix the offset/len table (it's big endian format) for (ixTable = 0; ixTable < TableSize; ixTable++) { iSwapUInt(OffTable + ixTable); iSwapUInt(LenTable + ixTable); } #endif //__LITTLE_ENDIAN__ // We have to create a temporary buffer for the image, because SGI // images are plane-separated. */ TempData = (ILubyte**)ialloc(Head->ZSize * sizeof(ILubyte*)); if (TempData == NULL) goto cleanup_error; imemclear(TempData, Head->ZSize * sizeof(ILubyte*)); // Just in case ialloc fails then cleanup_error. for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { TempData[ixPlane] = (ILubyte*)ialloc(Head->XSize * Head->YSize * Head->Bpc); if (TempData[ixPlane] == NULL) goto cleanup_error; } // Read the Planes into the temporary memory for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { for (ixHeight = 0, Cur = 0; ixHeight < Head->YSize; ixHeight++, Cur += Head->XSize * Head->Bpc) { RleOff = OffTable[ixHeight + ixPlane * Head->YSize]; RleLen = LenTable[ixHeight + ixPlane * Head->YSize]; // Seeks to the offset table position iseek(RleOff, IL_SEEK_SET); if (iGetScanLine((TempData[ixPlane]) + (ixHeight * Head->XSize * Head->Bpc), Head, RleLen) != Head->XSize * Head->Bpc) { ilSetError(IL_ILLEGAL_FILE_VALUE); goto cleanup_error; } } } // DW: Removed on 05/25/2002. /*// Check if an alphaplane exists and invert it if (Head->ZSize == 4) { for (ixPixel=0; (ILint)ixPixel<Head->XSize * Head->YSize; ixPixel++) { TempData[3][ixPixel] = TempData[3][ixPixel] ^ 255; } }*/ // Assemble the image from its planes for (ixPixel = 0; ixPixel < iCurImage->SizeOfData; ixPixel += Head->ZSize * Head->Bpc, ChanInt += Head->Bpc) { for (ixPlane = 0; (ILint)ixPlane < Head->ZSize * Head->Bpc; ixPlane += Head->Bpc) { iCurImage->Data[ixPixel + ixPlane] = TempData[ixPlane][ChanInt]; if (Head->Bpc == 2) iCurImage->Data[ixPixel + ixPlane + 1] = TempData[ixPlane][ChanInt + 1]; } } #ifdef __LITTLE_ENDIAN__ if (Head->Bpc == 2) sgiSwitchData(iCurImage->Data, iCurImage->SizeOfData); #endif ifree(OffTable); ifree(LenTable); for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { ifree(TempData[ixPlane]); } ifree(TempData); return IL_TRUE; cleanup_error: ifree(OffTable); ifree(LenTable); if (TempData) { for (ixPlane = 0; ixPlane < Head->ZSize; ixPlane++) { ifree(TempData[ixPlane]); } ifree(TempData); } return IL_FALSE; }
ILubyte *GetChannel() { BLOCKHEAD Block; CHANNEL_CHUNK Channel; ILubyte *CompData, *Data; ILuint ChunkSize, Padding; if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) return NULL; if (Header.MajorVersion == 3) Block.BlockLen = GetLittleUInt(); else UInt(&Block.BlockLen); if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { ilSetError(IL_ILLEGAL_FILE_VALUE); return NULL; } if (Block.BlockID != PSP_CHANNEL_BLOCK) { ilSetError(IL_ILLEGAL_FILE_VALUE); return NULL; } if (Header.MajorVersion >= 4) { ChunkSize = GetLittleUInt(); if (iread(&Channel, sizeof(Channel), 1) != 1) return NULL; Padding = (ChunkSize - 4) - sizeof(Channel); if (Padding > 0) iseek(Padding, IL_SEEK_CUR); } else { if (iread(&Channel, sizeof(Channel), 1) != 1) return NULL; } CompData = (ILubyte*)ialloc(Channel.CompLen); Data = (ILubyte*)ialloc(AttChunk.Width * AttChunk.Height); if (CompData == NULL || Data == NULL) { ifree(Data); ifree(CompData); return NULL; } if (iread(CompData, 1, Channel.CompLen) != Channel.CompLen) { ifree(CompData); ifree(Data); return NULL; } switch (AttChunk.Compression) { case PSP_COMP_NONE: ifree(Data); return CompData; break; case PSP_COMP_RLE: if (!UncompRLE(CompData, Data, Channel.CompLen)) { ifree(CompData); ifree(Data); return IL_FALSE; } break; default: ifree(CompData); ifree(Data); ilSetError(IL_INVALID_FILE_HEADER); return NULL; } ifree(CompData); return Data; }
ILboolean ReadAlphaBlock(ILuint BlockLen) { BLOCKHEAD Block; ALPHAINFO_CHUNK AlphaInfo; ALPHA_CHUNK AlphaChunk; ILushort NumAlpha, StringSize; ILuint ChunkSize, Padding; if (Header.MajorVersion == 3) { NumAlpha = GetLittleUShort(); } else { ChunkSize = GetLittleUInt(); NumAlpha = GetLittleUShort(); Padding = (ChunkSize - 4 - 2); if (Padding > 0) iseek(Padding, IL_SEEK_CUR); } // Alpha channel header if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) return IL_FALSE; if (Header.MajorVersion == 3) Block.BlockLen = GetLittleUInt(); else UInt(&Block.BlockLen); if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { return IL_FALSE; } if (Block.BlockID != PSP_ALPHA_CHANNEL_BLOCK) return IL_FALSE; if (Header.MajorVersion >= 4) { ChunkSize = GetLittleUInt(); StringSize = GetLittleUShort(); iseek(StringSize, IL_SEEK_CUR); if (iread(&AlphaInfo, sizeof(AlphaInfo), 1) != 1) return IL_FALSE; Padding = (ChunkSize - 4 - 2 - StringSize - sizeof(AlphaInfo)); if (Padding > 0) iseek(Padding, IL_SEEK_CUR); ChunkSize = GetLittleUInt(); if (iread(&AlphaChunk, sizeof(AlphaChunk), 1) != 1) return IL_FALSE; Padding = (ChunkSize - 4 - sizeof(AlphaChunk)); if (Padding > 0) iseek(Padding, IL_SEEK_CUR); } else { iseek(256, IL_SEEK_CUR); iread(&AlphaInfo, sizeof(AlphaInfo), 1); if (iread(&AlphaChunk, sizeof(AlphaChunk), 1) != 1) return IL_FALSE; } /*Alpha = (ILubyte*)ialloc(AlphaInfo.AlphaRect.x2 * AlphaInfo.AlphaRect.y2); if (Alpha == NULL) { return IL_FALSE; }*/ Alpha = GetChannel(); if (Alpha == NULL) return IL_FALSE; return IL_TRUE; }
ILboolean ReadRGB(PSDHEAD *Head) { ILuint ColorMode, ResourceSize, MiscInfo; ILushort Compressed; ILenum Format, Type; ILubyte *Resources = NULL; ColorMode = GetBigUInt(); // Skip over the 'color mode data section' iseek(ColorMode, IL_SEEK_CUR); ResourceSize = GetBigUInt(); // Read the 'image resources section' Resources = (ILubyte*)ialloc(ResourceSize); if (Resources == NULL) return IL_FALSE; if (iread(Resources, 1, ResourceSize) != ResourceSize) goto cleanup_error; MiscInfo = GetBigUInt(); iseek(MiscInfo, IL_SEEK_CUR); Compressed = GetBigUShort(); 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 { ilSetError(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: ilSetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } if (!ilTexImage(Head->Width, Head->Height, 1, (Format==IL_RGB) ? 3 : 4, Format, Type, NULL)) goto cleanup_error; if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed)) goto cleanup_error; if (!ParseResources(ResourceSize, Resources)) goto cleanup_error; ifree(Resources); return IL_TRUE; cleanup_error: ifree(Resources); return IL_FALSE; }
// Internal function used to load the UTX. ILboolean iLoadUtxInternal(void) { UTXHEADER Header; UTXENTRYNAME *NameEntries; UTXEXPORTTABLE *ExportTable; UTXIMPORTTABLE *ImportTable; UTXPALETTE *Palettes; ILimage *Image; ILuint NumPal = 0, i, j = 0; ILint Name; ILubyte Type; ILint Val; ILint Size; ILint Width, Height, PalEntry; ILboolean BaseCreated = IL_FALSE, HasPal; ILuint Pos; ILint Format; ILubyte *CompData = NULL; ILubyte ExtraData[9]; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (!GetUtxHead(&Header)) return IL_FALSE; if (!CheckUtxHead(&Header)) return IL_FALSE; // Now we grab the name table. NameEntries = GetUtxNameTable(&Header); if (NameEntries == NULL) return IL_FALSE; // Then we get the export table. ExportTable = GetUtxExportTable(&Header); if (ExportTable == NULL) { UtxDestroyNameEntries(NameEntries, &Header); return IL_FALSE; } // Then the last table is the import table. ImportTable = GetUtxImportTable(&Header); if (ImportTable == NULL) { UtxDestroyNameEntries(NameEntries, &Header); UtxDestroyExportTable(ExportTable, &Header); return IL_FALSE; } for (i = 0; i < Header.ExportCount; i++) { if (!strcmp(NameEntries[ImportTable[ExportTable[i].Class].ObjectName].Name, "Palette")) NumPal++; } if (NumPal == 0) //@TODO: Take care of UTX files without paletted data. return IL_FALSE; Palettes = (UTXPALETTE*)ialloc(NumPal * sizeof(UTXPALETTE)); if (Palettes == NULL) { UtxDestroyNameEntries(NameEntries, &Header); UtxDestroyExportTable(ExportTable, &Header); UtxDestroyImportTable(ImportTable, &Header); return IL_FALSE; } NumPal = 0; for (i = 0; i < Header.ExportCount; i++) { if (!strcmp(NameEntries[ImportTable[ExportTable[i].Class].ObjectName].Name, "Palette")) { //Palettes[i].Name = strdup(NameEntries[ExportTable[i].ObjectName].Name); Palettes[NumPal].Name = i;//ExportTable[i].ObjectName; iseek(ExportTable[NumPal].SerialOffset, IL_SEEK_SET); Name = igetc(); // Skip the 2. Palettes[NumPal].Count = UtxReadCompactInteger(); Palettes[NumPal].Pal = (ILubyte*)ialloc(Palettes[NumPal].Count * 4); if (/*Palettes[NumPal].Name == NULL || */Palettes[NumPal].Pal == NULL) { UtxDestroyNameEntries(NameEntries, &Header); UtxDestroyExportTable(ExportTable, &Header); UtxDestroyImportTable(ImportTable, &Header); UtxDestroyPalettes(Palettes, NumPal); return IL_FALSE; } if (iread(Palettes[NumPal].Pal, Palettes[NumPal].Count * 4, 1) != 1) //@TODO: Deallocations here! return IL_FALSE; NumPal++; } } for (i = 0; i < Header.ExportCount; i++) { if (!strcmp(NameEntries[ImportTable[ExportTable[i].Class].ObjectName].Name, "Texture")) { iseek(ExportTable[i].SerialOffset, IL_SEEK_SET); Width = -1; Height = -1; PalEntry = NumPal; HasPal = IL_FALSE; Format = -1; ++j; j = j; do { Pos = itell(); Name = UtxReadCompactInteger(); if (!strcmp(NameEntries[Name].Name, "None")) break; Type = igetc(); Size = (Type & 0x70) >> 4; if (/*Name == 0 && */Type == 0xA2) igetc(); // Byte is 1 here... switch (Type & 0x0F) { case 1: Val = igetc(); break; case 2: Val = GetLittleUInt(); break; case 3: // Boolean value is in the info byte. igetc(); break; case 4: GetLittleFloat(); break; case 5: case 6: Val = itell(); Val = UtxReadCompactInteger(); break; case 10: Val = igetc(); switch (Size) { case 0: iseek(1, IL_SEEK_CUR); break; case 1: iseek(2, IL_SEEK_CUR); break; case 2: iseek(4, IL_SEEK_CUR); break; case 3: iseek(12, IL_SEEK_CUR); break; } break; default: // Uhm... Val = Val; break; } //@TODO: What should we do if Name >= Header.NameCount? if ((ILuint)Name < Header.NameCount) { if (!strcmp(NameEntries[Name].Name, "Palette")) { Val--; if (HasPal == IL_FALSE) { for (PalEntry = 0; (ILuint)PalEntry < NumPal; PalEntry++) { if (Val == Palettes[PalEntry].Name) { HasPal = IL_TRUE; break; } } } } if (!strcmp(NameEntries[Name].Name, "Format")) if (Format == -1) Format = Val; if (!strcmp(NameEntries[Name].Name, "USize")) if (Width == -1) Width = Val; if (!strcmp(NameEntries[Name].Name, "VSize")) if (Height == -1) Height = Val; } } while (!ieof()); if (Format == -1) Format = UTX_P8; if (Width == -1 || Height == -1 || (PalEntry == NumPal && Format != UTX_DXT1) || (Format != UTX_P8 && Format != UTX_DXT1)) return IL_FALSE; if (BaseCreated == IL_FALSE) { BaseCreated = IL_TRUE; ilTexImage(Width, Height, 1, UtxFormatToBpp(Format), UtxFormatToDevIL(Format), IL_UNSIGNED_BYTE, NULL); Image = iCurImage; } else { Image->Next = ilNewImageFull(Width, Height, 1, UtxFormatToBpp(Format), UtxFormatToDevIL(Format), IL_UNSIGNED_BYTE, NULL); if (Image->Next == NULL) return IL_FALSE; Image = Image->Next; } iseek(5, IL_SEEK_CUR); UtxReadCompactInteger(); switch (Format) { case UTX_P8: Image->Pal.PalSize = Palettes[PalEntry].Count * 4; Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize); if (Image->Pal.Palette == NULL) //@TODO: Do all the deallocations needed here! return IL_FALSE; memcpy(Image->Pal.Palette, Palettes[PalEntry].Pal, Image->Pal.PalSize); Image->Pal.PalType = IL_PAL_RGBA32; if (iread(Image->Data, Image->SizeOfData, 1) != 1) return IL_FALSE; //@TODO: Deallocations... break; case UTX_DXT1: // // // HACK!!! // // //igetc(); //ExtraData[0] = igetc(); //if (ExtraData[0] == 0x0C) //iseek(8, IL_SEEK_CUR); // iread(ExtraData+1, 8, 1); //else //iseek(7, IL_SEEK_CUR); // iread(ExtraData+1, 7, 1); //if (igetc() == 0x80) // igetc(); Image->DxtcSize = IL_MAX(Image->Width * Image->Height / 2, 8); CompData = (ILubyte*)ialloc(Image->DxtcSize); if (CompData == NULL) //@TODO: Do all the deallocations needed here! return IL_FALSE; if (iread(CompData, Image->DxtcSize, 1) != 1) { ifree(CompData); return IL_FALSE; //@TODO: Deallocations... } // Keep a copy of the DXTC data if the user wants it. if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { Image->DxtcData = CompData; Image->DxtcFormat = IL_DXT1; CompData = NULL; } if (DecompressDXT1(Image, CompData) == IL_FALSE) { ifree(CompData); return IL_FALSE; } ifree(CompData); break; } Image->Origin = IL_ORIGIN_UPPER_LEFT; } }
ILboolean ReadCMYK(PSDHEAD *Head) { ILuint ColorMode, ResourceSize, MiscInfo, Size, i, j; ILushort Compressed; ILenum Format, Type; ILubyte *Resources = NULL, *KChannel = NULL; ColorMode = GetBigUInt(); // Skip over the 'color mode data section' iseek(ColorMode, IL_SEEK_CUR); ResourceSize = GetBigUInt(); // Read the 'image resources section' Resources = (ILubyte*)ialloc(ResourceSize); if (Resources == NULL) { return IL_FALSE; } if (iread(Resources, 1, ResourceSize) != ResourceSize) goto cleanup_error; MiscInfo = GetBigUInt(); iseek(MiscInfo, IL_SEEK_CUR); Compressed = GetBigUShort(); 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: ilSetError(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: ilSetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } if (!ilTexImage(Head->Width, Head->Height, 1, (ILubyte)Head->Channels, Format, Type, NULL)) goto cleanup_error; if (!PsdGetData(Head, iCurImage->Data, (ILboolean)Compressed)) goto cleanup_error; Size = iCurImage->Bpc * iCurImage->Width * iCurImage->Height; KChannel = (ILubyte*)ialloc(Size); if (KChannel == NULL) goto cleanup_error; if (!GetSingleChannel(Head, KChannel, (ILboolean)Compressed)) goto cleanup_error; if (Format == IL_RGB) { for (i = 0, j = 0; i < iCurImage->SizeOfData; i += 3, j++) { iCurImage->Data[i ] = (iCurImage->Data[i ] * KChannel[j]) >> 8; iCurImage->Data[i+1] = (iCurImage->Data[i+1] * KChannel[j]) >> 8; iCurImage->Data[i+2] = (iCurImage->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 < iCurImage->SizeOfData; i += 4, j++) {
ILimage *iUncompressDcx(DCXHEAD *Header) { ILubyte ByteHead, Colour, *ScanLine = NULL /* Only one plane */; ILuint c, i, x, y;//, Read = 0; ILimage *Image = NULL; if (Header->Bpp < 8) { /*ilSetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE;*/ return iUncompressDcxSmall(Header); } Image = ilNewImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 1); if (Image == NULL) return NULL; /*if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, Header->NumPlanes, 0, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; }*/ Image->Origin = IL_ORIGIN_UPPER_LEFT; ScanLine = (ILubyte*)ialloc(Header->Bps); if (ScanLine == NULL) goto dcx_error; switch (Image->Bpp) { case 1: Image->Format = IL_COLOUR_INDEX; Image->Pal.PalType = IL_PAL_RGB24; Image->Pal.PalSize = 256 * 3; // Need to find out for sure... Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize); if (Image->Pal.Palette == NULL) goto dcx_error; break; //case 2: // No 16-bit images in the dcx format! case 3: Image->Format = IL_RGB; Image->Pal.Palette = NULL; Image->Pal.PalSize = 0; Image->Pal.PalType = IL_PAL_NONE; break; case 4: Image->Format = IL_RGBA; Image->Pal.Palette = NULL; Image->Pal.PalSize = 0; Image->Pal.PalType = IL_PAL_NONE; break; default: ilSetError(IL_ILLEGAL_FILE_VALUE); goto dcx_error; } /*StartPos = itell(); Compressed = (ILubyte*)ialloc(Image->SizeOfData * 4 / 3); iread(Compressed, 1, Image->SizeOfData * 4 / 3); for (y = 0; y < Image->Height; y++) { for (c = 0; c < Image->Bpp; c++) { x = 0; while (x < Header->Bps) { ByteHead = Compressed[Read++]; if ((ByteHead & 0xC0) == 0xC0) { ByteHead &= 0x3F; Colour = Compressed[Read++]; for (i = 0; i < ByteHead; i++) { ScanLine[x++] = Colour; } } else { ScanLine[x++] = ByteHead; } } for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes ;) Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x]; } } } ifree(Compressed); iseek(StartPos + Read, IL_SEEK_SET);*/ //changed 2003-09-01 if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) iPreCache(iCurImage->SizeOfData); //TODO: because the .pcx-code was broken this //code is probably broken, too for (y = 0; y < Image->Height; y++) { for (c = 0; c < Image->Bpp; c++) { x = 0; while (x < Header->Bps) { if (iread(&ByteHead, 1, 1) != 1) { iUnCache(); goto dcx_error; } if ((ByteHead & 0xC0) == 0xC0) { ByteHead &= 0x3F; if (iread(&Colour, 1, 1) != 1) { iUnCache(); goto dcx_error; } for (i = 0; i < ByteHead; i++) { ScanLine[x++] = Colour; } } else { ScanLine[x++] = ByteHead; } } for (x = 0; x < Image->Width; x++) { // 'Cleverly' ignores the pad bytes ;) Image->Data[y * Image->Bps + x * Image->Bpp + c] = ScanLine[x]; } } } iUnCache(); ifree(ScanLine); // Read in the palette if (Image->Bpp == 1) { ByteHead = igetc(); // the value 12, because it signals there's a palette for some reason... // We should do a check to make certain it's 12... if (ByteHead != 12) iseek(-1, IL_SEEK_CUR); if (iread(Image->Pal.Palette, 1, Image->Pal.PalSize) != Image->Pal.PalSize) { ilCloseImage(Image); return NULL; } } return Image; dcx_error: ifree(ScanLine); ilCloseImage(Image); return NULL; }
// Note: .Ktx support has not been tested yet! // https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ ILboolean iLoadKtxInternal() { KTX_HEAD Header; ILuint imageSize; ILenum Format; ILubyte Bpp; ILubyte FileIdentifier[12] = { //0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A '«', 'K', 'T', 'X', ' ', '1', '1', '»', '\r', '\n', '\x1A', '\n' }; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } /*Header.Width = GetLittleShort(); Header.Height = GetLittleShort(); Header.Dummy = GetLittleInt();*/ if (iread(Header.identifier, 1, 12) != 12) return IL_FALSE; Header.endianness = GetLittleUInt(); Header.glType = GetLittleUInt(); Header.glTypeSize = GetLittleUInt(); Header.glFormat = GetLittleUInt(); Header.glInternalFormat = GetLittleUInt(); Header.glBaseInternalFormat = GetLittleUInt(); Header.pixelWidth = GetLittleUInt(); Header.pixelHeight = GetLittleUInt(); Header.pixelDepth = GetLittleUInt(); Header.numberOfArrayElements = GetLittleUInt(); Header.numberOfFaces = GetLittleUInt(); Header.numberOfMipmapLevels = GetLittleUInt(); Header.bytesOfKeyValueData = GetLittleUInt(); if (memcmp(Header.identifier, FileIdentifier, 12) || Header.endianness != 0x04030201) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } //@TODO: Additional types if (Header.glType != I_GL_UNSIGNED_BYTE || Header.glTypeSize != 1) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } //@TODO: Additional formats if (Header.glFormat <= I_GL_ALPHA || Header.glFormat >= I_GL_LUMINANCE_ALPHA || Header.glInternalFormat != Header.glFormat /*|| Header.glBaseInternalFormat != Header.glFormat*/) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } //@TODO: Mipmaps, etc. if (Header.numberOfArrayElements != 0 || Header.numberOfFaces != 1 || Header.numberOfMipmapLevels != 1) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } //@TODO: Parse this data if (iseek(Header.bytesOfKeyValueData, IL_SEEK_CUR)) return IL_FALSE; switch (Header.glFormat) { case I_GL_LUMINANCE: Bpp = 1; Format = IL_LUMINANCE; break; case IL_LUMINANCE_ALPHA: Bpp = 2; Format = IL_LUMINANCE_ALPHA; break; case I_GL_RGB: Bpp = 3; Format = IL_RGB; break; case I_GL_RGBA: Bpp = 4; Format = IL_RGBA; break; default: ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } //@TODO: More than just RGBA if (!ilTexImage(Header.pixelWidth, Header.pixelHeight, 1, Bpp, Format, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; imageSize = GetLittleUInt(); if (imageSize != Header.pixelWidth * Header.pixelHeight * Bpp) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } if (iread(iCurImage->Data, Bpp, Header.pixelWidth * Header.pixelHeight) != Header.pixelWidth * Header.pixelHeight) return IL_FALSE; return ilFixImage(); }
// Internal function used to get the DICOM header from the current file. ILboolean iGetDicomHead(DICOMHEAD *Header) { ILushort GroupNum, ElementNum; ILboolean ReachedData = IL_FALSE; ILubyte Var2, UID[65]; // Signature should be "DICM" at position 128. iseek(128, IL_SEEK_SET); if (iread(Header->Signature, 1, 4) != 4) return IL_FALSE; //@TODO: What about the case when we are reading an image with Big Endian data? do { GroupNum = GetGroupNum(Header); ElementNum = GetShort(Header, GroupNum);; switch (GroupNum) { case 0x02: switch (ElementNum) { /*case 0x01: // Version number if (!GetNumericValue(&Header->Version)) return IL_FALSE; if (Header->Version != 0x0100) return IL_FALSE; break;*/ case 0x10: //@TODO: Look at pg. 60 of 07_05pu.pdf (PS 3.5) for more UIDs. if (!GetUID(UID)) return IL_FALSE; if (!strncmp((const char*)UID, "1.2.840.10008.1.2.2", 64)) // Explicit big endian Header->BigEndian = IL_TRUE; else if (!strncmp((const char*)UID, "1.2.840.10008.1.2.1", 64)) // Explicit little endian Header->BigEndian = IL_FALSE; else if (!strncmp((const char*)UID, "1.2.840.10008.1.2", 64)) // Implicit little endian Header->BigEndian = IL_FALSE; else return IL_FALSE; // Unrecognized UID. break; default: if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. return IL_FALSE; } break; case 0x28: switch (ElementNum) { case 0x02: // Samples per pixel if (!GetNumericValue(Header, GroupNum, &Header->Samples)) return IL_FALSE; break; case 0x08: // Number of frames, or depth if (!GetNumericValue(Header, GroupNum, &Header->Depth)) return IL_FALSE; break; case 0x10: // The number of rows if (!GetNumericValue(Header, GroupNum, &Header->Height)) return IL_FALSE; break; case 0x11: // The number of columns if (!GetNumericValue(Header, GroupNum, &Header->Width)) return IL_FALSE; break; case 0x100: // Bits allocated per sample if (!GetNumericValue(Header, GroupNum, &Header->BitsAllocated)) return IL_FALSE; break; case 0x101: // Bits stored per sample - Do we really need this information? if (!GetNumericValue(Header, GroupNum, &Header->BitsStored)) return IL_FALSE; break; default: if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. return IL_FALSE; } break; case 0x7FE0: switch (ElementNum) { case 0x10: // This element is the actual pixel data. We are done with the header here. if (igetc() != 'O') // @TODO: Can we assume that this is always 'O'? return IL_FALSE; Var2 = igetc(); if (Var2 != 'B' && Var2 != 'W' && Var2 != 'F') // 'OB', 'OW' and 'OF' accepted for this element. return IL_FALSE; GetLittleUShort(); // Skip the 2 reserved bytes. Header->DataLen = GetInt(Header, GroupNum);//GetLittleUInt(); ReachedData = IL_TRUE; break; default: if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. return IL_FALSE; } break; default: if (!SkipElement(Header, GroupNum, ElementNum)) // We do not understand this entry, so we just skip it. return IL_FALSE; } } while (!ieof() && !ReachedData); if (ieof()) return IL_FALSE; // Some DICOM images do not have the depth (number of frames) field. if (Header->Depth == 0) Header->Depth = 1; switch (Header->BitsAllocated) { case 8: Header->Type = IL_UNSIGNED_BYTE; break; case 16: Header->Type = IL_UNSIGNED_SHORT; break; case 32: Header->Type = IL_FLOAT; //@TODO: Is this ever an integer? break; default: //@TODO: Any other types we can deal with? return IL_FALSE; } // Cannot handle more than 4 channels in an image. if (Header->Samples > 4) return IL_FALSE; Header->Format = ilGetFormatBpp(Header->Samples); return IL_TRUE; }
//! Loads a .col palette file ILboolean ilLoadColPal(ILconst_string FileName) { ILuint RealFileSize, FileSize; ILushort Version; ILHANDLE ColFile; if (!iCheckExtension(FileName, IL_TEXT("col"))) { ilSetError(IL_INVALID_EXTENSION); return IL_FALSE; } if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } ColFile = iopenr(FileName); if (ColFile == NULL) { ilSetError(IL_COULD_NOT_OPEN_FILE); return IL_FALSE; } if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { ifree(iCurImage->Pal.Palette); iCurImage->Pal.Palette = NULL; } iseek(0, IL_SEEK_END); RealFileSize = ftell((FILE*)ColFile); iseek(0, IL_SEEK_SET); if (RealFileSize > 768) { // has a header fread(&FileSize, 4, 1, (FILE*)ColFile); if ((FileSize - 8) % 3 != 0) { // check to make sure an even multiple of 3! icloser(ColFile); ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } if (iread(&Version, 2, 1) != 1) { icloser(ColFile); return IL_FALSE; } if (Version != 0xB123) { icloser(ColFile); ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } if (iread(&Version, 2, 1) != 1) { icloser(ColFile); return IL_FALSE; } if (Version != 0) { icloser(ColFile); ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } } iCurImage->Pal.Palette = (ILubyte*)ialloc(768); if (iCurImage->Pal.Palette == NULL) { icloser(ColFile); return IL_FALSE; } if (iread(iCurImage->Pal.Palette, 1, 768) != 768) { icloser(ColFile); ifree(iCurImage->Pal.Palette); iCurImage->Pal.Palette = NULL; return IL_FALSE; } iCurImage->Pal.PalSize = 768; iCurImage->Pal.PalType = IL_PAL_RGB24; icloser(ColFile); return IL_TRUE; }
ILboolean iLoadMdlInternal() { ILuint Id, Version, NumTex, TexOff, TexDataOff, Position, ImageNum; ILubyte *TempPal; TEX_HEAD TexHead; ILimage *BaseImage=NULL; ILboolean BaseCreated = IL_FALSE; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } Id = GetLittleUInt(); Version = GetLittleUInt(); // 0x54534449 == "IDST" if (Id != 0x54534449 || Version != 10) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Skips the actual model header. iseek(172, IL_SEEK_CUR); NumTex = GetLittleUInt(); TexOff = GetLittleUInt(); TexDataOff = GetLittleUInt(); if (NumTex == 0 || TexOff == 0 || TexDataOff == 0) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } iseek(TexOff, IL_SEEK_SET); for (ImageNum = 0; ImageNum < NumTex; ImageNum++) { if (iread(TexHead.Name, 1, 64) != 64) return IL_FALSE; TexHead.Flags = GetLittleUInt(); TexHead.Width = GetLittleUInt(); TexHead.Height = GetLittleUInt(); TexHead.Offset = GetLittleUInt(); Position = itell(); if (TexHead.Offset == 0) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } if (!BaseCreated) { ilTexImage(TexHead.Width, TexHead.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL); iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; BaseCreated = IL_TRUE; BaseImage = iCurImage; //iCurImage->NumNext = NumTex - 1; // Don't count the first image. } else { //iCurImage->Next = ilNewImage(TexHead.Width, TexHead.Height, 1, 1, 1); iCurImage = iCurImage->Next; iCurImage->Format = IL_COLOUR_INDEX; iCurImage->Type = IL_UNSIGNED_BYTE; } TempPal = (ILubyte*)ialloc(768); if (TempPal == NULL) { iCurImage = BaseImage; return IL_FALSE; } iCurImage->Pal.Palette = TempPal; iCurImage->Pal.PalSize = 768; iCurImage->Pal.PalType = IL_PAL_RGB24; iseek(TexHead.Offset, IL_SEEK_SET); if (iread(iCurImage->Data, TexHead.Width * TexHead.Height, 1) != 1) return IL_FALSE; if (iread(iCurImage->Pal.Palette, 1, 768) != 768) return IL_FALSE; if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); } iseek(Position, IL_SEEK_SET); } iCurImage = BaseImage; return ilFixImage(); }