// Much easier to read - just assemble from planes, no decompression ILboolean iReadNonRleSgi(iSgiHeader *Head) { ILuint i, c; // ILint ChanInt = 0; Unused ILint ChanSize; ILboolean Cache = IL_FALSE; if (!iNewSgi(Head)) { return IL_FALSE; } if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) { Cache = IL_TRUE; ChanSize = Head->XSize * Head->YSize * Head->Bpc; iPreCache(ChanSize); } for (c = 0; c < iCurImage->Bpp; c++) { for (i = c; i < iCurImage->SizeOfData; i += iCurImage->Bpp) { if (iread(iCurImage->Data + i, 1, 1) != 1) { if (Cache) iUnCache(); return IL_FALSE; } } } if (Cache) iUnCache(); return IL_TRUE; }
ILint ILAPIENTRY iGetcFile(ILvoid) { if (!UseCache) { return GetcProc(FileRead); } if (CachePos >= CacheSize) { iPreCache(CacheSize); } CacheBytesRead++; return Cache[CachePos++]; }
ILuint ILAPIENTRY iReadFile(ILvoid *Buffer, ILuint Size, ILuint Number) { ILuint TotalBytes = 0, BytesCopied; ILuint BuffSize = Size * Number; ILuint NumRead; if (!UseCache) { NumRead = ReadProc(Buffer, Size, Number, FileRead); if (NumRead != Number) ilSetError(IL_FILE_READ_ERROR); return NumRead; } /*if (Cache == NULL || CacheSize == 0) { // Shouldn't happen, but we check anyway. return ReadProc(Buffer, Size, Number, FileRead); }*/ if (BuffSize < CacheSize - CachePos) { memcpy(Buffer, Cache + CachePos, BuffSize); CachePos += BuffSize; CacheBytesRead += BuffSize; if (Size != 0) BuffSize /= Size; return BuffSize; } else { while (TotalBytes < BuffSize) { // If loop through more than once, after first, CachePos is 0. if (TotalBytes + CacheSize - CachePos > BuffSize) BytesCopied = BuffSize - TotalBytes; else BytesCopied = CacheSize - CachePos; memcpy((ILubyte*)Buffer + TotalBytes, Cache + CachePos, BytesCopied); TotalBytes += BytesCopied; CachePos += BytesCopied; if (TotalBytes < BuffSize) { iPreCache(CacheSize); } } } CacheBytesRead += TotalBytes; if (Size != 0) TotalBytes /= Size; if (TotalBytes != Number) ilSetError(IL_FILE_READ_ERROR); return TotalBytes; }
// 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; }
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; }
// Internal function used to load the .hdr. ILboolean iLoadHdrInternal() { HDRHEADER Header; ILfloat *data; ILubyte *scanline; ILuint i, j, e, r, g, b; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (!iGetHdrHead(&Header)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } if (!iCheckHdr(&Header)) { //iseek(-(ILint)sizeof(HDRHEAD), IL_SEEK_CUR); ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Update the current image with the new dimensions if (!ilTexImage(Header.Width, Header.Height, 1, 3, IL_RGB, IL_FLOAT, NULL)) { return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; //read image data if (iGetHint(IL_MEM_SPEED_HINT) == IL_FASTEST) iPreCache(iCurImage->Width / 8 * iCurImage->Height); data = (ILfloat*)iCurImage->Data; scanline = (ILubyte*)ialloc(Header.Width*4); for (i = 0; i < Header.Height; ++i) { ReadScanline(scanline, Header.Width); //convert hdrs internal format to floats for (j = 0; j < 4*Header.Width; j += 4) { ILuint *ee; ILfloat t, *ff; e = scanline[j + 3]; r = scanline[j + 0]; g = scanline[j + 1]; b = scanline[j + 2]; //t = (float)pow(2.f, ((ILint)e) - 128); if (e != 0) e = (e - 1) << 23; // All this just to avoid stric-aliasing warnings... // was: t = *(ILfloat*)&e ee = &e; ff = (ILfloat*)ee; t = *ff; data[0] = (r/255.0f)*t; data[1] = (g/255.0f)*t; data[2] = (b/255.0f)*t; data += 3; } } iUnCache(); ifree(scanline); return ilFixImage(); }