Location: PHPKode > projects > Moc10 PHP Library > library/Moc10/Image.php
<?php
/**
 * Moc10 Library
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.TXT.
 * It is also available through the world-wide-web at this URL:
 * http://www.moc10phplibrary.com/LICENSE.TXT
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to hide@address.com so we can send you a copy immediately.
 *
 * @category   Moc10
 * @package    Moc10_Image
 * @author     Nick Sagona, III <hide@address.com>
 * @copyright  Copyright (c) 2009-2011 Moc 10 Media, LLC. (http://www.moc10media.com)
 * @license    http://www.moc10phplibrary.com/LICENSE.TXT     New BSD License
 */

/**
 * Moc10_Image
 *
 * @category   Moc10
 * @package    Moc10_Image
 * @author     Nick Sagona, III <hide@address.com>
 * @copyright  Copyright (c) 2009-2011 Moc 10 Media, LLC. (http://www.moc10media.com)
 * @license    http://www.moc10phplibrary.com/LICENSE.TXT     New BSD License
 * @version    1.9.7
 */

class Moc10_Image extends Moc10_File
{

    /**
     * Image width
     * @var int|string
     */
    public $width;

    /**
     * Image height
     * @var int|string
     */
    public $height;

    /**
     * Image channels
     * @var int|string
     */
    public $channels;

    /**
     * Image quality
     * @var int|string
     */
    protected $_quality;

    /**
     * Array of allowed file types.
     * @var array
     */
    protected $_allowed = array('gif'  => 'image/gif',
                                'jpe'  => 'image/jpeg',
                                'jpg'  => 'image/jpeg',
                                'jpeg' => 'image/jpeg',
                                'png'  => 'image/png');

    /**
     * Language object
     * @var Moc10_Language
     */
    protected $_lang = null;

    /**
     * Constructor
     *
     * Instantiate an image file object based on either a pre-existing image file on disk, or a new image file.
     *
     * @param  string $img
     * @param  boolean $up
     * @param  array $typ
     * @param  int|string $w
     * @param  int|string $h
     * @param  int|string $r
     * @param  int|string $g
     * @param  int|string $b
     * @throws Exception
     * @return void
     */
    public function __construct($img, $up = false, $typ = null, $w = null, $h = null, $r = null, $g = null, $b = null)
    {

        $this->_lang = new Moc10_Language();

        parent::__construct($img, $up, $typ);

        if (file_exists($this->fullpath)) {
            // If image exists, get image info and store in an array.
            $imgSize = getimagesize($img);

            // Set image object properties.
            $this->width = $imgSize[0];
            $this->height = $imgSize[1];

            if (isset($imgSize['channels'])) {
                $this->channels = $imgSize['channels'];
            } else {
                $this->channels = null;
            }

            $this->_quality = null;

        } else {

            // If image does not exists, check to make sure the width and height properties of the new image have been passed.
            if (is_null($w) || is_null($h)) {

                throw new Exception($this->_lang->__('Error: You must define a width and height for a new image object.'));

            } else {

                // Set image object properties.
                $this->width = $w;
                $this->height = $h;
                $this->channels = null;
                $this->_quality = null;

                // Create a new image
                $new = imagecreate($w, $h);
                $color = null;

                // Allocate the background color.
                if (!is_null($r) && !is_null($g) && !is_null($b)) {
                    $color = imagecolorallocate($new, $r, $g, $b);
                } else {
                    $color = imagecolorallocate($new, 0, 0, 0);
                }

                // Set the quality and create a new, blank image file.
                $this->_setQuality(90);
                $this->_createImage($new, $this->fullpath, $this->_quality);

                unset($color);

            }

        }

    }

    /**
     * Resize the image object, allowing for the largest dimension to be scaled to the value of the $px argument.
     * For example, if the value of $px = 200, and the image is 800px X 600px, then the image will be scaled to 200px X 150px.
     * The $q argument is an optional argument for the quality of the image that must range between 0 (lowest) and 100 (highest.)
     * The $to argument is an optional argument to save the altered image to another image file without overwriting the original.
     *
     * @param  int|string $px
     * @param  int|string $q
     * @param  string $to
     * @return void
     */
    public function resize($px, $q = null, $to = null)
    {

        // Determine whether or not the image is landscape or portrait and set the scale, new width and new height accordingly,
        // with the largest dimension being scaled to the value of the $px argument.
        $scale = ($this->width > $this->height) ? ($px / $this->width) : ($px / $this->height);

        $wid = round($this->width * $scale);
        $hgt = round($this->height * $scale);

        if (is_null($to)) {

            // Save the image with the new dimensions.
            if (!is_null($q)) {
                $this->_save($wid, $hgt, $q);
            } else {
                $this->_save($wid, $hgt);
            }

        // Save the image to a new image file with the new dimensions.
        } else {

            // Set the image quality.
            if (!is_null($q)) {
                $this->_setQuality($q);
            } else {
                $this->_setQuality(90);
            }

            $new = imagecreatetruecolor($wid, $hgt);

            // Create a new, blank image file and copy the image over, saving it in it's proper format.
            $image = $this->_createNew();
            imagecopyresampled($new, $image, 0, 0, 0, 0, $wid, $hgt, $this->width, $this->height);
            $this->_createImage($new, $to, $this->_quality);

            clearstatcache();

        }

    }

