myugaruの色々構想中・・・!

「C#」「画像処理」「XNA未対応PCでゲームIDE作りの無謀な野望」

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  98  : 記事  0  : コメント  2322  : トラックバック  59

ニュース

myugaru
仕事(昔)=ヲタク系プログラマー~マスコミ系サポートデスク
仕事(今)=電子機器系サービス業
趣味a=パズルゲーム全般、シューティングは主に見学
趣味b=画像処理関係の勉強
趣味c=プログラミング言語の勉強
趣味d=アキバ系ヲタク
趣味e=芸能アイドル系ヲタク
d,e色の強いもう一つのブログ
最新目標=シューティングゲームを作る

わんくまりんく

わんくま同盟blog C#,VB.NET掲示板

ぶろぐつーる

あわせて読みたい

はてなりんぐ

書庫

日記カテゴリ

ギャラリ

お友達

リンク

[C#,VB.NET]Graphics.DrawImage(image,0,0)の落とし穴

サブタイトル:単に女の子の画像を張りたかっ(ry

12:00 すみません若干認識がずれていたようですので赤で修正しました

Graphics.DrawImage(image,0,0)は等倍表示を意味します。しかしこの等倍表示には2通りの意味があります。

●確認プログラム
確認のために以下のプログラムをダウンロードして実行してください。

これはDrawImage(image,0,0)で実装された単なる画像ビュアーです。

C#とVB.NETを用意してます。
http://myugaru.wankuma.com/DrawImageCheck_src.zip

実行形式も用意しました。実行には.Net Framework3.5が必要です。
http://myugaru.wankuma.com/DrawImageCheck_bin.zip

●確認手順
プログラムを実行すると単なるフォームが表示されます。↓の画像をドラッグ&ドロップしてみてください。

(c)elouai.com - Candybar 4 Doll Maker http://elouai.com/candybar4/dollmakergirl.php

ブラウザで表示されているものより拡大されましたか?手持ちの画像でもこの確認プログラムとブラウザにドラッグ&ドロップして確認してみてください。両者で見た目のサイズが違っているものはありませんか?

●原因
DrawImage(イメージ, 0, 0)は「物理サイズで等倍表示する」事を意味しています。
ですから「論理サイズでの等倍表示」を期待する人にとっては等倍と見えません。

すなわち
確認プログラムは「物理サイズ等倍表示」
ブラウザなどは「論理サイズ等倍表示」だという違いがこの現象を起こしています。

●解説
1.解像度
イメージには解像度と呼ばれるプロパティが存在しています。
水平方向の解像度=イメージ.HorizontalResolution
垂直方向の解像度=イメージ.VerticalResolution
ディスプレイにも解像度があります。例えば私の17インチディスプレイで1024×768表示時には解像度96dpiになっています。解像度は1024×768などを800×600に変えても変わるものではなくディスプレイそのものの能力値として機能しているようです。

2.画像に解像度が設定されるタイミング
画像の解像度の決まるタイミングはブラウザのような画像解像度を無視するアプリによって画像ストリームとしてファイルに保存される瞬間です。
ほとんどの場合は使っているディスプレイの解像度がその画像に設定されます。

以下のリンクを右クリックから「対象をファイルに保存」でPCへ保存してください。
http://myugaru.wankuma.com/image/20080309_50.bmp
この場合は画像ではなく単にファイルとして保存されるので本来の画像に設定された解像度が維持されます。
保存した画像ファイルをExplorer上で右クリックしてプロパティを確認してみてください。
この画像が解像度50dpiで作成されているのだというのが確認できます。

次に先ほどの女の子の画像上を右クリックして「名前を付けて画像を保存」でPCへ保存してみてください。
お使いのディスプレイに合わせてその解像度が設定されるかと思います。
先ほど同様に保存した画像ファイルのプロパティを確認してみてください。
(ブラウザによっては50dpiのままのものもあるかもしれません。IEはディスプレイ解像度に変わりました)

※ディスプレイ解像度はコントロールパネルの画面などから確認ができます。
 

2.物理サイズでの等倍
物理サイズというのは画像のインチ数でのサイズの事を指します。

上の確認プログラムの動作はこの物理サイズを等倍とするプログラムになっています。

先ほどの女の子の画像の論理サイズ(ピクセルサイズ)は横150×縦290です。

物理サイズ横=150÷50=3インチ
物理サイズ縦=290÷50=5.8インチ

の画像だといえます。

それを96dpiのディスプレイに物理サイズで等倍表示するとどういう事が起こるかというと、

横ピクセル=3×96=288
縦ピクセル=5.8×96=556.8

つまりディスプレイ上で288×556ピクセルで表示される事を意味します。
これは論理サイズでは拡大表示となります。

物理サイズでの等倍のシンプルな確認方法はディスプレイ解像度を変えてみる事です。
試しにディスプレイを1024×768や800×600などに変えてみてください。
物理サイズでの等倍を行うプログラムではその見た目のサイズは変わりません。

ディスプレイの能力によって96dpiが決まるので1024×768を800×600にする行為はこの能力の変更には直結していません。したがってこの場合見た目のサイズも変わってしまうという結果になります。確認が不足しておりました。すみません。

3.論理サイズでの等倍
論理サイズというのは画像のピクセル数でのサイズの事を指します。
ブラウザの動作は論理サイズを等倍とするプログラムになっています。
DrawImageのサイズ指定バージョンは画像の解像度を無視しディスプレイ解像度で表示することを意味しています。
DrawImage(image,0,0,image.Width,image.Height)は論理サイズでの等倍に利用できます。(可能な人は先ほどのプログラムを修正して確認してください)
論理サイズでの等倍の場合はディスプレイ解像度で表示されるわけですから、当然ディスプレイの解像度を1024×768や800×600に変えるとその物理サイズであるインチ数でのサイズは変わる事になります。これは前述の通り論理サイズ等倍だけの話ではありませんでした。すみません。
先の画像のように意図的に50dpiを設定している画像だったなら50dpiのディスプレイというのは見かけませんので、ほとんどの場合は製作者の意図したサイズで表示されていないという事を意味しています。この意味は多少あっていると思われます。

●対策
1.画像の解像度を変更する方法
残念ながら通常のWindows付属ペイントだとこれは出来ません。
画像解像度を簡単に変えることが出来るフリーのペイントツールがあります。
http://www.getpaint.net/
以下のように解像度のみ修正できます。
・[イメージ]→[キャンバスサイズ]の解像度の数値をかえる

2.とりあえず論理サイズの方が一般的?
一般に普及しているブラウザやペイントツールの動作を見てもディスプレイへの表示時はほとんどが画像の解像度を無視しているようです。
なので画像を単純にブラウジングするような場合にはDrawImage(image,0,0,image.Width,image.Height)とサイズ指定して論理サイズ等倍を意識したつくりにする方が良いように思います。

あまり需要は無いのかもですが、何かのプログラムでディスプレイ解像度に依存しない(つまり物理サイズが必要な)局面が出てきた場合にはこのエントリーの事を思い出して欲しいと思います。

物理サイズ等倍というのは見た目での等倍実現に寄与していないようです。現在のディスプレイの能力に見合ったサイズとしてそのサイズを表現するという意味合いで使われているように思います。不確かな記述をしてしまい申し訳ありませんでした。

最後に・・・ここまで書いてからふっと見ると・・・ほとんどここに書いてました。ヘルプも空気も嫁てません。。→http://msdn2.microsoft.com/ja-jp/library/558kfzex(VS.80).aspx
・・・開き直って私なりにまとめたのはこれで良しとしときます。

投稿日時 : 2008年3月9日 10:20

コメント

# re: [C#,VB.NET]Graphics.DrawImage(image,0,0)の落とし穴 2008/03/09 10:35 かずき
加えてきちんとサイズを指定してDrawImageを呼び出したほうが早い…みたいな情報をどこかでみたかも…

# re: [C#,VB.NET]Graphics.DrawImage(image,0,0)の落とし穴 2008/03/09 10:41 myugaru
To かずきさん
さっそくのコメントありがとうございます。
おっしゃるとおり画像から解像度を読み出して掛け算とかをしないわけですからサイズ指定した方が速度は向上する気がしますね。

# re: [C#,VB.NET]Graphics.DrawImage(image,0,0)の落とし穴 2008/03/09 10:57 かずき
.NET Framework 3.5 + VistaマシンでうちのHPの犬の画像を10000回DrawImageさせてみたけど、どっちも変わらんかったとですorz


# re: [C#,VB.NET]Graphics.DrawImage(image,0,0)の落とし穴 2008/03/09 11:01 myugaru
To かずきさん
引数2つスタックに積み降ろしするオーバーヘッドで相殺っすかねww
ご確認ありがとうございました!

# re: [C#,VB.NET]Graphics.DrawImage(image,0,0)の落とし穴 2008/03/09 21:58 junki

myugaru さん、こんばんは。

なるほど、永年の疑問が氷解しました。

DrawImageUnscaled( ) が DrawImage(bmp, x,y) のラッパだとしても、これは GDI+ がそういう方針で等倍描画する方針なら納得ですね。 DrawImageUnscaled( ) は、コードを書いた人が明確に当倍表示することを示したコードを書くためにあると。そうすると可読性がある程度上がります。

これからは、ピクセルとしての当倍表示を意図するときは

DrawImage(bmp, x, y, width, height)

とすることにします。

ほんとうにありがとうございました。


# re: [C#,VB.NET]Graphics.DrawImage(image,0,0)の落とし穴 2008/03/09 23:40 myugaru
To junkiさん
こんばんわ、お役に立ててこちらこそ光栄です。
また何か発見したらエントリーします!今後ともよろしくお願いします。

# re: [C#,VB.NET]Graphics.DrawImage(image,0,0)の落とし穴 2011/02/19 9:04 miyaw
myugaru さん。

詳細な解説、助かりました。
ありがとうございます!!

# SozYJkacyOmiwV 2021/07/03 3:03 https://amzn.to/365xyVY
Very good article.Really looking forward to read more. Really Great.

# re: [C#,VB.NET]Graphics.DrawImage(image,0,0)????? 2021/08/08 6:20 hydrochloroqine
is chloroquine phosphate the same as hydroxychloroquine https://chloroquineorigin.com/# hydroxychloroquine drug

# グランドセイコーコピー 2021/11/24 23:48 giydqlze@ybb.ne.jp
母へのプレゼントとして利用しました。男性なので女性物の品揃えがよいかどうかは分からないので「品揃え」は3点としましたが、ほかはずべて5点です。
私は注文からいかに早く発送していただくかを一番重視しておりますが、注文日の翌日にすぐ発送され、お礼のメールも届きましたのでネット通販としては十分な対応だと思います。
また何かあれば利用したいと思います。

# order hydroxychloroquine online cheap alberta 2022/12/26 10:55 MorrisReaks
http://hydroxychloroquinex.com/ plaquenil hydroxychloroquine

Post Feedback

タイトル
名前
Url:
コメント