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
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).