private static bool optimizeImage(PdfPaintedImage painted) { PdfImage image = painted.Image; // inline images can not be recompressed unless you move them to resources // using PdfCanvas.MoveInlineImagesToResources if (image.IsInline) { return(false); } // mask images are not good candidates for recompression if (image.IsMask || image.Width < 8 || image.Height < 8) { return(false); } // get size of the painted image int width = Math.Max(1, (int)painted.Bounds.Width); int height = Math.Max(1, (int)painted.Bounds.Height); // calculate resize ratio double ratio = Math.Min(image.Width / (double)width, image.Height / (double)height); if (ratio <= 1) { // the image size is smaller then the painted size return(recompressImage(image)); } if (ratio < 1.1) { // with ratio this small, the potential size reduction // usually does not justify resizing artefacts return(false); } if (image.Compression == PdfImageCompression.Group4Fax || image.Compression == PdfImageCompression.Group3Fax || image.Compression == PdfImageCompression.JBig2 || (image.ComponentCount == 1 && image.BitsPerComponent == 1)) { return(resizeBilevelImage(image, ratio)); } int resizedWidth = (int)Math.Floor(image.Width / ratio); int resizedHeight = (int)Math.Floor(image.Height / ratio); if ((image.ComponentCount >= 3 && image.BitsPerComponent == 8) || isGrayJpeg(image)) { image.ResizeTo(resizedWidth, resizedHeight, PdfImageCompression.Jpeg, 90); // or image.ResizeTo(resizedWidth, resizedHeight, PdfImageCompression.Jpeg2000, 10); } else { image.ResizeTo(resizedWidth, resizedHeight, PdfImageCompression.Flate, 9); } return(true); }
private static bool resizeBilevelImage(PdfImage image, double ratio) { // Fax documents usually look better if integer-ratio scaling is used // Fractional-ratio scaling introduces more artifacts int intRatio = (int)ratio; // decrease the ratio when it is too high if (intRatio > 3) { intRatio = Math.Min(intRatio - 2, 3); } if (intRatio == 1 && image.Compression == PdfImageCompression.Group4Fax) { // skipping the image, because the output size and compression are the same return(false); } image.ResizeTo(image.Width / intRatio, image.Height / intRatio, PdfImageCompression.Group4Fax); return(true); }
private static bool optimizeImage(PdfPaintedImage painted, PdfDocument pdf) { PdfImage image = painted.Image; // inline images can not be recompressed unless you move them to resources // using PdfCanvas.MoveInlineImagesToResources if (image.IsInline) { return(false); } // mask images are not good candidates for recompression if (image.IsMask || image.Width < 8 || image.Height < 8) { return(false); } // get size of the painted image int width = Math.Max(1, (int)painted.Bounds.Width); int height = Math.Max(1, (int)painted.Bounds.Height); if (width >= image.Width || height >= image.Height) { if (image.HasMask) { return(false); } if (image.ComponentCount == 1 && image.BitsPerComponent == 1 && image.Compression != PdfImageCompression.Group4Fax) { image.RecompressWithGroup4Fax(); } else if (image.BitsPerComponent == 8 && image.ComponentCount >= 3 && image.Compression != PdfImageCompression.Jpeg && image.Compression != PdfImageCompression.Jpeg2000) { image.RecompressWithJpeg2000(10); // or image.RecompressWithJpeg(); } return(true); } // try to replace large masked images if (image.HasMask) { if (image.Width < 300 || image.Height < 300) { return(false); } using (var stream = new MemoryStream()) { PdfPage tempPage = pdf.AddPage(); tempPage.Canvas.DrawImage(image, 0, 0, width, height, 0); PdfPaintedImage tempPaintedImage = tempPage.GetPaintedImages()[0]; tempPaintedImage.SaveAsPainted(stream); pdf.RemovePage(pdf.PageCount - 1); image.ReplaceWith(stream); return(true); } } if (image.Compression == PdfImageCompression.Group4Fax || image.Compression == PdfImageCompression.Group3Fax) { // Fax documents usually looks better if integer-ratio scaling is used // Fractional-ratio scaling introduces more artifacts int ratio = Math.Min(image.Width / width, image.Height / height); // decrease the ratio when it is too high if (ratio > 6) { ratio -= 5; } else if (ratio > 3) { ratio -= 2; } image.ResizeTo(image.Width / ratio, image.Height / ratio, PdfImageCompression.Group4Fax); } else if (image.ComponentCount >= 3 && image.BitsPerComponent == 8) { image.ResizeTo(width, height, PdfImageCompression.Jpeg, 90); } else { image.ResizeTo(width, height, PdfImageCompression.Flate, 9); } return(true); }
public static void Main() { // NOTE: // When used in trial mode, the library imposes some restrictions. // Please visit http://bitmiracle.com/pdf-library/trial-restrictions.aspx // for more information. const string originalFile = @"Sample Data\jpeg.pdf"; const string compressedFile = "CompressAllTechniques.pdf"; using (var pdf = new PdfDocument(originalFile)) { // 1. Recompress images foreach (PdfPage page in pdf.Pages) { foreach (PdfPaintedImage painted in page.GetPaintedImages()) { PdfImage image = painted.Image; // image that is used as mask or image with attached mask are // not good candidates for recompression if (image.IsMask || image.Mask != null || image.Width < 8 || image.Height < 8) { continue; } // get size of the painted image int width = Math.Max(1, (int)painted.Bounds.Width); int height = Math.Max(1, (int)painted.Bounds.Height); if (width >= image.Width || height >= image.Height) { if (image.ComponentCount == 1 && image.BitsPerComponent == 1 && image.Compression != PdfImageCompression.Group4Fax) { image.RecompressWithGroup4Fax(); } else if (image.BitsPerComponent == 8 && image.ComponentCount >= 3 && image.Compression != PdfImageCompression.Jpeg && image.Compression != PdfImageCompression.Jpeg2000) { image.RecompressWithJpeg2000(10); // or image.RecompressWithJpeg(); } } else { // NOTE: PdfImage.ResizeTo() method is not supported in version for .NET Standard if (image.Compression == PdfImageCompression.Group4Fax || image.Compression == PdfImageCompression.Group3Fax) { // Fax documents usually looks better if integer-ratio scaling is used // Fractional-ratio scaling introduces more artifacts int ratio = Math.Min(image.Width / width, image.Height / height); image.ResizeTo(image.Width / ratio, image.Height / ratio, PdfImageCompression.Group4Fax); } else if (image.ComponentCount >= 3 && image.BitsPerComponent == 8) { image.ResizeTo(width, height, PdfImageCompression.Jpeg, 90); } else { image.ResizeTo(width, height, PdfImageCompression.Flate, 9); } } } } // 2 Setup save options pdf.SaveOptions.Compression = PdfCompression.Flate; pdf.SaveOptions.UseObjectStreams = true; pdf.SaveOptions.RemoveUnusedObjects = true; pdf.SaveOptions.OptimizeIndirectObjects = true; pdf.SaveOptions.WriteWithoutFormatting = true; // 3. Remove structure information pdf.RemoveStructureInformation(); // 4. Flatten form fields // Controls become uneditable after that pdf.FlattenControls(); // 5. Clear metadata pdf.Metadata.Basic.Clear(); pdf.Metadata.DublinCore.Clear(); pdf.Metadata.MediaManagement.Clear(); pdf.Metadata.Pdf.Clear(); pdf.Metadata.RightsManagement.Clear(); pdf.Metadata.Custom.Properties.Clear(); foreach (XmpSchema schema in pdf.Metadata.Schemas) { schema.Properties.Clear(); } pdf.Info.Clear(false); // 6. Remove font duplicates pdf.ReplaceDuplicateFonts(); // 7. Unembed fonts foreach (PdfFont font in pdf.GetFonts()) { // Only unembed popular fonts installed in the typical OS. You can extend // the list of such fonts in the "if" statement below. if (font.Name == "Arial" || font.Name == "Verdana") { font.Unembed(); } } pdf.Save(compressedFile); } string message = string.Format( "Original file size: {0} bytes;\r\nCompressed file size: {1} bytes", new FileInfo(originalFile).Length, new FileInfo(compressedFile).Length ); MessageBox.Show(message); Process.Start(compressedFile); }
public static void Main() { // NOTE: // When used in trial mode, the library imposes some restrictions. // Please visit http://bitmiracle.com/pdf-library/trial-restrictions.aspx // for more information. const string originalFile = @"Sample Data\jpeg.pdf"; const string compressedFile = "OptimizeImages.pdf"; using (PdfDocument pdf = new PdfDocument(originalFile)) { foreach (PdfPage page in pdf.Pages) { foreach (PdfPaintedImage painted in page.GetPaintedImages()) { PdfImage image = painted.Image; // inline images can not be recompressed unless you move them to resources // using PdfCanvas.MoveInlineImagesToResources if (image.IsInline) { continue; } // image that is used as mask or image with attached mask are // not good candidates for recompression if (image.IsMask || image.Mask != null || image.Width < 8 || image.Height < 8) { continue; } // get size of the painted image int width = Math.Max(1, (int)painted.Bounds.Width); int height = Math.Max(1, (int)painted.Bounds.Height); if (width >= image.Width || height >= image.Height) { if (image.ComponentCount == 1 && image.BitsPerComponent == 1 && image.Compression != PdfImageCompression.Group4Fax) { image.RecompressWithGroup4Fax(); } else if (image.BitsPerComponent == 8 && image.ComponentCount >= 3 && image.Compression != PdfImageCompression.Jpeg && image.Compression != PdfImageCompression.Jpeg2000) { image.RecompressWithJpeg2000(10); // or image.RecompressWithJpeg(); } } else { if (image.Compression == PdfImageCompression.Group4Fax || image.Compression == PdfImageCompression.Group3Fax) { // Fax documents usually looks better if integer-ratio scaling is used // Fractional-ratio scaling introduces more artifacts int ratio = Math.Min(image.Width / width, image.Height / height); image.ResizeTo(image.Width / ratio, image.Height / ratio, PdfImageCompression.Group4Fax); } else if (image.ComponentCount >= 3 && image.BitsPerComponent == 8) { image.ResizeTo(width, height, PdfImageCompression.Jpeg, 90); } else { image.ResizeTo(width, height, PdfImageCompression.Flate, 9); } } } } pdf.Save(compressedFile); } string message = string.Format( "Original file size: {0} bytes;\r\nCompressed file size: {1} bytes", new FileInfo(originalFile).Length, new FileInfo(compressedFile).Length ); MessageBox.Show(message); Process.Start(compressedFile); }