{"id":3281,"date":"2015-06-23T19:51:05","date_gmt":"2015-06-23T19:51:05","guid":{"rendered":"https:\/\/www.zensations.at\/?p=3281"},"modified":"2023-08-09T00:34:35","modified_gmt":"2023-08-09T00:34:35","slug":"bringing-magick-to-gd","status":"publish","type":"post","link":"https:\/\/www.zensations.at\/en\/blog\/bringing-magick-to-gd\/","title":{"rendered":"Bringing Magick to GD"},"content":{"rendered":"<h2><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">ImageMagick straightens the skew<\/span><\/span><\/h2>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Building a component for a client of our&#8217;s (Take on the Night) for merging some images together to get a kind of cut-out effect, at first I went straight to the known and \u201cbeloved\u201d GD-Library. <\/span><span style=\"vertical-align: inherit;\">About the struggles, that should follow, and why I jumped behind enemy lines (this is where the Magick happens), I&#8217;m going to tell you in a moment&#8217;s time.<\/span><\/span><\/p>\n<h2><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Unpacking the bundle<\/span><\/span><\/h2>\n<p>As the library formerly known as \u201c<a title=\"GIF Draw\" href=\"https:\/\/libgd.github.io\/pages\/faq.html\">GIF Draw<\/a>\u201d is bundled into PHP since version 4.3, I used it out of habit for our client\u2019s project. As I\u2019ve already shown in a\u00a0<a title=\"PI-Day: \u03c0ece of Cake (PI-HP)\" href=\"http:\/\/blog.timhagn.com\/pi-day-%CF%80ece-of-cake-pi-hp\/\">post on my own blog<\/a>\u00a0a few months back, GD is quite easy to grasp and use. Weren\u2019t it for a few flaws in the bundled library, like the following, we certainly would have sticked to it.<\/p>\n<p>For neat simple copying of one image to another I have never run into problems. But for the project at hand the objects to be pasted needed a little rotation. And here the problems began.<\/p>\n<h2>Upping the Set<\/h2>\n<p>Here\u2019s our basic code, up to the point, where we\u2019ll begin turning the screws:<\/p>\n<p><code>\/* Keeping it simple, we bundle all our * object Info into an array *\/ $imageObject = array( 'width' =&gt; 245.50001525879, 'height' =&gt; 92.5, 'zoom' =&gt; 0.5, 'rotation' =&gt; -10, 'left' =&gt; 75, 'top' =&gt; 125 );<\/code><\/p>\n<p>\/\/ Our background file and our object $backgroundFile = &#8216;background.jpg&#8217;; $objectFile = &#8216;object.png&#8217;;<\/p>\n<h2>Let the games begin<\/h2>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">And now the fun part begins, let&#8217;s load our image and process it:<\/span><\/span><\/p>\n<p><code>\/\/ Load the background image from a string \/\/ so we won't have to think about the format $boximage = imagecreatefromstring(file_get_contents($backgroundFile));<\/code><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">\/\/ The image object has larger proportions than \/\/ we wan&#8217;t it to, so we have to scale it down. <\/span><span style=\"vertical-align: inherit;\">$objectWidth = ceil($imageObject[&#8216;width&#8217;] * $imageObject[&#8216;zoom&#8217;]); <\/span><span style=\"vertical-align: inherit;\">$objectHeight = ceil($imageObject[&#8216;height&#8217;] * $imageObject[&#8216;zoom&#8217;]);<\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">\/\/ Now create an objectImage with our \/\/ calculated dimensions and load our object. <\/span><span style=\"vertical-align: inherit;\">$objectImage = imagecreatetruecolor($objectWidth, $objectHeight); <\/span><span style=\"vertical-align: inherit;\">$tempImage = imagecreatefromstring(file_get_contents($objectFile));<\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">\/\/ Copying and resampling our object with \/\/ preserved alpha-channel imagecolortransparent($objectImage, imagecolorallocatealpha($objectImage, 0, 0, 0, 127)); <\/span><span style=\"vertical-align: inherit;\">imagealphablending($objectImage, false); <\/span><span style=\"vertical-align: inherit;\">imagesavealpha($objectImage, true); <\/span><span style=\"vertical-align: inherit;\">imagecopyresampled($objectImage, $tempImage, 0, 0, 0, 0, $objectWidth, $objectHeight, imagesx($tempImage), imagesy($tempImage));<\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Up until now there isn&#8217;t much to worry about &#8211; preserving the PNG&#8217;s alpha-channel might be the most troublesome part, but I think the\u00a0 <\/span><\/span><a title=\"PHP documentation\" href=\"http:\/\/php.net\/manual\/en\/function.imagecolorallocatealpha.php\"><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">PHP documentation, specifically the comments<\/span><\/span><\/a><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\"> \u00a0there, has this covered. <\/span><span style=\"vertical-align: inherit;\">To see our progress till now, let&#8217;s paste the object:<\/span><\/span><\/p>\n<h2><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">The bold and the beautiful<\/span><\/span><\/h2>\n<p><code>imagealphablending($boxImage, true); imagecopy($boxImage, $objectImage, $imageObject['left'], $imageObject['top'], 0, 0, $objectWidth, $objectHeight);<\/code><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">\u2026 and flush our image to the browser:<\/span><\/span><\/p>\n<p><code>\/\/ Flush the image to the browser. header('Content-type: image\/jpeg'); imagejpeg($boximage); imagedestroy($boximage);<\/code><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Try it on your server and you&#8217;ll get something like this \u201cbeauty\u201d:<\/span><\/span><\/p>\n<h2><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Flop-ROD<\/span><\/span><\/h2>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Now here comes the part which &#8220;breaks&#8221; our neat script &#8211; &#8220;Rotation of Death&#8221;:<\/span><\/span><\/p>\n<p><code>$angle = $imageObject['rotation'] % 360; $objectRotated = imagerotate($objectImage, -$angle, imagecolorallocatealpha($objectImage, 0, 0, 0, 127)); imagealphablending($objectRotated, false); imagesavealpha($objectRotated, true);<\/code><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">\/\/ The rotated object has other dimensions \/\/ than the original image so for placing \/\/ it at the correct position, we have \/\/ \u200b\u200bto calculate the difference. <\/span><span style=\"vertical-align: inherit;\">$diffx = (imagesx($objectRotated) &#8211; $objectWidth)\/2; <\/span><span style=\"vertical-align: inherit;\">$diffy = (imagesy($objectRotated) &#8211; $objectHeight)\/2;<\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">\/\/ And copy it to our background. <\/span><span style=\"vertical-align: inherit;\">imagealphablending($boximage, true); <\/span><span style=\"vertical-align: inherit;\">imagecopyresampled($boximage, $objectRotated, $imageObject[&#8216;left&#8217;]-$diffx, $imageObject[&#8216;top&#8217;]-$diffy, 0, 0, imagesx($objectRotated), imagesy($objectRotated), imagesx($objectRotated ), imagesy($objectRotated));<\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">When using this code instead of the simple paste operation, one should think we would get a nicely rotated object and were finished with our little project. <\/span><span style=\"vertical-align: inherit;\">But flush the image to the browser and you are going to get this:<\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\"><img fetchpriority=\"high\" decoding=\"async\" class=\"alignnone size-full wp-image-3284\" src=\"https:\/\/www.zensations.at\/wp-content\/uploads\/2023\/06\/blog_gd-_rotated.jpg\" alt=\"\" width=\"300\" height=\"300\" srcset=\"https:\/\/www.zensations.at\/wp-content\/uploads\/2023\/06\/blog_gd-_rotated.jpg 300w, https:\/\/www.zensations.at\/wp-content\/uploads\/2023\/06\/blog_gd-_rotated-150x150.jpg 150w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">As you can plainly see, GD did us no favor and cropped the rotated object. <\/span><span style=\"vertical-align: inherit;\">Sad, but that&#8217;s how it is. <\/span><span style=\"vertical-align: inherit;\">I researched some other methods and even started writing my own rotate functionality, but getting this to work with nice interpolation would have gone beyond the constraints of the client&#8217;s project.<\/span><\/span><\/p>\n<p><em><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">So\u00a0 <\/span><\/span><a title=\"ImageMagick\" href=\"http:\/\/www.imagemagick.org\/\"><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">ImageMagick<\/span><\/span><\/a><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\"> \u00a0to the rescue!<\/span><\/span><\/em><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Sadly, ImageMagick isn&#8217;t bundled with PHP, so you&#8217;ve got to install it first &#8211; but again, read the\u00a0 <\/span><\/span><a title=\"PHP documentation\" href=\"http:\/\/php.net\/manual\/en\/imagick.setup.php\"><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">comments to the PHP documentation<\/span><\/span><\/a><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\"> , which should get you going soon.<\/span><\/span><\/p>\n<h2><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Ready for the Magick?<\/span><\/span><\/h2>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">We&#8217;re gonna work on the same foundation as before, so I&#8217;ll exclude the basic setup variables and jump straight into loading and resizing our background image.<\/span><\/span><\/p>\n<p><code>imagecreatefromstring<\/code><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">\u00a0becomes:<\/span><\/span><\/p>\n<p><code>\/\/ Load the background image into a \/\/ new ImageMagick object $boxImage = new Imagick($backgroundFile);<\/code><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">And now the fun part: ImageMagick terrifically releases us of having to copy our object image around just for having it resized:<\/span><\/span><\/p>\n<p><code>\/\/ Load the object image with the new \/\/ dimensions applied $objectImage = new Imagick($objectFile); $objectImage-&gt;resizeImage($objectWidth, $objectHeight, Imagick::FILTER_LANCZOS, 1);<\/code><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Easy as that. <\/span><span style=\"vertical-align: inherit;\">And copying an image onto another is just as straightforward:<\/span><\/span><\/p>\n<p><code>$boxImage-&gt;compositeImage($objectImage, imagick::COMPOSITE_DEFAULT, $imageObject['left'], $imageObject['top']);<\/code><\/p>\n<h2><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Grub first, then ethics.<\/span><\/span><\/h2>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Flushing the boxImage to the browser is done with a little more code than as with GD:<\/span><\/span><\/p>\n<p><code>\/\/ Flush the image to the browser header('Content-type: image\/jpeg'); $boxImage-&gt;setImageFormat('jpeg'); $boxImage-&gt;setImageCompressionQuality(100); echo $boxImage-&gt;getImageBlob();<\/code><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">The function\u00a0 <\/span><\/span><code>getImageBlob<\/code><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">\u00a0returns the final image as a string, just as\u00a0 <\/span><\/span><code>imagejpeg<\/code><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">\u00a0does in GD. <\/span><span style=\"vertical-align: inherit;\">With ImageMagick you just have to set the image format beforehand.<\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\"> <img decoding=\"async\" class=\"alignnone size-full wp-image-3286\" src=\"https:\/\/www.zensations.at\/wp-content\/uploads\/2023\/06\/blog_im.jpg\" alt=\"\" width=\"300\" height=\"300\" srcset=\"https:\/\/www.zensations.at\/wp-content\/uploads\/2023\/06\/blog_im.jpg 300w, https:\/\/www.zensations.at\/wp-content\/uploads\/2023\/06\/blog_im-150x150.jpg 150w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">It&#8217;s a wee bit cleaner than with GD, in my humble opinion, but that&#8217;s not the point. <\/span><span style=\"vertical-align: inherit;\">Because when we now add a little rotation\u2026<\/span><\/span><\/p>\n<h2><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Flushing without blushing<\/span><\/span><\/h2>\n<p><code>\/\/ Rotate the Image - as simple as that $objectImage-&gt;rotateImage(new ImagickPixel('#00000000'), $imageObject['rotation']);<\/code><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">\u2026 where\u00a0 <\/span><\/span><code>ImagickPixel<\/code><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">\u00a0creates the alpha channel for our image object. <\/span><span style=\"vertical-align: inherit;\">We&#8217;ll get our final image &#8211; with no more cropped edges:<\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\"><img decoding=\"async\" class=\"alignnone size-full wp-image-3288\" src=\"https:\/\/www.zensations.at\/wp-content\/uploads\/2023\/06\/blog_im_rotated.jpg\" alt=\"\" width=\"300\" height=\"300\" srcset=\"https:\/\/www.zensations.at\/wp-content\/uploads\/2023\/06\/blog_im_rotated.jpg 300w, https:\/\/www.zensations.at\/wp-content\/uploads\/2023\/06\/blog_im_rotated-150x150.jpg 150w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">Working with images in PHP is really nice with GD &#8211; but I think ImageMagick just sugar-coats the process.<\/span><\/span><\/p>\n<p><span style=\"vertical-align: inherit;\"><span style=\"vertical-align: inherit;\">I&#8217;m a convert &#8211; will you be?<\/span><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>ImageMagick straightens the skew Building a component for a client of our&#8217;s (Take on the Night) for merging some images together to get a kind of cut-out effect, at first I went straight to the known and \u201cbeloved\u201d GD-Library. About the struggles, that should follow, and why I jumped behind enemy lines (this is where [&hellip;]<\/p>\n","protected":false},"author":25,"featured_media":3282,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[242],"tags":[278],"class_list":["post-3281","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-en","tag-revolving-resolve-magickaly-g-phpgdmagick"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.zensations.at\/en\/wp-json\/wp\/v2\/posts\/3281","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.zensations.at\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.zensations.at\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.zensations.at\/en\/wp-json\/wp\/v2\/users\/25"}],"replies":[{"embeddable":true,"href":"https:\/\/www.zensations.at\/en\/wp-json\/wp\/v2\/comments?post=3281"}],"version-history":[{"count":2,"href":"https:\/\/www.zensations.at\/en\/wp-json\/wp\/v2\/posts\/3281\/revisions"}],"predecessor-version":[{"id":3291,"href":"https:\/\/www.zensations.at\/en\/wp-json\/wp\/v2\/posts\/3281\/revisions\/3291"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.zensations.at\/en\/wp-json\/wp\/v2\/media\/3282"}],"wp:attachment":[{"href":"https:\/\/www.zensations.at\/en\/wp-json\/wp\/v2\/media?parent=3281"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.zensations.at\/en\/wp-json\/wp\/v2\/categories?post=3281"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.zensations.at\/en\/wp-json\/wp\/v2\/tags?post=3281"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}