Dynamic Image Generator Concept

How To Generate Images Responsively

How does one make images responsive? There are a number of techniques available: each with its own strengths and weaknesses. This method is unique because it ensures that the image served does not need to be scaled in the viewer’s browser. The secret, we will see, lies in PHP’s image editing capabilities.

Capturing the Client’s Screen Resolution

PHP is a server side scripting language and is unable to detect the client’s device size. Fortunately, JavaScript can.[1] Here is what you would need to grab and store the client’s screen resolution:

var width = screen.width;
var height = screen.height;

The next step is to add the client’s screen resolution to the URL and refresh the page.[2] We can use $_SERVER['REQUEST_URI'] (PHP) to capture the domain name. The following code uses PHP’s echo command to combine the PHP and the JavaScript.

echo '
	if (width > 0 && height > 0) {   // Check if width and height have been properly set
		var str = "'.$_SERVER['REQUEST_URI'].'";   // Get domain name using PHP and store in JavaScript variable
		var n = str.indexOf("?");   // Determine position of question mark in the domain name 
		
        /*-- Place Screen Resolution Into Domain Name...  --*/
		if(n==-1){ window.location.href = "'.$_SERVER['REQUEST_URI'].'?width=" + width + "&height=" + height; }   // ...after a "?" if none were found
		else{ window.location.href = "'.$_SERVER['REQUEST_URI'].'&width=" + width + "&height=" + height; }   // ...after a "&" if a "?" was found
	}
';

Let us put that all together and place it inside an if statement so that it is only called when the screen resolution is not found in the domain name. Placing this code at the beginning of the document gives the fastest results.

<?php
if(!isset($_GET['width'])){   // Skip these steps is the screen resolution is already in the domain name
	echo '
		<script type="text/javascript">
		var width = screen.width;
		var height = screen.height;
		if (width > 0 && height > 0) {
			var str = "'.$_SERVER['REQUEST_URI'].'";
			var n = str.indexOf("?");
			if(n==-1){ window.location.href = "'.$_SERVER['REQUEST_URI'].'?width=" + width + "&height=" + height; }
			else{ window.location.href = "'.$_SERVER['REQUEST_URI'].'&width=" + width + "&height=" + height; }
		}
		</script>
	';
}
?>

Using The Client’s Screen Resolution To Size Images

We are now able to use the client’s screen resolution in a PHP function to resize images. We will start by capturing the screen resolution and storing it in PHP variables.

$screen_width=$_GET['width'];
$screen_height=$_GET['height'];

In this first example, we are going to scale and crop an image to fill the client’s screen. The following code will specify which image we want to use. It will also define its dimensions. (Do not bother using the switch statement if you know the image file extension)

$src ='path/to/original/image.extension';

$type = strtolower(substr(strrchr($src,"."),1));   // Define image type by file name extension
  if($type == 'jpeg'){ $type = 'jpg'; }

switch($type){   // Create a duplicate of the original image 
    case 'bmp': $img = imagecreatefromwbmp($src); break;
    case 'gif': $img = imagecreatefromgif($src); break;
    case 'jpg': $img = imagecreatefromjpeg($src); break;
    case 'png': $img = imagecreatefrompng($src); break;
  }	

$image_width = imagesx($img);   // Image width
$image_height = imagesy($img);  // Image height

Things get a bit tricky here. We need to define what portion of the image will be kept when we make our crop. This requires a comparison of the image’s aspect ratio with that of the client’s screen…and some division. (Kids, you really will use use this stuff in the real world)

$original_aspect = $image_width / $image_height;
$screen_aspect = $screen_width / $screen_height;
	
if ( $original_aspect >= $screen_aspect ){
    // If image is wider than screen (in aspect ratio sense)
    $new_height = $screen_height;
    $new_width = $image_width / ($image_height / $screen_height);
}else{
    // If the screen is wider than the image
    $new_width = $screen_width;
    $new_height = $image_height / ($image_width / $screen_width);
}

The next step is to create a black image that is the same size as the client’s screen. Then we take the first image, crop it, and resize it to fit in the blank image we just created.

$img2 = imagecreatetruecolor( $screen_width, $screen_height );
		
