Ticket #8988: iff001.patch
File iff001.patch, 25.0 KB (added by , 16 years ago) |
---|
-
common/iff_container.cpp
1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 * $URL$ 22 * $Id$ 23 */ 24 25 26 #include "common/iff_container.h" 27 28 namespace Common { 29 30 31 char *ID2string(Common::IFF_ID id) { 32 static char str[] = "abcd"; 33 34 str[0] = (char)(id >> 24 & 0xff); 35 str[1] = (char)(id >> 16 & 0xff); 36 str[2] = (char)(id >> 8 & 0xff); 37 str[3] = (char)(id >> 0 & 0xff); 38 39 return str; 40 } 41 42 43 void IFFParser::setInputStream(SeekableReadStream *stream) { 44 destroy(); 45 46 assert(stream); 47 _stream = stream; 48 _startOffset = 0; 49 _endOffset = _stream->size(); 50 51 _formType = 0; 52 _formSize = (uint32)-1; 53 54 if (_stream->size() < 12) { 55 // this file is too small to be a valid IFF container 56 return; 57 } 58 59 if (_stream->readUint32BE() != ID_FORM) { 60 // no FORM header was found 61 return; 62 } 63 64 _formSize = _stream->readUint32BE(); 65 _formType = _stream->readUint32BE(); 66 } 67 68 void IFFParser::destroy() { 69 _stream = 0; 70 _startOffset = _endOffset = 0; 71 } 72 73 uint32 IFFParser::getFORMSize() const { 74 return _formSize; 75 } 76 77 IFF_ID IFFParser::getFORMType() const { 78 return _formType; 79 } 80 81 uint32 IFFParser::moveToIFFBlock(IFF_ID chunkName) { 82 uint32 size = (uint32)-1; 83 84 _stream->seek(_startOffset + 0x0C); 85 86 while ((uint)_stream->pos() < _endOffset) { 87 uint32 chunk = _stream->readUint32BE(); 88 uint32 size_temp = _stream->readUint32BE(); 89 90 if (chunk != chunkName) { 91 _stream->seek((size_temp + 1) & (~1), SEEK_CUR); 92 assert((uint)_stream->pos() <= _endOffset); 93 } else { 94 size = size_temp; 95 break; 96 } 97 } 98 99 return size; 100 } 101 102 uint32 IFFParser::getIFFBlockSize(IFF_ID chunkName) { 103 uint32 size = moveToIFFBlock(chunkName); 104 return size; 105 } 106 107 bool IFFParser::loadIFFBlock(IFF_ID chunkName, void *loadTo, uint32 ptrSize) { 108 uint32 chunkSize = moveToIFFBlock(chunkName); 109 110 if (chunkSize == (uint32)-1) { 111 return false; 112 } 113 114 uint32 loadSize = 0; 115 loadSize = MIN(ptrSize, chunkSize); 116 _stream->read(loadTo, loadSize); 117 return true; 118 } 119 120 SeekableReadStream *IFFParser::getIFFBlockStream(IFF_ID chunkName) { 121 uint32 chunkSize = moveToIFFBlock(chunkName); 122 123 if (chunkSize == (uint32)-1) { 124 return 0; 125 } 126 127 uint32 pos = _stream->pos(); 128 return new SeekableSubReadStream(_stream, pos, pos + chunkSize, false); 129 } 130 131 } // namespace Common -
common/iff_container.h
Property changes on: common\iff_container.cpp ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Date Rev Author URL Id Added: svn:eol-style + native
142 142 /* 8SVX Voice8Header */ 143 143 144 144 145 char * ID2string( Common::IFF_ID id);145 char * ID2string(IFF_ID id); 146 146 147 147 148 class IFFChunk : public Common::ReadStream { 149 150 protected: 151 Common::ReadStream *_input; 152 uint32 bytesRead; 153 148 class IFFParser { 154 149 public: 155 IFF_ID id; 156 uint32 size; 157 158 IFFChunk(Common::ReadStream *input): _input(input) { 159 size = bytesRead = 0; 150 IFFParser() : _stream(0), _startOffset(0), _endOffset(0) {} 151 IFFParser(SeekableReadStream *stream) : _stream(0), _startOffset(0), _endOffset(0) { 152 setInputStream(stream); 160 153 } 154 ~IFFParser() { destroy(); } 161 155 162 void incBytesRead(uint32 inc) { 163 bytesRead += inc; 164 if (bytesRead > size) { 165 error("Chunk overread"); 166 } 167 } 156 /** 157 * Sets up the parser to work on the stream. It is the caller duty to 158 * destroy any previously assigned stream. 159 */ 160 void setInputStream(SeekableReadStream *stream); 168 161 169 void readHeader() { 170 id = _input->readUint32BE(); 171 size = _input->readUint32BE(); 172 bytesRead = 0; 173 } 162 operator bool() const { return (_startOffset != _endOffset) && _stream; } 174 163 175 bool hasReadAll() const { 176 return (size - bytesRead) == 0; 177 } 164 /** 165 * Returns the size from the IFF FORM header, or -1 if not found. 166 */ 167 uint32 getFORMSize() const; 178 168 179 void feed() { 180 if (size % 2) { 181 size++; 182 } 183 while (!hasReadAll()) { 184 readByte(); 185 } 186 } 169 /** 170 * Returns the type from the IFF FORM header, or 0 if not found. 171 */ 172 IFF_ID getFORMType() const; 187 173 188 / / Common::ReadStream implementation189 bool eos() const { return _input->eos(); }190 bool err() const { return _input->err(); }191 void clearErr() { _input->clearErr(); }174 /** 175 * Returns the size (in bytes) of a chunk, or -1 if not found. 176 */ 177 uint32 getIFFBlockSize(IFF_ID chunk); 192 178 193 uint32 read(void *dataPtr, uint32 dataSize) { 194 incBytesRead(dataSize); 195 return _input->read(dataPtr, dataSize); 196 } 179 /** 180 * Loads at most ptrSize bytes from the beginning of the selected chunk 181 * to the buffer. The caller must allocate the buffer. 182 * 183 * Returns false if the chunk is not found in the file. 184 */ 185 bool loadIFFBlock(IFF_ID chunk, void *loadTo, uint32 ptrSize); 197 186 198 }; 187 /** 188 * Returns a stream pointing to the beginning of the raw data in the 189 * specified IFF block if it exists, or 0 otherwise. 190 */ 191 SeekableReadStream *getIFFBlockStream(IFF_ID chunkName); 199 192 200 class IFFParser { 201 public: 202 IFFParser(Common::ReadStream &input) : _formChunk(&input), _chunk(&input) { 203 _formChunk.readHeader(); 204 if (_formChunk.id != ID_FORM) { 205 error("IFFDecoder input is not a FORM type IFF file"); 206 } 207 _typeId = _formChunk.readUint32BE(); 208 } 193 protected: 194 uint32 moveToIFFBlock(IFF_ID chunkName); 209 195 210 virtual ~IFFParser() {} 196 private: 197 void destroy(); 211 198 212 IFFChunk *nextChunk() {213 _chunk.feed();214 _formChunk.incBytesRead(_chunk.size);199 SeekableReadStream *_stream; 200 uint32 _startOffset; 201 uint32 _endOffset; 215 202 216 if (_formChunk.hasReadAll()) 217 return 0; 218 219 _formChunk.incBytesRead(8); 220 _chunk.readHeader(); 221 222 return &_chunk; 223 } 224 225 IFF_ID _typeId; 226 227 protected: 228 IFFChunk _formChunk; 229 IFFChunk _chunk; 203 uint32 _formSize; 204 IFF_ID _formType; 230 205 }; 231 206 232 207 } // namespace Common -
engines/parallaction/sound_br.cpp
453 453 if (!stream) 454 454 return false; 455 455 456 Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize); 457 decoder.decode(); 456 Audio::A8SVXDecoder decoder(stream); 457 decoder.fillHeader(&ch->header); 458 ch->data = decoder.getData(); 459 assert(ch->data); 460 ch->dataSize = decoder.getDataSize(); 458 461 ch->dispose = true; 459 462 delete stream; 460 463 -
engines/parallaction/sound_ns.cpp
380 380 } 381 381 382 382 Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename); 383 Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize); 384 decoder.decode(); 383 Audio::A8SVXDecoder decoder(stream); 384 decoder.fillHeader(&ch->header); 385 ch->data = decoder.getData(); 386 assert(ch->data); 387 ch->dataSize = decoder.getDataSize(); 385 388 ch->dispose = true; 386 389 delete stream; 387 390 } -
engines/saga/scene.cpp
506 506 cPal[j].green = *pal++; 507 507 cPal[j].blue = *pal++; 508 508 } 509 free(colors);509 delete []colors; 510 510 _vm->_gfx->setPalette(cPal); 511 511 512 512 } -
graphics/iff.cpp
28 28 #include "common/util.h" 29 29 30 30 31 namespace Common {32 33 // this really belongs to iff_container.cpp, but we don't want34 // to put only this in a source file35 char *ID2string(Common::IFF_ID id) {36 static char str[] = "abcd";37 38 str[0] = (char)(id >> 24 & 0xff);39 str[1] = (char)(id >> 16 & 0xff);40 str[2] = (char)(id >> 8 & 0xff);41 str[3] = (char)(id >> 0 & 0xff);42 43 return str;44 }45 46 }47 48 49 31 namespace Graphics { 50 32 33 // ILBM decoder implementation 51 34 52 void fillBMHD(BMHD &bitmapHeader, Common::ReadStream &stream) { 35 ILBMDecoder::ILBMDecoder(Common::SeekableReadStream *in, bool disposeStream) : _in(in), _hasHeader(false), _bodySize((uint32)-1), _paletteSize((uint32)-1) { 36 assert(in); 37 _parser.setInputStream(in); 53 38 54 bitmapHeader.width = stream.readUint16BE(); 55 bitmapHeader.height = stream.readUint16BE(); 56 bitmapHeader.x = stream.readUint16BE(); 57 bitmapHeader.y = stream.readUint16BE(); 58 bitmapHeader.depth = stream.readByte(); 59 bitmapHeader.masking = stream.readByte(); 60 bitmapHeader.pack = stream.readByte(); 61 bitmapHeader.flags = stream.readByte(); 62 bitmapHeader.transparentColor = stream.readUint16BE(); 63 bitmapHeader.xAspect = stream.readByte(); 64 bitmapHeader.yAspect = stream.readByte(); 65 bitmapHeader.pageWidth = stream.readUint16BE(); 66 bitmapHeader.pageHeight = stream.readUint16BE(); 39 _hasHeader = _parser.loadIFFBlock(ID_BMHD, &_header, sizeof(_header)); 40 if (!_hasHeader) { 41 return; 42 } 67 43 68 } 44 _header.width = TO_BE_16(_header.width); 45 _header.height = TO_BE_16(_header.height); 69 46 70 71 ILBMDecoder::ILBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors) : IFFParser(input), _surface(&surface), _colors(&colors) { 72 if (_typeId != ID_ILBM) 73 error("unsupported IFF subtype '%s'", Common::ID2string(_typeId)); 47 _paletteSize = _parser.getIFFBlockSize(ID_CMAP); 48 _bodySize = _parser.getIFFBlockSize(ID_BODY); 74 49 } 75 50 76 void ILBMDecoder::decode() {77 51 78 Common::IFFChunk *chunk; 79 while ((chunk = nextChunk()) != 0) { 80 switch (chunk->id) { 81 case ID_BMHD: 82 readBMHD(*chunk); 83 break; 84 85 case ID_CMAP: 86 readCMAP(*chunk); 87 break; 88 89 case ID_BODY: 90 readBODY(*chunk); 91 break; 92 } 52 ILBMDecoder::~ILBMDecoder() { 53 if (_disposeStream) { 54 delete _in; 93 55 } 56 } 94 57 95 return; 58 uint32 ILBMDecoder::getWidth() { 59 assert(_hasHeader); 60 return _header.width; 96 61 } 97 62 98 void ILBMDecoder::readBMHD(Common::IFFChunk &chunk) { 63 uint32 ILBMDecoder::getHeight() { 64 assert(_hasHeader); 65 return _header.height; 66 } 99 67 100 fillBMHD(_bitmapHeader, chunk); 68 uint32 ILBMDecoder::getNumColors() { 69 assert(_hasHeader); 70 return (1 << _header.depth); 71 } 101 72 102 _colorCount = 1 << _bitmapHeader.depth; 103 *_colors = (byte*)malloc(sizeof(**_colors) * _colorCount * 3); 104 _surface->create(_bitmapHeader.width, _bitmapHeader.height, 1); 105 73 byte *ILBMDecoder::getPalette() { 74 assert(_paletteSize != (uint32)-1); 75 byte *palette = new byte[_paletteSize]; 76 assert(palette); 77 _parser.loadIFFBlock(ID_CMAP, palette, _paletteSize); 78 return palette; 106 79 } 107 80 108 void ILBMDecoder::readCMAP(Common::IFFChunk &chunk) { 109 if (*_colors == NULL) { 110 error("wrong input chunk sequence"); 81 byte *ILBMDecoder::getBitmap(uint32 numPlanes, bool packPixels) { 82 assert(_bodySize != (uint32)-1); 83 assert(numPlanes == 1 || numPlanes == 2 || numPlanes == 4 || numPlanes == 5 || numPlanes == 8); 84 85 _packPixels = packPixels; 86 _outPlanes = MIN(numPlanes, (uint32)_header.depth); 87 if (_outPlanes > 4) { 88 _packPixels = false; 111 89 } 112 for (uint32 i = 0; i < _colorCount; i++) { 113 (*_colors)[i * 3 + 0] = chunk.readByte(); 114 (*_colors)[i * 3 + 1] = chunk.readByte(); 115 (*_colors)[i * 3 + 2] = chunk.readByte(); 90 91 uint32 bitmapSize = _header.width * _header.height; 92 uint32 bitmapWidth = _header.width; 93 if (packPixels) { 94 bitmapSize /= (8 / _outPlanes); 95 bitmapWidth /= (8 / _outPlanes); 116 96 } 117 }118 97 119 void ILBMDecoder::readBODY(Common::IFFChunk& chunk) { 98 Common::SeekableReadStream *bodyStream = _parser.getIFFBlockStream(ID_BODY); 99 assert(bodyStream); 120 100 121 switch (_bitmapHeader.pack) { 122 case 0: 123 error("unpacked ILBM files are not supported"); 124 break; 101 byte *bitmap = new byte[bitmapSize]; 102 assert(bitmap); 103 memset(bitmap, 0, bitmapSize); 125 104 126 case 1: { 127 uint32 scanWidth = (_bitmapHeader.width + 7) >> 3; 128 byte *scan = (byte*)malloc(scanWidth); 129 byte *out = (byte*)_surface->pixels; 105 switch (_header.pack) { 106 case 1: { // PackBits compressed bitmap 107 Graphics::PackBitsReadStream stream(*bodyStream); 130 108 131 PackBitsReadStream stream(chunk);109 byte *out = bitmap; 132 110 133 for (uint32 i = 0; i < _bitmapHeader.height; i++) { 134 for (uint32 j = 0; j < _bitmapHeader.depth; j++) { 135 stream.read(scan, scanWidth); 136 fillPlane(out, scan, scanWidth, j); 111 // setup a buffer to hold enough data to build a line in the output 112 uint32 scanWidth = (_header.width + 7) >> 3; 113 byte *scanBuffer = new byte[scanWidth * _header.depth]; 114 115 for (uint i = 0; i < _header.height; ++i) { 116 byte *s = scanBuffer; 117 for (uint32 j = 0; j < _header.depth; ++j) { 118 stream.read(s, scanWidth); 119 s += scanWidth; 137 120 } 138 121 139 out += _bitmapHeader.width; 122 planarToChunky(out, bitmapWidth, scanBuffer, scanWidth); 123 out += bitmapWidth; 140 124 } 141 free(scan); 125 126 delete []scanBuffer; 142 127 break; 143 128 } 144 129 default: 130 error("only RLE compressed ILBM files are supported"); 131 break; 145 132 } 146 }147 133 148 void ILBMDecoder::fillPlane(byte *out, byte* buf, uint32 width, uint32 plane) { 134 delete bodyStream; 149 135 150 byte src, idx, set; 151 byte mask = 1 << plane; 152 153 for (uint32 j = 0; j < _bitmapHeader.width; j++) { 154 src = buf[j >> 3]; 155 idx = 7 - (j & 7); 156 set = src & (1 << idx); 157 158 if (set) 159 out[j] |= mask; 160 } 161 136 return bitmap; 162 137 } 163 138 164 139 140 void ILBMDecoder::planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth) { 141 byte pix, ofs, bit; 142 byte *s; 165 143 144 uint32 pixels = width; 145 if (_packPixels) { 146 pixels *= (8 / _outPlanes); 147 } 166 148 167 PBMDecoder::PBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors) : IFFParser(input), _surface(&surface), _colors(&colors) { 168 if (_typeId != ID_PBM) 169 error("unsupported IFF subtype '%s'", Common::ID2string(_typeId)); 170 } 149 for (uint32 x = 0; x < pixels; ++x) { 171 150 172 void PBMDecoder::decode() { 151 pix = 0; 152 ofs = x >> 3; 153 bit = 0x80 >> (x & 7); 173 154 174 Common::IFFChunk *chunk; 175 while ((chunk = nextChunk()) != 0) { 176 switch (chunk->id) { 177 case ID_BMHD: 178 readBMHD(*chunk); 179 break; 155 // first build a pixel by scanning all the usable planes in the input 156 s = in; 157 for (uint32 plane = 0; plane < _outPlanes; ++plane) { 158 if (s[ofs] & bit) { 159 pix |= (1 << plane); 160 } 161 s += planeWidth; 162 } 180 163 181 case ID_CMAP:182 readCMAP(*chunk);183 break;184 164 185 case ID_BODY: 186 readBODY(*chunk); 187 break; 165 // then output the pixel according to the requested packing 166 if (!_packPixels) { 167 out[x] = pix; 168 } else 169 if (_outPlanes == 1) { 170 out[x/8] |= (pix << (x & 7)); 171 } else 172 if (_outPlanes == 2) { 173 out[x/4] |= (pix << ((x & 3) << 1)); 174 } else 175 if (_outPlanes == 4) { 176 out[x/2] |= (pix << ((x & 1) << 2)); 188 177 } 189 178 } 190 179 191 return;192 180 } 193 181 194 void PBMDecoder::readBMHD(Common::IFFChunk &chunk) {195 182 196 fillBMHD(_bitmapHeader, chunk);197 183 198 _colorCount = 1 << _bitmapHeader.depth;199 *_colors = (byte*)malloc(sizeof(**_colors) * _colorCount * 3);200 _surface->create(_bitmapHeader.width, _bitmapHeader.height, 1);201 184 202 }203 185 204 void PBMDecoder::readCMAP(Common::IFFChunk &chunk) { 205 if (*_colors == NULL) { 206 error("wrong input chunk sequence"); 186 PBMDecoder::PBMDecoder(Common::SeekableReadStream *input) : _hasHeader(false), _paletteSize((uint32)-1), _bodySize((uint32)-1) { 187 assert(input); 188 _parser.setInputStream(input); 189 190 Common::IFF_ID typeId = _parser.getFORMType(); 191 if (typeId != ID_PBM) { 192 error("unsupported IFF subtype '%s'", Common::ID2string(typeId)); 207 193 } 208 for (uint32 i = 0; i < _colorCount; i++) { 209 (*_colors)[i * 3 + 0] = chunk.readByte();210 (*_colors)[i * 3 + 1] = chunk.readByte();211 (*_colors)[i * 3 + 2] = chunk.readByte();194 195 _hasHeader = _parser.loadIFFBlock(ID_BMHD, &_header, sizeof(_header)); 196 if (!_hasHeader) { 197 return; 212 198 } 199 200 _header.width = TO_BE_16(_header.width); 201 _header.height = TO_BE_16(_header.height); 202 203 _paletteSize = _parser.getIFFBlockSize(ID_CMAP); 204 _bodySize = _parser.getIFFBlockSize(ID_BODY); 213 205 } 214 206 215 void PBMDecoder::readBODY(Common::IFFChunk& chunk) { 207 byte *PBMDecoder::getPalette() { 208 assert(_paletteSize != (uint32)-1); 209 byte *palette = new byte[_paletteSize]; 210 assert(palette); 211 _parser.loadIFFBlock(ID_CMAP, palette, _paletteSize); 212 return palette; 213 } 216 214 217 uint si = 0; 215 byte *PBMDecoder::getBitmap() { 216 byte *bitmap = new byte[_bodySize]; 217 assert(bitmap); 218 218 219 switch (_ bitmapHeader.pack) {219 switch (_header.pack) { 220 220 case 0: 221 while (!chunk.hasReadAll()) { 222 ((byte*)_surface->pixels)[si++] = chunk.readByte(); 223 } 221 _parser.loadIFFBlock(ID_BODY, bitmap, _bodySize); 224 222 break; 225 223 226 224 case 1: { 227 PackBitsReadStream stream(chunk); 228 stream.read((byte*)_surface->pixels, _surface->w * _surface->h); 225 Common::SeekableReadStream *packed = _parser.getIFFBlockStream(ID_BODY); 226 assert(packed); 227 PackBitsReadStream stream(*packed); 228 stream.read(bitmap, _bodySize); 229 delete packed; 229 230 break; 230 231 } 231 232 232 233 } 234 235 return bitmap; 233 236 } 234 237 238 uint32 PBMDecoder::getWidth() { 239 assert(_hasHeader); 240 return _header.width; 241 } 235 242 243 uint32 PBMDecoder::getHeight() { 244 assert(_hasHeader); 245 return _header.height; 246 } 236 247 248 uint32 PBMDecoder::getNumColors() { 249 assert(_hasHeader); 250 return (1 << _header.depth); 251 } 237 252 253 void decodePBM(Common::SeekableReadStream &input, Surface &surface, byte *&colors) { 254 PBMDecoder decoder(&input); 238 255 256 colors = decoder.getPalette(); 257 258 surface.w = decoder.getWidth(); 259 surface.h = decoder.getHeight(); 260 surface.pitch = surface.w; 261 surface.bytesPerPixel = 1; 262 surface.pixels = decoder.getBitmap(); 263 } 264 265 266 267 268 269 270 271 239 272 PackBitsReadStream::PackBitsReadStream(Common::ReadStream &input) : _input(&input) { 240 273 } 241 274 … … 281 314 return dataSize - left; 282 315 } 283 316 284 285 void decodePBM(Common::ReadStream &input, Surface &surface, byte *&colors) {286 PBMDecoder decoder(input, surface, colors);287 decoder.decode();288 317 } 289 290 } -
graphics/iff.h
55 55 }; 56 56 57 57 58 // handles ILBM subtype of IFF FORM files 59 // 60 class ILBMDecoder : public Common::IFFParser { 58 /** 59 * Loads and decodes ILBM pictures. 60 * The decoder handles 1,2,4,5 and 8 bit deep pictures. 61 */ 62 class ILBMDecoder { 63 Common::SeekableReadStream *_in; 64 bool _disposeStream; 61 65 66 void planarToChunky(byte *out, uint32 width, byte *in, uint32 planeWidth); 67 68 uint32 _outPlanes; 69 bool _packPixels; 70 62 71 protected: 63 void readBMHD(Common::IFFChunk &chunk); 64 void readCMAP(Common::IFFChunk &chunk); 65 void readBODY(Common::IFFChunk &chunk); 72 Common::IFFParser _parser; 73 BMHD _header; 74 bool _hasHeader; 75 uint32 _bodySize; 76 uint32 _paletteSize; 66 77 67 BMHD _bitmapHeader; 68 uint32 _colorCount;78 public: 79 ILBMDecoder(Common::SeekableReadStream *input, bool disposeStream = false); 69 80 70 Surface *_surface; 71 byte **_colors; 81 virtual ~ILBMDecoder(); 72 82 73 void fillPlane(byte *out, byte* buf, uint32 width, uint32 plane); 83 uint32 getWidth(); 84 uint32 getHeight(); 74 85 75 public: 76 ILBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors); 77 virtual ~ILBMDecoder() { } 78 void decode(); 86 /** 87 * Returns the number of colors in the palette. 88 */ 89 uint32 getNumColors(); 90 91 /** 92 * Returns the palette. 93 * The caller must delete the returned buffer. 94 */ 95 byte *getPalette(); 96 97 /** 98 * Extract and decompress the pixels in the image. Caller can specify the 99 * number of color planes needed (higher order planes are discarded). 100 * 101 * packPixels controls how the pixels are stored in the output bitmap. E.g.: 102 * an unpacked picture stores 1 pixel per byte, while in case of 2 or 4 bit 103 * deep pictures, multiple pixels can be stored into 1 byte. 104 * 105 * The caller must delete the returned buffer. 106 */ 107 byte *getBitmap(uint32 numPlanes, bool packPixels); 108 109 /** 110 * Default call using physical color depth and producing an unpacked bitmap. 111 */ 112 byte *getBitmap() { 113 assert(_hasHeader); 114 return getBitmap(_header.depth, false); 115 } 79 116 }; 80 117 81 118 82 // handles PBM subtype of IFF FORM files 83 // 119 /** 120 * Loads and decodes ILBM pictures. 121 * The decoder handles 8 bit deep pictures. 122 */ 84 123 class PBMDecoder : public Common::IFFParser { 85 124 86 125 protected: 87 void readBMHD(Common::IFFChunk &chunk); 88 void readCMAP(Common::IFFChunk &chunk); 89 void readBODY(Common::IFFChunk &chunk); 126 Common::IFFParser _parser; 127 BMHD _header; 90 128 91 BMHD _bitmapHeader; 92 uint32 _colorCount; 129 bool _hasHeader; 130 uint32 _paletteSize; 131 uint32 _bodySize; 93 132 94 Surface *_surface; 95 byte **_colors;133 public: 134 PBMDecoder(Common::SeekableReadStream *input); 96 135 97 public: 98 PBMDecoder(Common::ReadStream &input, Surface &surface, byte *&colors); 99 virtual ~PBMDecoder() { } 100 void decode(); 136 uint32 getWidth(); 137 uint32 getHeight(); 138 139 /** 140 * Returns the number of colors in the palette. 141 */ 142 uint32 getNumColors(); 143 144 /** 145 * Returns the palette. 146 * The caller must delete the returned buffer. 147 */ 148 byte *getPalette(); 149 150 /** 151 * Returns the picture. 152 * The caller must delete the returned buffer. 153 */ 154 byte *getBitmap(); 101 155 }; 102 156 103 void decodePBM(Common:: ReadStream &input, Surface &surface, byte *&colors);157 void decodePBM(Common::SeekableReadStream &input, Surface &surface, byte *&colors); 104 158 105 106 159 /* 107 160 PackBits is a RLE compression algorithm introduced 108 161 by Apple. It is also used to encode ILBM and PBM -
sound/iff.cpp
30 30 namespace Audio { 31 31 32 32 33 void A8SVXDecoder::readVHDR(Common::IFFChunk &chunk) { 34 _header.oneShotHiSamples = chunk.readUint32BE(); 35 _header.repeatHiSamples = chunk.readUint32BE(); 36 _header.samplesPerHiCycle = chunk.readUint32BE(); 37 _header.samplesPerSec = chunk.readUint16BE(); 38 _header.octaves = chunk.readByte(); 39 _header.compression = chunk.readByte(); 40 _header.volume = chunk.readUint32BE(); 41 } 33 bool A8SVXDecoder::fillHeader(Voice8Header *header) { 34 assert(header); 42 35 43 void A8SVXDecoder::readBODY(Common::IFFChunk &chunk) { 36 if (!_parser.loadIFFBlock(ID_VHDR, header, sizeof(Voice8Header))) { 37 return false; 38 } 44 39 45 switch (_header.compression) { 46 case 0: 47 _dataSize = chunk.size; 48 _data = (int8*)malloc(_dataSize); 49 chunk.read(_data, _dataSize); 50 break; 40 header->oneShotHiSamples = TO_BE_32(header->oneShotHiSamples); 41 header->repeatHiSamples = TO_BE_32(header->repeatHiSamples); 42 header->samplesPerHiCycle = TO_BE_32(header->samplesPerHiCycle); 43 header->samplesPerSec = TO_BE_16(header->samplesPerSec); 44 header->volume = TO_BE_32(header->volume); 45 return true; 46 } 51 47 52 case 1: 53 warning("compressed IFF audio is not supported"); 54 break; 48 int8 *A8SVXDecoder::getData() { 49 uint32 size = getDataSize(); 50 if (size == (uint32)-1) { 51 return 0; 55 52 } 53 int8 *data = new int8[size]; 54 assert(data); 55 _parser.loadIFFBlock(ID_BODY, data, size); 56 return data; 57 } 56 58 59 uint32 A8SVXDecoder::getDataSize() { 60 return _parser.getIFFBlockSize(ID_BODY); 57 61 } 58 62 59 63 60 A8SVXDecoder::A8SVXDecoder(Common::ReadStream &input, Voice8Header &header, int8 *&data, uint32 &dataSize) : 61 IFFParser(input), _header(header), _data(data), _dataSize(dataSize) { 62 if (_typeId != ID_8SVX) 64 A8SVXDecoder::A8SVXDecoder(Common::SeekableReadStream *input) : _parser(input) { 65 if (_parser.getFORMType() != ID_8SVX) { 63 66 error("unknown audio format"); 67 } 64 68 } 65 69 66 void A8SVXDecoder::decode() {67 70 68 Common::IFFChunk *chunk;69 70 while ((chunk = nextChunk()) != 0) {71 switch (chunk->id) {72 case ID_VHDR:73 readVHDR(*chunk);74 break;75 76 case ID_BODY:77 readBODY(*chunk);78 break;79 }80 }81 71 } 82 83 } -
sound/iff.h
55 55 56 56 TODO: make a factory function for this kind of stream? 57 57 */ 58 class A8SVXDecoder : public Common::IFFParser { 58 class A8SVXDecoder { 59 Common::IFFParser _parser; 59 60 60 61 protected: 61 Voice8Header &_header; 62 int8* &_data; 63 uint32 &_dataSize; 62 Voice8Header *_header; 64 63 65 protected:66 void readVHDR(Common::IFFChunk &chunk);67 void readBODY(Common::IFFChunk &chunk);68 69 64 public: 70 A8SVXDecoder(Common::ReadStream &input, Voice8Header &header, int8 *&data, uint32 &dataSize); 71 void decode(); 65 A8SVXDecoder(Common::SeekableReadStream *input); 66 67 bool fillHeader(Voice8Header *header); 68 int8 *getData(); 69 uint32 getDataSize(); 72 70 }; 73 71 74 72