3

私の先生は、640x480 bmp のカラー画像をグレースケール画像に変換するクラスを作成するタスクを与えました。アイデアのあるソースをいくつか見つけたので、それを実行しました。しかし、それが原因でエラーが発生していないように見えるため、問題がありますが、出力は表示されません。私のコードだと思います。私のコードは

import java.io.*;

public class Grayscale{

FileInputStream image;
FileOutputStream img;
byte[] datos;
int gray;

public Grayscale(String nombre)throws Exception{

    this.image = new FileInputStream(nombre);
    this.img = img;
    this.datos = new byte[image.available()];
    this.gray = gray;
}

public void gray()throws Exception{

    image.read(datos);
    img = new FileOutputStream("grayscaleprueba.bmp");

    for (int i = 0; i<datos.length; i++){
        gray = (byte)(datos[i]*0.3 + datos[i+1]*0.59 + datos[i+2]);
        datos[i] = (byte)gray;
        datos[i+1] = (byte)gray;
        datos[i+2] = (byte)gray;
    }

    img.write(datos);
}
}
4

3 に答える 3

1

@joniが言及したものとは別に、いくつかの問題があります。この問題は、最初に思われたものよりも少し深いものです。

BMP ファイル形式

  • BMP 形式にはヘッダーがあります。画像変換を行う前に、ヘッダーをスキップ (またはおそらく更新) する必要があります。
  • カラーテーブル:「ストレート」パレットを想定しています:カラーインデックスはRGB値と同じです。しかし、これは違うかもしれません...(ところで:画像がカラーテーブルを使用している場合は、それのみを変更してグレースケール画像を取得できます...)
  • ピクセルあたり何ビットですか? 8-8-8 分布で、ピクセルあたり 24 ビットであると仮定しました。これは保証されていません...ヘッダーはこの情報を提供します。
  • 圧縮: ええ、画像は圧縮されている可能性があります。ピクセル値自体を処理するには、画像をデコードする必要があります。

ループ

ピクセルごとに 3 バイトを処理し、1 ずつ増分してファイルをループします。結果の画像は、3D メガネを通して見ると非常に興味深いものになるかもしれませんが、奇妙な画像が表示されることを意味します。

for (int i = 0; i<datos.length; i+=3){ // increment by 3 instead of 1
    gray = (byte)(datos[i]*0.3 + datos[i+1]*0.59 + datos[i+2]);
    datos[i] = (byte)gray;
    datos[i+1] = (byte)gray;
    datos[i+2] = (byte)gray;
}

符号付きバイト

Java のバイトは署名付きです。-128 から 127 になるため、算術演算は有効ではありません。バイトごとに、それを int として使用し、重みで合計する前に 128 を追加します。次に、合計した後、128 を減算し、バイトにキャストします。

ピクセル変換値の範囲

saem 範囲内の 3 つの数値を合計し、その範囲内の数値を取得したいとします。ただし、重みはこれを反映していません。重みは合計して 1 になるはずです。まず、すべての値に 0.33 を使用します (完全な色の重みは得られませんが、技術的には機能するはずです)。

    //using double to have some precision
    double temp = datos[i]/3.0d + datos[i+1]/3.0d + datos[i]/3.0d;
    gray = (byte)(Math.round(temp)-128); //rounding to Long, and converting to byt value range
于 2013-09-11T14:48:52.197 に答える
0

このコードにはいくつかの問題があります。

  1. このavailableメソッドは、実際にディスクから読み取ることなく、すぐに利用できるバイト数を通知するだけです。0 を返す場合もあります。
  2. このreadメソッドは、データの一部のみを読み取ります。戻り値は、実際に読み取ったバイト数を示します。
  3. 出力ストリームを閉じません。出力を閉じないと、出力ファイルに何かが書き込まれるという保証はありません。
于 2013-09-11T14:41:05.163 に答える