# Skalierung von Bildern mit Transparenz



## Liathne (31. Okt 2007)

Guten Morgen zusammen,

ich habe eine kleine GUI gebastelt, mit der es möglich ist, Bilder auf eine vorgegebene Größe zu skalieren.
Nun habe ich folgendes Problem:
Es kann durchaus vorkommen, das ein Bild Transparenz enthält. Hierbei entsteht beim skalieren am Übergang zwischen Nicht-Transparenz und Transparenz ein unschöner Balken. Ich gehe davon aus, er entsteht, da bei der Berechnung der Pixelfarben die Transparenz mit einbezogen wird. Lässt sich dieser Balken auf irgendeine Weise verhindern?

Meine Skalierungsmethode lautet wie folgt:


```
public static BufferedImage getScaledInstance(BufferedImage img,
            int targetWidth,
            int targetHeight,
            boolean higherQuality) throws Exception {
        int type = (img.getTransparency() == Transparency.OPAQUE) ?
            BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
        BufferedImage ret = (BufferedImage)img;
        int w, h;
        if (higherQuality) {
            // Use multi-step technique: start with original size, then
            // scale down in multiple passes with drawImage()
            // until the target size is reached
            w = img.getWidth();
            h = img.getHeight();
        } else {
            // Use one-step technique: scale directly from original
            // size to target size with a single drawImage() call
            w = targetWidth;
            h = targetHeight;
        }
        
        do {
            if (higherQuality && w > targetWidth) {
                w /= 2;
                if (w < targetWidth) {
                    w = targetWidth;
                }
            }
            
            if (higherQuality && h > targetHeight) {
                h /= 2;
                if (h < targetHeight) {
                    h = targetHeight;
                }
            }
            
            BufferedImage tmp = new BufferedImage(w, h, type);
            Graphics2D g2 = tmp.createGraphics();
            g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2.drawImage(ret, 0, 0, w, h, null);
            g2.dispose();
            
            ret = tmp;
        } while (w != targetWidth || h != targetHeight);
        
        return ret;
    }
```

Vielen Dank für Eure Mühe

  Liathne


----------



## The_S (31. Okt 2007)

Selbiger Fehler, wenn du über BufferedImage#getScaledInstance skalierst?


----------



## Liathne (31. Okt 2007)

Eben ausprobiert. Der schwarze Balken ist ebenfalls bei BufferedImage#getScaledInstance vorhanden.


----------



## Liathne (31. Okt 2007)

Ich lag wie ich inzwischen festgestellt habe mit meiner Anfangsvermutung, dass es am Skalierungsalgo liegt falsch.
Das Problem liegt woanders. Nach der Skalierung setzte ich anstelle des Alpha-Kanals eine vorher definierte Farbe und wandle das BufferedImage in TYPE_INT_RGB um. Hierdurch entsteht der schwarze Balken, da meine Methode nicht alle Pixel füllt. 
Was das Problem auf folgende Methode verlagert:


```
public static BufferedImage getTransparenz(BufferedImage img) throws Exception{
        int w = img.getWidth(), h = img.getHeight();
        for (int x=0;x<w;++x){
            for (int y=0;y<h;++y){
                int argb  = img.getRGB( x, y );
                int alpha = (argb >> 24) & 0xff;
                if (alpha == 0){
                    int purple = new Color(255, 0, 128).getRGB();
                    img.setRGB( x, y, purple );
                }
            }
        }
        return createBufferedRGBImage(img);
    }
```

Wo liegt mein Fehler, weshalb werden nicht alle transparente Pixel gefüllt?

  Liathne


----------



## The_S (31. Okt 2007)

mal ganz davon abgesehen, dass die Methode nicht gerade performant ist, ignorierst du in deinen Schleifen die erste Pixel-Zeile und Spalte. Du musst in deinen Schleifen "x++" und "y++" und nicht "++x" und "++y" schreiben. Außerdem kann der Alpha-Kanal einen beliebigen Wert zwischen 0 und 255 annehmen (Teiltransparenz), du überprüfst aber lediglich auf absolute Transparenz.


----------



## Liathne (31. Okt 2007)

Performance Verbesserungsvorschläge?
Wie prüfe ich auch auf Teiltransparenz?


----------



## The_S (31. Okt 2007)

Performance:

nicht alle Variablen in der Schleife bei jedem Durchlauf neu erzeugen. z. B.: 


```
int purple = new Color(255, 0, 128).getRGB();
```

leg dir die Variable purple außerhalb der Schleifen an.

Teiltransparenz:

Anstelle auf alpha == 0 überprüfen ob Alpha zwischen 0 und 254 liegt.


----------



## Liathne (31. Okt 2007)

Super, jetzt klappt alles.

Dank dir.


----------

