1

ソース画像(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);
}
}

よろしくラジャ。

4

1 に答える 1

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パレットの最大サイズ)であるため、何らかの重複排除ロジックが必要になります。画像の色よりも大きなパレットで画像を保存しないように注意してください(特に後で新しい色を追加する場合)。元のファイルは2色パレットで保存でき、762バイト節約できます。

同じ色数のトゥルーカラーとは対照的に、インデックス付きの画像を保存してもあまりメリットがないことに注意してください。その理由は、バイトストリーム(パレット= 1ピクセルあたり1バイト、トゥルーカラー= 1ピクセルあたり3または4バイト)がとにかくロスレス圧縮(DEFLATEを使用)されるためです。インデックスを作成すると、数バイト節約できます(パレットが大きい場合は、数バイトを失う可能性があります)が、ファイルサイズが3分の1に減少することはありません。

于 2012-12-11T08:14:49.900 に答える