处理像素数据时如何淡化 BufferedImage?
How do I fade a BufferedImage when manipulating it's pixel data?
我正在尝试做一些我以前从未做过的事情。
我的目标是能够操纵 BufferedImage 的不透明度。首先,我不使用图形。我正在开发一个简单的游戏引擎,我只使用来自 BufferedImages 的像素数据。
我尝试了什么?
我制作了自己的“图像”class,它接受了 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 c = new Color(image.getPixels()[value2],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,没有别的。
所以这里有些奇怪,我想知道你们是否知道这个问题?
可能与图像有关 class 我没有将其设置为 BufferedImage.RGBA 但我不知道如何设置我可以在加载图像时这样做吗?
如果您需要更多信息,请发表评论,我会提供更多信息!
提前致谢!
编辑
我通过操纵背景像素(也是一个缓冲图像)每 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);
但这也没有用。有人有解决办法吗?
您的游戏引擎正在循环绘制图像。绘制足够多次后,效果与完全不使用透明度相同。 alpha 越低,花费的时间越长:50% alpha 需要 7 帧才能获得 99% 不透明度,5% alpha 需要大约 90 帧。
例如,假设您要在初始为 0(黑色)且不透明度为 50% 的屏幕上绘制像素值为 100 的像素值。在第一帧之后,输出像素值为 .5*100 + .5*0 = 50。第二帧绘制在第一帧之上,因此输出像素值为 .5*100 + .5*50 = 75. 在第二帧之上绘制的第三帧将显示 .5*100 + .5*75 = 87.5.
为避免这种情况,您需要在每一帧的图像下方填充纯色背景。
我正在尝试做一些我以前从未做过的事情。 我的目标是能够操纵 BufferedImage 的不透明度。首先,我不使用图形。我正在开发一个简单的游戏引擎,我只使用来自 BufferedImages 的像素数据。
我尝试了什么?
我制作了自己的“图像”class,它接受了 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 c = new Color(image.getPixels()[value2],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,没有别的。
所以这里有些奇怪,我想知道你们是否知道这个问题?
可能与图像有关 class 我没有将其设置为 BufferedImage.RGBA 但我不知道如何设置我可以在加载图像时这样做吗?
如果您需要更多信息,请发表评论,我会提供更多信息!
提前致谢!
编辑 我通过操纵背景像素(也是一个缓冲图像)每 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);
但这也没有用。有人有解决办法吗?
您的游戏引擎正在循环绘制图像。绘制足够多次后,效果与完全不使用透明度相同。 alpha 越低,花费的时间越长:50% alpha 需要 7 帧才能获得 99% 不透明度,5% alpha 需要大约 90 帧。
例如,假设您要在初始为 0(黑色)且不透明度为 50% 的屏幕上绘制像素值为 100 的像素值。在第一帧之后,输出像素值为 .5*100 + .5*0 = 50。第二帧绘制在第一帧之上,因此输出像素值为 .5*100 + .5*50 = 75. 在第二帧之上绘制的第三帧将显示 .5*100 + .5*75 = 87.5.
为避免这种情况,您需要在每一帧的图像下方填充纯色背景。