Resized/Rotated PNG image using ImageMagic is blury. How to sharpen?
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 4x6 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 17x25 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.
-
Imagemagick converted image is blurry
-
ImageMagick v6 Examples -- Blurring and Sharpening Images
-
Blurry resized PNG. How do I keep the quality the image?
-
ImageMagick v6 Examples -- Resize or Scaling (General Techniques)
From this page
However, many filters (even the default filters) can blur images slightly. It is part of their nature. So normally this 'short-circuit' for a no-op resize a good thing.
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?
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.