java - 在Java2D中替换图像像素

标签 java java-2d

我正在尝试替换源图像(PNG 格式)中的一些像素。但我最终得到了一些令人困惑的结果。基本上我用黑色和白色替换特定的 RGB 值。这是我的代码,

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ChangePixel
{
public static void main(String args[]) throws IOException
{
    File file = new File(System.getProperty("user.dir"), "D4635.png");
    FileInputStream fis = new FileInputStream(file);
    BufferedImage image = ImageIO.read(fis);

    int[] replaceColors = new int[2];
    replaceColors[0] = Color.BLACK.getRGB();
    replaceColors[1] = Color.WHITE.getRGB();
    Color src = new Color(133, 101, 51);
    int srcRGBvalue = src.getRGB();

    changeAlg2(image, srcRGBvalue, replaceColors);
}

private static void changeAlg2(BufferedImage image, int srcRGBvalue, int[] replaceColors) throws IOException
{
    for (int width = 0; width < image.getWidth(); width++)
    {
        for (int height = 0; height < image.getHeight(); height++)
        {
            if (image.getRGB(width, height) == srcRGBvalue)
            {
                image.setRGB(width, height, ((width + height) % 2 == 0 ? replaceColors[0] : replaceColors[1]));
            }
        }
    }

    File file = new File(System.getProperty("user.dir"), "107.png");
    ImageIO.write(image, "png", file);
}
}

它将我的源像素更改为黑色和其他颜色,而不是白色。请告诉我这里出了什么问题。

由于这是我的第一篇文章,因此我无法附加我的图像。带来不便敬请谅解。

编辑:我已将源图像和输出图像上传到网站中。这是网址, 来源:http://s20.postimage.org/d7zdt7kwt/D4635.png 输出:http://s20.postimage.org/kdr4vntzx/107.png 预期输出:黑色像素之后,必须出现白色像素。

编辑:根据Jan Dvorak建议解决了代码,

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ChangePixel
{
public static void main(String args[]) throws IOException
{
    File file = new File(System.getProperty("user.dir"), "D12014.gif");
    FileInputStream fis = new FileInputStream(file);
    BufferedImage image = ImageIO.read(fis);

    Color src = new Color(223, 170, 66);
    int srcRGBvalue = src.getRGB();
    int[] replaceColors = new int[2];
    replaceColors[0] = Color.MAGENTA.getRGB();
    replaceColors[1] = Color.CYAN.getRGB();

    changeAlg2(image, srcRGBvalue, replaceColors);
}

private static void changeAlg2(BufferedImage image, int srcRGBvalue, int[] replaceColors) throws IOException
{
    BufferedImage image2 = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
    for (int width = 0; width < image.getWidth(); width++)
    {
        for (int height = 0; height < image.getHeight(); height++)
        {
            if (image.getRGB(width, height) == srcRGBvalue)
            {
                image2.setRGB(width, height, ((width + height) % 2 == 0 ? replaceColors[0] : replaceColors[1]));
            }
            else
            {
                image2.setRGB(width, height, image.getRGB(width, height));
            }
        }
    }

    File file = new File(System.getProperty("user.dir"), "110.gif");
    ImageIO.write(image2, "gif", file);
}
}

问候 拉贾。

最佳答案

由于您要添加原始图像调色板中不存在的颜色,因此您尝试设置的像素将被剪裁为调色板中最接近的颜色。您需要设置新的颜色模式。转换为 24bpp RGB(真彩色)或使用新颜色扩展调色板。

似乎无法修改现有的 BufferedImage ColorModel 或分配新的缓冲区,但您可以创建一个新缓冲区并将数据复制到其中。创建具有相同 Raster 的新 BufferedImage 也可能有效(仅当位深度不改变时?)。

如果您不介意,您可以随时创建真彩色图像。尝试:

{
    BufferedImage old = image;
    image = new BufferedImage(
        old.getWidth(),
        old.getHeight(),
        BufferedImage.TYPE_INT_RGB
    );
    image.setData(old.getRaster());
} // old is no longer needed

API引用:http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/image/BufferedImage.html

您可以尝试检测图像是否已经是真彩色(image.getColorModel() instanceof ???),以避免在不需要时复制缓冲区。

您可以尝试扩展现有的调色板。如果这是不可能的(没有可用的调色板或没有足够的空间),则必须回退到 RGB。

参见:

http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/image/BufferedImage.html (getColorModel 和采用 ColorModel 和类型的构造函数)
http://docs.oracle.com/javase/1.4.2/docs/api/java/awt/image/IndexColorModel.html (getMapSize、getRGBs以及相应的构造函数)

通过查看实际的调色板,您将需要某种重复数据删除逻辑,因为您的调色板已经是 256 字节 - PNG 调色板的最大大小。请注意,保存图像时不应使用比图像中颜色更大的调色板(特别是当您稍后想要添加新颜色时)。您的原始文件可以使用 2 调色板保存,从而节省 762 字节。

请注意,与具有相同颜色数量的真彩色图像相比,将图像存储为索引形式并不会带来太多好处。原因是字节流(调色板=每像素 1 字节,真彩色=每像素 3 或 4 字节)无论如何都是无损压缩的(使用 DEFLATE)。索引可以为您节省一些字节(或者如果调色板很大,则会损失一些字节),但它不会将文件大小减少到三分之一。

关于java - 在Java2D中替换图像像素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13814802/

相关文章:

java - java.awt.graphics 中图形的自定义方法

java - Akka Actor 中的 Httpclient 死锁

java - ListView 仅显示 ListView 第一个位置的最后一项

java - Eclipse 插件的名称是否无关紧要,只要驻留在plugins/目录中并且只要其内容有效?

java - 在基于图 block 的 map 中查找多边形的内部坐标

java - 如何在 java2D 中获取 Font X 偏移宽度?

java - 如何拖动多边形?

java - 如何对某个区域内的非GUI对象实现MouseListener?

java - Android MVP - Mockito 测试不传递 eq(ObjectDTO),但传递从中提取值

java - 连续多次打印字符串