Pluf Framework

Pluf Framework Git Source Tree


Root/src/Pluf/Image/Thumbnail.php

<?php
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
# ***** BEGIN LICENSE BLOCK *****
# This file is part of Plume Framework, a simple PHP Application Framework.
# Copyright (C) 2001-2007 Loic d'Anterroches and contributors.
#
# Plume Framework is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
#
# Plume Framework is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#
# ***** END LICENSE BLOCK ***** */

/**
 * Generate the thumbnail of an image.
 *
 * Sample usage.
 *
 * $thumbnail = new Pluf_Image_Thumbnail($thumbnail_folder, $source_image);
 * if (!$thumbnail->exists()) {
 *     $thumbnail_filename = $thumbnail->generate();
 * }
 *
 */
class Pluf_Image_Thumbnail
{
    protected $dir = ''; /**< Path to the thumbnail folder. */
    protected $filename = ''; /**< Filename of the last created thumbnail. */
    public $source = ''; /**< Full path to the source file. */
    public $size = array(120, 120); /** Max width and heigth of the thumb. */

    /**
     * Init the thumbnail class. 
     */
    public function __construct($dir, $source='')
    {
        $this->dir = $dir;
        $this->source = $source;
    }

    /**
     * Get the name of a thumbnail from the image name, the image
     * name can include a path this is just a md5() operation.
     * If the height and the width are given, the info is used to
     * generate the name, else not.
     *
     * @param array Optional size.
     * @return string Filename of the thumbnail.
     */
    public function getName($size=null)
    {
        $name = md5($this->source);
        if ($size === null) {
            $size = $this->size;
        }
        return $name.'-'.$size[0].'-'.$size[1].'.png';
    }
 
    /**
     * Get the full path to the thumbnail.
     */
    function getPath()
    {
        return $this->dir.'/'.$this->getName();
    }

    /**
     * Check if the thumbnail exists.
     */
    function exists()
    {
        return file_exists($this->getPath());
    }

    /**
     * Get the size of the last created thumbnail
     * return the same results as the builtin getimagesize PHP function.
     */
    function getSize() 
    {
        if (file_exists($this->getPath())) {
            return getimagesize($this->getPath());
        } else {
            return false;
        }
    }

    /**
     * Create thumbnail of an image, proportions are kept.
     *
     * @return mixed Filename or false.
     */
    function generate()
    {
        if (!file_exists($this->source)) {
            return false;
        }
    
        if (($size = @getimagesize($this->source)) === false) {
            return false;
        }
        list($w, $h) = $this->size;
        $type = $size[2];
        $H = $size[1];
        $W = $size[0];
    
        if ($type == '1') {
            $function = 'imagecreatefromgif';
        } elseif ($type == '2') {
            $function = 'imagecreatefromjpeg';
        } elseif ($type == '3') {
            $function = 'imagecreatefrompng';
        } else {
            return false;
        }
        if (!function_exists($function)) {
            return false;
        }
        if (($img = @$function($this->source)) == false) {
            return false;
        }
        // get the zoom factors and the thumbnail height and width
        $rB = $H/$W;
        $rS = $h/$w;
        if (($H > $h) && ($W > $w)) {
            if ($rB > $rS) {
                $height = $h;
                $width  = $height/$rB;
            } else {
                $width = $w;
                $height = $width*$rB; 
            }
        } elseif ($H > $h) {
            $height = $h;
            $width  = $height/$rB;
        } elseif ($W > $w) {
            $width = $w;
            $height = $width*$rB; 
        } else {
            $height = $H;
            $width  = $W;
        } 
        $zx = $W/$width;
        $zy = $H/$height;

        if (Pluf_Image_Thumbnail::gd_version() >= 2) {
            if (($img2=imagecreatetruecolor(round($width),round($height)))===false) {
                return false;
            }
        } else {
            if (($img2=ImageCreate(round($width),round($height)))===false) {
                return false;
            }   
        }
        $this->resampleBicubic($img2,$img,0,0,0,0,$width,$height,$zx,$zy);
        if (@imagepng($img2,$this->getPath(),9) === false) {
            return false;
        }
        imagedestroy($img2);
        if (@file_exists($this->getPath())) {
            return $this->getPath();
        } else {
            return false;
        }
    }
    
    /**
     * Get the current GD version. Need the output buffering functions.
     */
    public static function gd_version() 
    {
        static $gd_version_number = null;
        if ($gd_version_number === null) {
            // Use output buffering to get results from phpinfo()
            // without disturbing the page we're in.  Output
            // buffering is "stackable" so we don't even have to
            // worry about previous or encompassing buffering.
            ob_start();
            phpinfo(8);
            $module_info = ob_get_contents();
            ob_end_clean();
            if (preg_match("/\bgd\s+version\b[^\d\n\r]+?([\d\.]+)/i",
                           $module_info,$matches)) {
                $gd_version_number = $matches[1];
            } else {
                $gd_version_number = '0';
            }
        }
        return $gd_version_number;

    }

    /* ========================================================================
     *   Private functions, should not be called from outside of the class.
     * ========================================================================
     */

    /**
     * Resample the image 
     * http://www.php.net/manual/en/function.imagecopyresized.php
     */
    protected function resampleBicubic(&$dst, &$src, $dstx, $dsty, $srcx, 
                                       $srcy, $w, $h, $zoomX, $zoomY='')
    {
        if (!$zoomY) {
            $zoomY = $zoomX;
        }
        $palsize = ImageColorsTotal($src);
        for ($i = 0; $i<$palsize; $i++) {
            $colors = ImageColorsForIndex($src, $i);
            ImageColorAllocate($dst, $colors['red'], $colors['green'], 
                               $colors['blue']);
        }
        $zoomX2 = (int)($zoomX/2);
        $zoomY2 = (int)($zoomY/2);
        $dstX = imagesx($dst);
        $dstY = imagesy($dst);
        $srcX = imagesx($src);
        $srcY = imagesy($src);
    
        for ($j=0; $j<($h-$dsty); $j++) {
            $sY = (int)($j*$zoomY) + $srcy;
            $y13 = $sY+$zoomY2;
            $dY = $j+$dsty;
        
            if (($sY >= $srcY) or ($dY >= $dstY) or ($y13 >= $srcY)) {
                break 1;
            }
            for ($i=0; $i<($w-$dstx); $i++) {
                $sX = (int)($i*$zoomX)+$srcx;
                $x34 = $sX+$zoomX2;
                $dX = $i+$dstx;
                if (($sX >= $srcX) or ($dX >= $dstX) or ($x34 >= $srcX)) {
                    break 1;
                }
                $c1 = ImageColorsForIndex($src, ImageColorAt($src, $sX, $y13));
                $c2 = ImageColorsForIndex($src, ImageColorAt($src, $sX, $sY));
                $c3 = ImageColorsForIndex($src, ImageColorAt($src, $x34, $y13));
                $c4 = ImageColorsForIndex($src, ImageColorAt($src, $x34, $sY));
        
                $r = ($c1['red']+$c2['red']+$c3['red']+$c4['red'])/4;
                $g = ($c1['green']+$c2['green']+$c3['green']+$c4['green'])/4;
                $b = ($c1['blue']+$c2['blue']+$c3['blue']+$c4['blue'])/4;
        
                ImageSetPixel($dst, $dX, $dY, ImageColorClosest($dst, $r, 
                                                                $g, $b));
            }
        }
    }
}

Archive Download this file

Branches

Tags

Number of commits:
Page rendered in 0.06096s using 11 queries.