cargador de Java TGA
-
19-09-2019 - |
Pregunta
Busco una clase de carga de la imagen pequeña y libre TGA o biblioteca de Java. Lo ideal sería que el resultado es un BufferedImage.
Sí, ya he buscado en Google, pero la mayoría de los resultados no están actualizados, o son bastante grandes bibliotecas que contienen una gran cantidad de otras cosas que no necesito. Busco algo pequeño y simple que lee sólo imágenes TGA.
Gracias!
Solución
Utilizamos esta clase copiado de algún proyecto de código abierto para leer archivos TGA. Es muy viejo. Sólo se puede manejar archivos Targa con la mayor parte de codificación básica. Darle una oportunidad.
public class TargaReader
{
public static Image getImage(String fileName) throws IOException
{
File f = new File(fileName);
byte[] buf = new byte[(int)f.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
bis.read(buf);
bis.close();
return decode(buf);
}
private static int offset;
private static int btoi(byte b)
{
int a = b;
return (a<0?256+a:a);
}
private static int read(byte[] buf)
{
return btoi(buf[offset++]);
}
public static Image decode(byte[] buf) throws IOException
{
offset = 0;
// Reading header
for (int i=0;i<12;i++)
read(buf);
int width = read(buf)+(read(buf)<<8);
int height = read(buf)+(read(buf)<<8);
read(buf);
read(buf);
// Reading data
int n = width*height;
int[] pixels = new int[n];
int idx=0;
while (n>0)
{
int nb = read(buf);
if ((nb&0x80)==0)
{
for (int i=0;i<=nb;i++)
{
int b = read(buf);
int g = read(buf);
int r = read(buf);
pixels[idx++] = 0xff000000 | (r<<16) | (g<<8) | b;
}
}
else
{
nb &= 0x7f;
int b = read(buf);
int g = read(buf);
int r = read(buf);
int v = 0xff000000 | (r<<16) | (g<<8) | b;
for (int i=0;i<=nb;i++)
pixels[idx++] = v;
}
n-=nb+1;
}
BufferedImage bimg = new BufferedImage(width,height,BufferedImage.TYPE_INT_ARGB);
bimg.setRGB(0,0,width,height,pixels,0,width);
return bimg;
}
}
Otros consejos
tuve imágenes Targa sin comprimir, por lo que tuvo que modificar código de ejemplo. Aquí está mi edición se debe apoyar sin comprimir BGR Targa 24 bits y 32 bits BGRA
// http://paulbourke.net/dataformats/tga/
// little endian multi-byte integers: "low-order byte,high-order byte"
// 00,04 -> 04,00 -> 1024
class TargaReader {
public static BufferedImage getImage(String fileName) throws IOException {
File f = new File(fileName);
byte[] buf = new byte[(int)f.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
bis.read(buf);
bis.close();
return decode(buf);
}
private static int offset;
private static int btoi(byte b) {
int a = b;
return (a<0?256+a:a);
}
private static int read(byte[] buf) {
return btoi(buf[offset++]);
}
public static BufferedImage decode(byte[] buf) throws IOException {
offset = 0;
// Reading header bytes
// buf[2]=image type code 0x02=uncompressed BGR or BGRA
// buf[12]+[13]=width
// buf[14]+[15]=height
// buf[16]=image pixel size 0x20=32bit, 0x18=24bit
// buf{17]=Image Descriptor Byte=0x28 (00101000)=32bit/origin upperleft/non-interleaved
for (int i=0;i<12;i++)
read(buf);
int width = read(buf)+(read(buf)<<8); // 00,04=1024
int height = read(buf)+(read(buf)<<8); // 40,02=576
read(buf);
read(buf);
int n = width*height;
int[] pixels = new int[n];
int idx=0;
if (buf[2]==0x02 && buf[16]==0x20) { // uncompressed BGRA
while(n>0) {
int b = read(buf);
int g = read(buf);
int r = read(buf);
int a = read(buf);
int v = (a<<24) | (r<<16) | (g<<8) | b;
pixels[idx++] = v;
n-=1;
}
} else if (buf[2]==0x02 && buf[16]==0x18) { // uncompressed BGR
while(n>0) {
int b = read(buf);
int g = read(buf);
int r = read(buf);
int a = 255; // opaque pixel
int v = (a<<24) | (r<<16) | (g<<8) | b;
pixels[idx++] = v;
n-=1;
}
} else {
// RLE compressed
while (n>0) {
int nb = read(buf); // num of pixels
if ((nb&0x80)==0) { // 0x80=dec 128, bits 10000000
for (int i=0;i<=nb;i++) {
int b = read(buf);
int g = read(buf);
int r = read(buf);
pixels[idx++] = 0xff000000 | (r<<16) | (g<<8) | b;
}
} else {
nb &= 0x7f;
int b = read(buf);
int g = read(buf);
int r = read(buf);
int v = 0xff000000 | (r<<16) | (g<<8) | b;
for (int i=0;i<=nb;i++)
pixels[idx++] = v;
}
n-=nb+1;
}
}
BufferedImage bimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
bimg.setRGB(0, 0, width,height, pixels, 0,width);
return bimg;
}
}
He añadido una copia independiente de la biblioteca de Interactivo ImageIO TGA realidad aquí (LGPL):
https://github.com/tmyroadctfig/com.realityinteractive.imageio.tga
Sólo tiene que añadir el archivo de la jarra a la ruta de clases y registrarse con ImageIO:
IIORegistry registry = IIORegistry.getDefaultInstance();
registry.registerServiceProvider(
new com.realityinteractive.imageio.tga.TGAImageReaderSpi());
Por si acaso alguien está buscando la versión de Android de este (tuve que reemplazar BufferedImage
con Bitmap
).
class TargaReader {
public static Bitmap getImage(String fileName) throws IOException {
File f = new File(fileName);
byte[] buf = new byte[(int) f.length()];
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
bis.read(buf);
bis.close();
return decode(buf);
}
private static int offset;
private static int btoi(byte b) {
int a = b;
return (a < 0 ? 256 + a : a);
}
private static int read(byte[] buf) {
return btoi(buf[offset++]);
}
public static Bitmap decode(byte[] buf) throws IOException {
offset = 0;
// Reading header bytes
// buf[2]=image type code 0x02=uncompressed BGR or BGRA
// buf[12]+[13]=width
// buf[14]+[15]=height
// buf[16]=image pixel size 0x20=32bit, 0x18=24bit
// buf{17]=Image Descriptor Byte=0x28 (00101000)=32bit/origin
// upperleft/non-interleaved
for (int i = 0; i < 12; i++)
read(buf);
int width = read(buf) + (read(buf) << 8); // 00,04=1024
int height = read(buf) + (read(buf) << 8); // 40,02=576
read(buf);
read(buf);
int n = width * height;
int[] pixels = new int[n];
int idx = 0;
if (buf[2] == 0x02 && buf[16] == 0x20) { // uncompressed BGRA
while (n > 0) {
int b = read(buf);
int g = read(buf);
int r = read(buf);
int a = read(buf);
int v = (a << 24) | (r << 16) | (g << 8) | b;
pixels[idx++] = v;
n -= 1;
}
} else if (buf[2] == 0x02 && buf[16] == 0x18) { // uncompressed BGR
while (n > 0) {
int b = read(buf);
int g = read(buf);
int r = read(buf);
int a = 255; // opaque pixel
int v = (a << 24) | (r << 16) | (g << 8) | b;
pixels[idx++] = v;
n -= 1;
}
} else {
// RLE compressed
while (n > 0) {
int nb = read(buf); // num of pixels
if ((nb & 0x80) == 0) { // 0x80=dec 128, bits 10000000
for (int i = 0; i <= nb; i++) {
int b = read(buf);
int g = read(buf);
int r = read(buf);
pixels[idx++] = 0xff000000 | (r << 16) | (g << 8) | b;
}
} else {
nb &= 0x7f;
int b = read(buf);
int g = read(buf);
int r = read(buf);
int v = 0xff000000 | (r << 16) | (g << 8) | b;
for (int i = 0; i <= nb; i++)
pixels[idx++] = v;
}
n -= nb + 1;
}
}
Bitmap bimg = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bimg.setPixels(pixels, 0, width, 0, 0, width, height);
return bimg;
}
}
Gracias por compartirlo!
He hecho algunos cambios para mejorar el rendimiento. Yo sólo estoy haciendo BGRA 32 Bits archivo descifrar, pero puede ayudar a otros personas.
public static BufferedImage createTGAImage(byte[] buff) throws IOException {
int offset = 0, width = 0, height = 0;
int[] tgaBuffer = null;
if (buff[2] == 0x02) { // BGRA File
offset = 12;
width = (buff[offset + 1] << 8 | buff[offset]);
offset = 14;
height = (buff[offset + 1] << 8 | buff[offset]);
int colorDepth = buff[offset + 2];
if (colorDepth == 0x20) { // 32 bits depth
offset = 18;
int count = width * height;
tgaBuffer = new int[count];
for (int i = 0; i < count; i++) {
byte b = buff[offset++]; //This is for didatic prupose, you can remove it and make inline covert.
byte g = buff[offset++];
byte r = buff[offset++];
byte a = buff[offset++];
tgaBuffer[i] = ((a & 0xFF) << 24 | (r & 0xFF) << 16 | (g & 0xFF)<< 8 | b & 0xFF);
}
}
}
BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
result.setRGB(0, 0, width, height, tgaBuffer, 0, width);
return result;
}