JPEGを滑らかに表示する方法

解決


boon  2005-08-15 04:11:37  No: 17040

jpg := TJPEGImage.Create;
try
  jpg.LoadFromFile(OpenPictureDialog1.FileName);
  Image1.Picture.Assign(jpg);
finally
  jpg.Free;
end;

でImage1に表示していますが、拡大すると画質が悪いです・・・
滑らかに表示する方法があったら教えて下さい。
よろしくお願いします。
環境は、WinXP+Delphi7です。


宿命  2005-08-15 06:34:38  No: 17041

JPEGは、画質をある程度犠牲にしてでもDATAサイズを小さくする画像フォーマットです。
なので、JPEG画像を拡大すればブロックノイズ、モスキートノイズが目立つのはしかたありません。それが宿命です。
画質を重視するなら、BMP形式の画像を使うべきでしょう。
※画像加工ソフトでJPEG画像にソフトエフェクトをかければ少しはマシになるかな。


anone  2005-08-15 09:04:00  No: 17042

いや jpg に限らず GDI の普通の関数を使っている限りなめらかな縮小拡大は
望めません。自分で補間関数をつくるか、他人の作ったのを使うといいです。


sadoyama  URL  2005-08-15 19:37:35  No: 17043

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をに変換


sadoyama  2005-08-15 19:44:54  No: 17044

訂正

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に変換  削除


sadoyama  2005-08-15 19:56:34  No: 17045

単に表示するだけなら、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;


@a  2005-08-16 04:27:44  No: 17046

http://blog.livedoor.jp/junki560/


boon  2005-08-16 13:27:55  No: 17047

サンプルを見ましたが、かなり理想的な動作でした。
sadoyamaさんいい情報ありがとうございましたm(_ _)m
これからサンプル見ながら試して見たいと思いますw
また教えて下さい。


ウォレス  2005-08-16 19:57:17  No: 17048

興味あるレスだったのですが、既に解決済みですね・・・^^;

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点)で打ち切って、その近時関数をうまく求めたものが上記の式です。但し、どうやって求めたのかは私には導けませんでした・・
(上記式以外にも近似式は色んなタイプが得られます。)


ウォレス  2005-08-17 01:28:50  No: 17049

かなり適当ですが、補間の考え方が判れば、と思い汚いソースをのっけました。
ココにコピペでもよいのですが、結構長いのでblogに。

http://blog.goo.ne.jp/supurainhikaku


boon  2005-08-20 06:02:57  No: 17050

ウォレスさん、どうもです。
ソースまでありがとうございます。
早速書いて頂いたソースを試して見たところ
下記の位置で停止してしまいます。
コンパイルは出来ましたが、レート入力して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;


ウォレス  2005-08-20 21:56:41  No: 17051

早速、試していただき恐縮です。
指定した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専用に書き換えても速度変わりません。


ウォレス  2005-08-20 22:14:16  No: 17052

書き忘れましたが、環境はDel6Personal、Win2K or WinXP です。

マシン5台試しました。

ソースに何か問題があるかもしれませんが再現しません・・・汗


boon  2005-08-21 03:17:58  No: 17053

5台も試して頂いてありがとうございます・・・汗
私もDel7Pro+WinXP&Del6Per+WinXPで2台試して見ましたが
やはり駄目でした。残念です。
修正前のソースでも試してみましたが
      R3 := Ps0[Med3(xint+1,0,xssize)].rgbtRed;
の位置で停止してしまいました。
原因は分からなかったんですが、おそらく同じ原因だと思います。
今回はDHGL1.2を使用させて頂きますが、ウォレスさんの
ソースも大変勉強になりました。
また分からない事があったら教えて下さい。


メラトニン  2005-08-21 06:20:53  No: 17054

修正後のをDel7Pro+WinXPで試しました。
ちろん動きました。
Bmpファイルも色々意地悪してみましたが問題無しです。

記述ミス以外にこんな事って本当にあるのかな・・・?


ウォレス  2005-08-21 08:32:13  No: 17055

・エラーがどんなものだったでしょうか?
・エラーが起きる行(の直前とか)にブレークポイントを置いて、ブレーク後ステップ実行して行を特定したのでしょうか?
・エラーが起きるのは最初の1回目?そうでない場合には値のどれかが何らかの原因でオーバーフローしているのではないでしょうか?

私もあまり経験豊富とは言い難いのでなかなか想像できないんですが・・


ウォレス  2005-08-22 18:59:06  No: 17056

もう見ていらっしゃらないかもしれませんが、

setRGBの第2引数を-1してみてください。オーバーランしてる気がします(オイオイ

setRGB( Ps0, xssize, xint-2, R0,G0,B0);
ではなく
setRGB( Ps0, xssize-1, xint-2, R0,G0,B0);
とする。

D6Personalには、コードガードがないので・・と言い訳してみたりします。

実用化のためには、
・実数演算をなくす
・画面端処理をもう少しなんとかする(今は、一番端より外は一番端のピクセルで補填しています。これはあまり一般的でなく、黒画像で補填した方がよい)

でしょうか。

GDI+には、ライブラリに(フィルタを指定できる)拡大縮小が備わっているようです。
ただ、GDI+を使うのは結構面倒です。(Del2005なら簡単?)


junki  2005-08-24 12:23:49  No: 17057

ウォレスさん

>一般的かどうかはともかく、私の周りではバイキュービックとして(以下略)

この方が bicubic フィルタとしては一般的なようですね。
わたしも実装して前回の B-Spline の補間と比較してみました。

http://code.junki.main.jp/?eid=60070

確かボケなくて気持ちよいです。

ありがとうございました。


ウォレス  2005-08-26 18:33:00  No: 17058

御本家にお礼を述べられると照れますね。

IrfanViewのリサンプルの種類を見ると
  Hermite フィルタ (最高速)
  Triangle フィルタ
  Mitchell フィルタ
  Bell フィルタ
  Lanczos フィルタ (高画質)
がありますね。
Photoshopには線形、最近傍、バイキュービックしかないのでなかなかです。

B-splineを調べてみると、確かに、上記
http://astronomy.swin.edu.au/~pbourke/colour/bicubic/
の係数と同じでした。

各種フィルタ比較を
http://blog.goo.ne.jp/supurainhikaku
に載せましたので参考にしてください。


junki  2005-08-26 23:42:07  No: 17059

ウォレスさん

> 各種フィルタ比較を
http://blog.goo.ne.jp/supurainhikaku
> に載せましたので参考にしてください。

ありがとうございます。プロットしてみると違いが感覚的に分かりますね。

示された補間関数をすべて実装して、それを使ってイメージの拡大を試してみました。

http://code.junki.main.jp/?eid=69732

勉強になりました。ありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加