Frage

Ich habe zwei BufferedImages ich geladen von pngs.Der erste Teil enthält ein Bild, die zweite eine alpha-Maske für das Bild.

Ich will erstellen Sie ein kombiniertes Bild von den beiden, durch die Anwendung der alpha-Maske.Mein google-fu versagt mir.

Ich weiß, wie laden/speichern Sie die Bilder, ich muss nur das bit, wo gehe ich von zwei BufferedImages, um ein BufferedImage mit der rechten alpha-Kanal.

War es hilfreich?

Lösung

Ihre Lösung durch Abrufen der RGB-Daten mehr als ein Pixel in einer Zeit, verbessert werden könnte (siehe http://java.sun.com/javase/6/docs/api/java/awt/image/BufferedImage.html ) und von nicht mehr als drei Farben zu schaffen Objekte bei jeder Iteration der inneren Schleife.

final int width = image.getWidth();
int[] imgData = new int[width];
int[] maskData = new int[width];

for (int y = 0; y < image.getHeight(); y++) {
    // fetch a line of data from each image
    image.getRGB(0, y, width, 1, imgData, 0, 1);
    mask.getRGB(0, y, width, 1, maskData, 0, 1);
    // apply the mask
    for (int x = 0; x < width; x++) {
        int color = imgData[x] & 0x00FFFFFF; // mask away any alpha present
        int maskColor = (maskData[x] & 0x00FF0000) << 8; // shift red into alpha bits
        color |= maskColor;
        imgData[x] = color;
    }
    // replace the data
    image.setRGB(0, y, width, 1, imgData, 0, 1);
}

Andere Tipps

Ich bin zu spät mit dieser Antwort, aber vielleicht ist es von Nutzen für jemanden sowieso. Dies ist eine einfachere und effizientere Version von Michael Myers' Methode:

public void applyGrayscaleMaskToAlpha(BufferedImage image, BufferedImage mask)
{
    int width = image.getWidth();
    int height = image.getHeight();

    int[] imagePixels = image.getRGB(0, 0, width, height, null, 0, width);
    int[] maskPixels = mask.getRGB(0, 0, width, height, null, 0, width);

    for (int i = 0; i < imagePixels.length; i++)
    {
        int color = imagePixels[i] & 0x00ffffff; // Mask preexisting alpha
        int alpha = maskPixels[i] << 24; // Shift blue to alpha
        imagePixels[i] = color | alpha;
    }

    image.setRGB(0, 0, width, height, imagePixels, 0, width);
}

Es liest alle Pixel in einem Array zu Beginn, also nur eine for-Schleife erfordert. Außerdem ist es direkt verschiebt das blaue Byte an dem alpha (der Maskenfarbe), anstatt zuerst die rote Byte maskiert und dann verschiebt es.

Wie die anderen Methoden, nimmt beide Bilder die gleichen Abmessungen haben.

ich zuletzt ein wenig mit diesem Zeug, ein Bild über ein anderes anzuzeigen, und ein Bild zu verblassen grau.
Auch ein Bild mit einer Maske mit Transparenz (meine frühere Version dieser Meldung!) Maskiert werden.

habe ich mein kleines Testprogramm und zwickte es ein bisschen das gewünschte Ergebnis zu erhalten.

Hier sind die relevanten Bits:

TestMask() throws IOException
{
    m_images = new BufferedImage[3];
    m_images[0] = ImageIO.read(new File("E:/Documents/images/map.png"));
    m_images[1] = ImageIO.read(new File("E:/Documents/images/mapMask3.png"));
    Image transpImg = TransformGrayToTransparency(m_images[1]);
    m_images[2] = ApplyTransparency(m_images[0], transpImg);
}

private Image TransformGrayToTransparency(BufferedImage image)
{
    ImageFilter filter = new RGBImageFilter()
    {
        public final int filterRGB(int x, int y, int rgb)
        {
            return (rgb << 8) & 0xFF000000;
        }
    };

    ImageProducer ip = new FilteredImageSource(image.getSource(), filter);
    return Toolkit.getDefaultToolkit().createImage(ip);
}

private BufferedImage ApplyTransparency(BufferedImage image, Image mask)
{
    BufferedImage dest = new BufferedImage(
            image.getWidth(), image.getHeight(),
            BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = dest.createGraphics();
    g2.drawImage(image, 0, 0, null);
    AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.DST_IN, 1.0F);
    g2.setComposite(ac);
    g2.drawImage(mask, 0, 0, null);
    g2.dispose();
    return dest;
}

Der Rest nur die Bilder in einem kleinen Swing-Panel angezeigt werden soll.
Beachten Sie, dass das Maskenbild ist Graustufen, schwarz wird volle Transparenz, weiß immer voll deckend.

Auch wenn Sie Ihr Problem gelöst haben, dachte ich, könnte ich mein nehmen auf sie teilen. Es verwendet eine etwas Java-ish Methode, Standard-Klassen zu verarbeiten / Filter Bilder.
Eigentlich nutzt meine Methode ein bisschen mehr Speicher (ein zusätzliches Bild machen), und ich bin nicht sicher, es ist schneller (jeweilige Leistungen Messen interessant sein könnte), aber es ist etwas abstrakt.
Zumindest haben Sie die Wahl! : -)

