diff options
Diffstat (limited to 'graphics')
-rw-r--r-- | graphics/decoders/bmp.h | 1 | ||||
-rw-r--r-- | graphics/decoders/iff.cpp | 241 | ||||
-rw-r--r-- | graphics/decoders/iff.h | 119 | ||||
-rw-r--r-- | graphics/decoders/jpeg.cpp | 16 | ||||
-rw-r--r-- | graphics/decoders/jpeg.h | 1 | ||||
-rw-r--r-- | graphics/decoders/pict.cpp | 11 | ||||
-rw-r--r-- | graphics/decoders/png.cpp | 2 | ||||
-rw-r--r-- | graphics/decoders/png.h | 1 | ||||
-rw-r--r-- | graphics/decoders/tga.h | 2 | ||||
-rw-r--r-- | graphics/iff.cpp | 268 | ||||
-rw-r--r-- | graphics/iff.h | 137 | ||||
-rw-r--r-- | graphics/module.mk | 2 | ||||
-rw-r--r-- | graphics/primitives.cpp | 2 | ||||
-rw-r--r-- | graphics/primitives.h | 2 | ||||
-rw-r--r-- | graphics/scaler.cpp | 2 | ||||
-rw-r--r-- | graphics/scaler/aspect.cpp | 18 | ||||
-rw-r--r-- | graphics/thumbnail.cpp | 96 | ||||
-rw-r--r-- | graphics/thumbnail.h | 2 |
18 files changed, 467 insertions, 456 deletions
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/iff.cpp b/graphics/decoders/iff.cpp new file mode 100644 index 0000000000..50c7b4f7de --- /dev/null +++ b/graphics/decoders/iff.cpp @@ -0,0 +1,241 @@ +/* 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/iff_container.h" +#include "common/stream.h" +#include "common/util.h" + +#include "graphics/decoders/iff.h" + +namespace Graphics { + +IFFDecoder::IFFDecoder() { + _surface = 0; + _palette = 0; + + destroy(); +} + +IFFDecoder::~IFFDecoder() { + destroy(); +} + +void IFFDecoder::destroy() { + if (_surface) { + _surface->free(); + delete _surface; + _surface = 0; + } + + if (_palette) { + delete[] _palette; + _palette = 0; + } + + memset(&_header, 0, sizeof(Header)); + _paletteRanges.clear(); + _type = TYPE_UNKNOWN; + _paletteColorCount = 0; + _numRelevantPlanes = 8; + _pixelPacking = false; +} + +bool IFFDecoder::loadStream(Common::SeekableReadStream &stream) { + destroy(); + + const uint32 form = stream.readUint32BE(); + + if (form != ID_FORM) { + warning("Failed reading IFF-file"); + return false; + } + + stream.skip(4); + + const uint32 type = stream.readUint32BE(); + + switch (type) { + case ID_ILBM: + _type = TYPE_ILBM; + break; + case ID_PBM: + _type = TYPE_PBM; + break; + } + + if (type == TYPE_UNKNOWN) { + warning("Failed reading IFF-file"); + return false; + } + + while (1) { + const uint32 chunkType = stream.readUint32BE(); + const uint32 chunkSize = stream.readUint32BE(); + + if (stream.eos()) + break; + + switch (chunkType) { + case ID_BMHD: + loadHeader(stream); + break; + case ID_CMAP: + loadPalette(stream, chunkSize); + break; + case ID_CRNG: + loadPaletteRange(stream, chunkSize); + break; + case ID_BODY: + loadBitmap(stream); + break; + default: + stream.skip(chunkSize); + } + } + + return true; +} + +void IFFDecoder::loadHeader(Common::SeekableReadStream &stream) { + _header.width = stream.readUint16BE(); + _header.height = stream.readUint16BE(); + _header.x = stream.readUint16BE(); + _header.y = stream.readUint16BE(); + _header.numPlanes = stream.readByte(); + _header.masking = stream.readByte(); + _header.compression = stream.readByte(); + _header.flags = stream.readByte(); + _header.transparentColor = stream.readUint16BE(); + _header.xAspect = stream.readByte(); + _header.yAspect = stream.readByte(); + _header.pageWidth = stream.readUint16BE(); + _header.pageHeight = stream.readUint16BE(); + + assert(_header.width >= 1); + assert(_header.height >= 1); + assert(_header.numPlanes >= 1 && _header.numPlanes <= 8 && _header.numPlanes != 7); +} + +void IFFDecoder::loadPalette(Common::SeekableReadStream &stream, const uint32 size) { + _palette = new byte[size]; + stream.read(_palette, size); + _paletteColorCount = size / 3; +} + +void IFFDecoder::loadPaletteRange(Common::SeekableReadStream &stream, const uint32 size) { + PaletteRange range; + + range.timer = stream.readSint16BE(); + range.step = stream.readSint16BE(); + range.flags = stream.readSint16BE(); + range.first = stream.readByte(); + range.last = stream.readByte(); + + _paletteRanges.push_back(range); +} + +void IFFDecoder::loadBitmap(Common::SeekableReadStream &stream) { + _numRelevantPlanes = MIN(_numRelevantPlanes, _header.numPlanes); + + if (_numRelevantPlanes != 1 && _numRelevantPlanes != 2 && _numRelevantPlanes != 4) + _pixelPacking = false; + + uint16 outPitch = _header.width; + + if (_pixelPacking) + outPitch /= (8 / _numRelevantPlanes); + + // FIXME: CLUT8 is not a proper format for packed bitmaps but there is no way to tell it to use 1, 2 or 4 bits per pixel + _surface = new Graphics::Surface(); + _surface->create(outPitch, _header.height, Graphics::PixelFormat::createFormatCLUT8()); + + if (_type == TYPE_ILBM) { + uint32 scanlinePitch = ((_header.width + 15) >> 4) << 1; + byte *scanlines = new byte[scanlinePitch * _header.numPlanes]; + byte *data = (byte *)_surface->pixels; + + for (uint16 i = 0; i < _header.height; ++i) { + byte *scanline = scanlines; + + for (uint16 j = 0; j < _header.numPlanes; ++j) { + uint16 outSize = scanlinePitch; + + if (_header.compression) { + Common::PackBitsReadStream packStream(stream); + packStream.read(scanline, outSize); + } else { + stream.read(scanline, outSize); + } + + scanline += outSize; + } + + packPixels(scanlines, data, scanlinePitch, outPitch); + data += outPitch; + } + + delete[] scanlines; + } else if (_type == TYPE_PBM) { + byte *data = (byte *)_surface->pixels; + uint32 outSize = _header.width * _header.height; + + if (_header.compression) { + Common::PackBitsReadStream packStream(stream); + packStream.read(data, outSize); + } else { + stream.read(data, outSize); + } + } +} + +void IFFDecoder::packPixels(byte *scanlines, byte *data, const uint16 scanlinePitch, const uint16 outPitch) { + uint32 numPixels = _header.width; + + if (_pixelPacking) + numPixels = outPitch * (8 / _numRelevantPlanes); + + for (uint32 x = 0; x < numPixels; ++x) { + byte *scanline = scanlines; + byte pixel = 0; + byte offset = x >> 3; + byte bit = 0x80 >> (x & 7); + + // first build a pixel by scanning all the usable planes in the input + for (uint32 plane = 0; plane < _numRelevantPlanes; ++plane) { + if (scanline[offset] & bit) + pixel |= (1 << plane); + + scanline += scanlinePitch; + } + + // then output the pixel according to the requested packing + if (!_pixelPacking) + data[x] = pixel; + else if (_numRelevantPlanes == 1) + data[x / 8] |= (pixel << (x & 7)); + else if (_numRelevantPlanes == 2) + data[x / 4] |= (pixel << ((x & 3) << 1)); + else if (_numRelevantPlanes == 4) + data[x / 2] |= (pixel << ((x & 1) << 2)); + } +} + +} // End of namespace Graphics diff --git a/graphics/decoders/iff.h b/graphics/decoders/iff.h new file mode 100644 index 0000000000..beac62e519 --- /dev/null +++ b/graphics/decoders/iff.h @@ -0,0 +1,119 @@ +/* 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. + */ + +/** + * @file + * Image decoder used in engines: + * - gob + * - parallaction + * - queen + * - saga + */ + +#ifndef GRAPHICS_DECODERS_IFF_H +#define GRAPHICS_DECODERS_IFF_H + +#include "common/array.h" +#include "common/endian.h" + +#include "graphics/surface.h" +#include "graphics/decoders/image_decoder.h" + +namespace Common { +class SeekableReadStream; +} + +namespace Graphics { + +struct Surface; + +class IFFDecoder : public ImageDecoder { +public: + struct Header { + uint16 width, height; + uint16 x, y; + byte numPlanes; + byte masking; + byte compression; + byte flags; + uint16 transparentColor; + byte xAspect, yAspect; + uint16 pageWidth, pageHeight; + }; + + struct PaletteRange { + int16 timer, step, flags; + byte first, last; + }; + + enum Type { + TYPE_UNKNOWN = 0, + TYPE_ILBM, + TYPE_PBM + }; + + IFFDecoder(); + virtual ~IFFDecoder(); + + // ImageDecoder API + void destroy(); + bool loadStream(Common::SeekableReadStream &stream); + const Header *getHeader() const { return &_header; } + const Surface *getSurface() const { return _surface; } + const byte *getPalette() const { return _palette; } + const Common::Array<PaletteRange> &getPaletteRanges() const { return _paletteRanges; } + uint16 getPaletteColorCount() const { return _paletteColorCount; } + + /** + * The number of planes to decode, also determines the pixel packing if _packPixels is true. + * 8 == decode all planes, map 1 pixel in 1 byte. (default, no packing even if _packPixels is true) + */ + void setNumRelevantPlanes(const uint8 numRelevantPlanes) { _numRelevantPlanes = numRelevantPlanes; } + + /** + * Enables pixel packing, the amount of packing is determined by _numRelevantPlanes + * 1 == decode first plane, pack 8 pixels in 1 byte. This makes _surface->w 1/8th of _header.width + * 2 == decode first 2 planes, pack 4 pixels in 1 byte. This makes _surface->w 1/4th of _header.width + * 4 == decode first 4 planes, pack 2 pixels in 1 byte. This makes _surface->w half of _header.width + * Packed bitmaps won't have a proper surface format since there is no way to tell it to use 1, 2 or 4 bits per pixel + */ + void setPixelPacking(const bool pixelPacking) { _pixelPacking = pixelPacking; } +private: + + Header _header; + Surface *_surface; + byte *_palette; + Common::Array<PaletteRange> _paletteRanges; + Type _type; + uint16 _paletteColorCount; + uint8 _numRelevantPlanes; + bool _pixelPacking; + + void loadHeader(Common::SeekableReadStream &stream); + void loadPalette(Common::SeekableReadStream &stream, const uint32 size); + void loadPaletteRange(Common::SeekableReadStream &stream, const uint32 size); + void loadBitmap(Common::SeekableReadStream &stream); + void packPixels(byte *scanlines, byte *data, const uint16 scanlinePitch, const uint16 outPitch); +}; + +} // End of namespace Graphics + +#endif // GRAPHICS_DECODERS_IFF_H diff --git a/graphics/decoders/jpeg.cpp b/graphics/decoders/jpeg.cpp index 08bc1f7a3d..75fdcd6e5a 100644 --- a/graphics/decoders/jpeg.cpp +++ b/graphics/decoders/jpeg.cpp @@ -74,7 +74,7 @@ const Surface *JPEGDecoder::getSurface() const { // Create an RGBA8888 surface _rgbSurface = new Graphics::Surface(); - _rgbSurface->create(_w, _h, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0)); + _rgbSurface->create(_w, _h, Graphics::PixelFormat(4, 8, 8, 8, 0, 24, 16, 8, 0)); // Get our component surfaces const Graphics::Surface *yComponent = getComponent(1); @@ -215,28 +215,34 @@ bool JPEGDecoder::loadStream(Common::SeekableReadStream &stream) { bool JPEGDecoder::readJFIF() { uint16 length = _stream->readUint16BE(); uint32 tag = _stream->readUint32BE(); + if (tag != MKTAG('J', 'F', 'I', 'F')) { warning("JPEGDecoder::readJFIF() tag mismatch"); return false; } + if (_stream->readByte() != 0) { // NULL warning("JPEGDecoder::readJFIF() NULL mismatch"); return false; } + byte majorVersion = _stream->readByte(); byte minorVersion = _stream->readByte(); - if (majorVersion != 1 || minorVersion != 1) - warning("JPEGDecoder::readJFIF() Non-v1.1 JPEGs may not be handled correctly"); + if (majorVersion != 1 || minorVersion > 2) + warning("JPEGDecoder::readJFIF(): v%d.%02d JPEGs may not be handled correctly", majorVersion, minorVersion); + /* byte densityUnits = */_stream->readByte(); /* uint16 xDensity = */_stream->readUint16BE(); /* uint16 yDensity = */_stream->readUint16BE(); byte thumbW = _stream->readByte(); byte thumbH = _stream->readByte(); + _stream->seek(thumbW * thumbH * 3, SEEK_CUR); // Ignore thumbnail if (length != (thumbW * thumbH * 3) + 16) { warning("JPEGDecoder::readJFIF() length mismatch"); return false; } + return true; } @@ -481,8 +487,8 @@ bool JPEGDecoder::readDQT() { // Validate the table id tableId &= 0xF; - if (tableId > JPEG_MAX_QUANT_TABLES) { - warning("JPEG: Invalid number of components"); + if (tableId >= JPEG_MAX_QUANT_TABLES) { + warning("JPEG: Invalid quantization table"); return false; } 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/pict.cpp b/graphics/decoders/pict.cpp index d35e5c3064..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. diff --git a/graphics/decoders/png.cpp b/graphics/decoders/png.cpp index 4f917b44b1..11e26162eb 100644 --- a/graphics/decoders/png.cpp +++ b/graphics/decoders/png.cpp @@ -227,7 +227,7 @@ bool PNGDecoder::loadStream(Common::SeekableReadStream &stream) { png_read_end(pngPtr, NULL); // Destroy libpng structures - png_destroy_read_struct(&pngPtr, &infoPtr, NULL); + png_destroy_read_struct(&pngPtr, &infoPtr, &endInfo); // We no longer need the file stream, thus close it here _stream = 0; 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.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 diff --git a/graphics/iff.cpp b/graphics/iff.cpp deleted file mode 100644 index 4011126bd3..0000000000 --- a/graphics/iff.cpp +++ /dev/null @@ -1,268 +0,0 @@ -/* 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 "graphics/iff.h" -#include "graphics/surface.h" - -#include "common/endian.h" -#include "common/func.h" -#include "common/iff_container.h" -#include "common/textconsole.h" -#include "common/util.h" - -namespace Graphics { - -void BMHD::load(Common::ReadStream *stream) { - assert(stream); - stream->read(this, sizeof(BMHD)); - width = FROM_BE_16(width); - height = FROM_BE_16(height); - x = FROM_BE_16(x); - y = FROM_BE_16(y); - transparentColor = FROM_BE_16(transparentColor); - pageWidth = FROM_BE_16(pageWidth); - pageHeight = FROM_BE_16(pageHeight); -} - - -void ILBMDecoder::loadHeader(Common::ReadStream *stream) { - _header.load(stream); -} - -void ILBMDecoder::loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream) { - assert(stream); - uint32 numPlanes = MIN(mode & ILBM_UNPACK_PLANES, (uint32)_header.depth); - assert(numPlanes == 1 || numPlanes == 2 || numPlanes == 3 || numPlanes == 4 || numPlanes == 5 || numPlanes == 8); - - bool packPixels = (mode & ILBM_PACK_PLANES) != 0; - if (numPlanes != 1 && numPlanes != 2 && numPlanes != 4) { - packPixels = false; - } - - uint32 outPitch = _header.width; - if (packPixels) { - outPitch /= (8 / numPlanes); - } - byte *out = buffer; - - switch (_header.pack) { - case 1: { // PackBits compressed bitmap - Graphics::PackBitsReadStream packStream(*stream); - - // setup a buffer to hold enough data to build a line in the output - uint32 scanlineWidth = ((_header.width + 15) / 16) << 1; - byte *scanline = new byte[scanlineWidth * _header.depth]; - - for (uint i = 0; i < _header.height; ++i) { - byte *s = scanline; - for (uint32 j = 0; j < _header.depth; ++j) { - packStream.read(s, scanlineWidth); - s += scanlineWidth; - } - - planarToChunky(out, outPitch, scanline, scanlineWidth, numPlanes, packPixels); - out += outPitch; - } - - delete[] scanline; - break; - } - - default: - // implement other compression types here! - error("only RLE compressed ILBM files are supported"); - break; - } -} - -void ILBMDecoder::planarToChunky(byte *out, uint32 outPitch, byte *in, uint32 inWidth, uint32 nPlanes, bool packPlanes) { - byte pix, ofs, bit; - byte *s; - - uint32 pixels = outPitch; - if (packPlanes) { - pixels *= (8 / nPlanes); - } - - for (uint32 x = 0; x < pixels; ++x) { - - pix = 0; - ofs = x >> 3; - bit = 0x80 >> (x & 7); - - // first build a pixel by scanning all the usable planes in the input - s = in; - for (uint32 plane = 0; plane < nPlanes; ++plane) { - if (s[ofs] & bit) { - pix |= (1 << plane); - } - s += inWidth; - } - - - // then output the pixel according to the requested packing - if (!packPlanes) { - out[x] = pix; - } else if (nPlanes == 1) { - out[x / 8] |= (pix << (x & 7)); - } else if (nPlanes == 2) { - out[x / 4] |= (pix << ((x & 3) << 1)); - } else if (nPlanes == 4) { - out[x / 2] |= (pix << ((x & 1) << 2)); - } - } - -} - - -// handles PBM subtype of IFF FORM files -// -struct PBMDecoder { - /** - * PBM header data, necessary for loadBitmap() - */ - Graphics::BMHD _header; - - /** - * Fills the _header member from the given stream. - */ - void loadHeader(Common::ReadStream *stream); - - /** - * Loads and unpacks the PBM bitmap data from the stream into the buffer. - * The functions assumes the buffer is large enough to contain all data. - */ - void loadBitmap(byte *buffer, Common::ReadStream *stream); -}; - -void PBMDecoder::loadHeader(Common::ReadStream *stream) { - _header.load(stream); -} - - -void PBMDecoder::loadBitmap(byte *buffer, Common::ReadStream *stream) { - uint32 outSize = _header.width * _header.height; - - switch (_header.pack) { - case 0: - stream->read(buffer, outSize); - break; - - case 1: { - PackBitsReadStream packStream(*stream); - packStream.read(buffer, outSize); - break; - } - } -} - - -struct PBMLoader { - PBMDecoder _decoder; - Surface *_surface; - byte *_colors; - - void load(Common::ReadStream &input, Surface &surface, byte *&colors) { - _surface = &surface; - _colors = colors; - Common::IFFParser parser(&input); - Common::Functor1Mem<Common::IFFChunk &, bool, PBMLoader> c(this, &PBMLoader::callback); - parser.parse(c); - } - - bool callback(Common::IFFChunk &chunk) { - switch (chunk._type) { - case ID_BMHD: - _decoder.loadHeader(chunk._stream); - break; - - case ID_CMAP: - if (_colors) { - chunk._stream->read(_colors, chunk._size); - } - break; - - case ID_BODY: - if (_surface) { - _surface->create(_decoder._header.width, _decoder._header.height, PixelFormat::createFormatCLUT8()); - _decoder.loadBitmap((byte *)_surface->pixels, chunk._stream); - } - return true; // stop the parser - } - - return false; - } -}; - -void decodePBM(Common::ReadStream &input, Surface &surface, byte *colors) { - PBMLoader loader; - loader.load(input, surface, colors); -} - - - - -PackBitsReadStream::PackBitsReadStream(Common::ReadStream &input) : _input(&input) { -} - -PackBitsReadStream::~PackBitsReadStream() { -} - -bool PackBitsReadStream::eos() const { - return _input->eos(); -} - -uint32 PackBitsReadStream::read(void *dataPtr, uint32 dataSize) { - byte *out = (byte *)dataPtr; - uint32 left = dataSize; - - uint32 lenR = 0, lenW = 0; - while (left > 0 && !_input->eos()) { - lenR = _input->readByte(); - - if (lenR == 128) { - // no-op - lenW = 0; - } else if (lenR <= 127) { - // literal run - lenR++; - lenW = MIN(lenR, left); - for (uint32 j = 0; j < lenW; j++) { - *out++ = _input->readByte(); - } - for (; lenR > lenW; lenR--) { - _input->readByte(); - } - } else { // len > 128 - // expand run - lenW = MIN((256 - lenR) + 1, left); - byte val = _input->readByte(); - memset(out, val, lenW); - out += lenW; - } - - left -= lenW; - } - - return dataSize - left; -} - -} // End of namespace Graphics diff --git a/graphics/iff.h b/graphics/iff.h deleted file mode 100644 index 4d88148372..0000000000 --- a/graphics/iff.h +++ /dev/null @@ -1,137 +0,0 @@ -/* 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. - */ - -/* - * Bitmap decoder used in engines: - * - parallaction - * - saga - */ - -#ifndef GRAPHICS_IFF_H -#define GRAPHICS_IFF_H - -#include "common/stream.h" - -namespace Graphics { - -struct Surface; - - -struct BMHD { - uint16 width, height; - uint16 x, y; - byte depth; - byte masking; - byte pack; - byte flags; - uint16 transparentColor; - byte xAspect, yAspect; - uint16 pageWidth, pageHeight; - - BMHD() { - memset(this, 0, sizeof(*this)); - } - - void load(Common::ReadStream *stream); -}; - - -struct ILBMDecoder { - /** - * ILBM header data, necessary for loadBitmap() - */ - Graphics::BMHD _header; - - /** - * Available decoding modes for loadBitmap(). - */ - enum { - ILBM_UNPACK_PLANES = 0xFF, ///< Decode all bitplanes, and map 1 pixel to 1 byte. - ILBM_PACK_PLANES = 0x100, ///< Request unpacking, used as a mask with below options. - - ILBM_1_PLANES = 1, ///< Decode only the first bitplane, don't pack. - ILBM_1_PACK_PLANES = ILBM_1_PLANES | ILBM_PACK_PLANES, ///< Decode only the first bitplane, pack 8 pixels in 1 byte. - ILBM_2_PLANES = 2, ///< Decode first 2 bitplanes, don't pack. - ILBM_2_PACK_PLANES = ILBM_2_PLANES | ILBM_PACK_PLANES, ///< Decode first 2 bitplanes, pack 4 pixels in 1 byte. - ILBM_3_PLANES = 3, ///< Decode first 3 bitplanes, don't pack. - ILBM_4_PLANES = 4, ///< Decode first 4 bitplanes, don't pack. - ILBM_4_PACK_PLANES = ILBM_4_PLANES | ILBM_PACK_PLANES, ///< Decode first 4 bitplanes, pack 2 pixels in 1 byte. - ILBM_5_PLANES = 5, ///< Decode first 5 bitplanes, don't pack. - ILBM_8_PLANES = 8 ///< Decode all 8 bitplanes. - }; - - /** - * Fills the _header member from the given stream. - */ - void loadHeader(Common::ReadStream *stream); - - /** - * Loads and unpacks the ILBM bitmap data from the stream into the buffer. - * The functions assumes the buffer is large enough to contain all data. - * The caller controls how data should be packed by choosing mode from - * the enum above. - */ - void loadBitmap(uint32 mode, byte *buffer, Common::ReadStream *stream); - - /** - * Converts from bitplanar to chunky representation. Intended for internal - * usage, but you can be (ab)use it from client code if you know what you - * are doing. - */ - void planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth, uint32 nPlanes, bool packPlanes); -}; - - - -/** - * Handles PBM subtype of IFF FORM files - */ -void decodePBM(Common::ReadStream &input, Surface &surface, byte *colors); - - -/** - * Decode a given PackBits encoded stream. - * - * PackBits is an RLE compression algorithm introduced by Apple. It is also - * used to encode ILBM and PBM subtypes of IFF files, and some flavors of - * TIFF. - * - * As there is no compression across row boundaries in the above formats, - * read() will extract a *new* line on each call, discarding any alignment - * or padding. - */ -class PackBitsReadStream : public Common::ReadStream { - -protected: - Common::ReadStream *_input; - -public: - PackBitsReadStream(Common::ReadStream &input); - ~PackBitsReadStream(); - - virtual bool eos() const; - - uint32 read(void *dataPtr, uint32 dataSize); -}; - -} // End of namespace Graphics - -#endif diff --git a/graphics/module.mk b/graphics/module.mk index f560d9dc97..8b63435905 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -11,7 +11,6 @@ MODULE_OBJS := \ fonts/newfont.o \ fonts/ttf.o \ fonts/winfont.o \ - iff.o \ maccursor.o \ primitives.o \ scaler.o \ @@ -24,6 +23,7 @@ MODULE_OBJS := \ wincursor.o \ yuv_to_rgb.o \ decoders/bmp.o \ + decoders/iff.o \ decoders/jpeg.o \ decoders/pcx.o \ decoders/pict.o \ diff --git a/graphics/primitives.cpp b/graphics/primitives.cpp index b88db39f36..c140dc8644 100644 --- a/graphics/primitives.cpp +++ b/graphics/primitives.cpp @@ -78,4 +78,4 @@ void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, int color drawLine(x0 + x, y0 + y, x1 + x, y1 + y, color, plotProc, data); } -} // End of namespace Graphics +} // End of namespace Graphics diff --git a/graphics/primitives.h b/graphics/primitives.h index f0780afc2e..f4a92683ab 100644 --- a/graphics/primitives.h +++ b/graphics/primitives.h @@ -27,6 +27,6 @@ namespace Graphics { void drawLine(int x0, int y0, int x1, int y1, int color, void (*plotProc)(int, int, int, void *), void *data); void drawThickLine(int x0, int y0, int x1, int y1, int penX, int penY, int color, void (*plotProc)(int, int, int, void *), void *data); -} // End of namespace Graphics +} // End of namespace Graphics #endif diff --git a/graphics/scaler.cpp b/graphics/scaler.cpp index b81e8937a8..3325fd4db2 100644 --- a/graphics/scaler.cpp +++ b/graphics/scaler.cpp @@ -152,7 +152,7 @@ void InitScalers(uint32 BitFormat) { g_dotmatrix[12] = g_dotmatrix[14] = format.RGBToColor(63, 63, 63); } -void DestroyScalers(){ +void DestroyScalers() { #ifdef USE_HQ_SCALERS free(RGBtoYUV); RGBtoYUV = 0; diff --git a/graphics/scaler/aspect.cpp b/graphics/scaler/aspect.cpp index 327e7c5e89..92d6c5777e 100644 --- a/graphics/scaler/aspect.cpp +++ b/graphics/scaler/aspect.cpp @@ -23,11 +23,7 @@ #include "graphics/scaler/intern.h" #include "graphics/scaler/aspect.h" -#ifdef OPENPANDORA -#define NEON_ASPECT_CORRECTOR -#endif - -#ifdef NEON_ASPECT_CORRECTOR +#ifdef USE_ARM_NEON_ASPECT_CORRECTOR #include <arm_neon.h> #endif @@ -62,7 +58,7 @@ static inline void interpolate5Line(uint16 *dst, const uint16 *srcA, const uint1 #if ASPECT_MODE == kVeryFastAndGoodAspectMode -#ifdef NEON_ASPECT_CORRECTOR +#ifdef USE_ARM_NEON_ASPECT_CORRECTOR template<typename ColorMask> static void interpolate5LineNeon(uint16 *dst, const uint16 *srcA, const uint16 *srcB, int width, int k1, int k2) { @@ -97,31 +93,31 @@ static void interpolate5LineNeon(uint16 *dst, const uint16 *srcA, const uint16 * width -= 4; } } -#endif +#endif // USE_ARM_NEON_ASPECT_CORRECTOR template<typename ColorMask, int scale> static void interpolate5Line(uint16 *dst, const uint16 *srcA, const uint16 *srcB, int width) { if (scale == 1) { -#ifdef NEON_ASPECT_CORRECTOR +#ifdef USE_NEON_ASPECT_CORRECTOR int width4 = width & ~3; interpolate5LineNeon<ColorMask>(dst, srcA, srcB, width4, 7, 1); srcA += width4; srcB += width4; dst += width4; width -= width4; -#endif +#endif // USE_ARM_NEON_ASPECT_CORRECTOR while (width--) { *dst++ = interpolate16_7_1<ColorMask>(*srcB++, *srcA++); } } else { -#ifdef NEON_ASPECT_CORRECTOR +#ifdef USE_ARM_NEON_ASPECT_CORRECTOR int width4 = width & ~3; interpolate5LineNeon<ColorMask>(dst, srcA, srcB, width4, 5, 3); srcA += width4; srcB += width4; dst += width4; width -= width4; -#endif +#endif // USE_ARM_NEON_ASPECT_CORRECTOR while (width--) { *dst++ = interpolate16_5_3<ColorMask>(*srcB++, *srcA++); } diff --git a/graphics/thumbnail.cpp b/graphics/thumbnail.cpp index db61d828d2..ddb377306d 100644 --- a/graphics/thumbnail.cpp +++ b/graphics/thumbnail.cpp @@ -30,17 +30,17 @@ namespace Graphics { namespace { -#define THMB_VERSION 1 +#define THMB_VERSION 2 struct ThumbnailHeader { uint32 type; uint32 size; byte version; uint16 width, height; - byte bpp; + PixelFormat format; }; -#define ThumbnailHeaderSize (4+4+1+2+2+1) +#define ThumbnailHeaderSize (4+4+1+2+2+(1+4+4)) bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool outputWarnings) { header.type = in.readUint32BE(); @@ -64,7 +64,22 @@ bool loadHeader(Common::SeekableReadStream &in, ThumbnailHeader &header, bool ou header.width = in.readUint16BE(); header.height = in.readUint16BE(); - header.bpp = in.readByte(); + header.format.bytesPerPixel = in.readByte(); + // Starting from version 2 on we serialize the whole PixelFormat. + if (header.version >= 2) { + header.format.rLoss = in.readByte(); + header.format.gLoss = in.readByte(); + header.format.bLoss = in.readByte(); + header.format.aLoss = in.readByte(); + + header.format.rShift = in.readByte(); + header.format.gShift = in.readByte(); + header.format.bShift = in.readByte(); + header.format.aShift = in.readByte(); + } else { + // Version 1 used a hardcoded RGB565. + header.format = createPixelFormat<565>(); + } return true; } @@ -100,23 +115,32 @@ Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in) { if (!loadHeader(in, header, true)) return 0; - if (header.bpp != 2) { - warning("trying to load thumbnail with unsupported bit depth %d", header.bpp); + if (header.format.bytesPerPixel != 2 && header.format.bytesPerPixel != 4) { + warning("trying to load thumbnail with unsupported bit depth %d", header.format.bytesPerPixel); return 0; } - Graphics::PixelFormat format = g_system->getOverlayFormat(); Graphics::Surface *const to = new Graphics::Surface(); - to->create(header.width, header.height, format); + to->create(header.width, header.height, header.format); - OverlayColor *pixels = (OverlayColor *)to->pixels; for (int y = 0; y < to->h; ++y) { - for (int x = 0; x < to->w; ++x) { - uint8 r, g, b; - colorToRGB<ColorMasks<565> >(in.readUint16BE(), r, g, b); - - // converting to current OSystem Color - *pixels++ = format.RGBToColor(r, g, b); + switch (header.format.bytesPerPixel) { + case 2: { + uint16 *pixels = (uint16 *)to->getBasePtr(0, y); + for (uint x = 0; x < to->w; ++x) { + *pixels++ = in.readUint16BE(); + } + } break; + + case 4: { + uint32 *pixels = (uint32 *)to->getBasePtr(0, y); + for (uint x = 0; x < to->w; ++x) { + *pixels++ = in.readUint32BE(); + } + } break; + + default: + assert(0); } } @@ -138,8 +162,8 @@ bool saveThumbnail(Common::WriteStream &out) { } bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb) { - if (thumb.format.bytesPerPixel != 2) { - warning("trying to save thumbnail with bpp different than 2"); + if (thumb.format.bytesPerPixel != 2 && thumb.format.bytesPerPixel != 4) { + warning("trying to save thumbnail with bpp %u", thumb.format.bytesPerPixel); return false; } @@ -149,19 +173,45 @@ bool saveThumbnail(Common::WriteStream &out, const Graphics::Surface &thumb) { header.version = THMB_VERSION; header.width = thumb.w; header.height = thumb.h; - header.bpp = thumb.format.bytesPerPixel; out.writeUint32BE(header.type); out.writeUint32BE(header.size); out.writeByte(header.version); out.writeUint16BE(header.width); out.writeUint16BE(header.height); - out.writeByte(header.bpp); - // TODO: for later this shouldn't be casted to uint16... - uint16 *pixels = (uint16 *)thumb.pixels; - for (uint16 p = 0; p < thumb.w*thumb.h; ++p, ++pixels) - out.writeUint16BE(*pixels); + // Serialize the PixelFormat + out.writeByte(thumb.format.bytesPerPixel); + out.writeByte(thumb.format.rLoss); + out.writeByte(thumb.format.gLoss); + out.writeByte(thumb.format.bLoss); + out.writeByte(thumb.format.aLoss); + out.writeByte(thumb.format.rShift); + out.writeByte(thumb.format.gShift); + out.writeByte(thumb.format.bShift); + out.writeByte(thumb.format.aShift); + + // Serialize the pixel data + for (uint y = 0; y < thumb.h; ++y) { + switch (thumb.format.bytesPerPixel) { + case 2: { + const uint16 *pixels = (const uint16 *)thumb.getBasePtr(0, y); + for (uint x = 0; x < thumb.w; ++x) { + out.writeUint16BE(*pixels++); + } + } break; + + case 4: { + const uint32 *pixels = (const uint32 *)thumb.getBasePtr(0, y); + for (uint x = 0; x < thumb.w; ++x) { + out.writeUint32BE(*pixels++); + } + } break; + + default: + assert(0); + } + } return true; } diff --git a/graphics/thumbnail.h b/graphics/thumbnail.h index df99568f42..45a0fdbf07 100644 --- a/graphics/thumbnail.h +++ b/graphics/thumbnail.h @@ -50,8 +50,6 @@ bool skipThumbnail(Common::SeekableReadStream &in); /** * Loads a thumbnail from the given input stream. - * The loaded thumbnail will be automatically converted to the - * current overlay pixelformat. */ Graphics::Surface *loadThumbnail(Common::SeekableReadStream &in); |