ILint iGetScanLine(ILubyte *ScanLine, iSgiHeader *Head, ILuint Length) { ILushort Pixel, Count; // For current pixel ILuint BppRead = 0, CurPos = 0, Bps = Head->XSize * Head->Bpc; while (BppRead < Length && CurPos < Bps) { Pixel = 0; if (iread(&Pixel, Head->Bpc, 1) != 1) return -1; #ifndef __LITTLE_ENDIAN__ iSwapUShort(&Pixel); #endif if (!(Count = (Pixel & 0x7f))) // If 0, line ends return CurPos; if (Pixel & 0x80) { // If top bit set, then it is a "run" if (iread(ScanLine, Head->Bpc, Count) != Count) return -1; BppRead += Head->Bpc * Count + Head->Bpc; ScanLine += Head->Bpc * Count; CurPos += Head->Bpc * Count; } else { if (iread(&Pixel, Head->Bpc, 1) != 1) return -1; #ifndef __LITTLE_ENDIAN__ iSwapUShort(&Pixel); #endif if (Head->Bpc == 1) { while (Count--) { *ScanLine = (ILubyte)Pixel; ScanLine++; CurPos++; } } else { while (Count--) { *(ILushort*)ScanLine = Pixel; ScanLine += 2; CurPos += 2; } } BppRead += Head->Bpc + Head->Bpc; } } return CurPos; }
// Internal function used to load the Gif. ILboolean iLoadGifInternal(ILimage* image) { GIFHEAD Header; ILpal GlobalPal; if (image == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } GlobalPal.Palette = NULL; GlobalPal.PalSize = 0; // Read header iCurImage->io.read(iCurImage->io.handle, &Header, 1, sizeof(Header)); #ifdef __BIG_ENDIAN__ iSwapUShort(Header.Width); iSwapUShort(Header.Height); #endif if (strnicmp(Header.Sig, "GIF87A", 6) != 0 && strnicmp(Header.Sig, "GIF89A", 6) != 0) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) //if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_RGB, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; image->Origin = IL_ORIGIN_UPPER_LEFT; // Check for a global colour map. if (Header.ColourInfo & (1 << 7)) { if (!iGetPalette(Header.ColourInfo, &GlobalPal, NULL)) { return IL_FALSE; } } if (!GetImages(image, &GlobalPal, &Header)) return IL_FALSE; if (GlobalPal.Palette && GlobalPal.PalSize) ifree(GlobalPal.Palette); GlobalPal.Palette = NULL; GlobalPal.PalSize = 0; return ilFixImage(); }
// Internal function used to get the Psd header from the current file. ILboolean iGetPsdHead(SIO* io, PSDHEAD *Header) { io->read(io, Header, 1, sizeof(PSDHEAD)); #ifdef IL_LITTLE_ENDIAN iSwapUShort(&Header->Version); iSwapUShort(&Header->Channels); iSwapUInt(&Header->Height); iSwapUInt(&Header->Width); iSwapUShort(&Header->Depth); iSwapUShort(&Header->Mode); #endif return IL_TRUE; }
ILuint *GetCompChanLen(ILimage* image, PSDHEAD *Head, ILushort& ChannelNum) { ILushort *RleTable; ILuint *ChanLen, c, i, j; RleTable = (ILushort*)ialloc(Head->Height * ChannelNum * sizeof(ILushort)); ChanLen = (ILuint*)ialloc(ChannelNum * sizeof(ILuint)); if (RleTable == NULL || ChanLen == NULL) { return NULL; } if (image->io.read(&image->io, RleTable, sizeof(ILushort), Head->Height * ChannelNum) != Head->Height * ChannelNum) { ifree(RleTable); ifree(ChanLen); return NULL; } #ifdef IL_LITTLE_ENDIAN for (i = 0; i < Head->Height * ChannelNum; i++) { iSwapUShort(&RleTable[i]); } #endif imemclear(ChanLen, ChannelNum * sizeof(ILuint)); for (c = 0; c < ChannelNum; c++) { j = c * Head->Height; for (i = 0; i < Head->Height; i++) { ChanLen[c] += RleTable[i + j]; } } ifree(RleTable); return ChanLen; }
// Obtain .pcx header ILuint iGetPcxHead(SIO* io, PCXHEAD *header) { auto read = io->read(io->handle, header, 1, sizeof(PCXHEAD)); #ifdef __BIG_ENDIAN__ iSwapUShort(header->Xmin); // = GetLittleShort(); iSwapUShort(header->Ymin); // = GetLittleShort(); iSwapUShort(header->Xmax); // = GetLittleShort(); iSwapUShort(header->Ymax); // = GetLittleShort(); iSwapUShort(header->HDpi); // = GetLittleShort(); iSwapUShort(header->VDpi); // = GetLittleShort(); iSwapUShort(header->Bps); // = GetLittleShort(); iSwapUShort(header->PaletteInfo); // = GetLittleShort(); iSwapUShort(header->HScreenSize); // = GetLittleShort(); iSwapUShort(header->VScreenSize); // = GetLittleShort(); #endif return read; }
ILvoid EndianSwapData(void *_Image) { ILuint i; ILubyte *temp, *s, *d; ILushort *ShortS, *ShortD; ILuint *IntS, *IntD; ILfloat *FltS, *FltD; ILdouble *DblS, *DblD; ILimage *Image = (ILimage*)_Image; switch (Image->Type) { case IL_BYTE: case IL_UNSIGNED_BYTE: switch (Image->Bpp) { case 3: temp = (ILubyte*)ialloc(Image->SizeOfData); if (temp == NULL) return; s = Image->Data; d = temp; for( i = Image->Width * Image->Height; i > 0; i-- ) { *d++ = *(s+2); *d++ = *(s+1); *d++ = *s; s += 3; } ifree(Image->Data); Image->Data = temp; break; case 4: temp = (ILubyte*)ialloc(Image->SizeOfData); if (temp == NULL) return; s = Image->Data; d = temp; for (i = Image->Width * Image->Height; i > 0; i--) { *d++ = *(s+3); *d++ = *(s+2); *d++ = *(s+1); *d++ = *s; s += 4; } ifree(Image->Data); Image->Data = temp; break; } break; case IL_SHORT: case IL_UNSIGNED_SHORT: switch (Image->Bpp) { case 3: temp = (ILubyte*)ialloc(Image->SizeOfData); if (temp == NULL) return; ShortS = (ILushort*)Image->Data; ShortD = (ILushort*)temp; for (i = Image->Width * Image->Height; i > 0; i--) { *ShortD = *ShortS++; iSwapUShort(ShortD++); *ShortD = *ShortS++; iSwapUShort(ShortD++); *ShortD = *ShortS++; iSwapUShort(ShortD++); } ifree(Image->Data); Image->Data = temp; break; case 4: temp = (ILubyte*)ialloc(Image->SizeOfData); if (temp == NULL) return; ShortS = (ILushort*)Image->Data; ShortD = (ILushort*)temp; for (i = Image->Width * Image->Height; i > 0; i--) { *ShortD = *ShortS++; iSwapUShort(ShortD++); *ShortD = *ShortS++; iSwapUShort(ShortD++); *ShortD = *ShortS++; iSwapUShort(ShortD++); *ShortD = *ShortS++; iSwapUShort(ShortD++); } ifree(Image->Data); Image->Data = temp; break; } break; case IL_INT: case IL_UNSIGNED_INT: switch (Image->Bpp) { case 3: temp = (ILubyte*)ialloc(Image->SizeOfData); if (temp == NULL) return; IntS = (ILuint*)Image->Data; IntD = (ILuint*)temp; for (i = Image->Width * Image->Height; i > 0; i--) { *IntD = *IntS++; iSwapUInt(IntD++); *IntD = *IntS++; iSwapUInt(IntD++); *IntD = *IntS++; iSwapUInt(IntD++); } ifree(Image->Data); Image->Data = temp; break; case 4: temp = (ILubyte*)ialloc(Image->SizeOfData); if (temp == NULL) return; IntS = (ILuint*)Image->Data; IntD = (ILuint*)temp; for (i = Image->Width * Image->Height; i > 0; i--) { *IntD = *IntS++; iSwapUInt(IntD++); *IntD = *IntS++; iSwapUInt(IntD++); *IntD = *IntS++; iSwapUInt(IntD++); *IntD = *IntS++; iSwapUInt(IntD++); } ifree(Image->Data); Image->Data = temp; break; } break; case IL_FLOAT: switch (Image->Bpp) { case 3: temp = (ILubyte*)ialloc(Image->SizeOfData); if (temp == NULL) return; FltS = (ILfloat*)Image->Data; FltD = (ILfloat*)temp; for (i = Image->Width * Image->Height; i > 0; i--) { *FltD = *FltS++; iSwapFloat(FltD++); *FltD = *FltS++; iSwapFloat(FltD++); *FltD = *FltS++; iSwapFloat(FltD++); } ifree(Image->Data); Image->Data = temp; break; case 4: temp = (ILubyte*)ialloc(Image->SizeOfData); if (temp == NULL) return; FltS = (ILfloat*)Image->Data; FltD = (ILfloat*)temp; for (i = Image->Width * Image->Height; i > 0; i--) { *FltD = *FltS++; iSwapFloat(FltD++); *FltD = *FltS++; iSwapFloat(FltD++); *FltD = *FltS++; iSwapFloat(FltD++); *FltD = *FltS++; iSwapFloat(FltD++); } ifree(Image->Data); Image->Data = temp; break; } break; case IL_DOUBLE: switch (Image->Bpp) { case 3: temp = (ILubyte*)ialloc(Image->SizeOfData); if (temp == NULL) return; DblS = (ILdouble*)Image->Data; DblD = (ILdouble*)temp; for (i = Image->Width * Image->Height; i > 0; i--) { *DblD = *DblS++; iSwapDouble(DblD++); *DblD = *DblS++; iSwapDouble(DblD++); *DblD = *DblS++; iSwapDouble(DblD++); } ifree(Image->Data); Image->Data = temp; break; case 4: temp = (ILubyte*)ialloc(Image->SizeOfData); if (temp == NULL) return; DblS = (ILdouble*)Image->Data; DblD = (ILdouble*)temp; for (i = Image->Width * Image->Height; i > 0; i--) { *DblD = *DblS++; iSwapDouble(DblD++); *DblD = *DblS++; iSwapDouble(DblD++); *DblD = *DblS++; iSwapDouble(DblD++); *DblD = *DblS++; iSwapDouble(DblD++); } ifree(Image->Data); Image->Data = temp; break; } break; } if( iCurImage->Format == IL_COLOUR_INDEX ) { switch (iCurImage->Pal.PalType) { case IL_PAL_RGB24: case IL_PAL_BGR24: temp = (ILubyte*)ialloc(Image->Pal.PalSize); if (temp == NULL) return; s = Image->Pal.Palette; d = temp; for (i = Image->Pal.PalSize / 3; i > 0; i--) { *d++ = *(s+2); *d++ = *(s+1); *d++ = *s; s += 3; } ifree(Image->Pal.Palette); Image->Pal.Palette = temp; break; case IL_PAL_RGBA32: case IL_PAL_RGB32: case IL_PAL_BGRA32: case IL_PAL_BGR32: temp = (ILubyte*)ialloc(Image->Pal.PalSize); if (temp == NULL) return; s = Image->Pal.Palette; d = temp; for (i = Image->Pal.PalSize / 4; i > 0; i--) { *d++ = *(s+3); *d++ = *(s+2); *d++ = *(s+1); *d++ = *s; s += 4; } ifree(Image->Pal.Palette); Image->Pal.Palette = temp; break; } } return; }
ILboolean GetImages(ILimage* Image, ILpal *GlobalPal, GIFHEAD *GifHead) { IMAGEDESC ImageDesc, OldImageDesc; GFXCONTROL Gfx; ILboolean BaseImage = IL_TRUE; ILimage *TempImage = NULL, *PrevImage = NULL; ILuint NumImages = 0, i; ILint input; OldImageDesc.ImageInfo = 0; // to initialize the data with an harmless value Gfx.Used = IL_TRUE; while (!iCurImage->io.eof(iCurImage->io.handle)) { ILubyte DisposalMethod = 1; i = iCurImage->io.tell(iCurImage->io.handle); if (!SkipExtensions(&Gfx)) goto error_clean; i = iCurImage->io.tell(iCurImage->io.handle); if (!Gfx.Used) DisposalMethod = (Gfx.Packed & 0x1C) >> 2; //read image descriptor iCurImage->io.read(iCurImage->io.handle, &ImageDesc, 1, sizeof(ImageDesc)); #ifdef __BIG_ENDIAN__ iSwapUShort(ImageDesc.OffX); iSwapUShort(ImageDesc.OffY); iSwapUShort(ImageDesc.Width); iSwapUShort(ImageDesc.Height); #endif if (ImageDesc.Separator != 0x2C) //end of image break; if (!setMinSizes(ImageDesc.OffX + ImageDesc.Width, ImageDesc.OffY + ImageDesc.Height, Image)) goto error_clean; if (iCurImage->io.eof(iCurImage->io.handle)) { ilGetError(); // Gets rid of the IL_FILE_READ_ERROR that inevitably results. break; } if (!BaseImage) { NumImages++; Image->Next = ilNewImage(Image->Width, Image->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; } PrevImage = Image; 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); } 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, PrevImage)) { goto error_clean; } } else { if (!iCopyPalette(&Image->Pal, GlobalPal)) { goto error_clean; } } if (!GifGetData(Image, Image->Data, Image->SizeOfData, ImageDesc.OffX, ImageDesc.OffY, ImageDesc.Width, ImageDesc.Height, Image->Bps, &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 = iCurImage->io.tell(iCurImage->io.handle); // Terminates each block. if((input = iCurImage->io.getc(iCurImage->io.handle)) == IL_EOF) goto error_clean; if (input != 0x00) iCurImage->io.seek(iCurImage->io.handle, -1, IL_SEEK_CUR); // break; OldImageDesc = ImageDesc; } //Deinterlace last image if (OldImageDesc.ImageInfo & (1 << 6)) { // Image is interlaced. if (!RemoveInterlace(Image)) goto error_clean; } if (BaseImage) // Was not able to load any images in... return IL_FALSE; return IL_TRUE; error_clean: Image = Image->Next; /* while (Image) { TempImage = Image; Image = Image->Next; ilCloseImage(TempImage); }*/ return IL_FALSE; }
static Uint16 iSDL_SwapBE16( Uint16 s ) { Uint16 foo = s; iSwapUShort(&foo); return foo; }
ILboolean PsdGetData(ILimage* image, PSDHEAD *Head, void *Buffer, ILboolean Compressed, ILushort& ChannelNum) { ILuint c, x, y, i, Size, ReadResult, NumChan; ILubyte *Channel = NULL; ILushort *ShortPtr; ILuint *ChanLen = NULL; // Added 01-07-2009: This is needed to correctly load greyscale and // paletted images. switch (Head->Mode) { case 1: case 2: NumChan = 1; break; default: NumChan = 3; } Channel = (ILubyte*)ialloc(Head->Width * Head->Height * image->Bpc); if (Channel == NULL) { return IL_FALSE; } ShortPtr = (ILushort*)Channel; // @TODO: Add support for this in, though I have yet to run across a .psd // file that uses this. if (Compressed && image->Type == IL_UNSIGNED_SHORT) { il2SetError(IL_FORMAT_NOT_SUPPORTED); return IL_FALSE; } if (!Compressed) { if (image->Bpc == 1) { for (c = 0; c < NumChan; c++) { i = 0; if (image->io.read(&image->io, Channel, Head->Width * Head->Height, 1) != 1) { ifree(Channel); return IL_FALSE; } for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { image->Data[y + x + c] = Channel[i]; } } } // Accumulate any remaining channels into a single alpha channel //@TODO: This needs to be changed for greyscale images. for (; c < Head->Channels; c++) { i = 0; if (image->io.read(&image->io, Channel, Head->Width * Head->Height, 1) != 1) { ifree(Channel); return IL_FALSE; } for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { float curVal = ubyte_to_float(image->Data[y + x + 3]); float newVal = ubyte_to_float(Channel[i]); image->Data[y + x + 3] = float_to_ubyte(curVal * newVal); } } } } else { // image->Bpc == 2 for (c = 0; c < NumChan; c++) { i = 0; if (image->io.read(&image->io, Channel, Head->Width * Head->Height * 2, 1) != 1) { ifree(Channel); return IL_FALSE; } image->Bps /= 2; for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { #ifndef WORDS_BIGENDIAN iSwapUShort(ShortPtr+i); #endif ((ILushort*)image->Data)[y + x + c] = ShortPtr[i]; } } image->Bps *= 2; } // Accumulate any remaining channels into a single alpha channel //@TODO: This needs to be changed for greyscale images. for (; c < Head->Channels; c++) { i = 0; if (image->io.read(&image->io, Channel, Head->Width * Head->Height * 2, 1) != 1) { ifree(Channel); return IL_FALSE; } image->Bps /= 2; for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { float curVal = ushort_to_float(((ILushort*)image->Data)[y + x + 3]); float newVal = ushort_to_float(ShortPtr[i]); ((ILushort*)image->Data)[y + x + 3] = float_to_ushort(curVal * newVal); } } image->Bps *= 2; } } } else { ChanLen = GetCompChanLen(image, Head, ChannelNum); Size = Head->Width * Head->Height; for (c = 0; c < NumChan; c++) { ReadResult = ReadCompressedChannel(image, ChanLen[c], Size, Channel); if (ReadResult == READ_COMPRESSED_ERROR_FILE_CORRUPT) goto file_corrupt; else if (ReadResult == READ_COMPRESSED_ERROR_FILE_READ_ERROR) goto file_read_error; i = 0; for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { image->Data[y + x + c] = Channel[i]; } } } // Initialize the alpha channel to solid //@TODO: This needs to be changed for greyscale images. if (Head->Channels >= 4) { for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp) { image->Data[y + x + 3] = 255; } } for (; c < Head->Channels; c++) { ReadResult = ReadCompressedChannel(image, ChanLen[c], Size, Channel); if (ReadResult == READ_COMPRESSED_ERROR_FILE_CORRUPT) goto file_corrupt; else if (ReadResult == READ_COMPRESSED_ERROR_FILE_READ_ERROR) goto file_read_error; i = 0; for (y = 0; y < Head->Height * image->Bps; y += image->Bps) { for (x = 0; x < image->Bps; x += image->Bpp, i++) { float curVal = ubyte_to_float(image->Data[y + x + 3]); float newVal = ubyte_to_float(Channel[i]); image->Data[y + x + 3] = float_to_ubyte(curVal * newVal); } } } } ifree(ChanLen); } ifree(Channel); return IL_TRUE; file_corrupt: ifree(ChanLen); ifree(Channel); il2SetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; file_read_error: ifree(ChanLen); ifree(Channel); return IL_FALSE; }