- - PR -
[C#] KnownColorの対応パレット(Bitmapクラス)を知りたい
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2006-09-22 09:46
BitmapオブジェクトのPaletteのどこに任意のKnownColorがあるかを知る簡便な方法はありますか?
Palette.Entries[]を順番に照合して、KnownColorとパレット番号の対応を得ています。 この方法でも問題ありませんが、よりエレガントな解決方法はありますか? Bitmapクラスに見落としている便利なメソッド(プロパティ)があるかも知れないと思い 質問します。 --------------------------- // 256諧調(PixelFormat.Format8bppIndexed)のBitmap専用メソッド // KnownColorのColorPalette番号を得る // 失敗したら-1を返す int GetPaletteEntriesIndex(KnownColor k,Bitmap bmp) { Color c = Color.FromKnownColor(k); int argb = c.ToArgb(); ColorPalette p = bmp.Palette; int ans = -1; for(int i = 0;i < 256;i++) { if(argb == p.Entries[i].ToArgb()) { ans = i; } } // 適合するパレット番号がなければ-1を返す return ans; } | ||||||||||||
|
投稿日時: 2006-09-26 21:46
エレガントな方法より、自分が理解できる方法の方が良いと思うのですが。。。
2点ほど。 なぜ、for 文でループする範囲が 256 固定なのでしょう?これが 256 に固定されているというのは、誰が保証するのでしょう? 何度もこのルーチンが呼ばれるなら、色情報をハッシュテーブル化しておけば、何度も比較することはない。違いますか? _________________ | ||||||||||||
|
投稿日時: 2006-09-26 22:49
8bitビットマップ限定であれば、ひろしさんのロジックがスマートな気がします。
そういえば256色ってパレット面倒だったなぁ・・・とちょっと懐かしい気分です。 | ||||||||||||
|
投稿日時: 2006-09-27 12:58
ご回答ありがとうございます。
256諧調固定である理由 は単に処理の簡便化と速度アップのためです。 256諧調の場合BitmapDataが1画素1byteなのでアニメーション表示等応用性が要求 される場合書き換え処理が楽になるからです。 数色あるいは最大でも数十色程度の色の組み合わせ(SystemColorやKnownColor等) で画面(PictureBox)に簡単な図面やチャートを描きたい場合が時々あります。 特殊事情としては静止画では無く動画の図形やチャートを描きたい時もあります。 呼び出し側のソースではRed,Green,Pink等良く知られた色名称で記述しておいて、 Bitmapインスタンスが生成した時に変換テーブルを作成します。 その時の処理ロジックを今回質問しました。 | ||||||||||||
|
投稿日時: 2006-09-27 13:07
効果はほとんどない。 | ||||||||||||
|
投稿日時: 2006-09-27 14:18
こんにちは。
これだと、Jitta さんの質問の回答にはなりえないですよね。
を質問されているので
といった感じが答えになると思います。 ただ、それでも私であれば後々のメンテナンス性を考えて for(int i = 0; i < p.Entries.Length; i++) のように書くと思いますし、むしろ foreach で回すほうがエレガントと言えばエレ ガント…かなあ?とか。 また // 適合するパレット番号がなければ-1を返す return ans; のコメントは // 適合するパレット番号がなければ-1を返す int ans = -1; の場所の方がいいのじゃないかとか、まぁ処理とまったく関係ないところも気にな ります(個人的嗜好なのであまり気にしなくても良いかもしれません)。 むしろ「速度アップ」ということであれば
を一番初めに検討すべきかも…とは思いますが。 あと、ものすごく強引な手法(素人にはオススメできない)として、こんなのもあるかもしれません。
でも私ならこんなの業務のコードには実装しませんけど(じゃあ書くなよ)。 _________________ ぽぴ王子@わんくま同盟 ぽぴ王子の人生プログラミング中 / ぽぴンち。 | ||||||||||||
|
投稿日時: 2006-09-27 20:16
回答ありがとうございます。
高速処理が必要なのでLockBits/UnlockBitsを前提に話をしていました。 GetPixel/SetPixelは非常に遅いので、いつもBitmapDataを直接加工しています。 その場合1画素1byteだと2,3,4byteの場合より、書き込むデータ量が1/2〜1/4になり、 またポインタのアドレス計算のための乗算の回数が削減できます。 そのような時には確かに効果があります。 説明足らずで混乱させてすみませんでした。 本題から離れますが、forループの評価部分でプロパティ使用は パフォーマンス低下が発生することがあるので注意が必要です。 以前、 for(int i = 0; i < bmp.Size; i++) のような記述をして痛い目にあったことがあります。(処理が遅くて) int size = bmp.Size; for(int i = 0; i < size; i++) Paletteの場合はループが高々256回なので問題ないと思いますが、 それから、 (使うかどうか別としても)このコード面白いですね。私は発想できませんでした。 // Color c = Color.FromKnownColor(k); // KnownColorからColorを取得 // Color c2 = Color.FromArgb(c.ToArgb()); // ARGB成分から改めてColorを作成 // return Array.IndexOf(bmp.Palette.Entries, c2); | ||||||||||||
|
投稿日時: 2006-09-27 21:43
ぽぴ王子さんに言われてしまった。。。
例えば、「同じプログラム中で作っているビットマップしか使わないから」であれば、回答といえます。 で、たぶん、そういうことなのでしょう。
msdn 見たところ、未定義の KnownColor が判別できませんでした。if 文は、C# では enum と整数を比較できない、とかっていう警告が出るはずなので、適切に直すように。
痛い目を見たコードは、提示できますか? C# であれば、そのようなことは発生しないと思います。 VB6.0 以前であれば、毎回参照をたどるので、ループ回数が多いほど遅くなると思います。 _________________ |