Java 我试图实现透明度,但出了问题

Java 我试图实现透明度,但出了问题,java,alpha-transparency,Java,Alpha Transparency,我想在我的游戏引擎中增加“透明度”,而我之前并不知道这一点。关于如何实现它,我没有找到任何直接的答案,所以我最后做了一些研究,研究了一种叫做Alpha-Blending的方法,如果我理解正确的话,这是一种显示不透明度的方法 我在谷歌上搜索了一下,试图找到一个源代码,展示了当你有一个像素阵列时如何实现这一点。我不知道怎么回事,但除了Youtube上的一篇教程,我什么也没找到。他们没有解释为什么他们会这样做,因此我仍然不知道如何实施它或它是如何工作的。我试着按照教程进行操作,但他们使用的代码根本不起

我想在我的游戏引擎中增加“透明度”,而我之前并不知道这一点。关于如何实现它,我没有找到任何直接的答案,所以我最后做了一些研究,研究了一种叫做Alpha-Blending的方法,如果我理解正确的话,这是一种显示不透明度的方法

我在谷歌上搜索了一下,试图找到一个源代码,展示了当你有一个像素阵列时如何实现这一点。我不知道怎么回事,但除了Youtube上的一篇教程,我什么也没找到。他们没有解释为什么他们会这样做,因此我仍然不知道如何实施它或它是如何工作的。我试着按照教程进行操作,但他们使用的代码根本不起作用,所以我对它做了一些修改(显然不起作用)

