Image sequence breaks in gif animation - php

I am trying to animate all images in a directory with imagemagick's morph operator. I am calling the command-line arguments with PHP's exec command. The images hold a specific file name such as 000000.jpg, 000001.jpg, 000002.jpg, 000003.jpg, and so on.
the following code works fine from image sequence 000000.jpg to 000009.jpg, but when I have images such as 0000010.jpg, the 0000010.jpg comes after 000001.jpg while I want 000002.jpg should come after 000001.jpg. Can you please point out how to modify the code so that I can retain a sequence in gif animation?
$command = "convert -set delay 5 -loop 0 $img_dir/00000*.jpg -morph 10 $img_dir/morph.gif";
exec($command);

Normally, the length of the name is kept constant, so if you add an extra digit in going from 9 to 10, you remove one of the leading zeroes to keep the length the same. I mean, most people do this:
000008
000009
000010
000011
whereas you appear to have done this where the length changes at 10:
000008
000009
0000010
0000011
I would suggest you change the program that generates the naming so it generates a constant length name then everything will work properly.
Failing that, if you wish to, or are obliged to, stick with your naming system, ImageMagick will accept a list of files in any order you like, so you can create a file called filelist.txt or somesuch, with contents like this
000000.jpg
000001.jpg
000002.jpg
...
000009.jpg
0000010.jpg
0000011.jpg
and use it like this:
convert -delay 100 -loop 0 #filelist.txt anim.gif
Alternatively, you could let bash print your filenames always with 5 leading spaces using a command such as this:
printf "00000%d.jpg " {0..4}
000000.jpg 000001.jpg 000002.jpg 000003.jpg 000004.jpg
and embed that in your ImageMagick command
convert -delay 100 -loop 0 $(printf "00000%d.jpg " {0..4}) anim.gif

Related

Make a screenshot every page of PDF file

How can I make a screenshot from every page of PDF file and save result as images in PHP? Is it possible?
Maybe the "make a screenshot" can be replaced for your purpose by "create a raster image" for each PDF page?
In this case you could use ImageMagick and/or one of its PHP-enabled libraries. Here is a command line representation:
convert some.pdf[15-19] some.png
This will convert not all pages, but the page range 16--20 (page counting here is zero-based (not intuitive, I know...). To convert all pages, just skip the [15-19] part.
The output PNG names will be some-0.png, some-1.png, ... some-4.png.
To create JPEG or GIF instead of PNG, simply use one of these:
convert some.pdf[15-19] some.jpg
convert some.pdf[15-19] some.gif
By default ImageMagick will use a resolution of 72 PPI. This will indirectly determine the image dimensions of the PNG/JPEG/GIF output. Should you need other output dimensions than the defaults, you have different options, for example:
either add -density
or add -resize
to the command line:
convert -density 200 some.pdf some.png
convert some.pdf -resize 50% some.png

Combining 2 GraphicsMagick commands into 1 command, like in ImageMagick

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.

Is there a limit on the length of command passed to exec in PHP?

Currently I need to merge that 50+ PDF files into 1 PDF. I am using PDFTK. Using the guide from: http://www.johnboy.com/blog/merge-multiple-pdf-files-with-php
But it is not working. I have verified the following:
I have tried the command to merge 2 pdfs from my PHP and it is working.
I have echo the final command and copied that command and paste into command prompt and run manually and all the 50 PDFs are successfully merged.
Thus exec in my PHP and the command to merge 50 PDFs are both correct but it is not working when done together in PHP. I have also stated set_time_limit(0) to prevent any timeout but still not working.
Any idea what's wrong?
You can try to find out yourself:
print exec(str_repeat(' ', 5000) . 'whoami');
I think it's 8192, at least on my system, because it fails with strings larger than 10K, but it still works with strings shorter than 7K
I am not sure if there is a length restriction on how long a single command can be but I am pretty sure you can split it accross multiple lines with "\" just to check if thats the problem. Again I dont think it is... Is there any error output when you try to run the full command with PHP and exec, also try system() instead of exec().
PDFTK versions prior to 1.45 are limited to merge 26 files cuz use "handles"
/* Collate scanned pages sample */
pdftk A=even.pdf B=odd.pdf shuffle A B output collated.pdf
as you can see "A" and "B" are "handles", but should be a single upper-case letter, so only A-Z can be used, if u reach that limit, maybe you script outputs an error like
Error: Handle can only be a single, upper-case letter
but in 1.45 this limitation was removed, changelog extract
You can now use multi-character input handles. Prior versions were
limited to a single character, imposing an arbitrary limitation on
the number of input PDFs when using handles. Handles still must be all
upper-case ASCII.
maybe you only need update your lib ;)

Converting a PDF to JPG with ImageMagick in PHP Gives Odd Letter Spacing

