- PR -

PrintDocument.PrintPageイベントを使用した画像印刷について

1
投稿者投稿内容
たけっち
会議室デビュー日: 2006/11/28
投稿数: 4
投稿日時: 2006-11-28 17:22
環境:VB2005

いくつかの画像を合成してを印刷したいと考えています。
それぞれをPictureBoxで表示しておいて、印刷時にPrintPageイベントで
PictureBoxに表示した画像を取得して合成、印刷しているのですが、
用意したBitmapへの書き込みがかなり拡大されて書き込まれてしまい
困っています。(画像の左上の必要な部分のみ書き込まれる)

流れとして、
印刷したいサイズのBitmapを作成
そのBitmapへDrawImageを使って描画
BitmapをPrintPageのe.Graphics.DrawImageで描画
のようにしています。

以下が拡大されてしまうコードです。

Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

Dim pic As PictureBox = Me.PictureBox1
Dim pic2 as PictureBox = Me.PictureBox2

Const intW As Integer = 247
Const intH As Integer = 339
Const BarWidth As Integer = 29

Dim b As Bitmap = New Bitmap(intW, intH, e.Graphics) '※ここで悩んでます。
Dim g1 As Graphics = Graphics.FromImage(b)
g1.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic

Dim rect As New Rectangle(0, 0, intW, intH)
g1.DrawImage(pic.Image, rect)
g1.DrawImage(pic2, 0, 0, BarWidth, intH)
g1.Dispose()

e.Graphics.DrawImage(b, rect)
b.dispose()

End Sub


※印をつけた所のe.Graphicsをなくせば、必要なサイズできちんと描画されるのですが、
画像自体がにじんでしまいます。指定していない場合、bitmapのdpiが96になってしまうからだ
思います。Bitmapの作成サイズを大きくすればよい事がわかってきたのですが、今度は印刷された
サイズが思ったとおりになりません。dpiがらみの設定だと思うのですが、どのように考えれば
いいのかがわかりません。どなたかご教示お願いします。


