2009-10-03 8 views
7

Sto cercando una classe di caricamento di immagini TGA piccola o libera per java. Idealmente il risultato è una BufferedImage.Java TGA loader

Sì, ho già cercato su Google, ma la maggior parte dei risultati è obsoleta, o sono librerie piuttosto grandi che contengono molte altre cose di cui non ho bisogno. Sto cercando qualcosa di piccolo e semplice che legge solo immagini TGA.

Grazie!

risposta

8

Usiamo questa classe copiata da qualche progetto open source per leggere i file TGA. È molto vecchio Può gestire solo i file Targa con la maggior parte delle codifiche di base. Provaci.

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

grazie mille! un primo tentativo mi dà un arrayoutofboundsexception in questa linea: \t \t \t \t for (int i = 0; i <= nb; i ++) \t \t \t \t \t pixel [idx ++] = v; – clamp

+0

@clamp change <= nb a throwaway

+0

Il risultato dell'immagine è capovolta. qualche consiglio? – squallbayu

9

Avevo immagini di targa non compresse, quindi ho dovuto modificare il codice di esempio. Qui è la mia modifica dovrebbe sostenere non compresso BGR targa 24bit e 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

Ciao, Whome, sei ancora qui? grazie per la tua risposta, ha risolto quasi perfettamente il mio problema, ma c'è ancora un piccolo difetto, cioè, mai correggere la direzione del file tga. –

+0

Im qui, il tuo problema è un orientamento sbagliato/capovolto/specchiato? Sullo schermo o salvato in file png? Esempi di file TGA disponibili? – Whome

+0

Ciao, ecco il mio problema e qualcuno mi ha offerto la risposta ... Grazie. http://stackoverflow.com/questions/29845136/how-to-get-the-direction-of-tga-file-in-java –

4

Ho aggiunto una copia autonoma di Realtà biblioteca di Interactive ImageIO TGA qui (LGPL):

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


Basta aggiungere il file jar al classpath e registrarsi con ImageIO:

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

Grazie per averlo condiviso!

Ho apportato alcune modifiche per migliorare le prestazioni. Sto solo decifrando file BGRA 32 Bit, ma può aiutare gli altri.

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

Solo nel caso qualcuno è alla ricerca per la versione Android di questo (ho dovuto sostituire 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; 
    } 
} 
Problemi correlati