Imagemagick Crop command not giving perfect result - php

I am using Imagemagick for resizing and cropping image.
Test Image :
I need to re-size it for 300 x 320 frame for this first I am resizing the image and then cropping it and i am using the following commands:
exec("convert /uploadImagePath -thumbnail 300 /newImagePath");
exec("convert /newImagePath -gravity Center -crop 290x310+0+0 /newImagePath");
But it gives me following image
As you can see image is not complete. Where am I mistaken?

(Answer is updated, providing an illustrated example for -liquid-rescale further below now)
Your original image's dimensions are:
489 x 640 pixels
Your desired dimensions seem to be:
290 x 310 pixels
This cannot scale to these dimensions without either:
cropping (do not keep all areas of the intial image)
keeping desired width (give up desired height)
keeping desired height (give up desired width)
distortion (do not keep the aspect ratio when scaling)
padding (add more pixels to one or more edges)
removing pixels where it's not obvious ("liquid rescale" or "seam carving" -- see Wikipedia)
Your result shows '1.' (cropping), which you don't like. So you have options '2.' (keeping width), '3.' (keeping height), '4.' (distortion), '5.' (padding) and '6.' (seam carving) left to test.
'2.': Keeping desired Height
convert WPTgp.jpg -resize x310 keep-height.jpg
Resulting Image has dimensions of 237 x 310 pixels.
Keep Height....
(determine width automatically)
'3.': Keeping desired Width
convert WPTgp.jpg -resize 290x keep-width.jpg
Resulting Image has dimensions of 290 x 380 pixels.
Keep Width.....
(determine height automatically)
'4.': Distortion
convert WPTgp.jpg -resize 290x310\! distorted.jpg
Resulting Image has dimensions of 290 x 310 pixels.
Distorted......
(ignore aspect ratio -- distort image if required to fit dimensions)
'5.': Padding
convert WPTgp.jpg \
-resize 290x310 \
-gravity center \
-background orange \
-extent 290x310 \
padded.jpg
Resulting Image has dimensions of 290 x 310 pixels. (Orange background was added only to demonstrate that the 'extention' of the image did work.)
Padded.........
(keep aspect ratio -- extend image for desired dimensions)
'6.': Seam Carving
convert WPTgp.jpg -liquid-rescale 290x310\! liquid.jpg
The above would be the command you'd spontaneously derive from quick-reading the ImageMagick command options reference. However, it doesn't work well, and instead I used:
convert WPTgp.jpg -liquid-rescale 599x640\! -scale 290x310 liquid.jpg
convert WPTgp.jpg -liquid-rescale 599x640\! -scale 48.4% liquid.jpg
Further below is an explanation why I needed to modify it....
Liquid-rescaled
Sorry -- I cannot provide example picture right now; this requires the additional ImageMagick delegate liblqr (liquid rescaling library) to be installed, which I don't have at this moment) I've now had the opportunity to create a 'liquidly rescaled' version of the original image.
Caveats about Seam Carving / '-liquid-rescale':
As stated above, the last image is not the result of my originally proposed command, but of one of these two modified versions:
convert WPTgp.jpg -liquid-rescale 599x640\! -scale 290x310 liquid.jpg
convert WPTgp.jpg -liquid-rescale 599x640\! -scale 48.4% liquid.jpg
Remember, we have an original image of 489x610 pixels, which we are expected to scale to 290x310 pixels. But -liquid-rescale isn't good at rescaling in two dimensions at once -- it's designed to scale into one direction only (horizontal or vertical). If you try to do both at once, results may not be what you'd expect. Here is the result for the originally proposed command:
convert WPTgp.jpg -liquid-rescale 290x310\! liquid.jpg
LQR gone wrong
That's why I came up with the two modified commands which work in two steps:
First, apply liquid rescaling to the horizontal dimension only, expanding the original's width from 489 pixels to 599 pixels.
Second, apply 'normal' aspect-ratio-keeping scaling to the intermediate result to produce the final image.

Try:
$inputFile = "WPTgp.jpg";
exec("convert {$inputFile} -resize 290x310^ -gravity Center -crop 290x310+0+0 picCropped.png");

Related

How to reduce quality (filesize) for animated gif with PHP (ImageMagick)?

