- PR -

Bitmapのカラーパレットについて

投稿者投稿内容
Hidering
常連さん
会議室デビュー日: 2007/05/22
投稿数: 33
投稿日時: 2007-07-24 09:13
お世話になります。Bitmapのカラーパレットについて質問です。

新規作成したBitmapをDrawImage(Bitmap)で表示しています。

この状態で色置換を行う際、
個々の色を
GetPixelして判定→置換元色なら置換後色でSetPixel
全て終了してから
DrawImage(Bitmap)
とすると置換処理に時間がかかってしまい現実的な方法ではありません。

パレット付きの画像の場合、パレット内の置換元色を置換後色に変更するだけで変換が終了するはずですが、
Bitmapには、パレットと色情報とを関連付ける情報がないように思われます。

パレットの色を変換するだけで色置換はされるのでしょうか?
されるのならば、パレットのない状態からパレットを生成するにはどのようにすればよいのでしょうか?

宜しくお願いします。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-24 09:33
引用:

Hideringさんの書き込み (2007-07-24 09:13) より:
パレットの色を変換するだけで色置換はされるのでしょうか?



されます。

引用:

されるのならば、パレットのない状態からパレットを生成するにはどのようにすればよいのでしょうか?



PixelFormat8bppIndexedなどのパレットをもつBitmapに変更すれば作成できます。
もちろん、それ相応に減色されます。

SetPixelやGetPixelが遅いのであれば
LockBitsを使うといいですよ。
Hidering
常連さん
会議室デビュー日: 2007/05/22
投稿数: 33
投稿日時: 2007-07-24 10:53
れいさん。ご回答ありがとうございます。

引用:
PixelFormat8bppIndexedなどのパレットをもつBitmapに変更すれば



とありますが、
その場合、Graphicsが取得できないためDrawImageが使用できなくなると思います。
DrawImageのように画像を貼り付けるような処理はLockBits等を使用して
自力で1ピクセルずつ描画しないとダメでしょうか?

引用:
LockBitsを使うといいですよ。



LockBitsを使用すると体感出来るほど処理速度は向上しますか?

宜しくお願いします。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-24 11:29
引用:

Hideringさんの書き込み (2007-07-24 10:53) より:
引用:
PixelFormat8bppIndexedなどのパレットをもつBitmapに変更すれば


とありますが、
その場合、Graphicsが取得できないためDrawImageが使用できなくなると思います。



またインデックスなしのBitmapに写しなおせばいいのではないでしょうか?

引用:

LockBitsを使用すると体感出来るほど処理速度は向上しますか?



どのくらい早いのか測定したことはありません。
処理内容によって違うでしょう。

聞くより自分の環境で測定したほうが確実ではないでしょうか?

[ メッセージ編集済み 編集者: れい 編集日時 2007-07-24 11:30 ]
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-24 13:25
引用:

れいの書き込み (2007-07-24 09:33) より:
PixelFormat8bppIndexedなどのパレットをもつBitmapに変更すれば作成できます。
もちろん、それ相応に減色されます。



あー。間違えてました。
減色は大変なんでした。
元の(Indexedでない)画像を
PixelFormat8bppIndexedなどのパレットをもつBitmapにするのは
自前で減色アルゴリズムを用意しなければならないのでした。

IndexedなbmpをIndexedじゃないbmpに直すのは
描けばいいだけですが。
Hidering
常連さん
会議室デビュー日: 2007/05/22
投稿数: 33
投稿日時: 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バイトずつでよいのでしょうか?
それとも根本的に間違っているのでしょうか。。。

宜しくお願いします。
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2007-07-24 22:11
ところで、ImageAttributes クラスと ColorMap クラスというものがあるのですが、いかがでしょうか。

// 8bppIndexed なら GIF の方が扱いやすそうだな。
れい
ぬし
会議室デビュー日: 2005/11/01
投稿数: 346
投稿日時: 2007-07-24 22:56
引用:

Hideringさんの書き込み (2007-07-24 17:15) より:
れいさん。ご回答ありがとうございます。

元の画像は256色のパレット付き画像だということが分かっています。
元画像をストリームから取得してBitmapを作成し、
そのパレットのデータを抽出するのに



Image.Paletteプロパティからパレットを取得するのではだめなのですか?

引用:

ところで、ImageAttributes クラスと ColorMap クラスというものがあるのですが、いかがでしょうか。


そうですね。
色を変えるだけだったらそれが早いですね。

引用:

// 8bppIndexed なら GIF の方が扱いやすそうだな。


減色アルゴリズム書くのがやなときに
一度GIFにして誤魔化したことが…

スキルアップ/キャリアアップ(JOB@IT)