Combining 2 GraphicsMagick commands into 1 command, like in ImageMagick - php

I was using ImageMagick to create a new resized image with watermark, with this single command (in PHP):
exec("convert -filter Lanczos {$original_image} -thumbnail {$max_width}x{$max_height} -quality 90 {$watermark} -gravity center -unsharp 2x0.5+0.7+0 -composite {$cached}");
Now I switched to GM and am looking for a way to run 1 command to do the same task. The only way I found was to split it to 2 separate commands:
//create the resized image
exec("gm convert -filter Lanczos {$original_image} -thumbnail {$max_width}x{$max_height} -quality 90 -unsharp 2x0.5+0.7+0 {$cached}");
//apply the watermark and recreate the watermarked image, overwriting the previously resized image
exec("gm composite -quality 90 -dissolve 100 -gravity center {$watermark} {$cached} {$cached}");
Is there a way to combine them into 1 single command and by that maybe also reduce resources & drive usage?

I have received the following reply on this from Bob Friesenhahn, GraphicsMagick Maintainer:
You did not say what version of GraphicsMagick you are using. Modern
versions support a '-compose' option which may be put on the command
line after the input file name to remember the composition algorithm
to use. This composition algorithm is then used if the -mosaic or
-extent operators are used to do a composition. You can also use a
-page option after the input file name to locate the image when it
is composited with prior images in the list. Due to a weakness in
GM's convert command processing, the -mosaic or -extent operators must
be the last command prior to saving the output file. I believe that
ImageMagick's -composite must be a version of -mosaic which adds more
features (e.g. -mosaic might not support gravity but -composite does).
It seems like GraphicsMagick should implement something completely
compatible with ImageMagick's -composite.
Regardless, there is an effective workaround available if you need to
use your existing GM commands.
If you have a modern GraphicsMagick which supports 'gm batch', then
you can use the 'mpr' coder ("Magick Persistent Registry") to remember
intermediate images between commands and you can easily adapt your two
commands to execute with full efficiency using the existing command
lines. This Unix shell example should give you some ideas:
{
echo convert seaworld.jpg mpr:temporary
echo convert mpr:temporary crap.jpg
} | gm batch -prompt off -echo on
convert seaworld.jpg mpr:temporary
convert mpr:temporary crap.jpg
Notice that the output of the first command was saved (as an image
handle as natively used within GraphicsMagick) into 'mpr:temporary'
and then the second command took input from 'mpr:temporary' and wrote
the final output file. You can use arbitrary string arguments to
'mpr:' so you can have several images "in flight".
With this approach you can use 'gm convert' and 'gm composite' in the
same batch command.
I am not sure how one would best access this batch facility from PHP
but if PHP can stream commands to it from a pipe, then it can run for
quite a long time as a co-process to PHP and save considerable compute
time and overhead.

Related

Error Level Analysis with Imagick PHP - result without color

yesterday I posted about a problem with recreating an Error Level Analysis in PHP with Imagmagick. In this question I found a solution with the command-line interaction and tried to translate it into Imagick and PHP.
The following code was proposed:
convert barn.jpg \( +clone -quality 95 \) -compose difference -composite -auto-level -gamma 1.5 barn_ela.png
In this example, the result should highlight the manipulated parts of the image. So I implemented the following code:
$ELAImageMagick = new Imagick($targetDir . $OriginalImage);
$OriginalImageMagick = new Imagick($targetDir . $OriginalImage);
$ELAImageMagick->setImageCompression(Imagick::COMPRESSION_JPEG);
$ELAImageMagick->setImageCompressionQuality($this->getRequest()->postVar('elaQuality'));
$ELAImageMagick->compositeImage($OriginalImageMagick, Imagick::COMPOSITE_DIFFERENCE, 1,1);
$ELAImageMagick->autoLevelImage();
//Set gamma with a slider in the frontend
$ELAImageMagick->gammaImage($this->getRequest()->postVar('elaSize'));
//save ELA-image into Folder
$ELAImageMagick->writeImage($targetDir . $ELAImage);
Unfortunatly the result does not come close to the desired optic of the result:
The original image (yellow bird has been added in photoshop)
The ELA-Result
Does anyone have an idea, what step I didn't catch quite right and how to solve it? I looked into the documentation and didn't really find any alternatives to this.
Thanks in advance!
You need to first prove that your code works in Imagemagick. But -quality only works for writing a JPG output. So you need to actually save the result of the -quality operation as a JPG and then use it in a second command. Here I just pipe from one convert to another. The first convert actually creates the compressed JPG but just passes it to the second command without writing to disk.
Input:
convert birds.jpg -quality 95 JPG:- | convert birds.jpg - -compose difference -composite -auto-level -gamma 1.5 birds_ela.png
The result I get is:
This is a JPG version of the PNG output since the PNG was too large to post.
However the results from the command line do not match the resulting image you show. So the command is not going to work in Imagick either.
ADDITION:
From what I can see there is no tampering other than possibly the orange bird in the middle. Most of the image is flat or has random noise. The small bird in the middle has a bit brighter texture and so may be an insert.
ADDITION 2
For enhancing edge artifacts, add -geometry +1+1 to my command above just before -compose difference.
convert birds.jpg -quality 95 JPG:- | convert birds.jpg - -geometry +1+1 -compose difference -composite -auto-level -gamma 2 -define jpeg:extent=2000kb birds_ela2.png
Again posting a JPG version for file size issues.
This looks similar to your posted result.