// Resize and crop
imagecopyresampled(
    $img2,   // Second Image
    $img,    // Original Image
    0,	     // x-coordinate in Second Image to begin pasting copied image
    0,       // y-coordinate in Second Image to begin pasting copied image
    0,	     // x-coordinate in Original Image to begin copying
    0,       // y-coordinate in Original Image to begin copying
    $new_width, $new_height,
    $image_width, $image_height
);

/*-- Note: coordinates begin in top left corner --*/

Our new image has been created but has not yet been saved to the server. This would be the time to apply any image filters, should you wish to.

// Apply Image Filters (Optional)
imagefilter($img2,IMG_FILTER_GRAYSCALE);
imagefilter($img2,IMG_FILTER_CONTRAST,10);

// Save New Image Onto The Server
imagejpeg($img2,'path/to/location/for/new/image.jpg');

// Free up any memory associated with images we created
imagedestroy($img);
imagedestroy($img2);

Here is the code to crop and resize an image to the dimensions of the client’s screen resolution. I have added an if statement to determine in an identical image has already been created and prevents needless processing time.

<?php
// Check if client's screen resolution has been added to domain name 
if($_GET['width'] > 0){ 

// Make sure that an identical image has not already been created
	if(!file_exists('path/to/new/image_'.$_GET['width'].'x'.$_GET['height'].'.jpg')){
		$src ='path/to/original/image.extension';
		$type = strtolower(substr(strrchr($src,"."),1));
		  if($type == 'jpeg'){ $type = 'jpg'; }
		switch($type){
			case 'bmp': $img = imagecreatefromwbmp($src); break;
			case 'gif': $img = imagecreatefromgif($src); break;
			case 'jpg': $img = imagecreatefromjpeg($src); break;
			case 'png': $img = imagecreatefrompng($src); break;
		  }
		$screen_width=$_GET['width'];
		$screen_height=$_GET['height'];
		$image_width = imagesx($img);
		$image_height = imagesy($img);
		$original_aspect = $image_width / $image_height;
		$screen_aspect = $screen_width / $screen_height;
		if ( $original_aspect >= $screen_aspect ){
		   $new_height = $screen_height;
		   $new_width = $image_width / ($image_height / $screen_height);
		}else{
		   $new_width = $screen_width;
		   $new_height = $image_height / ($image_width / $screen_width);
		}
		$img2 = imagecreatetruecolor( $screen_width, $screen_height );
		imagecopyresampled($img2,$img,0,0,0,0,$new_width,$new_height,$image_width,$image_height);
		imagejpeg($img2,'path/to/location/for/new/image_'.$screen_width.'x'.$screen_height.'.jpg');
		imagedestroy($img);
		imagedestroy($img2);
	}

// Create a div that is the size of the browser viewport with the image sized for the device
	echo '<div style="background:url(path/to/new/image_'.$_GET['width'].'x'.$_GET['height'].'.jpg); background-size:cover;" width="100%" height="100vh"></div>';
}
?>

Using Base64 Encoding

The example that I just showed you saves an image to the server. This works fine for a background image since one only has to store derivatives of a single image. We are going to want to try something different for site wide implementation. One option is to convert the images into chunks of code and insert them directly into the HTML file.[3]

ob_start();  // Start buffering output image
imagejpeg($img2);   // No destination folder has been specified
$jpeg = ob_get_clean();   // Gets the output image and stop buffering
$uri = "data:image/jpeg;base64," . base64_encode($jpeg);   // Store encoded image in a new variable

Here is an example of that in practice.

function ImageResize($image,$alt,$title){
	if(0 < $_GET['width']){
		$img = imagecreatefromjpeg('includes/img/'.$image);
		$image_width = imagesx($img);
		$image_height = imagesy($img);
        
        // Define output image width
        $column_width = '702';   // max-width of column
		if($_GET['width'] < $column_width){
        	$new_width = $_GET['width']; 
        }else{
        	$new_width = $column_width;
        }
        
        // Define output image height
		$new_height = ($image_height / $image_width) * $new_width;
		
        // Create output image 
        $img2 = imagecreatetruecolor($new_width,$new_height);
		imagecopyresampled($img2,$img,0,0,0,0,$new_width,$new_height,$image_width,$image_height);
		
        // Buffer and encode image
        ob_start();
		imagejpeg($img2,NULL);
		$jpeg = ob_get_clean();
		$uri = "data:image/jpeg;base64," . base64_encode($jpeg);
        
        // Free up memory
        imagedestroy($img);
		imagedestroy($img2);
        
        // Display Image 
		echo '<img src="'.$uri.'" title="'.$title.'" alt="'.$alt.'" />';
	}
}

