Hi,
I am trying to compress PDF files using PDF sharp 1.5.
I am able to find both DCTDecode and FlateCode. As per my understanding these are JPG/JPEG and PNG streams respectively. I am able to compress DCTDecode images. But I am unable to compress FlateDecode streams.
I tried 2 Approaches to compress FlateDecode. 1) Use FlateDecode compression c# code 2) Replace FlateDecode with DTCDecode
In approach 1 I am getting the compressed PDF generated but the PNG image is getting distorted
In approach 2, I am getting the PDF corrupted
Interestingly I am able to successfully extract both types of images from PDF's
Please find both functions pasted below. It will be great if any experts can point out the mistake I am doing here.
==========================================================
Approach 1 Compression
==========================================================
private static void CompressPngImage(ref PdfDictionary image, ref int count)
{
int width = image.Elements.GetInteger(PdfImage.Keys.Width);
int height = image.Elements.GetInteger(PdfImage.Keys.Height);
var canUnfilter = image.Stream.TryUnfilter();
byte[] decodedBytes;
if (canUnfilter)
{
decodedBytes = image.Stream.Value;
}
else
{
PdfSharp.Pdf.Filters.FlateDecode flate = new PdfSharp.Pdf.Filters.FlateDecode();
decodedBytes = flate.Decode(image.Stream.Value);
}
int bitsPerComponent = 0;
while (decodedBytes.Length - ((width * height) * bitsPerComponent /
!= 0)
{
bitsPerComponent++;
}
System.Drawing.Imaging.PixelFormat pixelFormat;
switch (bitsPerComponent)
{
case 1:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format1bppIndexed;
break;
case 8:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format8bppIndexed;
break;
case 16:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format16bppArgb1555;
break;
case 24:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
break;
case 32:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format32bppArgb;
break;
case 64:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format64bppArgb;
break;
default:
throw new Exception("Unknown pixel format " + bitsPerComponent);
}
decodedBytes = decodedBytes.Reverse().ToArray();
Bitmap bmp = new Bitmap(width, height, pixelFormat);
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
int length = (int)Math.Ceiling(width * (bitsPerComponent / 8.0));
for (int i = 0; i < height; i++)
{
int offset = i * length;
int scanOffset = i * bmpData.Stride;
Marshal.Copy(decodedBytes, offset, new IntPtr(bmpData.Scan0.ToInt64() + scanOffset), length);
}
bmp.UnlockBits(bmpData);
bmp.RotateFlip(RotateFlipType.Rotate180FlipNone);
var TempPNGStream1 = new MemoryStream();
var TempPNGStream = new MemoryStream();
bmp.Save(TempPNGStream, ImageFormat.Png);
byte[] ImageBytes = ImageMagic.QualityEncode(TempPNGStream, ImageFormat.Png).ToArray();
ImageBytes=ImageMagic.QualityEncode(TempPNGStream, ImageFormat.Png).ToArray();
TempPNGStream.Write(ImageBytes, 0, ImageBytes.Length);
Bitmap bmp1 = new Bitmap(TempPNGStream);
BitmapData bmpData1 = bmp1.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp1.PixelFormat);
byte[] data = new byte[Math.Abs(bmpData.Stride * bmpData.Height)];//applied bmpData instead of bmpData1
Marshal.Copy(bmpData1.Scan0, data, 0, data.Length);
decodedBytes = data;//.Reverse().ToArray();
PdfSharp.Pdf.Filters.FlateDecode flate1 = new PdfSharp.Pdf.Filters.FlateDecode();
image.Stream.Value = decodedBytes;// flate1.Decode(decodedBytes);
TempPNGStream1.Write(decodedBytes, 0, decodedBytes.Length);
bmp.Save(TempPNGStream1, ImageFormat.Jpeg);
bmp.Save("D:\\CustomCompression\\Uploaded through API\\RE9fQURfMTU2Nl8yNDRfMjAwMQ==/"+String.Format("Image{0}.png", count++), System.Drawing.Imaging.ImageFormat.Png);
}
===========================================================================
Approach 2 Replace FlateDecode with DCTDecode
===========================================================================
private static void ReplacePngImageDictionaryWithJpg(ref PdfDictionary image, ref int count)
{
int width = image.Elements.GetInteger(PdfImage.Keys.Width);
int height = image.Elements.GetInteger(PdfImage.Keys.Height);
var canUnfilter = image.Stream.TryUnfilter();
byte[] decodedBytes;
if (canUnfilter)
{
decodedBytes = image.Stream.Value;
}
else
{
PdfSharp.Pdf.Filters.FlateDecode flate = new PdfSharp.Pdf.Filters.FlateDecode();
decodedBytes = flate.Decode(image.Stream.Value);
}
int bitsPerComponent = 0;
while (decodedBytes.Length - ((width * height) * bitsPerComponent /
!= 0)
{
bitsPerComponent++;
}
System.Drawing.Imaging.PixelFormat pixelFormat;
switch (bitsPerComponent)
{
case 1:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format1bppIndexed;
break;
case 8:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format8bppIndexed;
break;
case 16:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format16bppArgb1555;
break;
case 24:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format24bppRgb;
break;
case 32:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format32bppArgb;
break;
case 64:
pixelFormat = System.Drawing.Imaging.PixelFormat.Format64bppArgb;
break;
default:
throw new Exception("Unknown pixel format " + bitsPerComponent);
}
decodedBytes = decodedBytes.Reverse().ToArray();
Bitmap bmp = new Bitmap(width, height, pixelFormat);
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
int length = (int)Math.Ceiling(width * (bitsPerComponent / 8.0));
for (int i = 0; i < height; i++)
{
int offset = i * length;
int scanOffset = i * bmpData.Stride;
Marshal.Copy(decodedBytes, offset, new IntPtr(bmpData.Scan0.ToInt64() + scanOffset), length);
}
bmp.UnlockBits(bmpData);
bmp.RotateFlip(RotateFlipType.Rotate180FlipNone);
var TempPNGStream1 = new MemoryStream();
var TempPNGStream = new MemoryStream();
bmp.Save("D:\\CustomCompression\\Uploaded through API\\RE9fQURfMTU2Nl8yNDRfMjAwMQ==/" + String.Format("Image{0}.png", count++), System.Drawing.Imaging.ImageFormat.Png);
bmp.Save("D:\\CustomCompression\\Uploaded through API\\RE9fQURfMTU2Nl8yNDRfMjAwMQ==/" + String.Format("Image{0}.jpg", count++), System.Drawing.Imaging.ImageFormat.Jpeg);
bmp.Save(TempPNGStream, ImageFormat.Jpeg);
string CurrentColorSpace = image.Elements.GetName("/ColorSpace");
image.Stream.Value = TempPNGStream.ToArray().ToArray();
image.Elements.SetValue("/Height", new PdfInteger(bmp.Height));
image.Elements.SetValue("/Width", new PdfInteger(bmp.Width));
image.Elements.SetValue("/Length", new PdfInteger(image.Stream.Value.Length));
image.Elements.SetValue("/ColorSpace", new PdfString(CurrentColorSpace));
image.Elements.SetValue("/Filter", new PdfString("/DCTDecode"));
image.Elements.SetValue("/Type", new PdfString("/XObject"));
image.Elements.SetValue("/Name", new PdfString("/Im0")); //new PdfString(String.Format("Image{0}.jpg", count++)));
image.Elements.Remove("/Interpolate");
image.Elements.Remove("/DecodeParams");
}
Thanks
Praveen