How to apply special filters to image using PHP?

I was working on image filters using PHP, but I am unable to find some filters like those at https://pinetools.com/. In particular, the ones listed below:
Clip Image
Adjust channels
Change Image exposure
Vibrance
I couldn't find these filters' solution in PHP GD filters or in PHP Imagick, based upon ImageMagick.
Is there any solution for this. Are there any of these filters there that I could not find?
How do I apply these filters to an image in PHP Imagick?
I know the question is broad please don't devote it, I thought it strange to post a separate question for each filter?
I have worked out the equivalent of Pinetools clip image in ImageMagick commands for values between 0 and 50.
Input:
For example at 50, clip image produces the following:
The following ImageMagick command reproduces that:
convert lena.jpg -black-threshold 50% -white-threshold 50% clip_image_imagemagick.png
The functions to use in Imagick are:
http://us3.php.net/manual/en/imagick.blackthresholdimage.php
http://us3.php.net/manual/en/imagick.whitethresholdimage.php
I do not know Imagick, but looking at the documentation, it appears that it wants a threshold value as a color, so try "gray(50%)" when the clip image value is 50.
Similarly, I have worked out the equivalent of Pinetools Adjust colors.
Here is the result for Pinetools red adjust 50.
In ImageMagick, that would be:
convert lena.jpg -channel r -level 0x50% +channel adjust_red_50.png
And the Imagick command is:
http://us3.php.net/manual/en/imagick.levelimage.php
But I am not sure what the values are. I believe they may be number in the range of 0 to quantum range. So if your IM version is Q16, then 0 to 65535 and if Q8, then 0 to 255. So 50% in Q16 would be 65535/2=32767.5. So
levelImage (0, 1.0, 32767.5, $channel = Imagick::CHANNEL_RED );
For Pinetools exposure 50, I can come close using the ImageMagick command -evaluate add.
Pinetools Exposure 50:
The ImageMagick command would be:
convert lena.jpg -evaluate add 40% lena_add_40%.png
And for Pinetools Exposure 100:
And the ImageMagick command would be twice that:
convert lena.jpg -evaluate add 80% lena_add_80%.png
The Imagick command for 50 would likely be:
http://us3.php.net/manual/en/imagick.evaluateimage.php
evaluateImage(Imagick::EVALUATE_ADD, 26214);
where 65535*40/100=26214
For Pinetools Vibrance 50:
You can do that in ImageMagick by changing colorspace to HSL (or HCL or similar), then applying sigmoidal-contrast to the Saturation/Chroma channel.
A close equivalent would be:
convert lena.jpg -colorspace HSL -channel g -sigmoidal-contrast 3,0% +channel -colorspace sRGB tmp.jpg
In Imagick, you would change colorspace using:
http://us3.php.net/manual/en/imagick.transformimagecolorspace.php
Then apply sigmoidalcontrastImage to the Saturation channel which in HSL would be the green channel:
http://us3.php.net/manual/en/imagick.sigmoidalcontrastimage.php
Then convert the colorspace back to (s)RGB.
Note that sigmoidal contrast is non-linear. You want to set the mid-point to 0% so that the straight part of the curve is at 0 and the curved part that curves over to near flat is at the top right. So it is like a non-linear brightness control on the Saturation.
You won't find one-to-one matching of those filters. But you can get similar effects in Imagick (or ImageMagick directly) with the following, though argument control is different.
clip image is http://us3.php.net/manual/en/imagick.contraststretchimage.php
adjust channels is
http://us3.php.net/manual/en/imagick.levelimage.php
change exposure is also
http://us3.php.net/manual/en/imagick.levelimage.php
There is no vibrance exact equivalence, but you can change saturation using:
http://us3.php.net/manual/en/imagick.modulateimage.php
If you are on Unix-like systems, you can use PHP exec() and run some of my bash ImageMagick shell scripts. I have several for vibrance and exposure (called xposure) and one for brightness-contrast adjustment. See http://www.fmwconcepts.com/imagemagick/index.php

