Does Gmagick have a method like Imagick::thresholdImage? - php

I'm trying to create a scripts with PHP's pecl module Gmagick to remove a somewhat white background from an image. On the command line I use the following two commands for imagemagick:
convert source.jpg \( +clone -fx 'p{0,0}' \) \
-compose Difference -composite \
-modulate 100,0 -alpha off -threshold 10% source_mask.png
convert source.jpg source_mask.png \
-alpha Off -compose CopyOpacity -composite \
source_transparent.png
I already have been able to take the first few steps:
$source_gm = new Gmagick();
$source_gm->readImage($source_path);
$white_gm = new Gmagick();
$white_gm->newImage($source_gm->getImageWidth(), $source_gm->getImageHeight(), 'white', 'png');
$mask_image = $source_gm->compositeImage($white_gm, Gmagick::COMPOSITE_DIFFERENCE, 0, 0);
$mask_image->modulateImage(100, 0, 0);
The Gmagick module has some kind of constant which should be used for the threshold Gmagick::COMPOSITE_THRESHOLD. However, there is no hint on how to use it. Can someone help me with the threshold?
Thanks!

I found out that the thresholdImage function is not available in gmagick yet. The feature has been implemented in SVN, but didn't make it to a release yet.

Related

ImageMagick dashed rectangle incorrectly rendered

When trying to draw a dashed rectangle with ImageMagick using the following command:
convert -size 300x300 xc:skyblue -fill white -stroke black \
-draw "stroke-width 3 stroke-dasharray 10 10 rectangle 50,50 250,250" draw_rect.gif
I get the following image, clearly wrong (note the "z" shapes):
No matter what I try (it happens also with paths, with different line caps and joins, stroke widths, dash arrays, colors, transparent fill,...) I get these strange artifacts.
Version is ImageMagick 6.9.10-68 Q16 aarch64 2021-02-02 (ARM), but I tried also with an x86 server ImageMagick 6.9.10-68 Q16 x86_64 2021-02-03 and got the same result.
Is this an ImageMagick limitation? a bug? If so, I can't believe a library so mature could behave so weird.
Using IM 6.9.12.73, I get the following result with your following command.
convert -size 300x300 xc:skyblue -fill white -stroke black -draw "stroke-width 3 stroke-dasharray 10 10 rectangle 50,50 250,250" draw_rect.gif
Likely, your old version of Imagemagick had a bug. You should upgrade if you can.

How to stylize text with PHP using GD/Imagick?

I use imagettftext() function to add a caption to the image:
example
Background and captions are separate.
How could I apply the style similar to this one, is it possible with Imagick?
I need to create the 3D effect for the letters.
required style
I was trying to use and combine letters' images, but I think it's not a good solution.
Thanks!
If you are willing to use PHP exec(), you can call my Unix Bash Imagemagick script, texteffect2 at my web site http://www.fmwconcepts.com/imagemagick/index.html. It will do bevel and other effects. Here is the script command for doing a bevel:
texteffect2 -t "bevel" -e bevel -s plain -f Ubuntu-Bold -p 200 -c red -bg none result.png
-t is the text you want to use
-e is the effect you want
-s is whether to make it plain or add an outline
-f is the font name or font file
-p is the point size for the font
-c is the text color
-bg is the background color (none means transparent)
Here is the basic Imagemagick code to do the bevel effect:
convert -background none -font Ubuntu-Bold \
-pointsize 200 -fill "red" -gravity west label:"BEVEL" \
\( +clone -alpha Extract -write mpr:alpha -blur 0x8 -shade 135x30 \
-auto-level -function polynomial 3.5,-5.05,2.05,0.25 \
mpr:alpha -compose copy_opacity -composite \) \
-compose Hardlight -composite result.png
I do not know Imagick that well. So you might look here http://us3.php.net/manual/en/book.imagick.php for the Imagick equivalents or perhaps someone else who uses Imagick can convert it for you.
the method is called Imagick::embossImage, where the text should be a separate layer, before merging the layers for output. just try to manually produce the desired effect with GIMP2, then you know the steps required to get there. the gimp-imagemagick plugin also appears useful for testing.

