18

C/C++ で 32 ビット RGBA イメージをスケーリングするコードを書いています。ある程度成功したいくつかの試みを書いたことがありますが、それらは遅く、最も重要なことは、サイズ変更された画像の品質が受け入れられないことです。

OpenGL (つまり、ビデオ カード) でスケーリングされた同じ画像とルーチンを比較したところ、品質が大きく異なります。私はGoogleコードを検索し、いくつかの光を当てると思われるもの(SDL、Allegro、wxWidgets、CxImage、GD、ImageMagickなど)のソースツリーを精査しましたが、通常、それらのコードは複雑であちこちに散らばっているか、いじられていますアセンブラであり、コメントはほとんどまたはまったくありません。また、ウィキペディアや他の場所で複数の記事を読みましたが、必要なものについて明確な説明が見つかりません。補間とサンプリングの基本的な概念は理解していますが、アルゴリズムを正しく理解するのに苦労しています。1 つのルーチンを外部ライブラリに依存したくないので、画像形式に変換して元に戻す必要はありません。それに、とにかく自分でそれを行う方法を知りたいです。:)

以前にスタック オーバーフローに関する同様の質問を見たことがありますが、実際にはこのように回答されていませんでしたが、正しい方向に私を微調整するのを手伝ってくれる人がそこにいることを願っています. たぶん、いくつかの記事や疑似コードを教えてください...私が学び、実行するのに役立つものなら何でも。

これが私が探しているものです:

  1. アセンブラはありません (複数の種類のプロセッサ用に非常に移植性の高いコードを書いています)。
  2. 外部ライブラリへの依存はありません。
  3. 私は主にスケール ダウンに関心がありますが、後でスケール アップ ルーチンも作成する必要があります。
  4. 結果の品質とアルゴリズムの明快さが最も重要です (後で最適化できます)。

私のルーチンは基本的に次の形式を取ります。

DrawScaled(uint32 *src, uint32 *dst, 
      src_x, src_y, src_w, src_h, 
      dst_x, dst_y, dst_w, dst_h );

ありがとう!

