Browse Source

Made image-loading use CoreImage on the Mac and iOS.

tags/2021-05-28
Julian Storer 15 years ago
parent
commit
90b74fcdee
18 changed files with 893 additions and 813 deletions
  1. +0
    -2
      Builds/MacOSX/Juce.xcodeproj/project.pbxproj
  2. +0
    -1
      Builds/VisualStudio2005/Juce.vcproj
  3. +0
    -1
      Builds/VisualStudio2008/Juce.vcproj
  4. +0
    -1
      Builds/VisualStudio2008_DLL/Juce.vcproj
  5. +0
    -1
      Builds/VisualStudio2010/Juce.vcxproj
  6. +0
    -3
      Builds/VisualStudio2010/Juce.vcxproj.filters
  7. +0
    -2
      Builds/iPhone/Juce.xcodeproj/project.pbxproj
  8. +0
    -2
      Juce.jucer
  9. +440
    -381
      juce_amalgamated.cpp
  10. +21
    -3
      juce_amalgamated.h
  11. +1
    -1
      src/core/juce_StandardHeader.h
  12. +356
    -295
      src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp
  13. +0
    -81
      src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.h
  14. +8
    -0
      src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp
  15. +8
    -0
      src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp
  16. +0
    -37
      src/gui/graphics/imaging/juce_ImageFileFormat.cpp
  17. +21
    -2
      src/gui/graphics/imaging/juce_ImageFileFormat.h
  18. +38
    -0
      src/native/mac/juce_mac_CoreGraphicsContext.mm

+ 0
- 2
Builds/MacOSX/Juce.xcodeproj/project.pbxproj View File

@@ -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 = (


+ 0
- 1
Builds/VisualStudio2005/Juce.vcproj View File

@@ -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>


+ 0
- 1
Builds/VisualStudio2008/Juce.vcproj View File

@@ -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>


+ 0
- 1
Builds/VisualStudio2008_DLL/Juce.vcproj View File

@@ -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>


+ 0
- 1
Builds/VisualStudio2010/Juce.vcxproj View File

@@ -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"/>


+ 0
- 3
Builds/VisualStudio2010/Juce.vcxproj.filters View File

@@ -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>


+ 0
- 2
Builds/iPhone/Juce.xcodeproj/project.pbxproj View File

@@ -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 = (


+ 0
- 2
Juce.jucer View File

@@ -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"


+ 440
- 381
juce_amalgamated.cpp View File

@@ -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 ***/



+ 21
- 3
juce_amalgamated.h View File

@@ -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 ***/



+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -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.


+ 356
- 295
src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.cpp View File

@@ -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;
}


+ 0
- 81
src/gui/graphics/imaging/image_file_formats/juce_GIFLoader.h View File

@@ -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__

+ 8
- 0
src/gui/graphics/imaging/image_file_formats/juce_JPEGLoader.cpp View File

@@ -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)


+ 8
- 0
src/gui/graphics/imaging/image_file_formats/juce_PNGLoader.cpp View File

@@ -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)


+ 0
- 37
src/gui/graphics/imaging/juce_ImageFileFormat.cpp View File

@@ -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;
}
};
//==============================================================================


+ 21
- 2
src/gui/graphics/imaging/juce_ImageFileFormat.h View File

@@ -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__

+ 38
- 0
src/native/mac/juce_mac_CoreGraphicsContext.mm View File

@@ -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

Loading…
Cancel
Save