Example #1
0
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 && imageType != 10) {
        throw Error("TGA images must be type 2 (Uncompressed truecolor) or 10 (Run-length 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 (imageType == 2) {
        // Uncompressed
        if (m_channels == 3) {
            for (y = m_height - 1; y >= 0; --y) {
              for (x = 0; x < m_width; ++x) {
                int i = (x + y * m_width) * 3;
                readBGR(m_byte + i, input);
              }
            }
        } else {
            for (y = m_height - 1; y >= 0; --y) {
              for (x = 0; x < m_width; ++x) {
                 int i = (x + y * m_width) * 4;
                 readBGRA(m_byte + i, input);
              }
            }
        }
    } else if (imageType == 10) {

        // Run-length encoded
        for (y = m_height - 1; y >= 0; --y) {
            for (int x = 0; x < m_width; /* intentionally no x increment */) {
                // The specification guarantees that no packet will wrap past the end of a row
                const uint8 repetitionCount = input.readUInt8();
                const uint8 numValues = (repetitionCount & (~128)) + 1;
                int byteOffset = (x + y * m_width) * 3;

                if (repetitionCount & 128) {
                    // When the high bit is 1, this is a run-length packet
                    if (m_channels == 3) {
                        Color3uint8 value;
                        readBGR((uint8*)(&value), input);
                        for (int i = 0; i < numValues; ++i, ++x) {
                            for (int b = 0; b < 3; ++b, ++byteOffset) {
                                m_byte[byteOffset] = value[b];
                            }
                        }
                    } else {
                        Color4uint8 value;
                        readBGRA((uint8*)(&value), input);
                        for (int i = 0; i < numValues; ++i, ++x) {
                            for (int b = 0; b < 3; ++b, ++byteOffset) {
                                m_byte[byteOffset] = value[b];
                            }
                        }
                    }

                } else {
                    // When the high bit is 0, this is a raw packet
                    for (int i = 0; i < numValues; ++i, ++x, byteOffset += m_channels) {
                        readBGR(m_byte + byteOffset, input);
                    }
                }
            }
        }
    } else {
        alwaysAssertM(false, "Unsupported type");
    }
}
Example #2
0
void GImage::decodeBMP(
    BinaryInput&            input) {

    // The BMP decoding uses these flags.
    static const uint16 PICTURE_NONE               = 0x0000;
    static const uint16 PICTURE_BITMAP             = 0x1000;

    // Compression Flags
    static const uint16 PICTURE_UNCOMPRESSED       = 0x0100;
    static const uint16 PICTURE_MONOCHROME         = 0x0001;
    static const uint16 PICTURE_4BIT               = 0x0002;
    static const uint16 PICTURE_8BIT               = 0x0004;
    static const uint16 PICTURE_16BIT              = 0x0008;
    static const uint16 PICTURE_24BIT              = 0x0010;
    static const uint16 PICTURE_32BIT              = 0x0020;

    (void)PICTURE_16BIT;
    (void)PICTURE_32BIT;

    // This is a simple BMP loader that can handle uncompressed BMP files.
    // Verify this is a BMP file by looking for the BM tag.
    input.reset();
    std::string tag = input.readString(2);
    if (tag != "BM") {
        throw Error("Not a BMP file", input.getFilename());
    }

    m_channels = 3;
	// Skip to the BITMAPINFOHEADER's width and height
	input.skip(16);

    m_width  = input.readUInt32();
    m_height = input.readUInt32();

	// Skip to the bit count and compression type
	input.skip(2);

    uint16 bitCount        = input.readUInt16();
    uint32 compressionType = input.readUInt32();

    uint8 red;
    uint8 green;
    uint8 blue;
    uint8 blank;

	// Only uncompressed bitmaps are supported by this code
    if ((int32)compressionType != BI_RGB) {
        throw Error("BMP images must be uncompressed", input.getFilename());
    }

    uint8* palette = NULL;

	// Create the palette if needed
    if (bitCount <= 8) {

        // Skip to the palette color count in the header
        input.skip(12);

        int numColors = input.readUInt32();

        palette = (uint8*)System::malloc(numColors * 3);
        debugAssert(palette);

        // Skip past the end of the header to the palette info
        input.skip(4);

        int c;
        for (c = 0; c < numColors * 3; c += 3) {
            // Palette information in bitmaps is stored in BGR_ format.
            // That means it's blue-green-red-blank, for each entry.
            blue  = input.readUInt8();
            green = input.readUInt8();
            red   = input.readUInt8();
            blank = input.readUInt8();

            palette[c]     = red;
            palette[c + 1] = green;
            palette[c + 2] = blue;
        }
	}

    int hStart = 0;
    int hEnd   = 0;
    int hDir   = 0;

    if (m_height < 0) {
        m_height = -m_height;
        hStart = 0;
        hEnd   = m_height;
        hDir   = 1;
    } else {
        //height = height;
        hStart = m_height - 1;
        hEnd   = -1;
        hDir   = -1;
    }

    m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 3);
    debugAssert(m_byte);

    int BMScanWidth;
    int BMPadding;
    uint8 BMGroup;
    uint8 BMPixel8;
    int currPixel;
    int dest;
    int flags = PICTURE_NONE;

    if (bitCount == 1) {
        // Note that this file is not necessarily grayscale, since it's possible
        // the palette is blue-and-white, or whatever. But of course most image
        // programs only write 1-bit images if they're black-and-white.
        flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_MONOCHROME;

        // For bitmaps, each scanline is dword-aligned.
        BMScanWidth = (m_width + 7) >> 3;
        if (BMScanWidth & 3) {
            BMScanWidth += 4 - (BMScanWidth & 3);
        }

        // Powers of 2
        int pow2[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

        for (int h = hStart; h != hEnd; h += hDir) {

            currPixel = 0;
            dest = 3 * h * m_width;

            for (int w = 0; w < BMScanWidth; ++w) {

                BMGroup = input.readUInt8();

                // Now we read the pixels. Usually there are eight pixels per byte,
                // since each pixel is represented by one bit, but if the width
                // is not a multiple of eight, the last byte will have some bits
                // set, with the others just being extra. Plus there's the
                // dword-alignment padding. So we keep checking to see if we've
                // already read "width" number of pixels.
                for (int i = 7; i >= 0; --i) {
                    if (currPixel < m_width) {
                        int src  = 3 * ((BMGroup & pow2[i]) >> i);
                    
                        m_byte[dest]     = palette[src];
                        m_byte[dest + 1] = palette[src + 1];
                        m_byte[dest + 2] = palette[src + 2];
                    
                        ++currPixel;
                        dest += 3;
                    }
                }
            }
        }
Example #3
0
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;
          }
        }
    }
}