ビットマップをimage1に表示し、image2に画像を縮小して表示したいのですが、StretchDraw,CopyRect、StretchBltなどで試してみましたが比率を指定してimage2に表示しようとするとモアレのようなぎざぎざがはいった画像になってしまいます。きれいに表示する方法ないでしょうか。
おはようございまする。
これはAPIに任せず自力で行う必要があります。
といっても初心者には結構難しいとおもいます。
が、
http://www.asahi-net.or.jp/~HA3T-NKMR/DGS/index.htm
で中村氏によるやり方およびそれをコンポーネント化したものがあります。
本気で取り組むなら、絶対購入するべきです。
おはようございます。
Strechは単純間引きなので、斜め線がギザギザしたり、モアレっぽくなったりしますね。
(画像に限りませんが)
例え単純間引きを止めて、ある程度のタップ数で補間しても縮小サンプリングは「折り返し」という現象が発生し、モアレ状のパターンが生じることがあります。
従って縮小する前にローパスフィルタによって帯域制限をかけるのが普通です。
しかしながら、一般的な用途(サムネイル表示とか)であれば、ローパスフィルタは端折っても、まあ大丈夫ではないでしょうか。
縮小なら補間も線形補間で十分かと。
この場合、原理的には水平のみ縮小→垂直のみ縮小でOKです。
以下に単純な例を挙げます。(例ですので、速度・効率とかは考えていません)
//----------------------------------------------------
type節に
TRGBTripleArray = array[0 .. High(Integer) div 3 - 1] of RGBTRIPLE;
PRGBTripleArray = ^TRGBTripleArray; //配列型のポインタ
を追加、
button1、edit1、image1、image2を貼り付けて、FormCreate等で Image1 に既にbmpが読み込まれているものとします。
edit1に倍率(0.667とか)を入力しボタンを押すとimage2に縮小画像を表示します。
なお、デバッグは適当なので、倍率が2以上でエラーになっちゃいます^^;
//---------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
Ps,Ps2,Pd: PRGBTripleArray;
HBMP,VBMP : TBitMap;
xk,yk,rate : double;
xphase,yphase : double;
xdsize,ydsize :Integer;
x,y :Integer;
R0,G0,B0 :Short;
R1,G1,B1 :Short;
begin
rate := StrToFloat(Edit1.Text);
HBMP := TBitMap.Create;
VBMP := TBitMap.Create;
HBMP.PixelFormat := pf24bit;
VBMP.PixelFormat := pf24bit;
xdsize:=round(Image1.Picture.Bitmap.Width * rate);
ydsize:=round(Image1.Picture.Bitmap.Height* rate);
HBMP.Width := xdsize;
HBMP.Height := Image1.Picture.Bitmap.Height;
VBMP.Width := xdsize;
VBMP.Height := ydsize;
//水平のみ処理
for y := 0 to Image1.Picture.Bitmap.Height-1 do
begin
Ps := Image1.Picture.Bitmap.ScanLine[y];
Pd := HBMP.ScanLine[y];
xk := 0;
x := 0;
while (x < xdsize-1 )do
begin
xphase := xk - Trunc(xk);
R0 := Ps[Trunc(xk)].rgbtRed;
G0 := Ps[Trunc(xk)].rgbtGreen;
B0 := Ps[Trunc(xk)].rgbtBlue;
R1 := Ps[Trunc(xk)+1].rgbtRed;
G1 := Ps[Trunc(xk)+1].rgbtGreen;
B1 := Ps[Trunc(xk)+1].rgbtBlue;
Pd[x].rgbtRed := Trunc(R0*(1-xphase) +R1*xphase);
Pd[x].rgbtGreen:= Trunc(G0*(1-xphase) +G1*xphase);
Pd[x].rgbtBlue := Trunc(B0*(1-xphase) +B1*xphase);
xk := xk + 1/rate;
Inc(x);
end;
end;
//Image2.Picture.Bitmap.Assign(HBMP);
//垂直のみ処理
yk :=0;
y :=0;
while ( y < ydsize-1) do
begin
yphase := yk - Trunc(yk);
Ps := HBMP.ScanLine[Trunc(yk)];
Ps2:= HBMP.ScanLine[Trunc(yk)+1];
Pd := VBMP.ScanLine[y];
for x := 0 to xdsize-1 do
begin
R0 := Ps[x].rgbtRed;
G0 := Ps[x].rgbtGreen;
B0 := Ps[x].rgbtBlue;
R1 := Ps2[x].rgbtRed;
G1 := Ps2[x].rgbtGreen;
B1 := Ps2[x].rgbtBlue;
Pd[x].rgbtRed := Trunc(R0*(1-yphase) +R1*yphase);
Pd[x].rgbtGreen:= Trunc(G0*(1-yphase) +G1*yphase);
Pd[x].rgbtBlue := Trunc(B0*(1-yphase) +B1*yphase);
end;
yk := yk +1/rate;
Inc(y);
end;
Image2.Picture.Bitmap.Assign(VBMP);
HBMP.free;
VBMP.free;
end;
> 本気で取り組むなら、絶対購入するべきです。
「画像処理全般に」という意味だと思います。解ったふりをして通読するのに私は2年半かかりましたが。それだけの価値はあります。\2,980+悪税。
ただし、添付CDのコードはすべて無料でダウンロードして使えます。
DHGL1.2 をダウンロードします。
質問の件については、CommonフォルダのBitmapUtils.pas を uses に加え、
Shrink() を使用すると実現できます。
品質は、10万する Photoshop と同等か若干上という優れものです。
処理速度も速いです。
使い方は、Chapter4\4-5\Stretch\ に Demo.dpr があります。
尚、DHGL はすべて Delphi4 以上対応ですので、Delphi3 の場合は、一部自分で書き直す必要があります。
困難であれば、当方で提供可能です。
めだまやきさん、sadoyamaありがとうござます。
データベースが中心で画像処理ほとんど関わっていなかったものでこれから勉強してみたいと思います。
ウォレスさん ありがとうございます。
紹介いただいた方法で試してみました。きれいに表示することができました。
Delphi3.1を昔使用していましたが、しばらくVB,Access関係がメインになりしばらくDelphiから離れていましたが今回Delphi7 proを購入し試しためし使っています。やはりDelphiいいですね。これからもよろしくお願いします。
ツイート | ![]() |