Я использую C # и библиотеку PDFium для печати PDF на конкретном принтере этикеток. Когда я печатаю этот PDF через Chrome, Edge или мое приложение, качество сомнительно. Когда я печатаю через Adobe Reader или Foxit Reader, качество именно то, что я хочу.
Вот изображение на изображении различий: https://i.imgur.com/gSnYcEE.jpg
Мое приложение называется «Сетевая печать». Как вы можете видеть на изображении, его качество соответствует тому, что делают браузеры. В частности, небольшой текст справа - моя забота.
Так что же отличают настольные программы чтения PDF при печати с них?
Вот фрагмент кода, который фактически печатает PDF в C #:
public static Boolean Print(PrintQueue printer, byte[] content, Boolean landscape)
{
using (MemoryStream stream = new MemoryStream(content))
{
PdfDocument doc = PdfDocument.Load(stream);
PrintDocument pd = GetPrintDocumentAsPDF(printer.Name, doc, landscape);
pd.Print();
return true;
}
}
private static PrintDocument GetPrintDocumentAsPDF(String printerName, PdfDocument doc, Boolean landscape)
{
PdfPrintMultiplePages multiPages = new PdfPrintMultiplePages(1, 1, landscape ? System.Windows.Forms.Orientation.Horizontal : System.Windows.Forms.Orientation.Vertical, 0);
PdfPrintSettings settings = new PdfPrintSettings(PdfPrintMode.CutMargin, multiPages);
PrintDocument pd = doc.CreatePrintDocument(settings);
pd.PrinterSettings.PrinterName = printerName;
Rectangle firstPage = GetSizeForDoc(doc, 0);
pd.DefaultPageSettings.Landscape = landscape;
// Find the closest matching media profile based on the size of the first page
PaperSize bestFit = GetBestFitMediaProfile(firstPage.Width, firstPage.Height, landscape, pd.PrinterSettings.PaperSizes);
if (bestFit != null)
{
pd.DefaultPageSettings.PaperSize = bestFit;
}
else
{
Util.RestLog("!!! No matching media profile. Using default !!!");
}
return pd;
}
/// <summary>
/// Calculates the size of a page from a document
/// </summary>
/// <param name="doc">the document to get the page from</param>
/// <param name="page">the page number to get the size for</param>
/// <returns>a rectangle with the width and height of the page</returns>
private static Rectangle GetSizeForDoc(PdfDocument doc, int page)
{
// Calculate the actual size of the document
SizeF docSize = doc.PageSizes[page];
Rectangle docBounds = new Rectangle(0, 0, (int)Math.Floor(docSize.Width / DOT_PER_INCH * 100),
(int)Math.Floor(docSize.Height / DOT_PER_INCH * 100));
return docBounds;
}
/// <summary>
/// For a given width and height (of a document page), determines the smallest available media profile
/// that can be printed to while still encompassing the entire page
/// </summary>
/// <param name="width">width of the page to print</param>
/// <param name="height">height of the page to print</param>
/// <param name="mediaProfiles">the media profiles available on the print being printed to</param>
/// <returns></returns>
private static PaperSize GetBestFitMediaProfile(int width, int height, bool landscape, PrinterSettings.PaperSizeCollection mediaProfiles)
{
PaperSize mediaProfile = null;
double docLong = Math.Round((landscape ? width : height) * 1f, 2);
double docShort = Math.Round((landscape ? height : width) * 1f, 2);
double profileLong;
double profileShort;
foreach (PaperSize profile in mediaProfiles)
{
Util.RestLog("Found media profile: " + profile.Width + " x " + profile.Height);
double profileWidth = Math.Round(profile.Width * 1f, 2);
double profileHeight = Math.Round(profile.Height * 1f, 2);
profileLong = landscape ? profileWidth : profileHeight;
profileShort = landscape ? profileHeight : profileWidth;
if (mediaProfile == null)
{
// Grab the first media profile that is larger than the document in both width and height
if (profileLong >= docLong && profileShort >= docShort)
{
mediaProfile = profile;
}
}
else
{
// If this profile is closer to the document size than the current one
if (profileLong >= docLong && profileShort >= docShort &&
GetArea(profileWidth, profileHeight) < GetArea(mediaProfile.Width, mediaProfile.Height))
{
mediaProfile = profile;
}
}
}
return mediaProfile;
}
/// <summary>
/// Calculates an area give a width and a height
/// </summary>
/// <param name="width">the width</param>
/// <param name="height">the height</param>
/// <returns>the area of the width and height</returns>
private static double GetArea(double width, double height)
{
return width * height;
}
По сути, главное, что он делает, - это выбирает правильный профиль носителя для размера печатаемого документа PDF. Я не верю, что кому-то понадобится видеть методы, связанные с поиском правильного размера (GetSizeForDoc и GetBestFitMediaProfile), но я могу опубликовать их, если кому-то понадобится.