| @@ -850,7 +850,6 @@ | |||
| 2AA4DDD1F26188A570F4DBE2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_RelativeCoordinate.cpp; path = ../../src/gui/graphics/geometry/juce_RelativeCoordinate.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 54D9BBB69BDA3837240F7749 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_RelativeCoordinate.h; path = ../../src/gui/graphics/geometry/juce_RelativeCoordinate.h; sourceTree = SOURCE_ROOT; }; | |||
| 0F1C5770B363EF7DF64A876A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_GIFLoader.cpp; path = ../../src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp; sourceTree = SOURCE_ROOT; }; | |||
| EFBDB957445BD56D0458535D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_GIFLoader.h; path = ../../src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.h; sourceTree = SOURCE_ROOT; }; | |||
| 6619D27E74F623B1E8CE8F71 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_JPEGLoader.cpp; path = ../../src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp; sourceTree = SOURCE_ROOT; }; | |||
| EAF0F2EAB230F7539B91A7FB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_PNGLoader.cpp; path = ../../src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 0337723C9D607B82CF8AA682 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CameraDevice.h; path = ../../src/gui/graphics/imaging/juce_CameraDevice.h; sourceTree = SOURCE_ROOT; }; | |||
| @@ -1602,7 +1601,6 @@ | |||
| 54D9BBB69BDA3837240F7749 ); name = geometry; sourceTree = "<group>"; }; | |||
| D71FD838B3FD1536FCA839A4 = { isa = PBXGroup; children = ( | |||
| 0F1C5770B363EF7DF64A876A, | |||
| EFBDB957445BD56D0458535D, | |||
| 6619D27E74F623B1E8CE8F71, | |||
| EAF0F2EAB230F7539B91A7FB ); name = image_file_formats; sourceTree = "<group>"; }; | |||
| 36A6F90D0C87EA1D8FBE9EC0 = { isa = PBXGroup; children = ( | |||
| @@ -766,7 +766,6 @@ | |||
| <Filter Name="imaging"> | |||
| <Filter Name="image_file_formats"> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_GIFLoader.cpp"/> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_GIFLoader.h"/> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_JPEGLoader.cpp"/> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_PNGLoader.cpp"/> | |||
| </Filter> | |||
| @@ -766,7 +766,6 @@ | |||
| <Filter Name="imaging"> | |||
| <Filter Name="image_file_formats"> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_GIFLoader.cpp"/> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_GIFLoader.h"/> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_JPEGLoader.cpp"/> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_PNGLoader.cpp"/> | |||
| </Filter> | |||
| @@ -768,7 +768,6 @@ | |||
| <Filter Name="imaging"> | |||
| <Filter Name="image_file_formats"> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_GIFLoader.cpp"/> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_GIFLoader.h"/> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_JPEGLoader.cpp"/> | |||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_PNGLoader.cpp"/> | |||
| </Filter> | |||
| @@ -707,7 +707,6 @@ | |||
| <ClInclude Include="..\..\src\gui\graphics\geometry\juce_Rectangle.h"/> | |||
| <ClInclude Include="..\..\src\gui\graphics\geometry\juce_RectangleList.h"/> | |||
| <ClInclude Include="..\..\src\gui\graphics\geometry\juce_RelativeCoordinate.h"/> | |||
| <ClInclude Include="..\..\src\gui\graphics\imaging\image_file_formats\juce_GIFLoader.h"/> | |||
| <ClInclude Include="..\..\src\gui\graphics\imaging\juce_CameraDevice.h"/> | |||
| <ClInclude Include="..\..\src\gui\graphics\imaging\juce_Image.h"/> | |||
| <ClInclude Include="..\..\src\gui\graphics\imaging\juce_ImageCache.h"/> | |||
| @@ -2043,9 +2043,6 @@ | |||
| <ClInclude Include="..\..\src\gui\graphics\geometry\juce_RelativeCoordinate.h"> | |||
| <Filter>Juce\Source\gui\graphics\geometry</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\gui\graphics\imaging\image_file_formats\juce_GIFLoader.h"> | |||
| <Filter>Juce\Source\gui\graphics\imaging\image_file_formats</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="..\..\src\gui\graphics\imaging\juce_CameraDevice.h"> | |||
| <Filter>Juce\Source\gui\graphics\imaging</Filter> | |||
| </ClInclude> | |||
| @@ -850,7 +850,6 @@ | |||
| 2AA4DDD1F26188A570F4DBE2 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_RelativeCoordinate.cpp; path = ../../src/gui/graphics/geometry/juce_RelativeCoordinate.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 54D9BBB69BDA3837240F7749 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_RelativeCoordinate.h; path = ../../src/gui/graphics/geometry/juce_RelativeCoordinate.h; sourceTree = SOURCE_ROOT; }; | |||
| 0F1C5770B363EF7DF64A876A = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_GIFLoader.cpp; path = ../../src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp; sourceTree = SOURCE_ROOT; }; | |||
| EFBDB957445BD56D0458535D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_GIFLoader.h; path = ../../src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.h; sourceTree = SOURCE_ROOT; }; | |||
| 6619D27E74F623B1E8CE8F71 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_JPEGLoader.cpp; path = ../../src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp; sourceTree = SOURCE_ROOT; }; | |||
| EAF0F2EAB230F7539B91A7FB = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_PNGLoader.cpp; path = ../../src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp; sourceTree = SOURCE_ROOT; }; | |||
| 0337723C9D607B82CF8AA682 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_CameraDevice.h; path = ../../src/gui/graphics/imaging/juce_CameraDevice.h; sourceTree = SOURCE_ROOT; }; | |||
| @@ -1602,7 +1601,6 @@ | |||
| 54D9BBB69BDA3837240F7749 ); name = geometry; sourceTree = "<group>"; }; | |||
| D71FD838B3FD1536FCA839A4 = { isa = PBXGroup; children = ( | |||
| 0F1C5770B363EF7DF64A876A, | |||
| EFBDB957445BD56D0458535D, | |||
| 6619D27E74F623B1E8CE8F71, | |||
| EAF0F2EAB230F7539B91A7FB ); name = image_file_formats; sourceTree = "<group>"; }; | |||
| 36A6F90D0C87EA1D8FBE9EC0 = { isa = PBXGroup; children = ( | |||
| @@ -1129,8 +1129,6 @@ | |||
| <GROUP id="UpDEgf4Fr" name="image_file_formats"> | |||
| <FILE id="82P2bqp" name="juce_GIFLoader.cpp" compile="1" resource="0" | |||
| file="src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp"/> | |||
| <FILE id="mvmvVPw1S" name="juce_GIFLoader.h" compile="0" resource="0" | |||
| file="src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.h"/> | |||
| <FILE id="SuwswXcCp" name="juce_JPEGLoader.cpp" compile="1" resource="0" | |||
| file="src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp"/> | |||
| <FILE id="GbTEpJRyd" name="juce_PNGLoader.cpp" compile="1" resource="0" | |||
| @@ -95819,95 +95819,6 @@ END_JUCE_NAMESPACE | |||
| /*** Start of inlined file: juce_ImageFileFormat.cpp ***/ | |||
| BEGIN_JUCE_NAMESPACE | |||
| /*** Start of inlined file: juce_GIFLoader.h ***/ | |||
| #ifndef __JUCE_GIFLOADER_JUCEHEADER__ | |||
| #define __JUCE_GIFLOADER_JUCEHEADER__ | |||
| #ifndef DOXYGEN | |||
| /** | |||
| Used internally by ImageFileFormat - don't use this class directly in your | |||
| application. | |||
| @see ImageFileFormat | |||
| */ | |||
| class GIFLoader | |||
| { | |||
| public: | |||
| GIFLoader (InputStream& in); | |||
| ~GIFLoader(); | |||
| const Image& getImage() const { return image; } | |||
| private: | |||
| Image image; | |||
| InputStream& input; | |||
| uint8 buffer [300]; | |||
| uint8 palette [256][4]; | |||
| bool dataBlockIsZero, fresh, finished; | |||
| int currentBit, lastBit, lastByteIndex; | |||
| int codeSize, setCodeSize; | |||
| int maxCode, maxCodeSize; | |||
| int firstcode, oldcode; | |||
| int clearCode, end_code; | |||
| enum { maxGifCode = 1 << 12 }; | |||
| int table [2] [maxGifCode]; | |||
| int stack [2 * maxGifCode]; | |||
| int *sp; | |||
| bool getSizeFromHeader (int& width, int& height); | |||
| bool readPalette (const int numCols); | |||
| int readDataBlock (unsigned char* dest); | |||
| int processExtension (int type, int& transparent); | |||
| int readLZWByte (bool initialise, int input_code_size); | |||
| int getCode (int code_size, bool initialise); | |||
| bool readImage (int interlace, int transparent); | |||
| static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; } | |||
| GIFLoader (const GIFLoader&); | |||
| GIFLoader& operator= (const GIFLoader&); | |||
| }; | |||
| #endif // DOXYGEN | |||
| #endif // __JUCE_GIFLOADER_JUCEHEADER__ | |||
| /*** End of inlined file: juce_GIFLoader.h ***/ | |||
| class GIFImageFormat : public ImageFileFormat | |||
| { | |||
| public: | |||
| GIFImageFormat() {} | |||
| ~GIFImageFormat() {} | |||
| const String getFormatName() | |||
| { | |||
| return "GIF"; | |||
| } | |||
| bool canUnderstand (InputStream& in) | |||
| { | |||
| const int bytesNeeded = 4; | |||
| char header [bytesNeeded]; | |||
| return (in.read (header, bytesNeeded) == bytesNeeded) | |||
| && header[0] == 'G' | |||
| && header[1] == 'I' | |||
| && header[2] == 'F'; | |||
| } | |||
| const Image decodeImage (InputStream& in) | |||
| { | |||
| const ScopedPointer <GIFLoader> loader (new GIFLoader (in)); | |||
| return loader->getImage(); | |||
| } | |||
| bool writeImageToStream (const Image& /*sourceImage*/, OutputStream& /*destStream*/) | |||
| { | |||
| return false; | |||
| } | |||
| }; | |||
| ImageFileFormat* ImageFileFormat::findImageFormatForStream (InputStream& input) | |||
| { | |||
| static PNGImageFormat png; | |||
| @@ -95976,255 +95887,195 @@ END_JUCE_NAMESPACE | |||
| /*** Start of inlined file: juce_GIFLoader.cpp ***/ | |||
| BEGIN_JUCE_NAMESPACE | |||
| GIFLoader::GIFLoader (InputStream& in) | |||
| : input (in), | |||
| dataBlockIsZero (false), | |||
| fresh (false), | |||
| finished (false) | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| const Image juce_loadWithCoreImage (InputStream& input); | |||
| #else | |||
| class GIFLoader | |||
| { | |||
| currentBit = lastBit = lastByteIndex = 0; | |||
| maxCode = maxCodeSize = codeSize = setCodeSize = 0; | |||
| firstcode = oldcode = 0; | |||
| clearCode = end_code = 0; | |||
| public: | |||
| GIFLoader (InputStream& in) | |||
| : input (in), | |||
| dataBlockIsZero (false), | |||
| fresh (false), | |||
| finished (false) | |||
| { | |||
| currentBit = lastBit = lastByteIndex = 0; | |||
| maxCode = maxCodeSize = codeSize = setCodeSize = 0; | |||
| firstcode = oldcode = 0; | |||
| clearCode = end_code = 0; | |||
| int imageWidth, imageHeight; | |||
| int transparent = -1; | |||
| int imageWidth, imageHeight; | |||
| int transparent = -1; | |||
| if (! getSizeFromHeader (imageWidth, imageHeight)) | |||
| return; | |||
| if (! getSizeFromHeader (imageWidth, imageHeight)) | |||
| return; | |||
| if ((imageWidth <= 0) || (imageHeight <= 0)) | |||
| return; | |||
| if ((imageWidth <= 0) || (imageHeight <= 0)) | |||
| return; | |||
| unsigned char buf [16]; | |||
| if (in.read (buf, 3) != 3) | |||
| return; | |||
| unsigned char buf [16]; | |||
| if (in.read (buf, 3) != 3) | |||
| return; | |||
| int numColours = 2 << (buf[0] & 7); | |||
| int numColours = 2 << (buf[0] & 7); | |||
| if ((buf[0] & 0x80) != 0) | |||
| readPalette (numColours); | |||
| if ((buf[0] & 0x80) != 0) | |||
| readPalette (numColours); | |||
| for (;;) | |||
| { | |||
| if (input.read (buf, 1) != 1) | |||
| break; | |||
| if (buf[0] == ';') | |||
| break; | |||
| if (buf[0] == '!') | |||
| for (;;) | |||
| { | |||
| if (input.read (buf, 1) != 1) | |||
| break; | |||
| if (processExtension (buf[0], transparent) < 0) | |||
| if (input.read (buf, 1) != 1 || buf[0] == ';') | |||
| break; | |||
| continue; | |||
| } | |||
| if (buf[0] != ',') | |||
| continue; | |||
| if (buf[0] == '!') | |||
| { | |||
| if (input.read (buf, 1) != 1) | |||
| break; | |||
| if (input.read (buf, 9) != 9) | |||
| break; | |||
| if (processExtension (buf[0], transparent) < 0) | |||
| break; | |||
| imageWidth = makeWord (buf[4], buf[5]); | |||
| imageHeight = makeWord (buf[6], buf[7]); | |||
| continue; | |||
| } | |||
| numColours = 2 << (buf[8] & 7); | |||
| if (buf[0] != ',') | |||
| continue; | |||
| if ((buf[8] & 0x80) != 0) | |||
| if (! readPalette (numColours)) | |||
| if (input.read (buf, 9) != 9) | |||
| break; | |||
| image = Image ((transparent >= 0) ? Image::ARGB : Image::RGB, | |||
| imageWidth, imageHeight, (transparent >= 0)); | |||
| imageWidth = makeWord (buf[4], buf[5]); | |||
| imageHeight = makeWord (buf[6], buf[7]); | |||
| readImage ((buf[8] & 0x40) != 0, transparent); | |||
| numColours = 2 << (buf[8] & 7); | |||
| break; | |||
| } | |||
| } | |||
| if ((buf[8] & 0x80) != 0) | |||
| if (! readPalette (numColours)) | |||
| break; | |||
| GIFLoader::~GIFLoader() | |||
| { | |||
| } | |||
| image = Image ((transparent >= 0) ? Image::ARGB : Image::RGB, | |||
| imageWidth, imageHeight, (transparent >= 0)); | |||
| bool GIFLoader::getSizeFromHeader (int& w, int& h) | |||
| { | |||
| char b[8]; | |||
| readImage ((buf[8] & 0x40) != 0, transparent); | |||
| if (input.read (b, 6) == 6) | |||
| { | |||
| if ((strncmp ("GIF87a", b, 6) == 0) | |||
| || (strncmp ("GIF89a", b, 6) == 0)) | |||
| { | |||
| if (input.read (b, 4) == 4) | |||
| { | |||
| w = makeWord (b[0], b[1]); | |||
| h = makeWord (b[2], b[3]); | |||
| return true; | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| bool GIFLoader::readPalette (const int numCols) | |||
| { | |||
| unsigned char rgb[4]; | |||
| for (int i = 0; i < numCols; ++i) | |||
| { | |||
| input.read (rgb, 3); | |||
| palette [i][0] = rgb[0]; | |||
| palette [i][1] = rgb[1]; | |||
| palette [i][2] = rgb[2]; | |||
| palette [i][3] = 0xff; | |||
| } | |||
| return true; | |||
| } | |||
| int GIFLoader::readDataBlock (unsigned char* const dest) | |||
| { | |||
| unsigned char n; | |||
| if (input.read (&n, 1) == 1) | |||
| { | |||
| dataBlockIsZero = (n == 0); | |||
| ~GIFLoader() {} | |||
| if (dataBlockIsZero || (input.read (dest, n) == n)) | |||
| return n; | |||
| } | |||
| return -1; | |||
| } | |||
| int GIFLoader::processExtension (const int type, int& transparent) | |||
| { | |||
| unsigned char b [300]; | |||
| int n = 0; | |||
| if (type == 0xf9) | |||
| { | |||
| n = readDataBlock (b); | |||
| if (n < 0) | |||
| return 1; | |||
| Image image; | |||
| if ((b[0] & 0x1) != 0) | |||
| transparent = b[3]; | |||
| } | |||
| private: | |||
| InputStream& input; | |||
| uint8 buffer [300]; | |||
| uint8 palette [256][4]; | |||
| bool dataBlockIsZero, fresh, finished; | |||
| int currentBit, lastBit, lastByteIndex; | |||
| int codeSize, setCodeSize; | |||
| int maxCode, maxCodeSize; | |||
| int firstcode, oldcode; | |||
| int clearCode, end_code; | |||
| enum { maxGifCode = 1 << 12 }; | |||
| int table [2] [maxGifCode]; | |||
| int stack [2 * maxGifCode]; | |||
| int *sp; | |||
| do | |||
| bool getSizeFromHeader (int& w, int& h) | |||
| { | |||
| n = readDataBlock (b); | |||
| } | |||
| while (n > 0); | |||
| char b[8]; | |||
| return n; | |||
| } | |||
| if (input.read (b, 6) == 6) | |||
| { | |||
| if ((strncmp ("GIF87a", b, 6) == 0) | |||
| || (strncmp ("GIF89a", b, 6) == 0)) | |||
| { | |||
| if (input.read (b, 4) == 4) | |||
| { | |||
| w = makeWord (b[0], b[1]); | |||
| h = makeWord (b[2], b[3]); | |||
| return true; | |||
| } | |||
| } | |||
| } | |||
| int GIFLoader::getCode (const int codeSize_, const bool initialise) | |||
| { | |||
| if (initialise) | |||
| { | |||
| currentBit = 0; | |||
| lastBit = 0; | |||
| finished = false; | |||
| return 0; | |||
| return false; | |||
| } | |||
| if ((currentBit + codeSize_) >= lastBit) | |||
| bool readPalette (const int numCols) | |||
| { | |||
| if (finished) | |||
| return -1; | |||
| unsigned char rgb[4]; | |||
| buffer[0] = buffer [lastByteIndex - 2]; | |||
| buffer[1] = buffer [lastByteIndex - 1]; | |||
| const int n = readDataBlock (&buffer[2]); | |||
| for (int i = 0; i < numCols; ++i) | |||
| { | |||
| input.read (rgb, 3); | |||
| if (n == 0) | |||
| finished = true; | |||
| palette [i][0] = rgb[0]; | |||
| palette [i][1] = rgb[1]; | |||
| palette [i][2] = rgb[2]; | |||
| palette [i][3] = 0xff; | |||
| } | |||
| lastByteIndex = 2 + n; | |||
| currentBit = (currentBit - lastBit) + 16; | |||
| lastBit = (2 + n) * 8 ; | |||
| return true; | |||
| } | |||
| int result = 0; | |||
| int i = currentBit; | |||
| for (int j = 0; j < codeSize_; ++j) | |||
| int readDataBlock (unsigned char* dest) | |||
| { | |||
| result |= ((buffer[i >> 3] & (1 << (i & 7))) != 0) << j; | |||
| ++i; | |||
| } | |||
| unsigned char n; | |||
| currentBit += codeSize_; | |||
| if (input.read (&n, 1) == 1) | |||
| { | |||
| dataBlockIsZero = (n == 0); | |||
| return result; | |||
| } | |||
| if (dataBlockIsZero || (input.read (dest, n) == n)) | |||
| return n; | |||
| } | |||
| int GIFLoader::readLZWByte (const bool initialise, const int inputCodeSize) | |||
| { | |||
| int code, incode, i; | |||
| return -1; | |||
| } | |||
| if (initialise) | |||
| int processExtension (const int type, int& transparent) | |||
| { | |||
| setCodeSize = inputCodeSize; | |||
| codeSize = setCodeSize + 1; | |||
| clearCode = 1 << setCodeSize; | |||
| end_code = clearCode + 1; | |||
| maxCodeSize = 2 * clearCode; | |||
| maxCode = clearCode + 2; | |||
| getCode (0, true); | |||
| fresh = true; | |||
| unsigned char b [300]; | |||
| int n = 0; | |||
| for (i = 0; i < clearCode; ++i) | |||
| if (type == 0xf9) | |||
| { | |||
| table[0][i] = 0; | |||
| table[1][i] = i; | |||
| n = readDataBlock (b); | |||
| if (n < 0) | |||
| return 1; | |||
| if ((b[0] & 0x1) != 0) | |||
| transparent = b[3]; | |||
| } | |||
| for (; i < maxGifCode; ++i) | |||
| do | |||
| { | |||
| table[0][i] = 0; | |||
| table[1][i] = 0; | |||
| n = readDataBlock (b); | |||
| } | |||
| while (n > 0); | |||
| sp = stack; | |||
| return 0; | |||
| return n; | |||
| } | |||
| else if (fresh) | |||
| int readLZWByte (const bool initialise, const int inputCodeSize) | |||
| { | |||
| fresh = false; | |||
| int code, incode, i; | |||
| do | |||
| if (initialise) | |||
| { | |||
| firstcode = oldcode | |||
| = getCode (codeSize, false); | |||
| } | |||
| while (firstcode == clearCode); | |||
| setCodeSize = inputCodeSize; | |||
| codeSize = setCodeSize + 1; | |||
| clearCode = 1 << setCodeSize; | |||
| end_code = clearCode + 1; | |||
| maxCodeSize = 2 * clearCode; | |||
| maxCode = clearCode + 2; | |||
| return firstcode; | |||
| } | |||
| getCode (0, true); | |||
| if (sp > stack) | |||
| return *--sp; | |||
| fresh = true; | |||
| while ((code = getCode (codeSize, false)) >= 0) | |||
| { | |||
| if (code == clearCode) | |||
| { | |||
| for (i = 0; i < clearCode; ++i) | |||
| { | |||
| table[0][i] = 0; | |||
| @@ -96237,158 +96088,276 @@ int GIFLoader::readLZWByte (const bool initialise, const int inputCodeSize) | |||
| table[1][i] = 0; | |||
| } | |||
| codeSize = setCodeSize + 1; | |||
| maxCodeSize = 2 * clearCode; | |||
| maxCode = clearCode + 2; | |||
| sp = stack; | |||
| firstcode = oldcode = getCode (codeSize, false); | |||
| return firstcode; | |||
| return 0; | |||
| } | |||
| else if (code == end_code) | |||
| else if (fresh) | |||
| { | |||
| if (dataBlockIsZero) | |||
| return -2; | |||
| unsigned char buf [260]; | |||
| fresh = false; | |||
| int n; | |||
| while ((n = readDataBlock (buf)) > 0) | |||
| {} | |||
| do | |||
| { | |||
| firstcode = oldcode | |||
| = getCode (codeSize, false); | |||
| } | |||
| while (firstcode == clearCode); | |||
| if (n != 0) | |||
| return -2; | |||
| return firstcode; | |||
| } | |||
| incode = code; | |||
| if (sp > stack) | |||
| return *--sp; | |||
| if (code >= maxCode) | |||
| while ((code = getCode (codeSize, false)) >= 0) | |||
| { | |||
| *sp++ = firstcode; | |||
| code = oldcode; | |||
| } | |||
| if (code == clearCode) | |||
| { | |||
| for (i = 0; i < clearCode; ++i) | |||
| { | |||
| table[0][i] = 0; | |||
| table[1][i] = i; | |||
| } | |||
| while (code >= clearCode) | |||
| { | |||
| *sp++ = table[1][code]; | |||
| if (code == table[0][code]) | |||
| return -2; | |||
| for (; i < maxGifCode; ++i) | |||
| { | |||
| table[0][i] = 0; | |||
| table[1][i] = 0; | |||
| } | |||
| code = table[0][code]; | |||
| } | |||
| codeSize = setCodeSize + 1; | |||
| maxCodeSize = 2 * clearCode; | |||
| maxCode = clearCode + 2; | |||
| sp = stack; | |||
| firstcode = oldcode = getCode (codeSize, false); | |||
| return firstcode; | |||
| } | |||
| else if (code == end_code) | |||
| { | |||
| if (dataBlockIsZero) | |||
| return -2; | |||
| *sp++ = firstcode = table[1][code]; | |||
| unsigned char buf [260]; | |||
| if ((code = maxCode) < maxGifCode) | |||
| { | |||
| table[0][code] = oldcode; | |||
| table[1][code] = firstcode; | |||
| ++maxCode; | |||
| int n; | |||
| while ((n = readDataBlock (buf)) > 0) | |||
| {} | |||
| if (n != 0) | |||
| return -2; | |||
| } | |||
| if ((maxCode >= maxCodeSize) | |||
| && (maxCodeSize < maxGifCode)) | |||
| incode = code; | |||
| if (code >= maxCode) | |||
| { | |||
| maxCodeSize <<= 1; | |||
| ++codeSize; | |||
| *sp++ = firstcode; | |||
| code = oldcode; | |||
| } | |||
| } | |||
| oldcode = incode; | |||
| while (code >= clearCode) | |||
| { | |||
| *sp++ = table[1][code]; | |||
| if (code == table[0][code]) | |||
| return -2; | |||
| if (sp > stack) | |||
| return *--sp; | |||
| } | |||
| code = table[0][code]; | |||
| } | |||
| return code; | |||
| } | |||
| *sp++ = firstcode = table[1][code]; | |||
| bool GIFLoader::readImage (const int interlace, const int transparent) | |||
| { | |||
| unsigned char c; | |||
| if ((code = maxCode) < maxGifCode) | |||
| { | |||
| table[0][code] = oldcode; | |||
| table[1][code] = firstcode; | |||
| ++maxCode; | |||
| if (input.read (&c, 1) != 1 | |||
| || readLZWByte (true, c) < 0) | |||
| return false; | |||
| if ((maxCode >= maxCodeSize) | |||
| && (maxCodeSize < maxGifCode)) | |||
| { | |||
| maxCodeSize <<= 1; | |||
| ++codeSize; | |||
| } | |||
| } | |||
| if (transparent >= 0) | |||
| { | |||
| palette [transparent][0] = 0; | |||
| palette [transparent][1] = 0; | |||
| palette [transparent][2] = 0; | |||
| palette [transparent][3] = 0; | |||
| } | |||
| oldcode = incode; | |||
| int index; | |||
| int xpos = 0, ypos = 0, pass = 0; | |||
| if (sp > stack) | |||
| return *--sp; | |||
| } | |||
| const Image::BitmapData destData (image, true); | |||
| uint8* p = destData.data; | |||
| const bool hasAlpha = image.hasAlphaChannel(); | |||
| return code; | |||
| } | |||
| while ((index = readLZWByte (false, c)) >= 0) | |||
| int getCode (const int codeSize_, const bool initialise) | |||
| { | |||
| const uint8* const paletteEntry = palette [index]; | |||
| if (initialise) | |||
| { | |||
| currentBit = 0; | |||
| lastBit = 0; | |||
| finished = false; | |||
| return 0; | |||
| } | |||
| if (hasAlpha) | |||
| if ((currentBit + codeSize_) >= lastBit) | |||
| { | |||
| ((PixelARGB*) p)->setARGB (paletteEntry[3], | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| if (finished) | |||
| return -1; | |||
| buffer[0] = buffer [lastByteIndex - 2]; | |||
| buffer[1] = buffer [lastByteIndex - 1]; | |||
| const int n = readDataBlock (&buffer[2]); | |||
| if (n == 0) | |||
| finished = true; | |||
| ((PixelARGB*) p)->premultiply(); | |||
| lastByteIndex = 2 + n; | |||
| currentBit = (currentBit - lastBit) + 16; | |||
| lastBit = (2 + n) * 8 ; | |||
| } | |||
| else | |||
| int result = 0; | |||
| int i = currentBit; | |||
| for (int j = 0; j < codeSize_; ++j) | |||
| { | |||
| result |= ((buffer[i >> 3] & (1 << (i & 7))) != 0) << j; | |||
| ++i; | |||
| } | |||
| currentBit += codeSize_; | |||
| return result; | |||
| } | |||
| bool readImage (const int interlace, const int transparent) | |||
| { | |||
| unsigned char c; | |||
| if (input.read (&c, 1) != 1 | |||
| || readLZWByte (true, c) < 0) | |||
| return false; | |||
| if (transparent >= 0) | |||
| { | |||
| ((PixelRGB*) p)->setARGB (0, | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| palette [transparent][0] = 0; | |||
| palette [transparent][1] = 0; | |||
| palette [transparent][2] = 0; | |||
| palette [transparent][3] = 0; | |||
| } | |||
| p += destData.pixelStride; | |||
| ++xpos; | |||
| int index; | |||
| int xpos = 0, ypos = 0, pass = 0; | |||
| if (xpos == destData.width) | |||
| const Image::BitmapData destData (image, true); | |||
| uint8* p = destData.data; | |||
| const bool hasAlpha = image.hasAlphaChannel(); | |||
| while ((index = readLZWByte (false, c)) >= 0) | |||
| { | |||
| xpos = 0; | |||
| const uint8* const paletteEntry = palette [index]; | |||
| if (interlace) | |||
| if (hasAlpha) | |||
| { | |||
| switch (pass) | |||
| { | |||
| case 0: | |||
| case 1: ypos += 8; break; | |||
| case 2: ypos += 4; break; | |||
| case 3: ypos += 2; break; | |||
| } | |||
| ((PixelARGB*) p)->setARGB (paletteEntry[3], | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| while (ypos >= destData.height) | |||
| { | |||
| ++pass; | |||
| ((PixelARGB*) p)->premultiply(); | |||
| } | |||
| else | |||
| { | |||
| ((PixelRGB*) p)->setARGB (0, | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| } | |||
| p += destData.pixelStride; | |||
| ++xpos; | |||
| if (xpos == destData.width) | |||
| { | |||
| xpos = 0; | |||
| if (interlace) | |||
| { | |||
| switch (pass) | |||
| { | |||
| case 1: ypos = 4; break; | |||
| case 2: ypos = 2; break; | |||
| case 3: ypos = 1; break; | |||
| default: return true; | |||
| case 0: | |||
| case 1: ypos += 8; break; | |||
| case 2: ypos += 4; break; | |||
| case 3: ypos += 2; break; | |||
| } | |||
| while (ypos >= destData.height) | |||
| { | |||
| ++pass; | |||
| switch (pass) | |||
| { | |||
| case 1: ypos = 4; break; | |||
| case 2: ypos = 2; break; | |||
| case 3: ypos = 1; break; | |||
| default: return true; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| else | |||
| { | |||
| ++ypos; | |||
| else | |||
| { | |||
| ++ypos; | |||
| } | |||
| p = destData.getPixelPointer (xpos, ypos); | |||
| } | |||
| p = destData.getPixelPointer (xpos, ypos); | |||
| if (ypos >= destData.height) | |||
| break; | |||
| } | |||
| if (ypos >= destData.height) | |||
| break; | |||
| return true; | |||
| } | |||
| return true; | |||
| static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; } | |||
| GIFLoader (const GIFLoader&); | |||
| GIFLoader& operator= (const GIFLoader&); | |||
| }; | |||
| #endif | |||
| GIFImageFormat::GIFImageFormat() {} | |||
| GIFImageFormat::~GIFImageFormat() {} | |||
| const String GIFImageFormat::getFormatName() { return "GIF"; } | |||
| bool GIFImageFormat::canUnderstand (InputStream& in) | |||
| { | |||
| char header [4]; | |||
| return (in.read (header, sizeof (header)) == sizeof (header)) | |||
| && header[0] == 'G' | |||
| && header[1] == 'I' | |||
| && header[2] == 'F'; | |||
| } | |||
| const Image GIFImageFormat::decodeImage (InputStream& in) | |||
| { | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| return juce_loadWithCoreImage (in); | |||
| #else | |||
| const ScopedPointer <GIFLoader> loader (new GIFLoader (in)); | |||
| return loader->image; | |||
| #endif | |||
| } | |||
| bool GIFImageFormat::writeImageToStream (const Image& /*sourceImage*/, OutputStream& /*destStream*/) | |||
| { | |||
| jassertfalse; // writing isn't implemented for GIFs! | |||
| return false; | |||
| } | |||
| END_JUCE_NAMESPACE | |||
| @@ -211445,8 +211414,15 @@ bool JPEGImageFormat::canUnderstand (InputStream& in) | |||
| return false; | |||
| } | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| const Image juce_loadWithCoreImage (InputStream& input); | |||
| #endif | |||
| const Image JPEGImageFormat::decodeImage (InputStream& in) | |||
| { | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| return juce_loadWithCoreImage (in); | |||
| #else | |||
| using namespace jpeglibNamespace; | |||
| using namespace JPEGHelpers; | |||
| @@ -211540,6 +211516,7 @@ const Image JPEGImageFormat::decodeImage (InputStream& in) | |||
| } | |||
| return image; | |||
| #endif | |||
| } | |||
| bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | |||
| @@ -237122,8 +237099,15 @@ bool PNGImageFormat::canUnderstand (InputStream& in) | |||
| && header[3] == 'G'; | |||
| } | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| const Image juce_loadWithCoreImage (InputStream& input); | |||
| #endif | |||
| const Image PNGImageFormat::decodeImage (InputStream& in) | |||
| { | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| return juce_loadWithCoreImage (in); | |||
| #else | |||
| using namespace pnglibNamespace; | |||
| Image image; | |||
| @@ -237231,6 +237215,7 @@ const Image PNGImageFormat::decodeImage (InputStream& in) | |||
| } | |||
| return image; | |||
| #endif | |||
| } | |||
| bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | |||
| @@ -266979,6 +266964,43 @@ LowLevelGraphicsContext* CoreGraphicsImage::createLowLevelContext() | |||
| return new CoreGraphicsContext (context, height); | |||
| } | |||
| #if USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| const Image juce_loadWithCoreImage (InputStream& input) | |||
| { | |||
| MemoryBlock data; | |||
| input.readIntoMemoryBlock (data, -1); | |||
| CGDataProviderRef provider = CGDataProviderCreateWithData (0, data.getData(), data.getSize(), 0); | |||
| CGImageSourceRef imageSource = CGImageSourceCreateWithDataProvider (provider, 0); | |||
| CGDataProviderRelease (provider); | |||
| if (imageSource != 0) | |||
| { | |||
| CGImageRef loadedImage = CGImageSourceCreateImageAtIndex (imageSource, 0, 0); | |||
| CFRelease (imageSource); | |||
| if (loadedImage != 0) | |||
| { | |||
| const bool hasAlphaChan = CGImageGetAlphaInfo (loadedImage) != kCGImageAlphaNone; | |||
| Image image (hasAlphaChan ? Image::ARGB : Image::RGB, | |||
| (int) CGImageGetWidth (loadedImage), (int) CGImageGetHeight (loadedImage), | |||
| hasAlphaChan, Image::NativeImage); | |||
| CoreGraphicsImage* const cgImage = dynamic_cast<CoreGraphicsImage*> (image.getSharedImage()); | |||
| jassert (cgImage != 0); // if USE_COREGRAPHICS_RENDERING is set, the CoreGraphicsImage class should have been used. | |||
| CGContextDrawImage (cgImage->context, CGRectMake (0, 0, image.getWidth(), image.getHeight()), loadedImage); | |||
| CGContextFlush (cgImage->context); | |||
| CFRelease (loadedImage); | |||
| return image; | |||
| } | |||
| } | |||
| return Image::null; | |||
| } | |||
| #endif | |||
| #endif | |||
| /*** End of inlined file: juce_mac_CoreGraphicsContext.mm ***/ | |||
| @@ -271610,6 +271632,43 @@ LowLevelGraphicsContext* CoreGraphicsImage::createLowLevelContext() | |||
| return new CoreGraphicsContext (context, height); | |||
| } | |||
| #if USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| const Image juce_loadWithCoreImage (InputStream& input) | |||
| { | |||
| MemoryBlock data; | |||
| input.readIntoMemoryBlock (data, -1); | |||
| CGDataProviderRef provider = CGDataProviderCreateWithData (0, data.getData(), data.getSize(), 0); | |||
| CGImageSourceRef imageSource = CGImageSourceCreateWithDataProvider (provider, 0); | |||
| CGDataProviderRelease (provider); | |||
| if (imageSource != 0) | |||
| { | |||
| CGImageRef loadedImage = CGImageSourceCreateImageAtIndex (imageSource, 0, 0); | |||
| CFRelease (imageSource); | |||
| if (loadedImage != 0) | |||
| { | |||
| const bool hasAlphaChan = CGImageGetAlphaInfo (loadedImage) != kCGImageAlphaNone; | |||
| Image image (hasAlphaChan ? Image::ARGB : Image::RGB, | |||
| (int) CGImageGetWidth (loadedImage), (int) CGImageGetHeight (loadedImage), | |||
| hasAlphaChan, Image::NativeImage); | |||
| CoreGraphicsImage* const cgImage = dynamic_cast<CoreGraphicsImage*> (image.getSharedImage()); | |||
| jassert (cgImage != 0); // if USE_COREGRAPHICS_RENDERING is set, the CoreGraphicsImage class should have been used. | |||
| CGContextDrawImage (cgImage->context, CGRectMake (0, 0, image.getWidth(), image.getHeight()), loadedImage); | |||
| CGContextFlush (cgImage->context); | |||
| CFRelease (loadedImage); | |||
| return image; | |||
| } | |||
| } | |||
| return Image::null; | |||
| } | |||
| #endif | |||
| #endif | |||
| /*** End of inlined file: juce_mac_CoreGraphicsContext.mm ***/ | |||
| @@ -64,7 +64,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 55 | |||
| #define JUCE_BUILDNUMBER 56 | |||
| /** Current Juce version number. | |||
| @@ -60797,7 +60797,7 @@ public: | |||
| }; | |||
| /** | |||
| A type of ImageFileFormat for reading and writing PNG files. | |||
| A subclass of ImageFileFormat for reading and writing PNG files. | |||
| @see ImageFileFormat, JPEGImageFormat | |||
| */ | |||
| @@ -60815,7 +60815,7 @@ public: | |||
| }; | |||
| /** | |||
| A type of ImageFileFormat for reading and writing JPEG files. | |||
| A subclass of ImageFileFormat for reading and writing JPEG files. | |||
| @see ImageFileFormat, PNGImageFormat | |||
| */ | |||
| @@ -60842,6 +60842,24 @@ private: | |||
| float quality; | |||
| }; | |||
| /** | |||
| A subclass of ImageFileFormat for reading GIF files. | |||
| @see ImageFileFormat, PNGImageFormat, JPEGImageFormat | |||
| */ | |||
| class JUCE_API GIFImageFormat : public ImageFileFormat | |||
| { | |||
| public: | |||
| GIFImageFormat(); | |||
| ~GIFImageFormat(); | |||
| const String getFormatName(); | |||
| bool canUnderstand (InputStream& input); | |||
| const Image decodeImage (InputStream& input); | |||
| bool writeImageToStream (const Image& sourceImage, OutputStream& destStream); | |||
| }; | |||
| #endif // __JUCE_IMAGEFILEFORMAT_JUCEHEADER__ | |||
| /*** End of inlined file: juce_ImageFileFormat.h ***/ | |||
| @@ -33,7 +33,7 @@ | |||
| */ | |||
| #define JUCE_MAJOR_VERSION 1 | |||
| #define JUCE_MINOR_VERSION 52 | |||
| #define JUCE_BUILDNUMBER 55 | |||
| #define JUCE_BUILDNUMBER 56 | |||
| /** Current Juce version number. | |||
| @@ -27,260 +27,202 @@ | |||
| BEGIN_JUCE_NAMESPACE | |||
| #include "juce_GIFLoader.h" | |||
| #include "../juce_ImageFileFormat.h" | |||
| #include "../../../../io/streams/juce_InputStream.h" | |||
| #include "../../colour/juce_PixelFormats.h" | |||
| //============================================================================== | |||
| GIFLoader::GIFLoader (InputStream& in) | |||
| : input (in), | |||
| dataBlockIsZero (false), | |||
| fresh (false), | |||
| finished (false) | |||
| { | |||
| currentBit = lastBit = lastByteIndex = 0; | |||
| maxCode = maxCodeSize = codeSize = setCodeSize = 0; | |||
| firstcode = oldcode = 0; | |||
| clearCode = end_code = 0; | |||
| int imageWidth, imageHeight; | |||
| int transparent = -1; | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| const Image juce_loadWithCoreImage (InputStream& input); | |||
| #else | |||
| if (! getSizeFromHeader (imageWidth, imageHeight)) | |||
| return; | |||
| //============================================================================== | |||
| class GIFLoader | |||
| { | |||
| public: | |||
| GIFLoader (InputStream& in) | |||
| : input (in), | |||
| dataBlockIsZero (false), | |||
| fresh (false), | |||
| finished (false) | |||
| { | |||
| currentBit = lastBit = lastByteIndex = 0; | |||
| maxCode = maxCodeSize = codeSize = setCodeSize = 0; | |||
| firstcode = oldcode = 0; | |||
| clearCode = end_code = 0; | |||
| if ((imageWidth <= 0) || (imageHeight <= 0)) | |||
| return; | |||
| int imageWidth, imageHeight; | |||
| int transparent = -1; | |||
| unsigned char buf [16]; | |||
| if (in.read (buf, 3) != 3) | |||
| return; | |||
| if (! getSizeFromHeader (imageWidth, imageHeight)) | |||
| return; | |||
| int numColours = 2 << (buf[0] & 7); | |||
| if ((imageWidth <= 0) || (imageHeight <= 0)) | |||
| return; | |||
| if ((buf[0] & 0x80) != 0) | |||
| readPalette (numColours); | |||
| unsigned char buf [16]; | |||
| if (in.read (buf, 3) != 3) | |||
| return; | |||
| for (;;) | |||
| { | |||
| if (input.read (buf, 1) != 1) | |||
| break; | |||
| int numColours = 2 << (buf[0] & 7); | |||
| if (buf[0] == ';') | |||
| break; | |||
| if ((buf[0] & 0x80) != 0) | |||
| readPalette (numColours); | |||
| if (buf[0] == '!') | |||
| for (;;) | |||
| { | |||
| if (input.read (buf, 1) != 1) | |||
| break; | |||
| if (processExtension (buf[0], transparent) < 0) | |||
| if (input.read (buf, 1) != 1 || buf[0] == ';') | |||
| break; | |||
| continue; | |||
| } | |||
| if (buf[0] != ',') | |||
| continue; | |||
| if (buf[0] == '!') | |||
| { | |||
| if (input.read (buf, 1) != 1) | |||
| break; | |||
| if (input.read (buf, 9) != 9) | |||
| break; | |||
| if (processExtension (buf[0], transparent) < 0) | |||
| break; | |||
| imageWidth = makeWord (buf[4], buf[5]); | |||
| imageHeight = makeWord (buf[6], buf[7]); | |||
| continue; | |||
| } | |||
| numColours = 2 << (buf[8] & 7); | |||
| if (buf[0] != ',') | |||
| continue; | |||
| if ((buf[8] & 0x80) != 0) | |||
| if (! readPalette (numColours)) | |||
| if (input.read (buf, 9) != 9) | |||
| break; | |||
| image = Image ((transparent >= 0) ? Image::ARGB : Image::RGB, | |||
| imageWidth, imageHeight, (transparent >= 0)); | |||
| imageWidth = makeWord (buf[4], buf[5]); | |||
| imageHeight = makeWord (buf[6], buf[7]); | |||
| readImage ((buf[8] & 0x40) != 0, transparent); | |||
| numColours = 2 << (buf[8] & 7); | |||
| break; | |||
| } | |||
| } | |||
| if ((buf[8] & 0x80) != 0) | |||
| if (! readPalette (numColours)) | |||
| break; | |||
| GIFLoader::~GIFLoader() | |||
| { | |||
| } | |||
| image = Image ((transparent >= 0) ? Image::ARGB : Image::RGB, | |||
| imageWidth, imageHeight, (transparent >= 0)); | |||
| bool GIFLoader::getSizeFromHeader (int& w, int& h) | |||
| { | |||
| char b[8]; | |||
| readImage ((buf[8] & 0x40) != 0, transparent); | |||
| if (input.read (b, 6) == 6) | |||
| { | |||
| if ((strncmp ("GIF87a", b, 6) == 0) | |||
| || (strncmp ("GIF89a", b, 6) == 0)) | |||
| { | |||
| if (input.read (b, 4) == 4) | |||
| { | |||
| w = makeWord (b[0], b[1]); | |||
| h = makeWord (b[2], b[3]); | |||
| return true; | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| bool GIFLoader::readPalette (const int numCols) | |||
| { | |||
| unsigned char rgb[4]; | |||
| for (int i = 0; i < numCols; ++i) | |||
| ~GIFLoader() {} | |||
| Image image; | |||
| private: | |||
| InputStream& input; | |||
| uint8 buffer [300]; | |||
| uint8 palette [256][4]; | |||
| bool dataBlockIsZero, fresh, finished; | |||
| int currentBit, lastBit, lastByteIndex; | |||
| int codeSize, setCodeSize; | |||
| int maxCode, maxCodeSize; | |||
| int firstcode, oldcode; | |||
| int clearCode, end_code; | |||
| enum { maxGifCode = 1 << 12 }; | |||
| int table [2] [maxGifCode]; | |||
| int stack [2 * maxGifCode]; | |||
| int *sp; | |||
| bool getSizeFromHeader (int& w, int& h) | |||
| { | |||
| input.read (rgb, 3); | |||
| palette [i][0] = rgb[0]; | |||
| palette [i][1] = rgb[1]; | |||
| palette [i][2] = rgb[2]; | |||
| palette [i][3] = 0xff; | |||
| } | |||
| return true; | |||
| } | |||
| char b[8]; | |||
| int GIFLoader::readDataBlock (unsigned char* const dest) | |||
| { | |||
| unsigned char n; | |||
| if (input.read (&n, 1) == 1) | |||
| { | |||
| dataBlockIsZero = (n == 0); | |||
| if (input.read (b, 6) == 6) | |||
| { | |||
| if ((strncmp ("GIF87a", b, 6) == 0) | |||
| || (strncmp ("GIF89a", b, 6) == 0)) | |||
| { | |||
| if (input.read (b, 4) == 4) | |||
| { | |||
| w = makeWord (b[0], b[1]); | |||
| h = makeWord (b[2], b[3]); | |||
| return true; | |||
| } | |||
| } | |||
| } | |||
| if (dataBlockIsZero || (input.read (dest, n) == n)) | |||
| return n; | |||
| return false; | |||
| } | |||
| return -1; | |||
| } | |||
| int GIFLoader::processExtension (const int type, int& transparent) | |||
| { | |||
| unsigned char b [300]; | |||
| int n = 0; | |||
| if (type == 0xf9) | |||
| bool readPalette (const int numCols) | |||
| { | |||
| n = readDataBlock (b); | |||
| if (n < 0) | |||
| return 1; | |||
| unsigned char rgb[4]; | |||
| if ((b[0] & 0x1) != 0) | |||
| transparent = b[3]; | |||
| } | |||
| do | |||
| { | |||
| n = readDataBlock (b); | |||
| } | |||
| while (n > 0); | |||
| for (int i = 0; i < numCols; ++i) | |||
| { | |||
| input.read (rgb, 3); | |||
| return n; | |||
| } | |||
| palette [i][0] = rgb[0]; | |||
| palette [i][1] = rgb[1]; | |||
| palette [i][2] = rgb[2]; | |||
| palette [i][3] = 0xff; | |||
| } | |||
| int GIFLoader::getCode (const int codeSize_, const bool initialise) | |||
| { | |||
| if (initialise) | |||
| { | |||
| currentBit = 0; | |||
| lastBit = 0; | |||
| finished = false; | |||
| return 0; | |||
| return true; | |||
| } | |||
| if ((currentBit + codeSize_) >= lastBit) | |||
| int readDataBlock (unsigned char* dest) | |||
| { | |||
| if (finished) | |||
| return -1; | |||
| unsigned char n; | |||
| buffer[0] = buffer [lastByteIndex - 2]; | |||
| buffer[1] = buffer [lastByteIndex - 1]; | |||
| const int n = readDataBlock (&buffer[2]); | |||
| if (input.read (&n, 1) == 1) | |||
| { | |||
| dataBlockIsZero = (n == 0); | |||
| if (n == 0) | |||
| finished = true; | |||
| if (dataBlockIsZero || (input.read (dest, n) == n)) | |||
| return n; | |||
| } | |||
| lastByteIndex = 2 + n; | |||
| currentBit = (currentBit - lastBit) + 16; | |||
| lastBit = (2 + n) * 8 ; | |||
| return -1; | |||
| } | |||
| int result = 0; | |||
| int i = currentBit; | |||
| for (int j = 0; j < codeSize_; ++j) | |||
| int processExtension (const int type, int& transparent) | |||
| { | |||
| result |= ((buffer[i >> 3] & (1 << (i & 7))) != 0) << j; | |||
| ++i; | |||
| } | |||
| currentBit += codeSize_; | |||
| unsigned char b [300]; | |||
| int n = 0; | |||
| return result; | |||
| } | |||
| int GIFLoader::readLZWByte (const bool initialise, const int inputCodeSize) | |||
| { | |||
| int code, incode, i; | |||
| if (initialise) | |||
| { | |||
| setCodeSize = inputCodeSize; | |||
| codeSize = setCodeSize + 1; | |||
| clearCode = 1 << setCodeSize; | |||
| end_code = clearCode + 1; | |||
| maxCodeSize = 2 * clearCode; | |||
| maxCode = clearCode + 2; | |||
| getCode (0, true); | |||
| fresh = true; | |||
| for (i = 0; i < clearCode; ++i) | |||
| if (type == 0xf9) | |||
| { | |||
| table[0][i] = 0; | |||
| table[1][i] = i; | |||
| n = readDataBlock (b); | |||
| if (n < 0) | |||
| return 1; | |||
| if ((b[0] & 0x1) != 0) | |||
| transparent = b[3]; | |||
| } | |||
| for (; i < maxGifCode; ++i) | |||
| do | |||
| { | |||
| table[0][i] = 0; | |||
| table[1][i] = 0; | |||
| n = readDataBlock (b); | |||
| } | |||
| while (n > 0); | |||
| sp = stack; | |||
| return 0; | |||
| return n; | |||
| } | |||
| else if (fresh) | |||
| int readLZWByte (const bool initialise, const int inputCodeSize) | |||
| { | |||
| fresh = false; | |||
| int code, incode, i; | |||
| do | |||
| if (initialise) | |||
| { | |||
| firstcode = oldcode | |||
| = getCode (codeSize, false); | |||
| } | |||
| while (firstcode == clearCode); | |||
| setCodeSize = inputCodeSize; | |||
| codeSize = setCodeSize + 1; | |||
| clearCode = 1 << setCodeSize; | |||
| end_code = clearCode + 1; | |||
| maxCodeSize = 2 * clearCode; | |||
| maxCode = clearCode + 2; | |||
| return firstcode; | |||
| } | |||
| getCode (0, true); | |||
| if (sp > stack) | |||
| return *--sp; | |||
| fresh = true; | |||
| while ((code = getCode (codeSize, false)) >= 0) | |||
| { | |||
| if (code == clearCode) | |||
| { | |||
| for (i = 0; i < clearCode; ++i) | |||
| { | |||
| table[0][i] = 0; | |||
| @@ -293,158 +235,277 @@ int GIFLoader::readLZWByte (const bool initialise, const int inputCodeSize) | |||
| table[1][i] = 0; | |||
| } | |||
| codeSize = setCodeSize + 1; | |||
| maxCodeSize = 2 * clearCode; | |||
| maxCode = clearCode + 2; | |||
| sp = stack; | |||
| firstcode = oldcode = getCode (codeSize, false); | |||
| return firstcode; | |||
| return 0; | |||
| } | |||
| else if (code == end_code) | |||
| else if (fresh) | |||
| { | |||
| if (dataBlockIsZero) | |||
| return -2; | |||
| unsigned char buf [260]; | |||
| fresh = false; | |||
| int n; | |||
| while ((n = readDataBlock (buf)) > 0) | |||
| {} | |||
| do | |||
| { | |||
| firstcode = oldcode | |||
| = getCode (codeSize, false); | |||
| } | |||
| while (firstcode == clearCode); | |||
| if (n != 0) | |||
| return -2; | |||
| return firstcode; | |||
| } | |||
| incode = code; | |||
| if (sp > stack) | |||
| return *--sp; | |||
| if (code >= maxCode) | |||
| while ((code = getCode (codeSize, false)) >= 0) | |||
| { | |||
| *sp++ = firstcode; | |||
| code = oldcode; | |||
| } | |||
| if (code == clearCode) | |||
| { | |||
| for (i = 0; i < clearCode; ++i) | |||
| { | |||
| table[0][i] = 0; | |||
| table[1][i] = i; | |||
| } | |||
| while (code >= clearCode) | |||
| { | |||
| *sp++ = table[1][code]; | |||
| if (code == table[0][code]) | |||
| return -2; | |||
| for (; i < maxGifCode; ++i) | |||
| { | |||
| table[0][i] = 0; | |||
| table[1][i] = 0; | |||
| } | |||
| code = table[0][code]; | |||
| } | |||
| codeSize = setCodeSize + 1; | |||
| maxCodeSize = 2 * clearCode; | |||
| maxCode = clearCode + 2; | |||
| sp = stack; | |||
| firstcode = oldcode = getCode (codeSize, false); | |||
| return firstcode; | |||
| *sp++ = firstcode = table[1][code]; | |||
| } | |||
| else if (code == end_code) | |||
| { | |||
| if (dataBlockIsZero) | |||
| return -2; | |||
| if ((code = maxCode) < maxGifCode) | |||
| { | |||
| table[0][code] = oldcode; | |||
| table[1][code] = firstcode; | |||
| ++maxCode; | |||
| unsigned char buf [260]; | |||
| int n; | |||
| while ((n = readDataBlock (buf)) > 0) | |||
| {} | |||
| if (n != 0) | |||
| return -2; | |||
| } | |||
| incode = code; | |||
| if ((maxCode >= maxCodeSize) | |||
| && (maxCodeSize < maxGifCode)) | |||
| if (code >= maxCode) | |||
| { | |||
| maxCodeSize <<= 1; | |||
| ++codeSize; | |||
| *sp++ = firstcode; | |||
| code = oldcode; | |||
| } | |||
| } | |||
| oldcode = incode; | |||
| while (code >= clearCode) | |||
| { | |||
| *sp++ = table[1][code]; | |||
| if (code == table[0][code]) | |||
| return -2; | |||
| if (sp > stack) | |||
| return *--sp; | |||
| } | |||
| code = table[0][code]; | |||
| } | |||
| return code; | |||
| } | |||
| *sp++ = firstcode = table[1][code]; | |||
| bool GIFLoader::readImage (const int interlace, const int transparent) | |||
| { | |||
| unsigned char c; | |||
| if ((code = maxCode) < maxGifCode) | |||
| { | |||
| table[0][code] = oldcode; | |||
| table[1][code] = firstcode; | |||
| ++maxCode; | |||
| if (input.read (&c, 1) != 1 | |||
| || readLZWByte (true, c) < 0) | |||
| return false; | |||
| if ((maxCode >= maxCodeSize) | |||
| && (maxCodeSize < maxGifCode)) | |||
| { | |||
| maxCodeSize <<= 1; | |||
| ++codeSize; | |||
| } | |||
| } | |||
| if (transparent >= 0) | |||
| { | |||
| palette [transparent][0] = 0; | |||
| palette [transparent][1] = 0; | |||
| palette [transparent][2] = 0; | |||
| palette [transparent][3] = 0; | |||
| } | |||
| oldcode = incode; | |||
| int index; | |||
| int xpos = 0, ypos = 0, pass = 0; | |||
| if (sp > stack) | |||
| return *--sp; | |||
| } | |||
| const Image::BitmapData destData (image, true); | |||
| uint8* p = destData.data; | |||
| const bool hasAlpha = image.hasAlphaChannel(); | |||
| return code; | |||
| } | |||
| while ((index = readLZWByte (false, c)) >= 0) | |||
| int getCode (const int codeSize_, const bool initialise) | |||
| { | |||
| const uint8* const paletteEntry = palette [index]; | |||
| if (initialise) | |||
| { | |||
| currentBit = 0; | |||
| lastBit = 0; | |||
| finished = false; | |||
| return 0; | |||
| } | |||
| if (hasAlpha) | |||
| if ((currentBit + codeSize_) >= lastBit) | |||
| { | |||
| ((PixelARGB*) p)->setARGB (paletteEntry[3], | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| if (finished) | |||
| return -1; | |||
| buffer[0] = buffer [lastByteIndex - 2]; | |||
| buffer[1] = buffer [lastByteIndex - 1]; | |||
| const int n = readDataBlock (&buffer[2]); | |||
| if (n == 0) | |||
| finished = true; | |||
| ((PixelARGB*) p)->premultiply(); | |||
| lastByteIndex = 2 + n; | |||
| currentBit = (currentBit - lastBit) + 16; | |||
| lastBit = (2 + n) * 8 ; | |||
| } | |||
| else | |||
| int result = 0; | |||
| int i = currentBit; | |||
| for (int j = 0; j < codeSize_; ++j) | |||
| { | |||
| ((PixelRGB*) p)->setARGB (0, | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| result |= ((buffer[i >> 3] & (1 << (i & 7))) != 0) << j; | |||
| ++i; | |||
| } | |||
| p += destData.pixelStride; | |||
| ++xpos; | |||
| currentBit += codeSize_; | |||
| if (xpos == destData.width) | |||
| return result; | |||
| } | |||
| bool readImage (const int interlace, const int transparent) | |||
| { | |||
| unsigned char c; | |||
| if (input.read (&c, 1) != 1 | |||
| || readLZWByte (true, c) < 0) | |||
| return false; | |||
| if (transparent >= 0) | |||
| { | |||
| xpos = 0; | |||
| palette [transparent][0] = 0; | |||
| palette [transparent][1] = 0; | |||
| palette [transparent][2] = 0; | |||
| palette [transparent][3] = 0; | |||
| } | |||
| if (interlace) | |||
| int index; | |||
| int xpos = 0, ypos = 0, pass = 0; | |||
| const Image::BitmapData destData (image, true); | |||
| uint8* p = destData.data; | |||
| const bool hasAlpha = image.hasAlphaChannel(); | |||
| while ((index = readLZWByte (false, c)) >= 0) | |||
| { | |||
| const uint8* const paletteEntry = palette [index]; | |||
| if (hasAlpha) | |||
| { | |||
| switch (pass) | |||
| { | |||
| case 0: | |||
| case 1: ypos += 8; break; | |||
| case 2: ypos += 4; break; | |||
| case 3: ypos += 2; break; | |||
| } | |||
| ((PixelARGB*) p)->setARGB (paletteEntry[3], | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| while (ypos >= destData.height) | |||
| { | |||
| ++pass; | |||
| ((PixelARGB*) p)->premultiply(); | |||
| } | |||
| else | |||
| { | |||
| ((PixelRGB*) p)->setARGB (0, | |||
| paletteEntry[0], | |||
| paletteEntry[1], | |||
| paletteEntry[2]); | |||
| } | |||
| p += destData.pixelStride; | |||
| ++xpos; | |||
| if (xpos == destData.width) | |||
| { | |||
| xpos = 0; | |||
| if (interlace) | |||
| { | |||
| switch (pass) | |||
| { | |||
| case 1: ypos = 4; break; | |||
| case 2: ypos = 2; break; | |||
| case 3: ypos = 1; break; | |||
| default: return true; | |||
| case 0: | |||
| case 1: ypos += 8; break; | |||
| case 2: ypos += 4; break; | |||
| case 3: ypos += 2; break; | |||
| } | |||
| while (ypos >= destData.height) | |||
| { | |||
| ++pass; | |||
| switch (pass) | |||
| { | |||
| case 1: ypos = 4; break; | |||
| case 2: ypos = 2; break; | |||
| case 3: ypos = 1; break; | |||
| default: return true; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| else | |||
| { | |||
| ++ypos; | |||
| else | |||
| { | |||
| ++ypos; | |||
| } | |||
| p = destData.getPixelPointer (xpos, ypos); | |||
| } | |||
| p = destData.getPixelPointer (xpos, ypos); | |||
| if (ypos >= destData.height) | |||
| break; | |||
| } | |||
| if (ypos >= destData.height) | |||
| break; | |||
| return true; | |||
| } | |||
| return true; | |||
| static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; } | |||
| GIFLoader (const GIFLoader&); | |||
| GIFLoader& operator= (const GIFLoader&); | |||
| }; | |||
| #endif | |||
| //============================================================================== | |||
| GIFImageFormat::GIFImageFormat() {} | |||
| GIFImageFormat::~GIFImageFormat() {} | |||
| const String GIFImageFormat::getFormatName() { return "GIF"; } | |||
| bool GIFImageFormat::canUnderstand (InputStream& in) | |||
| { | |||
| char header [4]; | |||
| return (in.read (header, sizeof (header)) == sizeof (header)) | |||
| && header[0] == 'G' | |||
| && header[1] == 'I' | |||
| && header[2] == 'F'; | |||
| } | |||
| const Image GIFImageFormat::decodeImage (InputStream& in) | |||
| { | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| return juce_loadWithCoreImage (in); | |||
| #else | |||
| const ScopedPointer <GIFLoader> loader (new GIFLoader (in)); | |||
| return loader->image; | |||
| #endif | |||
| } | |||
| bool GIFImageFormat::writeImageToStream (const Image& /*sourceImage*/, OutputStream& /*destStream*/) | |||
| { | |||
| jassertfalse; // writing isn't implemented for GIFs! | |||
| return false; | |||
| } | |||
| @@ -1,81 +0,0 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library - "Jules' Utility Class Extensions" | |||
| Copyright 2004-10 by Raw Material Software Ltd. | |||
| ------------------------------------------------------------------------------ | |||
| JUCE can be redistributed and/or modified under the terms of the GNU General | |||
| Public License (Version 2), as published by the Free Software Foundation. | |||
| A copy of the license is included in the JUCE distribution, or can be found | |||
| online at www.gnu.org/licenses. | |||
| JUCE is distributed in the hope that it will be useful, but WITHOUT ANY | |||
| WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR | |||
| A PARTICULAR PURPOSE. See the GNU General Public License for more details. | |||
| ------------------------------------------------------------------------------ | |||
| To release a closed-source product which uses JUCE, commercial licenses are | |||
| available: visit www.rawmaterialsoftware.com/juce for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef __JUCE_GIFLOADER_JUCEHEADER__ | |||
| #define __JUCE_GIFLOADER_JUCEHEADER__ | |||
| #ifndef DOXYGEN | |||
| #include "../../../../io/streams/juce_InputStream.h" | |||
| #include "../juce_Image.h" | |||
| //============================================================================== | |||
| /** | |||
| Used internally by ImageFileFormat - don't use this class directly in your | |||
| application. | |||
| @see ImageFileFormat | |||
| */ | |||
| class GIFLoader | |||
| { | |||
| public: | |||
| GIFLoader (InputStream& in); | |||
| ~GIFLoader(); | |||
| const Image& getImage() const { return image; } | |||
| private: | |||
| Image image; | |||
| InputStream& input; | |||
| uint8 buffer [300]; | |||
| uint8 palette [256][4]; | |||
| bool dataBlockIsZero, fresh, finished; | |||
| int currentBit, lastBit, lastByteIndex; | |||
| int codeSize, setCodeSize; | |||
| int maxCode, maxCodeSize; | |||
| int firstcode, oldcode; | |||
| int clearCode, end_code; | |||
| enum { maxGifCode = 1 << 12 }; | |||
| int table [2] [maxGifCode]; | |||
| int stack [2 * maxGifCode]; | |||
| int *sp; | |||
| bool getSizeFromHeader (int& width, int& height); | |||
| bool readPalette (const int numCols); | |||
| int readDataBlock (unsigned char* dest); | |||
| int processExtension (int type, int& transparent); | |||
| int readLZWByte (bool initialise, int input_code_size); | |||
| int getCode (int code_size, bool initialise); | |||
| bool readImage (int interlace, int transparent); | |||
| static inline int makeWord (const uint8 a, const uint8 b) { return (b << 8) | a; } | |||
| GIFLoader (const GIFLoader&); | |||
| GIFLoader& operator= (const GIFLoader&); | |||
| }; | |||
| #endif // DOXYGEN | |||
| #endif // __JUCE_GIFLOADER_JUCEHEADER__ | |||
| @@ -249,8 +249,15 @@ bool JPEGImageFormat::canUnderstand (InputStream& in) | |||
| return false; | |||
| } | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| const Image juce_loadWithCoreImage (InputStream& input); | |||
| #endif | |||
| const Image JPEGImageFormat::decodeImage (InputStream& in) | |||
| { | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| return juce_loadWithCoreImage (in); | |||
| #else | |||
| using namespace jpeglibNamespace; | |||
| using namespace JPEGHelpers; | |||
| @@ -344,6 +351,7 @@ const Image JPEGImageFormat::decodeImage (InputStream& in) | |||
| } | |||
| return image; | |||
| #endif | |||
| } | |||
| bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | |||
| @@ -148,8 +148,15 @@ bool PNGImageFormat::canUnderstand (InputStream& in) | |||
| && header[3] == 'G'; | |||
| } | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| const Image juce_loadWithCoreImage (InputStream& input); | |||
| #endif | |||
| const Image PNGImageFormat::decodeImage (InputStream& in) | |||
| { | |||
| #if (JUCE_MAC || JUCE_IOS) && USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| return juce_loadWithCoreImage (in); | |||
| #else | |||
| using namespace pnglibNamespace; | |||
| Image image; | |||
| @@ -257,6 +264,7 @@ const Image PNGImageFormat::decodeImage (InputStream& in) | |||
| } | |||
| return image; | |||
| #endif | |||
| } | |||
| bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | |||
| @@ -31,43 +31,6 @@ BEGIN_JUCE_NAMESPACE | |||
| #include "../../../io/streams/juce_MemoryInputStream.h" | |||
| #include "../../../io/files/juce_FileInputStream.h" | |||
| #include "../../../io/streams/juce_BufferedInputStream.h" | |||
| #include "image_file_formats/juce_GIFLoader.h" | |||
| //============================================================================== | |||
| class GIFImageFormat : public ImageFileFormat | |||
| { | |||
| public: | |||
| GIFImageFormat() {} | |||
| ~GIFImageFormat() {} | |||
| const String getFormatName() | |||
| { | |||
| return "GIF"; | |||
| } | |||
| bool canUnderstand (InputStream& in) | |||
| { | |||
| const int bytesNeeded = 4; | |||
| char header [bytesNeeded]; | |||
| return (in.read (header, bytesNeeded) == bytesNeeded) | |||
| && header[0] == 'G' | |||
| && header[1] == 'I' | |||
| && header[2] == 'F'; | |||
| } | |||
| const Image decodeImage (InputStream& in) | |||
| { | |||
| const ScopedPointer <GIFLoader> loader (new GIFLoader (in)); | |||
| return loader->getImage(); | |||
| } | |||
| bool writeImageToStream (const Image& /*sourceImage*/, OutputStream& /*destStream*/) | |||
| { | |||
| return false; | |||
| } | |||
| }; | |||
| //============================================================================== | |||
| @@ -138,7 +138,7 @@ public: | |||
| //============================================================================== | |||
| /** | |||
| A type of ImageFileFormat for reading and writing PNG files. | |||
| A subclass of ImageFileFormat for reading and writing PNG files. | |||
| @see ImageFileFormat, JPEGImageFormat | |||
| */ | |||
| @@ -159,7 +159,7 @@ public: | |||
| //============================================================================== | |||
| /** | |||
| A type of ImageFileFormat for reading and writing JPEG files. | |||
| A subclass of ImageFileFormat for reading and writing JPEG files. | |||
| @see ImageFileFormat, PNGImageFormat | |||
| */ | |||
| @@ -188,6 +188,25 @@ private: | |||
| float quality; | |||
| }; | |||
| //============================================================================== | |||
| /** | |||
| A subclass of ImageFileFormat for reading GIF files. | |||
| @see ImageFileFormat, PNGImageFormat, JPEGImageFormat | |||
| */ | |||
| class JUCE_API GIFImageFormat : public ImageFileFormat | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| GIFImageFormat(); | |||
| ~GIFImageFormat(); | |||
| //============================================================================== | |||
| const String getFormatName(); | |||
| bool canUnderstand (InputStream& input); | |||
| const Image decodeImage (InputStream& input); | |||
| bool writeImageToStream (const Image& sourceImage, OutputStream& destStream); | |||
| }; | |||
| #endif // __JUCE_IMAGEFILEFORMAT_JUCEHEADER__ | |||
| @@ -770,4 +770,42 @@ LowLevelGraphicsContext* CoreGraphicsImage::createLowLevelContext() | |||
| return new CoreGraphicsContext (context, height); | |||
| } | |||
| //============================================================================== | |||
| #if USE_COREGRAPHICS_RENDERING && ! DONT_USE_COREIMAGE_LOADER | |||
| const Image juce_loadWithCoreImage (InputStream& input) | |||
| { | |||
| MemoryBlock data; | |||
| input.readIntoMemoryBlock (data, -1); | |||
| CGDataProviderRef provider = CGDataProviderCreateWithData (0, data.getData(), data.getSize(), 0); | |||
| CGImageSourceRef imageSource = CGImageSourceCreateWithDataProvider (provider, 0); | |||
| CGDataProviderRelease (provider); | |||
| if (imageSource != 0) | |||
| { | |||
| CGImageRef loadedImage = CGImageSourceCreateImageAtIndex (imageSource, 0, 0); | |||
| CFRelease (imageSource); | |||
| if (loadedImage != 0) | |||
| { | |||
| const bool hasAlphaChan = CGImageGetAlphaInfo (loadedImage) != kCGImageAlphaNone; | |||
| Image image (hasAlphaChan ? Image::ARGB : Image::RGB, | |||
| (int) CGImageGetWidth (loadedImage), (int) CGImageGetHeight (loadedImage), | |||
| hasAlphaChan, Image::NativeImage); | |||
| CoreGraphicsImage* const cgImage = dynamic_cast<CoreGraphicsImage*> (image.getSharedImage()); | |||
| jassert (cgImage != 0); // if USE_COREGRAPHICS_RENDERING is set, the CoreGraphicsImage class should have been used. | |||
| CGContextDrawImage (cgImage->context, CGRectMake (0, 0, image.getWidth(), image.getHeight()), loadedImage); | |||
| CGContextFlush (cgImage->context); | |||
| CFRelease (loadedImage); | |||
| return image; | |||
| } | |||
| } | |||
| return Image::null; | |||
| } | |||
| #endif | |||
| #endif | |||