views:

208

answers:

3

We are using a product called DynamicPDF to generate PDF's on the fly from dynamic data from a database. Their documentation says that their software leaves the image bytes intact and doesn't make any changes. Despite this, we have observed that the images we add seem to have quality loss on the resulting PDF output (at least that's how they look). So my question is what do I need to do with the DynamicPDF API to ensure that the image quality output is equal or close to what I put in?

We are using Version 5.1.2 Build 13650, below is the code that we use to add the image.

private void plcImageMain_LaidOut(object sender, PlaceHolderLaidOutEventArgs e)
{
 if (e.LayoutWriter.RecordSets.Current.HasData)
 {
         string productId = e.LayoutWriter.RecordSets.Current["ProductId"].ToString();
         string imgUrl = base.SetImageUrlParams(e.LayoutWriter.RecordSets.Current["ImageUrl"] as string, e.ContentArea.Width, e.ContentArea.Height);

         System.Drawing.Bitmap bm = base.GetBitmap(imgUrl);

         ceTe.DynamicPDF.PageElements.Image img = new ceTe.DynamicPDF.PageElements.Image(bm, 0, 0);
         img.Height = e.ContentArea.Height;
         img.Width = e.ContentArea.Width;
         e.ContentArea.Add(img);
 }
}

/// <summary>
/// Gets a bitmap from the requested image url
/// </summary>
/// <param name="imgCtrl"></param>
/// <param name="imgUrl"></param>
protected System.Drawing.Bitmap GetBitmap(string imgUrl)
{
 // TODO: Add some validation to ensure the url is an image.
 System.Net.WebRequest httpRequest = System.Net.HttpWebRequest.Create(imgUrl);

 using (System.Net.HttpWebResponse httpResponse = httpRequest.GetResponse() as System.Net.HttpWebResponse)
 using (Stream imgStream = httpResponse.GetResponseStream())
 {
    System.Drawing.Bitmap bm = System.Drawing.Bitmap.FromStream(imgStream) as System.Drawing.Bitmap;
    return bm;
 }
}

[Edit]

Here is the before and after screenshot.

[Edit]

Code using GetImage (why so slow?)

protected ceTe.DynamicPDF.Imaging.ImageData GetImageData(string imgUrl)
{
   ImageData imgData = null;
   using (System.Net.WebClient wc = new System.Net.WebClient())
   {
     imgData = ImageData.GetImage(wc.DownloadData(imgUrl));
   }
  return imgData;
}

GetImageData ("http://s7d2.scene7.com/is/image/SwissArmy/cm_vm_53900E--111mm_sol_front_a?fmt=jpeg&amp;wid=400&amp;hei=640");
+1  A: 

All right, this looks like poor effort at resizing but it could just as well be your Acrobat reader doing it on screen, with the actual data being perfectly fine.

You should be able to select an image by clicking it in Reader (so it's highlighted blue) and then copy and paste it to an image editing program of your choice. That way, you should get the resource in original solution no matter what it's scaled down to.

There are also tools to extract images and other resources from PDFs, but I don't know one I can recommend offhand.

Pekka
+1 for your effort. The text in the PDF highlights but the images do not. Is there a setting I need to turn on?
James
I'm not sure, I can highlight it right away. Check the "tools" menu in the latest version of Acrobat reader, you should get a selection of selection tools there. One of them should work.
Pekka
+1  A: 

In regards to the DynamicPDF product, there is not any resizing or resampling done to the image as it is added to the PDF document. Pekka is actually right on with this. It is the reader that is visually representing the image with differing clarity (at different zoom levels).

If you are able to pull the image out of the PDF (as Pekka recommends above) you will see the image data is completely original and not modified.

One additional thing you can do to demonstrate this would be to take your original image, right click on it and select "Convert To Adobe PDF" (requires full Acrobat Pro). In that newly created PDF you would also visually see the same results.

One final thing worth noting is just a smalll inefficiency in the code you displayed above. Right now you are pulling the image content as a Stream, creating a bitmap out of that Stream object and then using that bitmap to create the DynamicPDF Image object. The recommended way to accomplish this would be to take the Stream object of the image that you are pulling from the URL, pass this into the DynamicPDF's ImageData Static method "GetImage". This GetImage method will return the ImageData object. Then use that ImageData to create your DynamicPDF Image object out of.

There are two clear advantages to loading the image this way. First is that you do not have the overhead involved with the System.Drawing.Bitmap object needing to separately process the image content (so in theory the app would run faster without this). And the second advantage is that the image content is added to the PDF in whatever native compression that it was originally in. As in the case of JPEG images, using the image’s native compression as opposed to the bitmap’s compression will result in a smaller output PDF file size. None of this will have any influence on the image quality of the output PDF but it could affect the efficiency and output PDF file size.

I hope this helps and feel free to update us if you have any further questions.

Thanks, Robbie Watkins ceTe Software, www.dynamicpdf.com

Robbie
+1 Thanks for help on this one. I followed your suggestion of using ImageData.GetImage(). But i'm finding that it's now incredibly slower than my old implementation. Why is that? My new code is above.
James
A: 

You were both right that it was Acrobat that was causing the fuzzy display. There is a setting in preferences called resolution, instead of using the System dpi setting by default Acrobat decided to use a custom dpi setting of 110 (I have no idea why!?!?). After setting it to system (in my case 96dpi) the images were crystal clear.

James