Christian: JPG unter Java speichern / Image in ein BufferedImage umwandeln?

Hallo,

Ich möchte ein Bild, auf das eine Imagereferenz verweist, unter Java als jpg abspeichern und dazu den jpeg-Encoder von sun (com.sun.image.codec.jpeg.*) verwenden:

/********************************************************/
es funktioniert z.B. folgendes (Code in der main):
try
{
// screenshot in ein BufferedImage schreiben:
BufferedImage screenshot = (new Robot()).createScreenCapture(new Rectangle(0,0,800,600)) ;

// in die Datei test.jpg schreiben:
OutputStream out = new BufferedOutputStream(new FileOutputStream("meinBild.jpg")) ;
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder (out) ;
encoder.encode(screenshot) ;
out.close() ;
}
catch (Exception exc) {exc.printStackTrace();}
/********************************************************/

Statt eines screenshots möchte ich jetzt ein bestehendes Imageobjekt (Image pic;) in die Datei schreiben. Die Methode encode des JPEGImageEncoder-Objekts benötigt aber ein BufferedImage. Weiß jemand wie ein Imageobjekt in Java in ein BufferedImage umgewandelt werden kann bzw. das Bild, auf das die Image-Referenz verweist in ein mit new erstelltes BufferedImage kopiert werden kann? Oder ist es viel einfacher?

Grüße aus Stralsund,
Christian

  1. Hi!

    Statt eines screenshots möchte ich jetzt ein bestehendes Imageobjekt (Image pic;) in die Datei schreiben. Die Methode encode des JPEGImageEncoder-Objekts benötigt aber ein BufferedImage. Weiß jemand wie ein Imageobjekt in Java in ein BufferedImage umgewandelt werden kann bzw. das Bild, auf das die Image-Referenz verweist in ein mit new erstelltes BufferedImage kopiert werden kann? Oder ist es viel einfacher?

    Ich hab mal nachgeguckt: BufferedImage ist von Image abgeleitet. Du müsstest es also eigentlich ohne Probleme übergeben können. Hast Du es schon mal ausprobiert? Was meldet er?

    VG Simon

    1. Ich hab mal nachgeguckt: BufferedImage ist von Image abgeleitet. Du müsstest es also eigentlich ohne Probleme übergeben können. Hast Du es schon mal ausprobiert? Was meldet er?

      VG Simon

      Hi Simon,

      Ja, hatte ich auch gesehen, dass BufferedImage von Image abgeleitet ist, und versucht das Image so zu übergeben. Ging aber nicht, die Methode encode der Klasse JPEGImageEncoder benötigt ein BufferedImage. Die Fehlermeldung lautet:

      Fehler#300: Methode encode(java.awt.Image) nicht gefunden in Schnittstelle com.sun.image.codec.jpeg.IPEGImageEncoder

      Mit einem BufferedImage-Objekt funktioniert es dagegen. Downcasten geht natürlich nicht, also hatte ich ein BufferedImage mit new erzeugt und versucht, das Bild irgendwie über ein graphics-objekt mit der Methode drawimage zu übertragen.. hat aber bisher nicht geklappt:

      /***************************************************/
      BufferedImage img = new BufferedImage(0,0, BufferedImage.TYPE_INT_RGB);
      Graphics2D g = (Graphics2D)img.getGraphics();
      g.fillRect(0,0,200,200); //dies geht, das Rechteck wird mit abgespeichert
      g.drawImage( meineImageInstanz , 0,0, this); //geht irgendwie nicht, (this ist ein ImageObserver-objekt, die Klasse implementiert dieses Interface).
      /***************************************************/

      Hintergrund ist der, das Bild in einer HTML-Seite mit dem <img> tag anzuzeigen. dazu soll es aus dem Image-objekt zuvor auf Festplatte gespeichert werden. Das muß ja eigentlich einfach gehen, nur wie?

      Christian

      1. Hi Christian,

        /***************************************************/
        BufferedImage img = new BufferedImage(0,0, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = (Graphics2D)img.getGraphics();
        g.fillRect(0,0,200,200); //dies geht, das Rechteck wird mit abgespeichert
        g.drawImage( meineImageInstanz , 0,0, this); //geht irgendwie nicht, (this ist ein ImageObserver-objekt, die Klasse implementiert dieses Interface).
        /***************************************************/

        erstmal müsste das BufferedImge größer als 0,0 sein. Ich vermute mal Tippfehler im posting, aber das eignetliche Problem liegt wahrscheinlich in der Art, wie in Java so ein Bild gezeichnet wird. Wenn fillRect funktioniert, funktioniert DrawImage genauso gut, mit einem kleinen Unterschied: DrawImage malt das Bild in einem nebenläufigen Thread, wenn Du abspeicherst ist er schlicht noch nicht fertig mit dem Malen. Ich glaube der ImageObserver dient zur Kontrolle ob der Zweichenvorgang fertig ist, allerdings weiss ich auch nicht wie man den einsetzt, hab das mal auf primitive Methode gelöst, indem ich zwishcen dem Malen und der Verwendung des Bildes schon ein neues Bild über die Leitung geholt hab, wenn das da war, war er dann auch fertig mit malen, aber das ist nicht die professionelle Variante.

        Gruss

        Marko

        Gruss

        Marko

        1. Hi Marko!

          DrawImage malt das Bild in einem nebenläufigen Thread, wenn Du abspeicherst ist er schlicht noch nicht fertig mit dem Malen.

          Naja, kann sein, dass drawImage() einen Thread benutzt; es kommt aber laut Doku sofort zurück. Der Haken ist nur, dass es nur soviel zeichnet, wie bisher geladen wurde. Wenn das Bild also noch nicht komplett geladen ist, malt er einfach was da ist. Wenigstens sagt er aber in diesem Fall bescheid: Wenn das Bild nicht komplett geladen war, gibt er false zurück; außerdem benachrichtigt er den ImageObserver davon. Zu überprüfen, ob es daran liegt, ist also ziemlich einfach.

          VG Simon

      2. Hi!

        Ja, hatte ich auch gesehen, dass BufferedImage von Image abgeleitet ist, und versucht das Image so zu übergeben. Ging aber nicht, die Methode encode der Klasse JPEGImageEncoder benötigt ein BufferedImage. Die Fehlermeldung lautet:

        Achsooooo, sorry, hatte mich verlesen. Hab gedacht, Du hättest ein BufferedImage und bräuchtest ein Image.
        Sag mir mal, wo ich die API-Doku zu diesem Encoder finde? Ist natürlich die Frage, warum er ein BufferedImage fordert. Woher kriegst Du denn das Image-Objekt? Gibt es da nicht eine Möglichkeit, direkt ein BufferedImage zu bekommen?

        /***************************************************/
        BufferedImage img = new BufferedImage(0,0, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = (Graphics2D)img.getGraphics();

        Nimm doch img.createGraphics(), dann brauchst Du nicht mehr zu casten. Außerdem: Du benutzt nachher sowieso die drawImage()-Methode von Graphics.

        g.fillRect(0,0,200,200); //dies geht, das Rechteck wird mit abgespeichert
        g.drawImage( meineImageInstanz , 0,0, this); //geht irgendwie nicht, (this ist ein ImageObserver-objekt, die Klasse implementiert dieses Interface).

        Was genau geht hier nicht? Passiert einfach nur nichts?
        In der Doku steht, drawImage() würde false zurückgeben, wenn das Bild noch nicht fertig geladen ist. Fang das mal ab. Ich denke, da liegt das Problem.

        VG Simon