{"id":69995,"date":"2025-10-03T03:01:00","date_gmt":"2025-10-02T17:01:00","guid":{"rendered":"https:\/\/www.rjmprogramming.com.au\/ITblog\/?p=69995"},"modified":"2025-10-03T13:54:13","modified_gmt":"2025-10-03T03:54:13","slug":"command-line-imagemagick-pdf-and-animated-gif-tutorial","status":"publish","type":"post","link":"https:\/\/www.rjmprogramming.com.au\/ITblog\/command-line-imagemagick-pdf-and-animated-gif-tutorial\/","title":{"rendered":"Command Line ImageMagick PDF and Animated GIF Tutorial"},"content":{"rendered":"<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=\"_blank\" href=\"http:\/\/www.rjmprogramming.com.au\/Mac\/paintbrush_crontab_jpeg_pdf.gif\" rel=\"noopener\"><img decoding=\"async\" style=\"border: 15px solid pink;\" alt=\"Command Line ImageMagick PDF and Animated GIF Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/Mac\/paintbrush_crontab_jpeg_pdf.gif\" title=\"Command Line ImageMagick PDF and Animated GIF Tutorial\"  style=\"float:left;\"  \/><\/a><p class=\"wp-caption-text\">Command Line ImageMagick PDF and Animated GIF Tutorial<\/p><\/div>\n<p>The recent <a title='Command Line ImageMagick JPEG Image Creation Tutorial' href='#climjpegict'>Command Line ImageMagick JPEG Image Creation Tutorial<\/a> addressed &#8230;<\/p>\n<blockquote>\n<p>For a while now, on macOS, we&#8217;ve been putting up with a scenario with our beloved macOS <a target=\"_blank\" title='macOS PaintBrush' href='https:\/\/paintbrush.sourceforge.io\/' rel=\"noopener\">Paintbrush<\/a> desktop application version whereby it will not save images in &#8230;<\/p>\n<p><\/p>\n<ul>\n<li>JPEG format &#8230; any more, so we have been saving in &#8230;<\/li>\n<li>PNG format<\/li>\n<\/ul>\n<p><\/p>\n<p> &#8230; for some time now.  Is this a big deal?  Well, that is the question?  We got a bit of a surprise in aspects of the solution we came up with.<\/p>\n<\/blockquote>\n<p> &#8230; as a &#8220;single image file&#8221; convert<sup>ing<\/sup> concept.   But then, while we are there &#8230;<\/p>\n<ol>\n<li>there are two &#8220;container like&#8221; image slide presentation formats we like to use, they being animated GIF and PDF &#8230; and it just so happens &#8230;<\/li>\n<li><a target=\"_blank\" href='https:\/\/imagemagick.org' title='ImageMagick' rel=\"noopener\">ImageMagick<\/a> command line (for us, gotten to via PHP <a target=\"_blank\" title='PHP exec() method information' href='http:\/\/php.net\/manual\/en\/function.exec.php' rel=\"noopener\">exec<\/a>) happens to be very good at convert<sup>ing<\/sup> sets of JPEG images to animated GIF and PDF &#8220;container like&#8221; presentation formats<\/li>\n<\/ol>\n<p>But we don&#8217;t want to automate any such task on every scenario where we are creating those original PNG files in our macOS Paintbrush desktop application.  So we decided that &#8230;<\/p>\n<ul>\n<li>if filenames contain <i>_to_pdf<\/i> or <i>_via_pdf<\/i> within their PNG filenames we are interested in a <i>set of JPEG images to PDF conversion via ImageMagick command line automated process<\/i>, here<\/li>\n<li>if filenames contain <i>_to_gif<\/i> or <i>_via_gif<\/i> within their PNG filenames we are interested in a <i>set of JPEG images to animated GIF via ImageMagick command line conversion automated process<\/i>, here<\/li>\n<\/ul>\n<p>And do any of the &#8220;automation&#8221; scheduling arrangements need to change, here?  No, it&#8217;s the PHP <font color=blue>that changes<\/font>, to suit &#8230;<\/p>\n<p>&lt;?php<br \/>\n<code><br \/>\n  \/\/ paintbrush_png_jpg.php<br \/>\n  \/\/ August, 2025<br \/>\n  \/\/ crontab php command line called way to backup Paintbrush created *.png to reduced size *.jpg<br \/>\n  <font color=blue>$pdfprefix=\"\";<br \/>\n  $pdfcommand=\"\";<br \/>\n  $gifcommand=\"\";<\/font><br \/>\n  $it = new GlobIterator(__DIR__ . \"\/*.png\");<br \/>\n  $last2mis = 9020;<br \/>\n  foreach ( $it as $file ) {<br \/>\n    if ((time() - $file-&gt;getMTime()) &lt;= $last2mis) {<br \/>\n      <font color=blue>if (strpos($file, '_to_pdf') !== false || strpos($file, '_via_pdf') !== false) {<br \/>\n        if (strpos($file, '_to_pdf') !== false) {<br \/>\n          $pdfprefix=explode('_to_pdf', $file)[0];<br \/>\n          if (file_exists($pdfprefix . \".Pdf\")) {<br \/>\n            unlink($pdfprefix . \".Pdf\");<br \/>\n          }<br \/>\n          $pdfcommand=' ;  \/usr\/local\/bin\/convert -quality 100 \"' . $pdfprefix . '*.{jpeg}\" ' . $pdfprefix . '.Pdf';<br \/>\n        } else if (strpos($file, '_via_pdf') !== false) {<br \/>\n          $pdfprefix=explode('_via_pdf', $file)[0];<br \/>\n          if (file_exists($pdfprefix . \".Pdf\")) {<br \/>\n            unlink($pdfprefix . \".Pdf\");<br \/>\n          }<br \/>\n          $pdfcommand=' ;  \/usr\/local\/bin\/convert -quality 100 \"' . $pdfprefix . '*.{jpeg}\" ' . $pdfprefix . '.Pdf';<br \/>\n        }<br \/>\n      }<br \/>\n      if (strpos($file, '_to_gif') !== false || strpos($file, '_via_gif') !== false) {<br \/>\n        if (strpos($file, '_to_gif') !== false) {<br \/>\n          $gifprefix=explode('_to_gif', $file)[0];<br \/>\n          if (file_exists($gifprefix . \".Gif\")) {<br \/>\n            unlink($gifprefix . \".Gif\");<br \/>\n          }<br \/>\n          $gifcommand=' ;  \/usr\/local\/bin\/convert -delay 400 \"' . $gifprefix . '*.{jpeg}\" -loop 0 ' . $gifprefix . '.Gif';<br \/>\n        } else if (strpos($file, '_via_gif') !== false) {<br \/>\n          $gifprefix=explode('_via_gif', $file)[0];<br \/>\n          if (file_exists($gifprefix . \".Gif\")) {<br \/>\n            unlink($gifprefix . \".Gif\");<br \/>\n          }<br \/>\n          $gifcommand=' ;  \/usr\/local\/bin\/convert -delay 400 \"' . $gifprefix . '*.{jpeg}\" -loop 0 ' . $gifprefix . '.Gif';<br \/>\n        }<br \/>\n      }<\/font><br \/>\n      if (!file_exists(str_replace('.png','.jpg',$file)) && !file_exists(str_replace('.png','.jpeg',$file))) {<br \/>\n        exec(\"cd \" . __DIR__ . '; \/usr\/local\/bin\/convert -quality 30 ' . $file . ' ' . str_replace('.png','.jpeg',$file)<font color=blue> . $pdfcommand . $gifcommand<\/font>);<br \/>\n      } else if (!file_exists(str_replace('.png','.jpg',$file)) && file_exists(str_replace('.png','.jpeg',$file))) {<br \/>\n        exec(\"cd \" . __DIR__ . '; \/usr\/local\/bin\/convert -quality 30 ' . $file . ' ' . str_replace('.png','.jpg',$file)<font color=blue> . $pdfcommand . $gifcommand<\/font>);<br \/>\n      }<br \/>\n    }<br \/>\n  }<br \/>\n<\/code><br \/>\n?&gt;<\/p>\n<p> &#8230; to make this happen in <a target=\"_blank\" href=\"http:\/\/www.rjmprogramming.com.au\/PHP\/Geographicals\/diff.php?one=http:\/\/www.rjmprogramming.com.au\/Mac\/paintbrush_png_jpg.php-GETME\" rel=\"noopener\">the changed<\/a> <a target=\"_blank\" href=\"http:\/\/www.rjmprogramming.com.au\/Mac\/paintbrush_png_jpg.php-GETME\" rel=\"noopener\">paintbrush_png_jpg.php<\/a> second draft, designed for &#8220;inhouse use only&#8221; but feel free to download and use, if it interests you.<\/p>\n<p>All this begs the question &#8230; so, <a onclick=\"document.getElementById('lvt').style.display='block'; document.getElementById('lvt').scrollIntoView();\" style=text-decoration:underline;cursor:pointer;>how will we remember this arcane arrangement?<\/a><\/p>\n<p><img src='\/Mac\/luna_viato.jpg' id=lvt style=display:none;><\/img><\/p>\n<p><!--p>You can also see this play out at WordPress 4.1.1's <a target=\"_blank\" href='\/\/www.rjmprogramming.com.au\/ITblog\/command-line-imagemagick-pdf-and-animated-gif-tutorial\/' rel=\"noopener\">Command Line ImageMagick PDF and Animated GIF Tutorial<\/a>.<\/p-->\n<hr>\n<p id='climjpegict'>Previous relevant <a target=\"_blank\" title='Command Line ImageMagick JPEG Image Creation Tutorial' href='\/\/www.rjmprogramming.com.au\/ITblog\/command-line-imagemagick-jpeg-image-creation-tutorial\/' rel=\"noopener\">Command Line ImageMagick JPEG Image Creation Tutorial<\/a> is shown below.<\/p>\n<div style=\"width: 230px\" class=\"wp-caption alignnone\"><a target=\"_blank\" href=\"http:\/\/www.rjmprogramming.com.au\/Mac\/paintbrush_crontab_png_to_jpeg.gif\" rel=\"noopener\"><img decoding=\"async\" style=\"border: 15px solid pink;\" alt=\"Command Line ImageMagick JPEG Image Creation Tutorial\" src=\"http:\/\/www.rjmprogramming.com.au\/Mac\/paintbrush_crontab_png_to_jpeg.gif\" title=\"Command Line ImageMagick JPEG Image Creation Tutorial\"  style=\"float:left;\"  \/><\/a><p class=\"wp-caption-text\">Command Line ImageMagick JPEG Image Creation Tutorial<\/p><\/div>\n<p>For a while now, on macOS, we&#8217;ve been putting up with a scenario with our beloved macOS <a target=\"_blank\" title='macOS PaintBrush' href='https:\/\/paintbrush.sourceforge.io\/' rel=\"noopener\">Paintbrush<\/a> desktop application version whereby it will not save images in &#8230;<\/p>\n<ul>\n<li>JPEG format &#8230; any more, so we have been saving in &#8230;<\/li>\n<li>PNG format<\/li>\n<\/ul>\n<p> &#8230; for some time now.  Is this a big deal?  Well, that is the question?  We got a bit of a surprise in aspects of the solution we came up with.<\/p>\n<p>With that, pretty obvious to us, first aim of smaller sized output image media files to start producing, we decided to involve &#8230;<\/p>\n<ul>\n<li>macOS command line &#8230;<\/li>\n<li>PHP usage ( ending up with <a target=\"_blank\" href=\"http:\/\/www.rjmprogramming.com.au\/Mac\/paintbrush_png_jpg.php_GETME\" rel=\"noopener\">paintbrush_png_jpg.php<\/a> ) &#8230; in a &#8230;<\/li>\n<li><a target=\"_blank\" title='crontab information from computerhope ... thanks' href='http:\/\/www.computerhope.com\/jargon\/c\/cron.htm' rel=\"noopener\">crontab<\/a> scheduled &#8230;<br \/>\n<code><br \/>\n* * * * * ksh -c \"cd \/Applications\/MAMP\/htdocs; \/Applications\/MAMP\/bin\/php\/php7.4.33\/bin\/php \/Applications\/MAMP\/htdocs\/paintbrush_png_jpg.php\"<br \/>\n<\/code>\n<\/li>\n<\/ul>\n<p> &#8230; procedure, running each minute here on this MacBook Air using a command line command exemplified for a PNG called my_image.png &#8230;<\/p>\n<p><code><br \/>\n <a target=\"_blank\" title='ImageMagick software suite' href='https:\/\/www.imagemagick.org\/' rel=\"noopener\">convert<\/a> -quality 30 my_image.png my_image.jpeg<br \/>\n<\/code><\/p>\n<p> &#8230; via this PHP ( where we thank <a target=\"_blank\" title='Useful link, thanks' href='https:\/\/stackoverflow.com\/questions\/13324277\/select-a-file-that-was-created-the-last-minute' rel=\"noopener\">this useful link<\/a> for great help ) &#8230;<\/p>\n<p><code><br \/>\n&lt;?php<br \/>\n  \/\/ paintbrush_png_jpg.php<br \/>\n  \/\/ August, 2025<br \/>\n  \/\/ crontab php command line called way to backup Paintbrush created *.png to reduced size *.jpg<br \/>\n  $it = new GlobIterator(__DIR__ . \"\/*.png\");<br \/>\n  $last2mis = 9020;<br \/>\n  foreach ( $it as $file ) {<br \/>\n    if ((time() - $file-&gt;getMTime()) &lt;= $last2mis) {<br \/>\n      if (!file_exists(str_replace('.png','.jpg',$file)) && !file_exists(str_replace('.png','.jpeg',$file))) {<br \/>\n        exec(\"cd \" . __DIR__ . '; \/usr\/local\/bin\/convert -quality 30 ' . $file . ' ' . str_replace('.png','.jpeg',$file));<br \/>\n      }<br \/>\n    }<br \/>\n  }<br \/>\n?&gt;<br \/>\n<\/code><\/p>\n<p> &#8230; which achieves it&#8217;s objective, for the most part, because we are always saving these PNG files to <a target=\"_blank\" title='MAMP for Apache\/PHP\/MySql on Mac OS X local web server' href='http:\/\/www.mamp.info' rel=\"noopener\">MAMP<\/a>&#8216;s Document Root ( ie. \/Applications\/MAMP\/htdocs for us ).<\/p>\n<p>All good, smaller image JPEG files do result, but the twist for us came when we assembled our first JPEG vs PNG sets &#8230;<\/p>\n<p><code><br \/>\n$ ls -l mamp_p*.*g*<br \/>\n-rw-r--r--  1 user  admin   459400  3 Aug 15:15 mamp_paintbrush_job-15.jpeg<br \/>\n-rw-r--r--@ 1 user  admin  1857056  3 Aug 14:39 mamp_paintbrush_job-15.png<br \/>\n-rw-r--r--  1 user  admin   413477  3 Aug 15:14 mamp_paintbrush_job-17.jpeg<br \/>\n-rw-r--r--@ 1 user  admin  1816410  3 Aug 14:47 mamp_paintbrush_job-17.png<br \/>\n-rw-r--r--@ 1 user  admin   246569  3 Aug 15:08 mamp_paintbrush_job-21.jpeg<br \/>\n-rw-r--r--@ 1 user  admin  1959028  3 Aug 15:08 mamp_paintbrush_job-21.png<br \/>\n-rw-r--r--  1 user  admin   264874  3 Aug 15:10 mamp_paintbrush_job-23.jpeg<br \/>\n-rw-r--r--@ 1 user  admin  2555260  3 Aug 15:09 mamp_paintbrush_job-23.png<br \/>\n-rw-r--r--  1 user  admin   249117  3 Aug 15:11 mamp_paintbrush_job-25.jpeg<br \/>\n-rw-r--r--@ 1 user  admin  2704233  3 Aug 15:11 mamp_paintbrush_job-25.png<br \/>\n-rw-r--r--  1 user  admin   230524  3 Aug 15:16 mamp_paintbrush_job-27.jpeg<br \/>\n-rw-r--r--@ 1 user  admin  1962296  3 Aug 15:15 mamp_paintbrush_job-27.png<br \/>\n-rw-r--r--  1 user  admin   280417  3 Aug 15:17 mamp_paintbrush_job-29.jpeg<br \/>\n-rw-r--r--@ 1 user  admin  2677561  3 Aug 15:16 mamp_paintbrush_job-29.png<br \/>\n$<br \/>\n<\/code><\/p>\n<p> &#8230; into two animated GIF images ( with PNG based one called paintbrush_crontab_png_to_jpeg.gif ) &#8230;<\/p>\n<p><code><br \/>\n$ ls -l paintbrush_*.gif<br \/>\n-rw-r--r--@ 1 user  staff  5100166  3 Aug 19:11 <a target=\"_blank\" href=\"http:\/\/www.rjmprogramming.com.au\/Mac\/paintbrush_crontab_png_to_jpeg.gif\" rel=\"noopener\">paintbrush_crontab_png_to_jpeg.gif<\/a><br \/>\n-rw-r--r--@ 1 user  staff  6485830  3 Aug 19:14 <a target=\"_blank\" href=\"http:\/\/www.rjmprogramming.com.au\/Mac\/paintbrush_png_to_jpeg_crontab.gif\" rel=\"noopener\">paintbrush_png_to_jpeg_crontab.gif<\/a><br \/>\n$<br \/>\n<\/code><\/p>\n<p> &#8230; via our inhouse <a target=\"_blank\" href='http:\/\/www.rjmprogramming.com.au\/PHP\/animegif\/tutorial_to_animated_gif.php' rel=\"noopener\">animated GIF creator helper<\/a> web application.<\/p>\n<p><a target=\"_blank\" title='animated GIF larger creating it with JPEG than PNG' href='https:\/\/www.google.com\/search?q=animated+GIF+larger+creating+it+with+JPEG+than+PNG&#038;rlz=1C5OZZY_en&#038;oq=animated+GIF+larger+creating+it+with+JPEG+than+PNG&#038;gs_lcrp=EgZjaHJvbWUyBggAEEUYOTIHCAEQIRigAdIBCjI3NzgzajBqMTWoAgiwAgHxBTV7r9iyF30D&#038;sourceid=chrome&#038;ie=UTF-8' rel=\"noopener\">Huh?!<\/a>   Read a <a target=\"_blank\" title='Is it better to make a GIF out of a JPG or PNG?' href='https:\/\/graphicdesign.stackexchange.com\/questions\/159310\/is-it-better-to-make-a-gif-out-of-a-jpg-or-png' rel=\"noopener\">bit more about it here<\/a>!<\/p>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d69351' onclick='var dv=document.getElementById(\"d69351\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"https:\/\/www.rjmprogramming.com.au\/ITblog\/tag\/animated-GIF\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d69351' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n<hr>\n<p>If this was interesting you may be interested in <a title='Click here to see topics in which you might be interested' href='#d69995' onclick='var dv=document.getElementById(\"d69995\"); dv.innerHTML = \"&lt;iframe width=670 height=600 src=\" + \"https:\/\/www.rjmprogramming.com.au\/ITblog\/tag\/pdf\" + \"&gt;&lt;\/iframe&gt;\"; dv.style.display = \"block\";'>this<\/a> too.<\/p>\n<div id='d69995' style='display: none; border-left: 2px solid green; border-top: 2px solid green;'><\/div>\n","protected":false},"excerpt":{"rendered":"<p>The recent Command Line ImageMagick JPEG Image Creation Tutorial addressed &#8230; For a while now, on macOS, we&#8217;ve been putting up with a scenario with our beloved macOS Paintbrush desktop application version whereby it will not save images in &#8230; &hellip; <a href=\"https:\/\/www.rjmprogramming.com.au\/ITblog\/command-line-imagemagick-pdf-and-animated-gif-tutorial\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4,12,29,30,37],"tags":[5291,234,256,272,274,319,320,590,896,913,932,997,1893,1319],"class_list":["post-69995","post","type-post","status-publish","format-standard","hentry","category-animation","category-elearning","category-operating-system","category-photography","category-tutorials","tag-animated-gif-slide","tag-command-line","tag-container","tag-cron","tag-crontab","tag-desktop","tag-desktop-application","tag-image","tag-paintbrush","tag-pdf","tag-php","tag-programming","tag-schedule","tag-tutorial"],"_links":{"self":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/69995"}],"collection":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/comments?post=69995"}],"version-history":[{"count":15,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/69995\/revisions"}],"predecessor-version":[{"id":70012,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/posts\/69995\/revisions\/70012"}],"wp:attachment":[{"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/media?parent=69995"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/categories?post=69995"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rjmprogramming.com.au\/ITblog\/wp-json\/wp\/v2\/tags?post=69995"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}