ビットマップに別画像を描いたものをgif形式で保存すると画像が粗くなる

解決


ケイジ  2009-06-30 20:04:59  No: 142124

VB2008を使用していますが、以下の方法で、空のビットマップを用意し、別画像ファイル(gif)を読み込んで
それを空のビットマップ上に描きたいと思っています。

Dim bitmap1 As Bitmap = New Bitmap(100, 100)
Dim bitmap2 As Bitmap = New Bitmap(別画像ファイル名(gif))
Dim g As Graphics = Graphics.FromImage(bitmap1)
g.Clear(Color.White)
g.DrawImage(bitmap2, 20, 30, 50, 50)  '適当の場所に描画する
g.Dispose()
bitmap1.Save(保存ファイル名(gif), Imaging.ImageFormat.Gif)

しかし、作成された画像と、描画に使用した元の画像とを比較すると、作成された画像のグラデーションの部分が
元画像に比べて粗くなっています。
元画像もgif形式なのですが、何が問題なのでしょうか?
ちなみにpng形式で作成画像を保存すると特に問題はありませんでした。
どうぞアドバイスをよろしくお願いします。


魔界の仮面弁士  2009-06-30 20:19:12  No: 142125

GIF で使用可能な色数は、最大で256色までです。

元画像の色数は幾つですか? もしもフルカラーなのであれば、
元画像を 8bit 以下のパレットカラーに変更してから試すか、
もしくは、より多くの色数を使える画像形式(PNG 等)に
切り替える事を検討してみてください。


Hongliang  2009-06-30 21:29:02  No: 142126

New Bitmap(100, 100)
で作った Bitmap は 32bpp で作られます。
それを 8bpp しか使えない GIF に保存する場合、Bitmap が「現在何色持ってようが」減色処理が行われます。たとえ元画像が 1 色ベタ塗りでも(色次第ですけど)。これは仕様なのでどうしようもありません。
この New Bitmap の引数に PixelFormat.Format8bppIndexed を追加すれば保存時に減色処理が行われることはなくなりますが、代わりに Graphics.FromImage するのが不可能になり、LockBits を使って直接バイトデータを読み書きするしか無くなります。

GIF は使わない、が一番楽ですが……。


ケイジ  2009-06-30 21:43:32  No: 142127

魔界の仮面弁士様、早速のご回答ありがとうございました。
元画像の色数は少ないと思います。
(画像は、赤色のボールをイメージして頂ければ分かりやすいと思いますが、球体に光があたってその部分が
だんだん白くなるようにグラデーションをかけています。)
色数をどうやって調べればよいか理解していませんが、そもそも元画像はgif形式なので、
問題はないと思っています。画像のプロパティで、ビットの深さ=8となっていました。
元々白地のビットマップにこのgifファイルの画像だけをグラフィックスで描画しているので、
色数が膨大に増えるということはないはずなのですが、どうでしょうか?
何かビットマップなどのプロパティ設定またはインスタンス作成時のコンストラクタの引数設定を
しないといけないのでしょうか?
どうぞアドバイスをよろしくお願いします。


ケイジ  2009-06-30 22:10:51  No: 142128

Hongliang様、ご回答ありがとうございました。
入れ違いになり申し訳ございません。
ところで、ご提案のLockBitsはどういったものでしょうか?
vb.net LockBitsで検索しましたが、勉強不足でよく理解できません。
何か参考になるサイトはありますでしょうか?
よろしくお願いいたします。


ケイジ  2009-07-04 01:08:19  No: 142129

とりあえず、gifファイルを作成することについて、以下のURLを参考に、以下の所まで理解しました。
http://q.hatena.ne.jp/1179395002

・空のビットマップをPixelFormat.Format8bppIndexedで作成する
'このビットマップのパレット(Palette.Entries(0〜255))に、使用する色を設定する。
・LockBitsメソッドを使用して、このビットマップのBitmapDataを取得する。
・System.Runtime.InteropServices.Marshal.Copyメソッドで、このビットマップのバイト配列を取得する。
・ビットマップの各ピクセルに該当する、上記で取得したバイト配列の値を使用するパレットのインデックスに変更する。
・System.Runtime.InteropServices.Marshal.Copyメソッドで、取得した配列を変更する。
・UnlockBitsメソッドで、LockしたビットマップをUnlockする。

今後の課題では、パレットの作成(減色処理)ですが、これはもう少し自分で調べることとし、このスレは終了とさせて頂きます。
ありがとうございました。


Hongliang  2009-07-04 01:17:15  No: 142130

元が GIF 画像なら、その Bitmap オブジェクトの Palette をそのまま代入するだけで、減色も不要ですけどね。


ケイジ  2009-07-04 06:00:59  No: 142131

Hongliang様、コメントありがとうございました。
しかしながら、目指しているものは、複数のgif等の画像を新しいビットマップ上に合成してgif化するというものなので、
この場合は減色が必要となってくると思います。


genex  URL  2009-09-04 19:08:44  No: 142132

もう解決されたかも知れませんが一応自分も同じように困ったので
いろいろと試して見た結果、以下の手順で割と簡単に?いけました

FreeImageNetというライブラリを使用しますが
かなり優秀な減色をしてくれます。

http://d.hatena.ne.jp/genex/20090903


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加