ImageMagick crashing for JPEG with incorrect density value

I am trying to convert an image with ImageMagick. I am cropping and resampling to 112 DPI:
convert myimg.jpg -crop 1024x683+0+0 -resize 100% -resample 112 downsample.jpg
A script runs through many images of varying DPI and downsamples them.
However, a particular file has gummed up the script. Somehow, the file has a DPI of 1 (?!?) So it ends up trying to sample it up to 112 from 1, and the attempt eats up all my RAM and hangs the script.
identify -verbose myimage.jpg
Image: myimage.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Class: DirectClass
Geometry: 1024x683+0+0
Resolution: 1x1
Print size: 1024x683
Is there an argument/flag I can use with ImageMagick to prevent this from happening, maybe something that tells it to only downsample?
Could your error be related to...
For formats which do not support an image resolution, the original resolution of the image must be specified via -density on the command line prior to specifying the resample resolution.
JPEG I know supports resolution but maybe its wrong in the EXIF header or somehow ambiguous / confused with embedded thumbnail (again, maybe the unit is assumed). I'd look more closely at the [-density] argument (http://www.imagemagick.org/script/command-line-options.php#density) and how it relates to resolution and density on certain formats.
As for getting your script working. Seems you might want to break the operations out into more individual actions? If you can't satisfy the convert with using -density I would look at testing for the case you know fails and just skipping. Could parse the results of identify or just the failure of the convert. You are executing these in shell calls from PHP yes?

Generate a image thumbnail without stretching it with ImageMagick 6.2.8

Fill Area Flag ('^' flag) is support IM v6.3.8-3But my client's production server has version ImageMagick 6.2.8
Right now in my local server i use this command to generate thumbnail and it works fine:
convert image.jpg -resize "280x210^" -gravity Center -crop "280x210+0+0" thumbnail.jpg
Since my client's production server doesn't support '^' flag how can i generate a thumbnail without using it? (or maybe calculating it manually in PHP or BASH)
Should i use -extent, does it stretch the image?
I also read this and im not sure if ^ flag is for not letting the image stretch because thats what i want, generate a thumbnail without stretching it.
Note: i dont have root access on the server. Im using PHP and BASH to run the commands.
EDIT:
I also don't want any other background colors while resizing and croping.
try
convert image.jpg -background black -resize 280
-gravity center -crop 280x210+0+0 -extent 280x210 image.c.jpg
I found a solution
This is the PHP function i used:
function imgconvert($in,$out,$size){
$size_arr=explode('x',$size);
$resize=( ($size_arr[0]/$size_arr[1]) > 1.775 ? $size_arr[0].'x':'x'.$size_arr[1]);
system("convert \"$in\" -resize $resize -gravity Center -crop \"$size+0+0\" \"$out\"");
}
It seems that if width/height is larger than 1.775 i should use widthX as resize value and if else than i should use Xheight .

ImageMagick: What is this convert-command doing?

I'm trying to port a PHP script to Ruby and until now I only used ImageMagick to convert from one file-format to another. Meaning: Yes, I'm an ImageMagick newbie. ;-)
Somewhere inside the PHP script the following code is executed:
$output = array();
$returnValue = 0;
$cmd = 'convert '.$pngFile->path.' -resize 1x1 -alpha on -channel o -format "%[fx:u.a]" info:'
exec($cmd, $output, $returnValue);
Using the ImageMagick documentation for convert I identified the following options:
-resize 1x1 Resize to 1x1 pixels (right?)
-alpha on Activate alpha-channel
-channel o Apply options to the opacity image-channel
My questions:
What does -format "%[fx:u.a]" exactly do? I know that u is a symbol for first image in sequence and a one for alpha. But I don't get what the whole expression really does.
What does info: stand for?
What does this convert-command exactly do?
Thank you very much for your kind help.
Please note: The accepted answer on the following question has a very good answer to this question:
Understanding ImageMagick's convert and translating to Ruby RMagick
Seems like it is computing the average opacity. The info format is a dummy image format that will instruct convert to output image information to stdout (: means stdout) in the format %[fx:u.a]. Resizing to 1x1 is probably a way of averaging.

Categories