mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-11 19:54:03 +00:00
GRAPHICS: Move PNG to the ImageDecoder interface
This commit is contained in:
parent
dd9790c1c8
commit
a658fc660e
@ -33,18 +33,19 @@
|
||||
#include "sword25/gfx/image/image.h"
|
||||
#include "sword25/gfx/image/imgloader.h"
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "graphics/png.h"
|
||||
#include "graphics/decoders/png.h"
|
||||
|
||||
namespace Sword25 {
|
||||
|
||||
bool ImgLoader::decodePNGImage(const byte *fileDataPtr, uint fileSize, byte *&uncompressedDataPtr, int &width, int &height, int &pitch) {
|
||||
Common::MemoryReadStream *fileStr = new Common::MemoryReadStream(fileDataPtr, fileSize, DisposeAfterUse::NO);
|
||||
Graphics::PNG *png = new Graphics::PNG();
|
||||
if (!png->read(fileStr)) // the fileStr pointer, and thus pFileData will be deleted after this is done
|
||||
|
||||
Graphics::PNGDecoder png;
|
||||
if (!png.loadStream(*fileStr)) // the fileStr pointer, and thus pFileData will be deleted after this is done
|
||||
error("Error while reading PNG image");
|
||||
|
||||
Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
|
||||
Graphics::Surface *pngSurface = png->getSurface(format);
|
||||
const Graphics::Surface *sourceSurface = png.getSurface();
|
||||
Graphics::Surface *pngSurface = sourceSurface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24), png.getPalette());
|
||||
|
||||
width = pngSurface->w;
|
||||
height = pngSurface->h;
|
||||
@ -53,7 +54,7 @@ bool ImgLoader::decodePNGImage(const byte *fileDataPtr, uint fileSize, byte *&un
|
||||
pngSurface->free();
|
||||
|
||||
delete pngSurface;
|
||||
delete png;
|
||||
delete fileStr;
|
||||
|
||||
// Signal success
|
||||
return true;
|
||||
|
@ -20,7 +20,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "graphics/png.h"
|
||||
#include "graphics/decoders/png.h"
|
||||
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "graphics/surface.h"
|
||||
@ -98,113 +98,27 @@ enum PNGFilters {
|
||||
kFilterPaeth = 4
|
||||
};
|
||||
|
||||
PNG::PNG() : _compressedBuffer(0), _compressedBufferSize(0),
|
||||
_unfilteredSurface(0), _transparentColorSpecified(false) {
|
||||
PNGDecoder::PNGDecoder() : _compressedBuffer(0), _compressedBufferSize(0),
|
||||
_transparentColorSpecified(false), _outputSurface(0) {
|
||||
}
|
||||
|
||||
PNG::~PNG() {
|
||||
if (_unfilteredSurface) {
|
||||
_unfilteredSurface->free();
|
||||
delete _unfilteredSurface;
|
||||
PNGDecoder::~PNGDecoder() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void PNGDecoder::destroy() {
|
||||
if (_outputSurface) {
|
||||
_outputSurface->free();
|
||||
delete _outputSurface;
|
||||
_outputSurface = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Graphics::Surface *PNG::getSurface(const PixelFormat &format) {
|
||||
Graphics::Surface *output = new Graphics::Surface();
|
||||
output->create(_unfilteredSurface->w, _unfilteredSurface->h, format);
|
||||
byte *src = (byte *)_unfilteredSurface->pixels;
|
||||
byte a = 0xFF;
|
||||
byte bpp = _unfilteredSurface->format.bytesPerPixel;
|
||||
bool PNGDecoder::loadStream(Common::SeekableReadStream &stream) {
|
||||
destroy();
|
||||
|
||||
if (_header.colorType != kIndexed) {
|
||||
if (_header.colorType == kTrueColor ||
|
||||
_header.colorType == kTrueColorWithAlpha) {
|
||||
if (bpp != 3 && bpp != 4)
|
||||
error("Unsupported truecolor PNG format");
|
||||
} else if (_header.colorType == kGrayScale ||
|
||||
_header.colorType == kGrayScaleWithAlpha) {
|
||||
if (bpp != 1 && bpp != 2)
|
||||
error("Unsupported grayscale PNG format");
|
||||
}
|
||||
|
||||
for (uint16 i = 0; i < output->h; i++) {
|
||||
for (uint16 j = 0; j < output->w; j++) {
|
||||
uint32 result = 0;
|
||||
|
||||
switch (bpp) {
|
||||
case 1: // Grayscale
|
||||
if (_transparentColorSpecified)
|
||||
a = (src[0] == _transparentColor[0]) ? 0 : 0xFF;
|
||||
result = format.ARGBToColor( a, src[0], src[0], src[0]);
|
||||
break;
|
||||
case 2: // Grayscale + alpha
|
||||
result = format.ARGBToColor(src[1], src[0], src[0], src[0]);
|
||||
break;
|
||||
case 3: // RGB
|
||||
if (_transparentColorSpecified) {
|
||||
bool isTransparentColor = (src[0] == _transparentColor[0] &&
|
||||
src[1] == _transparentColor[1] &&
|
||||
src[2] == _transparentColor[2]);
|
||||
a = isTransparentColor ? 0 : 0xFF;
|
||||
}
|
||||
result = format.ARGBToColor( a, src[0], src[1], src[2]);
|
||||
break;
|
||||
case 4: // RGBA
|
||||
result = format.ARGBToColor(src[3], src[0], src[1], src[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (format.bytesPerPixel == 2) // 2bpp
|
||||
*((uint16 *)output->getBasePtr(j, i)) = (uint16)result;
|
||||
else // 4bpp
|
||||
*((uint32 *)output->getBasePtr(j, i)) = result;
|
||||
|
||||
src += bpp;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
byte index, r, g, b;
|
||||
uint32 mask = (0xff >> (8 - _header.bitDepth)) << (8 - _header.bitDepth);
|
||||
|
||||
// Convert the indexed surface to the target pixel format
|
||||
for (uint16 i = 0; i < output->h; i++) {
|
||||
int data = 0;
|
||||
int bitCount = 8;
|
||||
byte *src1 = src;
|
||||
|
||||
for (uint16 j = 0; j < output->w; j++) {
|
||||
if (bitCount == 8) {
|
||||
data = *src;
|
||||
src++;
|
||||
}
|
||||
|
||||
index = (data & mask) >> (8 - _header.bitDepth);
|
||||
data = (data << _header.bitDepth) & 0xff;
|
||||
bitCount -= _header.bitDepth;
|
||||
|
||||
if (bitCount == 0)
|
||||
bitCount = 8;
|
||||
|
||||
r = _palette[index * 4 + 0];
|
||||
g = _palette[index * 4 + 1];
|
||||
b = _palette[index * 4 + 2];
|
||||
a = _palette[index * 4 + 3];
|
||||
|
||||
if (format.bytesPerPixel == 2)
|
||||
*((uint16 *)output->getBasePtr(j, i)) = format.ARGBToColor(a, r, g, b);
|
||||
else
|
||||
*((uint32 *)output->getBasePtr(j, i)) = format.ARGBToColor(a, r, g, b);
|
||||
}
|
||||
src = src1 + output->w;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
bool PNG::read(Common::SeekableReadStream *str) {
|
||||
uint32 chunkLength = 0, chunkType = 0;
|
||||
_stream = str;
|
||||
_stream = &stream;
|
||||
|
||||
// First, check the PNG signature
|
||||
if (_stream->readUint32BE() != MKTAG(0x89, 'P', 'N', 'G')) {
|
||||
@ -249,8 +163,10 @@ bool PNG::read(Common::SeekableReadStream *str) {
|
||||
error("A palette chunk has been found in a non-indexed PNG file");
|
||||
if (chunkLength % 3 != 0)
|
||||
error("Palette chunk not divisible by 3");
|
||||
|
||||
_paletteEntries = chunkLength / 3;
|
||||
readPaletteChunk();
|
||||
_stream->read(_palette, _paletteEntries * 3);
|
||||
memset(_paletteTransparency, 0xff, sizeof(_paletteTransparency));
|
||||
break;
|
||||
case kChunkIEND:
|
||||
// End of stream
|
||||
@ -269,7 +185,6 @@ bool PNG::read(Common::SeekableReadStream *str) {
|
||||
}
|
||||
|
||||
// We no longer need the file stream, thus close it here
|
||||
delete _stream;
|
||||
_stream = 0;
|
||||
|
||||
// Unpack the compressed buffer
|
||||
@ -295,7 +210,7 @@ bool PNG::read(Common::SeekableReadStream *str) {
|
||||
* Taken from lodePNG, with a slight patch:
|
||||
* http://www.atalasoft.com/cs/blogs/stevehawley/archive/2010/02/23/libpng-you-re-doing-it-wrong.aspx
|
||||
*/
|
||||
byte PNG::paethPredictor(int16 a, int16 b, int16 c) {
|
||||
byte PNGDecoder::paethPredictor(int16 a, int16 b, int16 c) {
|
||||
int16 pa = ABS<int16>(b - c);
|
||||
int16 pb = ABS<int16>(a - c);
|
||||
int16 pc = ABS<int16>(a + b - c - c);
|
||||
@ -315,7 +230,7 @@ byte PNG::paethPredictor(int16 a, int16 b, int16 c) {
|
||||
*
|
||||
* Taken from lodePNG
|
||||
*/
|
||||
void PNG::unfilterScanLine(byte *dest, const byte *scanLine, const byte *prevLine, uint16 byteWidth, byte filterType, uint16 length) {
|
||||
void PNGDecoder::unfilterScanLine(byte *dest, const byte *scanLine, const byte *prevLine, uint16 byteWidth, byte filterType, uint16 length) {
|
||||
uint16 i;
|
||||
|
||||
switch (filterType) {
|
||||
@ -370,33 +285,29 @@ void PNG::unfilterScanLine(byte *dest, const byte *scanLine, const byte *prevLin
|
||||
|
||||
}
|
||||
|
||||
void PNG::constructImage() {
|
||||
int PNGDecoder::getBytesPerPixel() const {
|
||||
return (getNumColorChannels() * _header.bitDepth + 7) / 8;
|
||||
}
|
||||
|
||||
void PNGDecoder::constructImage() {
|
||||
assert (_header.bitDepth != 0);
|
||||
|
||||
byte *dest;
|
||||
byte *scanLine;
|
||||
byte *prevLine = 0;
|
||||
byte filterType;
|
||||
int bytesPerPixel = getBytesPerPixel();
|
||||
int pitch = bytesPerPixel * _header.width;
|
||||
byte *unfilteredSurface = new byte[pitch * _header.height];
|
||||
byte *dest = unfilteredSurface;
|
||||
uint16 scanLineWidth = (_header.width * getNumColorChannels() * _header.bitDepth + 7) / 8;
|
||||
|
||||
if (_unfilteredSurface) {
|
||||
_unfilteredSurface->free();
|
||||
delete _unfilteredSurface;
|
||||
}
|
||||
_unfilteredSurface = new Graphics::Surface();
|
||||
// TODO/FIXME: It seems we can not properly determine the format here. But maybe there is a way...
|
||||
_unfilteredSurface->create(_header.width, _header.height, PixelFormat((getNumColorChannels() * _header.bitDepth + 7) / 8, 0, 0, 0, 0, 0, 0, 0, 0));
|
||||
scanLine = new byte[_unfilteredSurface->pitch];
|
||||
dest = (byte *)_unfilteredSurface->getBasePtr(0, 0);
|
||||
byte *scanLine = new byte[scanLineWidth];
|
||||
byte *prevLine = 0;
|
||||
|
||||
switch(_header.interlaceType) {
|
||||
case kNonInterlaced:
|
||||
for (uint16 y = 0; y < _unfilteredSurface->h; y++) {
|
||||
filterType = _imageData->readByte();
|
||||
for (uint16 y = 0; y < _header.height; y++) {
|
||||
byte filterType = _imageData->readByte();
|
||||
_imageData->read(scanLine, scanLineWidth);
|
||||
unfilterScanLine(dest, scanLine, prevLine, _unfilteredSurface->format.bytesPerPixel, filterType, scanLineWidth);
|
||||
unfilterScanLine(dest, scanLine, prevLine, bytesPerPixel, filterType, scanLineWidth);
|
||||
prevLine = dest;
|
||||
dest += _unfilteredSurface->pitch;
|
||||
dest += pitch;
|
||||
}
|
||||
break;
|
||||
case kInterlaced:
|
||||
@ -409,9 +320,123 @@ void PNG::constructImage() {
|
||||
}
|
||||
|
||||
delete[] scanLine;
|
||||
|
||||
constructOutput(unfilteredSurface);
|
||||
delete[] unfilteredSurface;
|
||||
}
|
||||
|
||||
void PNG::readHeaderChunk() {
|
||||
Graphics::PixelFormat PNGDecoder::findPixelFormat() const {
|
||||
// Try to find the best pixel format based on what we have here
|
||||
// Which is basically 8bpp for paletted non-transparent
|
||||
// and 32bpp for everything else
|
||||
|
||||
switch (_header.colorType) {
|
||||
case kIndexed:
|
||||
if (!_transparentColorSpecified)
|
||||
return Graphics::PixelFormat::createFormatCLUT8();
|
||||
// fall through
|
||||
case kGrayScale:
|
||||
case kTrueColor:
|
||||
case kGrayScaleWithAlpha:
|
||||
case kTrueColorWithAlpha:
|
||||
// We'll go with standard RGBA 32-bit
|
||||
return Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
|
||||
}
|
||||
|
||||
error("Unknown PNG color type");
|
||||
return Graphics::PixelFormat();
|
||||
}
|
||||
|
||||
void PNGDecoder::constructOutput(const byte *surface) {
|
||||
_outputSurface = new Graphics::Surface();
|
||||
_outputSurface->create(_header.width, _header.height, findPixelFormat());
|
||||
|
||||
const byte *src = surface;
|
||||
byte a = 0xFF;
|
||||
int bytesPerPixel = getBytesPerPixel();
|
||||
|
||||
if (_header.colorType != kIndexed) {
|
||||
if (_header.colorType == kTrueColor ||
|
||||
_header.colorType == kTrueColorWithAlpha) {
|
||||
if (bytesPerPixel != 3 && bytesPerPixel != 4)
|
||||
error("Unsupported truecolor PNG format");
|
||||
} else if (_header.colorType == kGrayScale ||
|
||||
_header.colorType == kGrayScaleWithAlpha) {
|
||||
if (bytesPerPixel != 1 && bytesPerPixel != 2)
|
||||
error("Unsupported grayscale PNG format");
|
||||
}
|
||||
|
||||
for (uint16 i = 0; i < _outputSurface->h; i++) {
|
||||
for (uint16 j = 0; j < _outputSurface->w; j++) {
|
||||
uint32 result = 0;
|
||||
|
||||
switch (bytesPerPixel) {
|
||||
case 1: // Grayscale
|
||||
if (_transparentColorSpecified)
|
||||
a = (src[0] == _transparentColor[0]) ? 0 : 0xFF;
|
||||
result = _outputSurface->format.ARGBToColor(a, src[0], src[0], src[0]);
|
||||
break;
|
||||
case 2: // Grayscale + alpha
|
||||
result = _outputSurface->format.ARGBToColor(src[1], src[0], src[0], src[0]);
|
||||
break;
|
||||
case 3: // RGB
|
||||
if (_transparentColorSpecified) {
|
||||
bool isTransparentColor = (src[0] == _transparentColor[0] &&
|
||||
src[1] == _transparentColor[1] &&
|
||||
src[2] == _transparentColor[2]);
|
||||
a = isTransparentColor ? 0 : 0xFF;
|
||||
}
|
||||
|
||||
result = _outputSurface->format.ARGBToColor(a, src[0], src[1], src[2]);
|
||||
break;
|
||||
case 4: // RGBA
|
||||
result = _outputSurface->format.ARGBToColor(src[3], src[0], src[1], src[2]);
|
||||
break;
|
||||
}
|
||||
|
||||
*((uint32 *)_outputSurface->getBasePtr(j, i)) = result;
|
||||
src += bytesPerPixel;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint32 mask = (0xff >> (8 - _header.bitDepth)) << (8 - _header.bitDepth);
|
||||
|
||||
// Convert the indexed surface to the target pixel format
|
||||
for (uint16 i = 0; i < _outputSurface->h; i++) {
|
||||
int data = 0;
|
||||
int bitCount = 8;
|
||||
const byte *src1 = src;
|
||||
|
||||
for (uint16 j = 0; j < _outputSurface->w; j++) {
|
||||
if (bitCount == 8) {
|
||||
data = *src;
|
||||
src++;
|
||||
}
|
||||
|
||||
byte index = (data & mask) >> (8 - _header.bitDepth);
|
||||
data = (data << _header.bitDepth) & 0xff;
|
||||
bitCount -= _header.bitDepth;
|
||||
|
||||
if (bitCount == 0)
|
||||
bitCount = 8;
|
||||
|
||||
if (_transparentColorSpecified) {
|
||||
byte r = _palette[index * 3 + 0];
|
||||
byte g = _palette[index * 3 + 1];
|
||||
byte b = _palette[index * 3 + 2];
|
||||
a = _paletteTransparency[index];
|
||||
*((uint32 *)_outputSurface->getBasePtr(j, i)) = _outputSurface->format.ARGBToColor(a, r, g, b);
|
||||
} else {
|
||||
*((byte *)_outputSurface->getBasePtr(j, i)) = index;
|
||||
}
|
||||
}
|
||||
|
||||
src = src1 + _outputSurface->w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PNGDecoder::readHeaderChunk() {
|
||||
_header.width = _stream->readUint32BE();
|
||||
_header.height = _stream->readUint32BE();
|
||||
_header.bitDepth = _stream->readByte();
|
||||
@ -431,7 +456,7 @@ void PNG::readHeaderChunk() {
|
||||
_header.interlaceType = (PNGInterlaceType)_stream->readByte();
|
||||
}
|
||||
|
||||
byte PNG::getNumColorChannels() {
|
||||
byte PNGDecoder::getNumColorChannels() const {
|
||||
switch (_header.colorType) {
|
||||
case kGrayScale:
|
||||
return 1; // Gray
|
||||
@ -448,16 +473,7 @@ byte PNG::getNumColorChannels() {
|
||||
}
|
||||
}
|
||||
|
||||
void PNG::readPaletteChunk() {
|
||||
for (uint16 i = 0; i < _paletteEntries; i++) {
|
||||
_palette[i * 4 + 0] = _stream->readByte(); // R
|
||||
_palette[i * 4 + 1] = _stream->readByte(); // G
|
||||
_palette[i * 4 + 2] = _stream->readByte(); // B
|
||||
_palette[i * 4 + 3] = 0xFF; // Alpha, set in the tRNS chunk
|
||||
}
|
||||
}
|
||||
|
||||
void PNG::readTransparencyChunk(uint32 chunkLength) {
|
||||
void PNGDecoder::readTransparencyChunk(uint32 chunkLength) {
|
||||
_transparentColorSpecified = true;
|
||||
|
||||
switch(_header.colorType) {
|
||||
@ -472,8 +488,8 @@ void PNG::readTransparencyChunk(uint32 chunkLength) {
|
||||
_transparentColor[2] = _stream->readUint16BE();
|
||||
break;
|
||||
case kIndexed:
|
||||
for (uint32 i = 0; i < chunkLength; i++)
|
||||
_palette[i * 4 + 3] = _stream->readByte();
|
||||
_stream->read(_paletteTransparency, chunkLength);
|
||||
|
||||
// A transparency chunk may have less entries
|
||||
// than the palette entries. The remaining ones
|
||||
// are unmodified (set to 255). Check here:
|
@ -53,6 +53,7 @@
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "graphics/decoders/image_decoder.h"
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
@ -61,82 +62,44 @@ class SeekableReadStream;
|
||||
namespace Graphics {
|
||||
|
||||
struct Surface;
|
||||
|
||||
enum PNGColorType {
|
||||
kGrayScale = 0, // bit depths: 1, 2, 4, 8, 16
|
||||
kTrueColor = 2, // bit depths: 8, 16
|
||||
kIndexed = 3, // bit depths: 1, 2, 4, 8
|
||||
kGrayScaleWithAlpha = 4, // bit depths: 8, 16
|
||||
kTrueColorWithAlpha = 6 // bit depths: 8, 16
|
||||
};
|
||||
|
||||
enum PNGInterlaceType {
|
||||
kNonInterlaced = 0,
|
||||
kInterlaced = 1
|
||||
};
|
||||
|
||||
struct PNGHeader {
|
||||
uint32 width;
|
||||
uint32 height;
|
||||
byte bitDepth;
|
||||
PNGColorType colorType;
|
||||
byte compressionMethod;
|
||||
byte filterMethod;
|
||||
PNGInterlaceType interlaceType;
|
||||
};
|
||||
|
||||
struct PixelFormat;
|
||||
|
||||
class PNG {
|
||||
class PNGDecoder : public ImageDecoder {
|
||||
public:
|
||||
PNG();
|
||||
~PNG();
|
||||
PNGDecoder();
|
||||
~PNGDecoder();
|
||||
|
||||
/**
|
||||
* Reads a PNG image from the specified stream
|
||||
*/
|
||||
bool read(Common::SeekableReadStream *str);
|
||||
|
||||
/**
|
||||
* Returns the information obtained from the PNG header.
|
||||
*/
|
||||
PNGHeader getHeader() const { return _header; }
|
||||
|
||||
/**
|
||||
* Returns the PNG image, formatted for the specified pixel format.
|
||||
*/
|
||||
Graphics::Surface *getSurface(const PixelFormat &format);
|
||||
|
||||
/**
|
||||
* Returns the indexed PNG8 image. Used for PNGs with an indexed 256 color
|
||||
* palette, when they're shown on an 8-bit color screen, as no translation
|
||||
* is taking place.
|
||||
*/
|
||||
Graphics::Surface *getIndexedSurface() {
|
||||
if (_header.colorType != kIndexed)
|
||||
error("Indexed surface requested for a non-indexed PNG");
|
||||
return _unfilteredSurface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the palette of the specified PNG8 image, given a pointer to
|
||||
* an RGBA palette array (4 x 256).
|
||||
*/
|
||||
void getPalette(byte *palette, uint16 &entries) {
|
||||
if (_header.colorType != kIndexed)
|
||||
error("Palette requested for a non-indexed PNG");
|
||||
for (int i = 0; i < 256; i++) {
|
||||
palette[0 + i * 4] = _palette[0 + i * 4]; // R
|
||||
palette[1 + i * 4] = _palette[1 + i * 4]; // G
|
||||
palette[2 + i * 4] = _palette[2 + i * 4]; // B
|
||||
palette[3 + i * 4] = _palette[3 + i * 4]; // A
|
||||
}
|
||||
entries = _paletteEntries;
|
||||
}
|
||||
bool loadStream(Common::SeekableReadStream &stream);
|
||||
void destroy();
|
||||
const Graphics::Surface *getSurface() const { return _outputSurface; }
|
||||
const byte *getPalette() const { return _palette; }
|
||||
|
||||
private:
|
||||
enum PNGColorType {
|
||||
kGrayScale = 0, // bit depths: 1, 2, 4, 8, 16
|
||||
kTrueColor = 2, // bit depths: 8, 16
|
||||
kIndexed = 3, // bit depths: 1, 2, 4, 8
|
||||
kGrayScaleWithAlpha = 4, // bit depths: 8, 16
|
||||
kTrueColorWithAlpha = 6 // bit depths: 8, 16
|
||||
};
|
||||
|
||||
enum PNGInterlaceType {
|
||||
kNonInterlaced = 0,
|
||||
kInterlaced = 1
|
||||
};
|
||||
|
||||
struct PNGHeader {
|
||||
uint32 width;
|
||||
uint32 height;
|
||||
byte bitDepth;
|
||||
PNGColorType colorType;
|
||||
byte compressionMethod;
|
||||
byte filterMethod;
|
||||
PNGInterlaceType interlaceType;
|
||||
};
|
||||
|
||||
void readHeaderChunk();
|
||||
byte getNumColorChannels();
|
||||
byte getNumColorChannels() const;
|
||||
|
||||
void readPaletteChunk();
|
||||
void readTransparencyChunk(uint32 chunkLength);
|
||||
@ -152,7 +115,8 @@ private:
|
||||
|
||||
PNGHeader _header;
|
||||
|
||||
byte _palette[256 * 4]; // RGBA
|
||||
byte _palette[256 * 3]; // RGB
|
||||
byte _paletteTransparency[256];
|
||||
uint16 _paletteEntries;
|
||||
uint16 _transparentColor[3];
|
||||
bool _transparentColorSpecified;
|
||||
@ -160,9 +124,12 @@ private:
|
||||
byte *_compressedBuffer;
|
||||
uint32 _compressedBufferSize;
|
||||
|
||||
Graphics::Surface *_unfilteredSurface;
|
||||
Graphics::Surface *_outputSurface;
|
||||
Graphics::PixelFormat findPixelFormat() const;
|
||||
int getBytesPerPixel() const;
|
||||
void constructOutput(const byte *surface);
|
||||
};
|
||||
|
||||
} // End of Graphics namespace
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif // GRAPHICS_PNG_H
|
@ -13,7 +13,6 @@ MODULE_OBJS := \
|
||||
fonts/winfont.o \
|
||||
iff.o \
|
||||
maccursor.o \
|
||||
png.o \
|
||||
primitives.o \
|
||||
scaler.o \
|
||||
scaler/thumbnail_intern.o \
|
||||
@ -26,7 +25,8 @@ MODULE_OBJS := \
|
||||
yuv_to_rgb.o \
|
||||
decoders/bmp.o \
|
||||
decoders/jpeg.o \
|
||||
decoders/pict.o
|
||||
decoders/pict.o \
|
||||
decoders/png.o
|
||||
|
||||
ifdef USE_SCALERS
|
||||
MODULE_OBJS += \
|
||||
|
Loading…
Reference in New Issue
Block a user