更新:明確にするために、画像をぼやけさせるダウンスケーリング用のボックスリサンプルよりも高度なものが必要です。私が望むのは、バイキュービック アップスケーリング アルゴリズムとは逆の、ある種のバイキュービック (またはその他の) フィルターであると思います (つまり、各宛先ピクセルは、物事をシャープに保つ重み付けアルゴリズムと組み合わせて、寄与するすべてのソース ピクセルから計算されます。

これは、wxWidgets BoxResample アルゴリズムから取得したものと、55x55 にスケーリングされた 256x256 ビットマップで必要なものの例です。

  • www.free_image_hosting.net/uploads/1a25434e0b.png

そして最後に:

  • www.free_image_hosting.net/uploads/eec3065e2f.png

元の 256x256 画像

4

10 に答える 10

2

元の画像が表示されたので、OpenGLは最近傍アルゴリズムを使用していると思います。サイズを変更するのが最も簡単な方法であるだけでなく、最も速い方法でもあります。唯一の欠点は、元の画像に細部があると非常に粗く見えることです。

アイデアは、元の画像から等間隔のサンプルを取得することです。あなたの場合、256のうち55、または4.6545ごとに1つ。数値を丸めて、選択するピクセルを取得します。

于 2008-12-10T03:20:53.200 に答える
2

wxWidgets の実装は、必要に応じて簡単に変更できることがわかりました。すべて C++ であるため、移植性に問題はありません。唯一の違いは、それらの実装が unsigned char 配列 (画像を処理する最も簡単な方法であることがわかりました) で動作し、RGB のバイト オーダーと別の配列のアルファ コンポーネントを使用することです。

wxWidgets ソース ツリーの「src/common/image.cpp」ファイルを参照すると、ボックス サンプリング メソッド「wxImage::ResampleBox」を使用するダウンサンプラー関数と「wxImage::」と呼ばれるアップスケーラー関数があります。リサンプルバイキュービック」。

于 2008-12-09T15:18:05.497 に答える
2

画像をリサンプリングするためのかなりシンプルでまともなアルゴリズムはバイキュービック補間です。ウィキペディアだけでも、これを実装するために必要なすべての情報があります。

于 2008-12-09T15:21:09.453 に答える
2

OpenGL がベクトル ドメインでスケーリングを行っている可能性はありますか? もしそうなら、ピクセルベースのスケーリングがそれに近い品質になる方法はありません. これは、ベクターベースの画像の大きな利点です。

バイキュービック アルゴリズムは、シャープネスとアーティファクトに合わせて調整できます。リンクを見つけようとしています。見つけたら編集します。

編集: 私が考えていたのは Mitchell-Netravali の作品で、このリンクの下部で参照されています。

http://www.cg.tuwien.ac.at/~theussl/DA/node11.html

バイキュービックの代替手段として、ランチョスのリサンプリングを検討することもできます。

于 2008-12-09T18:00:02.300 に答える
1

Intelには、Intelファミリプロセッサ用に最適化された高速補間アルゴリズムを提供するIPPライブラリがあります。とても良いですが、無料ではありません。次のリンクを見てください。

Intel IPP

于 2008-12-09T16:33:58.357 に答える
1

私たちの最愛のホストからの一般的な記事: Better Image Resizing、さまざまなアルゴリズムの相対的な品質について説明しています (別の CodeProject 記事へのリンクがあります)。

于 2008-12-09T16:12:16.183 に答える
1

アルゴリズムだけでなく何か準備が必要な場合は、 Adobe Generic Image Library ( http://opensource.adobe.com/wiki/display/gil/Downloads )を使用してみてください。


抜粋: http://www.catenary.com/howto/enlarge.html#c

拡大または縮小 - C ソース コードには、32 ビット Windows v 5.3 以降用の Victor 画像処理ライブラリが必要です。


int enlarge_or_reduce(imgdes *image1)
{
   imgdes timage;
   int dx, dy, rcode, pct = 83; // 83% percent of original size

   // Allocate space for the new image
   dx = (int)(((long)(image1->endx - image1->stx + 1)) * pct / 100);
   dy = (int)(((long)(image1->endy - image1->sty + 1)) * pct / 100);
   if((rcode = allocimage(&timage, dx, dy,
      image1->bmh->biBitCount)) == NO_ERROR) {
      // Resize Image into timage
      if((rcode = resizeex(image1, &timage, 1)) == NO_ERROR) {
         // Success, free source image
         freeimage(image1);
         // Assign timage to image1
         copyimgdes(&timage, image1);
         }
      else // Error in resizing image, release timage memory
         freeimage(&timage);
      }
   return(rcode);
}

この例では、画像領域のサイズを変更し、元の画像を新しい画像に置き換えます。

于 2008-12-09T15:44:42.497 に答える
1

あなたが本当に理解するのが難しいのは、画像の適切なリサンプリングに関連する離散 -> 連続 -> 離散フローのようです。必要な洞察を得るのに役立つ優れた技術レポートは、Alvy Ray Smith のA Pixel Is Not A Little Squareです。

于 2008-12-09T19:41:03.033 に答える
0

フォローアップとして、Jeremy Rudd がこの記事を上に投稿しました。フィルター処理された 2 パスのサイズ変更を実装します。ソースは C# ですが、試してみるために移植できるほど明確に見えます。昨日、非常によく似た C コードを見つけましたが、理解するのははるかに困難でした (非常に悪い変数名)。ある程度の作業はできましたが、非常に遅く、良い結果が得られなかったため、適応にエラーがあると思いました。これを参考にゼロから書いたほうがうまくいくかもしれないので、試してみます。

しかし、2 パス アルゴリズムがどのように機能するかを考えると、おそらく 1 パスでも、より高速な方法はないのではないでしょうか?

于 2008-12-09T20:07:28.817 に答える
0

あらゆる種類の再スケーリング フィルターを実行するImageMagickを見てください。

于 2008-12-09T17:57:35.957 に答える