【问题标题】:Java TGA loaderJava TGA 加载器
【发布时间】:2009-10-03 15:24:09
【问题描述】:

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

是的,我已经用 google 搜索过了,但大多数结果已经过时,或者是包含许多其他我不需要的东西的相当大的库。我正在寻找只读取 TGA 图像的小而简单的东西。

谢谢!

【问题讨论】:

    标签: java image loading bufferedimage tga


    【解决方案1】:

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

    【讨论】:

    • 嗨,谁,你还在吗?感谢您的回答,它几乎完美地解决了我的问题,但是还有一个小瑕疵,就是永远不要纠正tga文件的方向。
    • 我在这里,您的问题是方向错误/翻转/镜像?在屏幕上或保存为 png 文件?示例 tga 文件是否可用?
    • 嗨谁,这是我的问题,有人给了我答案...谢谢。 stackoverflow.com/questions/29845136/…
    【解决方案2】:

    我们使用从一些开源项目复制的这个类来读取 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;
            }
    }
    

    【讨论】:

    • 非常感谢!第一次尝试在这一行给了我一个arrayoutofboundsexception: for (int i = 0; i
    • @clamp 将
    • 我的图像结果上下翻转。有什么建议吗?
    【解决方案3】:

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

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


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

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

    【讨论】:

      【解决方案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;
          }
      }
      

      【讨论】:

        【解决方案5】:

        感谢分享!

        我进行了一些更改以提高性能。我只是在做 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;
        }
        

        【讨论】:

          猜你喜欢
          • 2011-08-02
          • 2016-12-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-12-03
          • 2010-10-07
          • 2012-11-01
          相关资源
          最近更新 更多