123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459 |
- using ComPDFKit.Import;
- using ComPDFKit.PDFPage;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Drawing.Imaging;
- using System.Drawing.Printing;
- using System.Linq;
- using System.Printing;
- using System.Reflection;
- using System.Runtime.InteropServices;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- namespace ComPDFKit.Controls.Printer
- {
- public enum DuplexingStage
- {
- None,
- FontSide,
- BackSide
- }
- public static class PrintHelper
- {
- public static readonly PrintServer printServer = new PrintServer();
- private static PrintSettingsInfo printSettingsInfo;
- private static PrintQueue printQueue;
- private static int MaxCopies = 1;
- private static bool FinishedFrontSide = false;
- private static bool isManualDuplex = false;
- private static List<OutputColor> outputColors;
- private static List<Duplexing> duplexings;
- private static Bitmap blankPageBitmapForPrint;
- private static int PrintIndex;
- private static void SetPrinterLimits()
- {
- MaxCopies = printQueue.GetPrintCapabilities().MaxCopyCount.HasValue ? printQueue.GetPrintCapabilities().MaxCopyCount.Value : 1;
- outputColors = new List<OutputColor>(printQueue.GetPrintCapabilities().OutputColorCapability);
- duplexings = new List<Duplexing>(printQueue.GetPrintCapabilities().DuplexingCapability);
- }
- public static void PrintDocument(PrintSettingsInfo printSettings)
- {
- printSettingsInfo = printSettings;
- printQueue = printServer.GetPrintQueue(printSettings.PrinterName);
- SetPrinterLimits();
- if (printSettings.DuplexPrintMod == DuplexPrintMod.None ||
- (printSettings.PrintMode is BookletModeInfo bookletModeInfo && bookletModeInfo.Subset != BookletSubset.BothSides))
- {
- HandlePrintQueue(DuplexingStage.None);
- }
- else if (printSettings.DuplexPrintMod > 0 ||
- (printSettings.PrintMode is BookletModeInfo bookletModeInfo1 && bookletModeInfo1.Subset == BookletSubset.BothSides))
- {
- if (duplexings.Contains(Duplexing.TwoSidedShortEdge) || duplexings.Contains(Duplexing.TwoSidedLongEdge))
- {
- HandlePrintQueue(DuplexingStage.None);
- }
- else
- {
- if (OnlyOnePage())
- {
- HandlePrintQueue(DuplexingStage.None);
- }
- else
- {
- HandlePrintQueue(DuplexingStage.FontSide);
- if (FinishedFrontSide)
- {
- DialogResult dialogResult = MessageBox.Show("Do you want to print the back side?", "Print", MessageBoxButtons.YesNo);
- if (dialogResult == DialogResult.OK)
- {
- HandlePrintQueue(DuplexingStage.BackSide);
- }
- }
- }
- }
- }
- bool OnlyOnePage()
- {
- return ((printSettings.PrintMode is SizeModeInfo || printSettings.PrintMode is PosterModeInfo) &&
- printSettings.PageRangeList.Count == 1) ||
- (printSettings.PrintMode is MultipleModeInfo multipleModeInfo &&
- (int)Math.Ceiling(printSettings.PageRangeList.Count / (double)(multipleModeInfo.Sheet.TotalPageNumber)) == 1);
- }
- }
- private static void HandlePrintQueue(DuplexingStage stage)
- {
- if (printQueue != null)
- {
- using (var printDocument = new PrintDocument())
- {
- var printTicket = new PrintTicket();
- printDocument.PrinterSettings.PrinterName = printQueue.Name;
- printDocument.DefaultPageSettings.Color = !printSettingsInfo.IsGrayscale && outputColors.Contains(OutputColor.Color);
- if (printSettingsInfo.DuplexPrintMod > 0 || printSettingsInfo.PrintMode is BookletModeInfo)
- {
- if (stage == DuplexingStage.None)
- {
- printDocument.DefaultPageSettings.Landscape = (printSettingsInfo.PrintOrientation == PrintOrientation.Landscape);
- }
- else
- {
- printDocument.PrinterSettings.Duplex = Duplex.Simplex;
- isManualDuplex = true;
- PrintIndex = stage == DuplexingStage.FontSide ? 0 : 1;
- }
- }
- else
- {
- printDocument.PrinterSettings.Duplex = Duplex.Simplex;
- }
- printQueue.DefaultPrintTicket = printTicket;
- printDocument.DefaultPageSettings.PaperSize = printSettingsInfo.PaperSize;
- List<PaperSource> paperSources = Enumerable.Range(0, printDocument.PrinterSettings.PaperSources.Count).
- Select(i => printDocument.PrinterSettings.PaperSources[i]).ToList();
- printDocument.DefaultPageSettings.Margins = printSettingsInfo.Margins;
- printDocument.DefaultPageSettings.PaperSource = paperSources.FirstOrDefault();
- if (printSettingsInfo.Copies >= printQueue.GetPrintCapabilities().MaxCopyCount)
- {
- printDocument.PrinterSettings.Copies = (short)MaxCopies;
- }
- else
- {
- printDocument.PrinterSettings.Copies = (short)printSettingsInfo.Copies;
- }
- printDocument.PrintPage += PrintDocument_PrintPage;
- printDocument.PrinterSettings.PrintFileName = printSettingsInfo.Document.FileName;
- try
- {
- printDocument.Print();
- }
- catch (Exception ex)
- {
- MessageBox.Show(ex.Message);
- }
- }
- }
- }
- public static Bitmap ToGray(Bitmap bmp, int mode)
- {
- if (bmp == null)
- {
- return null;
- }
- int w = bmp.Width;
- int h = bmp.Height;
- try
- {
- byte newColor = 0;
- BitmapData srcData = bmp.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
- unsafe
- {
- byte* p = (byte*)srcData.Scan0.ToPointer();
- for (int y = 0; y < h; y++)
- {
- for (int x = 0; x < w; x++)
- {
- if (mode == 0)
- {
- newColor = (byte)((float)p[0] * 0.114f + (float)p[1] * 0.587f + (float)p[2] * 0.299f);
- }
- else
- {
- newColor = (byte)((float)(p[0] + p[1] + p[2]) / 3.0f);
- }
- p[0] = newColor;
- p[1] = newColor;
- p[2] = newColor;
- p += 3;
- }
- p += srcData.Stride - w * 3;
- }
- bmp.UnlockBits(srcData);
- return bmp;
- }
- }
- catch
- {
- return null;
- }
- }
- public static Bitmap BuildBmp(int width, int height, byte[] imgBytes)
- {
- // Check if the byte array length matches the expected size
- int expectedLength = width * height * 4;
- if (imgBytes.Length != expectedLength)
- {
- throw new ArgumentException("The length of imgBytes does not match the expected size.");
- }
- // Create a new bitmap with the specified width, height, and pixel format
- Bitmap bitmap = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
- // Lock the bitmap's bits for writing
- BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bitmap.PixelFormat);
- try
- {
- // Copy the byte array to the bitmap's scan0 pointer
- Marshal.Copy(imgBytes, 0, bmpData.Scan0, imgBytes.Length);
- }
- finally
- {
- // Ensure that the bitmap is always unlocked, even if an exception occurs
- bitmap.UnlockBits(bmpData);
- }
- return bitmap;
- }
- public static int CaculatePrintedPageCount(PrintSettingsInfo printSettingsInfo)
- {
- int tempCount = printSettingsInfo.PageRangeList.Count;
- if (printSettingsInfo.PrintMode is MultipleModeInfo multipleModeInfo)
- {
- tempCount = (int)Math.Ceiling((double)tempCount /
- multipleModeInfo.Sheet.TotalPageNumber);
- }
- else if (printSettingsInfo.PrintMode is BookletModeInfo bookletInfo)
- {
- if (tempCount != 1)
- {
- tempCount = (bookletInfo.EndPageIndex - bookletInfo.BeginPageIndex + 1) / 2;
- if (bookletInfo.Subset != BookletSubset.BothSides)
- {
- tempCount /= 2;
- }
- }
- }
- return tempCount;
- }
- public static Bitmap CombineBitmap(Bitmap background, Bitmap foreground, System.Drawing.Point point)
- {
- if (background == null)
- {
- return null;
- }
- int bgWidth = background.Width;
- int bgHeight = background.Height;
- Bitmap newMap = new Bitmap(bgWidth, bgHeight);
- Graphics graphics = Graphics.FromImage(newMap);
- graphics.DrawImage(background, new System.Drawing.Point(0, 0));
- graphics.DrawImage(foreground, point);
- graphics.Dispose();
- return newMap;
- }
- private static void PrintDocumentModSize(PrintPageEventArgs e)
- {
- int PrintedPageCount = CaculatePrintedPageCount(printSettingsInfo);
- int widthDpiRatio = (int)e.Graphics.DpiX / 100;
- int heightDpiRatio = (int)e.Graphics.DpiY / 100;
- if (printSettingsInfo.PrintMode is SizeModeInfo sizeMode)
- {
- CPDFPage page = printSettingsInfo.Document.PageAtIndex(printSettingsInfo.PageRangeList[PrintIndex]);
- Rectangle realBound = e.PageBounds;
- Point point = new Point(0, 0);
- if (page != null)
- {
- CSize cSize = page.PageSize;
- System.Drawing.Size pageSize = new System.Drawing.Size((int)cSize.width * widthDpiRatio, (int)cSize.height * heightDpiRatio);
- byte[] bmpData = new byte[(int)(pageSize.Width * pageSize.Height * 4)];
- page.RenderPageBitmap(0, 0, pageSize.Width, pageSize.Height, 0xFFFFFFFF, bmpData, printSettingsInfo.IsPrintAnnot ? 1 : 0, printSettingsInfo.IsPrintForm);
- Bitmap bitmap = BuildBmp((int)pageSize.Width, (int)pageSize.Height, bmpData);
- if (printSettingsInfo.IsGrayscale)
- {
- bitmap = ToGray(bitmap, 0);
- }
- if (sizeMode.SizeType == SizeType.Adaptive)
- {
- int resizeHeight;
- int resizeWidth;
- if (bitmap.Height / bitmap.Width >= printSettingsInfo.PaperSize.Height / printSettingsInfo.PaperSize.Width)
- {
- resizeHeight = printSettingsInfo.PaperSize.Height * heightDpiRatio;
- resizeWidth = bitmap.Width * printSettingsInfo.PaperSize.Height / bitmap.Height * widthDpiRatio;
- }
- else
- {
- resizeWidth = printSettingsInfo.PaperSize.Width * widthDpiRatio;
- resizeHeight = bitmap.Height * printSettingsInfo.PaperSize.Width / bitmap.Width * heightDpiRatio;
- }
- using (Bitmap resizedBitmap = new Bitmap(bitmap, resizeWidth, resizeHeight))
- {
- if (isManualDuplex && PrintIndex % 2 == 1 && printSettingsInfo.DuplexPrintMod == DuplexPrintMod.FlipShortEdge)
- {
- resizedBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
- }
- float aspectRatioResizedBitmap = (float)resizedBitmap.Width / resizedBitmap.Height;
- float aspectRatioRealBound = (float)realBound.Width / realBound.Height;
- if (aspectRatioResizedBitmap != aspectRatioRealBound)
- {
- if (realBound.Width / aspectRatioResizedBitmap <= realBound.Height)
- {
- realBound.Height = (int)(realBound.Width / aspectRatioResizedBitmap);
- }
- else
- {
- realBound.Width = (int)(realBound.Height * aspectRatioResizedBitmap);
- }
- }
- e.Graphics.DrawImage(resizedBitmap, realBound, new Rectangle(0, 0, resizedBitmap.Width, resizedBitmap.Height), GraphicsUnit.Pixel);
- }
- }
- else if (sizeMode.SizeType == SizeType.Actural)
- {
- using (Bitmap resizedBitmap = ResizeBitmap(bitmap, 100))
- {
- if (isManualDuplex && PrintIndex % 2 == 1 && printSettingsInfo.DuplexPrintMod == DuplexPrintMod.FlipShortEdge)
- {
- resizedBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
- }
- float aspectRatioResizedBitmap = (float)resizedBitmap.Width / resizedBitmap.Height;
- float aspectRatioRealBound = (float)realBound.Width / realBound.Height;
- if (aspectRatioResizedBitmap != aspectRatioRealBound)
- {
- if (realBound.Width / aspectRatioResizedBitmap <= realBound.Height)
- {
- realBound.Height = (int)(realBound.Width / aspectRatioResizedBitmap);
- }
- else
- {
- realBound.Width = (int)(realBound.Height * aspectRatioResizedBitmap);
- }
- }
- e.Graphics.DrawImage(resizedBitmap, realBound, new Rectangle(0, 0, resizedBitmap.Width, resizedBitmap.Height), GraphicsUnit.Pixel);
- }
- }
- else if (sizeMode.SizeType == SizeType.Customized)
- {
- using (Bitmap resizedBitmap = ResizeBitmap(bitmap, (printSettingsInfo.PrintMode as SizeModeInfo).Scale))
- {
- if (isManualDuplex && PrintIndex % 2 == 1 && printSettingsInfo.DuplexPrintMod == DuplexPrintMod.FlipShortEdge)
- {
- resizedBitmap.RotateFlip(RotateFlipType.RotateNoneFlipY);
- }
- float aspectRatioResizedBitmap = (float)resizedBitmap.Width / resizedBitmap.Height;
- float aspectRatioRealBound = (float)realBound.Width / realBound.Height;
- realBound.Width = (int)(realBound.Width * (printSettingsInfo.PrintMode as SizeModeInfo).Scale / 100.0);
- realBound.Height = (int)(realBound.Height * (printSettingsInfo.PrintMode as SizeModeInfo).Scale / 100.0);
- if (aspectRatioResizedBitmap != aspectRatioRealBound)
- {
- if (realBound.Width / aspectRatioResizedBitmap <= realBound.Height)
- {
- realBound.Height = (int)(realBound.Width / aspectRatioResizedBitmap);
- }
- else
- {
- realBound.Width = (int)(realBound.Height * aspectRatioResizedBitmap);
- }
- }
- realBound.X = (e.PageBounds.Width - realBound.Width) / 2;
- realBound.Y = (e.PageBounds.Height - realBound.Height) / 2;
- e.Graphics.DrawImage(resizedBitmap, realBound, new Rectangle(0, 0, resizedBitmap.Width, resizedBitmap.Height), GraphicsUnit.Pixel);
- }
- }
- bitmap.Dispose();
- GC.Collect();
- if (isManualDuplex && PrintedPageCount != 1)
- {
- if (PrintIndex < PrintedPageCount - 2)
- {
- PrintIndex += 2;
- e.HasMorePages = true;
- }
- else
- {
- e.HasMorePages = false;
- if (PrintIndex % 2 == 0)
- {
- //
- }
- }
- }
- else
- {
- if (PrintIndex < PrintedPageCount - 1)
- {
- PrintIndex++;
- e.HasMorePages = true;
- }
- else
- {
- e.HasMorePages = false;
- }
- }
- }
- }
- }
- private static void PrintDocument_PrintPage(object sender, PrintPageEventArgs e)
- {
- switch (printSettingsInfo.PrintMode)
- {
- case SizeModeInfo _:
- PrintDocumentModSize(e);
- break;
- case PosterModeInfo _:
- break;
- case MultipleModeInfo _:
- break;
- case BookletModeInfo _:
- break;
- }
- }
- internal static Bitmap ResizeBitmap(Bitmap bitmap, float scale)
- {
- int newWidth = (int)(bitmap.Width * scale / 72);
- int newHeight = (int)(bitmap.Height * scale / 72);
- Bitmap newBitmap = new Bitmap(newWidth, newHeight);
- using (Graphics g = Graphics.FromImage(newBitmap))
- {
- g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
- g.DrawImage(bitmap, 0, 0, newWidth, newHeight);
- }
- return newBitmap;
- }
- }
- }
|