== Thumbnail Klasse ==
Alles anzeigen
== Beispiele ==
=== Bild in meheren Größen speichern ===
Alles anzeigen
== Bild "on the fly" anzeigen ==
Den Original Bildnamen könnt ihr zum Beispiel als $_GET Parameter oder mit mod_rewrite Regeln durchleiten. Im Beispiel wird die Vorschau für das Bild "easy-coding.png" erzeugt.
Der dritte Parameter der Methode display kann einen Zeitausdruck wie "3 month" enthalten, dann wird das Bild für drei Monate im Browser Cache des Benutzers gespeichert, ohne dass es erneut angefragt wird und damit Traffickosten verursacht. Allerdings bekommt der Benutzer auf diese Weise auch nicht von Änderungen mit, deswegen sollte der Intervall je nach Anwendung besser bei "1 day" liegen.
== Demo ==
Die Live Demo findet ihr unter demo.easy-coding.de/php/thumbnail/, herunterladen könnt ihr euch den Code dann unter demo.easy-coding.de/php/thumbnail/download.zip
Quellcode
- <?php
- /**
- * Generates a thumbnail of given source file image.
- *
- * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
- */
- class Thumbnail {
- /**
- * path to source file
- *
- * @var string
- */
- protected $sourceFile = '';
- /**
- * maximum image width
- *
- * @var integer
- */
- protected $maxWidth = 100;
- /**
- * maximum image height
- *
- * @var integer
- */
- protected $maxHeight = 100;
- /**
- * true, to show source information in thumbnail
- *
- * @var boolean
- */
- protected $appendSourceInfo = false;
- /**
- * true, to prefer embedded thumbnails
- *
- * @var boolean
- */
- protected $useEmbedded = true;
- /**
- * true, to generate quadratic thumbnails
- *
- * @var boolean
- */
- protected $quadratic = false;
- /**
- * mime type of the thumbnail
- *
- * @var string
- */
- protected $mimeType = '';
- /**
- * name of the source image
- *
- * @var string
- */
- protected $sourceName = '';
- /**
- * width of the source image
- *
- * @var integer
- */
- protected $sourceWidth = 0;
- /**
- * height of the source image
- *
- * @var integer
- */
- protected $sourceHeight = 0;
- /**
- * file size of the source image
- *
- * @var integer
- */
- protected $sourceSize = 0;
- /**
- * height of the source information
- *
- * @var integer
- */
- protected static $sourceInfoLineHeight = 16;
- /**
- * image type of the source image
- *
- * @var integer
- */
- protected $imageType = 0;
- /**
- * Creates a new Thumbnail object.
- *
- * @param string $sourceFile
- */
- public function __construct($sourceFile) {
- $this->sourceFile = $sourceFile;
- }
- /**
- * setup dimenstions
- *
- * @param boolean $appendSourceInfo
- */
- public function setup($appendSourceInfo = false, $sourceName = null, $useEmbedded = true, $quadratic = false) {
- $this->appendSourceInfo = $appendSourceInfo;
- $this->useEmbedded = $useEmbedded;
- $this->quadratic = $quadratic;
- if ($this->appendSourceInfo) {
- // get source info
- if ($sourceName != null) $this->sourceName = $sourceName;
- else $this->sourceName = basename($this->sourceFile);
- list($this->sourceWidth, $this->sourceHeight, $type) = @getImageSize($this->sourceFile);
- $this->sourceSize = @filesize($sourceFile);
- }
- }
- /**
- * Creates a thumbnail picture (jpg/png) of a big image
- *
- * @param boolean $rescale
- * @return string thumbnail
- */
- protected function makeThumbnail($rescale = false) {
- list($width, $height, $this->imageType) = @getImageSize($this->sourceFile);
- // check image size
- if ($this->checkSize($width, $height, $rescale)) {
- return false;
- }
- // try to extract the embedded thumbnail first (faster)
- $thumbnail = false;
- if (!$rescale && $this->useEmbedded) {
- $thumbnail = $this->extractEmbeddedThumbnail();
- }
- if (!$thumbnail) {
- // calculate uncompressed filesize
- // and cancel to avoid a memory_limit error
- $memoryLimit = ini_get('memory_limit');
- if ($memoryLimit != '') {
- $memoryLimit = substr($memoryLimit, 0, -1) * 1024 * 1024;
- $fileSize = $width * $height * ($this->imageType == 3 ? 4 : 3);
- if (($fileSize * 2.1) + memory_get_usage() > ($memoryLimit)) {
- return false;
- }
- }
- // calculate new picture size
- $x = $y = 0;
- if ($this->quadratic) {
- $newWidth = $newHeight = $this->maxWidth;
- if ($this->appendSourceInfo) $newHeight -= self::$sourceInfoLineHeight * 2;
- if ($width > $height) {
- $x = ceil(($width - $height) / 2);
- $width = $height;
- }
- else {
- $y = ceil(($height - $width) / 2);
- $height = $width;
- }
- }
- else {
- $maxHeight = $this->maxHeight;
- if ($this->appendSourceInfo) $maxHeight -= self::$sourceInfoLineHeight * 2;
- if ($this->maxWidth / $width < $maxHeight / $height) {
- $newWidth = $this->maxWidth;
- $newHeight = round($height * ($newWidth / $width));
- }
- else {
- $newHeight = $maxHeight;
- $newWidth = round($width * ($newHeight / $height));
- }
- }
- // resize image
- $imageResource = false;
- // jpeg image
- if ($this->imageType == 2 && function_exists('imagecreatefromjpeg')) {
- $imageResource = @imageCreateFromJPEG($this->sourceFile);
- }
- // gif image
- if ($this->imageType == 1 && function_exists('imagecreatefromgif')) {
- $imageResource = @imageCreateFromGIF($this->sourceFile);
- }
- // png image
- if ($this->imageType == 3 && function_exists('imagecreatefrompng')) {
- $imageResource = @imageCreateFromPNG($this->sourceFile);
- }
- // could not create image
- if (!$imageResource) {
- return false;
- }
- // resize image
- if (function_exists('imageCreateTrueColor') && function_exists('imageCopyResampled')) {
- $imageNew = @imageCreateTrueColor($newWidth, $newHeight);
- imageAlphaBlending($imageNew, false);
- @imageCopyResampled($imageNew, $imageResource, 0, 0, $x, $y, $newWidth, $newHeight, $width, $height);
- imageSaveAlpha($imageNew, true);
- }
- else if (function_exists('imageCreate') && function_exists('imageCopyResized')) {
- $imageNew = @imageCreate($newWidth, $newHeight);
- imageAlphaBlending($imageNew, false);
- @imageCopyResized($imageNew, $imageResource, 0, 0, $x, $y, $newWidth, $newHeight, $width, $height);
- imageSaveAlpha($imageNew, true);
- }
- else return false;
- // create thumbnail
- ob_start();
- if ($this->imageType == 1 && function_exists('imageGIF')) {
- @imageGIF($imageNew);
- $this->mimeType = 'image/gif';
- }
- else if (($this->imageType == 1 || $this->imageType == 3) && function_exists('imagePNG')) {
- @imagePNG($imageNew);
- $this->mimeType = 'image/png';
- }
- else if (function_exists('imageJPEG')) {
- @imageJPEG($imageNew, '', 90);
- $this->mimeType = 'image/jpeg';
- }
- else {
- return false;
- }
- @imageDestroy($imageNew);
- $thumbnail = ob_get_contents();
- ob_end_clean();
- }
- if ($thumbnail && $this->appendSourceInfo && !$rescale) {
- $thumbnail = $this->appendSourceInfo($thumbnail);
- }
- return $thumbnail;
- }
- /**
- * Appends information about the source image to the thumbnail.
- *
- * @param string $thumbnail
- * @return string
- */
- protected function appendSourceInfo($thumbnail) {
- if (!function_exists('imageCreateFromString') || !function_exists('imageCreateTrueColor')) {
- return $thumbnail;
- }
- $imageSrc = imageCreateFromString($thumbnail);
- // get image size
- $width = imageSX($imageSrc);
- $height = imageSY($imageSrc);
- // increase height
- $heightDst = $height + self::$sourceInfoLineHeight * 2;
- // create new image
- $imageDst = imageCreateTrueColor($width, $heightDst);
- imageAlphaBlending($imageDst, false);
- // set background color
- $background = imageColorAllocate($imageDst, 102, 102, 102);
- imageFill($imageDst, 0, 0, $background);
- // copy image
- imageCopy($imageDst, $imageSrc, 0, 0, 0, 0, $width, $height);
- imageSaveAlpha($imageDst, true);
- // get font size
- $font = 2;
- $fontWidth = imageFontWidth($font);
- $fontHeight = imageFontHeight($font);
- $fontColor = imageColorAllocate($imageDst, 255, 255, 255);
- // write source info
- if($maxWidth) $this->maxWidth = $maxWidth;
- if($maxHeight) $this->maxHeight = $maxHeight;
- $line1 = $this->sourceName;
- // imageString supports only ISO-8859-1 encoded strings
- // if (CHARSET != 'ISO-8859-1') {
- // $line1 = StringUtil::convertEncoding(CHARSET, 'ISO-8859-1', $line1);
- // }
- // truncate text if necessary
- $maxChars = floor($width / $fontWidth);
- if (strlen($line1) > $maxChars) {
- $line1 = $this->truncateSourceName($line1, $maxChars);
- }
- $line2 = $this->sourceWidth.'x'.$this->sourceHeight;
- // write line 1
- // calculate text position
- $textX = 0;
- $textY = 0;
- if ($fontHeight < self::$sourceInfoLineHeight) {
- $textY = intval(round((self::$sourceInfoLineHeight - $fontHeight) / 2));
- }
- if (strlen($line1) * $fontWidth < $width) {
- $textX = intval(round(($width - strlen($line1) * $fontWidth) / 2));
- }
- imageString($imageDst, $font, $textX, $height + $textY, $line1, $fontColor);
- // write line 2
- // calculate text position
- $textX = 0;
- $textY = 0;
- if ($fontHeight < self::$sourceInfoLineHeight) {
- $textY = self::$sourceInfoLineHeight + intval(round((self::$sourceInfoLineHeight - $fontHeight) / 2));
- }
- if (strlen($line2) * $fontWidth < $width) {
- $textX = intval(round(($width - strlen($line2) * $fontWidth) / 2));
- }
- imageString($imageDst, $font, $textX, $height + $textY, $line2, $fontColor);
- // output image
- ob_start();
- if ($this->imageType == 1 && function_exists('imageGIF')) {
- @imageGIF($imageDst);
- $this->mimeType = 'image/gif';
- }
- else if (($this->imageType == 1 || $this->imageType == 3) && function_exists('imagePNG')) {
- @imagePNG($imageDst);
- $this->mimeType = 'image/png';
- }
- else if (function_exists('imageJPEG')) {
- @imageJPEG($imageDst, '', 90);
- $this->mimeType = 'image/jpeg';
- }
- else {
- return false;
- }
- @imageDestroy($imageDst);
- $thumbnail = ob_get_contents();
- ob_end_clean();
- return $thumbnail;
- }
- /**
- * Extracts the embedded thumbnail picture of a jpeg or tiff image
- *
- * @return string thumbnail
- */
- protected function extractEmbeddedThumbnail() {
- if (!function_exists('exif_thumbnail')) {
- return false;
- }
- $width = $height = $type = 0;
- $thumbnail = @exif_thumbnail($this->sourceFile, $width, $height, $type);
- if ($thumbnail && $type && $width && $height) {
- // resize the extracted thumbnail again if necessary
- // (normally the thumbnail size is set to 160px
- // which is recommended in EXIF >2.1 and DCF)
- $this->mimeType = image_type_to_mime_type($type);
- if (!$this->checkSize($width, $height) && function_exists('sys_get_temp_dir')) {
- // get temporary file name
- $this->sourceFile = tempnam(sys_get_temp_dir(), 'Tux');
- // create tmp file
- $fh = fopen($this->sourceFile, "w");
- fwrite($fh, $thumbnail);
- fclose($fh);
- unset($thumbnail, $tmpFile);
- // resize tmp file again
- return $this->makeThumbnail(true);
- }
- return $thumbnail;
- }
- return false;
- }
- /**
- * Checks the size of an image.
- */
- protected function checkSize($width, $height, $rescale = true) {
- $maxHeight = $this->maxHeight;
- if ($this->appendSourceInfo && $rescale) {
- $maxHeight -= self::$sourceInfoLineHeight * 2;
- }
- if ($width > $this->maxWidth || $height > $maxHeight) {
- return false;
- }
- return true;
- }
- /**
- * Returns the mime type of the generated thumbnail.
- *
- * @return string
- */
- public function getMimeType() {
- return $this->mimeType;
- }
- /**
- * Truncates the given file name to needed length.
- *
- * @param string $name
- * @param string $maxChars
- * @return string
- */
- protected static function truncateSourceName($name, $maxChars) {
- $extension = '';
- $lastPosition = strrpos($name, '.');
- if ($lastPosition !== null) {
- $extension = substr($name, $lastPosition);
- $name = substr($name, 0, $lastPosition);
- $maxChars -= strlen($extension);
- }
- return substr($name, 0, $maxChars - 3) . '...' . $extension;
- }
- /**
- *
- * @return boolean
- */
- public function save($targetFile, $maxWidth = 0, $maxHeight = 0) {
- $recover = array();
- if($maxWidth) {
- $recover['maxWidth'] = $this->maxWidth;
- $this->maxWidth = $maxWidth;
- }
- if($maxHeight) {
- $recover['maxHeight'] = $this->maxHeight;
- $this->maxHeight = $maxHeight;
- }
- // get thumbnail
- try {
- $success = true;
- if (($thumbnailData = $this->makeThumbnail())) {
- // save thumbnail
- $fh = fopen($targetFile, 'w');
- fwrite($fh, $thumbnailData);
- unset($thumbnailData);
- fclose($fh);
- }
- }
- catch (Exception $e) {
- $success = false;
- }
- foreach($recover as $key => $val) {
- $this->$key = $val;
- }
- return $success;
- }
- protected static function sendLastModified($timestamp) {
- // Getting headers sent by the client.
- $headers = apache_request_headers();
- // Checking if the client is validating his cache and if it is current.
- if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) >= $timestamp)) {
- // this timestamp can also be used to identify the user ;) see
- // Client's cache IS current, so we just respond '304 Not Modified'.
- header('Last-Modified: '.gmdate('D, d M Y H:i:s', $timestamp).' GMT', true, 304);
- exit;
- } else {
- // Image not cached or cache outdated, we respond '200 OK' and output the image.
- header('Last-Modified: '.gmdate('D, d M Y H:i:s', $timestamp).' GMT', true, 200);
- }
- }
- /**
- * send header and content for the picture
- */
- public function display($maxWidth = 100, $maxHeight = 100, $age = '3 MONTH') {
- $recover = array();
- if($maxWidth) {
- $recover['maxWidth'] = $this->maxWidth;
- $this->maxWidth = $maxWidth;
- }
- if($maxHeight) {
- $recover['maxHeight'] = $this->maxHeight;
- $this->maxHeight = $maxHeight;
- }
- $filemtime = @filemtime($this->sourceFile);
- $thumbnailData = $this->makeThumbnail();
- $size = strlen($thumbnailData);
- self::sendLastModified($filemtime);
- header('Accept-Ranges: bytes');
- header('Content-Length: '.$size);
- header('Content-Type: image/jpeg');
- header('Expires: '.gmdate('D, d M Y H:i:s', time() + strtotime($age)).' GMT');
- echo $thumbnailData;
- foreach($recover as $key => $val) {
- $this->$key = $val;
- }
- }
- }
- ?>
== Beispiele ==
=== Bild in meheren Größen speichern ===
Quellcode
== Bild "on the fly" anzeigen ==
Den Original Bildnamen könnt ihr zum Beispiel als $_GET Parameter oder mit mod_rewrite Regeln durchleiten. Im Beispiel wird die Vorschau für das Bild "easy-coding.png" erzeugt.
Der dritte Parameter der Methode display kann einen Zeitausdruck wie "3 month" enthalten, dann wird das Bild für drei Monate im Browser Cache des Benutzers gespeichert, ohne dass es erneut angefragt wird und damit Traffickosten verursacht. Allerdings bekommt der Benutzer auf diese Weise auch nicht von Änderungen mit, deswegen sollte der Intervall je nach Anwendung besser bei "1 day" liegen.
== Demo ==
Die Live Demo findet ihr unter demo.easy-coding.de/php/thumbnail/, herunterladen könnt ihr euch den Code dann unter demo.easy-coding.de/php/thumbnail/download.zip
10.048 mal gelesen