| @@ -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; }; | 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; }; | 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; }; | 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; }; | 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; }; | 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; }; | 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>"; }; | 54D9BBB69BDA3837240F7749 ); name = geometry; sourceTree = "<group>"; }; | ||||
| D71FD838B3FD1536FCA839A4 = { isa = PBXGroup; children = ( | D71FD838B3FD1536FCA839A4 = { isa = PBXGroup; children = ( | ||||
| 0F1C5770B363EF7DF64A876A, | 0F1C5770B363EF7DF64A876A, | ||||
| EFBDB957445BD56D0458535D, | |||||
| 6619D27E74F623B1E8CE8F71, | 6619D27E74F623B1E8CE8F71, | ||||
| EAF0F2EAB230F7539B91A7FB ); name = image_file_formats; sourceTree = "<group>"; }; | EAF0F2EAB230F7539B91A7FB ); name = image_file_formats; sourceTree = "<group>"; }; | ||||
| 36A6F90D0C87EA1D8FBE9EC0 = { isa = PBXGroup; children = ( | 36A6F90D0C87EA1D8FBE9EC0 = { isa = PBXGroup; children = ( | ||||
| @@ -766,7 +766,6 @@ | |||||
| <Filter Name="imaging"> | <Filter Name="imaging"> | ||||
| <Filter Name="image_file_formats"> | <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.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_JPEGLoader.cpp"/> | ||||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_PNGLoader.cpp"/> | <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_PNGLoader.cpp"/> | ||||
| </Filter> | </Filter> | ||||
| @@ -766,7 +766,6 @@ | |||||
| <Filter Name="imaging"> | <Filter Name="imaging"> | ||||
| <Filter Name="image_file_formats"> | <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.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_JPEGLoader.cpp"/> | ||||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_PNGLoader.cpp"/> | <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_PNGLoader.cpp"/> | ||||
| </Filter> | </Filter> | ||||
| @@ -768,7 +768,6 @@ | |||||
| <Filter Name="imaging"> | <Filter Name="imaging"> | ||||
| <Filter Name="image_file_formats"> | <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.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_JPEGLoader.cpp"/> | ||||
| <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_PNGLoader.cpp"/> | <File RelativePath="..\..\src\gui\graphics\imaging\image_file_formats\juce_PNGLoader.cpp"/> | ||||
| </Filter> | </Filter> | ||||
| @@ -707,7 +707,6 @@ | |||||
| <ClInclude Include="..\..\src\gui\graphics\geometry\juce_Rectangle.h"/> | <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_RectangleList.h"/> | ||||
| <ClInclude Include="..\..\src\gui\graphics\geometry\juce_RelativeCoordinate.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_CameraDevice.h"/> | ||||
| <ClInclude Include="..\..\src\gui\graphics\imaging\juce_Image.h"/> | <ClInclude Include="..\..\src\gui\graphics\imaging\juce_Image.h"/> | ||||
| <ClInclude Include="..\..\src\gui\graphics\imaging\juce_ImageCache.h"/> | <ClInclude Include="..\..\src\gui\graphics\imaging\juce_ImageCache.h"/> | ||||
| @@ -2043,9 +2043,6 @@ | |||||
| <ClInclude Include="..\..\src\gui\graphics\geometry\juce_RelativeCoordinate.h"> | <ClInclude Include="..\..\src\gui\graphics\geometry\juce_RelativeCoordinate.h"> | ||||
| <Filter>Juce\Source\gui\graphics\geometry</Filter> | <Filter>Juce\Source\gui\graphics\geometry</Filter> | ||||
| </ClInclude> | </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"> | <ClInclude Include="..\..\src\gui\graphics\imaging\juce_CameraDevice.h"> | ||||
| <Filter>Juce\Source\gui\graphics\imaging</Filter> | <Filter>Juce\Source\gui\graphics\imaging</Filter> | ||||
| </ClInclude> | </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; }; | 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; }; | 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; }; | 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; }; | 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; }; | 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; }; | 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>"; }; | 54D9BBB69BDA3837240F7749 ); name = geometry; sourceTree = "<group>"; }; | ||||
| D71FD838B3FD1536FCA839A4 = { isa = PBXGroup; children = ( | D71FD838B3FD1536FCA839A4 = { isa = PBXGroup; children = ( | ||||
| 0F1C5770B363EF7DF64A876A, | 0F1C5770B363EF7DF64A876A, | ||||
| EFBDB957445BD56D0458535D, | |||||
| 6619D27E74F623B1E8CE8F71, | 6619D27E74F623B1E8CE8F71, | ||||
| EAF0F2EAB230F7539B91A7FB ); name = image_file_formats; sourceTree = "<group>"; }; | EAF0F2EAB230F7539B91A7FB ); name = image_file_formats; sourceTree = "<group>"; }; | ||||
| 36A6F90D0C87EA1D8FBE9EC0 = { isa = PBXGroup; children = ( | 36A6F90D0C87EA1D8FBE9EC0 = { isa = PBXGroup; children = ( | ||||
| @@ -1129,8 +1129,6 @@ | |||||
| <GROUP id="UpDEgf4Fr" name="image_file_formats"> | <GROUP id="UpDEgf4Fr" name="image_file_formats"> | ||||
| <FILE id="82P2bqp" name="juce_GIFLoader.cpp" compile="1" resource="0" | <FILE id="82P2bqp" name="juce_GIFLoader.cpp" compile="1" resource="0" | ||||
| file="src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp"/> | 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 id="SuwswXcCp" name="juce_JPEGLoader.cpp" compile="1" resource="0" | ||||
| file="src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp"/> | file="src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp"/> | ||||
| <FILE id="GbTEpJRyd" name="juce_PNGLoader.cpp" compile="1" resource="0" | <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 ***/ | /*** Start of inlined file: juce_ImageFileFormat.cpp ***/ | ||||
| BEGIN_JUCE_NAMESPACE | 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) | ImageFileFormat* ImageFileFormat::findImageFormatForStream (InputStream& input) | ||||
| { | { | ||||
| static PNGImageFormat png; | static PNGImageFormat png; | ||||
| @@ -95976,255 +95887,195 @@ END_JUCE_NAMESPACE | |||||
| /*** Start of inlined file: juce_GIFLoader.cpp ***/ | /*** Start of inlined file: juce_GIFLoader.cpp ***/ | ||||
| BEGIN_JUCE_NAMESPACE | 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; | 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; | 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) | for (i = 0; i < clearCode; ++i) | ||||
| { | { | ||||
| table[0][i] = 0; | table[0][i] = 0; | ||||
| @@ -96237,158 +96088,276 @@ int GIFLoader::readLZWByte (const bool initialise, const int inputCodeSize) | |||||
| table[1][i] = 0; | table[1][i] = 0; | ||||
| } | } | ||||
| codeSize = setCodeSize + 1; | |||||
| maxCodeSize = 2 * clearCode; | |||||
| maxCode = clearCode + 2; | |||||
| sp = stack; | 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) | 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 | END_JUCE_NAMESPACE | ||||
| @@ -211445,8 +211414,15 @@ bool JPEGImageFormat::canUnderstand (InputStream& in) | |||||
| return false; | 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) | 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 jpeglibNamespace; | ||||
| using namespace JPEGHelpers; | using namespace JPEGHelpers; | ||||
| @@ -211540,6 +211516,7 @@ const Image JPEGImageFormat::decodeImage (InputStream& in) | |||||
| } | } | ||||
| return image; | return image; | ||||
| #endif | |||||
| } | } | ||||
| bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | ||||
| @@ -237122,8 +237099,15 @@ bool PNGImageFormat::canUnderstand (InputStream& in) | |||||
| && header[3] == 'G'; | && 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) | 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; | using namespace pnglibNamespace; | ||||
| Image image; | Image image; | ||||
| @@ -237231,6 +237215,7 @@ const Image PNGImageFormat::decodeImage (InputStream& in) | |||||
| } | } | ||||
| return image; | return image; | ||||
| #endif | |||||
| } | } | ||||
| bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | ||||
| @@ -266979,6 +266964,43 @@ LowLevelGraphicsContext* CoreGraphicsImage::createLowLevelContext() | |||||
| return new CoreGraphicsContext (context, height); | 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 | #endif | ||||
| /*** End of inlined file: juce_mac_CoreGraphicsContext.mm ***/ | /*** End of inlined file: juce_mac_CoreGraphicsContext.mm ***/ | ||||
| @@ -271610,6 +271632,43 @@ LowLevelGraphicsContext* CoreGraphicsImage::createLowLevelContext() | |||||
| return new CoreGraphicsContext (context, height); | 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 | #endif | ||||
| /*** End of inlined file: juce_mac_CoreGraphicsContext.mm ***/ | /*** End of inlined file: juce_mac_CoreGraphicsContext.mm ***/ | ||||
| @@ -64,7 +64,7 @@ | |||||
| */ | */ | ||||
| #define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
| #define JUCE_MINOR_VERSION 52 | #define JUCE_MINOR_VERSION 52 | ||||
| #define JUCE_BUILDNUMBER 55 | |||||
| #define JUCE_BUILDNUMBER 56 | |||||
| /** Current Juce version number. | /** 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 | @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 | @see ImageFileFormat, PNGImageFormat | ||||
| */ | */ | ||||
| @@ -60842,6 +60842,24 @@ private: | |||||
| float quality; | 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__ | #endif // __JUCE_IMAGEFILEFORMAT_JUCEHEADER__ | ||||
| /*** End of inlined file: juce_ImageFileFormat.h ***/ | /*** End of inlined file: juce_ImageFileFormat.h ***/ | ||||
| @@ -33,7 +33,7 @@ | |||||
| */ | */ | ||||
| #define JUCE_MAJOR_VERSION 1 | #define JUCE_MAJOR_VERSION 1 | ||||
| #define JUCE_MINOR_VERSION 52 | #define JUCE_MINOR_VERSION 52 | ||||
| #define JUCE_BUILDNUMBER 55 | |||||
| #define JUCE_BUILDNUMBER 56 | |||||
| /** Current Juce version number. | /** Current Juce version number. | ||||
| @@ -27,260 +27,202 @@ | |||||
| BEGIN_JUCE_NAMESPACE | BEGIN_JUCE_NAMESPACE | ||||
| #include "juce_GIFLoader.h" | |||||
| #include "../juce_ImageFileFormat.h" | |||||
| #include "../../../../io/streams/juce_InputStream.h" | |||||
| #include "../../colour/juce_PixelFormats.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; | 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; | 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) | for (i = 0; i < clearCode; ++i) | ||||
| { | { | ||||
| table[0][i] = 0; | table[0][i] = 0; | ||||
| @@ -293,158 +235,277 @@ int GIFLoader::readLZWByte (const bool initialise, const int inputCodeSize) | |||||
| table[1][i] = 0; | table[1][i] = 0; | ||||
| } | } | ||||
| codeSize = setCodeSize + 1; | |||||
| maxCodeSize = 2 * clearCode; | |||||
| maxCode = clearCode + 2; | |||||
| sp = stack; | 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) | 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; | 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) | 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 jpeglibNamespace; | ||||
| using namespace JPEGHelpers; | using namespace JPEGHelpers; | ||||
| @@ -344,6 +351,7 @@ const Image JPEGImageFormat::decodeImage (InputStream& in) | |||||
| } | } | ||||
| return image; | return image; | ||||
| #endif | |||||
| } | } | ||||
| bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | bool JPEGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | ||||
| @@ -148,8 +148,15 @@ bool PNGImageFormat::canUnderstand (InputStream& in) | |||||
| && header[3] == 'G'; | && 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) | 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; | using namespace pnglibNamespace; | ||||
| Image image; | Image image; | ||||
| @@ -257,6 +264,7 @@ const Image PNGImageFormat::decodeImage (InputStream& in) | |||||
| } | } | ||||
| return image; | return image; | ||||
| #endif | |||||
| } | } | ||||
| bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out) | ||||
| @@ -31,43 +31,6 @@ BEGIN_JUCE_NAMESPACE | |||||
| #include "../../../io/streams/juce_MemoryInputStream.h" | #include "../../../io/streams/juce_MemoryInputStream.h" | ||||
| #include "../../../io/files/juce_FileInputStream.h" | #include "../../../io/files/juce_FileInputStream.h" | ||||
| #include "../../../io/streams/juce_BufferedInputStream.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 | @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 | @see ImageFileFormat, PNGImageFormat | ||||
| */ | */ | ||||
| @@ -188,6 +188,25 @@ private: | |||||
| float quality; | 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__ | #endif // __JUCE_IMAGEFILEFORMAT_JUCEHEADER__ | ||||
| @@ -770,4 +770,42 @@ LowLevelGraphicsContext* CoreGraphicsImage::createLowLevelContext() | |||||
| return new CoreGraphicsContext (context, height); | 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 | #endif | ||||