ImageMagick single convert command performance

I have a few thousand images to be processed so each millisecond counts. Each image is ~2-3Mb in size.
Source file fed to the converter:
image.jpg
Files to be generated out of the source:
orig_image.jpg // original image
1024x768_image.jpg // large image
250x250_image.jpg // thumbnail 1
174x174_image.jpg // thumbnail 2
While browsing different topics on imagemagick convert performance I got a feeling that a single command should be way faster than individual converts for each image size. Also a memory utilization was mentioned as a performance boost. (ImageMagick batch resizing performance)
Multiple command conversion (each command run via php's exec() in a loop):
convert "image.jpg" \
-coalesce -resize "1024x768>" +repage "1024x768_image.jpg"
convert "1024x768_image.jpg" \
-coalesce \
-resize "250x250>" \
+repage \
-gravity center \
-extent "250x250" "250x250_image.jpg"
convert "1024x768_image.jpg" \
-coalesce \
-resize "174x174>" \
+repage \
-gravity center \
-extent "174x174" "174x174_image.jpg"
mv image.jpg orig_image.jpg
Single command conversion incorporating ImageMagicks mpr:
convert "image.jpg" -quality 85 -colorspace rgb -coalesce \
-resize "1024x768>" \'
-write "1024x768_image.jpg" \
-write mpr:myoriginal +delete \
mpr:myoriginal -coalesce \
-resize "250x250>" \
-gravity center \
-extent "250x250" \
-write "250x250_image.jpg" +delete \
mpr:myoriginal -coalesce \'
-resize "174x174>" \
-gravity center \
-extent "174x174" \
-write "174x174_image.jpg"
After performance testing the results are somewhat unexpected. Single command convert in a loop finishes in 62 seconds while multiple command conversion executes in just 16 seconds?
# convert -version
Version: ImageMagick 7.0.2-1 Q8 i686 2017-02-03 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2016 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC HDRI OpenMP
Delegates (built-in): bzlib freetype jng jpeg lzma png tiff wmf xml zlib
Also installed libjpeg-turbo jpg processing library but I cannot tell (don't know how to check) if ImageMagic is using it or the old libjpeg.
Any ideas how to speed up image converting process?
Edit:
Don't know how to format it properly here on stackoverflow, but I just noticed that single line command had an argument "-colorspace rgb" and multiple line commands did not which actually results in such strange results where multiple commands are processed faster.
Removed the "-colorspace rgb" argument after which the MPR convert version works the best and gave additional boost in performance.
To sum it all up I ended up using this command:
// MPR
convert "orig_image.jpg" -quality 80 -coalesce \
-resize "1024x768>" \
-write 1024x768_image.jpg \
-write mpr:myoriginal +delete \
mpr:myoriginal -resize "250x250>" \
+repage -gravity center -extent "250x250" \
-write "250x250_image.jpg" \
-write mpr:myoriginal +delete \
mpr:myoriginal -coalesce -resize "174x174>" \
+repage -gravity center -extent "174x174" \
-write "174x174_image.jpg"
You're not using jpeg shrink-on-load, that'll give an easy speedup.
The jpeg library has a neat feature where it'll let you decompress at full resolution, at 1/2, 1/4 or 1/8th. 1/8th resolution is especially quick because of the way jpg works internally.
To exploit this in convert you need to hint to the jpeg loader that you need an image of a particular size. To avoid aliasing you should ask for an image at least 200% larger than your target size.
On this machine, I see:
$ vipsheader image.jpg
image.jpg: 5112x3470 uchar, 3 bands, srgb, jpegload
$ time convert image.jpg -resize 1024x768 1024x768_image.jpg
real 0m0.405s
user 0m1.896s
sys 0m0.068s
If I set the shrink-on-load hint, it's about 2x faster:
$ time convert -define jpeg:size=2048x1536 image.jpg -resize 1024x768 1024x768_image.jpg
real 0m0.195s
user 0m0.604s
sys 0m0.016s
You'll see a dramatic speedup for very large jpg files.
You could also consider another thumbnailer. vipsthumbnail, for example, is quite a bit faster again:
$ time vipsthumbnail image.jpg -s 1024x768 -o 1024x768_image.jpg
real 0m0.111s
user 0m0.132s
sys 0m0.024s
Although real time is down by only a factor of 2, user time is down by a factor of 5 or so. This makes it useful to run with gnu parallel. For example:
parallel vipsthumbnail image.jpg -s {} -o {}_image.jpg ::: \
1024x768 250x250 174x174
Eric's and John's suggestions share much wisdom, and can be mixed in with my suggestion - which is to use GNU Parallel. It will REALLY count when you have thousands of images.
I created 100 images (actually using GNU Parallel, but that's not the point) called image-0.jpg through image-99.jpg. I then did a simple resize operation just to show how to do it without getting too hung up on the ImageMagick aspect. First I did it sequentially and it took 48 seconds to resize 100 images, then I did the exact same thing with GNU Parallel and came in under 10 seconds - so there are massive time savings to be made.
#!/bin/bash
# Create a function used by both sequential and parallel versions - it's only fair
doit(){
echo Converting $1 to $2
convert -define jpeg:size=2048x1536 "$1" -resize 1024x768 "$2"
}
export -f doit
# First do them all sequentially - 48 seconds on iMac
time for img in image*.jpg; do
doit $img "seq-$img"
done
# Now do them in parallel - 10 seconds on iMac
time parallel doit {} "par-{}" ::: image*.jpg
Just for kicks - watch the CPU meter (at top right corner of the movie) and the rate the files pop out of GNU Parallel in the last 1/6th of the movie.
It is funny as I did some conversions a while ago and found mpr was slower as well.
Anyway try this:
$cmd = " convert "image.jpg" -colorspace rgb -coalesce \( -clone 0 -resize 1024x768> -write 1024x768_image.jpg +delete \)".
" \( -clone 0 -resize 250x250> -gravity center -extent 250x250 -write 250_wide.jpg +delete \) ".
" -resize 174x174> -gravity center -extent 174x174 null: ";
exec("convert $cmd 174x174_image.jpg ");
I notice you do not have a background colour for you extent.
You can also add a -define to your loop method check it out in this list: https://www.imagemagick.org/script/command-line-options.php#define
jpeg:size=geometry only reads the amount of data you need to create the image without reading the whole image. You could probably also add it into your first line. -quality is for the output and will have no effect where you put it.
$cmd = " convert "image.jpg" jpeg:size=1024x768 -colorspace rgb -coalesce \( -clone 0 -resize 1024x768> -write 1024x768_image.jpg +delete \)"..
I can never remember if it comes before or after the file name though
Try Magick Persistent Cache image file format (.mpc) over Magick Persistent Registry (.mpr).
convert "image.jpg" -quality 85 -colorspace rgb myoriginal.mpc
convert myoriginal.mpc \
-resize "1024x768>" \
-write "1024x768_image.jpg" \
-resize "250x250>" \
-gravity center \
-extent "250x250" \
-write "250x250_image.jpg" \
-resize "174x174>" \
-gravity center \
-extent "174x174" \
"174x174_image.jpg"
Which results in the following times when tested with 1.8mb jpeg.
real 0m0.051s
user 0m0.133s
sys 0m0.013s
It's true that this will take two commands (although could be simplified to one with -write ... +delete), but very little I/O cost after .mpc is loaded back into the image stack.
Or
You can probably skip .mpc all together with ...
convert "image.jpg" -quality 85 -colorspace rgb \
-resize "1024x768>" \
-write "1024x768_image.jpg" \
-resize "250x250>" \
-gravity center \
-extent "250x250" \
-write "250x250_image.jpg" \
-resize "174x174>" \
-gravity center \
-extent "174x174" \
"174x174_image.jpg"
With results...
real 0m0.061s
user 0m0.163s
sys 0m0.012s
ImageMagick has a special resize operator variation named -thumbnail <geometry> for converting very large images to small thumbnails. Internally it uses
-sample to shrink the image down to 5 times the final height which is much faster than -resize if the thumbnail is much smaller than the original image. Because this operator uses a reduced filter set, the -filter operator is ignored!
-strip to remove all profiles from the image which are usually not required for thumbnails. This also further reduces the size of the resulting image file.
-resize to finally create the requested size and ratio
When it comes to creating thumbnails from JPEG images, then the special JPEG shrink-on-load option -define jpeg:size=<size> can be used instead, as stated out by user894763. Be aware that this option has to be specified immediately after convert, e.g.:
convert -define jpeg:size=<size> input-image.jpg ...
Anyway the -thumbnail operator can be specified additionaly then because it removes all profiles from the thumbnail image and thus reduces the file size.
Detailed information can be found in the ImageMagick usage documentation.
I get about half the time using one command line in ImageMagick 6.9.10.0 Q16 Mac OSX starting with a 3 MB input JPG image.
list="image.jpg"
time for img in $list; do
convert "image.jpg" \
-coalesce -resize "1024x768>" +repage "1024x768_image.jpg"
convert "1024x768_image.jpg" \
-coalesce \
-resize "250x250>" \
+repage \
-gravity center \
-extent "250x250" "250x250_image.jpg"
convert "1024x768_image.jpg" \
-coalesce \
-resize "174x174>" \
+repage \
-gravity center \
-extent "174x174" "174x174_image.jpg"
done
Time: 0m0.952s
time convert "image.jpg" \
-resize "1024x768>" \
+write "1024x768_image.jpg" \
-resize "250x250>" \
-gravity center \
-extent "250x250" \
+write "250x250_image.jpg" \
-resize "174x174>" \
-gravity center \
-extent "174x174" \
"174x174_image.jpg"
Time: 0m0.478s
The coalesce in your multiple commands is not needed, since JPG does not support a virtual canvas. So removing that reduces the multiply command line time to 0m0.738s
Multiple commands should be longer since you have to write and read intermediate images. Since your intermediate images are JPG, you will lose more visual quality each time you write and read the intermediate images. So the quality of one long command line should be better, also.

Conversion PDF to PNG or JPEG is very very slow using ImageMagick

I have a working PDF to PNG conversion script using PHP and ImageMagick but I am having a problem with the speed of the conversion.
I know it works because with a very small PDF the time taken to convert is not that great, but with a 250kb file (still not that large really) it takes in excess of 20 minutes to convert.
Here's the PHP:
//***** GET PATH TO IMAGEMAGICK *****
$path_to_imagemagick = trim(`which convert`);
//***** PATH TO PDF TO CONVERT *****
$path_to_pdf = getcwd() . "/pdf/myfile.pdf[0]";
//***** PATH TO OUTPUT TO *****
$output_path = getcwd() . "/pdfimage/test_converted.png";
#exec($path_to_imagemagick . " -density 72 -quality 60 -resize 150x " . $path_to_pdf . " " . $output_path);
Are there any settings I can change to make this quicker?
If it helps, the image does not need to be a PNG. If JPEG is going to be quicker I'm happy to go with that.
ImageMagick cannot convert PDF to raster images by itself at all.
ImageMagick uses a delegate for this job: that delegate is Ghostscript. If you hadn't installed Ghostscript on the same system as ImageMagick, the PDF conversion by convert wouldn't work.
To gain speed, don't use ImageMagick for PDF -> raster image conversion. Instead, rather use Ghostscript directly (also possible via PHP).
Command line for JPEG output:
gs \
-o ./pdfimage/test_converted.jpg \
-sDEVICE=jpeg \
-dJPEGQ=60 \
-r72 \
-dLastPage=1 \
pdf/myfile.pdf
Command line for PNG output:
gs \
-o ./pdfimage/test_converted.png \
-sDEVICE=pngalpha \
-dLastPage=1 \
-r72 \
pdf/myfile.pdf
Both of these commands will give you unscaled output.
To scale the output down, you may use something like
gs \
-o ./pdfimage/test_converted.png \
-sDEVICE=pngalpha \
-dLastPage=1 \
-r72 \
-dDEVICEWIDTHPOINTS=150 \
-dDEVICEHEIGHTPOINTS=150 \
-dPDFFitPage \
pdf/myfile.pdf
Also please note: You used a -quality 60 setting for your PNG outputting command. But -quality for JPEG and -quality for PNG output do have a completely different meaning with ImageMagick (and you may not be aware of it). See also this answer for some details about this.

Imagemagick - Same command gives different output in PHP or console

I'm trying to use ImageMagick on an Ubuntu 12.04 server to create simple business cards dynamically. This is done via a php page. I tried to install MagickWand, but it didn't really work so I'm now using ImageMagick syntax and executing it via PHP function exec().
I'm making good progress, and had the basics more or less done, the output image looked okay and am now finetuning, setting the positions right, changing fonts and sizes, etc.
Our graphic person wants the text to be in Arial with bold titles, so I installed msttcorefonts on the server. Since then, the text in the output image is italic, and it ignores whatever font I use.
The curious thing is: if I echo the command to the page, copy and paste it into the ubuntu console, the image that's created there uses the right fonts and is exactly what I want.
So, it seems that when I execute the command via console, everything is fine, but when I execute it in PHP via exec(), ImageMagick doesn't seem to recognize the fonts. Does anyone know why? Also, if it doesn't recognize the font, why does it default to italic, or, for that matter, why did the default change at all after installing the fonts?
This is the command I'm currently testing (with changed names and contact info):
convert \
-size 1051x697 \
xc:none \
-density 300 \
-fill white \
draw "rectangle 0,0 1051,697" \
-fill black \
-font Arial-Negreta \
-pointsize 9 \
-draw "text 140,175 'Hotel Example'" \
-font Arial-Normal \
-pointsize 6 \
-draw "text 140,220 'Example Street 8'" \
-draw "text 140,240 '12345 Exampletown'" \
-draw "text 140,280 'Telefon: 123 45 67 89 0'" \
-draw "text 140,300 'Fax: 234 56 78 90'" \
-draw "text 140,340 'http://www.example.de'" \
-draw "text 140,360 'hotel-example#example.de'" \
-stroke none -fill orange -draw "rectangle 1,32 1050,75" \
-fill grey \
-draw "rectangle 1,75 1050,100" \
-fill orange \
-draw "rectangle 1,626 1050,665" \
test_front.png
Edit:
I just noticed that running the command from the Ubunut console also only works in my home directory, and not in my /var/www directory. As APiK pointed out, it's probably a user thing.
It looks like you installed the fonts only for a specific user.
Try to run this command in console and PHP script:
# This will show you all the available fonts for ImageMagick
$ convert -list type
Or you can also specify TTF fonts directly:
$ convert -font /path/to/your/fonts.ttf
I doubt your font names Arial-Fett and Arial-Standard are recognized by ImageMagick.
To see which names for Arial font faces are known to convert, run this command first:
convert -list font | grep -i arial
On my system (a Mac OS Lion), I get this result:
[....]
Font: Arial-Narrow-Negreta-cursiva
family: Arial Narrow
glyphs: /Library/Fonts/Arial Narrow Bold Italic.ttf
Font: Arial-Narrow-Normal
family: Arial Narrow
glyphs: /Library/Fonts/Arial Narrow.ttf
Font: Arial-Negreta
family: Arial
glyphs: /Library/Fonts/Arial Bold.ttf
Font: Arial-Negreta-cursiva
family: Arial
glyphs: /Library/Fonts/Arial Bold Italic.ttf
Font: Arial-Normal
family: Arial
glyphs: /Library/Fonts/Arial.ttf
[....]
With ImageMagick, you can only apply these two methods to specify the font to use:
...either use exactly the names that appear after the Font: tag,
...or use exactly the path+name to the specific font file that appears after the glyphs: tag (if filename or path use spaces, enclose it in quotes!).
So on my system, for your -font Arial-Standard I'd have to use either of
-font Arial-Normal
-font /Library/Fonts/Arial.ttf
Instead of your -font Arial-Fett I'd have to use either of
-font Arial-Negreta
-font "/Library/Fonts/Arial Bold.ttf"
On your system this may be different of course (esp. if you're on Windows or Linux). That's why you have to verify using convert -list font...

Categories