I want to reduce the quality of an animated GIF to reduce GIF filesize. Animation and dimensions should stay the same.
Is this even possible?
I've tried various Imagemagick functions, but with no luck. Maybe someone has done this?
This is just a logical thinking, but it would be cool, if something like this would work:
$gif = new Imagick($tempFilePath);
$gif = $gif->coalesceImages();
foreach ($gif as $frame) {
$frame->setImageCompression(8);
$frame->setImageCompressionQuality(10);
}
$gif = $gif->deconstructImages();
$gif->writeImages($tempFilePath, true);```
GIF does not use compression. So your compression arguments will not do anything. In ImageMagick command line, the simplest way is just to reduce the number of colors in the animation.
Input (Mount St. Helens colorized):
convert animation.gif -coalesce +dither -colors 64 -layers optimize animation2.gif
I am not an Imagick expert, but I think what you want is quantizeImages, which I believe will reduce colors for an animation or set of images. See also the example at quantizeImage to reduce the colors of one single image.
Note that I first use -coalesce to fill out the frames. I use +dither to avoid dithering when reducing colors. And finally I re-optimize the animation.
However, the better way is to use one common color map for all frames and use as few colors as possible. Then also do layer optimization on the animation. This can be done as follows on this simple (extremely small number) 3-color example.
Input (Mount St. Helens colorized):
3-color Color Table (enlarged for viewing):
convert xc:red xc:green1 xc:blue +append colortable.gif
convert animation.gif -coalesce +dither -remap colortable.gif -layers optimize new_animation.gif
More practically, you can create a reduced color table by collecting all the colors from all the combined animation frames, reduce the colors and then get the unique colors. For example:
convert animation.gif -coalesce +append +dither -colors 64 -unique-colors -depth 8 colortable2.gif
Then apply this color table to the animation
convert animation.gif -coalesce +dither -remap colortable2.gif -layers optimize new_animation2.gif
The file sizes are:
animation.gif --- 481 K
animation2.gif (64 colors) --- 479 K
new_animation (3 colors) --- 57 K
new_animation2 (64 colors) --- 393 K
For Imagick, see the following methods:
coalesce
remap
append
uniquecolors
quantizeimage for reduced colors

PNG processing WITHOUT Image Magick and imagefrompng()

I need to change each hue of yellow to blue, and each hue of dark gray to light gray in PNG images with transparency.
The problem is:
I can't use Photoshop, because I have 100 images, and I need to change hues many time.
I can't use Image Magick, because I need more sophisticated calculations, than '-fx' can do.
I can't use PHP imagefrompng(), because this nasty crap not works with a lot of my images,
even with all suggested fixes like:
$background = imagecolorallocate($png, 255, 255, 255);
// removing the black from the placeholder
imagecolortransparent($png, $background);
// turning off alpha blending (to ensure alpha channel information is preserved, rather than removed (blending with the rest of the image in the form of black))
imagealphablending($png, true);
// turning on alpha channel information saving (to ensure the full range of transparency is preserved)
imagesavealpha($png, true);
and so on. It works with some images, but not with others.
All I need is a PNG library (maybe not in PHP), that can give me red, green, blue and alpha component of a pixel at coordinates x, y, and then set this pixel after my calculations, eg:
$rgba = getrgba($image, $x, $y);
$rgba = my_function($rgba);
setrgba($image, $x, $y, $rgba);
Maybe you can suggest libraries in other languages, not only PHP?
If you don't mind using Python check out Pillow, specifically its PixelAccess class. These threads (1, 2) should be helpful and have some code examples.
Method 1
If you just want to get at the raw pixel values of R,G,B and Alpha without worrying about compression and encoding, use ImageMagick to convert your image to plain, uncompressed, unencoded binary and read it and process it to your heart's content.
So, if we make a 1x1 pixel PNG file with RGBA(0,64,255,0.5) to test with:
convert -size 1x1 xc:"rgba(0,64,255,0.5)" a.png
Now we can get ImageMagick to make a raw, RGBA file that you can read and process as you wish with whatever language you wish at whatever level of complexity that you wish:
convert a.png rgba:data.bin
and now we can look in that file:
xxd data.bin
Result
0000000: 0040 ff80 .#..
There you can see and read all the RGBA pixels. When you are finished, just do the opposite to get back a PNG - note that you must tell ImageMagick the size first since it cannot know this:
convert -size 1x1 rgba:data.bin new.png
Note that ImageMagick is quite a large package to install, and you can achieve much the same as the above with the much lighter-weight vips package:
vips VipsForeignSaveRaw a.png data.rgb
Method 2
Alternatively, if you want your data as uncompressed, human-readable ASCII, use the venerable NetPBM formats of PPM (Portable Pixmap) and PGM (Portable Greymap) - see NetPBM on Wikipedia.
Make a 4x1 image and write as PPM:
convert -size 4x1 xc:"rgba(0,64,255,0.1)" -compress none ppm:-
P3
4 1
65535
0 16448 65535 0 16448 65535 0 16448 65535 0 16448 65535
You can see the 4 repeated RGB values there hopefully. If you want it as a file, just change the ppm:- at the end with someFile.ppm.
Make same image again and extract Alpha channel to separate file:
convert -size 4x1 xc:"rgba(0,64,255,0.1)" -alpha extract -compress none pgm:-
P2
4 1
65535
6554 6554 6554 6554
Hopefully you can see that 6554 is 0.1 on a scale of 0-65535.
If you just want 8-bit data on any of the above, add in -depth 8.
Method 3
As Glenn suggests in the comments, another option is to omit the -compress none on Option 2 which will give you a very similar file format except the pixel data will be in binary, after the header which remains in ASCII. This is generally faster and smaller.

Cropping an image using Jcrop and Imagemagick

I'm confused on how the -crop function works in Imagemagick.
I have the following values from Jcrop.
(x1,y1), (x2,y2), width and height.
And following command:
exec("convert $target_path -crop ".$w."x".$h."+$x+$y +repage $target_path");
Original image:
Result after crop:
My question is, How do I used the coordinates and dimensions from Jcrop, and use them with Imagemagick?
I have no idea what values you are passing into convert, but your command needs to look something like this to extract the light region -if that is your aim:
convert x.png -crop 240x240+120+100 out.png
The first 240 is the width of the cropped area, and the second 240 is its height. The 120 is the x-offset across from the top-left corner and the +100 is the y-offset down from the top.
Or, in general terms, you specify the crop like this
convert input.png -crop ${x}x${y}+${a}+${b} output.png
I feel like an idiot.
I had style='max-width:500px;' on my image during the crop. Removed the style and now it's working.

ImageMagick incorrect dimensions

I've been on this problem for several hours now. I can't crop/resize a certain image correctly.
The source image has a dimension of 900x398 px
The target dimension is 650x178 px
but the returned dimension is 647x178 px. I dont't get it. This is the command I use:
/usr/bin/convert jpg:"/location/20-prefab_woningen.jpg" -auto-orient -shave 0x78 -resize 650x174 -colorspace RGB "location/new.jpg" &&exit
Is this a common bug? I can't find anything on the web about it. ImageMagick version doesn't seem to matter, tried both local and on the server but I get the same results.
resize tries to fit the image into the specified dimensions. It doesn't force it to exactly that size. See the manual.
Use the !flag to tell IM to ignore the aspect ratio.
/usr/bin/convert jpg:"/location/20-prefab_woningen.jpg"
-auto-orient -shave 0x78
-resize 650x174\!
-colorspace RGB "location/new.jpg" &&exit

72DPI PNG to a 300DPI PDF + Cutting Cross

I have a flash which outputs a PNG file in 72DPI, I need to execute the following steps (not necessarily in that order) in order to make it ready for print:
Convert to 300DPI
Resize to 9x5 cm
Put cross (for cutting later) on it
Save as PDF - 300DPI
With my little of tutorial reading + knowledge in IM, I got this far:
1. convert -units PixelsPerInch IMAGE.PNG -resample 300 IMAGE_300DPI.png
2. convert IMAGE_300DPI.png -resize 1111x639 IMAGE_300DPI_correct_size.png
3. composite -gravity center IMAGE_300DPI_correct_size.png cross.png card_new_with_cross.png
4. convert card_new_with_cross.png card_new.pdf
When I execute stage #4 everything changes and gets enlarged as far as I can tell, any Ideas?
by the way - 2 files (sideA.png & cross.png) can be found at:
http://www.bikur.co.il/sideA.png <-- the image
http://www.bikur.co.il/cross.png <-- the `cross-
It would be great if someone can help me with it
DPI is a conversion factor, not a measurement. It's used to convert an image's intrinsic pixels into some display medium's pixel.
e.g. a 300 dpi printer has "pixels" that are 1/300 inches in size, while a 72dpi monitor has 1/72 inch sized pixels. A 100x100#72dpi image on a monitor would have to be printed out at about 417x417 printer pixels to have the same apparent size (300/72 = 4.16666)
So, whatever size your image is initially, to get a 9x5cm image # 300dpi, it'd have to be converted as follows:
9 x 5cm = 3.543 x 1.968 inches # 300dpi = 1063 x 591

Categories