使用iTextSharp压缩PDF的大小
将PDF中含有的图片压缩大小并转成灰度图,让PDF文件大幅下降
nuget 安装 iTextSharp
using iTextSharp.text.pdf;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
namespace Program
{
class Program
{
static void Main(string[] args)
{
string source = "C:\\Users\\xuxuzhaozhao\\Desktop\\PDFTest.pdf";
string destination = "C:\\Users\\xuxuzhaozhao\\Desktop\\1OUTPDFTest.pdf";
PdfReader reader = new PdfReader(source);
using (FileStream fs = new FileStream(destination, FileMode.Create, FileAccess.Write, FileShare.None))
{
using (PdfStamper stamper = new PdfStamper(reader, fs))
{
PdfDictionary page;
int pageCount = reader.NumberOfPages;
for (int i = 1; i <= pageCount; i++)
{
page = reader.GetPageN(i);
foreach (var obj in FindImageInPDFDictionary(page))
{
if (obj == null) continue;
iTextSharp.text.Image pdfImage = null;
int XrefIndex = Convert.ToInt32(((PRIndirectReference)obj).Number.ToString(System.Globalization.CultureInfo.InvariantCulture));
PdfObject pdfObj = reader.GetPdfObject(XrefIndex);
PdfStream pdfStrem = (PdfStream)pdfObj;
byte[] bytes = PdfReader.GetStreamBytesRaw((PRStream)pdfStrem);
if (bytes == null) continue;
try
{
using (var memStream = new MemoryStream(bytes))
{
memStream.Position = 0;
System.Drawing.Image img = null;
if (i == 1 || i == pageCount)
{
img = System.Drawing.Image.FromStream(memStream);
}
else
{
System.Drawing.Image Image = System.Drawing.Image.FromStream(memStream);
Bitmap bitmap = ImageHelper.ResizeImage(Image, .35M);
img = BitmapToGrayscale(bitmap);
}
ImageFormat format = img.PixelFormat == PixelFormat.Format1bppIndexed
|| img.PixelFormat == PixelFormat.Format4bppIndexed
|| img.PixelFormat == PixelFormat.Format8bppIndexed
? ImageFormat.Tiff
: ImageFormat.Jpeg;
pdfImage = iTextSharp.text.Image.GetInstance(img, format);
}
PdfReader.KillIndirect(obj);
} catch { }
if (pdfImage != null)
{
stamper.Writer.AddDirectImageSimple(pdfImage, (PRIndirectReference)obj);
}
}
}
}
}
}
private static List<PdfObject> FindImageInPDFDictionary(PdfDictionary pg)
{
List<PdfObject> resultList = new List<PdfObject>();
PdfDictionary res = (PdfDictionary)PdfReader.GetPdfObject(pg.Get(PdfName.RESOURCES));
PdfDictionary xobj = (PdfDictionary)PdfReader.GetPdfObject(res.Get(PdfName.XOBJECT));
if (xobj != null)
{
foreach (PdfName name in xobj.Keys)
{
PdfObject obj = xobj.Get(name);
if (obj.IsIndirect())
{
PdfDictionary tg = (PdfDictionary)PdfReader.GetPdfObject(obj);
PdfName type = (PdfName)PdfReader.GetPdfObject(tg.Get(PdfName.SUBTYPE));
//image at the root of the pdf
if (PdfName.IMAGE.Equals(type))
{
resultList.Add(obj);
}// image inside a form
else if (PdfName.FORM.Equals(type))
{
resultList.AddRange(FindImageInPDFDictionary(tg));
} //image inside a group
else if (PdfName.GROUP.Equals(type))
{
resultList.AddRange(FindImageInPDFDictionary(tg));
}
}
}
}
return resultList;
}
public static class ImageHelper
{
/// <summary>
/// Resize the image to the specified width and height.
/// </summary>
/// <param name="image">The image to resize.</param>
/// <param name="width">The width to resize to.</param>
/// <param name="height">The height to resize to.</param>
/// <returns>The resized image.</returns>
public static Bitmap ResizeImage(System.Drawing.Image image, int width, int height)
{
var destRect = new System.Drawing.Rectangle(0, 0, width, height);
var destImage = new System.Drawing.Bitmap(width, height);
destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
using (var graphics = Graphics.FromImage(destImage))
{
graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
using (var wrapMode = new ImageAttributes())
{
wrapMode.SetWrapMode(WrapMode.TileFlipXY);
graphics.DrawImage(image, destRect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, wrapMode);
}
}
return destImage;
}
public static Bitmap ResizeImage(System.Drawing.Image image, decimal percentage)
{
int width = (int)Math.Round(image.Width * percentage, MidpointRounding.AwayFromZero);
int height = (int)Math.Round(image.Height * percentage, MidpointRounding.AwayFromZero);
return ResizeImage(image, width, height);
}
}
public static Bitmap BitmapToGrayscale(Bitmap source)
{
// Create target image.
int width = source.Width;
int height = source.Height;
Bitmap target = new Bitmap(width, height, PixelFormat.Format8bppIndexed);
// Set the palette to discrete shades of gray
ColorPalette palette = target.Palette;
for (int i = 0; i < palette.Entries.Length; i++)
{
palette.Entries[i] = Color.FromArgb(0, i, i, i);
}
target.Palette = palette;
// Lock bits so we have direct access to bitmap data
BitmapData targetData = target.LockBits(new System.Drawing.Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
BitmapData sourceData = source.LockBits(new System.Drawing.Rectangle(0, 0, width, height),
ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
unsafe
{
for (int r = 0; r < height; r++)
{
byte* pTarget = (byte*)(targetData.Scan0 + r * targetData.Stride);
byte* pSource = (byte*)(sourceData.Scan0 + r * sourceData.Stride);
for (int c = 0; c < width; c++)
{
byte colorIndex = (byte)(((*pSource) * 0.3 + *(pSource + 1) * 0.59 + *(pSource + 2) * 0.11));
*pTarget = colorIndex;
pTarget++;
pSource += 3;
}
}
}
target.UnlockBits(targetData);
source.UnlockBits(sourceData);
return target;
}
}
}