123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496 |
- #include "EditorDefs.h"
- #include "ImageGif.h"
- #include "Util/Image.h"
- #define NEXTBYTE (*ptr++)
- #define IMAGESEP 0x2c
- #define GRAPHIC_EXT 0xf9
- #define PLAINTEXT_EXT 0x01
- #define APPLICATION_EXT 0xff
- #define COMMENT_EXT 0xfe
- #define START_EXTENSION 0x21
- #define INTERLACEMASK 0x40
- #define COLORMAPMASK 0x80
- #define CHK(x) x
- #pragma pack(push,1)
- struct SGIFRGBcolor
- {
- uint8 red, green, blue;
- };
- struct SGIFRGBPixel
- {
- uint8 red, green, blue, alpha;
- };
- #pragma pack(pop)
- static int BitOffset = 0,
- XC = 0, YC = 0,
- Pass = 0,
- OutCount = 0,
- RWidth, RHeight,
- Width, Height,
- LeftOfs, TopOfs,
- BitsPerPixel,
- BytesPerScanline,
- ColorMapSize,
- Background,
- CodeSize,
- InitCodeSize,
- Code,
- MaxCode,
- ClearCode,
- EOFCode,
- CurCode, OldCode, InCode,
- FirstFree,
- FreeCode,
- FinChar,
- BitMask,
- ReadMask;
- static bool Interlace, HasColormap;
- static SGIFRGBPixel* Image;
- static SGIFRGBcolor* Palette;
- static uint8* IndexImage;
- static uint8* Raster;
- static uint8 used[256];
- static int numused;
- const char* id87 = "GIF87a";
- const char* id89 = "GIF89a";
- inline int ReadCode (void)
- {
- int RawCode, ByteOffset;
- ByteOffset = BitOffset / 8;
- RawCode = Raster[ByteOffset] + (0x100 * Raster[ByteOffset + 1]);
- if (CodeSize >= 8)
- {
- RawCode += (0x10000 * Raster[ByteOffset + 2]);
- }
- RawCode >>= (BitOffset % 8);
- BitOffset += CodeSize;
- return RawCode & ReadMask;
- }
- inline void AddToPixel (uint8 Index)
- {
- if (YC < Height)
- {
- SGIFRGBPixel* p = Image + YC * BytesPerScanline + XC;
- p->red = Palette[Index].red;
- p->green = Palette[Index].green;
- p->blue = Palette[Index].blue;
- p->alpha = 0;
- IndexImage[YC * BytesPerScanline + XC] = Index;
- }
- if (!used[Index])
- {
- used[Index] = 1;
- numused++;
- }
-
- if (++XC == Width)
- {
-
- XC = 0;
- if (!Interlace)
- {
- YC++;
- }
- else
- {
- switch (Pass)
- {
- case 0:
- YC += 8;
- if (YC >= Height)
- {
- Pass++;
- YC = 4;
- }
- break;
- case 1:
- YC += 8;
- if (YC >= Height)
- {
- Pass++;
- YC = 2;
- }
- break;
- case 2:
- YC += 4;
- if (YC >= Height)
- {
- Pass++;
- YC = 1;
- }
- break;
- case 3:
- YC += 2;
- break;
- default:
- break;
- }
- }
- }
- }
- bool CImageGif::Load(const QString& fileName, CImageEx& outImage)
- {
- bool ret = false;
- std::vector<uint8> data;
- CCryFile file;
- if (!file.Open(fileName.toUtf8().data(), "rb"))
- {
- CLogFile::FormatLine("File not found %s", fileName.toUtf8().data());
- return false;
- }
- long filesize = static_cast<long>(file.GetLength());
- data.resize(filesize);
- uint8* ptr = &data[0];
- file.ReadRaw(ptr, filesize);
-
- if (strncmp ((char*)ptr, "GIF87a", 6) && strncmp ((char*)ptr, "GIF89a", 6))
- {
- CLogFile::FormatLine("Bad GIF file format %s", fileName.toUtf8().data());
- return false;
- }
- unsigned char ch, ch1;
- uint8* ptr1;
- int i;
- TImage<uint8> outImageIndex;
-
- int* Prefix;
- int* Suffix;
-
- int* OutCode;
- CHK (Prefix = new int [4096]);
- CHK (Suffix = new int [4096]);
- CHK (OutCode = new int [1025]);
- BitOffset = 0;
- XC = YC = 0;
- Pass = 0;
- OutCount = 0;
- Palette = nullptr;
- CHK (Raster = new uint8 [filesize]);
- if (strncmp((char*) ptr, id87, 6))
- {
- if (strncmp((char*) ptr, id89, 6))
- {
- CLogFile::FormatLine("Bad GIF file format %s",fileName.toUtf8().data());
- goto cleanup;
- }
- }
- ptr += 6;
-
- ch = NEXTBYTE;
- RWidth = ch + 0x100 * NEXTBYTE;
- ch = NEXTBYTE;
- RHeight = ch + 0x100 * NEXTBYTE;
- ch = NEXTBYTE;
- HasColormap = ((ch & COLORMAPMASK) ? true : false);
- BitsPerPixel = (ch & 7) + 1;
- BitMask = ColorMapSize - 1;
- Background = NEXTBYTE;
- if (NEXTBYTE)
- {
- CLogFile::FormatLine("Bad GIF file format %s", fileName.toUtf8().data());
- goto cleanup;
- }
-
- SGIFRGBcolor mspPal[1024];
- if (HasColormap)
- {
- for (i = 0; i < ColorMapSize; i++)
- {
- mspPal[i].red = NEXTBYTE;
- mspPal[i].green = NEXTBYTE;
- mspPal[i].blue = NEXTBYTE;
- used[i] = 0;
- }
- Palette = mspPal;
- numused = 0;
- }
-
- for (ch = NEXTBYTE; ch != IMAGESEP; ch = NEXTBYTE)
- {
- i = ch;
- if (ch != START_EXTENSION)
- {
- CLogFile::FormatLine("Bad GIF file format %s", fileName.toUtf8().data());
- goto cleanup;
- }
-
- switch (ch = NEXTBYTE)
- {
- case GRAPHIC_EXT:
- ch = NEXTBYTE;
- ptr += ch;
- break;
- case PLAINTEXT_EXT:
- break;
- case APPLICATION_EXT:
- break;
- case COMMENT_EXT:
- break;
- default:
- {
- CLogFile::FormatLine("Invalid GIF89 extension %s", fileName.toUtf8().data());
- goto cleanup;
- }
- }
- ch = NEXTBYTE;
- while (ch)
- {
- ptr += ch;
- ch = NEXTBYTE;
- }
- }
-
- ch = NEXTBYTE;
- LeftOfs = ch + 0x100 * NEXTBYTE;
- ch = NEXTBYTE;
- TopOfs = ch + 0x100 * NEXTBYTE;
- ch = NEXTBYTE;
- Width = ch + 0x100 * NEXTBYTE;
- ch = NEXTBYTE;
- Height = ch + 0x100 * NEXTBYTE;
- Interlace = ((NEXTBYTE & INTERLACEMASK) ? true : false);
-
-
- outImage.Allocate(Width, Height);
-
- Image = (SGIFRGBPixel*)outImage.GetData();
- outImageIndex.Allocate(Width, Height);
- IndexImage = outImageIndex.GetData();
-
-
- CodeSize = NEXTBYTE;
- ClearCode = (1 << CodeSize);
- EOFCode = ClearCode + 1;
- FreeCode = FirstFree = ClearCode + 2;
-
- CodeSize++;
- InitCodeSize = CodeSize;
- MaxCode = (1 << CodeSize);
- ReadMask = MaxCode - 1;
-
- ptr1 = Raster;
- do
- {
- ch = ch1 = NEXTBYTE;
- while (ch--)
- {
- *ptr1++ = NEXTBYTE;
- }
- if ((ptr1 - Raster) > filesize)
- {
- CLogFile::FormatLine("Corrupted GIF file (unblock) %s", fileName.toUtf8().data());
- goto cleanup;
- }
- }
- while (ch1);
- BytesPerScanline = Width;
-
- Code = ReadCode ();
- while (Code != EOFCode)
- {
-
- if (Code == ClearCode)
- {
- CodeSize = InitCodeSize;
- MaxCode = (1 << CodeSize);
- ReadMask = MaxCode - 1;
- FreeCode = FirstFree;
- CurCode = OldCode = Code = ReadCode();
- FinChar = CurCode & BitMask;
- AddToPixel(static_cast<uint8>(FinChar));
- }
- else
- {
-
- CurCode = InCode = Code;
-
- if (CurCode >= FreeCode)
- {
- CurCode = OldCode;
- OutCode[OutCount++] = FinChar;
- }
-
- while (CurCode > BitMask)
- {
- if (OutCount > 1024)
- {
- CLogFile::FormatLine("Corrupted GIF file (OutCount) %s", fileName.toUtf8().data());
- goto cleanup;
- }
- OutCode[OutCount++] = Suffix[CurCode];
- CurCode = Prefix[CurCode];
- }
-
- FinChar = CurCode & BitMask;
- OutCode[OutCount++] = FinChar;
-
- for (i = OutCount - 1; i >= 0; i--)
- {
- AddToPixel(static_cast<uint8>(OutCode[i]));
- }
- OutCount = 0;
-
- Prefix[FreeCode] = OldCode;
- Suffix[FreeCode] = FinChar;
- OldCode = InCode;
-
- FreeCode++;
- if (FreeCode >= MaxCode)
- {
- if (CodeSize < 12)
- {
- CodeSize++;
- MaxCode *= 2;
- ReadMask = (1 << CodeSize) - 1;
- }
- }
- }
- Code = ReadCode ();
- }
- ret = true;
- cleanup:
- if (Raster)
- {
- CHK (delete [] Raster);
- }
- if (Prefix)
- {
- CHK (delete [] Prefix);
- }
- if (Suffix)
- {
- CHK (delete [] Suffix);
- }
- if (OutCode)
- {
- CHK (delete [] OutCode);
- }
- return ret;
- }
|