Creative Commons

2007-06-10 22:04:56

Better way to work with images

So I found a better (maybe?) way to show the images in your database without making a database call for each. I guess I'll get right into the changes you need to make to my previous post. We'll disregard view.php, since we won't be using it anymore, and focus on index.php.
The first change we need to make is with the database. We need to add two columns, one for the image width and one for the image height. Second, we need to change the way we're storing the image. Instead of using the addslashes function, we'll use base64_encode (this comes in handy later). So, change these lines:
$data = addslashes(file_get_contents($_FILES['userfile']['tmp_name'])); $name = $_FILES['userfile']['name']; $sql = "insert into image (type,data,size,name) values ('"; $sql .= $type . "','" . $data . "','" . $size . "','" . $name . "');";
To this:
$data = base64_encode(file_get_contents($_FILES['userfile']['tmp_name'])); $name = $_FILES['userfile']['name']; list($width, $height, $typefoo, $attr) = getimagesize($_FILES['userfile']['tmp_name']); $sql = "insert into image (type,data,size,name,width,height) values ('" . $type . "','"; $sql = $data . "','" . $size . "','" . $name . "','" . $width . "','" . $height . "');";
Notice that we're storing the image data in base64 and using the getimagesize function to read the width and height. These become important later. Now that we're storing everything in the database we need to, we can move to how the images are displayed.
Previously we were querying the database for ids and then sending one id at a time to a page that would deliver the requested image. That sucked. It would be much quicker to get everything in one database call. So, further down the page, replace this line:
$sql = "select id from image order by id desc";
With this:
$sql = "select type,data,width,height from image order by id desc";
And this line:
echo "<img src=\"view.php?id=" . $row['id'] . "\" /><br />\n";
With this:
echo "<div style=\"width: " . $row['width'] . "px; height: " . $row['height']; echo "px; background: url(data:" . $row['type'] . ";base64," . $row['data'] . ");\" >"; echo "</div><br />\n";
The changes here are pretty major. We're not using an image anymore, since there is no way to get the image data into an image tag without using our previous method. Instead, we're making use of a little known CSS trick. You can throw base64 encoded data right into your style data. So we've made a DIV with the appropriate width and height and made the background of the DIV the image data. This has two implications. First, users can't right click and save the image since, technically, there is no image (enter Matrix pun here). Second, if the user right clicks on the DIV and chooses to view the background image, it will work, but the address bar will contain binary data. Personally, I don't see that as such a big deal, since Firefox handles it quite well. I couldn't care less about Internet Explorer, so someone else can test that out.


Post a comment!