<?php

/**

* @author Kaloyan K. Tsvetkov <kaloyan@kaloyan.info>

* @license http://opensource.org/licenses/lgpl-license.php GNU Lesser General Public License Version 2.1

* @package Asido

* @subpackage Asido.Driver.GD

* @version $Id: class.driver.gd.php 7 2007-04-09 21:09:09Z mrasnika $

*/



/////////////////////////////////////////////////////////////////////////////



/**

* Quality factor for saving JPEG files

* @see Asido_Driver_GD::Save()

*/

if (!defined('ASIDO_GD_JPEG_QUALITY')) {

	define('ASIDO_GD_JPEG_QUALITY', 80);

	}



if (!defined('ASIDO_GD_PNG_QUALITY')) {

	define('ASIDO_GD_PNG_QUALITY', floor(abs(99 - ASIDO_GD_JPEG_QUALITY) / 10));

}



/////////////////////////////////////////////////////////////////////////////



/**

* Asido GD(GD2) driver

*

* @package Asido

* @subpackage Asido.Driver.GD

*/

Class Asido_Driver_GD Extends Asido_Driver {



	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 

	

	/**

	* Maps to supported mime types

	* @var array

	* @access protected

	*/

	var $__mime = array(



		// support reading

		//

		'read' => array(

		

			// GIF

			//

			'image/gif',

			

			// JPEG

			//

			'application/jpg',

			'application/x-jpg',

			'image/jpg',

			'image/jpeg',

			

			// WBMP

			//

			'image/wbmp',

			

			// XPM

			//

			'image/x-xpixmap',

			'image/x-xpm',

			

			// XBM

			//

			'image/x-xbitmap',

			'image/x-xbm',

			

			// PNG

			//

			'application/png',

			'application/x-png',

			'image/x-png',

			'image/png',

		

			),

		

		// support writing

		//

		'write' => array(

		

			// GIF

			//

			'image/gif',

			

			// JPEG

			//

			'application/jpg',

			'application/x-jpg',

			'image/jpg',

			'image/jpeg',

			

			// WBMP

			//

			'image/wbmp',

			

			// PNG

			//

			'application/png',

			'application/x-png',

			'image/x-png',

			'image/png',

			),	



		);

	

	/**

	* Metaphone map for detecting image file extensions

	* @var array

	* @access private

	*/

	var $__mime_metaphone = array(

			'JPK' => 'image/jpeg',

			'JP' => 'image/jpeg',

			'JF' => 'image/gif',

			'NK' => 'image/png',

			'BMP' => 'image/wbmp',

			'SPM' => 'image/x-xbm',

			// 'SBM' => 'image/x-xpm',

				// ^

				// XPM is read-only and this map is used for

				// saving files, so this XPM entry is useless

		);



	/**

	* Soundex map for detecting image file extensions

	* @var array

	* @access private

	*/

	var $__mime_soundex = array(

			'J120' => 'image/jpeg',

			'J100' => 'image/jpeg',

			'G100' => 'image/gif',

			'P520' => 'image/png',

			'B510' => 'image/wbmp',

			'W151' => 'image/wbmp',

		);



	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 



	/**

	* Checks whether the environment is compatible with this driver

	*

	* @return boolean

	* @access public

	*/

	function is_compatible() {

		

		if (!extension_loaded('gd')) {

			trigger_error(

				'The Asido_Driver_GD driver is unnable to be '

					. ' initialized, because the GD (php_gd2) '

					. ' module is not installed',

				E_USER_ERROR

				);

			return false;

			}

		

		// give access to all the memory

		//

		@ini_set("memory_limit", -1);

		

		return true;

		}

	

	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 



	/**

	* Do the actual resize of an image

	*

	* @param Asido_TMP &$tmp

	* @param integer $width

	* @param integer $height

	* @return boolean

	* @access protected

	*/

	function __resize(&$tmp, $width, $height) {



		// create new target

		//

		$_ = imageCreateTrueColor($width, $height);

		imageSaveAlpha($_, true);

		imageAlphaBlending($_, false);



		$r = imageCopyResampled(

			$_, $tmp->target,

				0,0,

				0,0,

				$width, $height,

				$tmp->image_width, $tmp->image_height

			);



		// set new target

		//

		$this->__destroy_target($tmp);

		$tmp->target = $_;



		return $r;

		}



	/**

	* Copy one image to another

	*

	* @param Asido_TMP &$tmp_target

	* @param Asido_TMP &$tmp_source

	* @param integer $destination_x

	* @param integer $destination_y

	* @return boolean

	* @access protected

	*/

	function __copy(&$tmp_target, &$tmp_source, $destination_x, $destination_y) {



		imageAlphaBlending($tmp_target->target, true);

		$r = imageCopy($tmp_target->target, $tmp_source->source,

			$destination_x, $destination_y,

			0, 0,

			$tmp_source->image_width, $tmp_source->image_height

			);

		imageAlphaBlending($tmp_target->target, false);

		

		return $r;

		}



	/**

	* Make the image greyscale: supported only for PHP => 5.* and PHP => 4.0.1 except for PHP 4.3.11

	*

	* @param Asido_TMP &$tmp

	* @return boolean

	* @access protected

	*/

	function __grayscale(&$tmp) {



		// the shorter path: function already exists

		//

		if (function_exists('imagefilter')) {

			return imagefilter($tmp->target, IMG_FILTER_GRAYSCALE);

			return true;

			}



		// a bit wicked path: PHP 4.3.11 has a bug in this function

		//

		if (!in_array(PHP_VERSION, array('4.3.11'))) {

			return imageCopyMergeGray($tmp->target, $tmp->target,

				0, 0, 0, 0,

				$tmp->image_width, $tmp->image_height, 0);

			}

		

		return false;

		}



	/**

	* Rotate the image clockwise

	*

	* @param Asido_TMP &$tmp

	* @param float $angle

	* @param Asido_Color &$color

	* @return boolean

	* @access protected

	*/

	function __rotate(&$tmp, $angle, &$color) {



		// skip full loops

		//

		if (($angle % 360) == 0) {

			return true;

			}

		

		list($r, $g, $b) = $color->get();

		$rotate_color = imageColorAllocate($tmp->target, $r, $g, $b); 

		

		if ($t = imageRotate($tmp->target, $angle * -1, $rotate_color)) {

			imageDestroy($tmp->target);

			$tmp->target = $t;

			

			$tmp->image_width = imageSX($tmp->target);

			$tmp->image_height = imageSY($tmp->target);

			

			return true;

			}



		return false;

		}



	/**

	* Crop the image 

	*

	* @param Asido_TMP &$tmp

	* @param integer $x

	* @param integer $y

	* @param integer $width

	* @param integer $height

	* @return boolean

	* @access protected

	*/

	function __crop(&$tmp, $x, $y, $width, $height) {

		

		$t = imageCreateTrueColor($width, $height);

		imageAlphaBlending($t, true);

		$r = imageCopy($t, $tmp->target,

			0, 0,

			$x, $y,

			$width, $height

			);

		imageAlphaBlending($t, false);

		

		$this->__destroy_target($tmp);

		$tmp->target = $t;

		$tmp->image_width = $width;

		$tmp->image_height = $height;

		

		return $r;

		}



	/**

	* Vertically mirror (flip) the image: not supported

	* 

	* @param Asido_TMP &$tmp

	* @return boolean

	* @access protected

	*/

	function __flip(&$tmp) {

		return false;

		}



	/**

	* Horizontally mirror (flop) the image: not supported

	* 

	* @param Asido_Image &$image

	* @return boolean

	* @access protected

	*/

	function __flop(&$tmp) {

		return false;

		}



	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 



	/**

	* Get canvas

	*

	* @param integer $width

	* @param integer $height

	* @param Asido_Color &$color

	* @return Asido_TMP

	* @access protected

	*/

	function __canvas($width, $height, &$color) {

		

		$t = new Asido_TMP;

		$t->target = imageCreateTrueColor($width, $height);

		

		list($r, $g, $b) = $color->get();

		imageFill($t->target, 1, 1, 

			imageColorAllocate($t->target, $r, $g, $b)

			);

		$t->image_width = $width;

		$t->image_height = $height;



		return $t;

		}



	/**

	* Generate a temporary object for the provided argument

	*

	* @param mixed &$handler

	* @param string $filename the filename will be automatically generated 

	*	on the fly, but if you want you can use the filename provided by 

	*	this argument

	* @return Asido_TMP

	* @access protected

	*/

	function __tmpimage(&$handler, $filename=null) {



		if (!isset($filename)) {

			$filename = $this->__tmpfile();

			}



		imageAlphaBlending($handler, 0);

		imageSaveAlpha($handler, 1); 

		imagePNG($handler, $filename);

			// ^

			// PNG: no pixel losts



		return $this->prepare(

			new Asido_Image($filename)

			);

		}



	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 



	/**

	* Open the source and target image for processing it

	*

	* @param Asido_TMP &$tmp

	* @return boolean

	* @access protected

	*/

	function __open(&$tmp) {



		$error_source = false;

		$error_target = false;



		// get image dimensions

		//

		if ($i = @getImageSize($tmp->source_filename)) {

			$tmp->image_width = $i[0];

			$tmp->image_height = $i[1];

			}

		

		// image type ?

		//

		switch(@$i[2]) {

			

			case 1:	// GIF

				$error_source = (false == (

					$tmp->source = @imageCreateFromGIF(

						$tmp->source_filename

						)

					));



				$error_target = false == (

					$tmp->target = imageCreateTrueColor(

						$tmp->image_width, $tmp->image_height

						)

					);

				$error_target &= imageCopyResampled(

					$tmp->target, $tmp->source, 

					0, 0, 0, 0,

					$tmp->image_width, $tmp->image_height,

					$tmp->image_width, $tmp->image_height

					);

				

				break;



			case 2: // JPG

				$error_source = (false == (

					$tmp->source = imageCreateFromJPEG(

						$tmp->source_filename

						)

					));

				

				$error_target = (false == (

					$tmp->target = imageCreateFromJPEG(

						$tmp->source_filename

						)

					));

				break;



			case 3: // PNG

				$error_source = (false == (

					$tmp->source = @imageCreateFromPNG(

						$tmp->source_filename

						)

					));



				$error_target = (false == (

					$tmp->target = @imageCreateFromPNG(

						$tmp->source_filename

						)

					));

				break;



			case 15: // WBMP

				$error_source = (false == (

					$tmp->source = @imageCreateFromWBMP(

						$tmp->source_filename

						)

					));



				$error_target = (false == (

					$tmp->target = @imageCreateFromWBMP(

						$tmp->source_filename

						)

					));

				break;



			case 16: // XBM

				$error_source = (false == (

					$tmp->source = @imageCreateFromXBM(

						$tmp->source_filename

						)

					));



				$error_target = (false == (

					$tmp->target = @imageCreateFromXBM(

						$tmp->source_filename

						)

					));

				break;



			case 4: // SWF



			case 5: // PSD



			case 6: // BMP



			case 7: // TIFF(intel byte order)



			case 8: // TIFF(motorola byte order)



			case 9: // JPC



			case 10: // JP2



			case 11: // JPX



			case 12: // JB2



			case 13: // SWC



			case 14: // IFF

				

			default:

				

				$error_source = (false == (

					$tmp->source = @imageCreateFromString(

						file_get_contents(

							$tmp->source_filename

							)

						)

					));



				$error_target = (false == (

					$tmp->source = @imageCreateFromString(

						file_get_contents(

							$tmp->source_filename

							)

						)

					));

				break;

			}



		return !($error_source || $error_target);

		}



	/**

	* Write the image after being processed

	*

	* @param Asido_TMP &$tmp

	* @return boolean

	* @access protected

	*/

	function __write(&$tmp) {



		// try to guess format from extension

		//

		if (!$tmp->save) {

			$p = pathinfo($tmp->target_filename);



			($tmp->save = $this->__mime_metaphone[metaphone($p['extension'])])

				|| ($tmp->save = $this->__mime_soundex[soundex($p['extension'])]);

			}



		$result = false;

		switch($tmp->save) {



			case 'image/gif' :

				imageTrueColorToPalette($tmp->target, true, 256);

				$result = @imageGIF($tmp->target, $tmp->target_filename);

				break;

				

			case 'image/jpeg' :

				$result = @imageJPEG($tmp->target, $tmp->target_filename, ASIDO_GD_JPEG_QUALITY);

				break;

				

			case 'image/wbmp' :

				$result = @imageWBMP($tmp->target, $tmp->target_filename);

				break;

			

			default :

			case 'image/png' :



				imageSaveAlpha($tmp->target, true);

				imageAlphaBlending($tmp->target, false);

			

				$result = @imagePNG($tmp->target, $tmp->target_filename, ASIDO_GD_PNG_QUALITY);

				break;

			}

		

		@$this->__destroy_source($tmp);

		@$this->__destroy_target($tmp);



		return $result;

		}

	

	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 



	/**

	* Destroy the source for the provided temporary object

	*

	* @param Asido_TMP &$tmp

	* @return boolean

	* @access protected

	* @abstract

	*/	

	function __destroy_source(&$tmp) {

		return imageDestroy($tmp->source);

		}



	/**

	* Destroy the target for the provided temporary object

	*

	* @param Asido_TMP &$tmp

	* @return boolean

	* @access protected

	* @abstract

	*/	

	function __destroy_target(&$tmp) {

		return imageDestroy($tmp->target);

		}



	// -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 



//--end-of-class--	

}



/////////////////////////////////////////////////////////////////////////////



?>