<?php

Class PHPRC_IMAGE
{
	Private Static $CACHED_IMAGE = null;
	Private Static $GENERATED_IMAGE = null;
	
	Private Static $CACHED_IMAGE_WIDTH = null;
	Private Static $CACHED_IMAGE_HEIGHT = null;
	Private Static $CACHED_IMAGE_TYPE = null;
	
	
	/**
	 * Print QR Code as Image HTTP Header. This exits the PHP execution.
	 */
	Public Static Function REF_BARCODE
	(
	    $BARCODE_STRING = "", 
	    $BARCODE_SIZE = 20, 
	    $BARCODE_TYPE = "code128", 
	    $SHOW_CAPTION = false
	)
	{
	    // Parameter Validation
	    // ------------------------------------------------------------------
	    PHPVC_AV::VAR_VALIDATE_NULL($BARCODE_STRING, "BARCODE_STRING");
	    PHPVC_AV::VAR_VALIDATE_NULL($BARCODE_TYPE, "BARCODE_TYPE");
	    // ------------------------------------------------------------------
	    
	    // Actual Function
	    // ------------------------------------------------------------------
	    Try
	    {
	        Include_Once(PHPSET::$ROOT . '/Modules/References/phpbarcode/PHPRC_BARCODE.php');
	        Header('Content-Type: image/png');
	        PHPRC_BARCODE::png("", $BARCODE_STRING, $BARCODE_SIZE, "horizontal", $BARCODE_TYPE, $SHOW_CAPTION);
	        exit;
	    }
	    Catch(Exception $ERR)
	    {
	        PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
	        Throw $ERR;
	    }
	    // ------------------------------------------------------------------
	}
	
	
	/**
	 * Print QR Code as Image HTTP Header. This exits the PHP execution.
	 */
	Public Static Function REF_QRCODE($QRCODE_STRING = "", $QRCODE_SIZE = 10)
	{
	    // Parameter Validation
	    // ------------------------------------------------------------------
	    PHPVC_AV::VAR_VALIDATE_NULL($QRCODE_STRING, "QRCODE_STRING");
	    // ------------------------------------------------------------------
	    
	    // Actual Function
	    // ------------------------------------------------------------------
	    Try
	    {
	        Include_Once(PHPSET::$ROOT . '/Modules/References/phpqrcode/qrlib.php');
	        Header('Content-Type: image/png');
	        QRcode::png($QRCODE_STRING, false, QR_ECLEVEL_L, $QRCODE_SIZE);
	        exit;
	    }
	    Catch(Exception $ERR)
	    {
	        PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
	        Throw $ERR;
	    }
	    // ------------------------------------------------------------------
	}
	
	/**
	 * Prepare image to resize/crop, load image from file.
	 * @param String $FILE_PATH <br />Full path of file<br />
	 */
	Public Static Function REF_LOAD($FILE_PATH)
	{
		// Parameter Validation
		// ................................................
		if(isset(SELF::$CACHED_IMAGE) === true)
		{
			Throw PHPVC_ERROR::VAR_RAISERROR(New Exception(PHPVC_ERROR::VAR_EXCEPTION_CONTENT_EXISTS(false)));
		}
		// ................................................
		
		Try
		{
			$IMAGE_INFO = getimagesize($FILE_PATH);
			SELF::$CACHED_IMAGE_WIDTH = $IMAGE_INFO[0];
			SELF::$CACHED_IMAGE_HEIGHT = $IMAGE_INFO[1];
			SELF::$CACHED_IMAGE_TYPE = $IMAGE_INFO[2];
			
			if(SELF::$CACHED_IMAGE_TYPE == IMAGETYPE_GIF)
			{
				SELF::$CACHED_IMAGE = imagecreatefromgif($FILE_PATH);
			}
			else if(SELF::$CACHED_IMAGE_TYPE == IMAGETYPE_JPEG)
			{
				SELF::$CACHED_IMAGE = imagecreatefromjpeg($FILE_PATH);
			}
			elseif(SELF::$CACHED_IMAGE_TYPE == IMAGETYPE_PNG)
			{
				SELF::$CACHED_IMAGE = imagecreatefrompng($FILE_PATH);
			}
		}
		Catch(Exception $ERR)
		{
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			PHPRC_IMAGE::REF_DISPOSE();
			Throw $ERR;
		}
	}
	
	
	/**
	 * Use the source image as generated result
	 */
	Public Static Function REF_COPY()
	{
		// Parameter Validation
		// ................................................
		PHPVC_AV::VAR_VALIDATE_NULL(SELF::$CACHED_IMAGE, "CACHED_IMAGE");
		// ................................................
		
		// Actual Function
		// ................................................
		Try
		{
			SELF::$GENERATED_IMAGE = SELF::$CACHED_IMAGE;
		}
		Catch(Exception $ERR)
		{
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			Throw $ERR;
		}
		// ................................................
	}
	/**
	 * Overwrite GENERATED result into SOURCE image (variable only)
	 */
	Public Static Function REF_REPLACE()
	{
		// Parameter Validation
		// ................................................
		PHPVC_AV::VAR_VALIDATE_NULL(SELF::$CACHED_IMAGE, "CACHED_IMAGE");
		// ................................................
		
		// Actual Function
		// ................................................
		Try
		{
			SELF::$CACHED_IMAGE = null;
			SELF::$CACHED_IMAGE = SELF::$GENERATED_IMAGE;
			
			SELF::$CACHED_IMAGE_WIDTH = imagesx(SELF::$CACHED_IMAGE);
			SELF::$CACHED_IMAGE_HEIGHT = imagesy(SELF::$CACHED_IMAGE);
		}
		Catch(Exception $ERR)
		{
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			Throw $ERR;
		}
		// ................................................
	}
	
	
	/**
	 * Retrieves the width (X/px) of loaded image.
	 * @throws Exception
	 * @return Int
	 */
	Public Static Function REF_GET_WIDTH()
	{
		// Parameter Validation
		// ................................................
		PHPVC_AV::VAR_VALIDATE_NULL(SELF::$CACHED_IMAGE, "CACHED_IMAGE");
		// ................................................
		
		// Actual Function
		// ................................................
		Try
		{
			return SELF::$CACHED_IMAGE_WIDTH;
		}
		Catch(Exception $ERR)
		{
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			Throw $ERR;
		}
		// ................................................
	}
	
	/**
	 * Retrieves the height (Y/px) of loaded image.
	 * @throws Exception
	 * @return Int
	 */
	Public Static Function REF_GET_HEIGHT()
	{
		// Parameter Validation
		// ................................................
		PHPVC_AV::VAR_VALIDATE_NULL(SELF::$CACHED_IMAGE, "CACHED_IMAGE");
		// ................................................
		
		// Actual Function
		// ................................................
		Try
		{
			return SELF::$CACHED_IMAGE_HEIGHT;
		}
		Catch(Exception $ERR)
		{
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			Throw $ERR;
		}
		// ................................................
	}
	
	/**
	 * Retrieves the type (GIF/JPG/PNG) of loaded image.
	 * @throws Exception
	 * @return unknown
	 */
	Public Static Function REF_GET_TYPE()
	{
		// Parameter Validation
		// ................................................
		PHPVC_AV::VAR_VALIDATE_NULL(SELF::$CACHED_IMAGE, "CACHED_IMAGE");
		// ................................................
		
		// Actual Function
		// ................................................
		Try
		{
			return $CACHED_IMAGE_TYPE;
		}
		Catch(Exception $ERR)
		{
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			Throw $ERR;
		}
		// ................................................
	}
	
	/**
	 * Loads image file from base-64 encoded string
	 * @param String $BASE64_VALUE
	 * @throws Exception
	 */
	Public Static Function REF_LOAD_FROM_BASE64($BASE64_VALUE)
	{
		// Parameter Validation
		// ................................................
		if(isset(SELF::$CACHED_IMAGE) === true)
		{
			Throw PHPVC_ERROR::VAR_RAISERROR(New Exception(PHPVC_ERROR::VAR_EXCEPTION_CONTENT_EXISTS(false)));
		}
		// ................................................
		
		// Actual Function
		// ................................................
		Try
		{
			$TEMP_DIR = sys_get_temp_dir();
			$TEMP_EXT = '.tmp';
			
			$TEMP_IMAGE = tempnam($TEMP_DIR, $TEMP_EXT);
			PHPRC_FSO_FILE::REF_WRITE
			(
					PHPRC_FSO_FILE::REF_NAME($TEMP_IMAGE),
					PHPRC_FSO_FILE::REF_PATH($TEMP_IMAGE),
					$BASE64_VALUE
					);
			
			PHPRC_IMAGE::REF_LOAD($TEMP_IMAGE);
		}
		Catch(Exception $ERR)
		{
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			Throw $ERR;
		}
		// ................................................
	}
	
	/**
	 * Convert generated image into Base-64 string
	 * @return String
	 */
	Public Static Function REF_TO_BASE64()
	{
		// Parameter Validation
		// ................................................
		if(isset(SELF::$GENERATED_IMAGE) === false)
		{
			Throw PHPVC_ERROR::VAR_RAISERROR(New Exception(PHPVC_ERROR::VAR_ARGUMENT_EXCEPTION_NULL("GENERATED_IMAGE", False)));
		}
		// ................................................
		
		// ................................................
		Try
		{
			ob_start();
			
			if(SELF::$CACHED_IMAGE_TYPE == IMAGETYPE_GIF)
			{
				imagegif(SELF::$GENERATED_IMAGE);
			}
			else if(SELF::$CACHED_IMAGE_TYPE == IMAGETYPE_JPEG)
			{
				imagejpeg(SELF::$GENERATED_IMAGE);
			}
			elseif(SELF::$CACHED_IMAGE_TYPE == IMAGETYPE_PNG)
			{
				imagepng(SELF::$GENERATED_IMAGE);
			}
			else
			{
				Throw New Exception(PHPVC_ERROR::VAR_ARGUMENT_EXCEPTION_UNSUPPORTED_TYPE('CACHED_IMAGE_TYPE', false));
			}
			
			$BASE64_VALUE = base64_encode(ob_get_contents());
			ob_end_clean();
			
			return $BASE64_VALUE;
		}
		Catch(Exception $ERR)
		{
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			Throw $ERR;
		}
		
		// Let's start output buffering.
		imagejpeg($image); //This will normally output the image, but because of ob_start(), it won't.
		// ................................................
	}
	

    /**
     * Crop from loaded image. This automatically calls the REF_REPLACE() method.
     * @param unknown $IMAGE_WIDTH Result image width
     * @param unknown $IMAGE_HEIGHT Result image height
     * @param unknown $IMAGE_MAX_SIZE Result Max Size
     * @param number $CROP_LEFT Crop location of X
     * @param number $CROP_TOP Crop locayion of Y
     * @param boolean $CROP_CENTER If TRUE, automatically assign CROP_LEFT and CROP_TOP to get from center of the image. To use CROP_CENTER, you must NOT assign a value in CROP_LEFT or CROP_TOP. 
     * @throws Exception
     */
    Public Static Function REF_CROP
    (
        $IMAGE_WIDTH = -1,
        $IMAGE_HEIGHT = -1,
        $IMAGE_MAX_SIZE = -1,
        $CROP_LEFT = 0,
        $CROP_TOP = 0,
        $CROP_CENTER = False
    )
    {
        // Parameter Validation
        // ------------------------------------------------------------------------
        PHPVC_AV::VAR_VALIDATE_NULL(self::$CACHED_IMAGE, "CACHED_IMAGE");
        
        if($IMAGE_WIDTH > 0 && $IMAGE_WIDTH > self::$CACHED_IMAGE_WIDTH)
        {
            PHPVC_AV::VAR_VALIDATE_RANGE($IMAGE_WIDTH, "IMAGE_WIDTH:" . $IMAGE_WIDTH, 1, self::$CACHED_IMAGE_WIDTH);
        }
        
        if($IMAGE_HEIGHT > 0 && $IMAGE_HEIGHT > self::$CACHED_IMAGE_HEIGHT)
        {
            PHPVC_AV::VAR_VALIDATE_RANGE($IMAGE_HEIGHT, "IMAGE_HEIGHT:" . $IMAGE_HEIGHT, 1, self::$CACHED_IMAGE_HEIGHT);
        }
        
        if($IMAGE_WIDTH <= 0 && $IMAGE_HEIGHT <= 0 && $IMAGE_MAX_SIZE <= 0)
        {
            PHPVC_AV::VAR_VALIDATE_NULL(null, "IMAGE_WIDTH / IMAGE_HEIGHT / IMAGE_MAX_SIZE");
        }
        
        if(($IMAGE_WIDTH > 0 || $IMAGE_HEIGHT > 0) && $IMAGE_MAX_SIZE > 0)
        {
            Throw PHPVC_ERROR::VAR_RAISERROR(new Exception("Cannot process fixed width/height with max size arguments."));
        }
        
        if($CROP_LEFT < 0)
        {
            PHPVC_AV::VAR_VALIDATE_RANGE($CROP_LEFT, 'CROP_LEFT:' . $CROP_LEFT, 0, self::$CACHED_IMAGE_WIDTH);
        }
        
        if($CROP_TOP < 0)
        {
            PHPVC_AV::VAR_VALIDATE_RANGE($CROP_TOP, 'CROP_TOP:' . $CROP_TOP, 0, self::$CACHED_IMAGE_HEIGHT);
        }
        
        if($CROP_CENTER == true && ($CROP_LEFT > 0 || $CROP_TOP > 0))
        {
            Throw PHPVC_ERROR::VAR_RAISERROR(new Exception("Cannot process CROP CENTER with fixed CROP position."));
        }
        // ------------------------------------------------------------------------
        
        
        // Actual Function
        // ------------------------------------------------------------------------
        Try
        {
            // CROP_CENTER: Enlarge Image when crop target is too small
            // ......................................................................
            if
            (
                $CROP_CENTER == true && 
                (
                    self::$CACHED_IMAGE_WIDTH < $IMAGE_MAX_SIZE ||
                    self::$CACHED_IMAGE_HEIGHT < $IMAGE_MAX_SIZE
                )
            )
            {
                $IMAGE_WIDTH = self::$CACHED_IMAGE_WIDTH;
                $IMAGE_HEIGHT = self::$CACHED_IMAGE_HEIGHT;
                
                // Width exceeded the max size
                if
                (
                    self::$CACHED_IMAGE_WIDTH < $IMAGE_MAX_SIZE
                )
                {
                    $IMAGE_WIDTH = $IMAGE_MAX_SIZE;
                    
                    if(self::$CACHED_IMAGE_HEIGHT > self::$CACHED_IMAGE_WIDTH)
                    {
                        self::REF_RESIZE
                        (
                            $IMAGE_MAX_SIZE, -1,
                            -1, -1, true
                        );
                        self::REF_REPLACE();
                    }
                    elseif(self::$CACHED_IMAGE_WIDTH == self::$CACHED_IMAGE_HEIGHT)
                    {
                        $IMAGE_HEIGHT = $IMAGE_MAX_SIZE;
                        self::REF_RESIZE
                        (
                            $IMAGE_MAX_SIZE, $IMAGE_MAX_SIZE,
                            -1, -1, false
                        );
                        self::REF_REPLACE();
                    }
                }
                
                // Height exceeded the max size
                if(self::$CACHED_IMAGE_HEIGHT < $IMAGE_MAX_SIZE)
                {
                    $IMAGE_HEIGHT = $IMAGE_MAX_SIZE;
                    
                    if(self::$CACHED_IMAGE_WIDTH > self::$CACHED_IMAGE_HEIGHT)
                    {
                        self::REF_RESIZE
                        (
                            -1, $IMAGE_MAX_SIZE,
                            -1, -1, true
                        );
                        self::REF_REPLACE();
                    }
                    
                    elseif(self::$CACHED_IMAGE_WIDTH == self::$CACHED_IMAGE_HEIGHT)
                    {
                        $IMAGE_WIDTH = $IMAGE_MAX_SIZE;
                        self::REF_RESIZE
                        (
                            $IMAGE_MAX_SIZE, $IMAGE_MAX_SIZE,
                            -1, -1, false
                        );
                        self::REF_REPLACE();
                    }
                }
            }
            
            // CROP_CENTER: Check if image overflows the MAX given size
            // ......................................................................
            else if($CROP_CENTER == true && $IMAGE_MAX_SIZE > 0)
            {
                $IMAGE_WIDTH = self::$CACHED_IMAGE_WIDTH;
                $IMAGE_HEIGHT = self::$CACHED_IMAGE_HEIGHT;    
                
                // Width exceeded the max size
                if
                (
                    self::$CACHED_IMAGE_WIDTH > $IMAGE_MAX_SIZE
                )
                {
                    $IMAGE_WIDTH = $IMAGE_MAX_SIZE;
                    
                    if(self::$CACHED_IMAGE_HEIGHT > self::$CACHED_IMAGE_WIDTH)
                    {
                        self::REF_RESIZE
                        (
                            $IMAGE_WIDTH, -1,
                            -1, -1, true
                        );
                        self::REF_REPLACE();
                    }
                    elseif(self::$CACHED_IMAGE_WIDTH == self::$CACHED_IMAGE_HEIGHT)
                    {
                        $IMAGE_HEIGHT = $IMAGE_MAX_SIZE;
                        self::REF_RESIZE
                        (
                            -1, -1,
                            -1, $IMAGE_WIDTH, true
                        );
                        self::REF_REPLACE();
                    }
                }
                   
                // Height exceeded the max size
                if(self::$CACHED_IMAGE_HEIGHT > $IMAGE_MAX_SIZE)
                {
                    $IMAGE_HEIGHT = $IMAGE_MAX_SIZE;
                    
                    if(self::$CACHED_IMAGE_WIDTH > self::$CACHED_IMAGE_HEIGHT)
                    {
                        self::REF_RESIZE
                        (
                            -1, $IMAGE_HEIGHT,
                            -1, -1, true
                        );
                        self::REF_REPLACE();
                    }
                    
                    elseif(self::$CACHED_IMAGE_WIDTH == self::$CACHED_IMAGE_HEIGHT)
                    {
                        $IMAGE_WIDTH = $IMAGE_MAX_SIZE;
                        self::REF_RESIZE
                        (
                            -1, -1,
                            -1, $IMAGE_HEIGHT, true
                        );
                        self::REF_REPLACE();
                    }
                }
            }
            // ......................................................................
            
            
            // Compute Crop center location
            // ......................................................................
            if($CROP_CENTER == true)
            {
                if($IMAGE_WIDTH < self::$CACHED_IMAGE_WIDTH)
                {
                    $CROP_LEFT = PHPVC_NUM::VAR_STRIP_DECIMAL((self::$CACHED_IMAGE_WIDTH - $IMAGE_WIDTH) / 2);
                }
                
                if($IMAGE_HEIGHT < self::$CACHED_IMAGE_HEIGHT)
                {
                    $CROP_TOP = PHPVC_NUM::VAR_STRIP_DECIMAL((self::$CACHED_IMAGE_HEIGHT - $IMAGE_HEIGHT) / 2);
                }
            }
            // ......................................................................
            
            
            // Check if crop location overflows the actual image size
            // ......................................................................
            if($CROP_LEFT + $IMAGE_WIDTH > self::$CACHED_IMAGE_WIDTH)
            {
                PHPVC_LOG::VAR_COMMENTS('IMAGE_WIDTH', $IMAGE_WIDTH);
                PHPVC_LOG::VAR_COMMENTS('CROP_LEFT', $CROP_LEFT);
                PHPVC_LOG::VAR_COMMENTS('image.width', self::$CACHED_IMAGE_WIDTH);
                
                Throw PHPVC_ERROR::VAR_RAISERROR(new Exception("CROP_LEFT: " . $CROP_LEFT . " exceeded the total image width", false));
            }
            elseif($CROP_TOP + $IMAGE_HEIGHT > self::$CACHED_IMAGE_HEIGHT)
            {
                PHPVC_LOG::VAR_COMMENTS('IMAGE_HEIGHT', $IMAGE_HEIGHT);
                PHPVC_LOG::VAR_COMMENTS('CROP_TOP', $CROP_TOP);
                PHPVC_LOG::VAR_COMMENTS('image.height', self::$CACHED_IMAGE_HEIGHT);
                
                Throw PHPVC_ERROR::VAR_RAISERROR(new Exception("CROP_TOP: " . $CROP_TOP . " exceeded the total image top", false));
            }
            // ......................................................................
            
            
            // Crop image
            // ......................................................................            
            self::$GENERATED_IMAGE = null;
            self::$GENERATED_IMAGE = imagecreatetruecolor($IMAGE_WIDTH, $IMAGE_HEIGHT);

            imagecopyresampled
            (
                self::$GENERATED_IMAGE, self::$CACHED_IMAGE,
                $CROP_LEFT * -1, $CROP_TOP * -1, 0, 0,
                self::$CACHED_IMAGE_WIDTH, self::$CACHED_IMAGE_HEIGHT,
                self::$CACHED_IMAGE_WIDTH, self::$CACHED_IMAGE_HEIGHT
            ); 
            self::REF_REPLACE();
            // ......................................................................
            
        }
        Catch(Exception $ERR)
        {
            PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
            Throw $ERR;
        }
    }
    
    
    /**
     * Resize the currently loaded image. To load image call REF_LOAD() or REF_LOAD_FROM_BASE64().
     * @param unknown $IMAGE_WIDTH New width of image.
     * @param unknown $IMAGE_HEIGHT New height of image.
     * @param unknown $IMAGE_PERCENTAGE New percentile ratio from original size of image.
     * @param unknown $IMAGE_MAX_SIZE Resize image to fit width and height into this max size.
     * @param boolean $KEEP_RATIO
     * @throws Exception
     * @return boolean
     */
    Public Static Function REF_RESIZE
    (
        $IMAGE_WIDTH = -1,
        $IMAGE_HEIGHT = -1,
        $IMAGE_PERCENTAGE = -1,
        $IMAGE_MAX_SIZE = -1,
        $KEEP_RATIO = True
    )
    {
        // Parameter Validation
        // ------------------------------------------------------------------------
        PHPVC_AV::VAR_VALIDATE_NULL(self::$CACHED_IMAGE, "CACHED_IMAGE");
        // ------------------------------------------------------------------------
        
        // Actual Function
        // ------------------------------------------------------------------------
        Try
        {
            // Check if image overflows the MAX given size
            // ......................................................................
            If ($IMAGE_MAX_SIZE > 0)
            {
                // Nothing to change
                If
                (
                    self::$CACHED_IMAGE_WIDTH <= $IMAGE_MAX_SIZE &&
                    self::$CACHED_IMAGE_HEIGHT <= $IMAGE_MAX_SIZE
                    )
                {
                    self::$GENERATED_IMAGE = self::$CACHED_IMAGE;
                    Return True;
                }
                
                // Compute resized size
                If(self::$CACHED_IMAGE_WIDTH > self::$CACHED_IMAGE_HEIGHT)
                {
                    $IMAGE_WIDTH = $IMAGE_MAX_SIZE;
                    $KEEP_RATIO = True;
                }
                
                
                ElseIf(self::$CACHED_IMAGE_WIDTH < self::$CACHED_IMAGE_HEIGHT)
                {
                    $IMAGE_HEIGHT = $IMAGE_MAX_SIZE;
                    $KEEP_RATIO = True;
                }
                
                Else
                {
                    $IMAGE_WIDTH = $IMAGE_MAX_SIZE;
                    $IMAGE_HEIGHT = $IMAGE_MAX_SIZE;
                    $KEEP_RATIO = True;
                }
            }
            // ......................................................................
            
            
            // Compute resized size
            // ......................................................................
            
            // Percentage resize
            If($IMAGE_PERCENTAGE > 0)
            {
                If($IMAGE_PERCENTAGE == 100)
                {
                    self::$GENERATED_IMAGE = self::$CACHED_IMAGE;
                    Return True;
                }
                
                $IMAGE_WIDTH = self::$CACHED_IMAGE_WIDTH * ($IMAGE_PERCENTAGE / 100);
                $IMAGE_HEIGHT = self::$CACHED_IMAGE_HEIGHT * ($IMAGE_PERCENTAGE / 100);
            }
            
            // Keep ratio
            ElseIf($KEEP_RATIO == True)
            {
                
                If
                (
                    $IMAGE_WIDTH > 0 &&
                    self::$CACHED_IMAGE_WIDTH > $IMAGE_WIDTH
                )
                {
                    $IMAGE_HEIGHT =
                    self::$CACHED_IMAGE_HEIGHT -
                    (
                        self::$CACHED_IMAGE_HEIGHT *
                        (
                            (self::$CACHED_IMAGE_WIDTH - $IMAGE_WIDTH) /
                            self::$CACHED_IMAGE_WIDTH
                        )
                    );
                }
                
                
                ElseIf
                (
                    $IMAGE_WIDTH > 0 &&
                    self::$CACHED_IMAGE_WIDTH < $IMAGE_WIDTH
                )
                {
                    $IMAGE_HEIGHT =
                    self::$CACHED_IMAGE_HEIGHT +
                    (
                        self::$CACHED_IMAGE_HEIGHT *
                        (
                            (IMAGE_WIDTH - self::$CACHED_IMAGE_WIDTH) /
                            self::$CACHED_IMAGE_WIDTH
                        )
                    );
                }
                
                
                ElseIf
                (
                    $IMAGE_HEIGHT > 0 &&
                    self::$CACHED_IMAGE_HEIGHT > $IMAGE_HEIGHT
                )
                {
                    $IMAGE_WIDTH =
                    self::$CACHED_IMAGE_WIDTH -
                    (
                        self::$CACHED_IMAGE_WIDTH *
                        (
                            (self::$CACHED_IMAGE_HEIGHT- $IMAGE_HEIGHT) /
                            self::$CACHED_IMAGE_HEIGHT
                        )
                    );
                }
                
                ElseIf
                (
                    $IMAGE_HEIGHT > 0 &&
                    self::$CACHED_IMAGE_HEIGHT< $IMAGE_HEIGHT
                )
                {
                    $IMAGE_WIDTH =
                    self::$CACHED_IMAGE_WIDTH +
                    (
                        self::$CACHED_IMAGE_WIDTH *
                        (
                            ($IMAGE_HEIGHT - self::$CACHED_IMAGE_HEIGHT) /
                            self::$CACHED_IMAGE_HEIGHT
                        )
                    );
                }
                
                Else
                {
                    Throw New Exception("Failed to compute image size into the correct ratio.");
                }
            }
            
            // Fixed Size
            Else
            {
                if($IMAGE_WIDTH < 0)
                {
                    $IMAGE_WIDTH = self::$CACHED_IMAGE_WIDTH;
                }
                if($IMAGE_HEIGHT < 0)
                {
                    $IMAGE_HEIGHT = self::$CACHED_IMAGE_HEIGHT;
                }
            }
            
            // Validate size
            If($IMAGE_WIDTH <= 0 || $IMAGE_HEIGHT <= 0)
            {
                Throw New Exception("Failed to compute image size into the correct size. W:" . $IMAGE_WIDTH . " H:" . $IMAGE_HEIGHT);
            }
            // ......................................................................
            
            
            // Resize image
            // ......................................................................
            self::$GENERATED_IMAGE = null;
            self::$GENERATED_IMAGE = imagecreatetruecolor($IMAGE_WIDTH, $IMAGE_HEIGHT);
            
            imagecopyresampled
            (
                self::$GENERATED_IMAGE, self::$CACHED_IMAGE,
                0, 0, 0, 0,
                $IMAGE_WIDTH, $IMAGE_HEIGHT,
                self::$CACHED_IMAGE_WIDTH, self::$CACHED_IMAGE_HEIGHT
            );  
            // ......................................................................
            
        }
        Catch(Exception $ERR)
        {
            PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
            Throw $ERR;
        }
        // ------------------------------------------------------------------------
    }
	
	
   /**
     * Saves the generated image into the file system
     * @param String $SAVE_PATH
     * @param String $APPLY_EXTENSION <br />Supports AUTO, KEEP, JPG, JPEG, GIF, PNG. If 'AUTO' extension will based on image type of source image. If 'KEEP', keep same image type.<br />
     * @param integer $IMAGE_QUALITY From 1~100, default is 100.
     * @throws Exception
     */
    Public Static Function REF_SAVE($SAVE_PATH, $APPLY_EXTENSION = 'AUTO', $IMAGE_QUALITY = 100)
    {
        // Parameter Validation
        // ------------------------------------------------------------------------
        if(isset(self::$GENERATED_IMAGE) === false)
        {
            Throw PHPVC_ERROR::VAR_RAISERROR(New Exception(PHPVC_ERROR::VAR_ARGUMENT_EXCEPTION_NULL("GENERATED_IMAGE", False)));
        }
        // ------------------------------------------------------------------------
        
        
        // Actual Function
        // ------------------------------------------------------------------------
        Try
        {
            // Initialize
            // ......................................................................
            $FILE_PATH = PHPRC_FSO_FILE::REF_PATH($SAVE_PATH);
            $FILE_NAME = PHPRC_FSO_FILE::REF_NAME($SAVE_PATH, false);
            $FILE_EXTENSION = PHPRC_FSO_FILE::REF_EXTENSION($SAVE_PATH);
            $IMAGE_TYPE = 0;
            
            
            // Apply Auto Extension, or user defined extension type
            // ......................................................................
            if
            (
                (
                    is_bool($APPLY_EXTENSION) &&
                    $APPLY_EXTENSION == true
                ) ||
                PHPVC_STR::VAR_UCASE($APPLY_EXTENSION) == 'AUTO' 
            )
            {
                $SAVE_PATH = $FILE_PATH . '/' . $FILE_NAME . '.' . $FILE_EXTENSION;
                $IMAGE_TYPE = self::$CACHED_IMAGE_TYPE;
            }
            elseif
            (
                (
                    is_bool($APPLY_EXTENSION) &&
                    $APPLY_EXTENSION == false
                ) ||
                PHPVC_STR::VAR_UCASE($APPLY_EXTENSION) == 'KEEP' 
            )
            {
                $IMAGE_TYPE = self::$CACHED_IMAGE_TYPE;
            }
            elseif(PHPVC_STR::VAR_UCASE($APPLY_EXTENSION) == 'GIF')
            {
                $IMAGE_TYPE =  IMAGETYPE_GIF;
            }
            elseif
            (
                PHPVC_STR::VAR_UCASE($APPLY_EXTENSION) == 'JPG' || 
                PHPVC_STR::VAR_UCASE($APPLY_EXTENSION) == 'JPEG'
            )
            {
                $IMAGE_TYPE =  IMAGETYPE_JPEG;
            }
            elseif(PHPVC_STR::VAR_UCASE($APPLY_EXTENSION) == 'PNG')
            {
                $IMAGE_TYPE =  IMAGETYPE_PNG;
            }
            
            
            // Convert and save image
            // ......................................................................
            if($IMAGE_TYPE == IMAGETYPE_GIF)
            {
                imagegif
                (
                    self::$GENERATED_IMAGE,
                    $SAVE_PATH
                );
            }
            elseif($IMAGE_TYPE == IMAGETYPE_JPEG)
            {
                imagejpeg
                (
                    self::$GENERATED_IMAGE,
                    $SAVE_PATH,
                    $IMAGE_QUALITY
                );
            }
            elseif($IMAGE_TYPE == IMAGETYPE_PNG)
            {
                // PNG 
                $IMAGE_QUALITY = (100 - $IMAGE_QUALITY) / 10;
                if($IMAGE_QUALITY >= 9)
                {
                    $IMAGE_QUALITY = 9;
                }
                else if($IMAGE_QUALITY < 0)
                {
                    $IMAGE_QUALITY = 0;
                }
                else 
                {
                    $IMAGE_QUALITY = PHPVC_NUM::VAR_STRIP_DECIMAL($IMAGE_QUALITY);
                }    
                
                imagepng
                (
                    self::$GENERATED_IMAGE,
                    $SAVE_PATH,
                    $IMAGE_QUALITY
                );
            }
            else
            {
                Throw New Exception(PHPVC_ERROR::VAR_ARGUMENT_EXCEPTION_UNSUPPORTED_TYPE('CACHED_IMAGE_TYPE', false));
            }
        }
        Catch(Exception $ERR)
        {
            PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
            Throw $ERR;
        }
        // ------------------------------------------------------------------------
    }
	
	
	/**
	 * Disposes the cache of currently loaded/generated images.
	 * @throws Exception
	 */
	Public Static Function REF_DISPOSE()
	{
		Try
		{
			SELF::$CACHED_IMAGE = null;
			SELF::$GENERATED_IMAGE = null;
			
			SELF::$CACHED_IMAGE_WIDTH = null;
			SELF::$CACHED_IMAGE_HEIGHT = null;
			SELF::$CACHED_IMAGE_TYPE = null;
		}
		Catch(Exception $ERR)
		{
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			Throw $ERR;
		}
	}
	
	/**
	 * Displays the generated image.
	 * @throws Exception
	 */
	Public Static Function REF_PRINT()
	{
		// Parameter Validation
		// ................................................
		if(isset(SELF::$GENERATED_IMAGE) === false)
		{
			Throw PHPVC_ERROR::VAR_RAISERROR(New Exception(PHPVC_ERROR::VAR_ARGUMENT_EXCEPTION_NULL("GENERATED_IMAGE", False)));
		}
		// ................................................
		
		
		// Actual Function
		// ................................................
		Try
		{
			if(SELF::$CACHED_IMAGE_TYPE == IMAGETYPE_GIF)
			{
				Header('Content-Type: image/gif');
				imagegif(SELF::$GENERATED_IMAGE);
			}
			else if(SELF::$CACHED_IMAGE_TYPE == IMAGETYPE_JPEG)
			{
				Header('Content-Type: image/jpeg');
				imagejpeg(SELF::$GENERATED_IMAGE);
			}
			elseif(SELF::$CACHED_IMAGE_TYPE == IMAGETYPE_PNG)
			{
				Header('Content-Type: image/png');
				imagepng(SELF::$GENERATED_IMAGE);
			}
			else
			{
				Throw New Exception(PHPVC_ERROR::VAR_ARGUMENT_EXCEPTION_UNSUPPORTED_TYPE('CACHED_IMAGE_TYPE', false));
			}
			exit;
		}
		Catch(Exception $ERR)
		{
			PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
			Throw $ERR;
		}
		// ................................................
	}
	
	
	/**
	 * Checks if the given file is image or not.
	 * @param String $IMAGE_PATH
	 * @return boolean 
	 */
	Public Static Function REF_IS_IMAGE($IMAGE_PATH)
	{
	    // Parameter Validation
	    // ................................................
	    PHPVC_AV::VAR_VALIDATE_NULL($IMAGE_PATH, "IMAGE_PATH");
	    // ................................................
	    
	    
	    // Actual Function
	    // ................................................
	    Try
	    {
	        // Initialize
	        $IMAGE_INFO = getimagesize($IMAGE_PATH);
	        
	        // Abort if get image size is false
	        if($IMAGE_INFO == false)
	        {
	            return false;
	        }

	        // Legit Image file
	        else 
	        {
	            return true;
	        }
	    }
	    Catch(Exception $ERR)
	    {
	        PHPVC_LOG::VAR_REPORT_ERROR($ERR, 0);
	        PHPRC_IMAGE::REF_DISPOSE();
	        Throw $ERR;
	    }
	    // ................................................
	}
	
}

?>