    /**
     * Scale the image object, allowing for the dimensions to be scaled proportionally to the value of the $scl argument.
     * For example, if the value of $scl = 0.50, and the image is 800px X 600px, then the image will be scaled to 400px X 300px.
     * The $q argument is an optional argument for the quality of the image that must range between 0 (lowest) and 100 (highest.)
     * The $to argument is an optional argument to save the altered image to another image file without overwriting the original.
     *
     * @param  int|string $scl
     * @param  int|string $q
     * @param  string $to
     * @return void
     */
    public function scale($scl, $q = null, $to = null)
    {

        // Determine the new width and height of the image based on the value of the $scl argument.
        $wid = round($this->width * $scl);
        $hgt = round($this->height * $scl);

        if (is_null($to)) {

            // Save the image with the new dimensions.
            if (!is_null($q)) {
                $this->_save($wid, $hgt, $q);
            } else {
                $this->_save($wid, $hgt);
            }

        // Save the image to a new image file with the new dimensions.
        } else {

            // Set the image quality.
            if (!is_null($q)) {
                $this->_setQuality($q);
            } else {
                $this->_setQuality(90);
            }

            $new = imagecreatetruecolor($wid, $hgt);

            // Create a new, blank image file and copy the image over, saving it in it's proper format.
            $image = $this->_createNew();
            imagecopyresampled($new, $image, 0, 0, 0, 0, $wid, $hgt, $this->width, $this->height);
            $this->_createImage($new, $to, $this->_quality);

            clearstatcache();

        }

    }

    /**
     * Crop the image object to a square image whose dimensions are based on the value of the $px argument.
     * The optional $x and $y arguments allow for the adjustment of the crop to select a certain area of the image to be cropped.
     * For example, if the values of $px = 50, $x = 20, $y = 0 are passed, then a 50px X 50px image will be created from the
     * original image, with its origins starting at the (20, 0) x-y coordinates. The $q argument is an optional argument for
     * the quality of the image that must range between 0 (lowest) and 100 (highest.) The $to argument is an optional argument
     * to save the altered image to another image file without overwriting the original.
     *
     * @param  int|string $px
     * @param  int|string $x
     * @param  int|string $y
     * @param  int|string $q
     * @param  string $to
     * @return void
     */
    public function crop($px, $x = 0, $y = 0, $q = null, $to = null)
    {

        // Determine whether or not the image is landscape or portrait and set the scale, new width and new height accordingly,
        // with the smallest dimension being scaled to the value of the $px argument to allow for a complete crop.
        $scale = ($this->width > $this->height) ? ($px / $this->height) : ($px / $this->width);

        $wid = round($this->width * $scale);
        $hgt = round($this->height * $scale);

        if (is_null($to)) {

            // Save the image with the new dimensions.
            if (!is_null($q)) {
                $this->_save($wid, $hgt, $q);
            } else {
                $this->_save($wid, $hgt);
            }

            // Open a new image to the crop dimensions.
            $new = imagecreatetruecolor($px, $px);

            // Set the image quality.
            if (!is_null($q)) {
                $this->_setQuality($q);
            } else {
                $this->_setQuality(90);
            }

            // Create a new, blank image file and copy the image over, saving it in it's proper format.
            $image = $this->_createNew();
            imagecopy($new, $image, 0, 0, $x, $y, $px, $px);
            $this->_createImage($new, $this->fullpath, $this->_quality);

            // Redefine the image object properties with the newly set values.
            clearstatcache();
            $this->width = $px;
            $this->height = $px;
            $this->size = filesize($this->fullpath);

        // Save the image to a new image file with the new dimensions.
        } else {

            // Set the image quality.
            if (!is_null($q)) {
                $this->_setQuality($q);
            } else {
                $this->_setQuality(90);
            }

            $new = imagecreatetruecolor($px, $px);

            // Create a new, blank image file and copy the image over, saving it in it's proper format.
            $image = $this->_createNew();
            imagecopyresampled($new, $image, 0, 0, $x, $y, $wid, $hgt, $this->width, $this->height);
            $this->_createImage($new, $to, $this->_quality);

            clearstatcache();

        }

    }

