ResidualVM logo ResidualVM website - Forums - Contact us BuildBot - Doxygen - Wiki curved edge

pict.cpp

Go to the documentation of this file.
00001 /* ScummVM - Graphic Adventure Engine
00002  *
00003  * ScummVM is the legal property of its developers, whose names
00004  * are too numerous to list here. Please refer to the COPYRIGHT
00005  * file distributed with this source distribution.
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License
00009  * as published by the Free Software Foundation; either version 2
00010  * of the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #include "image/pict.h"
00024 #include "image/codecs/codec.h"
00025 
00026 #include "common/debug.h"
00027 #include "common/endian.h"
00028 #include "common/stream.h"
00029 #include "common/substream.h"
00030 #include "common/textconsole.h"
00031 #include "graphics/surface.h"
00032 
00033 namespace Image {
00034 
00035 // The PICT code is based off of the QuickDraw specs:
00036 // http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-461.html
00037 // http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-269.html
00038 
00039 PICTDecoder::PICTDecoder() {
00040     _outputSurface = 0;
00041     _paletteColorCount = 0;
00042 }
00043 
00044 PICTDecoder::~PICTDecoder() {
00045     destroy();
00046 }
00047 
00048 void PICTDecoder::destroy() {
00049     if (_outputSurface) {
00050         _outputSurface->free();
00051         delete _outputSurface;
00052         _outputSurface = 0;
00053     }
00054 
00055     _paletteColorCount = 0;
00056 }
00057 
00058 #define OPCODE(a, b, c) _opcodes.push_back(PICTOpcode(a, &PICTDecoder::b, c))
00059 
00060 void PICTDecoder::setupOpcodesCommon() {
00061     OPCODE(0x0000, o_nop, "NOP");
00062     OPCODE(0x0001, o_clip, "Clip");
00063     OPCODE(0x0003, o_txFont, "TxFont");
00064     OPCODE(0x0004, o_txFace, "TxFace");
00065     OPCODE(0x0007, o_pnSize, "PnSize");
00066     OPCODE(0x000D, o_txSize, "TxSize");
00067     OPCODE(0x0010, o_txRatio, "TxRatio");
00068     OPCODE(0x0011, o_versionOp, "VersionOp");
00069     OPCODE(0x001E, o_nop, "DefHilite");
00070     OPCODE(0x0028, o_longText, "LongText");
00071     OPCODE(0x00A1, o_longComment, "LongComment");
00072     OPCODE(0x00FF, o_opEndPic, "OpEndPic");
00073     OPCODE(0x0C00, o_headerOp, "HeaderOp");
00074 }
00075 
00076 void PICTDecoder::setupOpcodesNormal() {
00077     setupOpcodesCommon();
00078     OPCODE(0x0098, on_packBitsRect, "PackBitsRect");
00079     OPCODE(0x009A, on_directBitsRect, "DirectBitsRect");
00080     OPCODE(0x8200, on_compressedQuickTime, "CompressedQuickTime");
00081 }
00082 
00083 void PICTDecoder::setupOpcodesQuickTime() {
00084     setupOpcodesCommon();
00085     OPCODE(0x0098, oq_packBitsRect, "PackBitsRect");
00086     OPCODE(0x009A, oq_directBitsRect, "DirectBitsRect");
00087     OPCODE(0x8200, oq_compressedQuickTime, "CompressedQuickTime");
00088 }
00089 
00090 #undef OPCODE
00091 
00092 void PICTDecoder::o_nop(Common::SeekableReadStream &) {
00093     // Nothing to do
00094 }
00095 
00096 void PICTDecoder::o_clip(Common::SeekableReadStream &stream) {
00097     // Ignore
00098     stream.skip(stream.readUint16BE() - 2);
00099 }
00100 
00101 void PICTDecoder::o_txFont(Common::SeekableReadStream &stream) {
00102     // Ignore
00103     stream.readUint16BE();
00104 }
00105 
00106 void PICTDecoder::o_txFace(Common::SeekableReadStream &stream) {
00107     // Ignore
00108     stream.readByte();
00109 }
00110 
00111 void PICTDecoder::o_pnSize(Common::SeekableReadStream &stream) {
00112     // Ignore
00113     stream.readUint16BE();
00114     stream.readUint16BE();
00115 }
00116 
00117 void PICTDecoder::o_txSize(Common::SeekableReadStream &stream) {
00118     // Ignore
00119     stream.readUint16BE();
00120 }
00121 
00122 void PICTDecoder::o_txRatio(Common::SeekableReadStream &stream) {
00123     // Ignore
00124     stream.readUint16BE();
00125     stream.readUint16BE();
00126     stream.readUint16BE();
00127     stream.readUint16BE();
00128 }
00129 
00130 void PICTDecoder::o_versionOp(Common::SeekableReadStream &stream) {
00131     // We only support v2 extended
00132     if (stream.readUint16BE() != 0x02FF)
00133         error("Unknown PICT version");
00134 }
00135 
00136 void PICTDecoder::o_longText(Common::SeekableReadStream &stream) {
00137     // Ignore
00138     stream.readUint16BE();
00139     stream.readUint16BE();
00140     stream.skip(stream.readByte());
00141 }
00142 
00143 void PICTDecoder::o_longComment(Common::SeekableReadStream &stream) {
00144     // Ignore
00145     stream.readUint16BE();
00146     stream.skip(stream.readUint16BE());
00147 }
00148 
00149 void PICTDecoder::o_opEndPic(Common::SeekableReadStream &stream) {
00150     // We've reached the end of the picture
00151     _continueParsing = false;
00152 }
00153 
00154 void PICTDecoder::o_headerOp(Common::SeekableReadStream &stream) {
00155     // Read the basic header, but we don't really have to do anything with it
00156     /* uint16 version = */ stream.readUint16BE();
00157     stream.readUint16BE(); // Reserved
00158     /* uint32 hRes = */ stream.readUint32BE();
00159     /* uint32 vRes = */ stream.readUint32BE();
00160     Common::Rect origResRect;
00161     origResRect.top = stream.readUint16BE();
00162     origResRect.left = stream.readUint16BE();
00163     origResRect.bottom = stream.readUint16BE();
00164     origResRect.right = stream.readUint16BE();
00165     stream.readUint32BE(); // Reserved
00166 }
00167 
00168 void PICTDecoder::on_packBitsRect(Common::SeekableReadStream &stream) {
00169     // Unpack data (8bpp or lower)
00170     unpackBitsRect(stream, true);
00171 }
00172 
00173 void PICTDecoder::on_directBitsRect(Common::SeekableReadStream &stream) {
00174     // Unpack data (16bpp or higher)
00175     unpackBitsRect(stream, false);
00176 }
00177 
00178 void PICTDecoder::on_compressedQuickTime(Common::SeekableReadStream &stream) {
00179     // OK, here's the fun. We get to completely change how QuickDraw draws
00180     // the data in PICT files.
00181 
00182     // Swap out the opcodes to the new ones
00183     _opcodes.clear();
00184     setupOpcodesQuickTime();
00185 
00186     // We'll decode the first QuickTime data from here, but the QuickTime-specific
00187     // opcodes will take over from here on out. Normal opcodes, signing off.
00188     decodeCompressedQuickTime(stream);
00189 }
00190 
00191 void PICTDecoder::oq_packBitsRect(Common::SeekableReadStream &stream) {
00192     // Skip any data here (8bpp or lower)
00193     skipBitsRect(stream, true);
00194 }
00195 
00196 void PICTDecoder::oq_directBitsRect(Common::SeekableReadStream &stream) {
00197     // Skip any data here (16bpp or higher)
00198     skipBitsRect(stream, false);
00199 }
00200 
00201 void PICTDecoder::oq_compressedQuickTime(Common::SeekableReadStream &stream) {
00202     // Just pass the data along
00203     decodeCompressedQuickTime(stream);
00204 }
00205 
00206 bool PICTDecoder::loadStream(Common::SeekableReadStream &stream) {
00207     destroy();
00208 
00209     // Initialize opcodes to their normal state
00210     _opcodes.clear();
00211     setupOpcodesNormal();
00212 
00213     _continueParsing = true;
00214     memset(_palette, 0, sizeof(_palette));
00215 
00216     uint16 fileSize = stream.readUint16BE();
00217 
00218     // If we have no file size here, we probably have a PICT from a file
00219     // and not a resource. The other two bytes are the fileSize which we
00220     // don't actually need (and already read if from a resource).
00221     if (!fileSize)
00222         stream.seek(512 + 2);
00223 
00224     _imageRect.top = stream.readUint16BE();
00225     _imageRect.left = stream.readUint16BE();
00226     _imageRect.bottom = stream.readUint16BE();
00227     _imageRect.right = stream.readUint16BE();
00228     _imageRect.debugPrint(0, "PICT Rect:");
00229 
00230     // NOTE: This is only a subset of the full PICT format.
00231     //     - Only V2 (Extended) Images Supported
00232     //     - CompressedQuickTime compressed data is supported
00233     //     - DirectBitsRect/PackBitsRect compressed data is supported
00234     for (uint32 opNum = 0; !stream.eos() && !stream.err() && stream.pos() < stream.size() && _continueParsing; opNum++) {
00235         // PICT v2 opcodes are two bytes
00236         uint16 opcode = stream.readUint16BE();
00237 
00238         if (opNum == 0 && opcode != 0x0011) {
00239             warning("Cannot find PICT version opcode");
00240             return false;
00241         } else if (opNum == 1 && opcode != 0x0C00) {
00242             warning("Cannot find PICT header opcode");
00243             return false;
00244         }
00245 
00246         // Since opcodes are word-aligned, we need to mark our starting
00247         // position here.
00248         uint32 startPos = stream.pos();
00249 
00250         for (uint32 i = 0; i < _opcodes.size(); i++) {
00251             if (_opcodes[i].op == opcode) {
00252                 debug(4, "Running PICT opcode %04x '%s'", opcode, _opcodes[i].desc);
00253                 (this->*(_opcodes[i].proc))(stream);
00254                 break;
00255             } else if (i == _opcodes.size() - 1) {
00256                 // Unknown opcode; attempt to continue forward
00257                 warning("Unknown PICT opcode %04x", opcode);
00258             }
00259         }
00260 
00261         // Align
00262         stream.skip((stream.pos() - startPos) & 1);
00263     }
00264 
00265     return _outputSurface;
00266 }
00267 
00268 PICTDecoder::PixMap PICTDecoder::readPixMap(Common::SeekableReadStream &stream, bool hasBaseAddr) {
00269     PixMap pixMap;
00270     pixMap.baseAddr = hasBaseAddr ? stream.readUint32BE() : 0;
00271     pixMap.rowBytes = stream.readUint16BE() & 0x3fff;
00272     pixMap.bounds.top = stream.readUint16BE();
00273     pixMap.bounds.left = stream.readUint16BE();
00274     pixMap.bounds.bottom = stream.readUint16BE();
00275     pixMap.bounds.right = stream.readUint16BE();
00276     pixMap.pmVersion = stream.readUint16BE();
00277     pixMap.packType = stream.readUint16BE();
00278     pixMap.packSize = stream.readUint32BE();
00279     pixMap.hRes = stream.readUint32BE();
00280     pixMap.vRes = stream.readUint32BE();
00281     pixMap.pixelType = stream.readUint16BE();
00282     pixMap.pixelSize = stream.readUint16BE();
00283     pixMap.cmpCount = stream.readUint16BE();
00284     pixMap.cmpSize = stream.readUint16BE();
00285     pixMap.planeBytes = stream.readUint32BE();
00286     pixMap.pmTable = stream.readUint32BE();
00287     pixMap.pmReserved = stream.readUint32BE();
00288     return pixMap;
00289 }
00290 
00291 struct PackBitsRectData {
00292     PICTDecoder::PixMap pixMap;
00293     Common::Rect srcRect;
00294     Common::Rect dstRect;
00295     uint16 mode;
00296 };
00297 
00298 void PICTDecoder::unpackBitsRect(Common::SeekableReadStream &stream, bool withPalette) {
00299     PackBitsRectData packBitsData;
00300     packBitsData.pixMap = readPixMap(stream, !withPalette);
00301 
00302     // Read in the palette if there is one present
00303     if (withPalette) {
00304         // See http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-267.html
00305         stream.readUint32BE(); // seed
00306         stream.readUint16BE(); // flags
00307         _paletteColorCount = stream.readUint16BE() + 1;
00308 
00309         for (uint32 i = 0; i < _paletteColorCount; i++) {
00310             stream.readUint16BE();
00311             _palette[i * 3] = stream.readUint16BE() >> 8;
00312             _palette[i * 3 + 1] = stream.readUint16BE() >> 8;
00313             _palette[i * 3 + 2] = stream.readUint16BE() >> 8;
00314         }
00315     }
00316 
00317     packBitsData.srcRect.top = stream.readUint16BE();
00318     packBitsData.srcRect.left = stream.readUint16BE();
00319     packBitsData.srcRect.bottom = stream.readUint16BE();
00320     packBitsData.srcRect.right = stream.readUint16BE();
00321     packBitsData.dstRect.top = stream.readUint16BE();
00322     packBitsData.dstRect.left = stream.readUint16BE();
00323     packBitsData.dstRect.bottom = stream.readUint16BE();
00324     packBitsData.dstRect.right = stream.readUint16BE();
00325     packBitsData.mode = stream.readUint16BE();
00326 
00327     uint16 width = packBitsData.srcRect.width();
00328     uint16 height = packBitsData.srcRect.height();
00329 
00330     byte bytesPerPixel = 0;
00331 
00332     if (packBitsData.pixMap.pixelSize <= 8)
00333         bytesPerPixel = 1;
00334     else if (packBitsData.pixMap.pixelSize == 32)
00335         bytesPerPixel = packBitsData.pixMap.cmpCount;
00336     else
00337         bytesPerPixel = packBitsData.pixMap.pixelSize / 8;
00338 
00339     // Ensure we have enough space in the buffer to hold an entire line's worth of pixels
00340     uint32 lineSize = MAX<int>(width * bytesPerPixel + (8 * 2 / packBitsData.pixMap.pixelSize), packBitsData.pixMap.rowBytes);
00341     byte *buffer = new byte[lineSize * height];
00342 
00343     memset(buffer, 0, lineSize * height);
00344 
00345     // Read in amount of data per row
00346     for (uint16 i = 0; i < packBitsData.pixMap.bounds.height(); i++) {
00347         // NOTE: Compression 0 is "default". The format in SCI games is packed when 0.
00348         // In the future, we may need to have something to set the  "default" packing
00349         // format, but this is good for now.
00350 
00351         if (packBitsData.pixMap.packType == 1 || packBitsData.pixMap.rowBytes < 8) { // Unpacked, Pad-Byte (on 24-bit)
00352             // TODO: Finish this. Hasn't been needed (yet).
00353             error("Unpacked DirectBitsRect data (padded)");
00354         } else if (packBitsData.pixMap.packType == 2) { // Unpacked, No Pad-Byte (on 24-bit)
00355             // TODO: Finish this. Hasn't been needed (yet).
00356             error("Unpacked DirectBitsRect data (not padded)");
00357         } else if (packBitsData.pixMap.packType == 0 || packBitsData.pixMap.packType > 2) { // Packed
00358             uint16 byteCount = (packBitsData.pixMap.rowBytes > 250) ? stream.readUint16BE() : stream.readByte();
00359             unpackBitsLine(buffer + i * width * bytesPerPixel, packBitsData.pixMap.rowBytes, stream.readStream(byteCount), packBitsData.pixMap.pixelSize, bytesPerPixel);
00360         }
00361     }
00362 
00363     _outputSurface = new Graphics::Surface();
00364 
00365     switch (bytesPerPixel) {
00366     case 1:
00367         // Just copy to the image
00368         _outputSurface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
00369         memcpy(_outputSurface->getPixels(), buffer, _outputSurface->w * _outputSurface->h);
00370         break;
00371     case 2:
00372         // We have a 16-bit surface
00373         _outputSurface->create(width, height, Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0));
00374         for (uint16 y = 0; y < _outputSurface->h; y++)
00375             for (uint16 x = 0; x < _outputSurface->w; x++)
00376                 WRITE_UINT16(_outputSurface->getBasePtr(x, y), READ_UINT16(buffer + (y * _outputSurface->w + x) * 2));
00377         break;
00378     case 3:
00379         // We have a planar 24-bit surface
00380         _outputSurface->create(width, height, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
00381         for (uint16 y = 0; y < _outputSurface->h; y++) {
00382             for (uint16 x = 0; x < _outputSurface->w; x++) {
00383                 byte r = *(buffer + y * _outputSurface->w * 3 + x);
00384                 byte g = *(buffer + y * _outputSurface->w * 3 + _outputSurface->w + x);
00385                 byte b = *(buffer + y * _outputSurface->w * 3 + _outputSurface->w * 2 + x);
00386                 *((uint32 *)_outputSurface->getBasePtr(x, y)) = _outputSurface->format.RGBToColor(r, g, b);
00387             }
00388         }
00389         break;
00390     case 4:
00391         // We have a planar 32-bit surface
00392         // Note that we ignore the alpha channel since it seems to not be correct
00393         // Mac OS X does not ignore it, but then displays it incorrectly. Photoshop
00394         // does ignore it and displays it correctly.
00395         _outputSurface->create(width, height, Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0));
00396         for (uint16 y = 0; y < _outputSurface->h; y++) {
00397             for (uint16 x = 0; x < _outputSurface->w; x++) {
00398                 byte a = 0xFF;
00399                 byte r = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w + x);
00400                 byte g = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w * 2 + x);
00401                 byte b = *(buffer + y * _outputSurface->w * 4 + _outputSurface->w * 3 + x);
00402                 *((uint32 *)_outputSurface->getBasePtr(x, y)) = _outputSurface->format.ARGBToColor(a, r, g, b);
00403             }
00404         }
00405         break;
00406     }
00407 
00408     delete[] buffer;
00409 }
00410 
00411 void PICTDecoder::unpackBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bitsPerPixel, byte bytesPerPixel) {
00412     uint32 dataDecoded = 0;
00413     byte bytesPerDecode = (bytesPerPixel == 2) ? 2 : 1;
00414 
00415     while (data->pos() < data->size() && dataDecoded < length) {
00416         byte op = data->readByte();
00417 
00418         if (op & 0x80) {
00419             uint32 runSize = (op ^ 255) + 2;
00420             uint16 value = (bytesPerDecode == 2) ? data->readUint16BE() : data->readByte();
00421 
00422             for (uint32 i = 0; i < runSize; i++) {
00423                 if (bytesPerDecode == 2) {
00424                     WRITE_UINT16(out, value);
00425                     out += 2;
00426                 } else {
00427                     outputPixelBuffer(out, value, bitsPerPixel);
00428                 }
00429             }
00430             dataDecoded += runSize * bytesPerDecode;
00431         } else {
00432             uint32 runSize = op + 1;
00433 
00434             if (bytesPerDecode == 1) {
00435                 for (uint32 i = 0; i < runSize; i++)
00436                     outputPixelBuffer(out, data->readByte(), bitsPerPixel);
00437             } else {
00438                 for (uint32 i = 0; i < runSize; i++) {
00439                     WRITE_UINT16(out, data->readUint16BE());
00440                     out += 2;
00441                 }
00442             }
00443 
00444             dataDecoded += runSize * bytesPerDecode;
00445         }
00446     }
00447 
00448     // HACK: Even if the data is 24-bit, rowBytes is still 32-bit
00449     if (bytesPerPixel == 3)
00450         dataDecoded += length / 4;
00451 
00452     if (length != dataDecoded)
00453         warning("Mismatched PackBits read (%d/%d)", dataDecoded, length);
00454 
00455     delete data;
00456 }
00457 
00458 void PICTDecoder::outputPixelBuffer(byte *&out, byte value, byte bitsPerPixel) {
00459     switch (bitsPerPixel) {
00460     case 1:
00461         for (int i = 7; i >= 0; i--)
00462             *out++ = (value >> i) & 1;
00463         break;
00464     case 2:
00465         for (int i = 6; i >= 0; i -= 2)
00466             *out++ = (value >> i) & 3;
00467         break;
00468     case 4:
00469         *out++ = (value >> 4) & 0xf;
00470         *out++ = value & 0xf;
00471         break;
00472     default:
00473         *out++ = value;
00474     }
00475 }
00476 
00477 void PICTDecoder::skipBitsRect(Common::SeekableReadStream &stream, bool withPalette) {
00478     // Step through a PackBitsRect/DirectBitsRect function
00479 
00480     if (!withPalette)
00481         stream.readUint32BE();
00482 
00483     uint16 rowBytes = stream.readUint16BE();
00484     uint16 height = stream.readUint16BE();
00485     stream.readUint16BE();
00486     height = stream.readUint16BE() - height;
00487     stream.readUint16BE();
00488 
00489     uint16 packType;
00490 
00491     // Top two bits signify PixMap vs BitMap
00492     if (rowBytes & 0xC000) {
00493         // PixMap
00494         stream.readUint16BE();
00495         packType = stream.readUint16BE();
00496         stream.skip(14);
00497         stream.readUint16BE(); // pixelSize
00498         stream.skip(16);
00499 
00500         if (withPalette) {
00501             stream.readUint32BE();
00502             stream.readUint16BE();
00503             stream.skip((stream.readUint16BE() + 1) * 8);
00504         }
00505 
00506         rowBytes &= 0x3FFF;
00507     } else {
00508         // BitMap
00509         packType = 0;
00510     }
00511 
00512     stream.skip(18);
00513 
00514     for (uint16 i = 0; i < height; i++) {
00515         if (packType == 1 || packType == 2 || rowBytes < 8)
00516             error("Unpacked PackBitsRect data");
00517         else if (packType == 0 || packType > 2)
00518             stream.skip((rowBytes > 250) ? stream.readUint16BE() : stream.readByte());
00519     }
00520 }
00521 
00522 // Compressed QuickTime details can be found here:
00523 // http://developer.apple.com/legacy/mac/library/#documentation/QuickTime/Rm/CompressDecompress/ImageComprMgr/B-Chapter/2TheImageCompression.html
00524 // http://developer.apple.com/legacy/mac/library/#documentation/QuickTime/Rm/CompressDecompress/ImageComprMgr/F-Chapter/6WorkingwiththeImage.html
00525 void PICTDecoder::decodeCompressedQuickTime(Common::SeekableReadStream &stream) {
00526     // First, read all the fields from the opcode
00527     uint32 dataSize = stream.readUint32BE();
00528     uint32 startPos = stream.pos();
00529 
00530     /* uint16 version = */ stream.readUint16BE();
00531 
00532     // Read in the display matrix
00533     uint32 matrix[3][3];
00534     for (uint32 i = 0; i < 3; i++)
00535         for (uint32 j = 0; j < 3; j++)
00536             matrix[i][j] = stream.readUint32BE();
00537 
00538     // We currently only support offseting images vertically from the matrix
00539     uint16 xOffset = 0;
00540     uint16 yOffset = matrix[2][1] >> 16;
00541 
00542     uint32 matteSize = stream.readUint32BE();
00543     stream.skip(8); // matte rect
00544     /* uint16 transferMode = */ stream.readUint16BE();
00545     stream.skip(8); // src rect
00546     /* uint32 accuracy = */ stream.readUint32BE();
00547     uint32 maskSize = stream.readUint32BE();
00548 
00549     // Skip the matte and mask
00550     stream.skip(matteSize + maskSize);
00551 
00552     // Now we've reached the image descriptor, so read the relevant data from that
00553     uint32 idStart = stream.pos();
00554     uint32 idSize = stream.readUint32BE();
00555     uint32 codecTag = stream.readUint32BE();
00556     stream.skip(24); // miscellaneous stuff
00557     uint16 width = stream.readUint16BE();
00558     uint16 height = stream.readUint16BE();
00559     stream.skip(8); // resolution, dpi
00560     uint32 imageSize = stream.readUint32BE();
00561     stream.skip(34);
00562     uint16 bitsPerPixel = stream.readUint16BE();
00563     stream.skip(idSize - (stream.pos() - idStart)); // more useless stuff
00564 
00565     Common::SeekableSubReadStream imageStream(&stream, stream.pos(), stream.pos() + imageSize);
00566 
00567     Codec *codec = createQuickTimeCodec(codecTag, width, height, bitsPerPixel);
00568     if (!codec)
00569         error("Unhandled CompressedQuickTime format");
00570 
00571     const Graphics::Surface *surface = codec->decodeFrame(imageStream);
00572 
00573     if (!surface)
00574         error("PICTDecoder::decodeCompressedQuickTime(): Could not decode data");
00575 
00576     if (!_outputSurface) {
00577         _outputSurface = new Graphics::Surface();
00578         _outputSurface->create(_imageRect.width(), _imageRect.height(), surface->format);
00579     }
00580     assert(_outputSurface->format == surface->format);
00581 
00582     Common::Rect outputRect(surface->w, surface->h);
00583     outputRect.translate(xOffset, yOffset);
00584     outputRect.clip(_imageRect);
00585 
00586     for (uint16 y = 0; y < outputRect.height(); y++)
00587         memcpy(_outputSurface->getBasePtr(outputRect.left, y + outputRect.top), surface->getBasePtr(0, y), outputRect.width() * surface->format.bytesPerPixel);
00588 
00589     stream.seek(startPos + dataSize);
00590     delete codec;
00591 }
00592 
00593 } // End of namespace Image


Generated on Sat Feb 16 2019 05:01:01 for ResidualVM by doxygen 1.7.1
curved edge   curved edge