outputJpg(); //-------------------------------------------------- // Load two images $imageSub = new image('2.gif'); $image = new image('1.jpg'); $image->addImage($imageSub, 10, 123); $image->outputGif(); //-------------------------------------------------- // End of example setup ***************************************************/ define('IMAGE_LOAD_SUCCESS', 0); define('IMAGE_LOAD_ERR_GONE', 1); define('IMAGE_LOAD_ERR_SIZE', 2); define('IMAGE_LOAD_ERR_READ', 3); define('IMAGE_ADD_IMAGE_TILE_TOP_LEFT', 0); define('IMAGE_ADD_IMAGE_TILE_CENTER', 1); class image { //-------------------------------------------------- // Setup function image($filePath = NULL) { $this->imageRef = NULL; $this->imageWidth = NULL; $this->imageHeight = NULL; $this->imageType = NULL; $this->alphaBlending = true; if ($filePath !== NULL) { $this->loadFromFile($filePath); } } //-------------------------------------------------- // Create function createImage($width, $height, $bgRed = 0, $bgGreen = 0, $bgBlue = 0) { //-------------------------------------------------- // Kill old image if ($this->imageRef) { imagedestroy($this->imageRef); } //-------------------------------------------------- // Create $this->imageRef = $this->_create_canvas($width, $height); $this->imageWidth = $width; $this->imageHeight = $height; $this->imageType = NULL; // Unknown //-------------------------------------------------- // Background if ($bgRed !== NULL && $bgGreen !== NULL && $bgBlue !== NULL) { $background = imagecolorallocate($this->imageRef, $bgRed, $bgGreen, $bgBlue); imagefill($this->imageRef, 0, 0, $background); } } function loadFromFile($filePath) { $return = $this->_loadImage($filePath); if (!is_array($return)) { return $return; } $this->imageRef = $return['ref']; $this->imageWidth = $return['width']; $this->imageHeight = $return['height']; $this->imageType = $return['type']; if (is_object($filePath) && (get_class($filePath) == 'image' || is_subclass_of($filePath, 'image'))) { $this->alphaBlending = $filePath->alphaBlending; } if (!imageistruecolor($this->imageRef)) { // Happens when using imagecreatefromgif // Disabled as this breaks Creative Metier on the SS server when doing a simple load and save on a gif with transparency. // $oldAlphaBlending = $this->alphaBlending; // $this->alphaBlending = false; // Don't want blending support for this new canvas, while copy over the transparent gif // $newImage = $this->_create_canvas($this->imageWidth, $this->imageHeight); // imagecopyresampled($newImage, $this->imageRef, 0, 0, 0, 0, $this->imageWidth, $this->imageHeight, $this->imageWidth, $this->imageHeight); // imagedestroy($this->imageRef); // $this->imageRef = $newImage; // $this->alphaBlendingSet($oldAlphaBlending); } return IMAGE_LOAD_SUCCESS; } function _loadImage($image) { //-------------------------------------------------- // Return $return = array(); //-------------------------------------------------- // If an image object was passed into this function if (is_object($image) && (get_class($image) == 'image' || is_subclass_of($image, 'image'))) { if (!$image->imageRef) { return IMAGE_LOAD_ERR_READ; } $return['ref'] = $image->imageRef; $return['width'] = $image->imageWidth; $return['height'] = $image->imageHeight; $return['type'] = $image->imageType; return $return; } //-------------------------------------------------- // If we were passed an actual GD object if (is_resource($image) && get_resource_type($image) == 'gd') { $return['ref'] = $image; $return['width'] = imagesx($image); $return['height'] = imagesy($image); $return['type'] = NULL; // Unknown return $return; } //-------------------------------------------------- // If not a file if (substr($image, 0, 7) != 'http://' && (!is_file($image) || !is_readable($image))) { return IMAGE_LOAD_ERR_GONE; } //-------------------------------------------------- // Image dimensions $dimensions = getimagesize($image); if ($dimensions !== false) { $return['width'] = $dimensions[0]; $return['height'] = $dimensions[1]; $return['type'] = $dimensions[2]; } else { return IMAGE_LOAD_ERR_SIZE; } //-------------------------------------------------- // Reference if ($return['type'] == IMAGETYPE_JPEG) { $return['ref'] = imagecreatefromjpeg($image); } else if ($return['type'] == IMAGETYPE_GIF) { $return['ref'] = imagecreatefromgif($image); } else if ($return['type'] == IMAGETYPE_PNG) { $return['ref'] = imagecreatefrompng($image); } else { return IMAGE_LOAD_ERR_READ; } //-------------------------------------------------- // Return return $return; } //-------------------------------------------------- // Create canvas (alpha blending support) function _create_canvas($width, $height) { $image = imagecreatetruecolor($width, $height); $image = $this->alphaBlendingUpdate($image); if (!$this->alphaBlending) { imagecolortransparent($image, imagecolorallocatealpha($image, 0, 0, 0, 127)); // $background = imagecolorallocatealpha($image, 0, 0, 0, 127); // Does not work when opening and directly saving a gif with transparency // imagefill($image, 0, 0, $background); } return $image; } function alphaBlendingSet($enabled) { $this->alphaBlending = ($enabled === true); $this->alphaBlendingUpdate($this->imageRef); } function alphaBlendingUpdate($image) { if ($this->alphaBlending) { imagealphablending($image, true); // Must be on (default) for TrueType fonts imagesavealpha($image, false); } else { imagealphablending($image, false); // Must be off for 'save alpha' imagesavealpha($image, true); } return $image; } //-------------------------------------------------- // Adding an image function addImage($image, $left = 0, $top = 0, $width = NULL, $height = NULL) { if ($this->imageRef) { $return = $this->_loadImage($image); if (!is_array($return)) { return $return; } if ($width === NULL) $width = $return['width']; if ($height === NULL) $height = $return['height']; imagecopyresampled($this->imageRef, $return['ref'], $left, $top, 0, 0, $width, $height, $return['width'], $return['height']); return IMAGE_LOAD_SUCCESS; } } function addImageSizeAndCutToBox($image, $boxLeft, $boxTop, $boxWidth, $boxHeight, $bgRed = 0, $bgGreen = 0, $bgBlue = 0, $config = NULL) { if ($this->imageRef) { //-------------------------------------------------- // Image info $return = $this->_loadImage($image); if (!is_array($return)) { return $return; } //-------------------------------------------------- // Calculate how to crop or scale the image $sourceWidth = $return['width']; $sourceHeight = $return['height']; $sourceLeft = 0; $sourceTop = 0; if ($return['width'] > $boxWidth && $return['height'] > $boxHeight) { // Can only crop when image is big enough //-------------------------------------------------- // The new size if (($return['width'] / $boxWidth) > ($return['height'] / $boxHeight)) { $newHeight = $boxHeight; // Height is the best dimension for cropping to $newWidth = ceil($newHeight * ($return['width'] / $return['height'])); } else { $newWidth = $boxWidth; // Width is the best dimension for cropping to $newHeight = ceil($newWidth * ($return['height'] / $return['width'])); } //-------------------------------------------------- // Return back to the source scale if ($newWidth > $boxWidth) { $sourceWidth = round(($boxWidth / $boxHeight) * $sourceHeight); } else { $sourceHeight = round(($boxHeight / $boxWidth) * $sourceWidth); } //-------------------------------------------------- // Start point $sourceLeft = round(($return['width'] - $sourceWidth) / 2); if (isset($config['positionTop']) && $config['positionTop'] === true) { $sourceTop = 0; } else { $sourceTop = round(($return['height'] - $sourceHeight) / 2); } } else { //-------------------------------------------------- // Add a place holder background if ($bgRed !== NULL && $bgGreen !== NULL && $bgBlue !== NULL) { $background = imagecolorallocate($this->imageRef, $bgRed, $bgGreen, $bgBlue); imagefilledrectangle($this->imageRef, $boxLeft, $boxTop, ($boxLeft + $boxWidth - 1), ($boxTop + $boxHeight - 1), $background); } //-------------------------------------------------- // If a dimension is too big if ($boxWidth > $sourceWidth) { $boxLeft += round(($boxWidth - $sourceWidth) / 2); $boxWidth = $sourceWidth; } if ($boxHeight > $sourceHeight) { $boxTop += round(($boxHeight - $sourceHeight) / 2); $boxHeight = $sourceHeight; } //-------------------------------------------------- // If a dimension is too small if ($boxWidth < $sourceWidth) { $sourceLeft = round(($sourceWidth - $boxWidth) / 2); $sourceWidth = $boxWidth; } if ($boxHeight < $sourceHeight) { if (isset($config['positionTop']) && $config['positionTop'] === true) { $sourceTop = 0; } else { $sourceTop = round(($sourceHeight - $boxHeight) / 2); } $sourceHeight = $boxHeight; } } imagecopyresampled($this->imageRef, $return['ref'], $boxLeft, $boxTop, $sourceLeft, $sourceTop, $boxWidth, $boxHeight, $sourceWidth, $sourceHeight); //-------------------------------------------------- // Return return IMAGE_LOAD_SUCCESS; } } function addImageTile($image, $style = IMAGE_ADD_IMAGE_TILE_CENTER) { $this->addImageTileToArea($image, $this->imageWidth, $this->imageHeight, 0, 0, $style); } function addImageTileToArea($image, $areaWidth, $areaHeight, $areaLeft, $areaTop, $style = IMAGE_ADD_IMAGE_TILE_CENTER) { if ($this->imageRef) { //-------------------------------------------------- // Load $tile = $this->_loadImage($image); if (!is_array($tile)) { return $tile; } //-------------------------------------------------- // Tile repeat count $repeatL = ceil($areaWidth / $tile['width']); $repeatT = ceil($areaHeight / $tile['height']); //-------------------------------------------------- // Offset if ($style == IMAGE_ADD_IMAGE_TILE_TOP_LEFT) { $offsetLeft = 0; $offsetTop = 0; } else { $offsetLeft = (0 - round((($repeatL * $tile['width']) - $areaWidth) / 2)); $offsetTop = (0 - round((($repeatT * $tile['height']) - $areaHeight) / 2)); } //-------------------------------------------------- // Apply tiles for ($l = 0; $l < $repeatL; $l++) { for ($t = 0; $t < $repeatT; $t++) { //-------------------------------------------------- // Grid position $destLeft = ($tile['width'] * $l); $destTop = ($tile['height'] * $t); //-------------------------------------------------- // Which part of the tile to copy - cuts off the // left and top sides $srcLeft = ($l == 0 ? (0 - $offsetLeft) : 0); $srcTop = ($t == 0 ? (0 - $offsetTop) : 0); //-------------------------------------------------- // Size of the tile area to copy - cuts off the // right and bottom sides //-------------------------------------------------- // Width $srcWidth = ($areaWidth - $destLeft) - $offsetLeft; // Double negative, add offsetLeft if ($srcWidth > $tile['width']) { $srcWidth = $tile['width']; // Not too much } $srcWidth -= $srcLeft; // If left-side is cut, don't address too much //-------------------------------------------------- // Height $srcHeight = ($areaHeight - $destTop) - $offsetTop; // Double negative, add offsetTop if ($srcHeight > $tile['height']) { $srcHeight = $tile['height']; // Not too much } $srcHeight -= $srcTop; // If top-side is cut, don't address too much //-------------------------------------------------- // Apply the skew to the grid position - where // the 'offset' and 'src' are the same on the // left column or top row... otherwise its only // the 'offset' which is applied from these two. $destLeft += $areaLeft + ($offsetLeft + $srcLeft); $destTop += $areaTop + ($offsetTop + $srcTop); //-------------------------------------------------- // Copy the tile onto the image, keeping 1:1 ratio imagecopyresampled($this->imageRef, $tile['ref'], $destLeft, $destTop, $srcLeft, $srcTop, $srcWidth, $srcHeight, $srcWidth, $srcHeight); } } //-------------------------------------------------- // Success return IMAGE_LOAD_SUCCESS; } } //-------------------------------------------------- // Change image size function centerToBox($boxWidth, $boxHeight, $bgRed = 0, $bgGreen = 0, $bgBlue = 0, $scale = true) { if ($this->imageRef) { //-------------------------------------------------- // Create the canvas $newImage = $this->_create_canvas($boxWidth, $boxHeight); if ($bgRed !== NULL && $bgGreen !== NULL && $bgBlue !== NULL) { $background = imagecolorallocate($newImage, $bgRed, $bgGreen, $bgBlue); imagefill($newImage, 0, 0, $background); } //-------------------------------------------------- // Configure the centre area $width = $this->imageWidth; $height = $this->imageHeight; if ($scale) { if ($width > $boxWidth) { $height = ceil($boxWidth * ($height / $width)); $width = $boxWidth; } if ($height > $boxHeight) { $width = ceil($boxHeight * ($width / $height)); $height = $boxHeight; } } $left = round(($boxWidth / 2) - ($width / 2)); $top = round(($boxHeight / 2) - ($height / 2)); imagecopyresampled($newImage, $this->imageRef, $left, $top, 0, 0, $width, $height, $this->imageWidth, $this->imageHeight); //-------------------------------------------------- // Kill the old image imagedestroy($this->imageRef); //-------------------------------------------------- // Replace the image $this->imageRef = $newImage; $this->imageWidth = $boxWidth; $this->imageHeight = $boxHeight; } } function cutToBox($boxWidth, $boxHeight, $bgRed = 0, $bgGreen = 0, $bgBlue = 0) { $this->centerToBox($boxWidth, $boxHeight, $bgRed, $bgGreen, $bgBlue, false); } function sizeAndCutToBox($boxWidth, $boxHeight, $bgRed = 0, $bgGreen = 0, $bgBlue = 0) { if ($this->imageRef) { //-------------------------------------------------- // Create the canvas $newImage = $this->_create_canvas($boxWidth, $boxHeight); if ($bgRed !== NULL && $bgGreen !== NULL && $bgBlue !== NULL) { $background = imagecolorallocate($newImage, $bgRed, $bgGreen, $bgBlue); imagefill($newImage, 0, 0, $background); } //-------------------------------------------------- // Configure the centre area $newWidth = $this->imageWidth; $newHeight = $this->imageHeight; if ($this->imageWidth > $boxWidth && $this->imageHeight > $boxHeight) { // Can only crop when image is big enough if (($this->imageWidth / $boxWidth) > ($this->imageHeight / $boxHeight)) { $newHeight = $boxHeight; // Height is the best dimension for cropping to $newWidth = ceil($newHeight * ($this->imageWidth / $this->imageHeight)); } else { $newWidth = $boxWidth; // Width is the best dimension for cropping to $newHeight = ceil($newWidth * ($this->imageHeight / $this->imageWidth)); } } $left = round(($boxWidth / 2) - ($newWidth / 2)); $top = round(($boxHeight / 2) - ($newHeight / 2)); imagecopyresampled($newImage, $this->imageRef, $left, $top, 0, 0, $newWidth, $newHeight, $this->imageWidth, $this->imageHeight); //-------------------------------------------------- // Kill the old image imagedestroy($this->imageRef); //-------------------------------------------------- // Replace the image $this->imageRef = $newImage; $this->imageWidth = $boxWidth; $this->imageHeight = $boxHeight; } } function maxSize($maxWidth, $maxHeight) { if ($this->imageRef && ($this->imageWidth > $maxWidth || $this->imageHeight > $maxHeight)) { //-------------------------------------------------- // Dimensions $newWidth = $this->imageWidth; $newHeight = $this->imageHeight; if ($newWidth > $maxWidth) { $newHeight = (round($maxWidth * ($newHeight / $newWidth))); $newWidth = $maxWidth; } if ($newHeight > $maxHeight) { $newWidth = (round($maxHeight * ($newWidth / $newHeight))); $newHeight = $maxHeight; } //-------------------------------------------------- // Size $newImage = $this->_create_canvas($newWidth, $newHeight); imagecopyresampled($newImage, $this->imageRef, 0, 0, 0, 0, $newWidth, $newHeight, $this->imageWidth, $this->imageHeight); //-------------------------------------------------- // Kill the old image imagedestroy($this->imageRef); //-------------------------------------------------- // Store $this->imageRef = $newImage; $this->imageWidth = $newWidth; $this->imageHeight = $newHeight; } } function scaleWidth($width) { if ($this->imageRef) { $height = (round($width * ($this->imageHeight / $this->imageWidth))); $this->forceSize($width, $height); } } function scaleHeight($height) { if ($this->imageRef) { $width = (round($height * ($this->imageWidth / $this->imageHeight))); $this->forceSize($width, $height); } } function forceSize($width, $height) { if ($this->imageRef) { $newImage = $this->_create_canvas($width, $height); imagecopyresampled($newImage, $this->imageRef, 0, 0, 0, 0, $width, $height, $this->imageWidth, $this->imageHeight); imagedestroy($this->imageRef); $this->imageRef = $newImage; $this->imageWidth = $width; $this->imageHeight = $height; } } function cropSize($width, $height, $left = 0, $top = 0) { if ($this->imageRef) { $newImage = $this->_create_canvas($width, $height); imagecopyresampled($newImage, $this->imageRef, 0, 0, $left, $top, $width, $height, $width, $height); imagedestroy($this->imageRef); $this->imageRef = $newImage; $this->imageWidth = $width; $this->imageHeight = $height; } } //-------------------------------------------------- // Rotate image function rotate($degrees) { if ($this->imageRef) { // imagerotate($this->imageRef, $degrees, 0); if ($degrees == 90 || $degrees == 270) { $newWidth = $this->imageHeight; $newHeight = $this->imageWidth; } else if ($degrees == 180) { $newWidth = $this->imageWidth; $newHeight = $this->imageHeight; } else { return; } $newImage = $this->_create_canvas($newWidth, $newHeight); for ($i = 0; $i < $this->imageWidth; $i++) { for ($j = 0; $j < $this->imageHeight; $j++) { $srcColour = imagecolorat($this->imageRef, $i, $j); switch ($degrees) { case 90: imagesetpixel($newImage, (($this->imageHeight - 1) - $j), $i, $srcColour ); break; case 180: imagesetpixel($newImage, ($this->imageWidth - $i), (($this->imageHeight - 1) - $j), $srcColour ); break; case 270: imagesetpixel($newImage, $j, ($this->imageWidth - $i), $srcColour ); break; } } } imagedestroy($this->imageRef); $this->imageRef = $newImage; $this->imageWidth = $newWidth; $this->imageHeight = $newHeight; } } //-------------------------------------------------- // Return image details function getWidth() { return $this->imageWidth; } function getHeight() { return $this->imageHeight; } function getType() { return $this->imageType; } function getRef() { return $this->imageRef; } //-------------------------------------------------- // Print image function outputPng($compression = 0) { if ($this->imageRef) { header('Content-type: image/png'); imagepng($this->imageRef, NULL, $compression); } } function outputGif() { if ($this->imageRef) { header('Content-type: image/gif'); imagegif($this->imageRef); } } function outputJpg($quality = 80) { if ($this->imageRef) { header('Content-type: image/jpeg'); imagejpeg($this->imageRef, NULL, $quality); } } //-------------------------------------------------- // Save image function savePng($filePath, $compression = 0) { if ($this->imageRef) { imagepng($this->imageRef, $filePath, $compression); @chmod($filePath, 0666); } } function saveGif($filePath) { if ($this->imageRef) { imagegif($this->imageRef, $filePath); @chmod($filePath, 0666); } } function saveJpg($filePath, $quality = 80) { if ($this->imageRef) { imagejpeg($this->imageRef, $filePath, $quality); @chmod($filePath, 0666); } } function saveTiles($numTilesWide, $numTilesHigh, $fileNamePrefix, $fileNameExt = 'jpg', $tileWidth = 256, $tileHeight = 256, $bgRed = 0, $bgGreen = 0, $bgBlue = 0, $quality = NULL) { if ($this->imageRef) { //-------------------------------------------------- // Create the canvas //-------------------------------------------------- // Start $canvasWidth = ($numTilesWide * $tileWidth); $canvasHeight = ($numTilesHigh * $tileHeight); $canvas = $this->_create_canvas($canvasWidth, $canvasHeight); //-------------------------------------------------- // Background if ($bgRed !== NULL && $bgGreen !== NULL && $bgBlue !== NULL) { $background = imagecolorallocate($canvas, $bgRed, $bgGreen, $bgBlue); imagefill($canvas, 0, 0, $background); } //-------------------------------------------------- // Add image if ($this->imageWidth > $this->imageHeight) { $canvasZoomMaxLevel = ceil(log(ceil($this->imageWidth / $tileWidth), 2)); } else { $canvasZoomMaxLevel = ceil(log(ceil($this->imageHeight / $tileHeight), 2)); } $canvasZoomMaxSizeWidth = (intval(pow(2, $canvasZoomMaxLevel)) * $tileWidth); $canvasZoomMaxSizeHeight = (intval(pow(2, $canvasZoomMaxLevel)) * $tileHeight); $width = (($this->imageWidth / $canvasZoomMaxSizeWidth) * $canvasWidth); $height = (($this->imageHeight / $canvasZoomMaxSizeHeight) * $canvasHeight); $offsetLeft = (($canvasWidth / 2) - ($width / 2)); $offsetTop = (($canvasHeight / 2) - ($height / 2)); imagecopyresampled($canvas, $this->imageRef, $offsetLeft, $offsetTop, 0, 0, $width, $height, $this->imageWidth, $this->imageHeight); //-------------------------------------------------- // Save the image parts for ($x = 0; $x < $numTilesWide; $x++) { for ($y = 0; $y < $numTilesHigh; $y++) { $tile = $this->_create_canvas($tileWidth, $tileHeight); imagecopyresampled($tile, $canvas, 0, 0, ($x * $tileWidth), ($y * $tileWidth), $tileWidth, $tileHeight, $tileWidth, $tileHeight); $filePath = $fileNamePrefix . $x . '-' . $y . '.' . $fileNameExt; if ($quality) { if ($fileNameExt == 'png') imagepng($tile, $filePath, $quality); if ($fileNameExt == 'jpg') imagejpeg($tile, $filePath, $quality); } else { if ($fileNameExt == 'png') imagepng($tile, $filePath); if ($fileNameExt == 'gif') imagegif($tile, $filePath); if ($fileNameExt == 'jpg') imagejpeg($tile, $filePath); } @chmod($filePath, 0666); imagedestroy($tile); } } //-------------------------------------------------- // Cleanup imagedestroy($canvas); } } //-------------------------------------------------- // Destroy image function destroy() { if ($this->imageRef) { imagedestroy($this->imageRef); $this->imageRef = NULL; $this->imageWidth = NULL; $this->imageHeight = NULL; $this->imageType = NULL; } } //-------------------------------------------------- // Clone support public function __clone() { $newImage = $this->_create_canvas($this->imageWidth, $this->imageHeight); imagecopyresampled($newImage, $this->imageRef, 0, 0, 0, 0, $this->imageWidth, $this->imageHeight, $this->imageWidth, $this->imageHeight); $this->imageRef = $newImage; } } //-------------------------------------------------- // Copyright (c) 2006, Craig Francis All rights // reserved. // // Redistribution and use in source and binary forms, // with or without modification, are permitted provided // that the following conditions are met: // // * Redistributions of source code must retain the // above copyright notice, this list of // conditions and the following disclaimer. // * Redistributions in binary form must reproduce // the above copyright notice, this list of // conditions and the following disclaimer in the // documentation and/or other materials provided // with the distribution. // * Neither the name of the author nor the names // of its contributors may be used to endorse or // promote products derived from this software // without specific prior written permission. // // This software is provided by the copyright holders // and contributors "as is" and any express or implied // warranties, including, but not limited to, the // implied warranties of merchantability and fitness // for a particular purpose are disclaimed. In no event // shall the copyright owner or contributors be liable // for any direct, indirect, incidental, special, // exemplary, or consequential damages (including, but // not limited to, procurement of substitute goods or // services; loss of use, data, or profits; or business // interruption) however caused and on any theory of // liability, whether in contract, strict liability, or // tort (including negligence or otherwise) arising in // any way out of the use of this software, even if // advised of the possibility of such damage. //-------------------------------------------------- ?>