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位置上

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上看到:




留言

匿名表示…
請問你的文章內 Printer Driver 200 dpi
這個 200 dpi 的定義出處來自哪裡 ?
WILDOX寫道…
Re: 匿名 <1903047245662626092>
兩個地方:
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的时候蛮清晰的。 但是drawimage 里面的文字
或者二维码都有一点不太好
WILDOX寫道…
Re: 风云 <4669519137981560217>

直接drawstring的時候,是C# 把 trutype文字做vector(向量)運算在Graphices上,這樣可以做到最小解析遺失度(low drop-out)問題。

但是drawimage繪製圖像(image)時,通常會使用填滿(fit to fill)方法,然而圖像裡面的文字已經不是Vector狀態,而是pixel狀態,如果圖像的解析度(resolution)與大小(size)不同於要繪製的graphices對象時,就會進行降解(drop-out),因此圖像訊息損失太大,容易變成模糊或是不清楚的情形。

這個網誌中的熱門文章

【研究】列印的條碼為什麼很難刷(掃描)

C# 使用 Process.Start 執行外部程式

統一發票列印小程式