Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: Java: Kuvan osa Image-muuttujaan

Sivun loppuun

Mobel [26.03.2009 13:13:45]

#

Täytyy jälleen kysäistä täältä, kun ei millään meinaa itse keksiä.
Onko mahdollista tallentaa isosta kuvasta vain osan toiseen Image-tyypin muuttujaan? Isosta kuvasta voi toki piirtää pienen osan näytölle drawImage()-metodilla, mutta kun tämä pitäisi tallentaa omaan Image-muuttujaan, niin siitä ei sitten tulekaan mitään.

Jos viimeinen lause pääsi hämäämään: Miten tallennan Image-tyypin oliosta vain osan toiseen samanlaiseen olioon.

Blaze [26.03.2009 13:29:25]

#

Puhutaanhan nyt java.awt.Imagesta?

Imagella on getGraphics()-metodi, joka palauttaa Graphics-olion, joka piirtää siihen Imageen, ei siis ruudulle.

Luo siis uusi tyhjä Image, ota sen Graphics ja piirrä tuota Graphicsia käyttäen haluamasi osa isosta kuvasta tähän vastaluotuun.

Mobel [26.03.2009 13:36:07]

#

Kiitokset pikaisesta vastauksesta.
Olin käsittänyt tuon Image- ja Graphics-olion suhteen hieman väärin. Enköhän tuolla saa homman toimimaan.

Mobel [26.03.2009 17:45:16]

#

Yritin napata Graphics -oliota pieneltä kuvalta ja piirtää siihen, mutta eihän tuo suostu tottelemaan. Kääntäjä antaa virheen yrittäessäni pyytää pieneltä kuvalta Graphics- otusta. Mitä teen väärin tai jätän tekemättä?

Metodi, jota käytän näyttää tältä:

public void piirraIsostaPieneen(){

   Image pieni, iso;
   //ladataan pieneen kuvaan varulta jotain
   URL url = this.getClass().getResource("temp.png");
   pieni=Toolkit.getDefaultToolkit().getImage(url);

   url = this.getClass().getResource("iso.png");
   iso=Toolkit.getDefaultToolkit().getImage(url);

   pieni.getGraphics().drawImage(iso, 0, 0, 100, 100,
      50, 50, 100, 100, this);
}

Tällaista virhettä pukkaa:

java.lang.UnsupportedOperationException: getGraphics() not valid for images created with createImage(producer) at sun.awt.image.ToolkitImage.getGraphics(Unknown Source)

Blaze [26.03.2009 18:33:45]

#

Toolkitin getImagella ladatut kuvat on näköjään ei-off-screen (on-screen?) -kuvia, joihin ei voi piirtää.
No, java.awt.Componentilla on createImage(int w, int h), joka ainakin tekee tuollaisia piirtämiseen sopivia (tyhjiä) kuvia.

Mobel [26.03.2009 21:30:26]

#

Kiitoksia jälleen avusta.
Vieläkään en silti saa koodia toimimaan. Nyt tosin virhe on toinen, joten kaipa tässä edistytään. Ohjelma heittää NullPointteria yrittäessäni pyytää createImage():lla luodun kuvan Graphics-oliota. Eli jostain syystä tuo olio on null.

Component c=null;
Image img, iso;

URL url = this.getClass().getResource("iso.png");
iso=Toolkit.getDefaultToolkit().getImage(url);

img=c.createImage(100, 100);

//NullPointerException tulee tästä
img.getGraphics().drawImage(iso, 0, 0, 100, 100, 0, 0, 100, 100, this);

Blaze [26.03.2009 22:05:58]

#

Niin, c on null kun sen itse asetat nulliksi tuolla ylempänä :)

Tuo java.awt.Component on kaikkien AWT- ja Swing-komponenttien kantaluokka, joten jos tuo sun piirraIsostaPieneen()-metodi sattuis olemaan vaikka Appletissa, voisit sanoa ihan suoraan this.createImage(...)

Mobel [26.03.2009 22:52:48]

#

Blaze kirjoitti:

Niin, c on null kun sen itse asetat nulliksi tuolla ylempänä :)

Niinpä tietysti. Miten tuo Component pitäisi määritellä vai meneekö kovinkin hankalaksi?

Metodi on JPanelin perillisessä, josta siis myös löytyy tuo createImage(). No yritimpä nyt näin, mutta nullPointterilta ei vältytä tuon Graphics -olion kanssa. Tämänhän pitäisi toimia, mutta en millään keksi mistä jää kiinni.
Jos laitan koodin Applettiin, se toimii moitteetta. Voisi olettaa, että myös JPanelin perillisessä pelittäisi.

