在Java2D中替换图像像素

时间:2012-12-11 06:25:35

标签: 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);
}
}

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

由于这是我的第一篇文章,我无法附上我的图片。抱歉给你带来不便。

编辑:我已在网站上传了源图像和输出图像。这是URL, 资料来源: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);
}
}

此致 拉加。

1 个答案:

答案 0 :(得分:1)

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

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

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

{
    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调色板的最大尺寸。请注意,不应使用比图像中的颜色更大的调色板保存图像(特别是当您想稍后添加新颜色时)。您的原始文件可以使用双色调色板保存,节省762个字节。

请注意,将图像存储为索引,而不是使用相同数量的颜色的真彩色,您获得的收益并不高。原因是字节流(调色板=每像素1个字节,真彩色=每个像素3个或4个字节)无论如何都是无损压缩(使用DEFLATE)。索引可以节省几个字节(如果调色板很大,则会丢失几个字节),但它不会将文件大小减少到三分之一。