echo '<div id="column" style="width:100%; max-width:702px;";>';
ImageResize(
	'path/to/original/image.jpg',
    'value for the alt altribute',
    'value for the title altribute'
);
echo '<div>';

Foototes

  1. The client needs to be running JavaScript for the images to be created. Perhaps CSS media queries could be used as a fallback. It might make sense to use PHP’s $_SERVER['HTTP_USER_AGENT'] to approximate the device’s dimensions.
  2. Attaching the dimensions to the URL is an easy way to pass information from JavaScript to PHP – but it is unsightly. Try passing the information through PHP’s POST method or set some cookies for the scripts to retrieve…and let me know how it turns out.
  3. Creating a new image takes time. Saving the image to the server allows us to skip this step on subsequent loads. Using base64 encoding does not offer this advantage but it does save the end user money by serving smaller files (unless they have unlimited data plans). A third option is to save the file to the server but only keep it there for a set amount of time.

Testimonial From A Happy Customer

I had the pleasure of working with David Stewart and his team on a project to develop a brand identity, including logo, icons, and website for a mobile ecotourism application called ExploreEcoNB for Android, Apple, and Windows phones. This project brought together 10 provincial partners such as us (the Nature Trust of New Brunswick), Parks Canada, New Brunswick Provincial Parks, Nature Conservancy of Canada, and more. With so many partners involved, it can often be difficult to come to a consensus, but the quality work made it very easy for all to agree on the brand identity for the app.

As project manager for his team, David maintained good communication throughout the entire process and implemented all feedback provided in a timely manner. He even ensured that I was trained to be able to update the ExploreEcoNB website before our contract was over. He is a talented young professional who can help bring clarity to your graphic or web design project.

kid with camera

Bigstock vs. GraphicStock vs. Dollar Photo Club: A Stock Image Provider Comparion

I started acquiring stock images for the Baxter Foods Facebook page. I was used to sourcing public domain images from Pixabay, Free Images and Wikipedia Commons or creative commons images from Flickr, and raumrot. These are great resources but they are limited: too limited for what I am doing with Baxter.

I do not remember when I first learned about Dollar Photo Club but I do know that it impressed me as being a simple to use and affordable. I payed the $10 fee subscription fee and have been very satisfied with this service.

I had been using Dollar Photo Club for a month when I saw an advertisement for Bigstock in the Webdesigner Depot newsletter. The ad was offering five free downloads a day for 14 days. I signed up for a trial account and started downloading. It was like an early Christmas.

A short time later, I saw another ad but this time it was for GraphicStock. It offered unlimited downloads for seven days. My Bigstock trial had not ended yet but I signed up anyway. Using the three stock image providers simultaneously allowed me to pit them against each other.

How They Stock Up

I was very impressed with the quality and quantity of Bigstock’s collection. I was much less impressed with their payment models, especially the so-many-images-per-day one. It was fun at first but it soon became a burden. It was a huge time suck. I felt that I had to visit the site every day to download the images. I did not need five images every day and trying to foresee what I would need was an unnecessary stress. The cost-per-image is $0.16 to $0.53 depending on the plan. This is much less than on Dollar Photo Club but only if the correct number of downloads are made each day. Bigstock does offer a credit packs. In this model, one pays for so many credits which can be used within one year of purchase. They advertise that the price-per-image using credits is $0.99 to $3.50 depending on the size of the pack. This is very deceptive. This is the price range for a small image. A full sized image or vector costs six times as much.

It is hardly worth talking about the price of images on GraphicStock. They are potentially very cheep in that GraphicStock offers unlimited downloads for $49 a month or $588 a year. A quick look at its collection will tell you why I think this is a moot point because Bigstock and Dollar Photo Club have much better collections. The interesting thing about this site is that it offers a bigger variety of file formats: JPG, PNG, PDF, EPS, and even PSD.

