mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-29 14:42:26 +00:00
Move the PICT code to graphics/ with some updates; needed for SCI1.1 Mac.
svn-id: r49195
This commit is contained in:
parent
afd909d69e
commit
ad0eb0b06e
@ -79,7 +79,7 @@ MystGraphics::MystGraphics(MohawkEngine_Myst* vm) : _vm(vm) {
|
||||
|
||||
if (_vm->getFeatures() & GF_ME) {
|
||||
_jpegDecoder = new Graphics::JPEGDecoder();
|
||||
_pictDecoder = new MystPICT(_jpegDecoder);
|
||||
_pictDecoder = new Graphics::PictDecoder(_pixelFormat);
|
||||
} else {
|
||||
_jpegDecoder = NULL;
|
||||
_pictDecoder = NULL;
|
||||
|
@ -28,9 +28,9 @@
|
||||
|
||||
#include "mohawk/bitmap.h"
|
||||
#include "mohawk/livingbooks.h"
|
||||
#include "mohawk/myst_pict.h"
|
||||
|
||||
#include "common/file.h"
|
||||
#include "graphics/pict.h"
|
||||
#include "graphics/video/codecs/mjpeg.h"
|
||||
|
||||
namespace Mohawk {
|
||||
@ -104,7 +104,7 @@ public:
|
||||
private:
|
||||
MohawkEngine_Myst *_vm;
|
||||
MystBitmap *_bmpDecoder;
|
||||
MystPICT *_pictDecoder;
|
||||
Graphics::PictDecoder *_pictDecoder;
|
||||
Graphics::JPEGDecoder *_jpegDecoder;
|
||||
Graphics::PixelFormat _pixelFormat;
|
||||
|
||||
|
@ -9,7 +9,6 @@ MODULE_OBJS = \
|
||||
livingbooks.o \
|
||||
mohawk.o \
|
||||
myst.o \
|
||||
myst_pict.o \
|
||||
myst_vars.o \
|
||||
myst_saveload.o \
|
||||
myst_scripts.o \
|
||||
|
@ -13,6 +13,7 @@ MODULE_OBJS := \
|
||||
iff.o \
|
||||
imagedec.o \
|
||||
jpeg.o \
|
||||
pict.o \
|
||||
primitives.o \
|
||||
scaler.o \
|
||||
scaler/thumbnail_intern.o \
|
||||
|
@ -23,26 +23,38 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "mohawk/myst_pict.h"
|
||||
#include "graphics/conversion.h"
|
||||
#include "graphics/jpeg.h"
|
||||
#include "graphics/pict.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
namespace Mohawk {
|
||||
namespace Graphics {
|
||||
|
||||
// The PICT code is based off of the QuickDraw specs:
|
||||
// http://developer.apple.com/documentation/mac/QuickDraw/QuickDraw-461.html
|
||||
// http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-461.html
|
||||
// http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-269.html
|
||||
|
||||
MystPICT::MystPICT(Graphics::JPEGDecoder *jpegDecoder) {
|
||||
_jpegDecoder = jpegDecoder;
|
||||
_pixelFormat = g_system->getScreenFormat();
|
||||
PictDecoder::PictDecoder(PixelFormat pixelFormat) {
|
||||
_jpeg = new JPEG();
|
||||
_pixelFormat = pixelFormat;
|
||||
}
|
||||
|
||||
Graphics::Surface *MystPICT::decodeImage(Common::SeekableReadStream *stream) {
|
||||
// Skip initial 512 bytes (all 0's)
|
||||
stream->seek(512, SEEK_CUR);
|
||||
PictDecoder::~PictDecoder() {
|
||||
delete _jpeg;
|
||||
}
|
||||
|
||||
// Read in the first part of the header
|
||||
/* uint16 fileSize = */ stream->readUint16BE();
|
||||
Surface *PictDecoder::decodeImage(Common::SeekableReadStream *stream, byte *palette) {
|
||||
assert(stream);
|
||||
|
||||
uint16 fileSize = stream->readUint16BE();
|
||||
|
||||
// If we have no file size here, we probably have a PICT from a file
|
||||
// and not a resource. The other two bytes are the fileSize which we
|
||||
// don't actually need (and already read if from a resource).
|
||||
if (!fileSize)
|
||||
stream->seek(512 + 2);
|
||||
|
||||
_imageRect.top = stream->readUint16BE();
|
||||
_imageRect.left = stream->readUint16BE();
|
||||
@ -52,11 +64,12 @@ Graphics::Surface *MystPICT::decodeImage(Common::SeekableReadStream *stream) {
|
||||
|
||||
Graphics::Surface *image = new Graphics::Surface();
|
||||
image->create(_imageRect.width(), _imageRect.height(), _pixelFormat.bytesPerPixel);
|
||||
_isPaletted = false;
|
||||
|
||||
// NOTE: This is only a subset of the full PICT format.
|
||||
// - Only V2 Images Supported
|
||||
// - JPEG Chunks are Supported
|
||||
// - DirectBitsRect Chunks are Supported
|
||||
// - CompressedQuickTime (JPEG) compressed data is supported
|
||||
// - DirectBitsRect/PackBitsRect compressed data is supported
|
||||
for (uint32 opNum = 0; !stream->eos() && !stream->err() && stream->pos() < stream->size(); opNum++) {
|
||||
uint16 opcode = stream->readUint16BE();
|
||||
debug(2, "Found PICT opcode %04x", opcode);
|
||||
@ -82,8 +95,11 @@ Graphics::Surface *MystPICT::decodeImage(Common::SeekableReadStream *stream) {
|
||||
error ("Unknown PICT version");
|
||||
} else if (opcode == 0x001E) { // DefHilite
|
||||
// Ignore, Contains no Data
|
||||
} else if (opcode == 0x0098) { // PackBitsRect
|
||||
decodeDirectBitsRect(stream, image, true);
|
||||
_isPaletted = true;
|
||||
} else if (opcode == 0x009A) { // DirectBitsRect
|
||||
decodeDirectBitsRect(stream, image);
|
||||
decodeDirectBitsRect(stream, image, false);
|
||||
} else if (opcode == 0x00A1) { // LongComment
|
||||
stream->readUint16BE();
|
||||
uint16 dataSize = stream->readUint16BE();
|
||||
@ -106,59 +122,71 @@ Graphics::Surface *MystPICT::decodeImage(Common::SeekableReadStream *stream) {
|
||||
decodeCompressedQuickTime(stream, image);
|
||||
break;
|
||||
} else {
|
||||
error ("Unknown PICT opcode %04x", opcode);
|
||||
warning("Unknown PICT opcode %04x", opcode);
|
||||
}
|
||||
}
|
||||
|
||||
// If we got a palette throughout this nonsense, go and grab it
|
||||
if (palette && _isPaletted)
|
||||
memcpy(palette, _palette, 256 * 4);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
PictDecoder::PixMap PictDecoder::readPixMap(Common::SeekableReadStream *stream, bool hasBaseAddr) {
|
||||
PixMap pixMap;
|
||||
pixMap.baseAddr = hasBaseAddr ? stream->readUint32BE() : 0;
|
||||
pixMap.rowBytes = stream->readUint16BE() & 0x3fff;
|
||||
pixMap.bounds.top = stream->readUint16BE();
|
||||
pixMap.bounds.left = stream->readUint16BE();
|
||||
pixMap.bounds.bottom = stream->readUint16BE();
|
||||
pixMap.bounds.right = stream->readUint16BE();
|
||||
pixMap.pmVersion = stream->readUint16BE();
|
||||
pixMap.packType = stream->readUint16BE();
|
||||
pixMap.packSize = stream->readUint32BE();
|
||||
pixMap.hRes = stream->readUint32BE();
|
||||
pixMap.vRes = stream->readUint32BE();
|
||||
pixMap.pixelType = stream->readUint16BE();
|
||||
pixMap.pixelSize = stream->readUint16BE();
|
||||
pixMap.cmpCount = stream->readUint16BE();
|
||||
pixMap.cmpSize = stream->readUint16BE();
|
||||
pixMap.planeBytes = stream->readUint32BE();
|
||||
pixMap.pmTable = stream->readUint32BE();
|
||||
pixMap.pmReserved = stream->readUint32BE();
|
||||
return pixMap;
|
||||
}
|
||||
|
||||
struct DirectBitsRectData {
|
||||
// PixMap
|
||||
struct {
|
||||
uint32 baseAddr;
|
||||
uint16 rowBytes;
|
||||
Common::Rect bounds;
|
||||
uint16 pmVersion;
|
||||
uint16 packType;
|
||||
uint32 packSize;
|
||||
uint32 hRes;
|
||||
uint32 vRes;
|
||||
uint16 pixelType;
|
||||
uint16 pixelSize;
|
||||
uint16 cmpCount;
|
||||
uint16 cmpSize;
|
||||
uint32 planeBytes;
|
||||
uint32 pmTable;
|
||||
uint32 pmReserved;
|
||||
} pixMap;
|
||||
PictDecoder::PixMap pixMap;
|
||||
Common::Rect srcRect;
|
||||
Common::Rect dstRect;
|
||||
uint16 mode;
|
||||
};
|
||||
|
||||
void MystPICT::decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics::Surface *image) {
|
||||
static const Graphics::PixelFormat directBitsFormat16 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
|
||||
void PictDecoder::decodeDirectBitsRect(Common::SeekableReadStream *stream, Surface *image, bool hasPalette) {
|
||||
static const PixelFormat directBitsFormat16 = PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
|
||||
|
||||
// Clear the palette
|
||||
memset(_palette, 0, sizeof(_palette));
|
||||
|
||||
DirectBitsRectData directBitsData;
|
||||
directBitsData.pixMap.baseAddr = stream->readUint32BE();
|
||||
directBitsData.pixMap.rowBytes = stream->readUint16BE() & 0x3fff;
|
||||
directBitsData.pixMap.bounds.top = stream->readUint16BE();
|
||||
directBitsData.pixMap.bounds.left = stream->readUint16BE();
|
||||
directBitsData.pixMap.bounds.bottom = stream->readUint16BE();
|
||||
directBitsData.pixMap.bounds.right = stream->readUint16BE();
|
||||
directBitsData.pixMap.pmVersion = stream->readUint16BE();
|
||||
directBitsData.pixMap.packType = stream->readUint16BE();
|
||||
directBitsData.pixMap.packSize = stream->readUint32BE();
|
||||
directBitsData.pixMap.hRes = stream->readUint32BE();
|
||||
directBitsData.pixMap.vRes = stream->readUint32BE();
|
||||
directBitsData.pixMap.pixelType = stream->readUint16BE();
|
||||
directBitsData.pixMap.pixelSize = stream->readUint16BE();
|
||||
directBitsData.pixMap.cmpCount = stream->readUint16BE();
|
||||
directBitsData.pixMap.cmpSize = stream->readUint16BE();
|
||||
directBitsData.pixMap.planeBytes = stream->readUint32BE();
|
||||
directBitsData.pixMap.pmTable = stream->readUint32BE();
|
||||
directBitsData.pixMap.pmReserved = stream->readUint32BE();
|
||||
directBitsData.pixMap = readPixMap(stream, !hasPalette);
|
||||
|
||||
// Read in the palette if there is one present
|
||||
if (hasPalette) {
|
||||
// See http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-267.html
|
||||
stream->readUint32BE(); // seed
|
||||
stream->readUint16BE(); // flags
|
||||
uint16 colorCount = stream->readUint16BE() + 1;
|
||||
|
||||
for (uint32 i = 0; i < colorCount; i++) {
|
||||
stream->readUint16BE();
|
||||
_palette[i * 4] = stream->readUint16BE() >> 8;
|
||||
_palette[i * 4 + 1] = stream->readUint16BE() >> 8;
|
||||
_palette[i * 4 + 2] = stream->readUint16BE() >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
directBitsData.srcRect.top = stream->readUint16BE();
|
||||
directBitsData.srcRect.left = stream->readUint16BE();
|
||||
directBitsData.srcRect.bottom = stream->readUint16BE();
|
||||
@ -169,34 +197,44 @@ void MystPICT::decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics
|
||||
directBitsData.dstRect.right = stream->readUint16BE();
|
||||
directBitsData.mode = stream->readUint16BE();
|
||||
|
||||
if (directBitsData.pixMap.pixelSize != 16 && directBitsData.pixMap.pixelSize != 32)
|
||||
error("Unhandled directBitsRect bitsPerPixel %d", directBitsData.pixMap.pixelSize);
|
||||
if (directBitsData.pixMap.pixelSize != 8 && directBitsData.pixMap.pixelSize != 16 && directBitsData.pixMap.pixelSize != 32)
|
||||
error("Unhandled DirectBitsRect bitsPerPixel %d", directBitsData.pixMap.pixelSize);
|
||||
|
||||
byte bytesPerPixel = (directBitsData.pixMap.pixelSize == 16) ? 2 : 3;
|
||||
byte bytesPerPixel = (directBitsData.pixMap.pixelSize == 32) ? 3 : directBitsData.pixMap.pixelSize / 8;
|
||||
byte *buffer = new byte[image->w * image->h * bytesPerPixel];
|
||||
|
||||
// Read in amount of data per row
|
||||
for (uint16 i = 0; i < directBitsData.pixMap.bounds.height(); i++) {
|
||||
if (directBitsData.pixMap.packType == 1 || directBitsData.pixMap.rowBytes < 8) { // Unpacked, Pad-Byte
|
||||
error("Pack Type = %d, Row Bytes = %d", directBitsData.pixMap.packType, directBitsData.pixMap.rowBytes);
|
||||
// TODO
|
||||
} else if (directBitsData.pixMap.packType == 2) { // Unpacked, No Pad-Byte
|
||||
error("Pack Type = 2");
|
||||
// TODO
|
||||
} else if (directBitsData.pixMap.packType > 2) { // Packed
|
||||
// NOTE: Compression 0 is "default". The format in SCI games is packed when 0.
|
||||
// In the future, we may need to have something to set the "default" packing
|
||||
// format, but this is good for now.
|
||||
|
||||
if (directBitsData.pixMap.packType == 1 || directBitsData.pixMap.rowBytes < 8) { // Unpacked, Pad-Byte (on 24-bit)
|
||||
// TODO: Finish this. Hasn't been needed (yet).
|
||||
error("Unpacked DirectBitsRect data (padded)");
|
||||
} else if (directBitsData.pixMap.packType == 2) { // Unpacked, No Pad-Byte (on 24-bit)
|
||||
// TODO: Finish this. Hasn't been needed (yet).
|
||||
error("Unpacked DirectBitsRect data (not padded)");
|
||||
} else if (directBitsData.pixMap.packType == 0 || directBitsData.pixMap.packType > 2) { // Packed
|
||||
uint16 byteCount = (directBitsData.pixMap.rowBytes > 250) ? stream->readUint16BE() : stream->readByte();
|
||||
decodeDirectBitsLine(buffer + i * image->w * bytesPerPixel, directBitsData.pixMap.rowBytes, stream->readStream(byteCount), bytesPerPixel);
|
||||
}
|
||||
}
|
||||
|
||||
if (bytesPerPixel == 2) {
|
||||
|
||||
if (bytesPerPixel == 1) {
|
||||
// Just copy to the image
|
||||
memcpy(image->pixels, buffer, image->w * image->h);
|
||||
} else if (bytesPerPixel == 2) {
|
||||
// Convert from 16-bit to whatever surface we need
|
||||
for (uint16 y = 0; y < image->h; y++) {
|
||||
for (uint16 x = 0; x < image->w; x++) {
|
||||
byte r = 0, g = 0, b = 0;
|
||||
uint32 color = READ_BE_UINT16(buffer + (y * image->w + x) * bytesPerPixel);
|
||||
directBitsFormat16.colorToRGB(color, r, g, b);
|
||||
*((uint16 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
|
||||
if (_pixelFormat.bytesPerPixel == 2)
|
||||
*((uint16 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
|
||||
else
|
||||
*((uint32 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -206,7 +244,10 @@ void MystPICT::decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics
|
||||
byte r = *(buffer + y * image->w * 3 + x);
|
||||
byte g = *(buffer + y * image->w * 3 + image->w + x);
|
||||
byte b = *(buffer + y * image->w * 3 + image->w * 2 + x);
|
||||
*((uint16 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
|
||||
if (_pixelFormat.bytesPerPixel == 2)
|
||||
*((uint16 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
|
||||
else
|
||||
*((uint32 *)image->getBasePtr(x, y)) = _pixelFormat.RGBToColor(r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -214,7 +255,7 @@ void MystPICT::decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
void MystPICT::decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bytesPerPixel) {
|
||||
void PictDecoder::decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bytesPerPixel) {
|
||||
uint32 dataDecoded = 0;
|
||||
byte bytesPerDecode = (bytesPerPixel == 2) ? 2 : 1;
|
||||
|
||||
@ -256,14 +297,37 @@ void MystPICT::decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableRe
|
||||
// http://developer.apple.com/documentation/QuickTime/Rm/CompressDecompress/ImageComprMgr/F-Chapter/6WorkingwiththeImage.html
|
||||
// I'm just ignoring that because Myst ME uses none of that extra stuff. The offset is always the same.
|
||||
|
||||
void MystPICT::decodeCompressedQuickTime(Common::SeekableReadStream *stream, Graphics::Surface *image) {
|
||||
void PictDecoder::decodeCompressedQuickTime(Common::SeekableReadStream *stream, Graphics::Surface *image) {
|
||||
uint32 dataSize = stream->readUint32BE();
|
||||
uint32 startPos = stream->pos();
|
||||
|
||||
Graphics::Surface *jpegImage = _jpegDecoder->decodeImage(new Common::SeekableSubReadStream(stream, stream->pos() + 156, stream->pos() + dataSize));
|
||||
stream->seek(startPos + dataSize);
|
||||
Common::SeekableReadStream *jpegStream = new Common::SeekableSubReadStream(stream, stream->pos() + 156, stream->pos() + dataSize);
|
||||
|
||||
image->copyFrom(*jpegImage);
|
||||
if (!_jpeg->read(jpegStream))
|
||||
error("PictDecoder::decodeCompressedQuickTime(): Could not decode JPEG data");
|
||||
|
||||
Surface *yComponent = _jpeg->getComponent(1);
|
||||
Surface *uComponent = _jpeg->getComponent(2);
|
||||
Surface *vComponent = _jpeg->getComponent(3);
|
||||
|
||||
Surface jpegImage;
|
||||
jpegImage.create(yComponent->w, yComponent->h, _pixelFormat.bytesPerPixel);
|
||||
|
||||
for (uint16 i = 0; i < jpegImage.h; i++) {
|
||||
for (uint16 j = 0; j < jpegImage.w; j++) {
|
||||
byte r = 0, g = 0, b = 0;
|
||||
YUV2RGB(*((byte *)yComponent->getBasePtr(j, i)), *((byte *)uComponent->getBasePtr(j, i)), *((byte *)vComponent->getBasePtr(j, i)), r, g, b);
|
||||
if (_pixelFormat.bytesPerPixel == 2)
|
||||
*((uint16 *)jpegImage.getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
|
||||
else
|
||||
*((uint32 *)jpegImage.getBasePtr(j, i)) = _pixelFormat.RGBToColor(r, g, b);
|
||||
}
|
||||
}
|
||||
|
||||
image->copyFrom(jpegImage);
|
||||
stream->seek(startPos + dataSize);
|
||||
jpegImage.free();
|
||||
delete jpegStream;
|
||||
}
|
||||
|
||||
} // End of namespace Mohawk
|
||||
} // End of namespace Graphics
|
@ -23,35 +23,61 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MYST_PICT_H
|
||||
#define MYST_PICT_H
|
||||
#ifndef GRAPHICS_PICT_H
|
||||
#define GRAPHICS_PICT_H
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "graphics/pixelformat.h"
|
||||
#include "graphics/surface.h"
|
||||
|
||||
#include "graphics/video/codecs/mjpeg.h"
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
}
|
||||
|
||||
namespace Mohawk {
|
||||
namespace Graphics {
|
||||
|
||||
class MystPICT {
|
||||
class JPEG;
|
||||
class Surface;
|
||||
|
||||
class PictDecoder {
|
||||
public:
|
||||
MystPICT(Graphics::JPEGDecoder *jpegDecoder);
|
||||
~MystPICT() {}
|
||||
Graphics::Surface *decodeImage(Common::SeekableReadStream *stream);
|
||||
PictDecoder(Graphics::PixelFormat pixelFormat);
|
||||
~PictDecoder();
|
||||
Surface *decodeImage(Common::SeekableReadStream *stream, byte *palette = 0);
|
||||
|
||||
struct PixMap {
|
||||
uint32 baseAddr;
|
||||
uint16 rowBytes;
|
||||
Common::Rect bounds;
|
||||
uint16 pmVersion;
|
||||
uint16 packType;
|
||||
uint32 packSize;
|
||||
uint32 hRes;
|
||||
uint32 vRes;
|
||||
uint16 pixelType;
|
||||
uint16 pixelSize;
|
||||
uint16 cmpCount;
|
||||
uint16 cmpSize;
|
||||
uint32 planeBytes;
|
||||
uint32 pmTable;
|
||||
uint32 pmReserved;
|
||||
};
|
||||
|
||||
static PixMap readPixMap(Common::SeekableReadStream *stream, bool hasBaseAddr = true);
|
||||
|
||||
private:
|
||||
Graphics::JPEGDecoder *_jpegDecoder;
|
||||
Common::Rect _imageRect;
|
||||
Graphics::PixelFormat _pixelFormat;
|
||||
PixelFormat _pixelFormat;
|
||||
JPEG *_jpeg;
|
||||
byte _palette[256 * 4];
|
||||
bool _isPaletted;
|
||||
|
||||
void decodeDirectBitsRect(Common::SeekableReadStream *stream, Graphics::Surface *image);
|
||||
void decodeDirectBitsRect(Common::SeekableReadStream *stream, Surface *image, bool hasPalette);
|
||||
void decodeDirectBitsLine(byte *out, uint32 length, Common::SeekableReadStream *data, byte bytesPerPixel);
|
||||
void decodeCompressedQuickTime(Common::SeekableReadStream *stream, Graphics::Surface *image);
|
||||
void decodeCompressedQuickTime(Common::SeekableReadStream *stream, Surface *image);
|
||||
};
|
||||
|
||||
} // End of namespace Mohawk
|
||||
} // End of namespace Graphics
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user