Image temp=this.createImage(100, 100); //this viitaa siis JPaneliin
System.out.println(temp.getGraphics());

No, jos tuota huomenna yrittelisi uusilla silmillä. Kiitokset avusta!

Sami [26.03.2009 23:24:59]

#

int x = 255;
int y = 32;
int leveys = 110;
int korkeus = 50;

try {
	// Luodaan kuvaolio, mihin haluttu osa piirretään.
	BufferedImage kohde = new BufferedImage(leveys, korkeus, BufferedImage.TYPE_INT_RGB);

	// Luetaan kuvatiedosto, tavalla ei juurikaan ole väliä.
	// Haetaan kuitenkin mallin vuoksi ohjelmointiputkan logo ImageIO:lla.
	Image lahde = ImageIO.read(new URL("https://www.ohjelmointiputka.net/img/palkki2.jpg"));

	// Piirretään haluttu osa noudetusta kuvasta tuohon pari riviä
	// ylempänä luotuun kuvaan.
	kohde.getGraphics().drawImage(lahde, 0, 0, leveys, korkeus, x, y, x+leveys, y+korkeus, null);

	// Ja sitten mitä ikinä haluaakaan tehdä sillä kuvalla...
	// Kirjoitellaan se vaikka System.outiin kun ei muutakaan keksitä. :D
	ImageIO.write(kohde, "PNG", System.out);
} catch (MalformedURLException e) {
	System.out.println("Huono urli");
} catch (IOException e) {
	System.out.println("Kuvan lukemisessa on jotain häikkää");
}

Mobel [27.03.2009 14:07:03]

#

Kiitoksia!
Nyt sain kuvaan piirtämisen toimimaan. Nyt kuitenkin yrittäessäni saada ison kuvan pinkin taustan häivytettyä läpinäkyväksi alkaa ongelmia taas ilmetä. Käytän seuraavaa luokkaa - joka on toiminut hyvin muissa projekteissa pelkkien Image-instanssien kanssa - kuvan värin häivyttämiseen. Luokan käsittelyn jälkeen kuva on kokonaan musta.

public class SetTranspatency {
   public static Image makeTransparent(Image srcImage){
      ImageFilter RGBFilter=new RGBImageFilter(){

         Color pink=new Color(0xFFFF00FF); //100% transparent

	 public int triggerColor1=pink.getRGB() | 0xFF000000;

         public final int filterRGB(int x, int y, int rgb){
            if((rgb | 0xFF000000)==triggerColor1){
	       return 0x00FFFFFF  & rgb; //returns transparent white
	    }
            else{
	       return rgb; //rest of the colors are returned unchanced
	    }
         }
      };

      ImageProducer imgProducer=new FilteredImageSource(srcImage.getSource(), RGBFilter);
      return Toolkit.getDefaultToolkit().createImage(imgProducer);
   }

}

Kuitenkin käyttäessäni seuraavaa luokkaa, kuva näkyy oikein(pinkki häivytetynä).

public class SetTranspatency {
   public static Image makeTransparent(Image srcImage){
      Color toChange=new Color(0xFFFF00FF); //100% transparent
      int w = srcImage.getWidth(null);
      int h = srcImage.getHeight(null);

      BufferedImage dst = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
      Graphics2D g2 = dst.createGraphics();
      g2.drawImage(srcImage, 0, 0, null);
      g2.dispose();
      int repl = toChange.getRGB();
      int xp = new Color(0, 0, 0, 0).getRGB();
      System.out.printf("repl = %d  xp = %d%n", repl, xp);
      int count = 0;

      for(int y = 0; y < h; y++) {
         for(int x = 0; x < w; x++) {
            if(dst.getRGB(x, y) == repl) {
               count++;
               dst.setRGB(x, y, xp);
            }
         }
      }
      System.out.println("count = " + count);
      return dst;
   }
}

Jompaa kumpaa luokkaa käyttäen poistan tavallisesta Image:sta pinkin värin ja sen jälkeen luon kuvasta BufferedImagen näin:

...
iso=SetTranspatency.makeTransparent(iso);
bImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
bImage.getGraphics().drawImage(iso, 0, 0, 100, 100, this);
...

Mistä johtuu ensimmäisen luokan palauttama virheellinen kuva? Eipä tässä sinällään hätää ole kun kerran jälkimmäisellä tavalla toimii, ihmettelin vain miksei ensimmäinen luokka toimisi myös.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta