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 – 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.
<?php
//check out more shit at http://www.halnesbitt.com
ini_set('memory_limit', '100M');
$ch = curl_init();
$timeout = 20;
curl_setopt ($ch, CURLOPT_URL, 'http://news.yahoo.com/rss/');
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$xml = curl_exec($ch);
curl_close($ch);
$rss = simplexml_load_string($xml);
$total = count($rss->channel->item);
$random = rand(0, $total);
$count = 0;
foreach($rss->channel->item as $item) {
if($count == $random) {
$title = $item->title;
$title = preg_replace('/[^(\x20-\x7F)]*/','', $title); //clean the bullshit ascii
$title = substr($title,0,70); //keep the title from spilling over
$desc = strip_tags($item->description);
$desc = preg_replace('/[^(\x20-\x7F)]*/','', $desc); //clean the bullshit ascii
$link = $item->link;
$pubDate = $item->pubDate;
$pubDateFormatted = date('l F d, Y', strtotime($item->pubDate));
//extract the image from the description
preg_match('@@Uims', $item->description, $matches);
$src = $matches[1];
$fullsize = substr($src,strrpos($src, "http://"));
if($fullsize == "") {
$noimage = "Y";
}
//set defaults if the item is empty
if($title == "") {
$title = "Dynamic News Image";
$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
load. You are seeing this message because the random item selected happened to be a blank node.";
$link = "http://www.halnesbitt.com";
$pubDate = date("D, d M Y H:i:s T");
$pubDateFormatted = date('l F d, Y', strtotime($pubDate));
}
}
$count++;
}
if($noimage != "Y") {
//run another curl to get the image
$ch = curl_init();
$timeout = 20;
curl_setopt ($ch, CURLOPT_URL, $fullsize);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
$remoteImage = curl_exec($ch);
curl_close($ch);
$photo = imagecreatefromstring($remoteImage);
$old_width = imagesx($photo);
$old_height = imagesy($photo);
$layout_width = 845;
$layout_height = 560;
$original_aspect = $old_width / $old_height;
$layout_aspect = $layout_width / $layout_height;
if($original_aspect >= $layout_aspect) {
// If image is wider than thumbnail (in aspect ratio sense)
$new_height = $layout_height;
$new_width = $old_width / ($old_height / $layout_height);
} else {
// If the thumbnail is wider than the image
$new_width = $layout_width;
$new_height = $old_height / ($old_width / $layout_width);
}
$src_x = ($new_width - $layout_width) / 2;
$src_y = ($new_height - $layout_height) / 2;
//create the background
$bg_img = imagecreatefromjpeg("../images/newspaper.jpg");
//crop the new photo
$tmp_img = imagecreatetruecolor($layout_width, $layout_height);
imagecopyresampled($tmp_img, $photo, 0, 0, $src_x, $src_y, $new_width, $new_height, $old_width, $old_height);
$photo = $tmp_img;
//run it through some filters to make it look more newspaper-esque
imagefilter($photo, IMG_FILTER_COLORIZE, 84, 80, 66); //84, 80, 66
imagefilter($photo, IMG_FILTER_BRIGHTNESS, -50);
imagefilter($photo, IMG_FILTER_CONTRAST, 10);
imagefilter($photo, IMG_FILTER_GAUSSIAN_BLUR);
//place the new photo on top of the background
imagecopy($bg_img, $photo, 32, -90, 0, 0, $layout_width, $layout_height);
//assign photo data
$photo = $bg_img;
} else {
$photo = imagecreatefromjpeg("../images/newspaper.jpg");
}
// Create some colors
$white = imagecolorallocate($photo, 255, 255, 255);
$black = imagecolorallocate($photo, 0, 0, 0);
$grey = imagecolorallocate($photo, 58, 55, 49);
$blue = imagecolorallocate($photo, 3, 113, 164);
// Replace path by your own font path
$fontR = '../css/fonts/times.ttf';
$fontB = '../css/fonts/timesbd.ttf';
$fontI = '../css/fonts/timesi.ttf';
$fontBI = '../css/fonts/timesbi.ttf';
// Add the title
imagettftext($photo, 20, 0, 32, 535, $grey, $fontB, $title);
// Add the date
imagettftext($photo, 12, 0, 32, 563, $grey, $fontBI, $pubDateFormatted);
//now add the description - need to break them up
$lines = explode('|', wordwrap($desc, 130, '|'));
$y = 590;
foreach ($lines as $line) {
imagettftext($photo, 11, 0, 32, $y, $grey, $fontR, $line);
$y += 23;
}
//add the link
imagettftext($photo, 11, 0, 32, $y, $blue, $fontI, $link);
//resize the image into a thumbnail if parameters are passed
if(isset($_GET['w']) || isset($_GET['h'])) {
//resize the image if it is a thumbnail
$thumb_width = $_GET['w'];
$thumb_height = $_GET['h'];
$old_width = imagesx($photo);
$old_height = imagesy($photo);
//if only one value is given, then scale the other proportionately
if($thumb_width == "") {
$scale = $thumb_height/$old_height;
$thumb_width = round($old_width * $scale);
}
if($thumb_height == "") {
$scale = $thumb_width/$old_width;
$thumb_height = round($old_height * $scale);
}
//defaults and maxs/mins
if($thumb_width > 1500 || $thumb_width < 15) {
$thumb_width = 950;
}
if($thumb_height > 1500 || $thumb_height < 15) {
$thumb_height = 726;
}
$original_aspect = $old_width / $old_height;
$thumb_aspect = $thumb_width / $thumb_height;
if($original_aspect >= $thumb_aspect) {
// If image is wider than thumbnail (in aspect ratio sense)
$new_height = $thumb_height;
$new_width = $old_width / ($old_height / $thumb_height);
} else {
// If the thumbnail is wider than the image
$new_width = $thumb_width;
$new_height = $old_height / ($old_width / $thumb_width);
}
$src_x = ($new_width - $thumb_width) / 2;
$src_y = ($new_height - $thumb_height) / 2;
$tmp_img = imagecreatetruecolor($thumb_width, $thumb_height);
imagecopyresampled($tmp_img, $photo, 0, 0, $src_x, $src_y, $new_width, $new_height, $old_width, $old_height);
$photo = $tmp_img;
}
// Set the headers
header('Content-Type: image/jpeg');
header("Content-Disposition: inline; filename=news-image-by-hal-nesbitt-" . $random . ".jpg");
session_cache_limiter('nocache');
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
// output the image and clean up
imagejpeg($photo);
if($photo) {
imagedestroy($photo);
}
if($bg_img) {
imagedestroy($bg_img);
}
if($tmp_img) {
imagedestroy($tmp_img);
}
?>