How can I change (resample/downscale) resolution of images embedded in a PDF?

223 views
Skip to first unread message

Support

unread,
Aug 28, 2009, 7:37:26 PM8/28/09
to PDFTron PDFNet SDK
Q: We are working on a product which generates a flash file from a PDF
document uploaded. If the PDF document contains any images (grayscale/
Monochrome/Color) we want to compress the images to different DPI
based on their format.
Ex. If color images are more than 150 DPI we want to compress them to
150 DPI
If Greyscale images are more than 200 DPI we want to compress them
to 200 DPI.

Could you please let me know where I sand find a relevant C# sample
for compression of images and also how to find out the current DPI of
the images in PDF.

--------
A: You may want to search PDFNet Forum (http://groups.google.com/group/
pdfnet-sdk/) or KB for keywords such as "PDF Optimize", "replace
images", to find more in-depth discussion of how to implement PDF
optimization and image resampling using PDFNet.

The basic idea is outlined in the following C# code snippet (the logic
should be fairly simple in C++, Java, or some other language):

// This code snippet is a rough code sketch which you could use as a
starting
// point to implement image reduction (image downscaling) in PDF.
// The sample is based on JBIG2 Test sample (http://www.pdftron.com/
pdfnet/samplecode.html#JBIG2)

PDFNet.Initialize();
pdfDocument = new PDFDoc(bookControl.PdfFilepath);
pdfDocument.InitSecurityHandler();

// Do the resampling of the pages
ProcessPages(reductionFactor); // See functions below

pdfDocument.Save(filepath, SDFDoc.SaveOptions.e_linearized);
pdfDocument.Close();


//-------------------------------------------------------
private void ProcessPages(float reductionFactor) {
// Get the number of objects from the file
int num_objs = sdfDocument.XRefSize();

for (int i = 1; i < num_objs; ++i)
{
Obj obj = sdfDocument.GetObj(i);
if (obj != null && !obj.IsFree() && obj.IsStream())
{
// Process only images
DictIterator itr = obj.Find("Subtype");

if (itr.HasNext() && itr.Value().GetName() == "Image")
{
ProcessGDIImage(ref obj, itr, i, reductionFactor);
}
}
}
}

//-------------------------------------------------------
private void ProcessGDIImage(ref Obj obj, DictIterator itr, int i,
float resFactor) {
try
{
pdftron.PDF.Image input_image = new pdftron.PDF.Image(obj);
pdftron.PDF.Image new_image = null;

int bpc = input_image.GetBitsPerComponent();

// Only process the 8 bits per pixel images
if (bpc == 8)
{
// Get the GDI+ Bitmap
Bitmap bm = input_image.GetBitmap();

// Create the new image
new_image = pdftron.PDF.Image.Create(sdfDocument, SetResolution
(bm, resFactor));

Obj new_img_obj = new_image.GetSDFObj();

// Copy any important entries from the image dictionary
itr = obj.Find("Decode");
if (itr.HasNext()) new_img_obj.Put("Decode", itr.Value());

itr = obj.Find("ImageMask");
if (itr.HasNext()) new_img_obj.Put("ImageMask", itr.Value());

itr = obj.Find("Mask");
if (itr.HasNext()) new_img_obj.Put("Mask", itr.Value());

// Take the document we have just created and swap it into the
document
sdfDocument.Swap(i, new_image.GetSDFObj().GetObjNum());
}
}
catch (Exception ex)
{
Log.WriteException(Severity.Warning, ex.Message, ex);
}
}

//-------------------------------------------------------
private Bitmap SetResolution(Bitmap bm, float conv_factor) {
// Change the resolution
// Get the horizontal Resolution
float eh = bm.HorizontalResolution;

// Create a new bitmap using a factor for width and height
Bitmap new_bm = new Bitmap((int)(conv_factor * bm.Width), (int)
(conv_factor * bm.Height));

// Use the GDI+ Graphics page to draw on
Graphics g = Graphics.FromImage(new_bm);

// Draw the new image at reduced resolution
g.DrawImage(bm, new Rectangle(0, 0, new_bm.Width, new_bm.Height), 0,
0, bm.Width, bm.Height, GraphicsUnit.Pixel);
g.Dispose();

return new_bm;
}


Regarding resolution of existing images (embedded in PDF) you may want
to take search for "How do I get the image resolution and DPI?" in
PDFNet FAQ (http://www.pdftron.com/pdfnet/faq.html) or search PDFNet
forum. Since a same image image may be used multiple times (using
different scale factors) the resolution may differ (so you may want to
pick the higher res?)


Reply all
Reply to author
Forward
0 new messages