- - PR -
Bitmapのカラーパレットについて
投稿者 | 投稿内容 | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-07-24 09:13
お世話になります。Bitmapのカラーパレットについて質問です。
新規作成したBitmapをDrawImage(Bitmap)で表示しています。 この状態で色置換を行う際、 個々の色を GetPixelして判定→置換元色なら置換後色でSetPixel 全て終了してから DrawImage(Bitmap) とすると置換処理に時間がかかってしまい現実的な方法ではありません。 パレット付きの画像の場合、パレット内の置換元色を置換後色に変更するだけで変換が終了するはずですが、 Bitmapには、パレットと色情報とを関連付ける情報がないように思われます。 パレットの色を変換するだけで色置換はされるのでしょうか? されるのならば、パレットのない状態からパレットを生成するにはどのようにすればよいのでしょうか? 宜しくお願いします。 | ||||||||||||
|
投稿日時: 2007-07-24 09:33
されます。
PixelFormat8bppIndexedなどのパレットをもつBitmapに変更すれば作成できます。 もちろん、それ相応に減色されます。 SetPixelやGetPixelが遅いのであれば LockBitsを使うといいですよ。 | ||||||||||||
|
投稿日時: 2007-07-24 10:53
れいさん。ご回答ありがとうございます。
とありますが、 その場合、Graphicsが取得できないためDrawImageが使用できなくなると思います。 DrawImageのように画像を貼り付けるような処理はLockBits等を使用して 自力で1ピクセルずつ描画しないとダメでしょうか?
LockBitsを使用すると体感出来るほど処理速度は向上しますか? 宜しくお願いします。 | ||||||||||||
|
投稿日時: 2007-07-24 11:29
またインデックスなしのBitmapに写しなおせばいいのではないでしょうか?
どのくらい早いのか測定したことはありません。 処理内容によって違うでしょう。 聞くより自分の環境で測定したほうが確実ではないでしょうか? [ メッセージ編集済み 編集者: れい 編集日時 2007-07-24 11:30 ] | ||||||||||||
|
投稿日時: 2007-07-24 13:25
あー。間違えてました。 減色は大変なんでした。 元の(Indexedでない)画像を PixelFormat8bppIndexedなどのパレットをもつBitmapにするのは 自前で減色アルゴリズムを用意しなければならないのでした。 IndexedなbmpをIndexedじゃないbmpに直すのは 描けばいいだけですが。 | ||||||||||||
|
投稿日時: 2007-07-24 17:15
れいさん。ご回答ありがとうございます。
元の画像は256色のパレット付き画像だということが分かっています。 元画像をストリームから取得してBitmapを作成し、 そのパレットのデータを抽出するのに 以下のようなプログラムを作成しましたが 上手くパレットが行きません。 使用した画像によって異なるとは思いますが、 (a,r,g,b)=(0,0,0,0)か(255,255,255,255)のデータしか取得できませんでした。 (colPalette.Addが1度呼ばれただけ) Dim ms As New System.IO.MemoryStream(bytBuffer) ms.Flush() Dim bmpBuffer As New Bitmap(ms, True) (省略) Dim bitmapdata As System.Drawing.Imaging.BitmapData = _ bmpBuffer.LockBits(wkrect, _ Imaging.ImageLockMode.ReadOnly, _ Imaging.PixelFormat.Format32bppArgb) Dim intSize As Integer = bitmapdata.Height * bitmapdata.Stride Dim buffer(intSize - 1) As Byte System.Runtime.InteropServices.Marshal.Copy(bitmapdata.Scan0, buffer, 0, intSize) Dim a As Integer Dim r As Integer Dim g As Integer Dim b As Integer Dim clrTmp As Color Dim strIndex As String For intOffSet As Integer = 0 To intSize - 1 Step 4 a = buf(intOffSet + 0) r = buf(intOffSet + 1) g = buf(intOffSet + 2) b = buf(intOffSet + 3) clrTmp = Color.FromArgb(a, r, g, b) strIndex = CStr(r) & "," & CStr(g) & "," & CStr(b) If a = 255 Then If Not colPalette.Contains(strIndex) Then colPalette.Add(clrTmp, strIndex) End If End If Next bmpPngBuffer.UnlockBits(bitmapdata) いろいろ調べましたが、どこが間違っているのか分かりません。 不安なのは、PixelFormat.Format32bppArgbの時のデータの構造が どこにも記載されていなかったので PixelFormat.Format24bppRgbのデータから予測して作成しました。 データ構造はAlpha、Red、Green、Blueの順に1バイトずつでよいのでしょうか? それとも根本的に間違っているのでしょうか。。。 宜しくお願いします。 | ||||||||||||
|
投稿日時: 2007-07-24 22:11
ところで、ImageAttributes クラスと ColorMap クラスというものがあるのですが、いかがでしょうか。
// 8bppIndexed なら GIF の方が扱いやすそうだな。 | ||||||||||||
|
投稿日時: 2007-07-24 22:56
Image.Paletteプロパティからパレットを取得するのではだめなのですか?
そうですね。 色を変えるだけだったらそれが早いですね。
減色アルゴリズム書くのがやなときに 一度GIFにして誤魔化したことが… |