1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-28 02:30:05 +00:00

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

This commit is contained in:
Julian Storer 2010-08-26 18:25:24 +01:00
parent 4e68bd517b
commit 90b74fcdee
18 changed files with 991 additions and 911 deletions

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

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>

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>

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>

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

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>

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

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"

File diff suppressed because it is too large Load diff

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

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.

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)
#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;
int imageWidth, imageHeight;
int transparent = -1;
if (! getSizeFromHeader (imageWidth, imageHeight))
return;
if ((imageWidth <= 0) || (imageHeight <= 0))
return;
unsigned char buf [16];
if (in.read (buf, 3) != 3)
return;
int numColours = 2 << (buf[0] & 7);
if ((buf[0] & 0x80) != 0)
readPalette (numColours);
for (;;)
public:
GIFLoader (InputStream& in)
: input (in),
dataBlockIsZero (false),
fresh (false),
finished (false)
{
if (input.read (buf, 1) != 1)
break;
currentBit = lastBit = lastByteIndex = 0;
maxCode = maxCodeSize = codeSize = setCodeSize = 0;
firstcode = oldcode = 0;
clearCode = end_code = 0;
if (buf[0] == ';')
break;
int imageWidth, imageHeight;
int transparent = -1;
if (buf[0] == '!')
if (! getSizeFromHeader (imageWidth, imageHeight))
return;
if ((imageWidth <= 0) || (imageHeight <= 0))
return;
unsigned char buf [16];
if (in.read (buf, 3) != 3)
return;
int numColours = 2 << (buf[0] & 7);
if ((buf[0] & 0x80) != 0)
readPalette (numColours);
for (;;)
{
if (input.read (buf, 1) != 1)
if (input.read (buf, 1) != 1 || buf[0] == ';')
break;
if (processExtension (buf[0], transparent) < 0)
break;
continue;
}
if (buf[0] != ',')
continue;
if (input.read (buf, 9) != 9)
break;
imageWidth = makeWord (buf[4], buf[5]);
imageHeight = makeWord (buf[6], buf[7]);
numColours = 2 << (buf[8] & 7);
if ((buf[8] & 0x80) != 0)
if (! readPalette (numColours))
break;
image = Image ((transparent >= 0) ? Image::ARGB : Image::RGB,
imageWidth, imageHeight, (transparent >= 0));
readImage ((buf[8] & 0x40) != 0, transparent);
break;
}
}
GIFLoader::~GIFLoader()
{
}
bool GIFLoader::getSizeFromHeader (int& w, int& h)
{
char b[8];
if (input.read (b, 6) == 6)
{
if ((strncmp ("GIF87a", b, 6) == 0)
|| (strncmp ("GIF89a", b, 6) == 0))
{
if (input.read (b, 4) == 4)
if (buf[0] == '!')
{
w = makeWord (b[0], b[1]);
h = makeWord (b[2], b[3]);
return true;
if (input.read (buf, 1) != 1)
break;
if (processExtension (buf[0], transparent) < 0)
break;
continue;
}
if (buf[0] != ',')
continue;
if (input.read (buf, 9) != 9)
break;
imageWidth = makeWord (buf[4], buf[5]);
imageHeight = makeWord (buf[6], buf[7]);
numColours = 2 << (buf[8] & 7);
if ((buf[8] & 0x80) != 0)
if (! readPalette (numColours))
break;
image = Image ((transparent >= 0) ? Image::ARGB : Image::RGB,
imageWidth, imageHeight, (transparent >= 0));
readImage ((buf[8] & 0x40) != 0, transparent);
break;
}
}
~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)
{
char b[8];
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;
}
}
}
return false;
}
return false;
}
bool GIFLoader::readPalette (const int numCols)
{
unsigned char rgb[4];
for (int i = 0; i < numCols; ++i)
bool readPalette (const int numCols)
{
input.read (rgb, 3);
unsigned char rgb[4];
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);
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;
if ((b[0] & 0x1) != 0)
transparent = b[3];
}
do
{
n = readDataBlock (b);
}
while (n > 0);
return n;
}
int GIFLoader::getCode (const int codeSize_, const bool initialise)
{
if (initialise)
{
currentBit = 0;
lastBit = 0;
finished = false;
return 0;
}
if ((currentBit + codeSize_) >= lastBit)
{
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;
lastByteIndex = 2 + n;
currentBit = (currentBit - lastBit) + 16;
lastBit = (2 + n) * 8 ;
}
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;
}
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)
for (int i = 0; i < numCols; ++i)
{
table[0][i] = 0;
table[1][i] = i;
input.read (rgb, 3);
palette [i][0] = rgb[0];
palette [i][1] = rgb[1];
palette [i][2] = rgb[2];
palette [i][3] = 0xff;
}
for (; i < maxGifCode; ++i)
return true;
}
int readDataBlock (unsigned char* dest)
{
unsigned char n;
if (input.read (&n, 1) == 1)
{
table[0][i] = 0;
table[1][i] = 0;
dataBlockIsZero = (n == 0);
if (dataBlockIsZero || (input.read (dest, n) == n))
return n;
}
sp = stack;
return 0;
return -1;
}
else if (fresh)
int processExtension (const int type, int& transparent)
{
fresh = false;
unsigned char b [300];
int n = 0;
if (type == 0xf9)
{
n = readDataBlock (b);
if (n < 0)
return 1;
if ((b[0] & 0x1) != 0)
transparent = b[3];
}
do
{
firstcode = oldcode
= getCode (codeSize, false);
n = readDataBlock (b);
}
while (firstcode == clearCode);
while (n > 0);
return firstcode;
return n;
}
if (sp > stack)
return *--sp;
while ((code = getCode (codeSize, false)) >= 0)
int readLZWByte (const bool initialise, const int inputCodeSize)
{
if (code == clearCode)
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)
{
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;
fresh = false;
unsigned char buf [260];
int n;
while ((n = readDataBlock (buf)) > 0)
{}
if (n != 0)
return -2;
}
incode = code;
if (code >= maxCode)
{
*sp++ = firstcode;
code = oldcode;
}
while (code >= clearCode)
{
*sp++ = table[1][code];
if (code == table[0][code])
return -2;
code = table[0][code];
}
*sp++ = firstcode = table[1][code];
if ((code = maxCode) < maxGifCode)
{
table[0][code] = oldcode;
table[1][code] = firstcode;
++maxCode;
if ((maxCode >= maxCodeSize)
&& (maxCodeSize < maxGifCode))
do
{
maxCodeSize <<= 1;
++codeSize;
firstcode = oldcode
= getCode (codeSize, false);
}
}
while (firstcode == clearCode);
oldcode = incode;
return firstcode;
}
if (sp > stack)
return *--sp;
}
return code;
}
bool GIFLoader::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)
{
palette [transparent][0] = 0;
palette [transparent][1] = 0;
palette [transparent][2] = 0;
palette [transparent][3] = 0;
}
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)
while ((code = getCode (codeSize, false)) >= 0)
{
((PixelARGB*) p)->setARGB (paletteEntry[3],
paletteEntry[0],
paletteEntry[1],
paletteEntry[2]);
((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)
if (code == clearCode)
{
switch (pass)
for (i = 0; i < clearCode; ++i)
{
case 0:
case 1: ypos += 8; break;
case 2: ypos += 4; break;
case 3: ypos += 2; break;
table[0][i] = 0;
table[1][i] = i;
}
while (ypos >= destData.height)
for (; i < maxGifCode; ++i)
{
++pass;
switch (pass)
{
case 1: ypos = 4; break;
case 2: ypos = 2; break;
case 3: ypos = 1; break;
default: return true;
}
table[0][i] = 0;
table[1][i] = 0;
}
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;
unsigned char buf [260];
int n;
while ((n = readDataBlock (buf)) > 0)
{}
if (n != 0)
return -2;
}
incode = code;
if (code >= maxCode)
{
*sp++ = firstcode;
code = oldcode;
}
while (code >= clearCode)
{
*sp++ = table[1][code];
if (code == table[0][code])
return -2;
code = table[0][code];
}
*sp++ = firstcode = table[1][code];
if ((code = maxCode) < maxGifCode)
{
table[0][code] = oldcode;
table[1][code] = firstcode;
++maxCode;
if ((maxCode >= maxCodeSize)
&& (maxCodeSize < maxGifCode))
{
maxCodeSize <<= 1;
++codeSize;
}
}
oldcode = incode;
if (sp > stack)
return *--sp;
}
return code;
}
int getCode (const int codeSize_, const bool initialise)
{
if (initialise)
{
currentBit = 0;
lastBit = 0;
finished = false;
return 0;
}
if ((currentBit + codeSize_) >= lastBit)
{
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;
lastByteIndex = 2 + n;
currentBit = (currentBit - lastBit) + 16;
lastBit = (2 + n) * 8 ;
}
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)
{
palette [transparent][0] = 0;
palette [transparent][1] = 0;
palette [transparent][2] = 0;
palette [transparent][3] = 0;
}
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)
{
((PixelARGB*) p)->setARGB (paletteEntry[3],
paletteEntry[0],
paletteEntry[1],
paletteEntry[2]);
((PixelARGB*) p)->premultiply();
}
else
{
++ypos;
((PixelRGB*) p)->setARGB (0,
paletteEntry[0],
paletteEntry[1],
paletteEntry[2]);
}
p = destData.getPixelPointer (xpos, ypos);
p += destData.pixelStride;
++xpos;
if (xpos == destData.width)
{
xpos = 0;
if (interlace)
{
switch (pass)
{
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;
}
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;
}

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__

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)

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)

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

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__

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