ILboolean SkipExtensions(GFXCONTROL *Gfx) { ILint Code; ILint Label; ILint Size; // DW (06-03-2002): Apparently there can be... //if (GifType == GIF87A) // return IL_TRUE; // No extensions in the GIF87a format. do { if((Code = igetc()) == IL_EOF) return IL_FALSE; if (Code != 0x21) { iseek(-1, IL_SEEK_CUR); return IL_TRUE; } if((Label = igetc()) == IL_EOF) return IL_FALSE; switch (Label) { case 0xF9: Gfx->Size = igetc(); Gfx->Packed = igetc(); Gfx->Delay = GetLittleUShort(); Gfx->Transparent = igetc(); Gfx->Terminator = igetc(); if (ieof()) return IL_FALSE; Gfx->Used = IL_FALSE; break; /*case 0xFE: break; case 0x01: break;*/ default: do { if((Size = igetc()) == IL_EOF) return IL_FALSE; iseek(Size, IL_SEEK_CUR); } while (!ieof() && Size != 0); } // @TODO: Handle this better. if (ieof()) { ilSetError(IL_FILE_READ_ERROR); return IL_FALSE; } } while (1); return IL_TRUE; }
ILboolean channelReadMixed(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes) { ILint count; int i, j, k; ILubyte col[4]; for(i = 0; i < width; i += count) { if (ieof()) return IL_FALSE; count = igetc(); if (count == IL_EOF) return IL_FALSE; if (count >= 128) { // Repeated sequence if (count == 128) { // Long run count = GetLittleUShort(); if (ieof()) return IL_FALSE; } else count -= 127; // We've run past... if ((i + count) > width) { //fprintf(stderr, "ERROR: FF_PIC_load(): Overrun scanline (Repeat) [%d + %d > %d] (NC=%d)\n", i, count, width, noCol); return IL_FALSE; } for (j = 0; j < noCol; j++) if (iread(&col[j], 1, 1) != 1) return IL_FALSE; for (k = 0; k < count; k++, scan += bytes) { for (j = 0; j < noCol; j++) scan[off[j]] = col[j]; } } else { // Raw sequence count++; if ((i + count) > width) { //fprintf(stderr, "ERROR: FF_PIC_load(): Overrun scanline (Raw) [%d + %d > %d] (NC=%d)\n", i, count, width, noCol); return IL_FALSE; } for (k = count; k > 0; k--, scan += bytes) { for (j = 0; j < noCol; j++) if (iread(&scan[off[j]], 1, 1) != 1) return IL_FALSE; } } } return IL_TRUE; }
ILboolean channelReadPure(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes) { ILubyte col[4]; ILint count; int i, j, k; for (i = width; i > 0; ) { count = igetc(); if (count == IL_EOF) return IL_FALSE; if (count > width) count = width; i -= count; if (ieof()) return IL_FALSE; for (j = 0; j < noCol; j++) if (iread(&col[j], 1, 1) != 1) return IL_FALSE; for (k = 0; k < count; k++, scan += bytes) { for(j = 0; j < noCol; j++) scan[off[j] + k] = col[j]; } } return IL_TRUE; }
ILint XpmGetsInternal(ILubyte *Buffer, ILint MaxLen) { ILint i = 0, Current; if (ieof()) return IL_EOF; while ((Current = igetc()) != IL_EOF && i < MaxLen - 1) { if (Current == IL_EOF) return 0; if (Current == '\n') //unix line ending break; if (Current == '\r') { //dos/mac line ending Current = igetc(); if (Current == '\n') //dos line ending break; if (Current == IL_EOF) break; Buffer[i++] = Current; continue; } Buffer[i++] = Current; } Buffer[i++] = 0; return i; }
ILboolean iGetWord(ILvoid) { ILint WordPos = 0; ILint Current = 0; ILboolean Started = IL_FALSE; ILboolean Looping = IL_TRUE; if (ieof()) return IL_FALSE; while (Looping) { while ((Current = igetc()) != IL_EOF && Current != '\n' && Current != '#' && Current != ' ') { if (Current == IL_EOF) return IL_FALSE; if (!isalnum(Current)) { if (Started) { Looping = IL_FALSE; break; } continue; } if (Looping) SmallBuff[WordPos++] = Current; } SmallBuff[WordPos] = NUL; if (!Looping) break; if (Current == '#') { // '#' is a comment...read until end of line while ((Current = igetc()) != IL_EOF && Current != '\n'); } // Get rid of any erroneous spaces while ((Current = igetc()) != IL_EOF) { if (Current != ' ') break; } iseek(-1, IL_SEEK_CUR); if (WordPos > 0) break; } if (Current == -1 || WordPos == 0) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } return IL_TRUE; }
ILboolean channelReadRaw(ILubyte *scan, ILint width, ILint noCol, ILint *off, ILint bytes) { ILint i, j; for (i = 0; i < width; i++) { if (ieof()) return IL_FALSE; for (j = 0; j < noCol; j++) if (iread(&scan[off[j]], 1, 1) != 1) return IL_FALSE; scan += bytes; } return IL_TRUE; }
// Gets a name variable from the file. Keep in mind that the return value must be freed. char *GetUtxName(UTXHEADER *Header) { #define NAME_MAX_LEN 256 //@TODO: Figure out if these can possibly be longer. char *Name, OldName[NAME_MAX_LEN]; ILubyte Length = 0; // New style (Unreal Tournament) name. This has a byte at the beginning telling // how long the string is (plus terminating 0), followed by the terminating 0. if (Header->Version >= 64) { Length = igetc(); Name = (char*)ialloc(Length); if (Name == NULL) return NULL; if (iread(Name, Length, 1) != 1) { ifree(Name); return NULL; } return Name; } // Old style (Unreal) name. This string length is unknown, but it is terminated // by a 0. do { OldName[Length++] = igetc(); } while (!ieof() && OldName[Length-1] != 0 && Length < NAME_MAX_LEN); // Never reached the terminating 0. if (Length == NAME_MAX_LEN && OldName[Length-1] != 0) return NULL; // Just copy the string and return it. Name = (char*)ialloc(Length); if (Name == NULL) return NULL; memcpy(Name, OldName, Length); return Name; #undef NAME_MAX_LEN }
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; }
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; }
// Internal function used to load the .pic ILboolean iLoadPicInternal() { ILuint Alpha = IL_FALSE; ILubyte Chained; CHANNEL *Channel = NULL, *Channels = NULL, *Prev; PIC_HEAD Header; ILboolean Read; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (!iGetPicHead(&Header)) return IL_FALSE; if (!iCheckPic(&Header)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Read channels do { if (Channel == NULL) { Channel = Channels = (CHANNEL*)ialloc(sizeof(CHANNEL)); if (Channels == NULL) return IL_FALSE; } else { Channels->Next = (CHANNEL*)ialloc(sizeof(CHANNEL)); if (Channels->Next == NULL) { // Clean up the list before erroring out. while (Channel) { Prev = Channel; Channel = (CHANNEL*)Channel->Next; ifree(Prev); } return IL_FALSE; } Channels = (CHANNEL*)Channels->Next; } Channels->Next = NULL; Chained = igetc(); Channels->Size = igetc(); Channels->Type = igetc(); Channels->Chan = igetc(); if (ieof()) { Read = IL_FALSE; goto finish; } // See if we have an alpha channel in there if (Channels->Chan & PIC_ALPHA_CHANNEL) Alpha = IL_TRUE; } while (Chained); if (Alpha) { // Has an alpha channel if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { Read = IL_FALSE; goto finish; // Have to destroy Channels first. } } else { // No alpha channel if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) { Read = IL_FALSE; goto finish; // Have to destroy Channels first. } } iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; Read = readScanlines((ILuint*)iCurImage->Data, Header.Width, Header.Height, Channel, Alpha); finish: // Destroy channels while (Channel) { Prev = Channel; Channel = (CHANNEL*)Channel->Next; ifree(Prev); } if (Read == IL_FALSE) 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; }
// 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; }
Bool iEOSWS_File(struct WMPStream* pWS) { //return feof(pWS->state.file.pFile); return ieof(); }
// 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(); }
// 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; } }