    /**
     * Create text within the an image object and output it. A true-type font file is required for the font argument. The size,
     * rotation and position can be set by those respective arguments. The RGB color of the text can be set by the respective
     * optional arguments. This is a useful method for creating CAPTCHA images or rendering sensitive information to the user
     * that cannot or should not be rendered by HTML (i.e. email addresses.) The $to argument is an optional argument to save
     * the altered image to another image file without overwriting the original.
     *
     * @param  string $str
     * @param  int|string $size
     * @param  int|string $x
     * @param  int|string $y
     * @param  int|string $rotate
     * @param  string $font
     * @param  int|string $r
     * @param  int|string $g
     * @param  int|string $b
     * @param  string $to
     * @param  int|string $q
     * @return void
     */
    public function text($str, $size, $x, $y, $rotate = null, $font = null, $r = null, $g = null, $b = null, $to = null, $q = null)
    {

        // Set the image and font color.
        $image = $this->_createNew();
        if (!is_null($r) && !is_null($g) && !is_null($b)) {
            $color = imagecolorallocate($image, $r, $g, $b);
        } else {
            $color = imagecolorallocate($image, 0, 0, 0);
        }

        // Write text to the image.
        if (!is_null($font)) {
            imagettftext($image, $size, $rotate, $x, $y, $color, $font, $str);
        } else {
            imagestring($image, $size, $x, $y,  $str, $color);
        }

        // Output the image
        if (is_null($to)) {

            // Begin output of headers.
            header('Content-type: ' . $this->mime);

            if ($this->mime == 'image/gif') {
                // Output the GIF image file.
                imagegif($image);
            } else if ($this->mime == 'image/png') {
                // Output the PNG image file.
                imagepng($image);
            } else if ($this->mime == 'image/jpeg') {
                // Output the JPG image file.
                imagejpeg($image);
            }

            // Destroy the image resource.
            imagedestroy($image);

        // Else, save the image to a new image file.
        } else {

            // Set the image quality.
            if (!is_null($q)) {
                $this->_setQuality($q);
            } else {
                $this->_setQuality(90);
            }

            $this->_createImage($image, $to, $this->_quality);

        }

    }

    /**
     * Convert the image object to the new specified image type.
     *
     * @param  string $type
     * @param  int|string $q
     * @throws Exception
     * @return void
     */
    public function convert($type, $q = null)
    {

        if (!is_null($this->_perm['file']) && ($this->_perm['file'] != 777)) {

            throw new Exception($this->_lang->__('Error: Permission denied.'));

        } else {

            $type = strtolower($type);

            // Check if the requested image type is supported.
            if (!array_key_exists($type, $this->_allowed)) {
                throw new Exception($this->_lang->__('Error: That image type is not supported. Only GIF, JPG and PNG image types are supported.'));
            }

            // Check if the image is already the requested image type.
            if ($this->ext == $type) {
                throw new Exception($this->_lang->__('Error: This image file is already a %1 image file.', strtoupper($type)));
            }

            // Open a new image, maintaining the GIF image's palette and transparency where applicable.
            if ($this->mime == 'image/gif') {

                $image = $this->_createNew();
                imageinterlace($image, 0);

                // Change the type of the image object to the new, requested image type.
                $this->ext = $type;
                $this->mime = $this->_allowed[$this->ext];

                // Set the image quality.
                if (!is_null($q)) {
                    $this->_setQuality($q);
                } else {
                    $this->_setQuality(90);
                }

                // Redefine the image object properties with the new values.
                $this->fullpath = $this->dir . $this->filename . '.' . $this->ext;
                $this->basename = basename($this->fullpath);

                // Create and save the image in it's new, proper format.
                $this->_createImage($image, $this->fullpath, $this->_quality);

            // Else, open a new true color image.
            } else {

                $new = imagecreatetruecolor($this->width, $this->height);

                // Create a new, blank image file and copy the image over.
                $image = $this->_createNew();

                // Change the type of the image object to the new, requested image type.
                $this->ext = $type;
                $this->mime = $this->_allowed[$this->ext];

                // Set the image quality.
                if (!is_null($q)) {
                    $this->_setQuality($q);
                } else {
                    $this->_setQuality(90);
                }

                // Redefine the image object properties with the new values.
                $this->fullpath = $this->dir . $this->filename . '.' . $this->ext;
                $this->basename = basename($this->fullpath);

                // Create and save the image in it's new, proper format.
                imagecopyresampled($new, $image, 0, 0, 0, 0, $this->width, $this->height, $this->width, $this->height);
                $this->_createImage($new, $this->fullpath, $this->_quality);

            }

            clearstatcache();
            $this->size = filesize($this->fullpath);
            chmod($this->fullpath, 0777);

        }

    }

