マッピングモードについて

[戻る]
WAT 2010/02/06(土) 21:32:57
下記のようにマッピングモードを設定すると、論理単位は0.01mmになります。

 SetMapMode(デバイスコンテキスト, MM_HIMETRIC);

この場合の論理単位は何ピクセルになるのか計算みると、
0.01mmは0.000393700787401575inchiで、
1inchiは「GetDeviceCaps(デバイスコンテキスト, LOGPIXELSY)」より96なので、
「0.000393700787401575×96」を計算して、0.0377952755905512pixelになりました。

確認のため、TextOutでX軸方向に100pixelのところに文字を表示してみようとして、
下記のコードを実行したのですが、X軸方向に100pixelのところに文字が表示されません
でした。

 TextOut(デバイスコンテキスト , 2645.833333333333333333333333362, 0 , ...);
 100 ÷ 0.0377952755905512 = 2645.833333333333333333333333362

どこがおかしなところがあればご指摘いただけないでしょうか。
よろしくお願いします。

ロマ 2010/02/07(日) 14:37:27
MM_HIMETRICは、GetDeviceCapsのHORZSIZE/VERTSIZEとHORZRES/VERTRESとを使って
マッピングしています。
(SetMapModeの後にGetWindowExtEx,GetViewportExtExを使えば確認できます。)
このマッピングを物理マッピングとか、ここで得られるインチを物理インチとか呼ぶこ
とがあります。

一方、LOGPIXELSX/LOGPIXELSYは論理インチです。
両者はまったく違うものです。

WAT 2010/02/08(月) 02:09:24
ありがとうございます。

0.01mmは物理単位なので、物理単位で統一して考えないといけないということですね。

論理単位のピクセル数は、ビューポートサイズ/ウインドウサイズから求めることができ
るので、
私の環境で、GetWindowExtExとGetViewportExtExを実行し、
ウインドウサイズとビューポートサイズを求めてみました。

 ウインドウサイズ(GetWindowExtExで求める) : X成分(36800), Y成分(23000)
 ビューポートサイズ(GetViewportExtExで求める) : X成分(1920), Y成分(-1200)

よって、ビューポートサイズ/ウインドウサイズは
0.052173913043478260869565217391304になりました。
つまり、論理単位のピクセル数は0.052173913043478260869565217391304になります。

確認のため、TextOutでX軸方向に100pixelのところに文字を表示してみようとして、
下記のコードを実行し、正常な位置に文字が表示されているのを確認しました。

 TextOut(デバイスコンテキスト , 1916.6666666666666666666666666778, 0 , ...);
 100 ÷ 0.052173913043478260869565217391304 = 
1916.6666666666666666666666666778

--------------------------

もう一つ質問なのですが、論理インチとはどういうものなのでしょうか。
マッピングモードがMM_TEXTとMM_HIMETRICのときに
「GetDeviceCaps(デバイスコンテキスト, LOGPIXELSY)」を実行してみると、値は96dpi
で同じでした。
マッピングモードが異なれば、論理単位とピクセル数の関係が異なるので、
論理インチとピクセル数の関係も異なるように思うのですが同じになります。
私の考えでおかしなところがあればご指摘いただけないでしょうか。
よろしくお願いします。

ロマ 2010/02/08(月) 10:03:48
HDCで[mm]や[in.]など長さの単位とピクセルを対応させるには
2つのやり方があります。
1)GetDeviceCapsのHORZSIZEとHORZRESを使う(縦方向はVERTSIZEとVERTRES)。
2)GetDeviceCapsのLOGPIXELSXを使う(縦方向はLOGPIXELSY)。

> 0.01mmは物理単位なので、物理単位で統一して考えないといけないということです
ね。

違います。上記2つの方法のいずれでも長さの単位をピクセルに変換できます。
1)の方法を使うと、368[mm] <==> 1920[pixel]から
  0.01[mm] <==> 0.0521739[pixel],  1[inch] <==> 132.522[pixel]
2)だと 96DPI、つまり、25.4[mm] <==> 96[pixel]から
  0.01[mm] <==> 0.0377953[pixel], 1[inch] <==> 96[pixel]

MM_HIMETRICは上記の1)の方法を使うということです。

補足)
MM_HIMETRICで0,01[mm]は論理単位です。

---------------

LOGPIXELSX/LOGPIXELSYは主にディスプレイに表示する文字の大きさを決めるために
使われるらしいです。
マッピングモードに関係なく、「画面のプロパティ」で設定できます。

