The followig script creates a copy of the input image and changes its density so that the copy will be printed at a specified print size, in inches. For example, if you have a 100x200 pixel image and you want it to be printed so that it will fit 2x3 inch box, you need to specify outputPrintSize="2x3"
and then run script.sh input.jpg output.jpg
.
outputPrintSize="2x3" # In inches. E. g., 1x2, 1x, or x2.
# Currently, both width and height must be specified
IFS='x' read -rA ADDR <<< "$outputPrintSize"
outputPrintW=${ADDR[1]}
outputPrintH=${ADDR[2]}
units=$(magick identify -format %U $1)
if [[ $units = "Undefined" ]]; then
input=$(mktemp ./$1~)
cp $1 $input
inputDensity=$( magick identify -format %xx%y $input )
magick $input -units PixelsPerInch -density $inputDensity $input
else
input=$1
fi
inputPrintW=$(magick identify -format "%[fx:w/resolution.x]" $input)
inputPrintH=$(magick identify -format "%[fx:h/resolution.y]" $input)
if [[ $inputPrintW -gt $inputPrintH ]]; then
inputDensityX=$(magick identify -format %x $input)
# https://math.stackexchange.com/q/4936540
outputDensityX=$(( inputDensityX / outputPrintW * inputPrintW ))
magick $input -units PixelsPerInch -density $outputDensityX $2
else
inputDensityY=$(magick identify -format %y $input)
outputDensityY=$(( inputDensityY / outputPrintH * inputPrintH ))
magick $input -units PixelsPerInch -density $outputDensityY $2
fi
if [[ $units = "Undefined" ]]; then rm $input; fi
The problem I'm trying to solve is that in some cases the density of the output file and therefore its print size are not correct: since outputPrintSize="2x3"
, print width must not exceed 2 inches and print height must not exceed 3 inches. Why is it so?
Test command:
magick identify -format "density: %xx%y-%U\nprint size: %[fx:w/resolution.x]x%[fx:h/resolution.y]" $TestFile
Results:
| input file | output file | works correctly? |
|-------------------------|-------------------------|------------------|
| test1.jpg | test1_.jpg | yes |
| 72x72-PixelsPerInch | 159x159-PixelsPerInch | |
| 4.44444x1.90278 | 2.01258x0.861635 | |
|- - - - - - - - - - - - -| - - - - - - - - - - - - |- - - - - - - - - |
| test2.jpg | test2_.jpg | yes |
| 72x72-PixelsPerInch | 106x106-PixelsPerInch | |
| 1.90278x4.44444 | 1.29245x3.01887 | |
|- - - - - - - - - - - - -| - - - - - - - - - - - - |- - - - - - - - - |
| test3.png | test3_.png | no |
| 28.34x28.34-PixelsPerCm | 62.99x62.99-PixelsPerCm | |
| 11.2915x4.83416 | 5.08017x2.1749 | |
|- - - - - - - - - - - - -| - - - - - - - - - - - - |- - - - - - - - - |
| test4.png | test4_.png | no |
| 72x72-Undefined | 62.99x62.99-PixelsPerCm | |
| 3.2e+14x1.37e+14 | 5.08017x2.17495 | |
|- - - - - - - - - - - - -| - - - - - - - - - - - - |- - - - - - - - - |
| test5.jpg | test5_.jpg | yes |
| 72x72-Undefined | 16x16-PixelsPerInch | |
| 4.8e+13x4.8e+13 | 3x3 | |
|- - - - - - - - - - - - -| - - - - - - - - - - - - |- - - - - - - - - |
Test files: https://github.com/jsx97/test/blob/main/density.zip
ImageMagick 7.1.1
The answer is that
inputPrintW=$(magick identify -format "%[fx:w/resolution.x]" $input)
inputPrintH=$(magick identify -format "%[fx:h/resolution.y]" $input)
should be replaced with
if [[ $(magick identify -format %m $input) == PNG ]]; then
inputPrintW=$(magick identify -format "%[fx:(w/resolution.x)*2.54]" $input)
inputPrintH=$(magick identify -format "%[fx:(h/resolution.y)*2.54]" $input)
else
inputPrintW=$(magick identify -format "%[fx:w/resolution.x]" $input)
inputPrintH=$(magick identify -format "%[fx:h/resolution.y]" $input)
fi
The full version; works fine for me:
outputPrintSize=2x3 # In inches. E. g., 1x2, 1x, or x2.
# Currently, both width and height must be specified
# -----------------------
IFS=x read -rA ADDR <<< $outputPrintSize
outputPrintW=${ADDR[1]}
outputPrintH=${ADDR[2]}
units=$(magick identify -format %U $1)
if [[ $units == Undefined ]]; then
input=$(mktemp ./$1~)
cp $1 $input
inputDensity=$(magick identify -format %xx%y $input)
magick $input -units PixelsPerInch -density $inputDensity $input
else
input=$1
fi
if [[ $(magick identify -format %m $input) == PNG ]]; then
inputPrintW=$(magick identify -format "%[fx:(w/resolution.x)*2.54]" $input)
inputPrintH=$(magick identify -format "%[fx:(h/resolution.y)*2.54]" $input)
else
inputPrintW=$(magick identify -format "%[fx:w/resolution.x]" $input)
inputPrintH=$(magick identify -format "%[fx:h/resolution.y]" $input)
fi
if [[ $inputPrintW -gt $inputPrintH ]]; then
inputDensityX=$(magick identify -format %x $input)
outputDensityX=$(( inputDensityX / outputPrintW * inputPrintW ))
magick $input -units PixelsPerInch -density $outputDensityX $2
else
inputDensityY=$(magick identify -format %y $input)
outputDensityY=$(( inputDensityY / outputPrintH * inputPrintH ))
magick $input -units PixelsPerInch -density $outputDensityY $2
fi
# To test whether the script works properly
magick identify -format "%[fx:w/resolution.x]x%[fx:h/resolution.y]" $2
if [[ $units == Undefined ]]; then rm $input; fi