toxi.in.process

Friday, March 05, 2004

loading Targa images

if you ever wanted to load images with an embedded alpha channel, TGA (Targa) is a feasible format as long as the image is not too big and too complex. this is because the bitmap is stored uncompressed and tends to be very large in filesize, so for sketches intended to run online, the only compression applied to it will be the LZW one of the .jar file the image will reside in. in my tests i got results between 25-50% of the original filesize. below is some code for loading such an image. like the default loadImage() function, loadTarga() also returns a standard BImage object.

void setup() {

BImage img=loadTarga("test.tga");
// resize screen to image dimensions
size(img.width,img.height);
image(img,0,0);
}

BImage loadTarga(String file) {
// load image file as byte array
byte[] buffer=loadBytes(file);

// check if it's a TGA and has 8bits/colour channel
if (buffer[2] == 2 && buffer[17] == 8) {
// get image dimensions
int w=(b2i(buffer[13])<<8) + b2i(buffer[12]);
int h=(b2i(buffer[15])<<8) + b2i(buffer[14]);
// check if image has alpha
boolean hasAlpha=(buffer[16] == 32);

// setup new image object
BImage img=new BImage(w,h);
img.format=(hasAlpha ? RGBA : RGB);

// targa's are written upside down, so we need to parse it in reverse
int index = (h-1) * w;
// actual bitmap data starts at byte 18
int offset=18;

// read out line by line
for (int y = h-1; y >= 0; y--) {
for (int x = 0; x < w; x++) {
// merge RGB components first
img.pixels[index + x] = b2i(buffer[offset++]) |
b2i(buffer[offset++])<<8 |
b2i(buffer[offset++])<<16;
// then set alpha based on data or revert to 100%
// (if there's only a 24bit image)
if (hasAlpha) img.pixels[index + x]|=b2i(buffer[offset++])<<24;
else img.pixels[index + x]|=0xff000000;
}
// next scanline
index -= w;
}
return img;
}
println("loadTarga(): wrong image format");
return null;
}

// byte to integer conversion
int b2i(byte b) {
return (int)(b<0 ? 256+b : b);
}