» »

[java] branje TGA

[java] branje TGA

DCER ::

Ok, že cel dan se mučim s tem, pa zgleda da sem nesposoben in se več ne bom.
Mogoče pa bo kdo tu vedel, kaj delam narobe oz. ima kako drugo rešitev.

Torej skušam prebrati tga datoteko in jo prikazati. Java sama po sebi tega ne omogoča.
Iskal sem po guglu pa nic pametnega, razen Jimi, ki pa je zgleda iz pradavnine
in mi pravtako ne dela...

Drug nacin, ki sem ga poskusil, je da bi risal posamezne pixle v BufferedImage,
in potem le-to prikazal. Tga je precej enostaven in mene zaenkrat zanima le en tip:
16-bitni Unmapped RGB.

Ima 18 bytov headerja. Od tam pa po dva byta predstavljata en pixel
(ker je little endian, zgleda v bitih to tako: GGGBBBBB ARRRRRGG)
A - alpha, G - green, R - red, B - blue.

Vec o formatu tule: TGA format specification

Tole imam do sedaj:

    public static final int TGA16toPixel(byte[] pixel, boolean littleEndian){
	    byte[] orig = new byte[]{pixel[1], pixel[0]};
	    int alpha=0;
	    int red=0;
	    int blue=0;
	    int green=0;
	    if (littleEndian){
		    //blue
		    byte[] b = new byte[4];
		    pixel = orig;
		    b[0] = pixel[1];
		    blue = (toInt(b, true) & 31) << 3;
		    //green
		    b = new byte[4];
		    pixel=orig;
		    b[0]=pixel[0];
		    green = ((toInt(b, true) & 3) << 6);
		    b[0]=pixel[1];
		    green = green | ( (toInt(b, true) >>> 2) & 56);
		    //red
		    b=new byte[4];
		    pixel=orig;
		    b[0] = pixel[0];
		    red = ((toInt(b, true) & 124) << 1);
		    //alpha
		    b=new byte[4];
		    pixel=orig;
		    b[0] = pixel[1];
		    alpha = toInt(b, true) & 128;
	    }
	    int rgba = (alpha << 24) | (red << 16) | (green << 8) | blue;
	    return rgba;
    }

	public TGA(InputStream in) throws EOFException, UnsupportedImage, IOException{
		//first read fully from inputstream
		byte[] b = new byte[in.available()];
		int kuku = 0;
		while(in.available()>0){
			int len = in.read(b, kuku, in.available());
			kuku += len;
		}
		//then get/save header
		identification_Field_Length = b[0];
		color_Map_Present = b[1];
		image_Type = b[2];
		//for (int i=0; i<5; i++) color_Map_Specs[i] = b[3+i];
		//x_Origin[0] = b[8];
		//x_Origin[1] = b[9];
		//y_Origin[0] = b[10];
		//y_Origin[1] = b[11];
		width[0] = b[12];
		width[1] = b[13];
		height[0] = b[14];
		height[1] = b[15];
		pixel_Size = b[16];
		//descriptor_Byte = b[17];
		//throw exception if format not supported
		if (identification_Field_Length != 0x00) throw new UnsupportedImage("Identification field should not be present.");
		if (color_Map_Present != 0x00) throw new UnsupportedImage("Color map should not be present.");
		if (image_Type != 0x02) throw new UnsupportedImage("Image should be unmapped RGB, but is <unknown>.");
		if (pixel_Size != 0x10) throw new UnsupportedImage("Image should be 16-bit.");
		//save data
		byte[] lul = new byte[2];
		//create bufferedimage from rest
		byte[] nWidth = new byte[4];
		byte[] nHeight = new byte[4];
		nWidth[0] = width[0];
		nWidth[1] = width[1];
		nHeight[0] = height[0];
		nHeight[1] = height[1];		
		image = new BufferedImage(Convert.toInt(nWidth, true),Convert.toInt(nHeight, true), BufferedImage.TYPE_INT_ARGB);
		//System.out.println(Convert.toInt(nWidth, true));
		//System.out.println(Convert.toInt(nHeight, true));
		for (int w=0; w<Convert.toInt(nWidth, true); w++){
			for (int h=0; h<Convert.toInt(nHeight, true); h++){
				lul[0] = b[17 + w*(Convert.toInt(nHeight, true))+(2*h)];
				lul[1] = b[17 + w*(Convert.toInt(nHeight, true))+(2*h+1)];
				image.setRGB(w, h, Convert.TGA16toPixel(lul, true));
			}
		}
	}
	
	public BufferedImage getBufferedImage(){
		return image;
	}
}

	public java.awt.Image getTGAImage(String name) throws FileNotFoundException{
		InputStream in = null;
		java.awt.Image img = null;
		try{
			ZipFile zf = new ZipFile(FILE);
			ZipEntry ze = zf.getEntry(name);
			
			if (ze==null){
				zf.close();
				throw new FileNotFoundException(name + " not found.");
			}
			
			in = zf.getInputStream(ze);
			img = (new TGA(in)).getBufferedImage();
			zf.close();
		}catch (IOException e){
			JOptionPane.showMessageDialog(null, "An IO error occured.", "Error in getImage()", JOptionPane.ERROR_MESSAGE);			
		}catch (UnsupportedImage e){
			JOptionPane.showMessageDialog(null, "Error reading TGA file (" + name + ") :\n" + e.getMessage(), "Error in getImage()", JOptionPane.ERROR_MESSAGE);			
			return null;
		}
		return img;
	}

