{"id":400,"date":"2012-09-08T16:05:36","date_gmt":"2012-09-08T22:05:36","guid":{"rendered":"http:\/\/rrbits.com\/epb\/?p=400"},"modified":"2012-09-08T16:12:55","modified_gmt":"2012-09-08T22:12:55","slug":"imagemagick-rounded-corner-php-function","status":"publish","type":"post","link":"https:\/\/rrbits.com\/epb\/2012\/09\/08\/imagemagick-rounded-corner-php-function\/","title":{"rendered":"ImageMagick: Rounded-corner PHP function"},"content":{"rendered":"<p>I&#8217;ve converted my rounded-corner bash script into a PHP function that&#8217;ll use the Image Magick command line tools to do the same.  With some added functionality to handle automatically creating thumbnails and applying a background color to the source image itself.  This also allows for the insertion of basic pre-processing and post-processing arguments to IM.<\/p>\n<p>For more information and output examples see. <a href=\"https:\/\/rrbits.com\/epb\/2012\/06\/06\/rounded-corner-script\/\" title=\"Rounded Corner Script\">the bash version.<\/a><\/p>\n<p>To see an example of thumbnails generated with some pre-processing done:<\/p>\n<div id=\"attachment_406\" style=\"width: 160px\" class=\"wp-caption alignleft\"><a href=\"https:\/\/rrbits.com\/epb\/files\/2012\/09\/first-preprocessor-test.jpg\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-406\" src=\"https:\/\/rrbits.com\/epb\/files\/2012\/09\/first-preprocessor-test-150x150.jpg\" alt=\"\" title=\"First Preprocessor Test\" width=\"150\" height=\"150\" class=\"size-thumbnail wp-image-406\" \/><\/a><p id=\"caption-attachment-406\" class=\"wp-caption-text\">First Preprocessor Test<\/p><\/div>\n<p>This is a sample done with thumbnail pre-processing.  That is processing done before the rounded corners are made.<\/p>\n<p>With this sample, I switched colorspace to HSL and then set the hue and saturation to a constant before applying the glass-bubble rounded corners.<\/p>\n<p>Known bug: sometimes the glass-bubble method will add a single pixel to the width, which is transparent.  I believe passing <code>-trim<\/code> in the postprocessing option may trim that off for you, though I have not thoroughly tested it.<\/p>\n<p>Also: I have no idea if this will work on a Windows server.<\/p>\n<p><!--more--><\/p>\n<pre lang=\"php\">\/**\r\n * Produce a thumbnail with rounded corners as specificed in options.\r\n * @param String $in Input file name.\r\n * @param String $out Output file name.\r\n * @param Integer $width Width constraint of desired thumbnail. Omit with empty string.\r\n * @param Integer $height Height of desired thumbnail. Omit with empty string.\r\n * @param Array $options An array of options as such:\r\n *  method: plain or glass-bubble (Default: plain)\r\n *  radius: requested radius (Default: min($width, $height) * 0.2)\r\n *   if it calculates 0, this will default to 14.\r\n *  image-background: Background color applied to the image itself. (Default: '#000000')\r\n *  background: Background color behind an image (for the corners) (Default: transparent)\r\n *   A note for this: jpg output doesn't really like transparent.\r\n *  convertcommand: Override the path to the convert command. (default: convert)\r\n *  preprocessing: Additional preprocessing arguments you'd like to send IM for the preproc img\r\n *  postprocessing: Additional postprocessing arguments \"\" for the output thumbnail.\r\n * @return Mixed String if error (contains error message) or array of image information.\r\n *\/\r\nfunction rounded_thumbnail_im($in, $out, $width, $height, $options = array())\r\n{\r\n   $convertcommand = 'convert';\r\n   $method = 'plain';\r\n   $imgback = '#000000';\r\n   $back = 'transparent';\r\n   $radius = floor(min($width, $height) * 0.2);\r\n   $preprocessing = '';\r\n   $postprocessing = '';\r\n   if($radius == 0)\r\n   {\r\n      $radius = 14;\r\n   }\r\n   if(isset($options['method']))\r\n   {\r\n      if(in_array($options['method'], array('plain', 'glass-bubble')))\r\n      {\r\n         $method = $options['method'];\r\n      }\r\n   }\r\n   \r\n   if(isset($options['image-background'])) $options['imgback'] = $options['image-background'];\r\n   if(isset($options['background'])) $options['back'] = $options['background'];\r\n   \r\n   foreach(array('imgback', 'back', 'convertcommand', \r\n   'radius', 'preprocessing', 'postprocessing') as $key)\r\n   {\r\n      if(isset($options[$key]))\r\n      {\r\n         $$key = $options[$key];\r\n      }\r\n   }\r\n   \r\n   if(!is_file($in))\r\n   {\r\n      return \"$in is not a file.\";\r\n   }\r\n\r\n   $swidth = escapeshellarg($width);\r\n   $sheight = escapeshellarg($height);\r\n   $sradius = intval($radius);\r\n   $sinfile = escapeshellarg($in);\r\n   $soutfile = escapeshellarg($out);\r\n   $sbackground = escapeshellarg($back);\r\n   $simgbackground = escapeshellarg($imgback);\r\n   $spreproc = escapeshellcmd($preprocessing);\r\n   $spostproc = escapeshellcmd($postprocessing);\r\n   \r\n   $sconv = escapeshellarg($convertcommand);\r\n   \r\n   \/\/Build preprocessor command.\r\n   $resize = '';\r\n   if($width != '' || $height != '')\r\n   {\r\n      $resize = \"-resize {$swidth}x{$sheight}\";\r\n   }\r\n   $preprocess = \"$sconv $sinfile $resize -background $simgbackground -flatten $spreproc png:-\";\r\n   \r\n   \/\/Post process:\r\n   if($back != 'transparent')\r\n   {\r\n      $backgroundproc = \"png:- | $sconv png:- -background $sbackground -flatten $spostproc\";\r\n   }\r\n   else\r\n   {\r\n      if($postprocessing == '')\r\n      {\r\n         $backgroundproc = \"\";\r\n      }\r\n      else\r\n      {\r\n         $backgroundproc = \"png:- | $sconv png:- -background transparent $spostproc\";\r\n      }\r\n   }\r\n   \r\n   \/\/Perform smashy smashy\r\n   if($method == 'plain')\r\n   {\r\n      $command=\"$preprocess | $sconv \\\\( png:- \r\n      \\\\( +clone  -alpha extract \r\n         -draw \\\"fill black polygon 0,0 0,$sradius $sradius,0 fill white circle $sradius,$sradius $sradius,0\\\" \r\n         \\\\( +clone -flip \\\\) -compose Multiply -composite \r\n         \\\\( +clone -flop \\\\) -compose Multiply -composite \r\n      \\\\) -alpha off -compose CopyOpacity -composite \\\\) $backgroundproc $soutfile\";\r\n      $command = preg_replace('\/[\\r\\n]+\/', '', $command);\r\n      \/\/echo $command;\r\n      system($command);\r\n      if(is_file($out) && filesize($out) > 100)\r\n      {\r\n         return getimagesize($out);\r\n      }\r\n      else\r\n      {\r\n         return 'Plain rounded-corner conversion failed.';\r\n      }\r\n   }\r\n   else if ($method == 'glass-bubble')\r\n   {\r\n      \/\/Removes the stream to standard out from the preprocess command.\r\n      \/\/So we can use it slightly differently.\r\n      $preprocess = preg_replace('\/png\\:-$\/', '', $preprocess);\r\n      $nfile = tempnam(sys_get_temp_dir(), 'GBb');\r\n      $snfile = escapeshellarg('png:'.$nfile);\r\n      system($cmd = \"$preprocess $snfile\");\r\n      \/\/echo \"$cmd\\n\";\r\n      $command=\"$sconv $snfile -alpha off -fill white -colorize 100% \r\n      -draw \\\"fill black polygon 0,0 0,$sradius $sradius,0 fill white circle $sradius,$sradius $sradius,0\\\" \r\n      \\\\( +clone -flip \\\\) -compose Multiply -composite \r\n      \\\\( +clone -flop \\\\) -compose Multiply -composite \r\n      -background Gray50 -alpha Shape  png:- |\r\n      $sconv png:- -bordercolor None -border 1x1 \r\n          -alpha Extract -blur 0x10  -shade 130x30 -alpha On \r\n          -background gray50 -alpha background -auto-level \r\n          -function polynomial  3.5,-5.05,2.05,0.3 \r\n          \\\\( +clone -alpha extract  -blur 0x3 \\\\) \r\n          -channel RGB -compose multiply -composite \r\n          +channel +compose -chop 1x1 \r\n          png:- |\r\n       $sconv \\\\( $snfile -alpha Set png:- \r\n          \\\\( -clone 0,1 -alpha Opaque -compose Hardlight -composite \\\\) \r\n          -delete 0 -compose In -composite \\\\) $backgroundproc $soutfile 2>> debug.txt\";\r\n      $command = preg_replace('\/[\\r\\n]+\/', '', $command);\r\n      \/\/echo $command,\"\\n\";\r\n      system($command);\r\n      \r\n      if(is_file($nfile))\r\n      {\r\n         unlink($nfile);\r\n      }\r\n      if(is_file($out) && filesize($out) > 100)\r\n      {\r\n         return getimagesize($out);\r\n      }\r\n      else\r\n      {\r\n         return 'Glass-bubble rounded-corner conversion failed.';\r\n      }      \r\n   }\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve converted my rounded-corner bash script into a PHP function that&#8217;ll use the Image Magick command line tools to do the same. With some added functionality to handle automatically creating thumbnails and applying a background color to the source image itself. This also allows for the insertion of basic pre-processing and post-processing arguments to IM&#8230;.  <a class=\"excerpt-read-more\" href=\"https:\/\/rrbits.com\/epb\/2012\/09\/08\/imagemagick-rounded-corner-php-function\/\" title=\"ReadImageMagick: Rounded-corner PHP function\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":413,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[42,31],"tags":[4243,4006],"class_list":["post-400","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux","category-php","tag-image-manipulation","tag-imagemagick"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/rrbits.com\/epb\/wp-json\/wp\/v2\/posts\/400","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rrbits.com\/epb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rrbits.com\/epb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rrbits.com\/epb\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rrbits.com\/epb\/wp-json\/wp\/v2\/comments?post=400"}],"version-history":[{"count":12,"href":"https:\/\/rrbits.com\/epb\/wp-json\/wp\/v2\/posts\/400\/revisions"}],"predecessor-version":[{"id":414,"href":"https:\/\/rrbits.com\/epb\/wp-json\/wp\/v2\/posts\/400\/revisions\/414"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rrbits.com\/epb\/wp-json\/wp\/v2\/media\/413"}],"wp:attachment":[{"href":"https:\/\/rrbits.com\/epb\/wp-json\/wp\/v2\/media?parent=400"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rrbits.com\/epb\/wp-json\/wp\/v2\/categories?post=400"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rrbits.com\/epb\/wp-json\/wp\/v2\/tags?post=400"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}