This project has moved. For the latest updates, please go here.

Converting from PDF to PNG image quality loss.

Mar 24 at 9:22 AM
Using the follow code to convert a PDF in the form of a byte array to a PNG image.

It's converting it successfully and the PNG image is the correct size, 4 inches by 6 inches. The problem is the quality of the PNG its extremely blurred.

I've experimented with increased the density but it seems to be making little difference.
using (ImageMagick.MagickImage image = new ImageMagick.MagickImage(label.Label.Data))
{
    ImageMagick.Density density = new ImageMagick.Density(400, ImageMagick.DensityUnit.PixelsPerInch);
    ImageMagick.MagickGeometry geometry = density.ToGeometry(4, 6);

    image.Density = density;

    image.Resize(geometry);

    // Sets the output format to Png
    image.Format = ImageMagick.MagickFormat.Png;

    // Create byte array that contains a Png 
    byte[] data = image.ToByteArray();
}
Coordinator
Mar 24 at 2:55 PM
You will need to set the Density in the MagickReadSettings and use that as an argument for the constructor.
Mar 27 at 7:59 AM
I tried that method before the one I've shown above, both out putted a blurred PNG image.
Coordinator
Mar 27 at 10:48 AM
Can you share a link to your input file? I can test it at the end of this week.
Mar 27 at 12:20 PM
Not easily, we're reading in the image as a byte array returned from a third party API.
Coordinator
Mar 27 at 3:17 PM
You could do a File.WriteAllBytes so save the bytes as a file and put that on something like dropbox?
Mar 28 at 9:13 AM
Excellent Idea,

here is the PDF file.

We're attempting to convert it to an PNG that is 4inchs in width and 6inches in length with the clearest quality possible.

https://www.dropbox.com/s/p2x8vfcxw0zxnle/test.pdf?dl=0
Coordinator
Mar 31 at 2:13 PM
Edited Mar 31 at 2:27 PM
You should use two separate density settings:
MagickReadSettings settings = new MagickReadSettings()
{
  Density = new Density(600)
};

using (MagickImage image = new MagickImage(@"d:\images\pdf\parcelforce.pdf", settings))
{
  Density desiredDensity = new Density(400);
  MagickGeometry geometry = desiredDensity.ToGeometry(4, 6);

  image.Resize(geometry);

  // Sets the output format to Png
  image.Format = MagickFormat.Png;

  // Create byte array that contains a Png 
  byte[] data = image.ToByteArray();
}
The first one is what you want it to be when the image is read and the second one is what you want it to be when the image is printed. You need to do this because when you use 400 for both values you will resize the image to a bigger size and that will have a bad affect on the quality. With this I get a good output image. But the logo is stored with a terrible quality in the image. You cannot make this better.
Apr 3 at 9:16 AM
Should I expect the same result when passing in a byte[] into the constructor on MagickImage?

I've taken the code you provided above and replaced the local pdf path with a byte[] but the image is huge, it doesn't appear like its being resized?
Apr 3 at 9:46 AM
I'm expecting to the outputed PNG to be 4inchs in width and 6inchs in height.

.ToGeometry(4, 6); should achieve this, correct?
Apr 3 at 9:57 AM
Changing the code to do the following;

Density desiredDensity = new Density(94);
Specifying 94 instead of 400 gives me a label the size I expected but the quality is awful, so I can only assume this is not the correct method.

Thanks for your assistance with this also, it's much appreciated :)
Coordinator
Apr 3 at 12:53 PM
When I change 400 to 94 I will get an image with a different size. The quality is still pretty good for me. Can you share your output image somewhere? I am getting the following image with the file you provided: https://www.dropbox.com/s/8jv30oxcwi4xah2/parcelforce.png?dl=0
Apr 3 at 12:58 PM
Ours look very similar, if not the same. It looks acceptable when viewed on a computer but the bar codes are totally unusable when printed.

Is changing the Density the only way of reducing its size? What does the ToGeometry function do?
Coordinator
Apr 3 at 1:09 PM
Edited Apr 3 at 1:09 PM
The ToGeometry function returns the pixels size of the image at the density (inch size) that you specified. I think the print quality is bad because the image density is still set to 600. What happens when you change the desiredDensity part to this:
image.Density = new Density(94);
MagickGeometry geometry = image.Density.ToGeometry(4, 6);
Apr 3 at 2:08 PM
Whilst that outputted a similar file, I changed the Density from 94 to 600 and the outputted image is perfect!

So the ToGeometry() method must only work when calling from the Image model, instead of the 'desiredDensity' like before?
Coordinator
Apr 3 at 4:02 PM
The ToGeometry method works in both situations. Just got rid of the variable because you don't really need it. The method is actually really simple: https://github.com/dlemstra/Magick.NET/blob/master/Source/Magick.NET/Core/Types/Density.cs#L227. It just multiplies the width and height you specify with the density.

And I wonder if you really need 600. Setting it to 300 should probably be enough. If you want to keep it at 600 you should probably change the value of settings.Density to a higher value because you are resizing the image.