AntiMoron / TgaLoader

I need a tgaLoader.
0 stars 0 forks source link

For inspiration... #1

Open MartinCapousek opened 9 years ago

MartinCapousek commented 9 years ago

define TGA_HEADER_SIZE 18 // size of TGA file header

define TGA_ORIGIN_MASK 0x30 // origin bit mask ... ImageDesc: bits 5-4

define TGA_ALPHA_MASK 0x0f // alpha bit mask .... ImageDesc: bits 3-0

enum E_TgaCMapType { TGA_CMAP_NONE = 0, // none color map/palette data TGA_CMAP_PRESENT = 1, // with color map/palette };

enum E_TgaImageType { TGA_TYPE_NOIMAGE = 0, // no image data included

TGA_TYPE_MAPPED         =  1,     // color-mapped image
TGA_TYPE_COLOR          =  2,     // true-color image
TGA_TYPE_GRAY           =  3,     // gray-scale image

TGA_TYPE_RLE_MAPPED     =  9,     // color-mapped image, RLE compression
TGA_TYPE_RLE_COLOR      = 10,     // true-color image, RLE compression
TGA_TYPE_RLE_GRAY       = 11,     // gray-scale image, RLE compression

};

enum E_TgaImageOrigin { TGA_ORIGIN_BOTTOM_LEFT = 0x00, // bottom left TGA_ORIGIN_BOTTOM_RIGHT = 0x10, // bottom right TGA_ORIGIN_TOP_LEFT = 0x20, // top left TGA_ORIGIN_TOP_RIGHT = 0x30, // top right };

typedef struct // 18 bytes { u8 m_IdLng; // size of image ID field u8 m_CmapType; // color map type u8 m_ImageType; // image type s16 m_Cmap1stEntry; // color map - origin s16 m_CmapLng; // color map - length u8 m_CmapEntrySize; // color map - depth of entries s16 m_OriginX; // X origin of image s16 m_OriginY; // Y origin of image u16 m_Width; // width of image u16 m_Height; // height of image u8 m_Bpp; // image pixel size u8 m_ImageDesc; // image descriptor } T_HeaderTGA;

//--------------------------------------------------------------------------------------------------------------------- void LoadMappedImageData( u8 const * buff, u8 const * cmap, unsigned int pixSize, unsigned int pixNum, u8 * imgData ) { unsigned int i, j, idx;

for (i=pixNum; i--; ++buff)
{
    idx = *buff * pixSize;

    for (j=0; j<pixSize; ++j)
    {
        imgData[j] = cmap[ idx + j ];
    }

    imgData += pixSize;
}

}

//--------------------------------------------------------------------------------------------------------------------- void LoadRawImageData( u8 const * buff, unsigned int pixSize, unsigned int pixNum, u8 * imgData ) { Memory::Copy( imgData, buff, pixSize * pixNum ); }

//--------------------------------------------------------------------------------------------------------------------- void LoadRLEImageData( u8 const * buff, unsigned int pixSize, unsigned int pixNum, u8 * imgData ) { unsigned int i, j; u8 pckHeader, pckSize, pck[4];

while (pixNum > 0)
{
    pckHeader = *(buff++);
    pckSize   = 1 + (pckHeader & 0x7f);

    // RLE packet
    if (pckHeader & 0x80)
    {
        for (i=0; i<pixSize; ++i)
        {
            pck[i] = *(buff++);
        }

        for (i=0; i<pckSize; ++i)
        {
            for (j=0; j<pixSize; ++j) *(imgData++) = pck[j];
        }
    }
    // non-RLE packet
    else
    {
        for (i=0; i<pckSize; ++i)
        {
            for (j=0; j<pixSize; ++j) *(imgData++) = *(buff++);
        }
    }

    pixNum -= pckSize;
}

}

//--------------------------------------------------------------------------------------------------------------------- void LoadRLEMappedImageData( u8 const * buff, u8 const * cmap, unsigned int pixSize, unsigned int pixNum, u8 * imgData ) { unsigned int i, j; unsigned char pckHeader, pckSize, pck[4], cmapIdx;

while (pixNum > 0)
{
    pckHeader = *(buff++);
    pckSize   = 1 + (pckHeader & 0x7f);

    // RLE packet
    if (pckHeader & 0x80)
    {
        cmapIdx = *buff * pixSize;

        for (i=0; i<pixSize; ++i)
        {
            pck[i] = cmap[ cmapIdx + i ];
        }

        ++buff;

        for (i=0; i<pckSize; ++i)
        {
            for (j=0; j<pixSize; ++j) *(imgData++) = pck[j];
        }
    }
    // non-RLE packet
    else
    {
        for (i=0; i<pckSize; ++i)
        {
            cmapIdx = *buff * pixSize;

            for (j=0; j<pixSize; ++j) *(imgData++) = cmap[ cmapIdx + j ];

            ++buff;
        }
    }

    pixNum -= pckSize;
}

}

