Java TGA loader

后端 未结 5 1422

I am looking for a small and free TGA image loading class or library for java. Ideally the result is a BufferedImage.

Yes, I have already googled, but most results a

相关标签:
5条回答
  • 2021-01-05 02:52

    I had uncompressed targa images, so had to tweak example code. Here is my edit it should support uncompressed targa 24bit BGR and 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;
            }
    }
    
    0 讨论(0)
  • 2021-01-05 02:54

    We use this class copied from some open source project to read TGA files. It's really old. It can only handle Targa files with most basic encoding. Give it a try.

    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;
            }
    }
    
    0 讨论(0)
  • 2021-01-05 03:07

    Thanks for sharing it!

    I've made some changes to improve performance. I'm only doing BGRA 32 Bits file decrypt, but it can help others people.

    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;
    }
    
    0 讨论(0)
  • 2021-01-05 03:11

    Just in case anyone is looking for the Android version of this (I had to replace BufferedImage with 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;
        }
    }
    
    0 讨论(0)
  • 2021-01-05 03:16

    I've added a standalone copy of Reality Interactive's ImageIO TGA library here (LGPL):

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


    Just add the the jar file to your classpath and register with ImageIO:

    IIORegistry registry = IIORegistry.getDefaultInstance();
    registry.registerServiceProvider(
        new com.realityinteractive.imageio.tga.TGAImageReaderSpi());
    
    0 讨论(0)
提交回复
热议问题