Skip to content

Commit

Permalink
IMAGE: Added BMP RLE4 decoder
Browse files Browse the repository at this point in the history
  • Loading branch information
sev- committed May 18, 2016
1 parent 64d4d02 commit d35cdf5
Show file tree
Hide file tree
Showing 4 changed files with 197 additions and 0 deletions.
3 changes: 3 additions & 0 deletions image/codecs/codec.cpp
Expand Up @@ -34,6 +34,7 @@
#include "image/codecs/mpeg.h"
#include "image/codecs/msvideo1.h"
#include "image/codecs/msrle.h"
#include "image/codecs/msrle4.h"
#include "image/codecs/qtrle.h"
#include "image/codecs/rpza.h"
#include "image/codecs/smc.h"
Expand Down Expand Up @@ -198,6 +199,8 @@ Codec *createBitmapCodec(uint32 tag, int width, int height, int bitsPerPixel) {
return new BitmapRawDecoder(width, height, bitsPerPixel);
case SWAP_CONSTANT_32(1):
return new MSRLEDecoder(width, height, bitsPerPixel);
case SWAP_CONSTANT_32(2):
return new MSRLE4Decoder(width, height, bitsPerPixel);
case MKTAG('C','R','A','M'):
case MKTAG('m','s','v','c'):
case MKTAG('W','H','A','M'):
Expand Down
140 changes: 140 additions & 0 deletions image/codecs/msrle4.cpp
@@ -0,0 +1,140 @@
/* 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 msrledec.c
#include "common/debug.h"
#include "image/codecs/msrle4.h"
#include "common/stream.h"
#include "common/textconsole.h"
#include "common/util.h"
namespace Image {

MSRLE4Decoder::MSRLE4Decoder(uint16 width, uint16 height, byte bitsPerPixel) {
_surface = new Graphics::Surface();
_surface->create(width, height, Graphics::PixelFormat::createFormatCLUT8());
_bitsPerPixel = bitsPerPixel;
}

MSRLE4Decoder::~MSRLE4Decoder() {
_surface->free();
delete _surface;
}

const Graphics::Surface *MSRLE4Decoder::decodeFrame(Common::SeekableReadStream &stream) {
if (_bitsPerPixel == 4) {
decode4(stream);
} else
error("Unhandled %d bit Microsoft RLE encoding", _bitsPerPixel);

return _surface;
}

void MSRLE4Decoder::decode4(Common::SeekableReadStream &stream) {
int x = 0;
int y = _surface->h - 1;

byte *output = (byte *)_surface->getBasePtr(x, y);
byte *output_end = (byte *)_surface->getBasePtr(_surface->w, y);

while (!stream.eos()) {
byte count = stream.readByte();

if (count == 0) {
byte value = stream.readByte();

if (value == 0) {
// End of line

x = 0;
y--;
output = (byte *)_surface->getBasePtr(x, y);
} else if (value == 1) {
// End of image

return;
} else if (value == 2) {
// Skip

count = stream.readByte();
value = stream.readByte();

x += count;
y -= value;

if (y < 0) {
warning("MS RLE Codec: Skip beyond picture bounds");
return;
}

output = (byte *)_surface->getBasePtr(x, y);;

} else {
// Copy data

int odd_pixel = value & 1;
int rle_code = (value + 1) / 2;
int extra_byte = rle_code & 0x01;

if (output + value > output_end) {
stream.skip(rle_code + extra_byte);
continue;
}

for (int i = 0; i < rle_code; i++) {
byte color = stream.readByte();
*output++ = (color & 0xf0) >> 4;
if (i + 1 == rle_code && odd_pixel) {
break;
}
*output++ = color & 0x0f;
}

if (extra_byte)
stream.skip(1);

x += value;
}

} else {
// Run data

if (output + count > output_end)
continue;

byte color = stream.readByte();

for (int i = 0; i < count; i++, x++) {
*output++ = (color & 0xf0) >> 4;
i++;
x++;
if (i == count)
break;
*output++ = color & 0x0f;
}
}

}

warning("MS RLE Codec: No end-of-picture code");
}

} // End of namespace Image
53 changes: 53 additions & 0 deletions image/codecs/msrle4.h
@@ -0,0 +1,53 @@
/* 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.
*
*/

#ifndef IMAGE_CODECS_MSRLE4_H
#define IMAGE_CODECS_MSRLE4_H

#include "image/codecs/codec.h"

namespace Image {

/**
* Microsoft Run-Length Encoding decoder.
*
* Used by BMP/AVI.
*/
class MSRLE4Decoder : public Codec {
public:
MSRLE4Decoder(uint16 width, uint16 height, byte bitsPerPixel);
~MSRLE4Decoder();

const Graphics::Surface *decodeFrame(Common::SeekableReadStream &stream);
Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); }

private:
byte _bitsPerPixel;

Graphics::Surface *_surface;

void decode4(Common::SeekableReadStream &stream);
};

} // End of namespace Image

#endif
1 change: 1 addition & 0 deletions image/module.mk
Expand Up @@ -15,6 +15,7 @@ MODULE_OBJS := \
codecs/indeo3.o \
codecs/mjpeg.o \
codecs/msrle.o \
codecs/msrle4.o \
codecs/msvideo1.o \
codecs/qtrle.o \
codecs/rpza.o \
Expand Down

0 comments on commit d35cdf5

Please sign in to comment.