{"id":139,"date":"2012-03-13T23:57:14","date_gmt":"2012-03-14T03:57:14","guid":{"rendered":"http:\/\/halnesbitt.com\/blog\/?p=139"},"modified":"2018-09-29T09:37:33","modified_gmt":"2018-09-29T13:37:33","slug":"dynamic-image-merging-wtext-from-rss-feed-via-php","status":"publish","type":"post","link":"https:\/\/halnesbitt.com\/blog\/2012\/03\/13\/dynamic-image-merging-wtext-from-rss-feed-via-php\/","title":{"rendered":"Dynamic Image Merging w\/Text from RSS Feed via PHP"},"content":{"rendered":"<p><!--more--><a target=\"_blank\" href=\"http:\/\/www.halnesbitt.com\/pages\/news-image.php\"><img decoding=\"async\" src=\"\/\/www.halnesbitt.com\/pages\/news-image.php\"  \/><\/a><\/p>\n<p>A good coder is a lazy coder, and I revel in my laziness. Most of my websites feature image slideshows on the front with content that constantly needs to be updated, so I was looking for ways to automate the process. I decided to write a script that would import the content from an RSS feed, but I was still left with the image issue. Then it hit me; why not pull images directly from the feed an dynamically resize them? So I created this proof of concept using the Yahoo! Top News Stories RSS feed &#8211; the script imports the feed > selects a random item from the group > parses the description to get the thumbnail image > parses the URL to determine the full size image > imports the full size image via cURL > applies some filters to make it look newspaper-y > resizes it > applies it to a newspaper background > adds the title and description from the item to the image > outputs the image to the browser, on the fly. You can view the image above to see this; either refresh the page to grab new content or click the image to open in a new window and then refresh the image a few times. Code below.<\/p>\n<pre>\r\n<code>\r\n&lt;?php\r\n\/\/check out more shit at http:\/\/www.halnesbitt.com\r\n\r\nini_set('memory_limit', '100M');\r\n\r\n$ch = curl_init(); \r\n$timeout = 20; \r\ncurl_setopt ($ch, CURLOPT_URL, 'http:\/\/news.yahoo.com\/rss\/'); \r\ncurl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); \r\ncurl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout); \r\n$xml = curl_exec($ch); \r\ncurl_close($ch); \r\n\r\n$rss = simplexml_load_string($xml);\r\n\r\n$total = count($rss->channel->item);\r\n$random = rand(0, $total);\r\n\r\n$count = 0;\r\nforeach($rss->channel->item as $item) {\r\n\tif($count == $random) {\r\n\r\n\t\t$title =  $item->title;\r\n \t\t$title = preg_replace('\/[^(\\x20-\\x7F)]*\/','', $title); \/\/clean the bullshit ascii\r\n\t\t$title = substr($title,0,70); \/\/keep the title from spilling over\r\n\t\t$desc =  strip_tags($item->description);\r\n\t\t$desc = preg_replace('\/[^(\\x20-\\x7F)]*\/','', $desc); \/\/clean the bullshit ascii\r\n\t\t$link = $item->link;\r\n\t\t$pubDate = $item->pubDate;\r\n\t\t$pubDateFormatted = date('l F d, Y', strtotime($item->pubDate));\r\n\r\n\t\t\/\/extract the image from the description\r\n\t\tpreg_match('@<img.+src=\"(.*)\".*>@Uims', $item->description, $matches); \r\n\t\t$src = $matches[1];\r\n\t\t$fullsize = substr($src,strrpos($src, \"http:\/\/\"));\r\n\t\tif($fullsize == \"\") {\r\n\t\t\t$noimage = \"Y\";\r\n\t\t}\r\n\r\n\t\t\/\/set defaults if the item is empty\r\n\t\tif($title == \"\") {\r\n\t\t\t$title = \"Dynamic News Image\";\r\n\t\t\t$desc = \"This script parses an RSS feed and grabs the item and outputs it as an image. It uses detection to find the fullsize image from the thumbnail and will display a random item from the current set on each \r\n\r\nload. You are seeing this message because the random item selected happened to be a blank node.\";\r\n\t\t\t$link = \"http:\/\/www.halnesbitt.com\";\r\n\t\t\t$pubDate = date(\"D, d M Y H:i:s T\");\r\n\t\t\t$pubDateFormatted = date('l F d, Y', strtotime($pubDate));\r\n\t\t}\r\n\r\n\t}\r\n\t$count++;\r\n\t\r\n}\r\n \r\nif($noimage != \"Y\") {\r\n\t\/\/run another curl to get the image\r\n\t$ch = curl_init(); \r\n\t$timeout = 20; \r\n\tcurl_setopt ($ch, CURLOPT_URL, $fullsize); \r\n\tcurl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1); \r\n\tcurl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout); \r\n\t$remoteImage = curl_exec($ch); \r\n\tcurl_close($ch);\r\n\t$photo = imagecreatefromstring($remoteImage);\r\n\r\n\t$old_width = imagesx($photo);\r\n\t$old_height = imagesy($photo);\r\n\r\n\t$layout_width = 845;\r\n\t$layout_height = 560;\r\n\r\n\r\n\t$original_aspect = $old_width \/ $old_height;\r\n\t$layout_aspect = $layout_width \/ $layout_height;\r\n\r\n\tif($original_aspect >= $layout_aspect) {   \r\n\t\/\/ If image is wider than thumbnail (in aspect ratio sense)   \r\n\t\t$new_height = $layout_height;   \r\n\t\t$new_width = $old_width \/ ($old_height \/ $layout_height);\r\n\t} else {   \r\n\t\/\/ If the thumbnail is wider than the image   \r\n\t\t$new_width = $layout_width;   \r\n\t\t$new_height = $old_height \/ ($old_width \/ $layout_width);\r\n\t}\r\n\r\n\t$src_x = ($new_width - $layout_width) \/ 2;\r\n\t$src_y = ($new_height - $layout_height) \/ 2;\r\n\r\n\t\/\/create the background\r\n\t$bg_img = imagecreatefromjpeg(\"..\/images\/newspaper.jpg\");\r\n\r\n\t\/\/crop the new photo\r\n\t$tmp_img = imagecreatetruecolor($layout_width, $layout_height);\r\n\timagecopyresampled($tmp_img, $photo, 0, 0, $src_x, $src_y, $new_width, $new_height, $old_width, $old_height);\r\n\t$photo = $tmp_img;\r\n\r\n\t\/\/run it through some filters to make it look more newspaper-esque\r\n \timagefilter($photo, IMG_FILTER_COLORIZE, 84, 80, 66); \/\/84, 80, 66\r\n\timagefilter($photo, IMG_FILTER_BRIGHTNESS, -50);\r\n\timagefilter($photo, IMG_FILTER_CONTRAST, 10);\r\n\timagefilter($photo, IMG_FILTER_GAUSSIAN_BLUR);\r\n\r\n\r\n\t\/\/place the new photo on top of the background\r\n\timagecopy($bg_img, $photo, 32, -90, 0, 0, $layout_width, $layout_height);\r\n\r\n\t\/\/assign photo data\r\n\t$photo = $bg_img; \r\n\r\n\r\n} else {\r\n\t$photo = imagecreatefromjpeg(\"..\/images\/newspaper.jpg\");\r\n}\r\n\r\n\/\/ Create some colors\r\n$white = imagecolorallocate($photo, 255, 255, 255);\r\n$black = imagecolorallocate($photo, 0, 0, 0);\r\n$grey = imagecolorallocate($photo, 58, 55, 49);\r\n$blue = imagecolorallocate($photo, 3, 113, 164);\r\n\r\n\r\n\/\/ Replace path by your own font path\r\n$fontR = '..\/css\/fonts\/times.ttf';\r\n$fontB = '..\/css\/fonts\/timesbd.ttf';\r\n$fontI = '..\/css\/fonts\/timesi.ttf';\r\n$fontBI = '..\/css\/fonts\/timesbi.ttf';\r\n\r\n\r\n\/\/ Add the title\r\nimagettftext($photo, 20, 0, 32, 535, $grey, $fontB, $title);\r\n\r\n\/\/ Add the date\r\nimagettftext($photo, 12, 0, 32, 563, $grey, $fontBI, $pubDateFormatted);\r\n\r\n\/\/now add the description - need to break them up\r\n$lines = explode('|', wordwrap($desc, 130, '|'));\r\n$y = 590;\r\nforeach ($lines as $line) {\r\n\timagettftext($photo, 11, 0, 32, $y, $grey, $fontR, $line);\r\n\t$y += 23;\r\n}\r\n\r\n\/\/add the link\r\nimagettftext($photo, 11, 0, 32, $y, $blue, $fontI, $link);\r\n\r\n\/\/resize the image into a thumbnail if parameters are passed\r\nif(isset($_GET['w']) || isset($_GET['h'])) {\r\n\r\n\t\/\/resize the image if it is a thumbnail\r\n\t$thumb_width = $_GET['w'];\r\n\t$thumb_height = $_GET['h'];\r\n\t$old_width = imagesx($photo);\r\n\t$old_height = imagesy($photo);\r\n\r\n\t\/\/if only one value is given, then scale the other proportionately\r\n\tif($thumb_width == \"\") {\r\n\t\t$scale = $thumb_height\/$old_height;\r\n\t\t$thumb_width = round($old_width * $scale);\r\n\t}\r\n\r\n\tif($thumb_height == \"\") {\r\n\t\t$scale = $thumb_width\/$old_width;\r\n\t\t$thumb_height = round($old_height * $scale);\r\n\t}\r\n\r\n\t\/\/defaults and maxs\/mins\r\n\tif($thumb_width > 1500 || $thumb_width < 15) {\r\n\t\t$thumb_width = 950;\r\n\t}\r\n\r\n\tif($thumb_height > 1500 || $thumb_height < 15) {\r\n\t\t$thumb_height = 726;\r\n\t}\r\n\r\n\r\n\t$original_aspect = $old_width \/ $old_height;\r\n\t$thumb_aspect = $thumb_width \/ $thumb_height;\r\n\r\n\tif($original_aspect >= $thumb_aspect) {   \r\n\t\/\/ If image is wider than thumbnail (in aspect ratio sense)   \r\n\t\t$new_height = $thumb_height;   \r\n\t\t$new_width = $old_width \/ ($old_height \/ $thumb_height);\r\n\t} else {   \r\n\t\/\/ If the thumbnail is wider than the image   \r\n\t\t$new_width = $thumb_width;   \r\n\t\t$new_height = $old_height \/ ($old_width \/ $thumb_width);\r\n\t}\r\n\r\n\t$src_x = ($new_width - $thumb_width) \/ 2;\r\n\t$src_y = ($new_height - $thumb_height) \/ 2;\r\n\r\n\t$tmp_img = imagecreatetruecolor($thumb_width, $thumb_height);\r\n\timagecopyresampled($tmp_img, $photo, 0, 0, $src_x, $src_y, $new_width, $new_height, $old_width, $old_height);\r\n\t$photo = $tmp_img;\r\n}\r\n \r\n\r\n\/\/ Set the headers\r\nheader('Content-Type: image\/jpeg');\r\nheader(\"Content-Disposition: inline; filename=news-image-by-hal-nesbitt-\" . $random . \".jpg\");\r\nsession_cache_limiter('nocache');\r\nheader(\"Last-Modified: \" . gmdate(\"D, d M Y H:i:s\") . \" GMT\");\r\nheader(\"Cache-Control: no-store, no-cache, must-revalidate\");\r\nheader(\"Cache-Control: post-check=0, pre-check=0\", false);\r\nheader(\"Pragma: no-cache\");\r\n\r\n\/\/ output the image and clean up\r\nimagejpeg($photo);\r\nif($photo) {\r\n\timagedestroy($photo);\r\n}\r\nif($bg_img) {\r\n\timagedestroy($bg_img);\r\n}\r\nif($tmp_img) {\r\n\timagedestroy($tmp_img);\r\n}\r\n\r\n?&gt;\r\n<\/code>\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,1],"tags":[],"class_list":["post-139","post","type-post","status-publish","format-standard","hentry","category-computer-stuff","category-show-all"],"_links":{"self":[{"href":"https:\/\/halnesbitt.com\/blog\/wp-json\/wp\/v2\/posts\/139","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/halnesbitt.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/halnesbitt.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/halnesbitt.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/halnesbitt.com\/blog\/wp-json\/wp\/v2\/comments?post=139"}],"version-history":[{"count":15,"href":"https:\/\/halnesbitt.com\/blog\/wp-json\/wp\/v2\/posts\/139\/revisions"}],"predecessor-version":[{"id":414,"href":"https:\/\/halnesbitt.com\/blog\/wp-json\/wp\/v2\/posts\/139\/revisions\/414"}],"wp:attachment":[{"href":"https:\/\/halnesbitt.com\/blog\/wp-json\/wp\/v2\/media?parent=139"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/halnesbitt.com\/blog\/wp-json\/wp\/v2\/categories?post=139"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/halnesbitt.com\/blog\/wp-json\/wp\/v2\/tags?post=139"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}