From f01d4c5aa84d80bac1355f8b709f4e1244fec3dc Mon Sep 17 00:00:00 2001 From: Tomas Jakobsson Date: Sun, 30 Dec 2012 19:33:59 +0100 Subject: COMMON: Add PackBitsReadStream to iff_container --- common/iff_container.cpp | 47 +++++++++++++++++++++++++++++++++++++++++++++++ common/iff_container.h | 41 +++++++++++++++++++++++++++++++++-------- 2 files changed, 80 insertions(+), 8 deletions(-) diff --git a/common/iff_container.cpp b/common/iff_container.cpp index 7bcbf86e0f..ffaa5c6d06 100644 --- a/common/iff_container.cpp +++ b/common/iff_container.cpp @@ -22,6 +22,7 @@ #include "common/iff_container.h" #include "common/substream.h" +#include "common/util.h" namespace Common { @@ -75,4 +76,50 @@ void IFFParser::parse(IFFCallback &callback) { } while (!stop); } + +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 Common diff --git a/common/iff_container.h b/common/iff_container.h index 104ecf0f36..a730930b2c 100644 --- a/common/iff_container.h +++ b/common/iff_container.h @@ -77,22 +77,22 @@ page 376) */ #define ID_copy MKTAG('(','c',')',' ') /* EA IFF 85 Generic Copyright text chunk */ -/* ILBM chunks */ +/* IFF chunks */ #define ID_BMHD MKTAG('B','M','H','D') -/* ILBM BitmapHeader */ +/* IFF BitmapHeader */ #define ID_CMAP MKTAG('C','M','A','P') -/* ILBM 8bit RGB colormap */ +/* IFF 8bit RGB colormap */ #define ID_GRAB MKTAG('G','R','A','B') -/* ILBM "hotspot" coordiantes */ +/* IFF "hotspot" coordiantes */ #define ID_DEST MKTAG('D','E','S','T') -/* ILBM destination image info */ +/* IFF destination image info */ #define ID_SPRT MKTAG('S','P','R','T') -/* ILBM sprite identifier */ +/* IFF sprite identifier */ #define ID_CAMG MKTAG('C','A','M','G') /* Amiga viewportmodes */ #define ID_BODY MKTAG('B','O','D','Y') -/* ILBM image data */ +/* IFF image data */ #define ID_CRNG MKTAG('C','R','N','G') /* color cycling */ #define ID_CCRT MKTAG('C','C','R','T') @@ -114,7 +114,7 @@ page 376) */ #define ID_PCHG MKTAG('P','C','H','G') /* Line by line palette control information (Sebastiano Vigna) */ #define ID_PRVW MKTAG('P','R','V','W') -/* A mini duplicate ILBM used for preview (Gary Bonham) */ +/* A mini duplicate IFF used for preview (Gary Bonham) */ #define ID_XBMI MKTAG('X','B','M','I') /* eXtended BitMap Information (Soft-Logik) */ #define ID_CTBL MKTAG('C','T','B','L') @@ -239,6 +239,31 @@ public: }; +/** + * 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); +}; + } // namespace Common #endif -- cgit v1.2.3 From fe2b4b39f73201ae599847235edfae18265fe0f1 Mon Sep 17 00:00:00 2001 From: Tomas Jakobsson Date: Sun, 6 Jan 2013 18:57:24 +0100 Subject: GRAPHICS: New IFFDecoder that decodes ILBM and PBM images --- graphics/decoders/iff.cpp | 241 ++++++++++++++++++++++++++++++++++++++++++++++ graphics/decoders/iff.h | 119 +++++++++++++++++++++++ graphics/module.mk | 1 + 3 files changed, 361 insertions(+) create mode 100644 graphics/decoders/iff.cpp create mode 100644 graphics/decoders/iff.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 &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 _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/module.mk b/graphics/module.mk index f560d9dc97..4e4428daac 100644 --- a/graphics/module.mk +++ b/graphics/module.mk @@ -24,6 +24,7 @@ MODULE_OBJS := \ wincursor.o \ yuv_to_rgb.o \ decoders/bmp.o \ + decoders/iff.o \ decoders/jpeg.o \ decoders/pcx.o \ decoders/pict.o \ -- cgit v1.2.3 From b85d51c4a3dc4cca681ca4b6cdd6826aabc7e68e Mon Sep 17 00:00:00 2001 From: Tomas Jakobsson Date: Sun, 30 Dec 2012 19:30:11 +0100 Subject: GOB: Update to new IFFDecoder for ILBM images --- engines/gob/inter.h | 2 +- engines/gob/inter_v7.cpp | 27 ++++++----- engines/gob/surface.cpp | 124 +++++------------------------------------------ engines/gob/surface.h | 32 +----------- 4 files changed, 29 insertions(+), 156 deletions(-) diff --git a/engines/gob/inter.h b/engines/gob/inter.h index 63bf3eb1c6..2aa837e777 100644 --- a/engines/gob/inter.h +++ b/engines/gob/inter.h @@ -693,7 +693,7 @@ protected: void o7_zeroVar(); void o7_getINIValue(); void o7_setINIValue(); - void o7_loadLBMPalette(); + void o7_loadIFFPalette(); void o7_opendBase(); void o7_closedBase(); void o7_getDBString(); diff --git a/engines/gob/inter_v7.cpp b/engines/gob/inter_v7.cpp index 6cf69ed9df..4d92386c94 100644 --- a/engines/gob/inter_v7.cpp +++ b/engines/gob/inter_v7.cpp @@ -27,6 +27,7 @@ #include "graphics/cursorman.h" #include "graphics/wincursor.h" +#include "graphics/decoders/iff.h" #include "gob/gob.h" #include "gob/global.h" @@ -72,7 +73,7 @@ void Inter_v7::setupOpcodesDraw() { OPCODEDRAW(0x95, o7_zeroVar); OPCODEDRAW(0xA1, o7_getINIValue); OPCODEDRAW(0xA2, o7_setINIValue); - OPCODEDRAW(0xA4, o7_loadLBMPalette); + OPCODEDRAW(0xA4, o7_loadIFFPalette); OPCODEDRAW(0xC4, o7_opendBase); OPCODEDRAW(0xC5, o7_closedBase); OPCODEDRAW(0xC6, o7_getDBString); @@ -523,7 +524,7 @@ void Inter_v7::o7_setINIValue() { _inis.setValue(file, section, key, value); } -void Inter_v7::o7_loadLBMPalette() { +void Inter_v7::o7_loadIFFPalette() { Common::String file = _vm->_game->_script->evalString(); if (!file.contains('.')) file += ".LBM"; @@ -534,26 +535,26 @@ void Inter_v7::o7_loadLBMPalette() { if (startIndex > stopIndex) SWAP(startIndex, stopIndex); - Common::SeekableReadStream *lbmFile = _vm->_dataIO->getFile(file); - if (!lbmFile) { - warning("o7_loadLBMPalette(): No such file \"%s\"", file.c_str()); + Common::SeekableReadStream *iffFile = _vm->_dataIO->getFile(file); + if (!iffFile) { + warning("o7_loadIFFPalette(): No such file \"%s\"", file.c_str()); return; } - ImageType type = Surface::identifyImage(*lbmFile); - if (type != kImageTypeLBM) { - warning("o7_loadLBMPalette(): \"%s\" is no LBM", file.c_str()); + ImageType type = Surface::identifyImage(*iffFile); + if (type != kImageTypeIFF) { + warning("o7_loadIFFPalette(): \"%s\" is no IFF", file.c_str()); return; } - byte palette[768]; - - LBMLoader lbm(*lbmFile); - if (!lbm.loadPalette(palette)) { - warning("o7_loadLBMPalette(): Failed reading palette from LBM \"%s\"", file.c_str()); + Graphics::IFFDecoder decoder; + decoder.loadStream(*iffFile); + if (!decoder.getPalette() || decoder.getPaletteColorCount() != 256) { + warning("o7_loadIFFPalette(): Failed reading palette from IFF \"%s\"", file.c_str()); return; } + byte *palette = (byte *)decoder.getPalette(); memset(palette , 0x00, 3); memset(palette + 765, 0xFF, 3); for (int i = 0; i < 768; i++) diff --git a/engines/gob/surface.cpp b/engines/gob/surface.cpp index afbb7c3bae..6b65eb6ab9 100644 --- a/engines/gob/surface.cpp +++ b/engines/gob/surface.cpp @@ -26,112 +26,15 @@ #include "common/stream.h" #include "common/util.h" #include "common/frac.h" +#include "common/textconsole.h" #include "graphics/primitives.h" #include "graphics/pixelformat.h" #include "graphics/surface.h" +#include "graphics/decoders/iff.h" namespace Gob { -LBMLoader::LBMLoader(Common::SeekableReadStream &stream) : _parser(&stream), - _hasHeader(false), _palette(0), _image(0) { - -} - -bool LBMLoader::loadHeader(Graphics::BMHD &header) { - if (!readHeader()) - return false; - - header = _decoder._header; - return true; -} - -bool LBMLoader::loadPalette(byte *palette) { - assert(!_palette); - assert(palette); - - _palette = palette; - - Common::Functor1Mem c(this, &LBMLoader::callbackPalette); - _parser.parse(c); - - if (!_palette) - return false; - - _palette = 0; - return true; -} - -bool LBMLoader::loadImage(byte *image) { - assert(!_image); - assert(image); - - if (!readHeader()) - return false; - - _image = image; - - Common::Functor1Mem c(this, &LBMLoader::callbackImage); - _parser.parse(c); - - if (!_image) - return false; - - _image = 0; - return true; -} - -bool LBMLoader::callbackHeader(Common::IFFChunk &chunk) { - if (chunk._type == ID_BMHD) { - if (chunk._size == sizeof(Graphics::BMHD)) { - _decoder.loadHeader(chunk._stream); - _hasHeader = true; - } - - return true; // Stop the IFF parser - } - - return false; -} - -bool LBMLoader::callbackPalette(Common::IFFChunk &chunk) { - assert(_palette); - - if (chunk._type == ID_CMAP) { - if (chunk._size == 768) { - if (chunk._stream->read(_palette, chunk._size) != chunk._size) - _palette = 0; - } else - _palette = 0; - - return true; // Stop the IFF parser - } - - return false; -} - -bool LBMLoader::callbackImage(Common::IFFChunk &chunk) { - assert(_image); - - if (chunk._type == ID_BODY) { - _decoder.loadBitmap(Graphics::ILBMDecoder::ILBM_UNPACK_PLANES, _image, chunk._stream); - return true; - } - - return false; -} - -bool LBMLoader::readHeader() { - if (_hasHeader) - return true; - - Common::Functor1Mem c(this, &LBMLoader::callbackHeader); - _parser.parse(c); - - return _hasHeader; -} - - static void plotPixel(int x, int y, int color, void *data) { Surface *dest = (Surface *)data; @@ -841,8 +744,8 @@ bool Surface::loadImage(Common::SeekableReadStream &stream, ImageType type) { switch (type) { case kImageTypeTGA: return loadTGA(stream); - case kImageTypeLBM: - return loadLBM(stream); + case kImageTypeIFF: + return loadIFF(stream); case kImageTypeBRC: return loadBRC(stream); case kImageTypeBMP: @@ -871,7 +774,7 @@ ImageType Surface::identifyImage(Common::SeekableReadStream &stream) { stream.seek(startPos); if (!strncmp(buffer , "FORM", 4)) - return kImageTypeLBM; + return kImageTypeIFF; if (!strncmp(buffer + 6, "JFIF", 4)) return kImageTypeJPEG; if (!strncmp(buffer , "BRC" , 3)) @@ -904,20 +807,17 @@ bool Surface::loadTGA(Common::SeekableReadStream &stream) { return false; } -bool Surface::loadLBM(Common::SeekableReadStream &stream) { +bool Surface::loadIFF(Common::SeekableReadStream &stream) { + Graphics::IFFDecoder decoder; + decoder.loadStream(stream); - LBMLoader loader(stream); - - Graphics::BMHD header; - loader.loadHeader(header); - - if (header.depth != 8) - // Only 8bpp LBMs supported for now + if (!decoder.getSurface()) return false; - resize(header.width, header.height); + resize(decoder.getSurface()->w, decoder.getSurface()->h); + memcpy(_vidMem, decoder.getSurface()->pixels, decoder.getSurface()->w * decoder.getSurface()->h); - return loader.loadImage(_vidMem); + return true; } bool Surface::loadBRC(Common::SeekableReadStream &stream) { diff --git a/engines/gob/surface.h b/engines/gob/surface.h index 8f895a7910..8a1b502a95 100644 --- a/engines/gob/surface.h +++ b/engines/gob/surface.h @@ -26,9 +26,6 @@ #include "common/scummsys.h" #include "common/ptr.h" #include "common/rational.h" -#include "common/iff_container.h" - -#include "graphics/iff.h" namespace Common { class SeekableReadStream; @@ -39,37 +36,12 @@ namespace Gob { enum ImageType { kImageTypeNone = -1, kImageTypeTGA = 0, - kImageTypeLBM, + kImageTypeIFF, kImageTypeBRC, kImageTypeBMP, kImageTypeJPEG }; -class LBMLoader { -public: - LBMLoader(Common::SeekableReadStream &stream); - - bool loadHeader (Graphics::BMHD &header); - bool loadPalette(byte *palette); - bool loadImage (byte *image); - -private: - Common::IFFParser _parser; - - bool _hasHeader; - - Graphics::ILBMDecoder _decoder; - - byte *_palette; - byte *_image; - - bool callbackHeader (Common::IFFChunk &chunk); - bool callbackPalette(Common::IFFChunk &chunk); - bool callbackImage (Common::IFFChunk &chunk); - - bool readHeader(); -}; - /** An iterator over a surface's image data, automatically handles different color depths. */ class Pixel { public: @@ -182,7 +154,7 @@ private: uint16 dWidth, uint16 dHeight, uint16 sWidth, uint16 sHeight); bool loadTGA (Common::SeekableReadStream &stream); - bool loadLBM (Common::SeekableReadStream &stream); + bool loadIFF (Common::SeekableReadStream &stream); bool loadBRC (Common::SeekableReadStream &stream); bool loadBMP (Common::SeekableReadStream &stream); bool loadJPEG(Common::SeekableReadStream &stream); -- cgit v1.2.3 From 548b505b687fec897b6d35903253f8935c8bf5ff Mon Sep 17 00:00:00 2001 From: Tomas Jakobsson Date: Sun, 6 Jan 2013 18:58:33 +0100 Subject: PARALLACTION: Update to new IFFDecoder for ILBM images --- engines/parallaction/disk.cpp | 145 --------------------------------------- engines/parallaction/disk.h | 33 --------- engines/parallaction/disk_br.cpp | 48 ++++++------- engines/parallaction/disk_ns.cpp | 57 ++++++++++----- engines/parallaction/module.mk | 1 - 5 files changed, 63 insertions(+), 221 deletions(-) delete mode 100644 engines/parallaction/disk.cpp diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk.cpp deleted file mode 100644 index f20e05771a..0000000000 --- a/engines/parallaction/disk.cpp +++ /dev/null @@ -1,145 +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 "common/iff_container.h" -#include "common/textconsole.h" - -#include "parallaction/disk.h" -#include "parallaction/graphics.h" - -namespace Parallaction { - -void ILBMLoader::setupBuffer(uint32 w, uint32 h) { - _intBuffer = 0; - switch (_bodyMode) { - case BODYMODE_SURFACE: - if (!_surf) { - _surf = new Graphics::Surface; - assert(_surf); - } - _surf->create(w, h, Graphics::PixelFormat::createFormatCLUT8()); - _mode = Graphics::ILBMDecoder::ILBM_UNPACK_PLANES; - _intBuffer = (byte *)_surf->pixels; - break; - - case BODYMODE_MASKBUFFER: - if (!_maskBuffer) { - _maskBuffer = new MaskBuffer; - assert(_maskBuffer); - } - _maskBuffer->create(w, h); - _mode = Graphics::ILBMDecoder::ILBM_2_PACK_PLANES; - _intBuffer = _maskBuffer->data; - break; - - case BODYMODE_PATHBUFFER: - if (!_pathBuffer) { - _pathBuffer = new PathBuffer; - assert(_pathBuffer); - } - _pathBuffer->create(w, h); - _mode = Graphics::ILBMDecoder::ILBM_1_PACK_PLANES; - _intBuffer = _pathBuffer->data; - break; - - default: - error("Invalid bodyMode '%i' for ILBMLoader", _bodyMode); - break; - } -} - -bool ILBMLoader::callback(Common::IFFChunk &chunk) { - switch (chunk._type) { - case ID_BMHD: - _decoder.loadHeader(chunk._stream); - break; - - case ID_CMAP: - if (_palette) { - chunk._stream->read(_palette, chunk._size); - } - break; - - case ID_CRNG: - if (_crng) { - PaletteFxRange *ptr = &_crng[_numCRNG]; - chunk._stream->read((byte *)ptr, chunk._size); - ptr->_timer = FROM_BE_16(ptr->_timer); - ptr->_step = FROM_BE_16(ptr->_step); - ptr->_flags = FROM_BE_16(ptr->_flags); - ++_numCRNG; - } - break; - - case ID_BODY: - setupBuffer(_decoder._header.width, _decoder._header.height); - assert(_intBuffer); - _decoder.loadBitmap(_mode, _intBuffer, chunk._stream); - return true; // stop the parser - } - - return false; -} - -void ILBMLoader::load(Common::ReadStream *in, bool disposeStream) { - Common::IFFParser parser(in, disposeStream); - Common::Functor1Mem< Common::IFFChunk&, bool, ILBMLoader > c(this, &ILBMLoader::callback); - parser.parse(c); -} - -ILBMLoader::ILBMLoader(uint32 bodyMode, byte *palette, PaletteFxRange *crng) { - _bodyMode = bodyMode; - _surf = 0; - _maskBuffer = 0; - _pathBuffer = 0; - _palette = palette; - _crng = crng; - _numCRNG = 0; -} - -ILBMLoader::ILBMLoader(Graphics::Surface *surf, byte *palette, PaletteFxRange *crng) { - _bodyMode = ILBMLoader::BODYMODE_SURFACE; - _surf = surf; - _palette = palette; - _crng = crng; - _numCRNG = 0; -} - -ILBMLoader::ILBMLoader(MaskBuffer *buffer) { - _bodyMode = ILBMLoader::BODYMODE_MASKBUFFER; - _maskBuffer = buffer; - _palette = 0; - _crng = 0; - _numCRNG = 0; -} - -ILBMLoader::ILBMLoader(PathBuffer *buffer) { - _bodyMode = ILBMLoader::BODYMODE_PATHBUFFER; - _pathBuffer = buffer; - _palette = 0; - _crng = 0; - _numCRNG = 0; -} - - - -} diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h index d1171c3179..63e33dcfbd 100644 --- a/engines/parallaction/disk.h +++ b/engines/parallaction/disk.h @@ -28,13 +28,10 @@ #include "common/archive.h" #include "common/str.h" -#include "graphics/iff.h" - namespace Common { class FSDirectory; class ReadStream; class SeekableReadStream; -struct IFFChunk; } namespace Graphics { @@ -86,36 +83,6 @@ public: virtual PathBuffer *loadPath(const char *name, uint32 w, uint32 h) { return 0; } }; -struct PaletteFxRange; - -struct ILBMLoader { - enum { - BODYMODE_SURFACE, - BODYMODE_MASKBUFFER, - BODYMODE_PATHBUFFER - }; - uint32 _bodyMode; - Graphics::Surface *_surf; - MaskBuffer *_maskBuffer; - PathBuffer *_pathBuffer; - byte *_palette; - PaletteFxRange *_crng; - uint32 _mode; - byte* _intBuffer; - uint32 _numCRNG; - Graphics::ILBMDecoder _decoder; - - ILBMLoader(uint32 bodyMode, byte *palette = 0, PaletteFxRange *crng = 0); - ILBMLoader(Graphics::Surface *surf, byte *palette = 0, PaletteFxRange *crng = 0); - ILBMLoader(MaskBuffer *buffer); - ILBMLoader(PathBuffer *buffer); - - bool callback(Common::IFFChunk &chunk); - void setupBuffer(uint32 w, uint32 h); - void load(Common::ReadStream *in, bool disposeStream = false); -}; - - class Disk_ns : public Disk { protected: diff --git a/engines/parallaction/disk_br.cpp b/engines/parallaction/disk_br.cpp index 8988897456..efddfb9935 100644 --- a/engines/parallaction/disk_br.cpp +++ b/engines/parallaction/disk_br.cpp @@ -20,11 +20,10 @@ * */ -#include "graphics/iff.h" - #include "common/config-manager.h" #include "common/fs.h" #include "common/textconsole.h" +#include "graphics/decoders/iff.h" #include "parallaction/parallaction.h" #include "parallaction/parser.h" @@ -459,8 +458,9 @@ void AmigaDisk_br::adjustForPalette(Graphics::Surface &surf, int transparentColo void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) { byte r,g,b; - byte *p; + const byte *p; Common::SeekableReadStream *stream; + Graphics::IFFDecoder decoder; uint i; stream = tryOpenFile("backs/" + Common::String(filename), ".ap"); @@ -488,15 +488,16 @@ void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) { } stream = openFile("backs/" + Common::String(filename), ".bkg"); + decoder.loadStream(*stream); - byte pal[768]; - ILBMLoader loader(&info.bg, pal); - loader.load(stream, true); - + info.bg.copyFrom(*decoder.getSurface()); info.width = info.bg.w; info.height = info.bg.h; - p = pal; + // Overwrite the first color (transparent key) in the palette + p = decoder.getPalette(); + info.palette.setEntry(0, p[0] >> 2, p[1] >> 2, p[2] >> 0); + for (i = 16; i < 32; i++) { r = *p >> 2; p++; @@ -507,9 +508,6 @@ void AmigaDisk_br::loadBackground(BackgroundInfo& info, const char *filename) { info.palette.setEntry(i, r, g, b); } - // Overwrite the first color (transparent key) in the palette - info.palette.setEntry(0, pal[0] >> 2, pal[1] >> 2, pal[2] >> 0); - // background data is drawn used the upper portion of the palette adjustForPalette(info.bg); } @@ -546,10 +544,15 @@ MaskBuffer *AmigaDisk_br::loadMask(const char *name, uint32 w, uint32 h) { return 0; } - ILBMLoader loader(ILBMLoader::BODYMODE_MASKBUFFER); - loader.load(stream, true); + Graphics::IFFDecoder decoder; + decoder.setNumRelevantPlanes(2); // use only 2 first bits from each pixels + decoder.setPixelPacking(true); // pack 4 2bit pixels into 1 byte + decoder.loadStream(*stream); - MaskBuffer *buffer = loader._maskBuffer; + MaskBuffer *buffer = new MaskBuffer; + // surface width was shrunk to 1/4th of the bitmap width due to the pixel packing + buffer->create(decoder.getSurface()->w * 4, decoder.getSurface()->h); + memcpy(buffer->data, decoder.getSurface()->pixels, buffer->size); buffer->bigEndian = true; finalpass(buffer->data, buffer->size); return buffer; @@ -580,12 +583,12 @@ GfxObj* AmigaDisk_br::loadStatic(const char* name) { Common::String sName = name; Common::SeekableReadStream *stream = openFile("ras/" + sName, ".ras"); + Graphics::IFFDecoder decoder; + decoder.loadStream(*stream); - ILBMLoader loader(ILBMLoader::BODYMODE_SURFACE); - loader.load(stream, true); - - Graphics::Surface* surf = loader._surf; + Graphics::Surface *surf = new Graphics::Surface; assert(surf); + surf->copyFrom(*decoder.getSurface()); // Static pictures are drawn used the upper half of the palette: this must be // done before shadow mask is applied. This way, only really transparent pixels @@ -717,16 +720,16 @@ GfxObj* AmigaDisk_br::loadObjects(const char *name, uint8 part) { debugC(5, kDebugDisk, "AmigaDisk_br::loadObjects"); Common::SeekableReadStream *stream = openFile(name); - ILBMLoader loader(ILBMLoader::BODYMODE_SURFACE); - loader.load(stream, true); + Graphics::IFFDecoder decoder; + decoder.loadStream(*stream); uint16 max = objectsMax[part]; if (_vm->getFeatures() & GF_DEMO) max = 72; byte *data = new byte[max * 2601]; - byte *srcPtr = (byte *)loader._surf->getBasePtr(0,0); - int w = loader._surf->w; + byte *srcPtr = (byte *)decoder.getSurface()->getBasePtr(0,0); + int w = decoder.getSurface()->w; // Convert to the expected display format for (int i = 0; i < max; i++) { @@ -741,7 +744,6 @@ GfxObj* AmigaDisk_br::loadObjects(const char *name, uint8 part) { dst += 51; } } - delete loader._surf; return new GfxObj(0, new Cnv(max, 51, 51, data, true)); } diff --git a/engines/parallaction/disk_ns.cpp b/engines/parallaction/disk_ns.cpp index bad854525d..f03f16ca37 100644 --- a/engines/parallaction/disk_ns.cpp +++ b/engines/parallaction/disk_ns.cpp @@ -22,9 +22,11 @@ #include "common/config-manager.h" #include "common/fs.h" +#include "common/iff_container.h" #include "common/memstream.h" #include "common/substream.h" #include "common/textconsole.h" +#include "graphics/decoders/iff.h" #include "parallaction/parser.h" #include "parallaction/parallaction.h" @@ -312,7 +314,7 @@ void DosDisk_ns::decodeCnv(byte *data, uint16 numFrames, uint16 width, uint16 he int32 decsize = numFrames * width * height; bool packed = (stream->size() - stream->pos()) != decsize; if (packed) { - Graphics::PackBitsReadStream decoder(*stream); + Common::PackBitsReadStream decoder(*stream); decoder.read(data, decsize); } else { stream->read(data, decsize); @@ -914,17 +916,15 @@ void AmigaDisk_ns::buildMask(byte* buf) { void AmigaDisk_ns::loadBackground(BackgroundInfo& info, const char *name) { - PaletteFxRange ranges[6]; - byte pal[768]; - Common::SeekableReadStream *s = openFile(name); - ILBMLoader loader(&info.bg, pal, ranges); - loader.load(s, true); + Graphics::IFFDecoder decoder; + decoder.loadStream(*s); + info.bg.copyFrom(*decoder.getSurface()); info.width = info.bg.w; info.height = info.bg.h; - byte *p = pal; + const byte *p = decoder.getPalette(); for (uint i = 0; i < 32; i++) { byte r = *p >> 2; p++; @@ -935,8 +935,15 @@ void AmigaDisk_ns::loadBackground(BackgroundInfo& info, const char *name) { info.palette.setEntry(i, r, g, b); } - for (uint j = 0; j < 6; j++) { - info.setPaletteRange(j, ranges[j]); + const Common::Array &paletteRanges = decoder.getPaletteRanges(); + for (uint j = 0; j < 6 && j < paletteRanges.size(); j++) { + PaletteFxRange range; + range._timer = paletteRanges[j].timer; + range._step = paletteRanges[j].step; + range._flags = paletteRanges[j].flags; + range._first = paletteRanges[j].first; + range._last = paletteRanges[j].last; + info.setPaletteRange(j, range); } } @@ -952,19 +959,25 @@ void AmigaDisk_ns::loadMask_internal(BackgroundInfo& info, const char *name) { return; // no errors if missing mask files: not every location has one } - byte pal[768]; - ILBMLoader loader(ILBMLoader::BODYMODE_MASKBUFFER, pal); - loader.load(s, true); + Graphics::IFFDecoder decoder; + decoder.setNumRelevantPlanes(2); // use only 2 first bits from each pixel + decoder.setPixelPacking(true); // pack 4 2bit pixels into 1 byte + decoder.loadStream(*s); + const byte *p = decoder.getPalette(); byte r, g, b; for (uint i = 0; i < 4; i++) { - r = pal[i*3]; - g = pal[i*3+1]; - b = pal[i*3+2]; + r = p[i*3]; + g = p[i*3+1]; + b = p[i*3+2]; info.layers[i] = (((r << 4) & 0xF00) | (g & 0xF0) | (b >> 4)) & 0xFF; } - info._mask = loader._maskBuffer; + info._mask = new MaskBuffer; + // surface width was shrunk to 1/4th of the bitmap width due to the pixel packing + info._mask->create(decoder.getSurface()->w * 4, decoder.getSurface()->h); + memcpy(info._mask->data, decoder.getSurface()->pixels, info._mask->size); + info._mask->bigEndian = true; } void AmigaDisk_ns::loadPath_internal(BackgroundInfo& info, const char *name) { @@ -977,9 +990,15 @@ void AmigaDisk_ns::loadPath_internal(BackgroundInfo& info, const char *name) { return; // no errors if missing path files: not every location has one } - ILBMLoader loader(ILBMLoader::BODYMODE_PATHBUFFER); - loader.load(s, true); - info._path = loader._pathBuffer; + Graphics::IFFDecoder decoder; + decoder.setNumRelevantPlanes(1); // use only first bit from each pixel + decoder.setPixelPacking(true); // pack 8 1bit pixels into 1 byte + decoder.loadStream(*s); + + info._path = new PathBuffer; + // surface width was shrunk to 1/8th of the bitmap width due to the pixel packing + info._path->create(decoder.getSurface()->w * 8, decoder.getSurface()->h); + memcpy(info._path->data, decoder.getSurface()->pixels, info._path->size); info._path->bigEndian = true; } diff --git a/engines/parallaction/module.mk b/engines/parallaction/module.mk index 36572a51df..f8a4e0b9a3 100644 --- a/engines/parallaction/module.mk +++ b/engines/parallaction/module.mk @@ -8,7 +8,6 @@ MODULE_OBJS := \ debug.o \ detection.o \ dialogue.o \ - disk.o \ disk_br.o \ disk_ns.o \ exec.o \ -- cgit v1.2.3 From 25752922efba96f2d4cd30fa35dbffa0c51bc31d Mon Sep 17 00:00:00 2001 From: Tomas Jakobsson Date: Wed, 2 Jan 2013 10:54:37 +0100 Subject: QUEEN: Update to new IFFDecoder for ILBM images --- engines/queen/display.cpp | 88 ++++++++++------------------------------------- engines/queen/display.h | 4 +-- 2 files changed, 21 insertions(+), 71 deletions(-) diff --git a/engines/queen/display.cpp b/engines/queen/display.cpp index cd9a1075fa..d7b20c203e 100644 --- a/engines/queen/display.cpp +++ b/engines/queen/display.cpp @@ -29,6 +29,7 @@ #include "graphics/cursorman.h" #include "graphics/palette.h" #include "graphics/surface.h" +#include "graphics/decoders/iff.h" #include "graphics/decoders/pcx.h" #include "queen/display.h" @@ -701,7 +702,7 @@ void Display::setupPanel() { uint8 *data = _vm->resource()->loadFile(dataName, 0, &dataSize); if (_vm->resource()->getPlatform() == Common::kPlatformAmiga) { - decodeLBM(data, dataSize, _panelBuf, PANEL_W, &panelWidth, &panelHeight, _pal.panel, 0, 32, 144); + decodeIFF(data, dataSize, _panelBuf, PANEL_W, &panelWidth, &panelHeight, _pal.panel, 0, 32, 144); } else { WRITE_LE_UINT16(data + 14, PANEL_H - 10); decodePCX(data, dataSize, _panelBuf + PANEL_W * 10, PANEL_W, &panelWidth, &panelHeight, _pal.panel, 144, 256); @@ -720,7 +721,7 @@ void Display::setupNewRoom(const char *name, uint16 room) { uint8 *data = _vm->resource()->loadFile(dataName, 0, &dataSize); if (_vm->resource()->getPlatform() == Common::kPlatformAmiga) { - decodeLBM(data, dataSize, _backdropBuf, BACKDROP_W, &_bdWidth, &_bdHeight, _pal.room, 0, 32); + decodeIFF(data, dataSize, _backdropBuf, BACKDROP_W, &_bdWidth, &_bdHeight, _pal.room, 0, 32); if (_bdHeight < BACKDROP_H) { memset(_backdropBuf + _bdHeight * BACKDROP_W, 0, (BACKDROP_H - _bdHeight) * BACKDROP_W); } @@ -828,73 +829,22 @@ void Display::decodePCX(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dst memcpy(dst + y * dstPitch, pcxSurface->getBasePtr(0, y), pcxSurface->w); } -void Display::decodeLBM(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd, uint8 colorBase) { - int planeCount = 0, planePitch = 0; - const uint8 *srcEnd = src + srcSize; - src += 12; - while (src < srcEnd) { - uint32 type = READ_BE_UINT32(src); - uint32 size = READ_BE_UINT32(src + 4); - src += 8; - switch (type) { - case MKTAG('B','M','H','D'): { - *w = READ_BE_UINT16(src + 0); - *h = READ_BE_UINT16(src + 2); - planeCount = src[8]; - planePitch = ((*w + 15) >> 4) * 2; - } - break; - case MKTAG('C','M','A','P'): { - assert(palStart <= palEnd && palEnd <= size / 3); - memcpy(pal, src + palStart * 3, (palEnd - palStart) * 3); - } - break; - case MKTAG('B','O','D','Y'): { - uint32 planarSize = (*h) * planeCount * planePitch; - uint8 *planarBuf = new uint8[planarSize]; - uint8 *dstPlanar = planarBuf; - for (int y = 0; y < *h; ++y) { - for (int p = 0; p < planeCount; ++p) { - const uint8 *end = dstPlanar + planePitch; - while (dstPlanar < end) { - int code = (int8)*src++; - if (code != -128) { - if (code < 0) { - code = -code + 1; - memset(dstPlanar, *src++, code); - } else { - ++code; - memcpy(dstPlanar, src, code); - src += code; - } - dstPlanar += code; - } - } - } - } - src = planarBuf; - for (int y = 0; y < *h; ++y) { - for (int x = 0; x < *w / 8; ++x) { - for (int b = 0; b < 8; ++b) { - const uint8 mask = (1 << (7 - b)); - uint8 color = 0; - for (int p = 0; p < planeCount; ++p) { - if (src[planePitch * p + x] & mask) { - color |= 1 << p; - } - } - dst[x * 8 + b] = colorBase + color; - } - } - src += planeCount * planePitch; - dst += dstPitch; - } - delete[] planarBuf; - } - return; - } - src += size; - } +void Display::decodeIFF(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd, uint8 colorBase) { + Common::MemoryReadStream str(src, srcSize); + + ::Graphics::IFFDecoder iff; + if (!iff.loadStream(str)) + error("Error while reading IFF image"); + + const ::Graphics::Surface *iffSurface = iff.getSurface(); + *w = iffSurface->w; + *h = iffSurface->h; + + assert(palStart <= palEnd && palEnd <= 256); + memcpy(pal, iff.getPalette() + palStart * 3, (palEnd - palStart) * 3); + for (uint16 y = 0; y < iffSurface->h; y++) + for(uint16 x = 0; x < iffSurface->w; x++) + dst[(y * dstPitch) + x] = *(const byte *)iffSurface->getBasePtr(x, y) + colorBase; } void Display::horizontalScrollUpdate(int16 xCamera) { diff --git a/engines/queen/display.h b/engines/queen/display.h index 4256b19d72..8a8aaef5a6 100644 --- a/engines/queen/display.h +++ b/engines/queen/display.h @@ -116,8 +116,8 @@ public: //! decode PCX picture data void decodePCX(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd); - //! decode ILBM picture data - void decodeLBM(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd, uint8 colorBase = 0); + //! decode IFF picture data + void decodeIFF(const uint8 *src, uint32 srcSize, uint8 *dst, uint16 dstPitch, uint16 *w, uint16 *h, uint8 *pal, uint16 palStart, uint16 palEnd, uint8 colorBase = 0); void horizontalScrollUpdate(int16 xCamera); void horizontalScroll(int16 scroll); -- cgit v1.2.3 From fe10773ac3533e301931586c93eb0b2a5bb7cf80 Mon Sep 17 00:00:00 2001 From: Tomas Jakobsson Date: Sun, 6 Jan 2013 20:04:50 +0100 Subject: SAGA: Update to new IFFDecoder for PBM images --- engines/saga/scene.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 35d923f821..75876b1c90 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -41,9 +41,10 @@ #include "saga/actor.h" #include "saga/resource.h" -#include "graphics/iff.h" #include "common/util.h" +#include "graphics/decoders/iff.h" + namespace Saga { static int initSceneDoors[SCENE_DOORS_MAX] = { @@ -450,11 +451,11 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy debug(5, "Scene::changeScene(%d, %d, %d, %d)", sceneNumber, actorsEntrance, transitionType, chapter); // This is used for latter ITE demos where all places on world map except - // Tent Faire are substituted with LBM picture and short description + // Tent Faire are substituted with IFF picture and short description if (_vm->_hasITESceneSubstitutes) { for (int i = 0; i < ARRAYSIZE(sceneSubstitutes); i++) { if (sceneSubstitutes[i].sceneId == sceneNumber) { - byte *pal, colors[768]; + const byte *pal; Common::File file; Rect rect; PalEntry cPal[PAL_ENTRIES]; @@ -462,12 +463,12 @@ void Scene::changeScene(int16 sceneNumber, int actorsEntrance, SceneTransitionTy _vm->_interface->setMode(kPanelSceneSubstitute); if (file.open(sceneSubstitutes[i].image)) { - Graphics::Surface bbmBuffer; - Graphics::decodePBM(file, bbmBuffer, colors); - pal = colors; - rect.setWidth(bbmBuffer.w); - rect.setHeight(bbmBuffer.h); - _vm->_gfx->drawRegion(rect, (const byte*)bbmBuffer.pixels); + Graphics::IFFDecoder decoder; + decoder.loadStream(file); + pal = decoder.getPalette(); + rect.setWidth(decoder.getSurface()->w); + rect.setHeight(decoder.getSurface()->h); + _vm->_gfx->drawRegion(rect, (const byte *)decoder.getSurface()->pixels); for (int j = 0; j < PAL_ENTRIES; j++) { cPal[j].red = *pal++; cPal[j].green = *pal++; -- cgit v1.2.3 From befa207bfa3709c7292252654a5bb9384d950a02 Mon Sep 17 00:00:00 2001 From: Tomas Jakobsson Date: Sun, 30 Dec 2012 19:34:43 +0100 Subject: GRAPHICS: Delete iff.cpp and iff.h since all ILBM and PBM decoding is handled by IFFDecoder now --- graphics/iff.cpp | 289 ----------------------------------------------------- graphics/iff.h | 137 ------------------------- graphics/module.mk | 1 - 3 files changed, 427 deletions(-) delete mode 100644 graphics/iff.cpp delete mode 100644 graphics/iff.h diff --git a/graphics/iff.cpp b/graphics/iff.cpp deleted file mode 100644 index 395d8d803b..0000000000 --- a/graphics/iff.cpp +++ /dev/null @@ -1,289 +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, uint32 outPitch) { - assert(stream); - uint32 numPlanes = MIN(mode & ILBM_UNPACK_PLANES, (uint32)_header.depth); - assert(numPlanes >= 1 && numPlanes <= 8 && numPlanes != 7); - - bool packPixels = (mode & ILBM_PACK_PLANES) != 0; - if (numPlanes != 1 && numPlanes != 2 && numPlanes != 4) { - packPixels = false; - } - - if (outPitch == 0) - outPitch = _header.width; - if (packPixels) { - outPitch /= (8 / numPlanes); - } - byte *out = buffer; - - switch (_header.pack) { - case 0: { // non-compressed bitmap - // 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) { - stream->read(s, scanlineWidth); - s += scanlineWidth; - } - - planarToChunky(out, outPitch, scanline, scanlineWidth, numPlanes, packPixels); - out += outPitch; - } - - delete[] scanline; - break; - } - - 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 uncompressed and 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 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 651867fa52..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, uint32 outPitch = 0); - - /** - * 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 4e4428daac..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 \ -- cgit v1.2.3