Outputting Images as base64 encoded strings

As you know, user uploads shouldn’t be in the public folder of your site, as that poses a security risk. However it also means that you need to make some sort of download controller, and the problem with that is that it’s sending more unnecessary requests than it needs to, and depending how you set your download controller up, it could go through a ton of framework php just to process your image!

So instead of having

<img src="/some/url/" />

I decided to actually output the src directly in the page, rather than have another request sent.

<img src="data:image/jpeg;base64,/9j/4AAQSkZJRABAgMRBAUhMQYEtcEtcEtcEtcEtc">

First up, here’s my image class. I added getHeader() and destroy() methods to it.

<?php
/**
* Utility class for processing images
* 6 Feb 2012
*/
class ESOS_Entity_Image {

    protected $_image;
    protected $_image_type;

    public function load($filename) {

        $image_info = getimagesize($filename);
        $this->_image_type = $image_info[2];
        if( $this->_image_type == IMAGETYPE_JPEG ) {

            $this->_image = imagecreatefromjpeg($filename);
        } elseif( $this->_image_type == IMAGETYPE_GIF ) {

            $this->_image = imagecreatefromgif($filename);
        } elseif( $this->_image_type == IMAGETYPE_PNG ) {

            $this->_image = imagecreatefrompng($filename);
        }
    }

    public function save($filename, $image_type=IMAGETYPE_JPEG, $compression=75, $permissions=null) {

        if( $image_type == IMAGETYPE_JPEG ) {
            imagejpeg($this->_image,$filename,$compression);
        } elseif( $image_type == IMAGETYPE_GIF ) {

            imagegif($this->_image,$filename);
        } elseif( $image_type == IMAGETYPE_PNG ) {

            imagepng($this->_image,$filename);
        }
        if( $permissions != null) {

            chmod($filename,$permissions);
        }
    }

    public function output($image_type=IMAGETYPE_JPEG) {

        if( $image_type == IMAGETYPE_JPEG ) {
            imagejpeg($this->_image);
        } elseif( $image_type == IMAGETYPE_GIF ) {

            imagegif($this->_image);
        } elseif( $image_type == IMAGETYPE_PNG ) {

            imagepng($this->_image);
        }
    }

    public function getWidth() {

        return imagesx($this->_image);
    }

    public function getHeight() {

        return imagesy($this->_image);
    }

    public function resizeToHeight($height) {

        $ratio = $height / $this->getHeight();
        $width = $this->getWidth() * $ratio;
        $this->resize($width,$height);
    }

    public function resizeToWidth($width) {
        $ratio = $width / $this->getWidth();
        $height = $this->getheight() * $ratio;
        $this->resize($width,$height);
    }

    public function scale($scale) {
        $width = $this->getWidth() * $scale/100;
        $height = $this->getheight() * $scale/100;
        $this->resize($width,$height);
    }

    public function resize($width,$height) {
        $new_image = imagecreatetruecolor($width, $height);
        imagecopyresampled($new_image, $this->_image, 0, 0, 0, 0, $width, $height, $this->getWidth(), $this->getHeight());
        $this->_image = $new_image;
    }

    public function getImageType()
    {
        return $this->_image_type;
    }


    

    public function getHeader() {

        if( $this->_image_type == IMAGETYPE_JPEG ) {
            return 'image/jpeg';
        } elseif( $this->_image_type == IMAGETYPE_GIF ) {
            return 'image/gif';
        } elseif( $this->_image_type == IMAGETYPE_PNG ) {
            return 'image/png';
        }
    }


    /** 
     *  Free's up memory
     */
    public function destroy()
    {
        imagedestroy($this->_image);
    }

}

Now for the fun part. In your image helper class:

<?php

class ESOS_View_Helper_OrgImage
{
    public function orgImage(ESOS_Entity_Organisation $org)
    {
        $id = $org->getLogoFileId();
        if($id != null)
        {
            $file_svc = ESOS_Service_Locator::getInstance()->getFileSvc();
            $file = $file_svc->getFile($id);
            $path = $file->getPath().DIRECTORY_SEPARATOR.$file->getFilenameOnDisk();
            $img = new ESOS_Entity_Image();
            $img->load(UPLOAD_PATH.$path);
            $header = $img->getHeader();

            ob_start();
             $img->output();
             $img->destroy();
            $i = ob_get_clean();
            
            return( '<img src="data:'.$header.';base64,' . base64_encode( $i ).'" />');
        }
    }
}

The important part to note is the section after ob_start(). We start output buffering the image, free up the memory, and clear the output buffer, allocating the output to a variable. Finally, we base64 encode the output, and return the image with src set to data:image/jpeg;base64,blahblah_encoded_string.

You now have your image, and have it in the same request! Have fun! I’m going to tweak this class now to set id, classes and styles!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s