Java 我试图实现透明度,但出了问题
我想在我的游戏引擎中增加“透明度”,而我之前并不知道这一点。关于如何实现它,我没有找到任何直接的答案,所以我最后做了一些研究,研究了一种叫做Alpha-Blending的方法,如果我理解正确的话,这是一种显示不透明度的方法 我在谷歌上搜索了一下,试图找到一个源代码,展示了当你有一个像素阵列时如何实现这一点。我不知道怎么回事,但除了Youtube上的一篇教程,我什么也没找到。他们没有解释为什么他们会这样做,因此我仍然不知道如何实施它或它是如何工作的。我试着按照教程进行操作,但他们使用的代码根本不起作用,所以我对它做了一些修改(显然不起作用) 下面的代码是我的setPixel()函数,用于在指定位置设置像素。从函数开始,它只检查是否需要放置一个像素。此函数用于从像素数据中绘制每个单独的像素。屏幕的像素数据存储在变量pixels中。图像数据存储在值中。值只是一个整数,而像素是一个数组Java 我试图实现透明度,但出了问题,java,alpha-transparency,Java,Alpha Transparency,我想在我的游戏引擎中增加“透明度”,而我之前并不知道这一点。关于如何实现它,我没有找到任何直接的答案,所以我最后做了一些研究,研究了一种叫做Alpha-Blending的方法,如果我理解正确的话,这是一种显示不透明度的方法 我在谷歌上搜索了一下,试图找到一个源代码,展示了当你有一个像素阵列时如何实现这一点。我不知道怎么回事,但除了Youtube上的一篇教程,我什么也没找到。他们没有解释为什么他们会这样做,因此我仍然不知道如何实施它或它是如何工作的。我试着按照教程进行操作,但他们使用的代码根本不起
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 );
}
}