简体   繁体   English

是否可以在 BufferedImage 中的其他像素之上不透明地绘制一条半透明颜色的线?

[英]Is it possible to draw a line with a semi-transparent color opaquely on top of other pixels in a BufferedImage?

I try to prepare a BufferedImage with semi-transparency so that whereever this image is painted on top of the background will partially shine through.我尝试准备一个半透明的 BufferedImage,这样无论这个图像被绘制在背景之上的任何位置,都会部分地透出来。 For this purpose I use among other things Graphics.drawLine() with a stroke > 1 and colors that have an alpha component < 255, ie are semi-transparent.为此,我使用 Graphics.drawLine() 的笔画 > 1 和 colors 的 alpha 分量 < 255,即半透明。 Lines I draw will often overlap or intersect to make sure there will be no gaps.我画的线经常会重叠或相交,以确保没有间隙。 When such intersections occur, the colors of the lines will stack, ie the color that was there before and the semi-transparent color I am painting with will result in a new color.当出现这样的交叉点时,线条的 colors 将堆叠,即之前的颜色和我正在绘制的半透明颜色将产生新的颜色。 Which is logical.这是合乎逻辑的。

That is not what I want, however.然而,这不是我想要的。 If possible, I would like to paint with my semi-transparent color as if it was completely opaque and the alpha component of the color just a fourth color component.如果可能的话,我想用我的半透明颜色进行绘制,就好像它完全不透明一样,并且颜色的 alpha 分量只是第四个颜色分量。 I would like to copy the color I am painting with - including the alpha component - exactly to the image, replacing everything that was there before.我想将我正在绘制的颜色(包括 alpha 组件)复制到图像中,替换之前的所有内容。

Is there a way to do this?有没有办法做到这一点?

The following code produces a simple semi-transparent red X, that will let the background partially shine through wherever it is painted on top of.下面的代码生成了一个简单的半透明红色 X,它可以让背景部分地透过它被绘制在上面的任何地方。 It will have, however, a darker part where both lines intersect.然而,它将在两条线相交的地方有一个较暗的部分。 I would like to be able to paint the X without this darker part.我希望能够在没有这个较暗部分的情况下绘制 X。 Is that possible (while still using Graphics.drawLine())?这可能吗(同时仍在使用 Graphics.drawLine())?

import java.awt.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

public class Test {
    
    public static void main(String[] args) {
        // create a new BufferedImage with alpha channel
        BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = img.createGraphics();
        // set a semi-transparent color and a stroke wider than one pixel
        g.setColor(new Color(255, 0, 0, 128 /* alpha; semi-transparent */));
        g.setStroke(new BasicStroke(2));
        // draw a cross; where the lines cross the color will (logically) be darker
        g.drawLine(0, 0, 100, 100);
        g.drawLine(0, 100, 100, 0);
        // use the image somehow, in this case write it to file
        writeImage(img, "test.png");
    }
    
    private static void writeImage(BufferedImage img, String fileName) {
        try {
            ImageIO.write(img, "png", new File(fileName));
        }
        catch (IOException e) {
            System.out.println(e);
        }
    }
}

I could, of course, solve this manually by implementing my own line drawing method and manipulate the pixels directly.当然,我可以通过实现我自己的线条绘制方法并直接操作像素来手动解决这个问题。 (Not sure if that would create new problems with clipping which I also need.) However, that would increase the effort substantially which I would like to avoid. (不确定这是否会产生我需要的剪辑的新问题。)但是,这会大大增加我想避免的工作量。

A further constraint: I am restricted to Java 7.进一步的限制:我仅限于 Java 7。

  • Create a second image.创建第二个图像。
  • Draw on that second image with opaque colors.使用不透明的 colors 在第二张图像上绘制。
  • Copy that second image onto your original image using translucent alpha.使用半透明 Alpha 将第二张图像复制到原始图像上。

import java.io.*;
import javax.imageio.*;

public class TranslucentX {
    
    public static void main(String[] args) {
        BufferedImage x = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = x.createGraphics();
        g.setColor(new Color(255, 0, 0));
        g.setStroke(new BasicStroke(2));
        // draw a cross; where the lines cross the color will (logically) be darker
        g.drawLine(0, 0, 100, 100);
        g.drawLine(0, 100, 100, 0);
        g.dispose();

        // create a new BufferedImage with alpha channel
        BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
        g = img.createGraphics();
        // Draw opaque image using translucency.
        g.setComposite(
            AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));
        g.drawImage(x, 0, 0, null);
        g.dispose();

        // use the image somehow, in this case write it to file
        writeImage(img, "test.png");
    }
    
    private static void writeImage(BufferedImage img, String fileName) {
        try {
            ImageIO.write(img, "png", new File(fileName));
        }
        catch (IOException e) {
            System.out.println(e);
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM