Java TGA加载器

时间:2009-10-03 15:24:10

标签: java image loading bufferedimage tga

我正在为java寻找一个小而免费的TGA图像加载类或库。 理想情况下,结果是BufferedImage。

是的,我已经google了,但大多数结果已经过时,或者是包含很多其他我不需要的东西的大型库。我正在寻找一些简单易读的TGA图像。

谢谢!

5 个答案:

答案 0 :(得分:9)

我有未压缩的targa图像,因此不得不调整示例代码。这是我的编辑它应该支持未压缩的targa 24bit BGR和32bit 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;
        }
}

答案 1 :(得分:8)

我们使用从某个开源项目复制的这个类来读取TGA文件。它真的很老了。它只能处理具有最基本编码的Targa文件。试一试。

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;
        }
}

答案 2 :(得分:4)

我在这里添加了Reality Interactive的ImageIO TGA库的独立副本(LGPL):

  

https://github.com/tmyroadctfig/com.realityinteractive.imageio.tga


只需将jar文件添加到类路径并注册ImageIO:

IIORegistry registry = IIORegistry.getDefaultInstance();
registry.registerServiceProvider(
    new com.realityinteractive.imageio.tga.TGAImageReaderSpi());

答案 3 :(得分:4)

以防万一有人在寻找Android版本(我必须将BufferedImage替换为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;
    }
}

答案 4 :(得分:1)

感谢分享!

我做了一些改进以提高性能。我只对BGRA 32位文件进行解密,但它可以帮助其他人。

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;
}