英文:
How do I fade a BufferedImage when manipulating it's pixel data?
问题
我正在尝试做一些我以前从未做过的事情。
我的目标是能够操作BufferedImage的不透明度。首先,我不使用Graphics。我正在开发一个简单的游戏引擎,我只使用来自BufferedImages的像素数据。
我尝试了什么?
我创建了自己的“Image”类,该类接受一个BufferedImage。
BufferedImage image = null;
try {
image = ImageIO.read(Image.class.getResourceAsStream(resourcePath));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
width = image.getWidth();
height = image.getHeight();
hasAlpha = image.getColorModel().hasAlpha();
pixels = image.getRGB(0, 0, width, height, null, 0, width);
然后,我继续进行渲染代码。我有一个名为“drawImage()”的函数,该函数接受图像及其数据,然后根据用户的意愿将其放置在屏幕上的特定位置。然而,我希望用户也能选择其不透明度。
我首先获取了该像素的像素数据,然后创建了一个Color对象。
Color c = new Color(image.getPixels()[value2], true);
关于“true”语句,据我所知,它表示它应该“关心”Alpha通道。
然后,我使用以下代码放置像素:
pixels[x + y * pWidth] = new Color(c.getRed(), c.getGreen(), c.getBlue(), alphaValue).getRGB();
这并不起作用。它不会输出任何错误,我可以将alphaValue更改为介于0和无穷大之间的数字。然而,我发现的一个问题是,当我将alpha从255更改为50时,它根本不影响图像。效果在0-5之间。我还注意到的另一件事是,当我将alphaValue设置为2时,我会得到一个动画,而不是具有较低不透明度的图像。听起来很奇怪,这就是我提供问题的.gif文件:
我向您保证没有代码会更改alphaValue。在那个“动画”期间,它被设置为2,没有其他操作。
因此,这里有一些奇怪的地方,我想知道您是否知道问题所在?
可能与Image类有关,我没有将其设置为BufferedImage.RGBA,但我不知道在加载图像时该如何设置?
如果您需要更多信息,请留言,我会提供更多信息!
提前感谢!
编辑
我通过操作背景像素(也是BufferedImage)每1/60秒清空屏幕一次:
public void clear() {
for (int i = 0; i < pixels.length; i++) {
pixels[i] = clearColor.getRGB();
}
}
可能的问题
我进行了一些故障排除,发现它实际上在每一帧中以某种方式增加了不透明度,就像@Joni所说的那样。不知何故,每帧的不透明度或alpha似乎都在增加,但我在绘制之间清除了屏幕。我将进一步排除故障。
更新
我使图像可以移动,发现了这种奇怪的行为:
似乎“alpha”没有重置。我知道RGB已经被重置了,但是在Alpha方面出现了一些问题。
我将清除函数更改为:
public void clear() {
for (int i = 0; i < pixels.length; i++) {
pixels[i] = new Color(clearColor.getRed(), clearColor.getGreen(), clearColor.getBlue(), 255).getRGB();
}
}
并且我定义了clearColor:
Color clearColor = new Color(Color.black.getRGB(), true);
然而,这也没有起作用。是否有人有解决办法?
英文:
I am trying to do something I have never done before.
My goal is to be able to manipulate the opacity of a BufferedImage. First off, I do not use Graphics. I am developing a simple Game Engine and I only use pixel data from BufferedImages.
What have I tried?
I made my own "Image" class that takes in a BufferedImage.
BufferedImage image = null;
try {
image = ImageIO.read(Image.class.getResourceAsStream(resourcePath));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
width = image.getWidth();
height = image.getHeight();
hasAlpha = image.getColorModel().hasAlpha();
pixels = image.getRGB(0, 0, width, height,null,0,width);
After that I proceeded to my rendering code. I have a function called "drawImage()" that takes the image and it's data and then puts it out on a specific spot on the screen depending on the users wishes. I however want the user to choose it's opacity as well.
I started out by taking the pixel data for that pixel and I instead made a Color.
Color c = new Color(image.getPixels()[value2],true);
The "true" statement, what I know of, says that it should "care" about Alpha.
After that I place the pixel by using this code:
pixels[x + y * pWidth] = new Color(c.getRed(),c.getGreen(),c.getBlue(),alphaValue).getRGB();
This doesn't work. It doesnt output any errors and I can change the alphaValue to a number between 0 and infinity. However one issue I found is that it doesnt affect the image at all when I change the alpha from 255 to something like 50. It stays the same. The affect comes at 0-5. Another thing that I noticed is that when I set alphaValue to something like 2 I get an animation instead of the image with lower opacity. Sounds weird, that's why I provided a .GIF of the issue:
I guarantee you that there is no code that changes the alphaValue. During that "animation" it is set to 2 and nothing else.
So something is weird here and I wonder if you guys know the issue?
It might have something to do with the Image class and that I don't set it to BufferedImage.RGBA but I don't know how I can do so when I load an image?
If you need any more information, please leave a comment and I will provide more info!
Thanks in advance!
EDIT
I clear the screen every 1/60 of a second by manipulating the backgrounds pixels (also a bufferedImage):
public void clear() {
for(int i = 0; i < pixels.length; i++) {
pixels[i] = clearColor.getRGB();
}
}
Possible issue
I did some troubleshooting and I found out that it actually somehow increased in opacity each frame as @Joni said. Somehow the opacity or alpha seems to increase each frame but I am clearing the screen between drawings. I will troubleshoot further.
UPDATE
I made so I could move the image around and found this weird behaviour:
It seems that the "alpha" isn't reset. I know that the RGB is being reset but something is really off when it comes to the Alpha.
I changed the clear function to this:
public void clear() {
for(int i = 0; i < pixels.length; i++) {
pixels[i] = new Color(clearColor.getRed(),clearColor.getGreen(),clearColor.getBlue(),255).getRGB();
}
}
And I defined clearColor as:
Color clearColor = new Color(Color.black.getRGB(),true);
That did however not work either. Does anyone have a solution?
答案1
得分: 2
你的游戏引擎在循环中将图像绘制在自身顶部。绘制足够多次后,效果与未使用透明度效果相同。透明度越低,所需时间越长:使用50%透明度,您需要7帧才能达到99%的不透明度,使用5%透明度大约需要90帧。
例如,假设您在初始为0(黑色)且透明度为50%的屏幕上绘制像素值为100。第一帧后,输出像素值为0.5100 + 0.50 = 50。第二帧绘制在第一帧之上,因此输出像素值为0.5100 + 0.550 = 75。第三帧绘制在第二帧之上,将显示0.5100 + 0.575 = 87.5。
为了避免这种情况,在每一帧的图像下方填充一个纯色背景。
英文:
Your game engine is drawing the image on top of itself in a loop. After drawing it enough many times the effect is the same as not having used transparency at all. The lower the alpha, the longer it takes though: with 50% alpha you need 7 frames to get 99% opacity, with 5% alpha you need about 90 frames.
For example, suppose you are drawing a pixel value of 100 on a screen that's intially 0 (black) with 50% opacity. After the first frame, the output pixel value is .5*100 + .5*0 = 50. The second frame is drawn on top of the first frame, so the output pixel value is .5*100 + .5*50 = 75. The third frame, drawn on top of the second frame, will show .5*100 + .5*75 = 87.5.
To avoid this, you need to fill a solid background color under the image in every frame.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论