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