C++ TGA reading fails

1.4k Views Asked by At

i'm using the java method below to write an android.graphics.Bitmap to tga, i've opened the photo in photoshop and it's allright. in native i have to load and display this image with opengl, but the loading of image is incorrect and i see incorrect colors on the screen, the c++ tga loader is below. anybody has any ideea what's the problem?

java write tga method:

public static void writeTGA(Bitmap src, String path) throws IOException {

    ByteBuffer buffer = ByteBuffer.allocate(src.getRowBytes() * src.getHeight());
    src.copyPixelsToBuffer(buffer);
    boolean alpha = src.hasAlpha();
    byte[] data;

    byte[] pixels = buffer.array();
    if (pixels.length != src.getWidth() * src.getHeight() * (alpha ? 4 : 3))
        throw new IllegalStateException();

    data = new byte[pixels.length];

    for(int i=0;i < pixels.length; i += 4){// rgba -> bgra
        data[i] = pixels[i+2];
        data[i+1] = pixels[i+1];
        data[i+2] = pixels[i];
        data[i+3] = pixels[i+3];
    }

    byte[] header = new byte[18];
    header[2] = 2; // uncompressed, true-color image
    header[12] = (byte) ((src.getWidth() >> 0) & 0xFF);
    header[13] = (byte) ((src.getWidth() >> 8) & 0xFF);
    header[14] = (byte) ((src.getHeight() >> 0) & 0xFF);
    header[15] = (byte) ((src.getHeight() >> 8) & 0xFF);
    header[16] = (byte) (alpha ? 32 : 24); // bits per pixel
    header[17] = (byte) ((alpha ? 8 : 0) | (1 << 4));

    File file = new File(path);
    RandomAccessFile raf = new RandomAccessFile(file, "rw");
    raf.write(header);
    raf.write(data);
    raf.setLength(raf.getFilePointer()); // trim
    raf.close();
}

tga 18 bit header c++ :

typedef struct _tgaheader {
    BYTE IDLength;        /* 00h  Size of Image ID field */
    BYTE ColorMapType;    /* 01h  Color map type */
    BYTE ImageType;       /* 02h  Image type code */
    BYTE CMapStart[2];       /* 03h  Color map origin */
    BYTE CMapLength[2];      /* 05h  Color map length */
    BYTE CMapDepth;       /* 07h  Depth of color map entries */
    WORD XOffset;         /* 08h  X origin of image */
    WORD YOffset;         /* 0Ah  Y origin of image */
    WORD Width;           /* 0Ch  Width of image */
    WORD Height;          /* 0Eh  Height of image */
    BYTE PixelDepth;      /* 10h  Image pixel size */
    BYTE ImageDescriptor; /* 11h  Image descriptor byte */
} TGAHEADER;

tga loader method:

void TgaFormat:: LoadImage(const char *path) {
    FILE* filePtr = fopen(path, "rb");
    long imageSize;
    short pixel_size;
    unsigned char colorSwap;

    // Open the TGA file.
    if( filePtr == NULL){
        LOGI("cannot find Tga File!");
        return;
    }
    fread(&file_header, 1, sizeof(TGAHEADER), filePtr);
    short sz = sizeof(TGAHEADER);
    // 2 (uncompressed RGB image), 3 (uncompressed black-and-white images).
    if (file_header.ImageType != 2 ){
        fclose(filePtr);
        LOGI("this file is not a TGA!");
        return;
    }

    // Color mode -> 3 = BGR, 4 = BGRA.
    pixel_size = file_header.PixelDepth / 8;
    imageSize = file_header.Width * file_header.Height * pixel_size;

    m_rgba_data = (BYTE* )malloc( sizeof(BYTE) * imageSize );

    if( fread(m_rgba_data, 1, imageSize, filePtr) != imageSize ) {
        fclose(filePtr);
        return ;
    }
    fclose(filePtr);

    // Change from BGRA to RGBA so OpenGL can read the image data.
    for (int imageIdx = 0; imageIdx < imageSize; imageIdx += pixel_size) {
        colorSwap = m_rgba_data[imageIdx];
        m_rgba_data[imageIdx] = m_rgba_data[imageIdx + 2];
        m_rgba_data[imageIdx + 2] = colorSwap;
    }
}

after reading the tga file in android native and rendered with opengles

the generated qr code into sdcard the opened with photoshop

1

There are 1 best solutions below

0
On BEST ANSWER

the second photo was writed in java, then open in photoshop. i found the mistake. as i was been thinking, i've got a wrong offset, but not in writing/reading process.

into the upload to gpu:

I had

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB.....);

instead of

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA....);

because my pixel size is 4 (RGBA) not 3 (RGB).