下面的代码是我的setPixel()函数,用于在指定位置设置像素。从函数开始,它只检查是否需要放置一个像素。此函数用于从像素数据中绘制每个单独的像素。屏幕的像素数据存储在变量pixels中。图像数据存储在值中。值只是一个整数,而像素是一个数组

    public void setPixel(int x, int y, int value, Color invis) {
    
    int alpha = (value>>24);
    
    if(invis != null && value == invis.getRGB() || alpha == 0x00) {
        
        return;
    }
    
    if(!isOutSideScreen(x,y)) {
        
        
        
        if(alpha == 255) {
            pixels[x + y * pWidth] = value;
        }
        else {
            int pixelColor =  value;
             
            
            int newRed = ((pixelColor >> 16) & 0xff) + (int)((((pixelColor >> 16) & 0xff) - ((pixels[x + y * pWidth] >> 16) & 0xff)) * (alpha/255f));
            int newGreen = ((pixelColor >> 8) & 0xff) + (int)((((pixelColor >> 8) & 0xff) - ((pixels[x + y * pWidth] >> 8) & 0xff)) * (alpha/255f));
            int newBlue = (pixelColor & 0xff) + (int)(((pixelColor & 0xff) - (pixels[x + y * pWidth] & 0xff)) * (alpha/255f));
            
            
            
            pixels[x+y * pWidth] = ((255 << 24) | (newRed << 16) | (newGreen << 8) | newBlue);
        }
        
    }
    
}
public void setPixel(int x,int y,int value,Color invi){
int alpha=(值>>24);
if(invi!=null&&value==invi.getRGB()| | alpha==0x00){
返回;
}
如果(!isOutSideScreen(x,y)){
如果(α=255){
像素[x+y*pWidth]=值;
}
否则{
int pixelColor=值;
int newRed=((像素颜色>>16)和0xff)+(int)(((像素颜色>>16)和0xff)-(像素[x+y*pWidth]>>16)和0xff))*(alpha/255f);
intnewgreen=((像素颜色>>8)和0xff)+(int)(((像素颜色>>8)和0xff)-(像素[x+y*pWidth]>>8)和0xff))*(alpha/255f);
intnewblue=(pixelColor&0xff)+(int)((pixelColor&0xff)-(像素[x+y*pWidth]&0xff))*(alpha/255f));
像素[x+y*pWidth]=((255>16)和0xff)-(像素[x+y*pWidth]>>16)和0xff))*(alpha/255f);
intnewgreen=((像素颜色>>8)和0xff)+(int)(((像素颜色>>8)和0xff)-(像素[x+y*pWidth]>>8)和0xff))*(alpha/255f);
intnewblue=(pixelColor&0xff)+(int)((pixelColor&0xff)-(像素[x+y*pWidth]&0xff))*(alpha/255f));
像素[x+y*pWidth]=(255>16)和0xff)+(alpha/255f)*(值>>16)和0xff);
int newGreen=(int)((1-(alpha/255f))*((pixelColor>>8)和0xff)+(alpha/255f)*((value>>8)和0xff));
int-newBlue=(int)((1-(alpha/255f))*(pixelColor&0xff)+(alpha/255f)*(value&0xff));
像素[x+y*pWidth]=((255在“backgroundColor”之上的“newColor”的公式是:

要了解其工作原理,请尝试不同的alpha值。alpha=0时,您将获得背景色。alpha=1时,您将获得新颜色

你编程的公式是

outColor = backgroundColor + alpha * (backgroundColor - newColor)
Alpha=1为您提供了不正确的
outColor=2*backgroundColor newColor
。要修复它,您需要交换
pixelColor
像素[x+y*pWidth]
周围-例如,对于蓝色通道:

int newBlue = (pixelColor & 0xff) + (int)(((pixels[x + y * pWidth] & 0xff) - (pixelColor & 0xff)) * (alpha/255f));
关于这段代码,我不理解的是所有的位代码,以及为什么要这样计算颜色

                int newRed = ((pixelColor >> 16) & 0xff) + (int)((((pixelColor >> 16) & 0xff) - ((pixels[x + y * pWidth] >> 16) & 0xff)) * (alpha/255f));
            int newGreen = ((pixelColor >> 8) & 0xff) + (int)((((pixelColor >> 8) & 0xff) - ((pixels[x + y * pWidth] >> 8) & 0xff)) * (alpha/255f));
            int newBlue = (pixelColor & 0xff) + (int)(((pixelColor & 0xff) - (pixels[x + y * pWidth] & 0xff)) * (alpha/255f));
            
            
            
            pixels[x+y * pWidth] = ((255 << 24) | (newRed << 16) | (newGreen << 8) | newBlue);
此代码假定颜色模型将四个8位整数打包为一个
int
。最有效的8位组成alpha分量,红色分量、绿色分量和蓝色分量各8位。从
int
中提取分量的方法是使用位运算符。例如,
color&0xff
是最低的8位,因此它是蓝色分量。
(color>>8)&0xff
给出第二低的8位,即绿色分量

屏幕的像素数据存储在可变像素中

不知道这是否有帮助,但您可以使用以下方法从像素阵列创建BuffereImage:

import java.awt.*;
import java.awt.image.*;
import javax.swing.*;

public class ImageFromArray3 extends JFrame
{
    int width = 50;
    int height = 50;
    int imageSize = width * height;

    public ImageFromArray3()
    {
        JPanel panel = new JPanel();
        getContentPane().add( panel );
        int[] pixels = new int[imageSize];

        //  Create Red Image

        for (int i = 0; i < imageSize; i++)
        {
            //pixels[i] = 255 << 16; // no alpha
            pixels[i] = (64 << 24 ) + (255 << 16);
        }

        panel.add( createImageLabel(pixels) );

        //  Create Green Image

        for (int i = 0; i < imageSize; i++)
        {
            //pixels[i] = 255 << 8;
            pixels[i] = (128 << 24 ) + (255 << 8);
        }

        panel.add( createImageLabel(pixels) );

        //  Create Blue Image

        for (int i = 0; i < imageSize; i++)
        {
            //pixels[i] = 255;
            pixels[i] = (192 << 24 ) + (255);
        }

        panel.add( createImageLabel(pixels) );

        //  Create Cyan Image

        for (int i = 0; i < imageSize; i++)
        {
            //pixels[i] = (255 << 8) + 255;
            pixels[i] = (255 << 24 ) + (255 << 8) + (255);
        }

        panel.add( createImageLabel(pixels) );

    }

    private JLabel createImageLabel(int[] pixels)
    {
        //BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RRGB);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        WritableRaster raster = image.getRaster();
        raster.setDataElements(0, 0, width, height, pixels);
        JLabel label = new JLabel( new ImageIcon(image) );
        return label;
    }

    public static void main(String args[])
    {
        JFrame frame = new ImageFromArray3();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
    }
}
import java.awt.*;
导入java.awt.image.*;
导入javax.swing.*;
公共类ImageFromArray3扩展了JFrame
{
整数宽度=50;
整数高度=50;
int imageSize=宽度*高度;
公共图像FromArray3()
{
JPanel面板=新的JPanel();
getContentPane().add(面板);
int[]像素=新的int[imageSize];
//创建红色图像
对于(int i=0;i//像素[i]=255可能会有帮助。它显示了如何混合两幅图像,并且您可以在每幅图像上使用透明度。@使用Graphics2D的camickr。我使用像素数据,所以我不能使用AlphaComposite类:/。至少据我所知不是这样!不太确定这意味着什么。像素数据数组只是一个数组。您不能在屏幕上显示像素数组。哟你需要对图像进行某种转换。你应该能够从像素数据创建一个BuffereImage。它有一个setPixel()方法。屏幕的像素数据存储在可变像素中。-我还是不太明白你为什么这么做。人们通常创建屏幕的BuffereImage并操作BuffereImage。在你的上一个问题中,你被要求发布一个。你没有,你也没有在这里,所以我不想猜测。@camickr我很想发布一个MRE,但是这是一个游戏引擎,它会产生大量的代码。我将尝试进一步解释。我有一个使用BufferedStrategy的画布框架。我使用BufferedStrategy中的图形将BufferedImage绘制到屏幕上。这个BufferedImage的类型为BufferedImage.type_INT_ARGB(我也有这个图像的像素阵列)。我后来添加了我自己的“drawImage”函数,在这里我获取像素数据
int newBlue = (pixelColor & 0xff) + (int)(((pixels[x + y * pWidth] & 0xff) - (pixelColor & 0xff)) * (alpha/255f));
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;

public class ImageFromArray3 extends JFrame
{
    int width = 50;
    int height = 50;
    int imageSize = width * height;

    public ImageFromArray3()
    {
        JPanel panel = new JPanel();
        getContentPane().add( panel );
        int[] pixels = new int[imageSize];

        //  Create Red Image

        for (int i = 0; i < imageSize; i++)
        {
            //pixels[i] = 255 << 16; // no alpha
            pixels[i] = (64 << 24 ) + (255 << 16);
        }

        panel.add( createImageLabel(pixels) );

        //  Create Green Image

        for (int i = 0; i < imageSize; i++)
        {
            //pixels[i] = 255 << 8;
            pixels[i] = (128 << 24 ) + (255 << 8);
        }

        panel.add( createImageLabel(pixels) );

        //  Create Blue Image

        for (int i = 0; i < imageSize; i++)
        {
            //pixels[i] = 255;
            pixels[i] = (192 << 24 ) + (255);
        }

        panel.add( createImageLabel(pixels) );

        //  Create Cyan Image

        for (int i = 0; i < imageSize; i++)
        {
            //pixels[i] = (255 << 8) + 255;
            pixels[i] = (255 << 24 ) + (255 << 8) + (255);
        }

        panel.add( createImageLabel(pixels) );

    }

    private JLabel createImageLabel(int[] pixels)
    {
        //BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RRGB);
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        WritableRaster raster = image.getRaster();
        raster.setDataElements(0, 0, width, height, pixels);
        JLabel label = new JLabel( new ImageIcon(image) );
        return label;
    }

    public static void main(String args[])
    {
        JFrame frame = new ImageFromArray3();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
    }
}