Hintergrund-Transparent PNG imageMerge

ph1015

Mitglied
Hallo,

ich versuche gerade zwei Bilder (*.png) übereinander zu legen, so dass letztendlich draus ein Bild generiert wird. Soweit klappt es mit dem nachfolgenden Code eigentlich ganz gut:
Java:
 public boolean generate(Component comp) {
            MediaTracker mt;
            mt = new MediaTracker(comp);
            mt.addImage(i1, 1);
            mt.addImage(i2, 2);
            try { mt.waitForAll(); } catch (Exception ie) { }

            int wid1, wid2;
            int hgt1, hgt2;
            
            wid1 = i1.getWidth(comp);
            wid2 = i2.getWidth(comp);
            hgt1 = i1.getHeight(comp);
            hgt2 = i2.getHeight(comp);

            rwid = Math.max(wid1, wid2);
            rhgt = Math.max(hgt1, hgt2);

            results = new int[rwid * rhgt];

            int [] p1 = new int[rwid * rhgt];
            int [] p2 = new int[rwid * rhgt];

            PixelGrabber pg1 = new PixelGrabber(i1, 0, 0, wid1, hgt1, p1, 0, rwid);
            try { pg1.grabPixels(); } catch (Exception ie1) { }

            PixelGrabber pg2 = new PixelGrabber(i2, 0, 0, wid2, hgt2, p2, 0, rwid);
            try { pg2.grabPixels(); } catch (Exception ie2) { }

            cm = ColorModel.getRGBdefault();

            int y, x, rp, rpi;
            int red1, red2, redr;
            int green1, green2, greenr;
            int blue1, blue2, bluer;
            int alpha1, alpha2, alphar;
            double wgt1, wgt2;
            
            for(y = 0; y < rhgt; y++) {
                for(x = 0; x < rwid; x++) {
                	
                    rpi = y * rwid + x;
                    rp = 0;
                    blue1 = p1[rpi] & 0x00ff;
                    blue2 = p2[rpi] & 0x00ff;
                    green1 = (p1[rpi] >> 8) & 0x00ff;
                    green2 = (p2[rpi] >> 8) & 0x00ff;
                    red1 = (p1[rpi] >> 16) & 0x00ff;
                    red2 = (p2[rpi] >> 16) & 0x00ff;
                    alpha1 = (p1[rpi] >> 24) & 0x00ff;
                    alpha2 = (p2[rpi] >> 24) & 0x00ff;

                    wgt1 = w1 * (alpha1 / 255.0);
                    wgt2 = w2 * (alpha2 / 255.0);
                    
                    redr = (int)(red1 * wgt1 + red2 * wgt2);
                    redr = (redr < 0)?(0):((redr>255)?(255):(redr));
                    greenr = (int)(green1 * wgt1 + green2 * wgt2);
                    greenr = (greenr < 0)?(0):((greenr>255)?(255):(greenr));
                    bluer = (int)(blue1 * wgt1 + blue2 * wgt2);
                    bluer =  (bluer < 0)?(0):((bluer>255)?(255):(bluer));
                    alphar = 255;

                    rp = (((((alphar << 8) + (redr & 0x0ff)) << 8) + (greenr & 0x0ff)) << 8) + (bluer & 0x0ff);
                    
                    // save the pixel
                    results[rpi] = rp;
                }
            }
            return true;
        }
        public Image getGeneratedImage() {
            Image ret;
            MemoryImageSource mis;
            if (results == null) {
                Frame dummy = new Frame();
                generate(dummy);
                dummy.dispose();
            }
            mis = new MemoryImageSource(rwid, rhgt, cm, results, 0, rwid);
            ret = Toolkit.getDefaultToolkit().createImage(mis);
            return ret;
        }

Die PNG-Bilder haben allerdings einen transparenten Hintergrund (im IrfanView -> schwarz). Nun wird beim übereinanderlegen die Schwarze Farbe auch verwendet.

Wie kriege es hin, dass die Hintergrundfarbe 100%-ig transparent ist?

Gruß
Andy
 
Sieht das Ergebnisbild denn bis auf die Transparenz richtig aus?

Zeile 64 sieht für mich etwas seltsam aus. Auch hier vermute ich mal, dass anstatt der + Operatoren, | Operatoren angebrachter wären?
 
Ja, das Ergebnisbild sieht ansonsten richtig aus.

Ich hatte es eben so getestet und das Ergebis ist gleich:
Java:
rp = (((((alphar << 8) | (redr & 0x0ff)) << 8) | (greenr & 0x0ff)) << 8) | (bluer & 0x0ff);

Gruß
Andy
 
Ich hätte erst einmal versucht ein BufferedImage passender Größe und vom Typ TYPE_INT_ARGB zu erstellen. Dann per createGraphics() das Graphics Objekt des Images holen und die zwei Bilder mittels drawImage(...) draufmalen und abspeichern.
 
@Michael...: Es hört sich gut an. Das werde ich mal bei Gelegenheit nachverfolgen.

@AlexSpritze: Wie kann ich es den an der Stelle anders machen?
 
@AlexSpritze: Wie kann ich es den an der Stelle anders machen?

Du könntest den Alpha-Wert alphar genauso wie z.B. den bluer-Wert gewichtet aus den beiden Ausgangsbildern bestimmen. Oder eben wenn beide Alpha-Werte gleich null sind dann auch auch alphar auf null setzen, damit im Endbild die komplette Transparenz zu sehen ist. Also laut dem Link von mir, ist 255 keine Transparenz und 0 wäre volle Transparenz.
 
Ja, das sieht schon besser aus. ich habe alphar wie folgt gesetzt:

Java:
alphar = (int)(alpha1 * wgt1 + alpha2 * wgt2);
alphar =  (alphar < 0)?(0):((alphar>255)?(255):(alphar));

Leider stimmt die Farbe im Ergebnisbild nicht genau. Im Anhang habe ich ein Screeenshot gemacht.

Hast du vl. noch eine Idee wie ich es hinkriege, dass auch die Farbe im Ergebnisbild einigermaßen stimmt?
 

Anhänge

  • 1.jpg
    1.jpg
    1,2 KB · Aufrufe: 22
  • 2.jpg
    2.jpg
    1,2 KB · Aufrufe: 26
  • 1und2.jpg
    1und2.jpg
    1,4 KB · Aufrufe: 25
Irgendwie gewichtest du ja die Pixel aus beiden Bildern abhängig vom Alpha. Vielleicht wäre es einfacher, du würdest sagen Bild1 ist oberhalb von Bild2 und wenn du an einem nichttransparenten Pixel von Bild1 bist, übernimmst du diesen Pixel, ansonsten nimmst du den Pixel von Bild2, und als letzte Möglichkeit ist der Pixel eben transparent im Ergebnisbild.

Oder möchtest du explizit beide Bilder vermischen, wenn sie an gleichen Orten sichtbare Informationen haben?

PS: Wo kommen die Werte w1 und w2 in Zeile 53 und 54 her?
 
Ich möchte eigentlich das Bild2 über das Bild1 legen, sodass das Bild1 von dem Bild2 überdeckt wird.

w1 und w2 sind fest definiert und zwar wie folgt:
Java:
double w1 = 0.5;
double w2 = 0.5;
 
ach ja stimmt, daran habe ich gar nicht gedacht. Danke! Nun sieht es gut aus bzw. es sieht so aus wie ich es haben möchte!

Ich habe die Werte w1 und w2 auf 1 gesetzt.

:toll:
Gruß
Andy
 

Neue Themen


Zurück
Oben