バイナリデータをビットマップに必要な8ビット形式(256階調)に直すことはできたのですが、このデータをビットマップ形式で画像表示することができません。
方法を教えていただけるとありがたいです。
よろしくお願いします。
縦横が同じ TBitmap を Create し PixelFormat を pf8bit にセットしてから、ScanLine を利用してデータを書き込み、グレイスケールのパレットをセット
します。これで作成したビットマップを普通に表示できるでしょう。
パレットのセットの例は
http://junki.lix.jp/delphigr/009SetPaletteEntries.htm
にあります。ここで紹介しているライブラリの TBmpData8 を使えば高速に
書き込みできるでしょう。
初心者の方ならば、先ずはわかりやすいPixelsプロパティを使って様子をみてはどうでしょう?
例えば、
Image1.canvas.Pixels[x,y] :=RGB(r,g,b);
x,y:座標
r,g,b:画素の各色データ(8bit)
です。先ずは r=g=b でその8bitデータを書き込んでみては?
それで過不足無ければそのままでもよいし、実行速度に不満があれば(Pixelsはめっちゃ遅い)ScanLineを使って一歩上を目指せばよいし。
ご回答ありがとうございます。
初心者ですのでPixelsプロパティを使用したのですが、
斜めに線が一本入るだけで画像にできません。
J:=0にしたら一列だけはできるのですが、一ライン312ピクセルの、二列目以降がうまくいかない状態です。
inc(i)では二列目以降はできないのでしょうか?
他の方法を教えていただけるとありがたいです。
procedure TForm1.Button2Click(Sender: TObject);
var
data : WORD;
cnt: WORD;
buff:WORD;
i,j: WORD;
begin
i :=0 ;
j :=0 ;
with TFileStream.Create('ファイル名', fmOpenRead) do try
while True do begin
cnt := Read(data, Sizeof(data));
if cnt < Sizeof(data) then break;
buff:=trunc(data/16); //12ビットのデータを8ビットに
if buff>255 then buff:=255;
begin
Image1.Canvas.Pixels[i,j]:=RGB(buff,buff,buff);
end;
inc(i) ;
inc(j) ;
end;
finally
Free;
end;
end;
iとjを同時にカウントアップしたら必ず右下がりの直線が描けます^^;
Inc(j);
ではなく、
if i=311 then
begin
Inc(j);
i := 0;
end;
とでもすればいいのかしら・・・
ここは素直にforの2重ループで書くのがベターです。
ループ関数を初めに試したのですが
for i := 0 to 311 do
for j := 0 to 239 do
としたら
止まってしまいましたw
重いからでしょうか?
「止まって」とはどのような状態ですか?正確な表現をしてください。
アプリケーションが落ちるのか、OS自体が落ちるのか、あるいはエラーメッセージが出るのか。
312x240程度なら、恐らく0.5秒もかかりません。(CPUによりますが)
重いからということはないと思います。
プロジェクトが応答なしの状態になるんです。
for i := 0 to 311 do
for j := 0 to 239 do
begin
Image1.Canvas.Pixels[i,j]:=RGB(buff,buff,buff);
end;
このような関数ではだめなのでしょうか?
プロジェクトが応答なしの状態になるんです。
for i := 0 to 311 do
for j := 0 to 239 do
begin
Image1.Canvas.Pixels[i,j]:=RGB(buff,buff,buff);
end;
このような関数ではだめなのでしょうか?
再現できるコードをきちんと載せる、かつ誰でも試せる状態を用意する。
これをクリアしない限り、貴方のプロジェクトが何故破綻するのかを指摘するのは難しいと思いますよ。
>このような関数ではだめなのでしょうか?
貴方自身で上記のコードを新プロジェクトに貼って試してみればわかります。
この6行のコード自体には特に問題はありません。
「問題の切り分け」というのは大事なことです。
きちんと押さえましょう。
※もしかして時間がかかっているだけかも^^;
今試してみたら0.35秒くらいかかってます。
(Core2Quad 2.8G)
ご指摘ありがとうございます。以後気をつけます。
エラーで二回送信されたのも申し訳ないです。
コードは以下のようにして再度試したのですがやはりプロジェクトが応答しない状態になってしまいました。CPU使用率100%でした。
XPでintelのceleronです。
この場合、やはりコードがどこかおかしいのが疑われると思うのですが。
以下にコードを貼り付けます。
たびたびすみませんが、指摘いただけるとありがたいです。
procedure TForm1.Button2Click(Sender: TObject);
var
data : WORD;
cnt: WORD;
buff:WORD;
i,j: WORD;
begin
with TFileStream.Create('ファイル名', fmOpenRead) do try
// 2Byte単位で読み込み
// Position := 0;
while True do begin
cnt := Read(data, Sizeof(data));
if cnt < Sizeof(data) then break;
buff:=trunc(data/16);
if buff>255 then buff:=255;
//12bitから8bitに変換
for i := 0 to 311 do
for j := 0 to 239 do
begin
Image1.Canvas.Pixels[i,j]:=RGB(buff,buff,buff);
end;
end;
finally
Free;
end;
end;
明らかにforのループの括りが間違っています。
これではデータ1つ読む度に全画面をそのデータでベタ塗り(しかも遅いPixelsで)し、そのベタ塗りをデータ数だけ繰り返していませんか?
動きそうな感じで書いてみました。いろいろ細かく変更してます。参考にしてください。
procedure TForm1.Button2Click(Sender: TObject);
var
data: ShortInt; //8bit単位にしている(注意)
cnt: Integer;
buff: Integer;
i, j: Integer;
fs: TFileStream;
breakflag: BOOL;
t1, t2: Cardinal;
begin
t1 := GetTickCount;
fs := TFileStream.Create('C:\WINDOWS\シャボン.bmp', fmOpenRead); //私のPCにはある。貴方のPCには無いかもしれない。
try
breakflag := false;
fs.Position := 440 * Sizeof(data); //ヘッダ読みとばし(注意)
for i := 0 to 255 {311} do //注意
begin
for j := 0 to 255 {239} do //注意
begin
cnt := fs.Read(data, Sizeof(data)); //8bit単位(注意)
if cnt < Sizeof(data) then
begin
breakflag := true;
break;
end;
buff := data * 4; //ここも適当に正規化(注意)
if buff > 255 then
buff := 255;
Image1.Canvas.Pixels[i, j] := RGB(buff, buff, buff);
end;
if breakflag = true then
break;
end;
t2 := GetTickCount;
Label1.Caption := IntToStr(t2 - t1 )+'ms';
finally
fs.Free;
end;
end;
ありがとうございます!!!
8bitで読み込んでいるところを変更して、
適当に計算式で正規化させればいいのですね。
うまくいきそうです^^;
本当に感謝です。丁寧なご指導ありがとうございました。
ツイート | ![]() |