2009-11-05 6 views
6

フルカラーのJPGイメージを取り込み、その色をインデックス付きパレットに再マップする必要があります。パレットは、データベースから取り込まれた特定の色で構成されます。画像の各色をインデックスに「最も近い」値にマップする必要があります。私は、 "最も近い"値を比較して計算するためのアルゴリズムが異なっていると確信しています。 C#、.NETマネージドコードライブラリのみを探しています。32-BPPから8-BPPへの変換(C#)

(それは我々がボタン120のまたはそう特定の色を有し、そして我々はコラージュを作るために、それらの120色に任意の画像をマッピングするプロセスにおいて使用されます)。

+0

+1、素敵な質問! –

答えて

2

このプロセスはQuantizationと呼ばれます。各色は3つのパックされた値を表すので、この問題を解決するにはOctreesを使用する必要があります。

チェックアウトのコード例でこのarticle

記事はイメージのための究極のパレットを得ることに焦点を当てているが、あなたのプロセスにのみ与えられたパレットに近い最も使用される色を減らし、第二部のために逆になります。

+0

.NET Frameworkには量子化ライブラリが組み込まれていますか? –

+0

私は.NET(私はLinuxの男です)についての知識はなく、私は自分自身でTMをやることに慣れています。申し訳ありませんが私は詳細を提供することはできません。 – LiraNuna

0

大きな.NETプロジェクトでこれを行う必要がありました。そこは何もそれのための枠組みの中でませんが、この記事では、すぐに解決策に私を導いた:http://codebetter.com/blogs/brendan.tompkins/archive/2004/01/26/6103.aspx

+0

あなたのリンクは死んでいます。 –

+0

「 '。」を削除したようです。彼の名前で。これは動作します:http://codebetter.com/brendantompkins/2004/01/26/use-gdi-to-save-crystal-clear-gif-images-with-net/ – Nestor

0

をJPEGワードが警鐘を鳴らす必要があります。イメージは、既に大きく量子化された色空間に存在する可能性が非常に高く、さらにリサンプリングすると、エイリアシングが発生する可能性があります。可能であれば、圧縮されていない画像から作業してこの効果を減らしてください。

あなたの質問への答えはイエスです - あなたが別の形式で画像を保存することができます - しかし、私はネイティブ機能は、非常に複雑な要件のように聞こえる何のために適切であるかはわかりません。イメージのコレクションからカラーパレットを定義できる場合、出力の品質が向上する可能性があります。

使用「GDI +は、.NETとクリスタルクリアなGIF画像を保存するために」と題するすでに参照ブログのエントリは、コードへの便利な参照が含まれています。

3

GDIに役立つものはありません。マイクロソフトにとっては、索引付けされたイメージがあまりにも後方の技術であるようです。できることは、インデックス付きのイメージファイルを読み書きすることだけです。

画像の色を量子化するときに、2つのステップが通常あります
1)画像に最適なパレットを探す(カラー量子化)
2)見つかったパレット(カラーマッピングにソースsolors地図)

私が理解していることから、あなたはすでにデータベースにパレットを持っています。つまり、最も難しい部分があなたのために行われました。 24ビットカラーを指定されたパレットカラーにマップするだけです。開始パレットがない場合は、量子化アルゴリズムを使用して自分で計算する必要があります。OctreesまたはMedian Cutが最もよく知られています。メディアンカットはより良い結果をもたらしますが、実装するのがより遅くて難しく、細かく調整します。

色をマッピングするには、ソースカラーからすべてのパレットカラーまでの距離を計算し、最も近いものを選択するのが最も簡単なアルゴリズムです。青が少ない重量を持つように

float ColorDistanceSquared(Color c1, Color c2) 
{ 
    float deltaR = c2.R - c1.R; 
    float deltaG = c2.G - c1.G; 
    float deltaB = c2.B - c1.B; 
    return deltaR*deltaR + deltaG*deltaG + deltaB*deltaB; 
} 

また、特に30/59/11がまったく動作しません、他のそれは恐ろしい結果が得られますが、それにあまりにも船外に行っていない、チャンネルをponderateことができます。

float ColorDistanceSquared(Color c1, Color c2) 
{ 
    float deltaR = (c2.R - c1.R) * 3; 
    float deltaG = (c2.G - c1.G) * 3; 
    float deltaB = (c2.B - c1.B) * 2; 
    return deltaR*deltaR + deltaG*deltaG + deltaB*deltaB; 
} 

すべてのソースとパレットの色についてそのものを呼び出し、最小値を見つけます。地図を表示しているときに結果をキャッシュすると、非常に高速になります。

また、元の色は、バンディングやプレーン領域が作成されず、画像の細部が失われないようにパレットカラーに適合することはめったにありません。これを避けるために、ディザリングを使用することができます。最も簡単なアルゴリズムと最良の結果をもたらすアルゴリズムは、誤差拡散ディザリングです。

色をマッピングしたら、ビットマップを手動でロックし、そこにインデックスを書き込む必要があります.Netでは、インデックス付きイメージに書き込むことはできません。