Private Sub PrintDocument1_PrintPage(ByVal sender As System.Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles PrintDocument1.PrintPage

〜宣言省略
Dim rect As New Rectangle(0, 0, intW, intH)
e.Graphics.DrawImage(pic.Image, rect)
e.Graphics.DrawImage(pic2, 0, 0, BarWidth, intH)

End Sub

上記のようにBitmapを用意せず、PictureBoxのImageを直接印刷すると非常にきれいに印刷されます。
ただ、拡大,縮小,クリッピング等をしてから描画したいのではじめの方の方法をとりました。
たけっち
会議室デビュー日: 2006/11/28
投稿数: 4
投稿日時: 2006-11-30 16:29
自己レスです。

あれから一時的なBitmapに対して、SetResolutionしてみたり、
DrawImage(pic.Image, rect,rect_s, GraphicsUnit.Pixel)のように
書き込む範囲を指定したりと、いろいろ試したのですがどうしても
画像の一部分しか書き込めなかったので、
e.Graphics.DrawImageを使用した方法をいろいろ試したところ、
希望する画質で、拡大、縮小、クリッピングができることがわかりましたので
スレッドを閉じさせていただきます。
方法はDrawImage(pic.Image, rect,rect_s, GraphicsUnit.Pixel)と
同じで方法で、元画像のrect_sの範囲がうまく計算できればOKでした。
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-12-03 20:51
引用:

たけっちさんの書き込み (2006-11-28 17:22) より:
環境:VB2005

指定していない場合、bitmapのdpiが96になってしまうからだ
思います。Bitmapの作成サイズを大きくすればよい事がわかってきたのですが、今度は印刷されたサイズが思ったとおりになりません。dpiがらみの設定だと思うのですが、どのように考えればいいのかがわかりません。どなたかご教示お願いします。


 解決できたと言うことですが、DPI も、理解できたでしょうか?

 これは、 Dot Per Inch の略です。1インチに何ドット打つかを表しています。96DPI ということは、96ピクセルで1インチ=2.54cm です。
_________________
たけっち
会議室デビュー日: 2006/11/28
投稿数: 4
投稿日時: 2006-12-04 12:19
引用:
解決できたと言うことですが、DPI も、理解できたでしょうか?

 これは、 Dot Per Inch の略です。1インチに何ドット打つかを表しています。96DPI ということは、96ピクセルで1インチ=2.54cm です。



Jittaさん、レスありがとうございます。

DPIについては理解しています。印刷に関しては
http://www.nextftp.com/swlabo/
ここがかなり勉強になりました。

別の解決法ができたので解決としたのですが、はじめの方法でなぜ拡大された
状態で書き込まれるかは未だ納得できず釈然としていません。
もうすこしお付き合いいただけないでしょうか?

先日書き込んだコードですが、

Dim rect As New Rectangle(0, 0, intW, intH)
g1.DrawImage(pic.Image, rect)

DrawImageメソッドは上記の引数の時は元の画像をスケーリングさせて
指定した場所に指定したサイズで書き込んでくれると思っています。
bitmap作成時にe.Graphicsを付けなければきちんとスケーリングしてくれていますから
これはOKだと思います。Bitmapを用意せず直接e.GraphicsへDrawImageで描画したときも
きちんとスケーリングしてくれます。
Dim b As Bitmap = New Bitmap(intW, intH, e.Graphics)
とした場合だけなぜスケーリングしてくれないのかがわかりません。

e.Graphicsを付けた場合
Dim scale As Single = 600 / 96 'dpi
Dim b As Bitmap = New Bitmap(CInt(intW * scale), CInt(intH * scale), e.Graphics)

e.GraphicsのResolutiongが600になっているので、上記のようにscaleを求めて
それにあわせてbitmapを用意してみたところ、画像はきれいに表示されますが、
描画したいサイズより少し縮小されて表示されてしまいます。

普通上記のようにdpiを考慮してDrawImageメソッドを考えなければいけないのでしょうか?
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-12-04 21:54
e.Graphics.PageUnit の値を確認してみてください。
その値と、intW, intH, BarWidth が表現しているものの差を、考えてみてください。

_________________
たけっち
会議室デビュー日: 2006/11/28
投稿数: 4
投稿日時: 2006-12-05 15:37
引用:

e.Graphics.PageUnit の値を確認してみてください。
その値と、intW, intH, BarWidth が表現しているものの差を、考えてみてください。



Jittaさん、回答ありがとうございます。

e.Graphics.PageUnitの値はGraphicsUnit.Displayになっています。
作成したBitmapのGraphics.PageUnitもGraphicsUnit.Displayでした。
Pixel単位にすればいいのではと思って

g1.PageUnit = GraphicsUnit.Pixel

としたところ、希望通りのサイズで描画されたのですが画質が落ちました。
600dpiで印刷するためには247*339では小さすぎるのでは?と考えました。

ヘルプではGraphicsUnit.Displayはプリンタでは1/100インチで
指定となっているのでそこから考えました。

Const intW As Integer = 247
Const intH As Integer = 339

この値から、100ドットで1インチなので、247ドットは2.47インチ。600dpiなので
2.47*600で1482ドット必要。縦も同じく考えて2076ドット。
この大きさのBitmapを作成すれば良いと思い、

Dim b As Bitmap = New Bitmap(1482, 2076, e.Graphics)

としたところ、バッチリ希望通りになりました!
この考え方であってますよね?
プリンタを相手に考えると難しいですね。勉強になりました。
ありがとうございました。

Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2006-12-05 21:21
ご名答。(^^)//""""""パチパチ

 MSDN も確認しておいてください。Graphics クラスの各メソッドが扱う数値の単位は、PageUnit となっています。したがって、この値を変更することで、様々な単位を元にして描画を行うことが出来ます。
(プリンタでは 1/100inch ってのは、見落としていた。ありがとう。そりゃ、若干小さくなるはずだorz)

_________________
1

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