//sliko hocem prikazati s JLabel
Image = new JLabel(new ImageIcon(getTGAImage("test.tga")));



Tga je pravega formata. Header je dobro prebran (višina, širina- sem preveril.)
Mogoče je problem pri pretvarjanju tga pixla v int? Prvič sem delal z biti :))
ampak mislim da bi moralo v redu biti. Slika je v redu prebrana, nobeni napak ne dobim,
ampak slika pa se pa ne prikaže :( pa ni problem pri JLabel, ker sem vmes imel tga16topixel narobe
in se je nek črn tatu narisal.:D seveda niti podoben pravi sliki, ki poleg vsega še barvasta...
Zdaj pa prazno. Ve kdo kak (lahek) način kako prikazati tga v javi?
Se raje pa bi vedel kaj je narobe z mojo implementacijo :))
  • spremenilo: DCER ()

BaToCarx ::

Nisem lih programer.

Samo ko ti prebereš TGA ga potem v spominu konvertiraš v kak Javi prijazen format al ne?

DCER ::

Ja, v BufferedImage.

Tule:

image = new BufferedImage(Convert.toInt(nWidth, true),Convert.toInt(nHeight, true), BufferedImage.TYPE_INT_ARGB);

S temle pa določam pixle:

image.setRGB(w, h, Convert.TGA16toPixel(lul, true));

Najbrž je nekaj s pretvorbo pixlov narobe, torej v TGA16toPixel. Sem že parkrat skoz šel, pa nevem... Mogoče mi bo kasneje še kaj kapnilo :))

Quikee ::

Mogoce pa ti more TGA16toPixel vracat v 0000 000A 000R RRRR 000G GGGG 000B BBBB.. trenutno mas A000 0000 RRRR R000 GGGG G000 BBBB B000.. Lahko pa da se motim ker ne vem kak ma java to.

kopernik ::

Tukaj imaš kar nekaj povezav do raznih orodij za delo s slikami, tudi TGA format:
http://www.geocities.com/marcoschmidt.geo/java-image-coding.html

Precej jih je zastonj.

DCER ::

Pri tem se nič ne vidi:

    /**Converts 16-bit Tga pixel to integer*/
    public static final int TGA16toPixel(byte[] pixel, boolean littleEndian){
	    byte[] orig = new byte[]{pixel[1], pixel[0]};
	    int alpha=0;
	    int red=0;
	    int blue=0;
	    int green=0;
	    //blue
	    byte[] b = new byte[4];
	    pixel = orig;
	    b[0] = pixel[1];
	    blue = (toInt(b, true) & 31);
	    //green
	    b = new byte[4];
	    pixel=orig;
	    b[0]=pixel[0];
	    green = ((toInt(b, true) & 3) << 3) & 24;
	    b[0]=pixel[1];
	    green = (green | ( (toInt(b, true) >> 5) & 7)) & 31;
	    //red
	    b=new byte[4];
	    pixel=orig;
	    b[0] = pixel[0];
	    red = ((toInt(b, true) & 124) >> 2) & 31;
	    //alpha
	    b=new byte[4];
	    pixel=orig;
	    b[0] = pixel[0];
	    alpha = (toInt(b, true) >> 7)& 1;
	    
	    int rgba = (alpha << 24) | (red << 16) | (green << 8) | blue;
	    return rgba;
    } 


To zgoraj naj bi vrnilo 000000A 000RRRRR 000GGGGG 000BBBBB