I am trying to convert a PDF to a JPG with a PHP exec() call, which looks like this:
convert page.pdf -resize 716x716 page.jpg
For some reason, the JPG comes out with janky text, despite the PDF looking just fine in Acrobat and Mac Preview. Here is the original PDF:
http://whit.info/dev/conversion/page.pdf
and here is the janktastic output:
http://whit.info/dev/conversion/page.jpg
The server is a LAMP stack with PHP 5 and ImageMagick 6.2.8.
Can you help this stumped Geek?
Thanks in advance,
Whit
ImageMagick is just going to call out to Ghostscript to convert this PDF to an image. If you run gs on the pdf, you get the same badly-spaced output.
I suspect Ghostscript isn't handling the PDF's embedded TrueType fonts very well. If you could change your output to either embed Type 1 fonts or use a "core" PostScript font, you'd get better results.
I suspect its an encoding/widths issue. Both are a tad off, though I can't put my finger on why.
Here are some suspects:
First
The text stream is defined in UTF-16 LE. charNULLcharNULL, using the normal string drawing command syntax:
(some text) Tj
There's a way to escape any old character value into a () string. You can also define strings in hex thusly:
<203245> Tj
Neither method are used, just the questionable inline nulls. That could cause an issue in GS if it's trying to work with pointers to char without lengths associated with them.
Second
The widths array is dumb. You can define widths in groups thusly:
[ 32 [450 525 500] 37 [600 250] 40 [0] ]
This defines
32: 450
33: 525
34: 500
37: 600
38: 250
40: 0
These fonts defines their consecutive widths in individual arrays. Not illegal, but definitely wasteful/stupid, and if GS were coded to EXPECT gaps between the arrays, it could induce a bug.
There's also some extremely fishy values in the array. 32 through 126 are defined consecutively, but then it starts jumping all over: ...126 [600] 8364 [500] 8216 [222] 402 [500] 8222 [389]. 8230 [1000] 8224 [444]... and then goes back to being consecutive from 160 to 255.
Just weird.
Third
I'm not even remotely sure, but the CIDToGIDMap stream contains an AWEFUL lot of nulls.
Bottom line
Those fonts are fishy. And I've never heard of "Bellflower Books" or "UFPDF 0.1"
That version number makes me cringe. It should make you cringe too.
Googleing for "UFPDF" I found this note from the author:
Note: I wrote UFPDF as an experiment, not as a finished product. If you have problems using it, don't bug me for support. Patches are welcome though, but I don't have much time to maintain this.
UFPDF is a PHP library that sits on top of FPDF. 0.1. Just run away.

PHP Converting PDF's to images -dUseCropBox

I'm trying to convert a PDF to an image and I need to make sure that the -dUseCropBox parameter is specified for when calling Ghostscript. Can this be done?
convert "/var/www/vhosts/site.co.uk/httpdocs/uploads/source_pdf/PP4SDpdf.pdf" -resize 500X500 "/var/www/vhosts/site.co.uk/httpdocs/uploads/image_pdf/SaturdayTest.jpg"
It works well but just need to get the Ghostscript parameter in.
Is it acceptable for you to run Ghostscript directly (instead of having convert call it anyway) ?
I ask, because convert does not do the PDF => JPEG conversion by itself. It calls Ghostscript as its 'delegate' to do the job. So for convert to work you need to have access to a functional Ghostscript installation on that system anyway... .
But how to add custom parameters to converts commandline to pass them through to Ghostscript's commandline isn't easy to figure out. Ghostscript's commandline isn't exactly easy either, but at least it is fully documented at a well-known place (see Use.htm, Devices.htm and Ps2pdf.htm there).
Here is a command that would convert your input PDF to a series of JPEGs (one file for each PDF page). I'm assuming Windows -- for Linux just replace the ^ by \ and gswin32c.exe by gs:
gswin32c.exe ^
-o "d:/path with spaces/to/output/dir/input_page_%03d.jpeg ^
-sDEVICE=jpeg ^
-dJPEQ=95 ^
-r720 ^
-g5000x5000 ^
-dUseCropBox=true ^
"d:/path/to/input.pdf"
Explanation:
-dJPEGQ sets the JPEG quality. Accepts integer values in the range 0..100. Higher values create bigger files... (Ghostscript's default for JPEGQ is set to 75.)
-r720 sets a (rather high) resolution of 720dpi. Higher values create bigger files... (Ghostscript's default for its jpeg output device would be 72dpi.)
-g5000x5000 gives the file dimension in pixels. (Note: when decreasing the -r... value you MUST also accordingly decrease the -g... value to keep the same dimension in userspace inches or mm.)
You could also add -dPDFFitPage=true if that is useful for you.
The switch for imagemagick (the convert-command) is:
-define pdf:use-cropbox=true
see http://www.imagemagick.org/Usage/formats/#ps_reading

Categories