Dollar Photo Club is the company I started with and the one I am sticking to. It has a nice collection and is extremely simple to manage. I do not have to ask myself what size of image I need or what its cost will be. I never have to concern myself with how many images I have downloaded or if my credits have expired. My big frustration with Bigstock is that its downloads and credits are time limited. If one downloads four out of five images, he or she will loose the fifth image. Its credits expire too but they are overpriced anyway.

My Recommendation

Dollar Photo Club makes billing simple. It is a subscription based payment plan. It costs $10 a month or $99 a year. These subscriptions pay for 10 and 99 images respectively. Think that you will need more than that? No problem. Additional image credits can be purchased at $1 a credit. Each image costs one credit which is why it’s called Dollar Photo Club. Additional credits can be purchased in any quantity under 5,000. I like how simple it is. It is easy to explain to my customers and to itemize on invoices. The collection quality and the ease of use make it my recommendation of the three.

If you are going to start an account with a stock image provider or are considering switching companies, I recommend that you take a look at Dollar Photo Club. I would appreciate it if you would use this link to do so. I signed up for the Dollar Photo Club Ambassador Program, which means that I will get $10 for every referral who decides to subscribe. (Hey, if I’m going to recommend something I might as well get paid for it)

What has your experience been with stock image providers?

Instructor Profile Pics

More Praise From School Days

David was a great student to have in the class. He was always punctual and had his work done on time. He also challenged us as teachers to go beyond what we had in the lesson plan, particularly in the web classes, which he excelled at.

David is a hard worker and would be a great asset to any company that employs him.

David was an excellent student of mine, he acquired and demonstrated sound technical and creative skills while studying at the College of Craft and Design, as well David is easy to work with, often helping others.

self portrait collage

Highly Recommended by Design Instructor

I have known David for many years and I have had the pleasure of being his instructor for three years, first at the University of New Brunswick and then at the New Brunswick College of Craft and Design. I taught him Media Design at the University of New Brunswick and several courses in the Integrated Media studio program at the New Brunswick College of Craft and Design, including Web Site Design, and Content and Interactivity.

Throughout his studies, David has shown an extremely professional attitude in his dealings with instructors, other students and clients. He has an easy-going, affable personality that allows him to work very well as part of a team. He has great attention to detail and dedication to whatever task is at hand.

David is keenly interested in design and recognizes the need a contemporary designer has to stay abreast of advances in technology. He is very knowledgeable particularly in the area of emerging web technologies. Additionally, David has always brought very creative, original solutions to design problems.

I highly recommend David and I feel he would be an asset to any employer.

Drew Kennickell

Check out Drew’s website at www.drewkennickell.com. You can also find him on LinkedIn. (The featured image was created from two of His self portraits, which can be seen here and here)

data concept image

Dealing with Data: A Possible Solution

I just finished watching a webinar titled Solving Your Top Data Challenges. It was put on by SiriusDecisions and Progress. I was not able to catch the whole thing but I will share what I took away from the portion I watched.

I learned that data becomes outdated within 36 months. Three years is enough time for most of one’s contacts to have changed their jobs, responsibilities, and or contact information. This does not mean that the data is useless but that it has to be verified and/or updated before it can be trusted. Data that is 12 to 36 months old can be used but the most reliable information is less than one year old. These time frames apply to data quality but also to data engagement. Data can be considered inactive if it is older than 36 months and robust if collected within 12.

The speaker for SiriusDecisions said that often 80% of one’s time is spent accessing and preparing data, and that only 20% is spent on analysis and presentation. It takes a lot of grunt work to produce the information that is needed to make business decisions. This is where a representative from Progress demoed a product called Easyl and showed how it dramatically increases the speed that one can get to the analysis stage. This product pulls data from one’s various storage locations. It takes this data and amalgamates it for easy access. The information updates as the data sources do. Unfortunately, it does not yet have ready-made solutions for pulling in data from social media analytics programs. It was commented that this is on Progress’s short list of things to add to Easyl.

The overall message of the webinar was that data management should be taken seriously. An individual or team should plan, execute, and measure data a management strategy. Each business should ask itself what it needs to learn from the data and work to get that information. Traditional methods may require an IT person to complete the 80% and a business or sales executive to do the 20%. Progress says that Easyl can reduce and possibly remove the need for IT’s involvement in the process.

