ILuint iSunGetRle(ILubyte *Data, ILuint Length) { ILuint i = 0, j; ILubyte Flag, Value; ILuint Count; for (i = 0; i < Length; ) { Flag = igetc(); if (Flag == 0x80) { // Run follows (or 1 byte of 0x80) Count = igetc(); if (Count == 0) { // 1 pixel of value (0x80) *Data = 0x80; Data++; i++; } else { // Here we have a run. Value = igetc(); Count++; // Should really be Count+1 for (j = 0; j < Count && i + j < Length; j++, Data++) { *Data = Value; } i += Count; } } else { // 1 byte of this value (cannot be 0x80) *Data = Flag; Data++; i++; } } return i; }
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 SkipElement(DICOMHEAD *Header, ILushort GroupNum, ILushort ElementNum) { ILubyte VR1, VR2; ILuint ValLen; // 2 byte character string telling what type this element is ('OB', 'UI', etc.) VR1 = igetc(); VR2 = igetc(); if ((VR1 == 'O' && VR2 == 'B') || (VR1 == 'O' && VR2 == 'W') || (VR1 == 'O' && VR2 == 'F') || (VR1 == 'S' && VR2 == 'Q') || (VR1 == 'U' && VR2 == 'T') || (VR1 == 'U' && VR2 == 'N')) { // These all have a different format than the other formats, since they can be up to 32 bits long. GetLittleUShort(); // Values reserved, we do not care about them. ValLen = GetInt(Header, GroupNum);//GetLittleUInt(); // Length of the rest of the element if (ValLen % 2) // This length must be even, according to the specs. return IL_FALSE; if (ElementNum != 0x00) // Element numbers of 0 tell the size of the full group, so we do not skip this. // @TODO: We could use this to skip groups that we do not care about. if (iseek(ValLen, IL_SEEK_CUR)) return IL_FALSE; } else { // These have a length of 16 bits. ValLen = GetShort(Header, GroupNum);//GetLittleUShort(); //if (ValLen % 2) // This length must be even, according to the specs. // ValLen++; // Add the extra byte to seek. //if (ElementNum != 0x00) // Element numbers of 0 tell the size of the full group, so we do not skip this. // @TODO: We could use this to skip groups that we do not care about. if (iseek(ValLen, IL_SEEK_CUR)) return IL_FALSE; } return IL_TRUE; }
// Note: .Cut support has not been tested yet! // A .cut can only have 1 bpp. // We need to add support for the .pal's PSP outputs with these... ILboolean iLoadCutInternal() { CUT_HEAD Header; ILuint Size, i = 0, j; ILubyte Count, Run; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } Header.Width = GetLittleShort(); Header.Height = GetLittleShort(); Header.Dummy = GetLittleInt(); if (Header.Width == 0 || Header.Height == 0) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) { // always 1 bpp return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; Size = Header.Width * Header.Height; while (i < Size) { Count = igetc(); if (Count == 0) { // end of row igetc(); // Not supposed to be here, but igetc(); // PSP is putting these two bytes here...WHY?! continue; } if (Count & BIT_7) { // rle-compressed ClearBits(Count, BIT_7); Run = igetc(); for (j = 0; j < Count; j++) { iCurImage->Data[i++] = Run; } } else { // run of pixels for (j = 0; j < Count; j++) { iCurImage->Data[i++] = igetc(); } } } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; // Not sure /*iCurImage->Pal.Palette = SharedPal.Palette; iCurImage->Pal.PalSize = SharedPal.PalSize; iCurImage->Pal.PalType = SharedPal.PalType;*/ return ilFixImage(); }
// Internal function used to load the Gif. ILboolean iLoadGifInternal() { GIFHEAD Header; ILpal GlobalPal; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } GlobalPal.Palette = NULL; GlobalPal.PalSize = 0; //read header iread(&Header.Sig, 1, 6); Header.Width = GetLittleUShort(); Header.Height = GetLittleUShort(); Header.ColourInfo = igetc(); Header.Background = igetc(); Header.Aspect = igetc(); if (!strnicmp(Header.Sig, "GIF87A", 6)) { GifType = GIF87A; } else if (!strnicmp(Header.Sig, "GIF89A", 6)) { GifType = GIF89A; } else { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; // Check for a global colour map. if (Header.ColourInfo & (1 << 7)) { if (!iGetPalette(Header.ColourInfo, &GlobalPal)) { return IL_FALSE; } } if (!GetImages(&GlobalPal, &Header)) return IL_FALSE; if (GlobalPal.Palette && GlobalPal.PalSize) ifree(GlobalPal.Palette); GlobalPal.Palette = NULL; GlobalPal.PalSize = 0; ilFixImage(); return IL_TRUE; }
ILvoid iGetJpgHead(ILubyte *Header) { Header[0] = igetc(); Header[1] = igetc(); return; }
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; }
// Internal function used to load the Pxr. ILboolean iLoadPxrInternal() { ILushort Width, Height; ILubyte Bpp; Width = sizeof(PIXHEAD); iseek(416, IL_SEEK_SET); Height = GetLittleUShort(); Width = GetLittleUShort(); iseek(424, IL_SEEK_SET); Bpp = igetc(); switch (Bpp) { case 0x08: ilTexImage(Width, Height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, NULL); break; case 0x0E: ilTexImage(Width, Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL); break; case 0x0F: ilTexImage(Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); break; default: ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } iseek(1024, IL_SEEK_SET); iread(iCurImage->Data, 1, iCurImage->SizeOfData); iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; 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; }
ILimage *iUncompressDcxSmall(DCXHEAD *Header) { ILuint i = 0, j, k, c, d, x, y, Bps; ILubyte HeadByte, Colour, Data = 0, *ScanLine = NULL; ILimage *Image; 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, 1, 0, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; }*/ Image->Origin = IL_ORIGIN_UPPER_LEFT; switch (Header->NumPlanes) { case 1: Image->Format = IL_LUMINANCE; break; case 4: Image->Format = IL_COLOUR_INDEX; break; default: ilSetError(IL_ILLEGAL_FILE_VALUE); ilCloseImage(Image); return NULL; } if (Header->NumPlanes == 1) { for (j = 0; j < Image->Height; j++) { i = 0; while (i < Image->Width) { if (iread(&HeadByte, 1, 1) != 1) goto file_read_error; if (HeadByte >= 192) { HeadByte -= 192; if (iread(&Data, 1, 1) != 1) goto file_read_error; for (c = 0; c < HeadByte; c++) { k = 128; for (d = 0; d < 8 && i < Image->Width; d++) { Image->Data[j * Image->Width + i++] = (!!(Data & k) == 1 ? 255 : 0); k >>= 1; } } } else { k = 128; for (c = 0; c < 8 && i < Image->Width; c++) { Image->Data[j * Image->Width + i++] = (!!(HeadByte & k) == 1 ? 255 : 0); k >>= 1; } } } if (Data != 0) igetc(); // Skip pad byte if last byte not a 0 }
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; }
// Internal function used to get the .sgi header from the current file. ILboolean iGetSgiHead(iSgiHeader *Header) { Header->MagicNum = GetBigUShort(); Header->Storage = (ILbyte)igetc(); Header->Bpc = (ILbyte)igetc(); Header->Dim = GetBigUShort(); Header->XSize = GetBigUShort(); Header->YSize = GetBigUShort(); Header->ZSize = GetBigUShort(); Header->PixMin = GetBigInt(); Header->PixMax = GetBigInt(); Header->Dummy1 = GetBigInt(); iread(Header->Name, 1, 80); Header->ColMap = GetBigInt(); iread(Header->Dummy, 1, 404); return IL_TRUE; }
ILboolean GetUID(ILubyte *UID) { ILubyte VR1, VR2; ILushort ValLen; // 2 byte character string telling what type this element is ('OB', 'UI', etc.) VR1 = igetc(); VR2 = igetc(); if (VR1 != 'U' || VR2 != 'I') // 'UI' == UID return IL_FALSE; ValLen = GetLittleUShort(); if (iread(UID, ValLen, 1) != 1) return IL_FALSE; UID[64] = 0; // Just to make sure that our string is terminated. return IL_TRUE; }
// Internal function used to get the BLP header from the current file. ILboolean iGetBlp2Head(BLP2HEAD *Header) { ILuint i; iread(Header->Sig, 1, 4); Header->Type = GetLittleUInt(); Header->Compression = igetc(); Header->AlphaBits = igetc(); Header->AlphaType = igetc(); Header->HasMips = igetc(); Header->Width = GetLittleUInt(); Header->Height = GetLittleUInt(); for (i = 0; i < 16; i++) Header->MipOffsets[i] = GetLittleUInt(); for (i = 0; i < 16; i++) Header->MipLengths[i] = GetLittleUInt(); 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 GetNumericValue(DICOMHEAD *Header, ILushort GroupNum, ILuint *Number) { ILubyte VR1, VR2; ILushort ValLen; // 2 byte character string telling what type this element is ('OB', 'UI', etc.) VR1 = igetc(); VR2 = igetc(); if (VR1 == 'U' && VR2 == 'S') { // Unsigned short ValLen = GetShort(Header, GroupNum);//GetLittleUShort(); if (ValLen != 2) // Must always be 2 for short ('US') return IL_FALSE; *((ILushort*)Number) = GetShort(Header, GroupNum);//GetLittleUShort(); return IL_TRUE; } if (VR1 == 'U' && VR2 == 'L') { // Unsigned long ValLen = GetInt(Header, GroupNum);//GetLittleUInt(); if (ValLen != 4) // Must always be 4 for long ('UL') return IL_FALSE; *Number = GetInt(Header, GroupNum); return IL_TRUE; } if (VR1 == 'S' && VR2 == 'S') { // Signed short ValLen = GetShort(Header, GroupNum); if (ValLen != 2) // Must always be 2 for short ('US') return IL_FALSE; *((ILshort*)Number) = GetShort(Header, GroupNum); return IL_TRUE; } if (VR1 == 'S' && VR2 == 'L') { // Signed long ValLen = GetInt(Header, GroupNum); if (ValLen != 4) // Must always be 4 for long ('UL') return IL_FALSE; *((ILint*)Number) = GetInt(Header, GroupNum); return IL_TRUE; } return IL_FALSE; }
// 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 }
// Last time I tried, MSVC++'s fgets() was really really screwy ILbyte *iFgets(char *buffer, ILuint maxlen) { ILuint counter = 0; ILint temp = '\0'; while ((temp = igetc()) && temp != '\n' && temp != IL_EOF && counter < maxlen) { buffer[counter] = temp; counter++; } buffer[counter] = '\0'; if (temp == IL_EOF && counter == 0) // Only return NULL if no data was "got". return NULL; return buffer; }
// This following code is from http://wiki.beyondunreal.com/Legacy:Package_File_Format/Data_Details. /// <summary>Reads a compact integer from the FileReader. /// Bytes read differs, so do not make assumptions about /// physical data being read from the stream. (If you have /// to, get the difference of FileReader.BaseStream.Position /// before and after this is executed.)</summary> /// <returns>An "uncompacted" signed integer.</returns> /// <remarks>FileReader is a System.IO.BinaryReader mapped /// to a file. Also, there may be better ways to implement /// this, but this is fast, and it works.</remarks> ILint UtxReadCompactInteger() { int output = 0; ILboolean sign = IL_FALSE; int i; ILubyte x; for(i = 0; i < 5; i++) { x = igetc(); // First byte if(i == 0) { // Bit: X0000000 if((x & 0x80) > 0) sign = IL_TRUE; // Bits: 00XXXXXX output |= (x & 0x3F); // Bit: 0X000000 if((x & 0x40) == 0) break; } // Last byte else if(i == 4) { // Bits: 000XXXXX -- the 0 bits are ignored // (hits the 32 bit boundary) output |= (x & 0x1F) << (6 + (3 * 7)); } // Middle bytes else { // Bits: 0XXXXXXX output |= (x & 0x7F) << (6 + ((i - 1) * 7)); // Bit: X0000000 if((x & 0x80) == 0) break; } } // multiply by negative one here, since the first 6+ bits could be 0 if (sign) output *= -1; return output; }
// Internal function to load a raw image ILboolean iLoadRawInternal() { if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } iCurImage->Width = GetLittleUInt(); iCurImage->Height = GetLittleUInt(); iCurImage->Depth = GetLittleUInt(); iCurImage->Bpp = igetc(); if (iread(&iCurImage->Bpc, 1, 1) != 1) return IL_FALSE; if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, iCurImage->Bpp, 0, ilGetTypeBpc(iCurImage->Bpc), NULL)) { return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; // Tries to read the correct amount of data if (iread(iCurImage->Data, 1, iCurImage->SizeOfData) < iCurImage->SizeOfData) return IL_FALSE; if (ilIsEnabled(IL_ORIGIN_SET)) { iCurImage->Origin = ilGetInteger(IL_ORIGIN_MODE); } else { iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; } if (iCurImage->Bpp == 1) iCurImage->Format = IL_LUMINANCE; else if (iCurImage->Bpp == 3) iCurImage->Format = IL_RGB; else // 4 iCurImage->Format = IL_RGBA; ilFixImage(); return IL_TRUE; }
ILimage *ilReadBitPbm(PPMINFO *Info) { ILuint m, j, x, CurrByte; if (!ilTexImage(Info->Width, Info->Height, 1, (ILubyte)(Info->Bpp), 0, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; x = 0; for (j = 0; j < iCurImage->SizeOfData;) { CurrByte = igetc(); for (m = 128; m > 0 && x < Info->Width; m >>= 1, ++x, ++j) { iCurImage->Data[j] = (CurrByte & m)?255:0; } if (x == Info->Width) x = 0; } return iCurImage; }
// Internal function used to load the Pix. ILboolean iLoadPixInternal() { PIXHEAD Header; ILuint i, j; ILubyte ByteHead, Colour[3]; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (!iGetPixHead(&Header)) return IL_FALSE; if (!iCheckPix(&Header)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_BGR, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; for (i = 0; i < iCurImage->SizeOfData; ) { ByteHead = igetc(); if (iread(Colour, 1, 3) != 3) return IL_FALSE; for (j = 0; j < ByteHead; j++) { iCurImage->Data[i++] = Colour[0]; iCurImage->Data[i++] = Colour[1]; iCurImage->Data[i++] = Colour[2]; } } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; ilFixImage(); return IL_TRUE; }
// Internal function obtain the .pcx header from the current file. ILboolean iGetPcxHead(PCXHEAD *Head) { Head->Manufacturer = igetc(); Head->Version = igetc(); Head->Encoding = igetc(); Head->Bpp = igetc(); Head->Xmin = GetLittleUShort(); Head->Ymin = GetLittleUShort(); Head->Xmax = GetLittleUShort(); Head->Ymax = GetLittleUShort(); Head->HDpi = GetLittleUShort(); Head->VDpi = GetLittleUShort(); iread(Head->ColMap, 1, 48); Head->Reserved = igetc(); Head->NumPlanes = igetc(); Head->Bps = GetLittleUShort(); Head->PaletteInfo = GetLittleUShort(); Head->HScreenSize = GetLittleUShort(); Head->VScreenSize = GetLittleUShort(); iread(Head->Filler, 1, 54); return IL_TRUE; }
ILboolean iUncompressSmall(PCXHEAD *Header) { ILuint i = 0, j, k, c, d, x, y, Bps; ILubyte HeadByte, Colour, Data = 0, *ScanLine; if (!ilTexImage(Header->Xmax - Header->Xmin + 1, Header->Ymax - Header->Ymin + 1, 1, 1, 0, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; switch (Header->NumPlanes) { case 1: iCurImage->Format = IL_LUMINANCE; break; case 4: iCurImage->Format = IL_COLOUR_INDEX; break; default: ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } if (Header->NumPlanes == 1 && Header->Bpp == 1) { for (j = 0; j < iCurImage->Height; j++) { i = 0; //number of written pixels while (i < iCurImage->Width) { if (iread(&HeadByte, 1, 1) != 1) return IL_FALSE; if (HeadByte >= 192) { HeadByte -= 192; if (iread(&Data, 1, 1) != 1) return IL_FALSE; for (c = 0; c < HeadByte; c++) { k = 128; for (d = 0; d < 8 && i < iCurImage->Width; d++) { iCurImage->Data[j * iCurImage->Width + i++] = ((Data & k) != 0 ? 255 : 0); k >>= 1; } } } else { k = 128; for (c = 0; c < 8 && i < iCurImage->Width; c++) { iCurImage->Data[j * iCurImage->Width + i++] = ((HeadByte & k) != 0 ? 255 : 0); k >>= 1; } } } //if(Data != 0) //changed 2003-09-01: //There has to be an even number of bytes per line in a pcx. //One byte can hold up to 8 bits, so Width/8 bytes //are needed to hold a 1 bit per pixel image line. //If Width/8 is even no padding is needed, //one pad byte has to be read otherwise. //(let's hope the above is true ;-)) if(!((iCurImage->Width >> 3) & 0x1)) igetc(); // Skip pad byte }
ILboolean GifGetData(ILubyte *Data, ILuint ImageSize, ILuint Width, ILuint Height, ILuint Stride, GFXCONTROL *Gfx) { ILubyte *sp; ILint code, fc, oc; ILubyte DisposalMethod = 0; ILint c, size; ILuint i = 0, Read = 0; if (!Gfx->Used) DisposalMethod = (Gfx->Packed & 0x1C) >> 2; if((size = igetc()) == IL_EOF) return IL_FALSE; if (size < 2 || 9 < size) { return IL_FALSE; } stack = (ILubyte*)ialloc(MAX_CODES + 1); suffix = (ILubyte*)ialloc(MAX_CODES + 1); prefix = (ILshort*)ialloc(sizeof(*prefix) * (MAX_CODES + 1)); if (!stack || !suffix || !prefix) { ifree(stack); ifree(suffix); ifree(prefix); return IL_FALSE; } curr_size = size + 1; top_slot = 1 << curr_size; clear = 1 << size; ending = clear + 1; slot = newcodes = ending + 1; navail_bytes = nbits_left = 0; oc = fc = 0; sp = stack; success = IL_TRUE; while ((c = get_next_code()) != ending && Read < Height) { if (c == clear) { curr_size = size + 1; slot = newcodes; top_slot = 1 << curr_size; while ((c = get_next_code()) == clear); if (c == ending) break; if (c >= slot) c = 0; oc = fc = c; if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == c && (Gfx->Packed & 0x1) != 0) i++; else Data[i++] = c; if (i == Width) { Data += Stride; i = 0; Read += 1; } } else { code = c; if (code >= slot) { code = oc; *sp++ = fc; } while (code >= newcodes) { *sp++ = suffix[code]; code = prefix[code]; } *sp++ = (ILbyte)code; if (slot < top_slot) { fc = code; suffix[slot] = fc; prefix[slot++] = oc; oc = c; } if (slot >= top_slot && curr_size < 12) { top_slot <<= 1; curr_size++; } while (sp > stack) { sp--; if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == *sp && (Gfx->Packed & 0x1) != 0) i++; else Data[i++] = *sp; if (i == Width) { Data += Stride; i = 0; Read += 1; } } } } ifree(stack); ifree(suffix); ifree(prefix); return success; }
ILint get_next_code(void) { ILint i, t; ILuint ret; //20050102: Tests for IL_EOF were added because this function //crashed sometimes if igetc() returned IL_EOF //(for example "table-add-column-before-active.gif" included in the //mozilla source package) if (!nbits_left) { if (navail_bytes <= 0) { pbytes = byte_buff; navail_bytes = igetc(); if(navail_bytes == IL_EOF) { success = IL_FALSE; return ending; } if (navail_bytes) { for (i = 0; i < navail_bytes; i++) { if((t = igetc()) == IL_EOF) { success = IL_FALSE; return ending; } byte_buff[i] = t; } } } b1 = *pbytes++; nbits_left = 8; navail_bytes--; } ret = b1 >> (8 - nbits_left); while (curr_size > nbits_left) { if (navail_bytes <= 0) { pbytes = byte_buff; navail_bytes = igetc(); if(navail_bytes == IL_EOF) { success = IL_FALSE; return ending; } if (navail_bytes) { for (i = 0; i < navail_bytes; i++) { if((t = igetc()) == IL_EOF) { success = IL_FALSE; return ending; } byte_buff[i] = t; } } } b1 = *pbytes++; ret |= b1 << nbits_left; nbits_left += 8; navail_bytes--; } nbits_left -= curr_size; return (ret & code_mask[curr_size]); }
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 GifGetData(ILimage *Image, ILubyte *Data, ILuint ImageSize, ILuint Width, ILuint Height, ILuint Stride, ILuint PalOffset, GFXCONTROL *Gfx) { ILubyte *sp; ILint code, fc, oc; ILubyte DisposalMethod = 0; ILint c, size; ILuint i = 0, Read = 0, j = 0; ILubyte *DataPtr = Data; if (!Gfx->Used) DisposalMethod = (Gfx->Packed & 0x1C) >> 2; if((size = igetc()) == IL_EOF) return IL_FALSE; if (size < 2 || 9 < size) { return IL_FALSE; } stack = (ILubyte*)ialloc(MAX_CODES + 1); suffix = (ILubyte*)ialloc(MAX_CODES + 1); prefix = (ILshort*)ialloc(sizeof(*prefix) * (MAX_CODES + 1)); if (!stack || !suffix || !prefix) { cleanUpGifLoadState(); return IL_FALSE; } curr_size = size + 1; top_slot = 1 << curr_size; clear = 1 << size; ending = clear + 1; slot = newcodes = ending + 1; navail_bytes = nbits_left = 0; oc = fc = 0; sp = stack; while ((c = get_next_code()) != ending && Read < Height) { if (c == clear) { curr_size = size + 1; slot = newcodes; top_slot = 1 << curr_size; while ((c = get_next_code()) == clear); if (c == ending) break; if (c >= slot) c = 0; oc = fc = c; if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == c && (Gfx->Packed & 0x1) != 0) i++; else if (i < Width) DataPtr[i++] = c + PalOffset; if (i == Width) { DataPtr += Stride; i = 0; Read += 1; ++j; if (j >= Height) { cleanUpGifLoadState(); return IL_FALSE; } } } else { code = c; //BG-2007-01-10: several fixes for incomplete GIFs if (code >= slot) { code = oc; if (sp >= stack + MAX_CODES) { cleanUpGifLoadState(); return IL_FALSE; } *sp++ = fc; } if (code >= MAX_CODES) return IL_FALSE; while (code >= newcodes) { if (sp >= stack + MAX_CODES) { cleanUpGifLoadState(); return IL_FALSE; } *sp++ = suffix[code]; code = prefix[code]; } if (sp >= stack + MAX_CODES) { cleanUpGifLoadState(); return IL_FALSE; } *sp++ = (ILbyte)code; if (slot < top_slot) { fc = code; suffix[slot] = fc; prefix[slot++] = oc; oc = c; } if (slot >= top_slot && curr_size < 12) { top_slot <<= 1; curr_size++; } while (sp > stack) { sp--; if (DisposalMethod == 1 && !Gfx->Used && Gfx->Transparent == *sp && (Gfx->Packed & 0x1) != 0) i++; else if (i < Width) DataPtr[i++] = *sp + PalOffset; if (i == Width) { i = 0; Read += 1; j = (j+1) % Height; // Needs to start from Data, not Image->Data. DataPtr = Data + j * Stride; } } } } cleanUpGifLoadState(); return IL_TRUE; }
// 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 .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(); }