# Aus farbigen images (JPG) graustufen images erstellen



## Thomas Peter (14. Dez 2006)

Hallo,
nachdem ich vor einigen Monaten mit Hilfe eines anderen Java-Entwicklers ein Java-Modul zum Laufen gebracht habe, mit dem ich JPG-Bilddateien in der Größe ändern und die Dateigröße komprimieren kann, möchte ich jetzt gerne die farbigen JPG-Bilder "entfärben" oder "umfärben". Das Modul läuft auf einem Webserver (TomCat), also ohne Swing-Unterstützung.
Ich würde gerne das Bild zu schwarz-weiß (Graustufenbild) umwandeln oder einen sepia-Effekt herstellen. Leider kriege ich das nicht hin. Ich habe mit Google schon eine Menge JAVA-Examples durchforstet...

Wie kann ich's lösen?

Vielen Dank
Thomas

Das Modul, mit dem die Dateien skaliert werden (auszugsweise):


```
public int createFileWithNewSize(String inFile,
String outFile,float x, float
y,long maxKB) throws IOException {

        int ret = 1;  // 1=ok, -1 = Fehler - keine Datei angelegt, 0 =...
        RenderedOp objImage =null;
        File inputFile = new File (inFile);
        File outputFile = new File(outFile);
        InputStream is;

        // einige Prüfungen, ob Datei vorhanden etc. ....
       
        try
        {
            is = new FileInputStream(inputFile);
            SeekableStream s = SeekableStream.wrapInputStream(is, true);
            objImage = JAI.create("stream", s);
            ((OpImage)objImage.getRendering()).setTileCache(null);

            // Breitenverhältnis (neu Breite/Originalbreite)
            float xScale = x/objImage.getWidth();

            // Höhenverhältnis (neue Länge/Originalhöhe)
            float yScale = y/objImage.getHeight();
           
            // Setze den Verkleinerungsfaktor auf das Kleinere der beiden
            // Verhältnisse (Breite oder Höhe)
            if (xScale>yScale) {xScale=yScale;} else {yScale=xScale;}

            if(!outputFile.createNewFile()){
              throw new IOException("Could not create new File, "+
                                          "check permissions!");
            }
            ParameterBlock pb = new ParameterBlock();
            pb.addSource(objImage);
            pb.add(xScale);
            pb.add(yScale);
            pb.add(0.0F);
            pb.add(0.0F);
            pb.add(new InterpolationNearest()); // The interpolation
            objImage = JAI.create("scale", pb, null);
               
            // Hier passierts ...
            debugOut("Datei neu berechen: ..."
                    +"+outputFile.getAbsolutePath());
            JAI.create("filestore", objImage,
                      outputFile.getAbsolutePath(), "JPEG", null);
               
            debugOut("Datei angelegt!");
            is.close();

        // Datei evtl. noch komprimieren ....
         
        }
            catch(IOException e){
            debugOut(e.getMessage());
            ret = -1;
        }
       
        return ret;
       
  }
```


----------



## The_S (14. Dez 2006)

Du könntest ein BufferedImage mit dem typ GRAYSCALE erstellen und dann auf dessen Graphics2D objekt (bufimage.createGraphics()) mittels Graphics2D#drawImage ein Image zeichnen. Müsstest nur dein JAI-Image irgendwie in ein normales casten/konvertieren/was weiß ich was.

Evtl. gibts so ne ähnliche Lösung auch direkt unter JAI, kenn mich mit JAI nicht aus.


----------



## Gast (14. Dez 2006)

Vielen Dank für die schnelle Antwort. 
Ich werde den Hinweis auf Typ "GRAYSCALE" mal verfolgen. Diese Konstante hatte ich bis jetzt noch nicht gesehen. Vielleicht gibt es diese ja auch bei den create-Methoden im JAI. Auf die Verwendung des JAI bin ich wohl angewiesen, weil die Bildverarbeitung ja "im Dunkeln" läuft, also ohne GUI.
Gruß
Thomas


----------



## The_S (14. Dez 2006)

Warum bist du da auf JAI angewiesen? ImageIO.read benötigt auch keine grafische Benutzeroberfläche gensowenig wie BufferedImage oder Graphics2D ...  ???:L


----------



## Thomas Peter (16. Dez 2006)

Hallo,

jetzt habe ich noch mal bei Sun im Developer FAQ getoebert und dort eine Methode gefunden, die ohne JAI eine JPG - Skalierung ermoeglicht. Ich musste nur noch das  BufferedImage, das das konvertierte Image aufnimmt, mit                "BufferedImage.TYPE_BYTE_GRAY" instanziieren und schon wird aus dem Farbbild ein Graustufenbild. 
Dank an Hobbit_..., Du hast mich in die richtige Richtung geschubst.

Was jetzt noch fehlt, ist eine Beigefaerbung, um einen Sepiaeeffekt herzustellen....

Hier der Code:

```
public void createGreyJPG(String infile, String outfile )throws Exception 
    {
        // Quelldatei laden          
        BufferedImage image = ImageIO.read(new File(infile));
        int srcWidth = image.getWidth(null);
        int srcHeight = image.getHeight(null);

        // Originalbild auf Zielimage zeichnen
        // Zur Grauumwandlung wird ein leeres Graustufen Bild 
        // zugrundegelegt 
        BufferedImage trgImage = new BufferedImage(srcWidth,
                srcHeight,BufferedImage.TYPE_BYTE_GRAY);
        Graphics2D graphics2D = trgImage.createGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.drawImage(image, 0, 0, srcWidth, srcHeight, null);

        // schreiben auf 'outfile'
        BufferedOutputStream out = new BufferedOutputStream(new
          FileOutputStream(outfile));
        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
        JPEGEncodeParam param = encoder.
          getDefaultJPEGEncodeParam(trgImage);
        param.setQuality(1.0f, false);
        encoder.setJPEGEncodeParam(param);
        encoder.encode(trgImage);
        out.close(); 

    }
```


----------



## Thomas Peter (17. Dez 2006)

kleiner Nachtrag:

Auf meinem Server ohne Graphiksystem (Linux) funktioniert die Sache wg. des AWT nicht: "X11 Server nicht vorhanden ...".
Ab  SDK 1.4 kann man in catalina.sh "CATALINA_OPTS="-Djava.awt.headless=true" setzen, und schon läuft's - im Gegensatz zur JAI-Lösung, mit der die Verkleinerung erledigt wird, quälend langsam.


----------



## The_S (18. Dez 2006)

Wie skallierst du denn?


----------



## Thomas Peter (18. Dez 2006)

Hallo,

im hochgeladenen Code hab ich mich auf das Graufärben beschränkt.
Man braucht nur die neu gewünschte Größe anzugeben, hier "trgWidth" und "trgHeight".
Man könnte auch den Kompressionsfaktor einbauen. 

Bei Bedarf kann ich die ganze Klasse, die ich dazu entwickelt habe, posten. Bin allerdings gleich erst Mal unterwegs, so dass es Morgen werden könnte.

So siehts bei mir im Einsatz aus (auszugsweise):

```
BufferedImage trgImage = new BufferedImage(trgWidth,trgHeight,
           BufferedImage.TYPE_BYTE_GRAY);
       
        Graphics2D graphics2D = trgImage.createGraphics();
        graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
          RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2D.drawImage(image, 0, 0, trgWidth, trgHeight, null);
```


----------



## The_S (18. Dez 2006)

Schau mal ob es mit Image#getScaledInstance und Image.SCALE_FAST schneller geht.


----------