Pa se tole imam:

 /**Converts 16-bit Tga pixel to integer*/
    public static final int TGA16toPixel(byte[] pixel, boolean littleEndian){
	    byte[] orig = new byte[]{pixel[1], pixel[0]};
	    int alpha=0;
	    int red=0;
	    int blue=0;
	    int green=0;
	    //blue
	    byte[] b = new byte[4];
	    pixel = orig;
	    b[0] = pixel[1];
	    blue = ((toInt(b, true) & 31) << 3) & 248;
	    //green
	    b = new byte[4];
	    pixel=orig;
	    b[0]=pixel[0];
	    green = ((toInt(b, true) & 3) << 6) & 192;
	    b[0]=pixel[1];
	    green = (green | ( (toInt(b, true) >> 2) & 56)) & 248;
	    //red
	    b=new byte[4];
	    pixel=orig;
	    b[0] = pixel[0];
	    red = ((toInt(b, true) & 124) << 1) & 248;
	    //alpha
	    b=new byte[4];
	    pixel=orig;
	    b[0] = pixel[0];
	    alpha = toInt(b, true) & 128;
	    
	    int rgba = (alpha << 24) | (red << 16) | (green << 8) | blue;
	    return rgba;
    } 


Tale pa naj bi vrnil A0000000 RRRRRR000 GGGGG000 BBBBB000, pri tem se mi zdaj pokaže zeleno violična umetnija.

Kopernik, bil sem na tisti strani, pa sta edino Jimi in ImageLoader obljubljala rešitev, s tem ko ImageLoader stran ni delala. Zdaj pa zgleda da dela. Bom probal zdaj še tega.

Zgodovina sprememb…

  • spremenilo: DCER ()

kopernik ::

Kaj pa TargaImage ? Imaš en class v izvorni kodi, mogoče si boš lahko kaj pomagal ...

DCER ::

Kopernik... hvala ti! hvala ti! hvala ti! hvala ti! hvala ti! hvala ti! hvala ti! hvala ti! hvala ti! hvala ti! hvala ti! :))

tale zadnji class je bil prava rešitev. Malo sem ga spremenil, tako da zdaj lahko bere tudi 16 bitne tga (kar sem rabil).

        /* --- read the pixel data ---
Prej:  */
        for (int i = (height - 1); i >= 0; i--) {
            srcLine = i * width;
            for (int j = 0; j < width; j++) {
                blue = bis.read() & 0xFF;
                green = bis.read() & 0xFF;
                red = bis.read() & 0xFF;
                if (pixelDepth == 32) {

                    alpha = bis.read() & 0xFF;
                    pixels[srcLine + j] =
                            alpha << 24 | red << 16 | green << 8 | blue;
                } else {
                    pixels[srcLine + j] = red << 16 | green << 8 | blue;
                }
            }
        }


        /* --- read the pixel data --- 
Zdaj:   */
        for (int i = (height - 1); i >= 0; i--) {
            srcLine = i * width;
            for (int j = 0; j < width; j++) {
                if (pixelDepth == 32) {
		    blue = bis.read() & 0xFF;
		    green = bis.read() & 0xFF;
		    red = bis.read() & 0xFF;
                    alpha = bis.read() & 0xFF;
                    pixels[srcLine + j] =
                            alpha << 24 | red << 16 | green << 8 | blue;
                } else if (pixelDepth == 24){
                    pixels[srcLine + j] = red << 16 | green << 8 | blue;
                } else if (pixelDepth == 16) {
		    int second = bis.read() & 0xFF;
		    int first = bis.read() & 0xFF;
		    blue = (second << 3) & 0xFF;
		    green = (((first << 6) & 0xC0) | ((second >>> 2) & 0x38)) & 0xFF;
		    red = ((first << 1) & 0xF8) & 0xFF;
                    alpha = ((first >>> 7) & 0x01) & 0xFF;
                    pixels[srcLine + j] =
                            alpha << 24 | red << 16 | green << 8 | blue;
		}
            }
        } 


Še enkrat hvala kopernik. Ravno to sem rabil, en preprost class, ki ga lahko po potrebi spremenim.

Edit: PS: zdi se mi da sem ga prej pri alpha kanalu lomil. Na koncu sem dobil A0000000, moral pa bi 0000000A.

Zgodovina sprememb…

  • spremenilo: DCER ()

kopernik ::

ej, ni problema :), zato smo tukaj, da si pomagamo.


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Začetki programiranja

Oddelek: Pomoč in nasveti
233518 (2566) FTad
»

[Android] Splošno

Oddelek: Programiranje
352004 (1134) piki12
»

Program zadelanje programčkov

Oddelek: Pomoč in nasveti
151565 (1157) boogie_xlr
»

[C#] int v byte[] in nazaj

Oddelek: Programiranje
131801 (1573) BlueRunner
»

branje byte[] iz MS access-ove baze

Oddelek: Programiranje
81938 (1848) BHawk

Več podobnih tem