MacOS – Resized/Rotated PNG image using ImageMagic is blury. How to sharpen

graphicsimage processingmacosprinting

When I try to resize (shrink, in this case) and/or rotate a PNG file, it becomes very blurry. Besides (obviously) not wanting a blurry image, it's actually critical because these are shipping labels with bar codes and the image is so bad, bar code readers actually have trouble with them.

The command that I am using is

% convert input_file.png -resize 288 -rotate -90 output_file.png
  • -resize 288 → resize to a width of 288 pixels (4 inches) keeping the aspect ratio. 288 is the number of pixels for a 72DPI (printing) resolution
  • -rotate -90 → rotates the whole image anti-clockwise 90°

The file that you get from eBay, USPS Click-n-Ship, or PayPal is a 4×6 inch label either in PNG or PDF. I choose PNG since I need to rotate it as I'm using my laser printer with letter sized labels (Avery 8127). I have to resize it because the PNG they provide is huge! Looking at the size in Preview, it's 17×25 inches.

I have researched this extensively, but the solutions I've found only marginally improve the sharpness of image. The end result is that depending on the bar code reader it may or may not read it. For example, I have two readers – a simple 2D Symbol bar code reader that more often than not will fail. However, my more expensive Focus 3D reader will read it more often, but still sometimes fail.

None of these worked.

I was under the impression that if I make an image smaller, I wouldn't lose quality however, this doesn't seem to be the case. So, my question is, how can I resize this image so that I can retain the quality?

Best Answer

The trick here is to increase the density(resolution) of the original image before doing any other processing like resizing or rotating.

% convert -density 300 inputfile.png inputfile.png

Normally, it would be necessary to specify the units (-units PixelsPerInch or -units PixelsPerCentimeter) along with density, but since PNG files only use the pixels /cm unit, it's not necessary here.

The reason we have to do this is because to resize an image, it must pass through one (or more) of several filters (algorithms). With a low resolution (like 72 dpi for printing) there simply isn't enough data for the algorithms to use for their calculations. ImageMagick has a lenghthy section on resizing and the different filters you can use and how they work: https://legacy.imagemagick.org/Usage/resize/#other. Unfortunately, none worked well enough until I realized that the data in the image was just too "thin."

By doing nothing other than increasing the density we're essentially giving the same element (a single bar code line for example) more data points to work with when we do manipulate the image later on. The more it has, the more accurate it can be though the trade off is speed. It will take longer to process.

By doing this first and then manipulating the image, I was able to achieve a crisp and clear image at the size I needed for printing on my laser printer. The other option I had was to purchase a dedicated label printer (like the Zebra or Brother printers) so I could use the high quality PDF they supplied.

Below is a more step-by-step process of how to manipulate the image to get the desired result


If we look at the resolution of the original image file (identify -ping -verbose image.png | head) we see that it's set for a resolution of 28.35x28.35 ppcm and a print size of 42.328cm x 63.4921cm (16.66" x 25").

  Filename: sample_label_orig.png
  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: PseudoClass
  Geometry: 1200x1800+0+0
  Resolution: 28.35x28.35
  Print size: 42.328x63.4921
  Units: PixelsPerCentimeter
  Colorspace: Gray

Since everything is metric, to convert to inches, multiply by 2.54. 28 ppcm translates to 72 ppi (or 72 DPI). This is supposedly the correct DPI for printing.

You can use the same filename for both input and output so it makes the changes "in place." I'm using a separate file for this example.

% convert -density 300 sample_label_orig.png sample_label.png 

When the density/resolution is increased to 300 ppcm, everything falls into place. However, don't be fooled by the new print size though; it's 4cm x 6cm not 4" x 6"!

  Filename: sample_label.png
  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: PseudoClass
  Geometry: 1200x1800+0+0
  Resolution: 300x300
  Print size: 4x6
  Units: PixelsPerCentimeter
  Colorspace: Gray

Now, instead of resizing the label, we simply specify the new label geometry. Note that geometry not the print size of the label. It's the dimensions of the label multiplied by the density. So, a 4x6 inch label would be 10.16x15.24 cm meaning the final geometry would be 300*(10.15x15.24) = 3048x4572.

% convert sample_label.png -geometry 3048x4572 label_out.png

Now, when we look at the details of the label (identify -ping -verbose label_out.png | head), everything is as it should be. It's a 4x6 inch label (converted from cm) with a 300 ppcm resolution

  Filename: label_out.png
  Format: PNG (Portable Network Graphics)
  Mime type: image/png
  Class: PseudoClass
  Geometry: 3048x4572+0+0
  Resolution: 300x300
  Print size: 10.16x15.24
  Units: PixelsPerCentimeter
  Colorspace: Gray

We can even rotate the label at the same time we change the geometry to make the process more efficient.

% convert sample_label.png -geometry 3048x4572 -rotate -90 label_out.png

This will create a crisp and clear label in the correct orientation to be printed on the laser printer.