Question

i'd like to get some help on my issue with .tga file format parsing. i have the code, which i use for a long time:

            int fileLength = Input.tellg();
            vector<char> tempData;
            tempData.resize(fileLength);

            Input.seekg(0);
            Input.read(&tempData[0], fileLength);
            Input.close();

            // Load information about the tga, aka the header.
            // Seek to the width.
            w = byteToUnsignedShort(tempData[12], tempData[13]);

            // Seek to the height.
            h = byteToUnsignedShort(tempData[14], tempData[15]);

            // Seek to the depth.
            depth = unsigned(tempData[16]);

            // Mode = components per pixel.
            md = depth / 8;

            // Total bytes = h * w * md.
            t = h * w * md;

            //Delete allocated data, if need to
            clear();

            //Allocate new storage
            data.resize(t);

            // Copy image data.
            for(unsigned i = 0, s = 18; s < t + 18; s++, i++)
                data[i] = unsigned char(tempData[s]);

            // Mode 3 = RGB, Mode 4 = RGBA
            // TGA stores RGB(A) as BGR(A) so
            // we need to swap red and blue.
            if(md > 2)
            {
                char aux;

                for(unsigned i = 0; i < t; i+= md)
                {
                    aux = data[i];
                    data[i] = data[i + 2];
                    data[i + 2] = aux;
                }
            }

but it keeps failing occasionally for some image resolutions(mostly odd numbers and non-POT resolutions). it results in distorted image(with diagonal patterns) or wrong colors. last time i've encountered it - it was 9x9 24bpp image showing weird colors.

i'm on windows(so it means little-endian), rendering with opengl(i'm taking in account alpha channel existence, when passing image data with glTexImage2D). i'm saving my images with photoshop, not setting RLE flag. this code always reads correct image resolution and color depth.

example of image causing trouble: http://pastie.org/private/p81wbh5sb6coldspln6mw

after loading problematic image, this code:

for(unsigned f = 0; f < imageData.w * imageData.h * imageData.depth; f += imageData.depth)
{
    if(f % (imageData.w * imageData.depth) == 0)
        writeLog << endl;

    writeLog << "[" << unsigned(imageData.data[f]) << "," << unsigned(imageData.data[f + 1]) << "," << unsigned(imageData.data[f + 2]) << "]" << flush;
}

outputs this:

[37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40]
[37,40,40][173,166,164][93,90,88][93,90,88][93,90,88][93,90,88][93,90,88][88,85,83][37,40,40]
[37,40,40][228,221,219][221,212,209][221,212,209][221,212,209][221,212,209][221,212,209][140,134,132][37,40,40]
[37,40,40][228,221,219][221,212,209][221,212,209][221,212,209][221,212,209][221,212,209][140,134,132][37,40,40]
[37,40,40][228,221,219][221,212,209][221,212,209][221,212,209][221,212,209][221,212,209][140,134,132][37,40,40]
[37,40,40][228,221,219][221,212,209][221,212,209][221,212,209][221,212,209][221,212,209][140,134,132][37,40,40]
[37,40,40][228,221,219][221,212,209][221,212,209][221,212,209][221,212,209][221,212,209][140,134,132][37,40,40]
[37,40,40][237,232,230][235,229,228][235,229,228][235,229,228][235,229,228][235,229,228][223,214,212][37,40,40]
[37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40][37,40,40]

so i guess it does read correct data. that brings us to opengl;

glGenTextures(1, &textureObject);
glBindTexture(GL_TEXTURE_2D, textureObject);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

GLenum in_comp_mode, comp_mode;

if(linear) //false for that image
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
else
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

//i don't use 1 or 2 - channel textures, so it's always 24 or 32bpp
    if(imageData.depth == 24)
    {
        in_tex_mode = GL_RGB8;
        tex_mode = GL_RGB;
    }
    else
    {
        in_tex_mode = GL_RGBA8;
        tex_mode = GL_RGBA;
    }

glTexImage2D(GL_TEXTURE_2D, 0, in_tex_mode, imageData.w, imageData.h, 0, tex_mode, GL_UNSIGNED_BYTE, &imageData.data[0]);

glBindTexture(GL_TEXTURE_2D, NULL);

texture compression code is omitted, 'cause it's not active for that texture.

Was it helpful?

Solution

This is probably a padding/alignment issue.

You're loading a TGA, which has no row-padding, but passing it to GL which by default expects rows of pixels to be padded to a multiple of 4 bytes.

Possible fixes for this are:

  • Tell GL how your texture is packed, using (for example) glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  • Change the dimensions of your texture, such that there will be no padding.
  • Change the loading of your texture, such that the padding is consistent with what GL expects

OTHER TIPS

most image format save image data aligned(4 bytes commonly). for example, resolution: 1rows 1columns each row has one pixel, so if RGB is used, each row has 3bytes. and will be extend to 4bytes for alignment because the CPU like that.

english is not my native language, so my bad grammar will kill you. just try to understand it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top