A number of other products were mentioned in the webinar. Some of these were Google Analytics, Eloqua, Marketo, Qlik, and Tableau.

3 Ways To Use Twitter Ads Without Paying a Cent

Twitter and HubSpot hosted a webinar yesterday afternoon. The attendees, myself included, learned about three advantages to having a Twitter Ads account. I will share these with you now.

slide from webinar

I received emails a while ago that promoted that Twitter Ads accounts. These emails said that users with these accounts get free analytics on their Twitter activity. The catch is that one needs to provide credit card information to create the account. The analytics tool allows one to evaluate and strategize his or her activities on Twitter.

slide from webinar

The second advantage to the Ads account is the ability to create website cards. You have seen them on Facebook. They are auto generated when one puts a hyperlink into a post. They usually feature an image of some kind, the page title, and a little bit of written content. These things are great! They increase the visibility of the post and get better response rates. Now you can have these on Twitter as well – and they are free. They are not auto generated though. One must go into the account and create the website card before it can be shared in a tweet. I have yet to try this but I think the extra work will be worth the effort.

slide from webinar

The third advantage is much like the second one. This time is something called a lead generation card. It is like a website card except that it has an action button. You might want to use a lead generation card to promote a newsletter. You might say something like “subscribe now,” on the button. A user can click this button to perform the action without leaving Twitter. The user is not asked to provide any kind of information. A click is all that is necessary. Twitter provides the information for you using your account details. There are no forms to intimidate. It is almost too easy.

Social media has long been a staple in bootstrap marketing. Twitter Ads accounts allows us to do it more effectively. All you need is a credit card and internet access. Don’t miss out.

**These images are webinar screenshots and are displayed in good will.**

little kid at computer keyboard

9 Rules for Blogging Newbs Who Want Results

What are the rules? It is the first question one asks when introduced to a game. The answer often has a fair bit of strategy thrown in. These extra bits of information are intended to help a person until he or she understands the game and can form new strategies. These nine “rules” were given by Hugh Hewitt in his book Blog. Here are his, “key rules of blogging success and significance:” (Hewitt, 151)

  • Post often
  • Link freely
  • Be generous in praise and attribution
  • Don’t be long-winded too often, if at all (Brevity is the soul of blogging when you are getting started)
  • Paragraphs are your friend
  • Profanity loses audiences
  • Avoid feuds and flame wars
  • At least at the start, skip the comments sections (You end up with the problem of nuts if you are any good)
  • Keep the title [of the blog] short and easy to remember so that it is easy to recall and type into the space at the top of the page

Two of these rules only apply to beginners. For example, long posts tend to be better received than short ones (read more here) but can easily cause burnout. Eliciting feedback from readers can be very beneficial but negative comments could discourage a beginner from continuing.

It might help you to know that the internet and the web are not the same thing. The internet is a global network of computers. The web is a bunch of linked HTML files (webpages) on the internet. Healthy websites are strongly connected to the web. This why Hewitt encourages people to be liberal…with their links.

I hope this has been a help to you. If so, please pass it along to others. Do you have any rules for me?

Blog Book Found In Unlikely Place

I finished Blog by Hugh Hewitt yesterday. I picked it up in a sale at the Lighthouse Christian Resource Center, where I could fill a bag with books for $5. It’s slick jacket caught my attention. Bill Chiaravalle, and Mark Mickel did an excellent job designing it. I was intrigued that a book about blogs would be found in a Christian bookstore. I did not have anything to lose so I through it into the bag. Here is what I found:

Blog chronicles the history of the blogosphere and pushes for its expansion. It argues that we are in the midst of a reformation, a democratization of information, very much like the one caused by the invention of the printing press. Hewitt tells his readers who he believes are the Martin Luthers of our day and warns us to join them or be left behind.

This book shares recent history of American politics and American news agencies to show how they were instrumental in establishing the blogosphere’s influence. In doing this, Hewitt shares his political views freely. (He says that this is important so that the reader can easily discern opinions for what they are) This approach might turn off some readers but it is the kind of writing that was so influential.

Blog was published in 2005. The book remains relevant despite the many changes that have taken place since then. Blog gives a frame of reference in which one can evaluate the current status of the “information revolution.”