diff options
Diffstat (limited to 'graphics/decoders')
-rw-r--r-- | graphics/decoders/bmp.cpp | 12 | ||||
-rw-r--r-- | graphics/decoders/bmp.h | 1 | ||||
-rw-r--r-- | graphics/decoders/image_decoder.h | 7 | ||||
-rw-r--r-- | graphics/decoders/jpeg.cpp | 4 | ||||
-rw-r--r-- | graphics/decoders/jpeg.h | 1 | ||||
-rw-r--r-- | graphics/decoders/pcx.cpp | 213 | ||||
-rw-r--r-- | graphics/decoders/pcx.h | 68 | ||||
-rw-r--r-- | graphics/decoders/pict.cpp | 25 | ||||
-rw-r--r-- | graphics/decoders/pict.h | 5 | ||||
-rw-r--r-- | graphics/decoders/png.cpp | 1 | ||||
-rw-r--r-- | graphics/decoders/png.h | 1 | ||||
-rw-r--r-- | graphics/decoders/tga.cpp | 5 | ||||
-rw-r--r-- | graphics/decoders/tga.h | 2 |
13 files changed, 321 insertions, 24 deletions
diff --git a/graphics/decoders/bmp.cpp b/graphics/decoders/bmp.cpp index f15d4e2519..bcfd0abbda 100644 --- a/graphics/decoders/bmp.cpp +++ b/graphics/decoders/bmp.cpp @@ -100,10 +100,10 @@ bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) { _paletteColorCount = stream.readUint32LE(); /* uint32 colorsImportant = */ stream.readUint32LE(); - if (_paletteColorCount == 0) - _paletteColorCount = 256; - if (bitsPerPixel == 8) { + if (_paletteColorCount == 0) + _paletteColorCount = 256; + // Read the palette _palette = new byte[_paletteColorCount * 3]; for (uint16 i = 0; i < _paletteColorCount; i++) { @@ -155,7 +155,7 @@ bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) { } } else { // 32 bpp byte *dst = (byte *)_surface->pixels + (height - 1) * _surface->pitch; - + for (int32 i = 0; i < height; i++) { for (uint32 j = 0; j < width; j++) { byte b = stream.readByte(); @@ -166,11 +166,11 @@ bool BitmapDecoder::loadStream(Common::SeekableReadStream &stream) { // ref: http://msdn.microsoft.com/en-us/library/windows/desktop/dd183376%28v=vs.85%29.aspx stream.readByte(); uint32 color = format.RGBToColor(r, g, b); - + *((uint32 *)dst) = color; dst += format.bytesPerPixel; } - + stream.skip(extraDataLength); dst -= _surface->pitch * 2; } diff --git a/graphics/decoders/bmp.h b/graphics/decoders/bmp.h index 59da682e4d..779da352be 100644 --- a/graphics/decoders/bmp.h +++ b/graphics/decoders/bmp.h @@ -24,6 +24,7 @@ * Image decoder used in engines: * - hugo * - mohawk + * - wintermute */ #ifndef GRAPHICS_DECODERS_BMP_H diff --git a/graphics/decoders/image_decoder.h b/graphics/decoders/image_decoder.h index 830645d361..49e31c6e3a 100644 --- a/graphics/decoders/image_decoder.h +++ b/graphics/decoders/image_decoder.h @@ -78,10 +78,15 @@ public: * The palette's format is the same as PaletteManager's palette * (interleaved RGB values). * - * @return the decoded palette, or 0 if no palette is present + * @return the decoded palette, or undefined if no palette is present */ virtual const byte *getPalette() const { return 0; } + /** + * Query if the decoded image has a palette. + */ + virtual bool hasPalette() const { return getPaletteColorCount() != 0; } + /** Return the starting index of the palette. */ virtual byte getPaletteStartIndex() const { return 0; } /** Return the number of colors in the palette. */ diff --git a/graphics/decoders/jpeg.cpp b/graphics/decoders/jpeg.cpp index a871377ca1..08bc1f7a3d 100644 --- a/graphics/decoders/jpeg.cpp +++ b/graphics/decoders/jpeg.cpp @@ -81,7 +81,7 @@ const Surface *JPEGDecoder::getSurface() const { const Graphics::Surface *uComponent = getComponent(2); const Graphics::Surface *vComponent = getComponent(3); - convertYUV444ToRGB(_rgbSurface, (byte *)yComponent->pixels, (byte *)uComponent->pixels, (byte *)vComponent->pixels, yComponent->w, yComponent->h, yComponent->pitch, uComponent->pitch); + YUVToRGBMan.convert444(_rgbSurface, Graphics::YUVToRGBManager::kScaleFull, (byte *)yComponent->pixels, (byte *)uComponent->pixels, (byte *)vComponent->pixels, yComponent->w, yComponent->h, yComponent->pitch, uComponent->pitch); return _rgbSurface; } @@ -452,7 +452,7 @@ bool JPEGDecoder::readSOS() { _bitsNumber = 0; for (byte i = 0; i < _numScanComp; i++) - _scanComp[i]->DCpredictor = 0; + _scanComp[i]->DCpredictor = 0; } } } diff --git a/graphics/decoders/jpeg.h b/graphics/decoders/jpeg.h index c74aa57ca1..d59b72adf4 100644 --- a/graphics/decoders/jpeg.h +++ b/graphics/decoders/jpeg.h @@ -25,6 +25,7 @@ * Image decoder used in engines: * - groovie * - mohawk + * - wintermute */ #ifndef GRAPHICS_JPEG_H diff --git a/graphics/decoders/pcx.cpp b/graphics/decoders/pcx.cpp new file mode 100644 index 0000000000..1250398c73 --- /dev/null +++ b/graphics/decoders/pcx.cpp @@ -0,0 +1,213 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "common/stream.h" +#include "common/textconsole.h" + +#include "graphics/pixelformat.h" +#include "graphics/surface.h" +#include "graphics/decoders/pcx.h" + +/** + * Based on the PCX specs: + * http://www.fileformat.info/format/pcx/spec/a10e75307b3a4cc49c3bbe6db4c41fa2/view.htm + * and the PCX decoder of FFmpeg (libavcodec/pcx.c): + * http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavcodec/pcx.c + */ + +namespace Graphics { + +PCXDecoder::PCXDecoder() { + _surface = 0; + _palette = 0; + _paletteColorCount = 0; +} + +PCXDecoder::~PCXDecoder() { + destroy(); +} + +void PCXDecoder::destroy() { + if (_surface) { + _surface->free(); + delete _surface; + _surface = 0; + } + + delete[] _palette; + _palette = 0; + _paletteColorCount = 0; +} + +bool PCXDecoder::loadStream(Common::SeekableReadStream &stream) { + destroy(); + + if (stream.readByte() != 0x0a) // ZSoft PCX + return false; + + byte version = stream.readByte(); // 0 - 5 + if (version > 5) + return false; + + bool compressed = stream.readByte(); // encoding, 1 = run length encoding + byte bitsPerPixel = stream.readByte(); // 1, 2, 4 or 8 + + // Window + uint16 xMin = stream.readUint16LE(); + uint16 yMin = stream.readUint16LE(); + uint16 xMax = stream.readUint16LE(); + uint16 yMax = stream.readUint16LE(); + + uint16 width = xMax - xMin + 1; + uint16 height = yMax - yMin + 1; + + if (xMax < xMin || yMax < yMin) { + warning("Invalid PCX image dimensions"); + return false; + } + + stream.skip(4); // HDpi, VDpi + + // Read the EGA palette (colormap) + _palette = new byte[16 * 3]; + for (uint16 i = 0; i < 16; i++) { + _palette[i * 3 + 0] = stream.readByte(); + _palette[i * 3 + 1] = stream.readByte(); + _palette[i * 3 + 2] = stream.readByte(); + } + + if (stream.readByte() != 0) // reserved, should be set to 0 + return false; + + byte nPlanes = stream.readByte(); + uint16 bytesPerLine = stream.readUint16LE(); + uint16 bytesPerscanLine = nPlanes * bytesPerLine; + + if (bytesPerscanLine < width * bitsPerPixel * nPlanes / 8) { + warning("PCX data is corrupted"); + return false; + } + + stream.skip(60); // PaletteInfo, HscreenSize, VscreenSize, Filler + + _surface = new Graphics::Surface(); + + byte *scanLine = new byte[bytesPerscanLine]; + byte *dst; + int x, y; + + if (nPlanes == 3 && bitsPerPixel == 8) { // 24bpp + Graphics::PixelFormat format = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0); + _surface->create(width, height, format); + dst = (byte *)_surface->pixels; + _paletteColorCount = 0; + + for (y = 0; y < height; y++) { + decodeRLE(stream, scanLine, bytesPerscanLine, compressed); + + for (x = 0; x < width; x++) { + byte b = scanLine[x]; + byte g = scanLine[x + bytesPerLine]; + byte r = scanLine[x + (bytesPerLine << 1)]; + uint32 color = format.RGBToColor(r, g, b); + + *((uint32 *)dst) = color; + dst += format.bytesPerPixel; + } + } + } else if (nPlanes == 1 && bitsPerPixel == 8) { // 8bpp indexed + _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + dst = (byte *)_surface->pixels; + _paletteColorCount = 16; + + for (y = 0; y < height; y++, dst += _surface->pitch) { + decodeRLE(stream, scanLine, bytesPerscanLine, compressed); + memcpy(dst, scanLine, width); + } + + if (version == 5) { + if (stream.readByte() != 12) { + warning("Expected a palette after the PCX image data"); + delete[] scanLine; + return false; + } + + // Read the VGA palette + delete[] _palette; + _palette = new byte[256 * 3]; + for (uint16 i = 0; i < 256; i++) { + _palette[i * 3 + 0] = stream.readByte(); + _palette[i * 3 + 1] = stream.readByte(); + _palette[i * 3 + 2] = stream.readByte(); + } + + _paletteColorCount = 256; + } + } else if ((nPlanes == 2 || nPlanes == 3 || nPlanes == 4) && bitsPerPixel == 1) { // planar, 4, 8 or 16 colors + _surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8()); + dst = (byte *)_surface->pixels; + _paletteColorCount = 16; + + for (y = 0; y < height; y++, dst += _surface->pitch) { + decodeRLE(stream, scanLine, bytesPerscanLine, compressed); + + for (x = 0; x < width; x++) { + int m = 0x80 >> (x & 7), v = 0; + for (int i = nPlanes - 1; i >= 0; i--) { + v <<= 1; + v += (scanLine[i * bytesPerLine + (x >> 3)] & m) == 0 ? 0 : 1; + } + dst[x] = v; + } + } + } else { + // Known unsupported case: 1 plane and bpp < 8 (1, 2 or 4) + warning("Invalid PCX file (%d planes, %d bpp)", nPlanes, bitsPerPixel); + delete[] scanLine; + return false; + } + + delete[] scanLine; + + return true; +} + +void PCXDecoder::decodeRLE(Common::SeekableReadStream &stream, byte *dst, uint32 bytesPerscanLine, bool compressed) { + uint32 i = 0; + byte run, value; + + if (compressed) { + while (i < bytesPerscanLine) { + run = 1; + value = stream.readByte(); + if (value >= 0xc0) { + run = value & 0x3f; + value = stream.readByte(); + } + while (i < bytesPerscanLine && run--) + dst[i++] = value; + } + } else { + stream.read(dst, bytesPerscanLine); + } +} + +} // End of namespace Graphics diff --git a/graphics/decoders/pcx.h b/graphics/decoders/pcx.h new file mode 100644 index 0000000000..b25166b3d9 --- /dev/null +++ b/graphics/decoders/pcx.h @@ -0,0 +1,68 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program 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. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * PCX decoder used in engines: + * - dreamweb + * - hugo + * - queen + * - tucker + */ + +#ifndef GRAPHICS_DECODERS_PCX_H +#define GRAPHICS_DECODERS_PCX_H + +#include "common/scummsys.h" +#include "common/str.h" +#include "graphics/decoders/image_decoder.h" + +namespace Common{ +class SeekableReadStream; +} + +namespace Graphics { + +struct PixelFormat; +struct Surface; + +class PCXDecoder : public ImageDecoder { +public: + PCXDecoder(); + virtual ~PCXDecoder(); + + // ImageDecoder API + void destroy(); + virtual bool loadStream(Common::SeekableReadStream &stream); + virtual const Surface *getSurface() const { return _surface; } + const byte *getPalette() const { return _palette; } + uint16 getPaletteColorCount() const { return _paletteColorCount; } + +private: + void decodeRLE(Common::SeekableReadStream &stream, byte *dst, uint32 bytesPerScanline, bool compressed); + + Surface *_surface; + byte *_palette; + uint16 _paletteColorCount; +}; + +} // End of namespace Graphics + +#endif diff --git a/graphics/decoders/pict.cpp b/graphics/decoders/pict.cpp index 7eddd3b893..b1d408ebc3 100644 --- a/graphics/decoders/pict.cpp +++ b/graphics/decoders/pict.cpp @@ -235,10 +235,13 @@ bool PICTDecoder::loadStream(Common::SeekableReadStream &stream) { // PICT v2 opcodes are two bytes uint16 opcode = stream.readUint16BE(); - if (opNum == 0 && opcode != 0x0011) - error("Cannot find PICT version opcode"); - else if (opNum == 1 && opcode != 0x0C00) - error("Cannot find PICT header opcode"); + if (opNum == 0 && opcode != 0x0011) { + warning("Cannot find PICT version opcode"); + return false; + } else if (opNum == 1 && opcode != 0x0C00) { + warning("Cannot find PICT header opcode"); + return false; + } // Since opcodes are word-aligned, we need to mark our starting // position here. @@ -292,12 +295,12 @@ struct PackBitsRectData { uint16 mode; }; -void PICTDecoder::unpackBitsRect(Common::SeekableReadStream &stream, bool hasPalette) { +void PICTDecoder::unpackBitsRect(Common::SeekableReadStream &stream, bool withPalette) { PackBitsRectData packBitsData; - packBitsData.pixMap = readPixMap(stream, !hasPalette); + packBitsData.pixMap = readPixMap(stream, !withPalette); // Read in the palette if there is one present - if (hasPalette) { + if (withPalette) { // See http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-267.html stream.readUint32BE(); // seed stream.readUint16BE(); // flags @@ -469,10 +472,10 @@ void PICTDecoder::outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel) { } } -void PICTDecoder::skipBitsRect(Common::SeekableReadStream &stream, bool hasPalette) { +void PICTDecoder::skipBitsRect(Common::SeekableReadStream &stream, bool withPalette) { // Step through a PackBitsRect/DirectBitsRect function - if (!hasPalette) + if (!withPalette) stream.readUint32BE(); uint16 rowBytes = stream.readUint16BE(); @@ -492,7 +495,7 @@ void PICTDecoder::skipBitsRect(Common::SeekableReadStream &stream, bool hasPalet stream.readUint16BE(); // pixelSize stream.skip(16); - if (hasPalette) { + if (withPalette) { stream.readUint32BE(); stream.readUint16BE(); stream.skip((stream.readUint16BE() + 1) * 8); @@ -543,7 +546,7 @@ void PICTDecoder::decodeCompressedQuickTime(Common::SeekableReadStream &stream) // Skip the matte and mask stream.skip(matteSize + maskSize); - + // Now we've reached the image descriptor, so read the relevant data from that uint32 idStart = stream.pos(); uint32 idSize = stream.readUint32BE(); diff --git a/graphics/decoders/pict.h b/graphics/decoders/pict.h index 417a7c5134..6f0d86c7a1 100644 --- a/graphics/decoders/pict.h +++ b/graphics/decoders/pict.h @@ -24,6 +24,7 @@ * @file * Image decoder used in engines: * - mohawk + * - pegasus * - sci */ @@ -87,9 +88,9 @@ private: bool _continueParsing; // Utility Functions - void unpackBitsRect(Common::SeekableReadStream &stream, bool hasPalette); + void unpackBitsRect(Common::SeekableReadStream &stream, bool withPalette); void unpackBitsLine(byte *out, uint32 length, Common::SeekableReadStream *stream, byte bitsPerPixel, byte bytesPerPixel); - void skipBitsRect(Common::SeekableReadStream &stream, bool hasPalette); + void skipBitsRect(Common::SeekableReadStream &stream, bool withPalette); void decodeCompressedQuickTime(Common::SeekableReadStream &stream); void outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel); diff --git a/graphics/decoders/png.cpp b/graphics/decoders/png.cpp index bfaab6dc35..4f917b44b1 100644 --- a/graphics/decoders/png.cpp +++ b/graphics/decoders/png.cpp @@ -191,6 +191,7 @@ bool PNGDecoder::loadStream(Common::SeekableReadStream &stream) { } // After the transformations have been registered, the image data is read again. + png_set_interlace_handling(pngPtr); png_read_update_info(pngPtr, infoPtr); png_get_IHDR(pngPtr, infoPtr, &w, &h, &bitDepth, &colorType, NULL, NULL, NULL); width = w; diff --git a/graphics/decoders/png.h b/graphics/decoders/png.h index e52ddabd7d..5e608eb7b1 100644 --- a/graphics/decoders/png.h +++ b/graphics/decoders/png.h @@ -23,6 +23,7 @@ /* * PNG decoder used in engines: * - sword25 + * - wintermute * Dependencies: * - libpng */ diff --git a/graphics/decoders/tga.cpp b/graphics/decoders/tga.cpp index 0b2318e127..c3b9d84055 100644 --- a/graphics/decoders/tga.cpp +++ b/graphics/decoders/tga.cpp @@ -145,7 +145,10 @@ bool TGADecoder::readHeader(Common::SeekableReadStream &tga, byte &imageType, by if (pixelDepth == 24) { _format = PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0); } else if (pixelDepth == 32) { - _format = PixelFormat(4, 8, 8, 8, attributeBits, 16, 8, 0, 24); + // HACK: According to the spec, attributeBits should determine the amount + // of alpha-bits, however, as the game files that use this decoder seems + // to ignore that fact, we force the amount to 8 for 32bpp files for now. + _format = PixelFormat(4, 8, 8, 8, /* attributeBits */ 8, 16, 8, 0, 24); } else if (pixelDepth == 16 && imageType == TYPE_TRUECOLOR) { // 16bpp TGA is ARGB1555 _format = PixelFormat(2, 5, 5, 5, attributeBits, 10, 5, 0, 15); diff --git a/graphics/decoders/tga.h b/graphics/decoders/tga.h index dfdc5a4da9..d8ccf8f766 100644 --- a/graphics/decoders/tga.h +++ b/graphics/decoders/tga.h @@ -25,7 +25,7 @@ /* * TGA decoder used in engines: - * - none + * - wintermute */ #ifndef GRAPHICS_DECODERS_TGA_H |