上へ ワークフロー 画像仕様 フォルダ構成 データベース構成 システム運用系 植物写真系 Web処理系 写真表示コントロール 写真画像生成 現像(Nikon Capture 4)との連携 写真印刷
| |
PC写真システム |
写真印刷 |
最終更新日:2006/09/17
修正 |
市販のアプリで印刷はできるが、自分のワークフロー内で印刷する場合は、やはり自製アプリでも印刷できた方が便利。
●印刷仕様
- 四辺縁なし印刷
焼き付けの代わりとなるものは、高精細印刷での(エプソンの)四辺縁なし印刷に対応する。
- 単一印刷
一品一葉の印刷。ランドスケープ、ポートレートは自動識別され印刷される。
- 一覧印刷
一覧表示を印刷。印刷サイズは長辺が約 5cm となる。
- センタリング
縁なし以外では、自動的にセンタリング(頁中央合せ)される。
- 印刷対象
CurrentSelect、Select 及び指定された全数。
●縁なし印刷とは?
これは、用紙の余白が完全に 0 になるもので、物理オフセット値も 0
になる。実際の印刷では写真専用紙やアート紙など、強度のある紙を使用しないといけない。
四辺縁なしで写真(画像)の場合は、用紙サイズ一杯に指定する。従って、写真のアスペクトレシオと用紙のそれは異なるので、用紙のアスペクトレシオにて写真をトリミングすることになる。エプソンによれば、縁なしの場合は、ドライバにて、僅かに写真を拡大し、少し
、はみ出るように調整されるらしい。これは、プリンタの機械的誤差を吸収するための処置らしい。
従って、実際の印刷では、用紙サイズより縦、横共に1.5% だけ縮めて印刷する。
●"縁なし"の認識
"縁なし"を指定しても、アプリ側でこれを認識できないと縁なし印刷は自分でできない。実験の結果、以下のことが分った。
印刷ダイアログ(エプソン提供)で縁なしを指定すると、デフォールトセッティングのPaperSource の値が特定値になる。
pdgD は印刷設定ダイアログとすれば、PaperSource のKind プロパティ、
pdgD.PrinterSettings.DefaultPageSettings.PaperSource.Kind
が、値 257(Integer変換) となる。これを検出すれば良い。
ちなみに、ダイアログでの紙質設定は、全て、解像度に反映するようだ。
●UI
以下のようなUIとなっている。
- 写真の通常表示で表示している写真群を対象とし、コンテキストメニューで対象と印刷方法を選ぶ。
- 必ず、印刷設定ダイアログが表示されるので、ここで、用紙、用紙サイズ、方向、品質、縁なしなどを指定する。
- すると、必ず、プレビューが自動表示される。ここで全ての頁の確認を行える。
- プレビュー窓から印刷を指示する。
プレビューの例
●自動センタリング
これは、用紙の四辺の余白を、上下と左右で均等になるように自動調整するものである。これは単純な処理ではない。これについては、こことここを参照方。
●事例
以下に実際のコード例を紹介する。
○コンテキストメニュー処理
Case "単一印刷"(CurrentSelect)
PrintPhotos(1)
Case "単一印刷"
PrintPhotos(2)
Case "一覧印刷(選択)"
PrintPhotos(3)
Case "一覧印刷(全頁)"
PrintPhotos(4)
○印刷設定とプリビュー
pdgD は印刷設定ダイログ
pdcD はドキュメントオブジェクト
prvD はプリビューダイアログ
Private Sub PrintPhotos(ByVal m As Integer)
Dim i, p As Integer
pdgD.Document = pdcD
pdgD.AllowPrintToFile = False
pdgD.AllowSelection = False
pdgD.AllowSomePages = False
pdgD.PrintToFile = False
pdgD.ShowHelp = False
DlgR = pdgD.ShowDialog()
Select Case DlgR
Case DialogResult.OK, DialogResult.Yes
PrintMode = m
CPSKind =
CInt(pdgD.PrinterSettings.DefaultPageSettings.PaperSource.Kind)
If CPSKind = EpsonNoMargin Then
'縁なし、物理オフセット値=0
ReDim
POffs(3)
Vmgn = 0
Hmgn = 0
Voffs = 0
Hoffs = 0
Else
GParam.GetPrinterMarginsEx(pdgD.PrinterSettings.PrinterName, POffs)
'プリンタの物理オフセット値を獲得
For i = 0 To
3
POffs(i) = POffs(i) * 100
'1/100インチ単位、A4縦基準
Next
Vmgn =
Math.Max(POffs(0), POffs(1)) '上下の空白
Hmgn =
Math.Max(POffs(2), POffs(3)) '左右の空白
Voffs =
POffs(0)
Hoffs =
POffs(2)
End If
Dim prc As Rectangle =
pdgD.PrinterSettings.DefaultPageSettings.Bounds
Select Case m
(mに応じて設定する、一覧では予め頁数や画像配置を算出しておく)
End Select
PreV = 0
pdcD.DocumentName = MMsg
prvD.Document = pdcD
prvD.AutoScroll = False
prvD.WindowState =
FormWindowState.Maximized
prvD.StartPosition =
FormStartPosition.CenterScreen
prvD.ShowDialog()
'プリビューし印刷する
Case Else
Exit Sub
End Select
End Sub
○pdcD のイベント処理
Private Sub pdcD_BeginPrint(ByVal sender As Object, ByVal
e As System.Drawing.Printing.PrintEventArgs) Handles pdcD.BeginPrint
CPPage = 0
PreV = PreV + 1
End Sub
単一画像の場合は、画像に応じて用紙方向を自動設定する
Private Sub pdcD_QueryPageSettings(ByVal sender As Object,
ByVal e As System.Drawing.Printing.QueryPageSettingsEventArgs) Handles
pdcD.QueryPageSettings
Select Case PrintMode
Case 1, 2
'単一画像の場合は、方向は強制設定
Select Case PS(pOrientation, PrintIXT(CPPage))
Case "P"
e.PageSettings.Landscape = False
Case "L"
e.PageSettings.Landscape = True
End Select
Case Else
'NOP
End Select
End Sub
印刷処理(プリビュー時も実行される)
PrintIXT は、印刷対象写真のインデックスリスト
Private Sub pdcD_PrintPage(ByVal sender As Object, ByVal e
As System.Drawing.Printing.PrintPageEventArgs) Handles pdcD.PrintPage
Dim g As Graphics = e.Graphics
Dim bmp As Bitmap
Dim ft As New Font(Me.Font.Name, 6,
FontStyle.Regular)
Dim PW, PH, W, H, nw, nh, ACnt, i,
Ix, ta, yo As Integer
Dim X, Y As Single
Dim FP As String
Select Case PreV
'オフセット設定
Case 1
'プリビュー
Xoffs = 0 : Yoffs = 0
Select Case e.PageSettings.Landscape
Case False
Xmgn = Hmgn
Ymgn = Vmgn
Case True
Xmgn = Vmgn
Ymgn = Hmgn
End Select
Case Else
'実印刷
If CPSKind = EpsonNoMargin Then '空白はなし
Xoffs = 0 : Yoffs = 0
Xmgn = 0 : Ymgn = 0
Else
Select Case e.PageSettings.Landscape
Case False
Xoffs = Hoffs
Yoffs = Voffs
Xmgn = Hmgn
Ymgn = Vmgn
Case True
Xoffs = Voffs
Yoffs = Hoffs
Xmgn = Vmgn
Ymgn = Hmgn
End Select
End If
End Select
Select Case PrintMode
Case 1, 2
If PreV = 1 Then 'プリビューの場合は小さい画像を確保
FP = LargeWebPath(PS(pPNo, PrintIXT(CPPage)), PS(pFld, PrintIXT(CPPage)))
Else
FP = PrintPath(PS(pPNo, PrintIXT(CPPage)), PS(pFld, PrintIXT(CPPage)))
End If
Dim st As Stream = File.Open(FP, FileMode.Open)
bmp = Bitmap.FromStream(st)
st.Close()
W = bmp.Width
H = bmp.Height
Dim prc As Rectangle = e.PageBounds
Dim drc As Rectangle
PW = prc.Width - 2 * Xmgn '印刷可能範囲
PH = prc.Height - 2 * Ymgn
If CPSKind = EpsonNoMargin Then '四辺縁なし処理
If PW / PH > W / H Then
nw = W
nh = nw * PH / PW
Else
nh = H
nw = nh * PW / PH
End If
'原画を切抜く矩形
Dim src As New Rectangle((W - nw) / 2, (H - nh) / 2, nw, nh) '画像切抜き範囲
drc = prc '描画領域は紙全体
If PreV <> 1 Then drc.Inflate(-PW * 0.015, -PH * 0.015) '印刷時は少し縮める
g.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
g.DrawImage(bmp, drc, src, GraphicsUnit.Pixel)
Else
If W / H > PW / PH Then
nw = PW
nh = PW * H / W
Else
nh = PH
nw = nh * W / H
End If
drc = New Rectangle((prc.Width - nw) / 2 - Xoffs, (prc.Height - nh) / 2 -
Yoffs,
nw, nh)
g.InterpolationMode = Drawing.Drawing2D.InterpolationMode.HighQualityBicubic
g.DrawImage(bmp, drc)
End If
Dim fmt As New StringFormat()
fmt.Alignment = StringAlignment.Far
fmt.LineAlignment = StringAlignment.Far
g.DrawString(Rights, Me.Font, Brushes.Yellow, drc.Right , drc.Bottom - 4, fmt)
Dim T As String
T = PS(pName, PrintIXT(CPPage))
T = T + " (" + PS(pLand, PrintIXT(CPPage)) + ", " + CDate(PS(pDate,
PrintIXT(CPPage))).ToString("yyyy/MM/dd") + ")"
fmt.Alignment = StringAlignment.Center
g.DrawString(T, Me.Font, Brushes.Yellow, (drc.Left + drc.Right) / 2 , drc.Bottom
- 4 , fmt)
fmt.Dispose()
Case 3, 4
'一覧印刷
If CPPage >= (PPages - 1) Then
ACnt = PImages - (CPPage * PageImages)
Else
ACnt = PageImages
End If
For i = 0 To ACnt - 1
Ix = CPPage * PageImages + i
ta = i \ PYoko
yo = i Mod PYoko
X = yo * MiniW + Prec.Left
Y = ta * MiniH + Prec.Top
FP = SmallWebPath(PS(pPNo, PrintIXT(Ix)), PS(pFld, PrintIXT(Ix)))
Dim st As Stream = File.Open(FP, FileMode.Open)
bmp = Bitmap.FromStream(st)
st.Close()
W = bmp.Width
H = bmp.Height
If W > H Then
nw = MiniLong
nh = nw * H / W
Else
nh = MiniLong
nw = nh * W / H
End If
Dim drc As New RectangleF(X + (MiniW - nw) / 2 - Xoffs, Y + MiniH - (MiniSpanY +
nh) - Yoffs, nw, nh)
g.DrawImage(bmp, drc)
Dim fmt As New StringFormat()
fmt.Alignment = StringAlignment.Center
fmt.LineAlignment = StringAlignment.Near
Dim T As String
T = PS(pName, PrintIXT(Ix))
T = T + " (" + CDate(PS(pDate, PrintIXT(Ix))).ToString("yyyy/MM/dd") + ", " +
PS(pLand, PrintIXT(Ix)) + ")"
g.DrawString(T, ft, Brushes.Black, X + MiniW / 2 - Xoffs, drc.Bottom + 12 -
Yoffs, fmt)
Next
End Select
CPPage = CPPage + 1
If CPPage < PPages Then
e.HasMorePages = True
Else
e.HasMorePages = False
End If
ft.Dispose
bmp.Dispose()
End Sub
|