jpg := TJPEGImage.Create;
try
jpg.LoadFromFile(OpenPictureDialog1.FileName);
Image1.Picture.Assign(jpg);
finally
jpg.Free;
end;
でImage1に表示していますが、拡大すると画質が悪いです・・・
滑らかに表示する方法があったら教えて下さい。
よろしくお願いします。
環境は、WinXP+Delphi7です。
JPEGは、画質をある程度犠牲にしてでもDATAサイズを小さくする画像フォーマットです。
なので、JPEG画像を拡大すればブロックノイズ、モスキートノイズが目立つのはしかたありません。それが宿命です。
画質を重視するなら、BMP形式の画像を使うべきでしょう。
※画像加工ソフトでJPEG画像にソフトエフェクトをかければ少しはマシになるかな。
いや jpg に限らず GDI の普通の関数を使っている限りなめらかな縮小拡大は
望めません。自分で補間関数をつくるか、他人の作ったのを使うといいです。
1.JpgをBmpに変換します。
2.そのBmpに滑らかに拡大(縮小)する処理をします。
3.BmpをJpgに変換し戻します。
滑らかに拡大(縮小)する処理方法は多数ありますが、私は中村拓男さんの関数を利用させていただいています。
photoshopと比較し、その品質は同等もしくは若干上というのが私の評価です。
1.http://www.asahi-net.or.jp/~HA3T-NKMR/DGS/DownLoad.htm よりDHGL1.2をダウンロードします。
2.解凍後、commonフォルダのBitmapUtils.pasを取り出します。
3.uses節にBitmapUtilsを追加します。
4.滑らかな拡大はfunction Enlarge(Bitmap: TBitmap; Width, Height: Integer): TBitmap;
縮小はfunction Shrink(Bitmap: TBitmap; Width, Height: Integer): TBitmap;を使用します。
使用例
var
SrcBmp, DestBmp: TBitmap;
NewWidth, NewHeight: Integer;
begin
SrcBmp にJpgを変換;
try
// DestBmpのインスタンスはEnlarge()内でCreateされる
DestBmp := Enlarge(SrcBmp, NewWidth, NewHeight);
finally
DestBmp.Free;
end;
DestBmpをに変換
訂正
DestBmpをJpgに戻す前にDestBmp.Freeをしてはいけませんね。
var
SrcBmp, DestBmp: TBitmap;
NewWidth, NewHeight: Integer;
begin
SrcBmp にJpgを変換;
try
// DestBmpのインスタンスはEnlarge()内でCreateされる
DestBmp := Enlarge(SrcBmp, NewWidth, NewHeight);
DestBmpをJpgに変換 // 訂正
finally
DestBmp.Free;
end;
// DestBmpをJpgに変換 削除
単に表示するだけなら、Jpgに戻す必要はありませんね。
var
Jpg: TJpegImage;
SrcBmp, DestBmp: TBitmap;
NewWidth, NewHeight: Integer;
begin
jpg := TJPEGImage.Create;
SrcBmp := TBitmap.Create;
try
jpg.LoadFromFile(OpenPictureDialog1.FileName);
Jpg.Assign(SrcBmp);
try
// DestBmpのインスタンスはEnlarge()内でCreateされる
DestBmp := Enlarge(SrcBmp, NewWidth, NewHeight);
Image1.Picture.Assign(DestBmp);
finally
DestBmp.Free;
end;
finally
jpg.Free;
SrcBmp.Free;
end;
http://blog.livedoor.jp/junki560/
サンプルを見ましたが、かなり理想的な動作でした。
sadoyamaさんいい情報ありがとうございましたm(_ _)m
これからサンプル見ながら試して見たいと思いますw
また教えて下さい。
興味あるレスだったのですが、既に解決済みですね・・・^^;
junkiさんのページが紹介されていましたので、蛇足ながら。
junkiさんのbicubicで使用されているフィルタ係数の元ネタは
http://astronomy.swin.edu.au/~pbourke/colour/bicubic/
です。
このフィルタ係数R(x)を-2〜2までプロットすると判りますが、元画位相でも隣の画素が足しこまれます。(だから鈍る)
一般的かどうかはともかく、私の周りではバイキュービックとして
|x|<1 :1-2|x|^2+|x|^3
1<=|x|<2 :4-8|x|+5|x|^2-|x|^3
の係数を用います。
(元画位相はそのまま元の画素が選択されます)
理想的な関数はサンプリング関数 sinπx/πx ですがこれだと無限遠点まで用いなければならず現実的ではありません。
従って有界(bicubicの場合水平・垂直に近傍4点)で打ち切って、その近時関数をうまく求めたものが上記の式です。但し、どうやって求めたのかは私には導けませんでした・・
(上記式以外にも近似式は色んなタイプが得られます。)
かなり適当ですが、補間の考え方が判れば、と思い汚いソースをのっけました。
ココにコピペでもよいのですが、結構長いのでblogに。
http://blog.goo.ne.jp/supurainhikaku
ウォレスさん、どうもです。
ソースまでありがとうございます。
早速書いて頂いたソースを試して見たところ
下記の位置で停止してしまいます。
コンパイルは出来ましたが、レート入力してButton1をクリックすると
読み込み違反で停止します。
スキル不足で私にはまだ、ソースの意味が理解出来ていないので
教えて貰えるとうれしいです。
よろしくお願いします。
procedure TForm1.setRGB( P :PRGBTripleArray; maxADR : integer; x: integer;var R :Short; var G :Short; var B :Short);
begin
R := P[Med3(x,0,maxADR)].rgbtRed;
G := P[Med3(x,0,maxADR)].rgbtGreen;
B := P[Med3(x,0,maxADR)].rgbtBlue;
早速、試していただき恐縮です。
指定したbitmapファイルがない、ということはありませんか?
環境の違うところで、BLOGからコピペして一から作りましたが動作しました。
setRGB は3行を1行にするためのタスクで、深い意味はありません。
Med3 は 3つのメディアンをとる関数ですが、CLIPとしても使えるので配列の添え字チェックとして、また、値が0〜255で収まるようにするためにも使っています。
Med3(0,255,x) とすれば返す値は、x<0のとき0、 0≦x≦255のときx、255<xのとき255です。
CLIPとして使うには冗長だ!という方もいらっしゃるでしょうが、今のコンパイラは優秀です。CLIP専用に書き換えても速度変わりません。
書き忘れましたが、環境はDel6Personal、Win2K or WinXP です。
マシン5台試しました。
ソースに何か問題があるかもしれませんが再現しません・・・汗
5台も試して頂いてありがとうございます・・・汗
私もDel7Pro+WinXP&Del6Per+WinXPで2台試して見ましたが
やはり駄目でした。残念です。
修正前のソースでも試してみましたが
R3 := Ps0[Med3(xint+1,0,xssize)].rgbtRed;
の位置で停止してしまいました。
原因は分からなかったんですが、おそらく同じ原因だと思います。
今回はDHGL1.2を使用させて頂きますが、ウォレスさんの
ソースも大変勉強になりました。
また分からない事があったら教えて下さい。
修正後のをDel7Pro+WinXPで試しました。
ちろん動きました。
Bmpファイルも色々意地悪してみましたが問題無しです。
記述ミス以外にこんな事って本当にあるのかな・・・?
・エラーがどんなものだったでしょうか?
・エラーが起きる行(の直前とか)にブレークポイントを置いて、ブレーク後ステップ実行して行を特定したのでしょうか?
・エラーが起きるのは最初の1回目?そうでない場合には値のどれかが何らかの原因でオーバーフローしているのではないでしょうか?
私もあまり経験豊富とは言い難いのでなかなか想像できないんですが・・
もう見ていらっしゃらないかもしれませんが、
setRGBの第2引数を-1してみてください。オーバーランしてる気がします(オイオイ
setRGB( Ps0, xssize, xint-2, R0,G0,B0);
ではなく
setRGB( Ps0, xssize-1, xint-2, R0,G0,B0);
とする。
D6Personalには、コードガードがないので・・と言い訳してみたりします。
実用化のためには、
・実数演算をなくす
・画面端処理をもう少しなんとかする(今は、一番端より外は一番端のピクセルで補填しています。これはあまり一般的でなく、黒画像で補填した方がよい)
でしょうか。
GDI+には、ライブラリに(フィルタを指定できる)拡大縮小が備わっているようです。
ただ、GDI+を使うのは結構面倒です。(Del2005なら簡単?)
ウォレスさん
>一般的かどうかはともかく、私の周りではバイキュービックとして(以下略)
この方が bicubic フィルタとしては一般的なようですね。
わたしも実装して前回の B-Spline の補間と比較してみました。
http://code.junki.main.jp/?eid=60070
確かボケなくて気持ちよいです。
ありがとうございました。
御本家にお礼を述べられると照れますね。
IrfanViewのリサンプルの種類を見ると
Hermite フィルタ (最高速)
Triangle フィルタ
Mitchell フィルタ
Bell フィルタ
Lanczos フィルタ (高画質)
がありますね。
Photoshopには線形、最近傍、バイキュービックしかないのでなかなかです。
B-splineを調べてみると、確かに、上記
http://astronomy.swin.edu.au/~pbourke/colour/bicubic/
の係数と同じでした。
各種フィルタ比較を
http://blog.goo.ne.jp/supurainhikaku
に載せましたので参考にしてください。
ウォレスさん
> 各種フィルタ比較を
> http://blog.goo.ne.jp/supurainhikaku
> に載せましたので参考にしてください。
ありがとうございます。プロットしてみると違いが感覚的に分かりますね。
示された補間関数をすべて実装して、それを使ってイメージの拡大を試してみました。
http://code.junki.main.jp/?eid=69732
勉強になりました。ありがとうございました。
ツイート | ![]() |