Für diejenigen, die mit alpha in der ursprünglichen Bild.

Ich schrieb diesen code in Koltin, der entscheidende Punkt hier ist, dass, wenn Sie die alpha auf Ihrer ursprünglichen Bild Sie benötigen multiplizieren Sie diese Kanäle.

Koltin Version:

    val width = this.width
    val imgData = IntArray(width)
    val maskData = IntArray(width)

    for(y in 0..(this.height - 1)) {

      this.getRGB(0, y, width, 1, imgData, 0, 1)
      mask.getRGB(0, y, width, 1, maskData, 0, 1)

      for (x in 0..(this.width - 1)) {

        val maskAlpha = (maskData[x] and 0x000000FF)/ 255f
        val imageAlpha = ((imgData[x] shr 24) and 0x000000FF) / 255f
        val rgb = imgData[x] and 0x00FFFFFF
        val alpha = ((maskAlpha * imageAlpha) * 255).toInt() shl 24
        imgData[x] = rgb or alpha
      }
      this.setRGB(0, y, width, 1, imgData, 0, 1)
    }

Java version (übersetzt von Kotlin)

    int width = image.getWidth();
    int[] imgData = new int[width];
    int[] maskData = new int[width];

    for (int y = 0; y < image.getHeight(); y ++) {

        image.getRGB(0, y, width, 1, imgData, 0, 1);
        mask.getRGB(0, y, width, 1, maskData, 0, 1);

        for (int x = 0; x < image.getWidth(); x ++) {

            //Normalize (0 - 1)
            float maskAlpha = (maskData[x] & 0x000000FF)/ 255f;
            float imageAlpha = ((imgData[x] >> 24) & 0x000000FF) / 255f;

            //Image without alpha channel
            int rgb = imgData[x] & 0x00FFFFFF;

            //Multiplied alpha
            int alpha = ((int) ((maskAlpha * imageAlpha) * 255)) << 24;

            //Add alpha to image
            imgData[x] = rgb | alpha;
        }
        image.setRGB(0, y, width, 1, imgData, 0, 1);
    }

Eigentlich habe ich es herausgefunden. Dies ist wahrscheinlich nicht ein schnell Art und Weise, es zu tun, aber es funktioniert:

for (int y = 0; y < image.getHeight(); y++) {
    for (int x = 0; x < image.getWidth(); x++) {
        Color c = new Color(image.getRGB(x, y));
        Color maskC = new Color(mask.getRGB(x, y));
        Color maskedColor = new Color(c.getRed(), c.getGreen(), c.getBlue(),
            maskC.getRed());
        resultImg.setRGB(x, y, maskedColor.getRGB());
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top