C# PrintDocument的解析度
這次在製作列印文件時,需要繪製圖像與文字
但是每次在PrintDocument列印時,圖像解析度一直始終都是不佳的狀態,
儘管把 Imag 或 Bitmap 繪製的時候把 Resolutions都調高,但在列印時依然沒變好。
後來,反覆研究測試後發現,原來是最終輸出影響了整個列印品質,
可以看下面的成型原因:
為什麼 Graphics 只有 100 DPI?
原因就在於 Graphics 成像時的參考單位是『螢幕』,而一般螢幕都是在 72~96 DPI左右的。
決定 Graphics 使用繪製的解析度是由 Graphics.PageUnit 來決定的。
它是個 GraphicsUnit 列舉變數,你可參考微軟說明:關於GraphicsUnit
預設值如下 Graphics.PageUnit = GraphicsUnit.Display
所以這就知道為什麼 Graphics 在進行 DrawImage 的時候,不管你的 Image 解析度多高,都會一律被轉成 100 DPI 的低解析度了。
因此在繪圖前你可以設定 PageUnit 為 GraphicsUnit.Document 或是 GraphicsUnit.Pixel。
當定義為 GraphicsUnit.Document 時,Graphics 的解析度固定為 300 DPI,
基本上它不管輸出設備本身的解析度。
這樣的好處是繪製圖形位置或大小時,可以用固定的解析度去計算繪製的位置。
例如:我要繪製 10cm x 7.5cm 圖像,並放置在 x:y = 5cm : 3cm位置上
某些情況下,繪製圖像必須以輸出裝置(通常為印表機)的解析度為主,
Graphics 上繪製的圖像輸出到裝置希望為 1:1 狀態,
而不希望發生解析度不一致的變型。例如:長寬比1:2高密度條碼。
此時可以設定為 GraphicsUnit.Pixel ,這樣 Graphics 解析度會直接以裝置解析度為主。
當然,在計算繪圖的位置、大小時就必須把解析度抓進來計算,
以免繪製的圖像,列印的位置不在應該的位置上。
以上面例子要繪製 10cm x 7.5cm 圖像,並放置在 x:y = 5cm : 3cm位置上
這樣,就可以很精準的定位要把圖像繪製到指定位置上了。
驅動程式解析度可以從『裝置與印表機』→(印表機)→『印表機內容』裡面看到:
或是從廠商提供的DM上看到:
但是每次在PrintDocument列印時,圖像解析度一直始終都是不佳的狀態,
儘管把 Imag 或 Bitmap 繪製的時候把 Resolutions都調高,但在列印時依然沒變好。
後來,反覆研究測試後發現,原來是最終輸出影響了整個列印品質,
可以看下面的成型原因:
為什麼 Graphics 只有 100 DPI?
原因就在於 Graphics 成像時的參考單位是『螢幕』,而一般螢幕都是在 72~96 DPI左右的。
決定 Graphics 使用繪製的解析度是由 Graphics.PageUnit 來決定的。
它是個 GraphicsUnit 列舉變數,你可參考微軟說明:關於GraphicsUnit
預設值如下 Graphics.PageUnit = GraphicsUnit.Display
所以這就知道為什麼 Graphics 在進行 DrawImage 的時候,不管你的 Image 解析度多高,都會一律被轉成 100 DPI 的低解析度了。
因此在繪圖前你可以設定 PageUnit 為 GraphicsUnit.Document 或是 GraphicsUnit.Pixel。
當定義為 GraphicsUnit.Document 時,Graphics 的解析度固定為 300 DPI,
基本上它不管輸出設備本身的解析度。
這樣的好處是繪製圖形位置或大小時,可以用固定的解析度去計算繪製的位置。
例如:我要繪製 10cm x 7.5cm 圖像,並放置在 x:y = 5cm : 3cm位置上
e.Graphics.PageUnit = GraphicsUnit.Document;
Image myImage = Image.FromFile(myPictureFile);
float toInch = 0.254f;
Rectangle myRect = new Rectangle (
(int)((5.0f / toInch) * 300),
(int)((3.0f / toInch) * 300),
(int)((10.0f / toInch) * 300),
(int)((7.5f / toInch) * 300));
e.Graphics.DrawImage(
myImage ,
myRect,
0,
0,
myImage.Width,
myImage.Height,
GraphicsUnit.Pixel);
某些情況下,繪製圖像必須以輸出裝置(通常為印表機)的解析度為主,
Graphics 上繪製的圖像輸出到裝置希望為 1:1 狀態,
而不希望發生解析度不一致的變型。例如:長寬比1:2高密度條碼。
此時可以設定為 GraphicsUnit.Pixel ,這樣 Graphics 解析度會直接以裝置解析度為主。
當然,在計算繪圖的位置、大小時就必須把解析度抓進來計算,
以免繪製的圖像,列印的位置不在應該的位置上。
以上面例子要繪製 10cm x 7.5cm 圖像,並放置在 x:y = 5cm : 3cm位置上
float dpiX = (float)e.PageSettings.PrinterSettings.DefaultPageSettings.PrinterResolution.X;
float dpiY = (float)e.PageSettings.PrinterSettings.DefaultPageSettings.PrinterResolution.Y;
e.Graphics.PageUnit = GraphicsUnit.Pixel;
Image myImage = Image.FromFile(myPictureFile);
float toInch = 0.254f;
Rectangle myRect = new Rectangle (
(int)((5.0f / toInch) * dpiX),
(int)((3.0f / toInch) * dpiY),
(int)((10.0f / toInch) * dpiX),
(int)((7.5f / toInch) * dpiY));
e.Graphics.DrawImage(
myImage ,
myRect,
0,
0,
myImage.Width,
myImage.Height,
GraphicsUnit.Pixel);
這樣,就可以很精準的定位要把圖像繪製到指定位置上了。
驅動程式解析度可以從『裝置與印表機』→(印表機)→『印表機內容』裡面看到:
或是從廠商提供的DM上看到:
留言
這個 200 dpi 的定義出處來自哪裡 ?
兩個地方:
1、印表機的『印表機內容』第一個頁面下方
https://3.bp.blogspot.com/-jfzXEUtXFiE/Wg5XLTw4trI/AAAAAAAACfg/mtBSsBAWlro8_7G5nXhgR1gr7ByO-eS9QCLcBGAs/s400/2017-11-17%2B%25E4%25B8%258A%25E5%258D%2588%2B11-01-51.png
2、廠商的DM
https://1.bp.blogspot.com/-mA9i99P8voM/Wg5XPe1gaQI/AAAAAAAACfk/qgBj1kjqJJAS0bmm4Z0X3CkMqVivhbuWgCLcBGAs/s640/2017-11-17%2B%25E4%25B8%258A%25E5%258D%2588%2B11-04-33.png
或者二维码都有一点不太好
直接drawstring的時候,是C# 把 trutype文字做vector(向量)運算在Graphices上,這樣可以做到最小解析遺失度(low drop-out)問題。
但是drawimage繪製圖像(image)時,通常會使用填滿(fit to fill)方法,然而圖像裡面的文字已經不是Vector狀態,而是pixel狀態,如果圖像的解析度(resolution)與大小(size)不同於要繪製的graphices對象時,就會進行降解(drop-out),因此圖像訊息損失太大,容易變成模糊或是不清楚的情形。