aboutsummaryrefslogtreecommitdiff
path: root/image/codecs/msvideo1.cpp
diff options
context:
space:
mode:
authorMatthew Hoops2014-02-27 21:27:23 -0500
committerMatthew Hoops2014-02-28 00:27:36 -0500
commitb568ac73b9d2e063eb04693e4610a9932035b696 (patch)
tree2791fe12d65ca2a832251248494991ff0598a068 /image/codecs/msvideo1.cpp
parent740b6e8fbdece44ae2a5295cb0549a53b6dc6ae7 (diff)
downloadscummvm-rg350-b568ac73b9d2e063eb04693e4610a9932035b696.tar.gz
scummvm-rg350-b568ac73b9d2e063eb04693e4610a9932035b696.tar.bz2
scummvm-rg350-b568ac73b9d2e063eb04693e4610a9932035b696.zip
IMAGE: Move video codecs to image/
Diffstat (limited to 'image/codecs/msvideo1.cpp')
-rw-r--r--image/codecs/msvideo1.cpp139
1 files changed, 139 insertions, 0 deletions
diff --git a/image/codecs/msvideo1.cpp b/image/codecs/msvideo1.cpp
new file mode 100644
index 0000000000..e94afedb2d
--- /dev/null
+++ b/image/codecs/msvideo1.cpp
@@ -0,0 +1,139 @@
+/* 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.
+ *
+ */
+
+ // Based off ffmpeg's msvideo.cpp
+
+#include "image/codecs/msvideo1.h"
+#include "common/stream.h"
+#include "common/textconsole.h"
+
+namespace Image {
+
+#define CHECK_STREAM_PTR(n) \
+ if ((stream->pos() + n) > stream->size() ) { \
+ warning ("MS Video-1: Stream out of bounds (%d >= %d)", stream->pos() + n, stream->size()); \
+ return; \
+ }
+
+MSVideo1Decoder::MSVideo1Decoder(uint16 width, uint16 height, byte bitsPerPixel) : Codec() {
+ _surface = new Graphics::Surface();
+ // TODO: Specify the correct pixel format for 2Bpp mode.
+ _surface->create(width, height, (bitsPerPixel == 8) ? Graphics::PixelFormat::createFormatCLUT8() : Graphics::PixelFormat(2, 0, 0, 0, 0, 0, 0, 0, 0));
+ _bitsPerPixel = bitsPerPixel;
+}
+
+MSVideo1Decoder::~MSVideo1Decoder() {
+ _surface->free();
+ delete _surface;
+}
+
+void MSVideo1Decoder::decode8(Common::SeekableReadStream *stream) {
+ byte colors[8];
+ byte *pixels = (byte *)_surface->getPixels();
+ uint16 stride = _surface->w;
+
+ int skipBlocks = 0;
+ uint16 blocks_wide = _surface->w / 4;
+ uint16 blocks_high = _surface->h / 4;
+ uint32 totalBlocks = blocks_wide * blocks_high;
+ uint32 blockInc = 4;
+ uint16 rowDec = stride + 4;
+
+ for (uint16 block_y = blocks_high; block_y > 0; block_y--) {
+ uint32 blockPtr = (block_y * 4 - 1) * stride;
+ for (uint16 block_x = blocks_wide; block_x > 0; block_x--) {
+ // check if this block should be skipped
+ if (skipBlocks > 0) {
+ blockPtr += blockInc;
+ skipBlocks--;
+ totalBlocks--;
+ continue;
+ }
+
+ uint32 pixelPtr = blockPtr;
+
+ /* get the next two bytes in the encoded data stream */
+ CHECK_STREAM_PTR(2);
+ byte byte_a = stream->readByte();
+ byte byte_b = stream->readByte();
+
+ /* check if the decode is finished */
+ if (byte_a == 0 && byte_b == 0 && totalBlocks == 0) {
+ return;
+ } else if ((byte_b & 0xFC) == 0x84) {
+ // skip code, but don't count the current block
+ skipBlocks = ((byte_b - 0x84) << 8) + byte_a - 1;
+ } else if (byte_b < 0x80) {
+ // 2-color encoding
+ uint16 flags = (byte_b << 8) | byte_a;
+
+ CHECK_STREAM_PTR(2);
+ colors[0] = stream->readByte();
+ colors[1] = stream->readByte();
+
+ for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (byte pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
+ pixels[pixelPtr++] = colors[(flags & 0x1) ^ 1];
+ pixelPtr -= rowDec;
+ }
+ } else if (byte_b >= 0x90) {
+ // 8-color encoding
+ uint16 flags = (byte_b << 8) | byte_a;
+
+ CHECK_STREAM_PTR(8);
+ for (byte i = 0; i < 8; i++)
+ colors[i] = stream->readByte();
+
+ for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (byte pixel_x = 0; pixel_x < 4; pixel_x++, flags >>= 1)
+ pixels[pixelPtr++] = colors[((pixel_y & 0x2) << 1) + (pixel_x & 0x2) + ((flags & 0x1) ^ 1)];
+ pixelPtr -= rowDec;
+ }
+ } else {
+ // 1-color encoding
+ colors[0] = byte_a;
+
+ for (byte pixel_y = 0; pixel_y < 4; pixel_y++) {
+ for (byte pixel_x = 0; pixel_x < 4; pixel_x++)
+ pixels[pixelPtr++] = colors[0];
+ pixelPtr -= rowDec;
+ }
+ }
+
+ blockPtr += blockInc;
+ totalBlocks--;
+ }
+ }
+}
+
+const Graphics::Surface *MSVideo1Decoder::decodeImage(Common::SeekableReadStream *stream) {
+ if (_bitsPerPixel == 8)
+ decode8(stream);
+ else {
+ // decode16(stream);
+ error ("Unhandled MS Video-1 16bpp encoding");
+ }
+
+ return _surface;
+}
+
+} // End of namespace Image