public static BufferedImage readTGA(File file) throws IOException { if (!file.exists()) throw new FileNotFoundException(file.getAbsolutePath()); byte[] header = new byte[18]; int len = (int) file.length() - header.length; if (len < 0) throw new IllegalStateException("file not big enough to contain header: " + file.getAbsolutePath()); byte[] data = new byte[len]; RandomAccessFile raf = new RandomAccessFile(file, "r"); raf.read(header); raf.read(data); raf.close(); if ((header[0] | header[1]) != 0) throw new IllegalStateException(file.getAbsolutePath()); if (header[2] != 2) throw new IllegalStateException(file.getAbsolutePath()); int w = 0, h = 0; w |= (header[12] & 0xFF) << 0; w |= (header[13] & 0xFF) << 8; h |= (header[14] & 0xFF) << 0; h |= (header[15] & 0xFF) << 8; boolean alpha; if ((w * h) * 3 == data.length) alpha = false; else if ((w * h) * 4 == data.length) alpha = true; else throw new IllegalStateException(file.getAbsolutePath()); if (!alpha && (header[16] != 24)) throw new IllegalStateException(file.getAbsolutePath()); if (alpha && (header[16] != 32)) throw new IllegalStateException(file.getAbsolutePath()); if ((header[17] & 15) != (alpha ? 8 : 0)) throw new IllegalStateException(file.getAbsolutePath()); BufferedImage dst = new BufferedImage(w, h, alpha ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB); int[] pixels = ((DataBufferInt) dst.getRaster().getDataBuffer()).getData(); if (pixels.length != w * h) throw new IllegalStateException(file.getAbsolutePath()); if (data.length != pixels.length * (alpha ? 4 : 3)) throw new IllegalStateException(file.getAbsolutePath()); if (alpha) { for (int i = 0, p = (pixels.length - 1) * 4; i < pixels.length; i++, p -= 4) { pixels[i] |= ((data[p + 0]) & 0xFF) << 0; pixels[i] |= ((data[p + 1]) & 0xFF) << 8; pixels[i] |= ((data[p + 2]) & 0xFF) << 16; pixels[i] |= ((data[p + 3]) & 0xFF) << 24; } } else { for (int i = 0, p = (pixels.length - 1) * 3; i < pixels.length; i++, p -= 3) { pixels[i] |= ((data[p + 0]) & 0xFF) << 0; pixels[i] |= ((data[p + 1]) & 0xFF) << 8; pixels[i] |= ((data[p + 2]) & 0xFF) << 16; } } if ((header[17] >> 4) == 1) { // ok } else if ((header[17] >> 4) == 0) { // flip horizontally for (int y = 0; y < h; y++) { int w2 = w / 2; for (int x = 0; x < w2; x++) { int a = (y * w) + x; int b = (y * w) + (w - 1 - x); int t = pixels[a]; pixels[a] = pixels[b]; pixels[b] = t; } } } else { throw new UnsupportedOperationException(file.getAbsolutePath()); } return dst; } public static void writeTGA(BufferedImage src, File file) throws IOException { DataBuffer buffer = src.getRaster().getDataBuffer(); boolean alpha = src.getColorModel().hasAlpha(); byte[] data; if (buffer instanceof DataBufferByte) { byte[] pixels = ((DataBufferByte) src.getRaster().getDataBuffer()).getData(); if (pixels.length != src.getWidth() * src.getHeight() * (alpha ? 4 : 3)) throw new IllegalStateException(); data = new byte[pixels.length]; for (int i = 0, p = pixels.length - 1; i < data.length; i++, p--) { data[i] = pixels[p]; } } else if (buffer instanceof DataBufferInt) { int[] pixels = ((DataBufferInt) src.getRaster().getDataBuffer()).getData(); if (pixels.length != src.getWidth() * src.getHeight()) throw new IllegalStateException(); data = new byte[pixels.length * (alpha ? 4 : 3)]; if (alpha) { for (int i = 0, p = pixels.length - 1; i < data.length; i += 4, p--) { data[i + 0] = (byte) ((pixels[p] >> 0) & 0xFF); data[i + 1] = (byte) ((pixels[p] >> 8) & 0xFF); data[i + 2] = (byte) ((pixels[p] >> 16) & 0xFF); data[i + 3] = (byte) ((pixels[p] >> 24) & 0xFF); } } else { for (int i = 0, p = pixels.length - 1; i < data.length; i += 3, p--) { data[i + 0] = (byte) ((pixels[p] >> 0) & 0xFF); data[i + 1] = (byte) ((pixels[p] >> 8) & 0xFF); data[i + 2] = (byte) ((pixels[p] >> 16) & 0xFF); } } } else { throw new UnsupportedOperationException(); } 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)); RandomAccessFile raf = new RandomAccessFile(file, "rw"); raf.write(header); raf.write(data); raf.setLength(raf.getFilePointer()); // trim raf.close(); }
2010-02-04
Image :: read/write TGA
Subscribe to:
Post Comments (Atom)
Hi. I would like to include this code (writeTGA) into my project http://perceptron.sourceforge.net/
ReplyDeleteI am using a very slow method of saving images, and this one works a lot better. Is it okay to attribute you in the source code like this:
/**
* Read and write TGA image files.
*
* @author Riven
* http://riven8192.blogspot.com/2010/02/image-readwrite-tga.html
*
*/
Hooray.
ReplyDeleteI am very new for the TGA images, Your code helped lot to create a TGA file. But writeTGA output look like flipped horizontally, is there any idea to fix this?
ReplyDeleteHorizontal flipping is controlled by the 5th bit of the 17th byte of the header.
ReplyDeleteheader[17] = (byte) ((alpha ? 8 : 0) | (1 << 4));
header[17] = (byte) ((alpha ? 8 : 0) | (0 << 4));
Great Work, in case you want to convert your tga file to other formats then use this converter;
ReplyDeleteFile Spinner
That will support in various formats like these;
ReplyDeleteMp4 to Png
Oga to Mp3
Tga to Jpg
3gp to mp3
Wav to Wma