グラフなどでズームに関係なく文字の大きさを固定したいような場合には便利です。

WAT 2010/02/08(月) 21:01:59
ご指摘ありがとうございます。

>MM_HIMETRICで0,01[mm]は論理単位です。

0.01mmは論理単位ということですが、
「http://msdn.microsoft.com/ja-jp/library/cc428670.aspx」に
下記のように書かれていました。

・HORZSIZE
 ミリメートル(mm)単位の画面の物理的な幅。
・VERTSIZE
 ミリメートル(mm)単位の画面の物理的な高さ。
・HORZRES
 ピクセル単位の画面の幅。
・VERTRES
 ピクセル単位(ラスタ行数)の画面の高さ。
・LOGPIXELS
 画面の水平方向での、論理インチ当たりのピクセル数。
・LOGPIXELSY
 画面の垂直方向での、論理インチ当たりのピクセル数。

HORZSIZE/VERTSIZEのところに「物理的」と書いてあります。
ということは、0,01[mm]は物理単位になるように思います。

よって、MM_HIMETRICの場合、論理単位は何ピクセルになるのかを求める際、
0.01mmは物理単位で、「GetDeviceCaps(デバイスコンテキスト, LOGPIXELSY)」で
得られる96dpiは論理単位のため、96dpiは使用してはいけないということに
なるように思います。

おかしなところがあればご指摘いただけないでしょうか。
よろしくお願いします。

ロマ 2010/02/08(月) 22:55:37
とりあえず、語 LOGPIXELSX/LOGPIXELSYは無視してください。


HORZRESが「ミリメートル(mm)単位の画面の物理的な幅」というのは
Width, in millimeters, of the physical screen.です。
誤訳に近いと思いますが、
「物理サイズ」という使われ方もありますから正しいのでしょう。

一方、論理単位/デバイス単位、これは、GDIの基本用語です。
MM_HIMETRICの場合、0.01[mm]は論理座標系の単位---1ユニットです。


私が前稿で言いたかったのは、
「0.01[mm]が物理的な大きさを示しているから物理単位だ」とお思いならは、
間違いだということです。
MM_HIMETRICがHORZSIZEとHORZRESを使って、論理単位とデバイス単位を変換しています
(または、VERTSIZEとVERTRES)。

----------------
で、LOGPIXELSX,LOGPISELSYの話。

これは、「10ポイントの文字を画面の表示する時は大き目にしたい」
という感じのようです。
ところが、MM_HIMETRICなどのマッピングモードと矛盾が生じます。

MM_HIMETRICを使ったアプリケーションがMM_HIMETRICに基づいた10ポイントの
フォントを表示した場合、文字は小さくなり、ユーザーは文句を言うでしょう。

私は、このようなユーザーを恐れるので、
MM_HIMETRICは使わず、LOGPIXLESX(Y)で物理的な長さもマッピングしています。

WAT 2010/02/10(水) 01:30:40
ありがとうございます。何度もすみません。
いろいろ考えていまして、なかなか返信できませんでした。

>「0.01[mm]が物理的な大きさを示しているから物理単位だ」とお思いならは、
>間違いだということです。

コンピュータ上の長さはすべて論理単位で考えているということですね。

簡単に、論理単位が必要な理由をまとめてみました。

ディスプレイのサイズや解像度が違っても、同じ大きさの図形を描画したいとする。
そのためには、ディスプレイのサイズや解像度が違っても、
共通の長さを定義する必要がある。それが論理単位である。

そのため、ディスプレイのサイズや解像度毎に、
「□論理インチ=○ピクセル」といった対応関係を決める必要がある
(ただし、論理インチと物理インチは同じとは限らない)。

このような対応関係を決めておけば、例えば、低解像度の場合、
「□論理インチ=○ピクセル」の「○」を小さくし、
高解像度の場合、「○」を大きくすれば、低解像度と高解像度の両方の場合で
同じ大きさの図形を描画できる。

MM_HIMETRICの場合の対応関係は、HORZSIZEとHORZRESを使って求めることができる。

>で、LOGPIXELSX,LOGPISELSYの話。

マッピングモードで「□論理インチ=○ピクセル」の関係が変わってしまい、
文字がサイズが変わってしまいます。文字のサイズは固定にしたい場合は、
マッピングモードに依存しないLOGPIXELSX,LOGPISELSYを基準に、
文字のサイズを決めるということですね。

いろいろ勉強になりました。本当にありがとうございました。

古いスレッドには追加発言できません。