aboutsummaryrefslogtreecommitdiff
path: root/dep/src/g3dlite/GImage_tga.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/src/g3dlite/GImage_tga.cpp')
-rw-r--r--dep/src/g3dlite/GImage_tga.cpp193
1 files changed, 193 insertions, 0 deletions
diff --git a/dep/src/g3dlite/GImage_tga.cpp b/dep/src/g3dlite/GImage_tga.cpp
new file mode 100644
index 00000000000..9785f879a1f
--- /dev/null
+++ b/dep/src/g3dlite/GImage_tga.cpp
@@ -0,0 +1,193 @@
+/**
+ @file GImage_tga.cpp
+ @author Morgan McGuire, http://graphics.cs.williams.edu
+ @created 2002-05-27
+ @edited 2009-05-10
+ */
+#include "G3D/platform.h"
+#include "G3D/GImage.h"
+#include "G3D/BinaryInput.h"
+#include "G3D/BinaryOutput.h"
+#include "G3D/Log.h"
+
+namespace G3D {
+
+void GImage::encodeTGA(
+ BinaryOutput& out) const {
+
+ out.setEndian(G3D_LITTLE_ENDIAN);
+
+ // ID length
+ out.writeUInt8(0);
+
+ // Color map Type
+ out.writeUInt8(0);
+
+ // Type
+ out.writeUInt8(2);
+
+ // Color map
+ out.skip(5);
+
+ // x, y offsets
+ out.writeUInt16(0);
+ out.writeUInt16(0);
+
+ // Width & height
+ out.writeUInt16(m_width);
+ out.writeUInt16(m_height);
+
+ // Color depth
+ if (m_channels == 1) {
+ // Force RGB mode
+ out.writeUInt8(8 * 3);
+ } else {
+ out.writeUInt8(8 * m_channels);
+ }
+
+ // Image descriptor
+ if (m_channels < 4) {
+ // 0 alpha bits
+ out.writeUInt8(0);
+ } else {
+ // 8 alpha bits
+ out.writeUInt8(8);
+ }
+
+ // Image ID (zero length)
+
+ if (m_channels == 1) {
+ // Pixels are upside down in BGR format.
+ for (int y = m_height - 1; y >= 0; --y) {
+ for (int x = 0; x < m_width; ++x) {
+ uint8 p = (m_byte[(y * m_width + x)]);
+ out.writeUInt8(p);
+ out.writeUInt8(p);
+ out.writeUInt8(p);
+ }
+ }
+ } else if (m_channels == 3) {
+ // Pixels are upside down in BGR format.
+ for (int y = m_height - 1; y >= 0; --y) {
+ for (int x = 0; x < m_width; ++x) {
+ uint8* p = &(m_byte[3 * (y * m_width + x)]);
+ out.writeUInt8(p[2]);
+ out.writeUInt8(p[1]);
+ out.writeUInt8(p[0]);
+ }
+ }
+ } else {
+ // Pixels are upside down in BGRA format.
+ for (int y = m_height - 1; y >= 0; --y) {
+ for (int x = 0; x < m_width; ++x) {
+ uint8* p = &(m_byte[4 * (y * m_width + x)]);
+ out.writeUInt8(p[2]);
+ out.writeUInt8(p[1]);
+ out.writeUInt8(p[0]);
+ out.writeUInt8(p[3]);
+ }
+ }
+ }
+
+ // Write "TRUEVISION-XFILE " 18 bytes from the end
+ // (with null termination)
+ out.writeString("TRUEVISION-XFILE ");
+}
+
+
+void GImage::decodeTGA(
+ BinaryInput& input) {
+
+ // This is a simple TGA loader that can handle uncompressed
+ // truecolor TGA files (TGA type 2).
+ // Verify this is a TGA file by looking for the TRUEVISION tag.
+ int pos = input.getPosition();
+ input.setPosition(input.size() - 18);
+ std::string tag = input.readString(16);
+ if (tag != "TRUEVISION-XFILE") {
+ throw Error("Not a TGA file", input.getFilename());
+ }
+
+ input.setPosition(pos);
+
+ int IDLength = input.readUInt8();
+ int colorMapType = input.readUInt8();
+ int imageType = input.readUInt8();
+
+ (void)colorMapType;
+
+ // 2 is the type supported by this routine.
+ if (imageType != 2) {
+ throw Error("TGA images must be type 2 (Uncompressed truecolor)", input.getFilename());
+ }
+
+ // Color map specification
+ input.skip(5);
+
+ // Image specification
+
+ // Skip x and y offsets
+ input.skip(4);
+
+ m_width = input.readInt16();
+ m_height = input.readInt16();
+
+ int colorDepth = input.readUInt8();
+
+ if ((colorDepth != 24) && (colorDepth != 32)) {
+ throw Error("TGA files must be 24 or 32 bit.", input.getFilename());
+ }
+
+ if (colorDepth == 32) {
+ m_channels = 4;
+ } else {
+ m_channels = 3;
+ }
+
+ // Image descriptor contains overlay data as well
+ // as data indicating where the origin is
+ int imageDescriptor = input.readUInt8();
+ (void)imageDescriptor;
+
+ // Image ID
+ input.skip(IDLength);
+
+ m_byte = (uint8*)m_memMan->alloc(m_width * m_height * m_channels);
+ debugAssert(m_byte);
+
+ // Pixel data
+ int x;
+ int y;
+
+ if (m_channels == 3) {
+ for (y = m_height - 1; y >= 0; --y) {
+ for (x = 0; x < m_width; ++x) {
+ int b = input.readUInt8();
+ int g = input.readUInt8();
+ int r = input.readUInt8();
+
+ int i = (x + y * m_width) * 3;
+ m_byte[i + 0] = r;
+ m_byte[i + 1] = g;
+ m_byte[i + 2] = b;
+ }
+ }
+ } else {
+ for (y = m_height - 1; y >= 0; --y) {
+ for (x = 0; x < m_width; ++x) {
+ int b = input.readUInt8();
+ int g = input.readUInt8();
+ int r = input.readUInt8();
+ int a = input.readUInt8();
+
+ int i = (x + y * m_width) * 4;
+ m_byte[i + 0] = r;
+ m_byte[i + 1] = g;
+ m_byte[i + 2] = b;
+ m_byte[i + 3] = a;
+ }
+ }
+ }
+}
+
+}