// buff, buffLng ... .tga file content & its length //--------------------------------------------------------------------------------------------------------------------- C_Image * C_ImageCodecTGA :: Decode( const u8 \ buff, const unsigned int buffLng ) { // read TGA header data...

T_HeaderTGA hdr;

hdr.m_IdLng         = buff[ 0];
hdr.m_CmapType      = buff[ 1];
hdr.m_ImageType     = buff[ 2];
hdr.m_Cmap1stEntry  = buff[ 3] + buff[ 4] * 256;
hdr.m_CmapLng       = buff[ 5] + buff[ 6] * 256;
hdr.m_CmapEntrySize = buff[ 7];
hdr.m_OriginX       = buff[ 8] + buff[ 9] * 256;
hdr.m_OriginY       = buff[10] + buff[11] * 256;
hdr.m_Width         = buff[12] + buff[13] * 256;
hdr.m_Height        = buff[14] + buff[15] * 256;
hdr.m_Bpp           = buff[16];
hdr.m_ImageDesc     = buff[17];

// check file type...

if ((hdr.m_ImageType == TGA_TYPE_MAPPED) || (hdr.m_ImageType == TGA_TYPE_RLE_MAPPED))
{
    if ((hdr.m_CmapEntrySize != 16) && (hdr.m_CmapEntrySize != 24) && (hdr.m_CmapEntrySize != 32))
    {
        return( false );
    }
    hdr.m_Bpp = hdr.m_CmapEntrySize; // small hack
}
else
{
    if ((hdr.m_ImageType != TGA_TYPE_COLOR) && (hdr.m_ImageType != TGA_TYPE_RLE_COLOR) &&
        (hdr.m_ImageType != TGA_TYPE_GRAY)  && (hdr.m_ImageType != TGA_TYPE_RLE_GRAY))
    {
        return( false );
    }
}

if ((hdr.m_Bpp != 8) && (hdr.m_Bpp != 16) && (hdr.m_Bpp != 24) && (hdr.m_Bpp != 32))
{
    return( false );
}

// check pixel format...

T_ImageDesc imgDesc;

imgDesc.m_Format = GetImagePixelFormat( hdr.m_Bpp, hdr.m_ImageDesc & TGA_ALPHA_MASK, false );

if (imgDesc.m_Format == E_IMAGE_FORMAT_UNKNOWN)
{
    return( false );
}

// load color map...

unsigned char * cmap   = NULL;
unsigned int    offset = TGA_HEADER_SIZE + hdr.m_IdLng;

buff += offset;

if (hdr.m_CmapType == TGA_CMAP_PRESENT)
{
    const unsigned int cmapSize = (hdr.m_CmapLng * hdr.m_CmapEntrySize) / 8;

    cmap = new u8 [cmapSize];

    Memory::Copy( cmap, buff, cmapSize );

    offset += cmapSize;
}

// decode image data...

const unsigned int pixSize = (hdr.m_Bpp + 7) >> 3;
const unsigned int imgSize = hdr.m_Width * hdr.m_Height;

imgDesc.m_Width  = hdr.m_Width;
imgDesc.m_Height = hdr.m_Height;
imgDesc.m_Data   = new u8 [ imgSize * pixSize ];

switch( hdr.m_ImageType )
{
case TGA_TYPE_MAPPED:
    LoadMappedImageData( buff, cmap, pixSize, imgSize, imgDesc.m_Data );
    break;

case TGA_TYPE_COLOR:
case TGA_TYPE_GRAY:
    LoadRawImageData( buff, pixSize, imgSize, imgDesc.m_Data );
    break;

case TGA_TYPE_RLE_MAPPED:
    LoadRLEMappedImageData( buff, cmap, pixSize, imgSize, imgDesc.m_Data );
    break;

case TGA_TYPE_RLE_COLOR:
case TGA_TYPE_RLE_GRAY:
    LoadRLEImageData( buff, pixSize, imgSize, imgDesc.m_Data );
    break;

default:
    RT_ASSERT( 0 );
}

// free memory...

delete [] cmap;

// create image...

C_Image * image = C_Image::Create( imgDesc );

if (image == NULL) return( NULL );

// flip image...

bool flipX, flipY;

switch (hdr.m_ImageDesc & TGA_ORIGIN_MASK)
{
case TGA_ORIGIN_BOTTOM_LEFT:    flipX = true;    flipY = false;   break;
case TGA_ORIGIN_BOTTOM_RIGHT:   flipX = true;    flipY = true;    break;
case TGA_ORIGIN_TOP_LEFT:       flipX = false;   flipY = false;   break;
case TGA_ORIGIN_TOP_RIGHT:      flipX = false;   flipY = true;    break;
}

if (flipX) image->FlipAroundX();
if (flipY) image->FlipAroundY();

// return image...

return( image );

}

AntiMoron commented 9 years ago

sure. The code here is not that OOP. Need to be reconstructed in the future.

AntiMoron commented 9 years ago

Thanks for your suggestion. :)