Press "Enter" to skip to content

Email inline Images… as a table!

See the Pen ImageTable Example by Jake Bown (@jakebown) on CodePen.

UPDATE: This has now been created as Github project!

Over the past couple of weeks I’ve been doing a lot more email templates for clients that are often quite image heavy due to lack of support for basic functionality like border radius or custom fonts.

Because of this it’s meant a number of these emails contain mostly images which look fine when you’re testing them but when they are loaded inside a client (I’m looking at your Outlook) the whole email looks dreadful because unless you accept the remote content it doesn’t load your beautiful email template that took 3 hours designing.

How is it that in this day and age we can generate 3D animation using vanilla JS but adding images to an email is so painful, do we need to reinvent email clients from the ground up? Surely there must be a way of ensuring a template retains its formatting and look when the end user receives it.

After thinking about this for a few minutes I remembered that in PHP there is a library called GD which allows you to pull individual pixels out of an image and display its colour in RGB. What if I could upload an image, loop through its width and height and output each colour (or pixel) as an individual table column? Well, I tried it out and it seemed to work!

The first thing I did was get a sample image, small so it wouldn’t kill the script, I chose a photo of Mona Lisa at a modest 256×256 pixels.

Mona Lisa thumbnail

Next, I created a simple script to get my sample image and loaded it into GD within a PHP script.

$image = imagecreatefromjpeg("sample.jpg");
$width = imagesx($image);
$height = imagesy($image);

This gave me the width and height of the image which i could use to generate a “canvas” for the table. I then looped through the height and width and used imagecolorat to get each pixel colour and converted it to RGB. I could then echo out a <tr> on each iteration of the height and a <td> for each of the pixels. This is the end script.

<table border="0" style="border-collapse: collapse;">
ini_set('display_errors', 0);
$image = imagecreatefromjpeg("sample.jpg");
$width = imagesx($image);
$height = imagesy($image);

$image = imagerotate($image, 90, 0);

for($x = 0; $x < $width; $x++) {
	echo "<tr>";
    for($y = 0; $y < $height; $y++) {
        // pixel color at (x, y)
        try {
        	$rgb = imagecolorat($image, $x, $y);
        	if(!$rgb) {
	        $r = ($rgb >> 16) & 0xFF;
			$g = ($rgb >> 8) & 0xFF;
			$b = $rgb & 0xFF;

	    	echo "<td style=\"background-color: rgba($r,$g,$b);\"></td>";
        } catch (Exception $e) {
    echo "<tr>";


I kept getting an odd result where the image was rotated 90 degrees so I had to use imagerotate to put it back to the correct rotation.

Now this obviously is very limited in terms of use, the actual table HTML came out at over 13MB where the image itself was a few KB! Maybe this could be useful for monochrome logos that you want to ensure are displayed in an email or for icons? I wouldn’t suggest it for a full sized image!

Be First to Comment

Leave a Reply