    /**
     * Return the number of colors in the palette of indexed images. Returns 0 for true color images.
     *
     * @return int
     */
    public function colorTotal()
    {

        // Set the image and get the total number of colors.
        $image = $this->_createNew();
        $colors = imagecolorstotal($image);

        // Destroy the image resource.
        imagedestroy($image);

        return $colors;

    }

    /**
     * Return all of the colors in the palette in an array format, omitting any repeats. It is strongly advised that this method only be used
     * for smaller image files, preferably with small palettes, as any large images with many colors will cause this method to run slowly.
     * Default format of the values in the returned array is the 6-digit HEX value, but if 'RGB' is passed, then the format of the values
     * in the returned array will be 'R,G,B', i.e. '235,123,12'.
     *
     * @param  string $format
     * @return array
     */
    public function getColors($format = 'HEX')
    {

        // Initialize the colors array and the image resource.
        $colors = array();
        $image = $this->_createNew();

        // Loop through each pixel of the image, recording the color result in the color array.
        for ($h = 0; $h < $this->height; $h++) {

            for ($w = 0; $w < $this->width; $w++) {

                // Get the color index at the pixel location, translating into human readable form.
                $color_index = imagecolorat($image, $w, $h);
                $color_trans = imagecolorsforindex($image, $color_index);

                // Convert to the proper HEX or RGB format.
                if ($format == 'HEX') {
                    $rgb = sprintf('%02s', dechex($color_trans['red'])) . sprintf('%02s', dechex($color_trans['green'])) . sprintf('%02s', dechex($color_trans['blue']));
                } else {
                    $rgb = $color_trans['red'] . "," . $color_trans['green'] . "," . $color_trans['blue'];
                }

                // If the color is not already in the array, add to it.
                if (!in_array($rgb, $colors)) {
                    $colors[] = $rgb;
                }

            }

        }

        // Destroy the image resource.
        imagedestroy($image);

        // Return the colors array.
        return $colors;

    }

    /**
     * Set the image quality based on the type of image.
     *
     * @param  int|string $q
     * @return void
     */
    protected function _setQuality($q)
    {

        if ($this->mime == 'image/png') {
            $this->_quality = 10 - round($q / 10);
        } else if ($this->mime == 'image/jpeg') {
            $this->_quality = round($q);
        } else {
            $this->_quality = null;
        }

    }

    /**
     * Create a blank image based on the current image type of the image object.
     *
     * @return image resource
     */
    protected function _createNew()
    {

        if ($this->mime == 'image/gif') {
            // Create a blank GIF image file.
            $img = imagecreatefromgif($this->fullpath);
        } else if ($this->mime == 'image/png') {
            // Create a blank PNG image file.
            $img = imagecreatefrompng($this->fullpath);
        } else if ($this->mime == 'image/jpeg') {
            // Create a blank JPG image file.
            $img = imagecreatefromjpeg($this->fullpath);
        }

        return $img;

    }

    /**
     * Create and save the new image file in the correct format.
     *
     * @param  string $new
     * @param  string $img
     * @param  int|string $q
     * @return void
     */
    protected function _createImage($new, $img, $q = null)
    {

        if ($this->mime == 'image/gif') {
            // Create and save the new GIF image file.
            imagegif($new, $img);
        } else if ($this->mime == 'image/png') {
            // Create and save the new PNG image file.
            imagepng($new, $img, $q);
        } else if ($this->mime == 'image/jpeg') {
            // Create and save the new JPG image file.
            imagejpeg($new, $img, $q);
        }

    }

    /**
     * Save the image object using with any newly defined properties.
     *
     * @param  int|string $w
     * @param  int|string $h
     * @param  int|string $q
     * @throws Exception
     * @return void
     */
    protected function _save($w, $h, $q = null)
    {

        if (!is_null($this->_perm['file']) && ($this->_perm['file'] != 777)) {

            throw new Exception($this->_lang->__('Error: Permission denied.'));

        } else {

            // Open a new image.
            $new = imagecreatetruecolor($w, $h);

            // Set the image quality.
            if (!is_null($q)) {
                $this->_setQuality($q);
            } else {
                $this->_setQuality(90);
            }

            // Create a new, blank image file and copy the image over, saving it in it's proper format.
            $image = $this->_createNew();
            imagecopyresampled($new, $image, 0, 0, 0, 0, $w, $h, $this->width, $this->height);
            $this->_createImage($new, $this->fullpath, $this->_quality);

            // Redefine the image object properties with the newly set values.
            clearstatcache();
            $this->width = $w;
            $this->height = $h;
            $this->size = filesize($this->fullpath);

        }

    }

}
Return current item: Moc10 PHP Library