[Scummvm-cvs-logs] scummvm master -> 933726a7e871fa9943cda9dc89cf91691a8f2ebf

lordhoto lordhoto at gmail.com
Wed Aug 29 15:58:46 CEST 2012


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
47a7df2d0f GRAPHICS: Add in a TGA-decoder
933726a7e8 Merge pull request #263 from somaen/tgaloader


Commit: 47a7df2d0f9be2c13648a18c9de7b81e77e5d7fe
    https://github.com/scummvm/scummvm/commit/47a7df2d0f9be2c13648a18c9de7b81e77e5d7fe
Author: Einar Johan Trøan Sømåen (einarjohants at gmail.com)
Date: 2012-08-29T05:05:54-07:00

Commit Message:
GRAPHICS: Add in a TGA-decoder

Changed paths:
  A graphics/decoders/tga.cpp
  A graphics/decoders/tga.h
    graphics/module.mk



diff --git a/graphics/decoders/tga.cpp b/graphics/decoders/tga.cpp
new file mode 100644
index 0000000..7d214a6
--- /dev/null
+++ b/graphics/decoders/tga.cpp
@@ -0,0 +1,419 @@
+/* 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 on code from xoreos https://github.com/DrMcCoy/xoreos/
+ * relicensed under GPLv2+ with permission from DrMcCoy and clone2727
+ */
+
+#include "common/util.h"
+#include "common/stream.h"
+#include "common/textconsole.h"
+#include "common/error.h"
+
+#include "graphics/decoders/tga.h"
+
+namespace Graphics {
+
+TGADecoder::TGADecoder() {
+	_colorMapSize = 0;
+	_colorMapOrigin = 0;
+	_colorMapLength = 0;
+	_colorMapEntryLength = 0;
+	_colorMap = NULL;
+}
+
+TGADecoder::~TGADecoder() {
+	destroy();
+}
+
+void TGADecoder::destroy() {
+	_surface.free();
+	delete[] _colorMap;
+}
+
+bool TGADecoder::loadStream(Common::SeekableReadStream &tga) {
+	byte imageType, pixelDepth;
+	bool success;
+	success = readHeader(tga, imageType, pixelDepth);
+	if (success) {
+		switch (imageType) {
+		case TYPE_BW:
+		case TYPE_TRUECOLOR:
+			success = readData(tga, imageType, pixelDepth);
+			break;
+		case TYPE_RLE_BW:
+		case TYPE_RLE_TRUECOLOR:
+		case TYPE_RLE_CMAP:
+			success = readDataRLE(tga, imageType, pixelDepth);
+			break;
+		case TYPE_CMAP:
+			success = readDataColorMapped(tga, imageType, pixelDepth);
+			break;
+		default:
+			success = false;
+			break;
+		}
+	}
+	if (tga.err() || !success) {
+		warning("Failed reading TGA-file");
+		return false;
+	}
+	return success;
+}
+
+bool TGADecoder::readHeader(Common::SeekableReadStream &tga, byte &imageType, byte &pixelDepth) {
+	if (!tga.seek(0)) {
+		warning("Failed reading TGA-file");
+		return false;
+	}
+
+	// TGAs have an optional "id" string in the header
+	uint32 idLength = tga.readByte();
+
+	// Number of colors in the color map / palette
+	int hasColorMap = tga.readByte();
+
+	// Image type. See header for numeric constants
+	imageType = tga.readByte();
+
+	switch (imageType) {
+	case TYPE_CMAP:
+	case TYPE_TRUECOLOR:
+	case TYPE_BW:
+	case TYPE_RLE_CMAP:
+	case TYPE_RLE_TRUECOLOR:
+	case TYPE_RLE_BW:
+		break;
+	default:
+		warning("Unsupported image type: %d", imageType);
+		return false;
+	}
+
+	// Color map specifications
+	if (hasColorMap == 0) {
+		tga.skip(5);
+	} else {
+		_colorMapOrigin = tga.readUint16LE();
+		_colorMapLength = tga.readUint16LE();
+		_colorMapEntryLength = tga.readByte();
+	}
+	// Origin-defintions
+	tga.skip(2 + 2);
+
+	// Image dimensions
+	_surface.w = tga.readUint16LE();
+	_surface.h = tga.readUint16LE();
+
+	// Bits per pixel
+	pixelDepth = tga.readByte();
+	_surface.format.bytesPerPixel = pixelDepth / 8;
+
+	// Image descriptor
+	byte imgDesc = tga.readByte();
+	int attributeBits = imgDesc & 0x0F;
+	assert((imgDesc & 0x10) == 0);
+	_originTop = (imgDesc & 0x20);
+
+	// Interleaving is not handled at this point
+	//int interleave = (imgDesc & 0xC);
+	if (imageType == TYPE_CMAP || imageType == TYPE_RLE_CMAP) {
+		if (pixelDepth == 8) {
+			_format = PixelFormat::createFormatCLUT8();
+		} else {
+			warning("Unsupported index-depth: %d", pixelDepth);
+			return false;
+		}
+	} else if (imageType == TYPE_TRUECOLOR || imageType == TYPE_RLE_TRUECOLOR) {
+		if (pixelDepth == 24) {
+			_format = PixelFormat(3, 8, 8, 8, 0, 16, 8, 0, 0);
+		} else if (pixelDepth == 32) {
+			_format = PixelFormat(4, 8, 8, 8, attributeBits, 16, 8, 0, 24);
+		} else if (pixelDepth == 16 && imageType == TYPE_TRUECOLOR) {
+			// 16bpp TGA is ARGB1555
+			_format = PixelFormat(2, 5, 5, 5, attributeBits, 10, 5, 0, 15);
+		} else {
+			warning("Unsupported pixel depth: %d, %d", imageType, pixelDepth);
+			return false;
+		}
+	} else if (imageType == TYPE_BW || TYPE_RLE_BW) {
+		if (pixelDepth == 8) {
+			_format = PixelFormat(4, 8, 8, 8, 0, 16, 8, 0, 0);
+		} else {
+			warning("Unsupported pixel depth: %d, %d", imageType, pixelDepth);
+			return false;
+		}
+
+	} else {
+		warning("Unsupported image type: %d", imageType);
+		return false;
+	}
+
+	// Skip the id string
+	tga.skip(idLength);
+
+	if (hasColorMap) {
+		return readColorMap(tga, imageType, pixelDepth);
+	}
+	return true;
+}
+
+bool TGADecoder::readColorMap(Common::SeekableReadStream &tga, byte imageType, byte pixelDepth) {
+	_colorMap = new byte[3 * _colorMapLength];
+	for (int i = 0; i < _colorMapLength * 3; i += 3) {
+		byte r, g, b, a;
+		if (_colorMapEntryLength == 32) {
+			PixelFormat format(4, 8, 8, 8, 0, 16, 8, 0, 24);
+			uint32 color = tga.readUint32LE();
+			format.colorToARGB(color, a, r, g, b);
+		} else if (_colorMapEntryLength == 24) {
+			r = tga.readByte();
+			g = tga.readByte();
+			b = tga.readByte();
+		} else if (_colorMapEntryLength == 16) {
+			PixelFormat format(2, 5, 5, 5, 0, 10, 5, 0, 15);
+			uint16 color = tga.readUint16LE();
+			format.colorToARGB(color, a, r, g, b);
+		}
+#ifdef SCUMM_LITTLE_ENDIAN
+		_colorMap[i] = r;
+		_colorMap[i + 1] = g;
+		_colorMap[i + 2] = b;
+#else
+		_colorMap[i] = b;
+		_colorMap[i + 1] = g;
+		_colorMap[i + 2] = r;
+#endif
+	}
+	return true;
+}
+
+// Additional information found from http://paulbourke.net/dataformats/tga/
+// With some details from the link referenced in the header.
+bool TGADecoder::readData(Common::SeekableReadStream &tga, byte imageType, byte pixelDepth) {
+	// TrueColor
+	if (imageType == TYPE_TRUECOLOR) {
+		_surface.create(_surface.w, _surface.h, _format);
+
+		if (pixelDepth == 16) {
+			for (int i = 0; i < _surface.h; i++) {
+				uint16 *dst;
+				if (!_originTop) {
+					dst = (uint16 *)_surface.getBasePtr(0, _surface.h - i - 1);
+				} else {
+					dst = (uint16 *)_surface.getBasePtr(0, i);
+				}
+				for (int j = 0; j < _surface.w; j++) {
+					*dst++ = tga.readUint16LE();
+				}
+			}
+		} else if (pixelDepth == 32) {
+			for (int i = 0; i < _surface.h; i++) {
+				uint32 *dst;
+				if (!_originTop) {
+					dst = (uint32 *)_surface.getBasePtr(0, _surface.h - i - 1);
+				} else {
+					dst = (uint32 *)_surface.getBasePtr(0, i);
+				}
+				for (int j = 0; j < _surface.w; j++) {
+					*dst++ = tga.readUint32LE();
+				}
+			}
+		} else if (pixelDepth == 24) {
+			for (int i = 0; i < _surface.h; i++) {
+				byte *dst;
+				if (!_originTop) {
+					dst = (byte *)_surface.getBasePtr(0, _surface.h - i - 1);
+				} else {
+					dst = (byte *)_surface.getBasePtr(0, i);
+				}
+				for (int j = 0; j < _surface.w; j++) {
+					byte r = tga.readByte();
+					byte g = tga.readByte();
+					byte b = tga.readByte();
+#ifdef SCUMM_LITTLE_ENDIAN
+					*dst++ = r;
+					*dst++ = g;
+					*dst++ = b;
+#else
+					*dst++ = b;
+					*dst++ = g;
+					*dst++ = r;
+#endif
+				}
+			}
+		}
+		// Black/White
+	} else if (imageType == TYPE_BW) {
+		_surface.create(_surface.w, _surface.h, _format);
+
+		byte *data  = (byte *)_surface.pixels;
+		uint32 count = _surface.w * _surface.h;
+
+		while (count-- > 0) {
+			byte g = tga.readByte();
+			*data++ = g;
+			*data++ = g;
+			*data++ = g;
+			*data++ = g;
+		}
+	}
+	return true;
+}
+
+bool TGADecoder::readDataColorMapped(Common::SeekableReadStream &tga, byte imageType, byte indexDepth) {
+	// Color-mapped
+	if (imageType == TYPE_CMAP) {
+		_surface.create(_surface.w, _surface.h, _format);
+		if (indexDepth == 8) {
+			for (int i = 0; i < _surface.h; i++) {
+				byte *dst;
+				if (!_originTop) {
+					dst = (byte *)_surface.getBasePtr(0, _surface.h - i - 1);
+				} else {
+					dst = (byte *)_surface.getBasePtr(0, i);
+				}
+				for (int j = 0; j < _surface.w; j++) {
+					byte index = tga.readByte();
+					*dst++ = index;
+				}
+			}
+		} else if (indexDepth == 16) {
+			warning("16 bit indexes not supported");
+			return false;
+		}
+	} else {
+		return false;
+	}
+	return true;
+}
+
+bool TGADecoder::readDataRLE(Common::SeekableReadStream &tga, byte imageType, byte pixelDepth) {
+	// RLE-TrueColor / RLE-Black/White
+	if (imageType == TYPE_RLE_TRUECOLOR || imageType == TYPE_RLE_BW || imageType == TYPE_RLE_CMAP) {
+		_surface.create(_surface.w, _surface.h, _format);
+		uint32 count = _surface.w * _surface.h;
+		byte *data = (byte *)_surface.pixels;
+
+		while (count > 0) {
+			uint32 header = tga.readByte();
+			byte type = (header & 0x80) >> 7;
+			uint32 rleCount = (header & 0x7F) + 1;
+
+			// RLE-packet
+			if (type == 1) {
+				if (pixelDepth == 32 && imageType == TYPE_RLE_TRUECOLOR) {
+					uint32 color = tga.readUint32LE();
+					while (rleCount-- > 0) {
+						*((uint32 *)data) = color;
+						data += 4;
+						count--;
+					}
+				} else if (pixelDepth == 24 && imageType == TYPE_RLE_TRUECOLOR) {
+					byte r = tga.readByte();
+					byte g = tga.readByte();
+					byte b = tga.readByte();
+					while (rleCount-- > 0) {
+#ifdef SCUMM_LITTLE_ENDIAN
+						*data++ = r;
+						*data++ = g;
+						*data++ = b;
+#else
+						*data++ = b;
+						*data++ = g;
+						*data++ = r;
+#endif
+						count--;
+					}
+				} else if (pixelDepth == 8 && imageType == TYPE_RLE_BW) {
+					byte color = tga.readByte();
+					while (rleCount-- > 0) {
+						*data++ = color;
+						*data++ = color;
+						*data++ = color;
+						*data++ = color;
+						count--;
+					}
+				} else if (pixelDepth == 8 && imageType == TYPE_RLE_CMAP) {
+					byte index = tga.readByte();
+					while (rleCount-- > 0) {
+						*data++ = index;
+						count--;
+					}
+				} else {
+					warning("Unhandled pixel-depth for image-type 10");
+					return false;
+				}
+				// Raw-packet
+			} else if (type == 0) {
+				if (pixelDepth == 32 && imageType == TYPE_RLE_TRUECOLOR) {
+					while (rleCount-- > 0) {
+						uint32 color = tga.readUint32LE();
+						*((uint32 *)data) = color;
+						data += 4;
+						count--;
+					}
+				} else if (pixelDepth == 24 && imageType == TYPE_RLE_TRUECOLOR) {
+					while (rleCount-- > 0) {
+						byte r = tga.readByte();
+						byte g = tga.readByte();
+						byte b = tga.readByte();
+#ifdef SCUMM_LITTLE_ENDIAN
+						*data++ = r;
+						*data++ = g;
+						*data++ = b;
+#else
+						*data++ = b;
+						*data++ = g;
+						*data++ = r;
+#endif
+						count--;
+					}
+				} else if (pixelDepth == 8 && imageType == TYPE_RLE_BW) {
+					while (rleCount-- > 0) {
+						byte color = tga.readByte();
+						*data++ = color;
+						*data++ = color;
+						*data++ = color;
+						*data++ = color;
+						count--;
+					}
+				} else if (pixelDepth == 8 && imageType == TYPE_RLE_CMAP) {
+					while (rleCount-- > 0) {
+						byte index = tga.readByte();
+						*data++ = index;
+						count--;
+					}
+				} else {
+					warning("Unhandled pixel-depth for image-type 10");
+					return false;
+				}
+			} else {
+				warning("Unknown header for RLE-packet %d", type);
+				return false;
+			}
+		}
+	} else {
+		return false;
+	}
+	return true;
+}
+
+} // End of namespace Graphics
diff --git a/graphics/decoders/tga.h b/graphics/decoders/tga.h
new file mode 100644
index 0000000..e8dd2b8
--- /dev/null
+++ b/graphics/decoders/tga.h
@@ -0,0 +1,100 @@
+/* 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 on code from eos https://github.com/DrMcCoy/xoreos/
+ * relicensed under GPLv2+ with permission from DrMcCoy and clone2727
+ */
+
+/*
+ * TGA decoder used in engines:
+ *  - none
+ */
+
+#ifndef GRAPHICS_DECODERS_TGA_H
+#define GRAPHICS_DECODERS_TGA_H
+
+#include "graphics/surface.h"
+#include "graphics/decoders/image_decoder.h"
+
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace Graphics {
+
+/** TarGa image-decoder
+ * The following variations of TGA are supported:
+ * - Type 1 - Color-mapped images in 16/24/32 bpp with 8 bit indexes
+ * - Type 2 - 16/24/32 bpp Top AND Bottom origined.
+ * - Type 3 - Black/White images, 8bpp.
+ * - Type 9 - RLE-encoded color-mapped images. (8 bit indexes only)
+ * - Type 10 - RLE-encoded TrueColor, 24/32bpp.
+ * - Type 11 - RLE-encoded Black/White, 8bpp.
+ *
+ * No images are returned with a palette, instead they are converted
+ * to 16 bpp for Type 1, or 32 bpp for Black/White-images.
+ */
+class TGADecoder : public ImageDecoder {
+public:
+	TGADecoder();
+	virtual ~TGADecoder();
+	virtual void destroy();
+	virtual const Surface *getSurface() const {
+		return &_surface;
+	};
+	virtual const byte *getPalette() const { return _colorMap; }
+	virtual uint16 getPaletteColorCount() const { return _colorMapLength; }
+	virtual bool loadStream(Common::SeekableReadStream &stream);
+private:
+	// Format-spec from:
+	//http://www.ludorg.net/amnesia/TGA_File_Format_Spec.html
+	enum {
+	    TYPE_CMAP = 1,
+	    TYPE_TRUECOLOR = 2,
+	    TYPE_BW = 3,
+	    TYPE_RLE_CMAP = 9,
+	    TYPE_RLE_TRUECOLOR = 10,
+	    TYPE_RLE_BW = 11
+	};
+
+	// Color-map:
+	bool _colorMapSize;
+	byte *_colorMap;
+	int16 _colorMapOrigin;
+	int16 _colorMapLength;
+	byte _colorMapEntryLength;
+
+	// Origin may be at the top, or bottom
+	bool _originTop;
+
+	PixelFormat _format;
+	Surface _surface;
+	// Loading helpers
+	bool readHeader(Common::SeekableReadStream &tga, byte &imageType, byte &pixelDepth);
+	bool readData(Common::SeekableReadStream &tga, byte imageType, byte pixelDepth);
+	bool readDataColorMapped(Common::SeekableReadStream &tga, byte imageType, byte indexDepth);
+	bool readDataRLE(Common::SeekableReadStream &tga, byte imageType, byte pixelDepth);
+	bool readColorMap(Common::SeekableReadStream &tga, byte imageType, byte pixelDepth);
+};
+
+} // End of namespace Graphics
+
+#endif // GRAPHICS_DECODERS_TGA_H
diff --git a/graphics/module.mk b/graphics/module.mk
index 281f904..e67efd2 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -26,7 +26,8 @@ MODULE_OBJS := \
 	decoders/bmp.o \
 	decoders/jpeg.o \
 	decoders/pict.o \
-	decoders/png.o
+	decoders/png.o \
+	decoders/tga.o
 
 ifdef USE_SCALERS
 MODULE_OBJS += \


Commit: 933726a7e871fa9943cda9dc89cf91691a8f2ebf
    https://github.com/scummvm/scummvm/commit/933726a7e871fa9943cda9dc89cf91691a8f2ebf
Author: Johannes Schickel (lordhoto at gmail.com)
Date: 2012-08-29T06:58:22-07:00

Commit Message:
Merge pull request #263 from somaen/tgaloader

GRAPHICS: Add in a TGA-decoder

Changed paths:
  A graphics/decoders/tga.cpp
  A graphics/decoders/tga.h
    graphics/module.mk









More information about the Scummvm-git-logs mailing list