<?php
/*
 Modified from original source of TimThumb script created by Tim McDaniels and
Darren Hoyt
 Original licence reproduced below
 */

/*
 TimThumb script created by Ben Gillbanks, originally created by Tim McDaniels
and Darren Hoyt
 http://code.google.com/p/timthumb/

 GNU General Public License, version 2
 http://www.gnu.org/licenses/old-licenses/gpl-2.0.html

 Examples and documentation available on the project homepage
 http://www.binarymoon.co.uk/projects/timthumb/
 */

//if ( !defined('K_COUCH_DIR') ) die(); // cannot be loaded directly

function k_resize_image($src, $dest = 0, $new_width = 0, $new_height = 0, $zoom_crop = 1, $enforce_max = 0, $quality = 95, $crop_position = 'middle', $check_thumb_exists = 0) {

    if (!isset($zoom_crop)) {
        $zoom_crop = 1;
    }

    if (!isset($enforce_max)) {
        $enforce_max = 0;
    }

    if (!isset($quality)) {
        $quality = 80;
    }

    if (!isset($crop_position)) {
        $crop_position = 'middle';
    }

    if (!isset($check_thumb_exists)) {
        $check_thumb_exists = 0;
    }

    global $FUNCS;

    // check to see if the GD function exists
    if (!function_exists('imagecreatetruecolor')) {
        return displayError('GD Library Error: imagecreatetruecolor does not exist - please contact your webhost and ask them to install the GD library');
    }

    // check to see if the exec function exists
    if (!function_exists('exec')) {
        return displayError('The exec function does not exist');
    }

    if (trim($src) == '') {
        return displayError('Source image not set');
    }

    // get mime type of src
    $mime_type = mime_type($src);

    ini_set('memory_limit', IMAGE_RESIZE_MEMORY_LIMIT);

    // make sure that the src is gif/jpg/png
    if (!valid_src_mime_type($mime_type)) {
        return displayError('Invalid src mime type: ' . $mime_type);
    }

    $gravity = 'center';

    $cmp_x = 1;
    $cmp_y = 1;
    
    if (strlen($src) && file_exists($src)) {

        // open the existing image
        //echo 'foobar0';
        $image = open_image($mime_type, $src);
        //echo 'foobar';
        if ($image === false) {
            return displayError('Unable to open image : ' . $src);
        }

        // get original width and height
        $width = imagesx($image);
        $height = imagesy($image);

        imageDestroy($image);

        // generate new w/h if not provided
        if ($new_width && !$new_height) {
            $new_height = $height * ($new_width / $width);
        } elseif ($new_height && !$new_width) {
            $new_width = $width * ($new_height / $height);
        } elseif (!$new_width && !$new_height) {
            $new_width = $width;
            $new_height = $height;
        }

        // if new dimensions cannot exceed certain values
        if ($enforce_max) {

            // the supplied width and height were actually the max permissible
            // values
            $max_width = $new_width;
            $max_height = $new_height;

            // make the new values the same as that of the source image
            $new_width = $width;
            $new_height = $height;

            // if new dimensions already within bounds (and this not a thumbnail
            // that we are creating), return
            if ($dest && ($new_width <= $max_width) && ($new_height <= $max_height)) {
                return;
            }

            if ($new_width > $max_width) {
                if (!$zoom_crop) {
                    $ratio = (float)($max_width / $new_width);
                    $new_width = ((int)($new_width * $ratio));
                    $new_height = ((int)($new_height * $ratio));
                } else {
                    $new_width = $max_width;
                }
            }

            // if new height still overshoots maximum value
            if ($new_height > $max_height) {
                if (!$zoom_crop) {
                    $ratio = (float)($max_height / $new_height);
                    $new_width = ((int)($new_width * $ratio));
                    $new_height = ((int)($new_height * $ratio));
                } else {
                    $new_height = $max_height;
                }
            }
        }

        // create filename if not provided one (happens only for thumbnails)
        $thumb_name = "";
        if (!$dest) {
            $path_parts = $FUNCS->pathinfo($src);
            $thumb_name = $path_parts['filename'] . '-' . round($new_width) . 'x' . round($new_height) . '.' . $path_parts['extension'];
            $thumbnail = $path_parts['dirname'] . '/' . $thumb_name;
            if ($check_thumb_exists && file_exists($thumbnail)) {
                return $thumb_name;
            }
        }

        if ($zoom_crop) {

            $cmp_x = $width / $new_width;
            $cmp_y = $height / $new_height;

            // if new dimensions equal to the original (and this not a thumbnail
            // that we are creating), return
            /*
             if( $dest && ($cmp_x==1) && ($cmp_y==1) ){
             echo 'XXX';
             return;
             } else {
             echo 'YYY';
             }*/


            if ($crop_position == "top_left" || $crop_position == "tl" || $crop_position == "northwest") {

                $gravity = 'northwest';

            } elseif ($crop_position == "top_center" || $crop_position == "tc" || $crop_position == "north") {

                $gravity = 'north';

            } elseif ($crop_position == "top_right" || $crop_position == "tr" || $crop_position == "northeast") {

                $gravity = 'northeast';

            } elseif ($crop_position == "middle_left" || $crop_position == "cl" || $crop_position == "west") {

                $gravity = 'west';

            } elseif ($crop_position == "middle" || $crop_position == "c" || $crop_position == "center") {

                $gravity = 'center';

            } elseif ($crop_position == "middle_right" || $crop_position == "cr" || $crop_position == "east") {

                $gravity = 'east';

            } elseif ($crop_position == "bottom_left" || $crop_position == "bl" || $crop_position == "southwest") {

                $gravity = 'southwest';

            } elseif ($crop_position == "bottom_center" || $crop_position == "bottom" || $crop_position == "b" || $crop_position == "south") {

                $gravity = 'south';

            } elseif ($crop_position == "bottom_right" || $crop_position == "br" || $crop_position == "southeast") {

                $gravity = 'southeast';

            }
            /*
             switch( $crop_position ){

             case 'top_left':
             $gravity = 'northwest';
             break;
             case 'tl':
             $gravity = 'northwest';
             break;
             case 'top_center':
             $gravity = 'north';
             break;
             case 'tc':
             $gravity = 'north';
             break;
             case 'top_right':
             $gravity = 'northeast';
             break;
             case 'middle_left':
             $gravity = 'west';
             break;
             case 'middle':
             $gravity = 'center';
             break;
             case 'middle_right':
             $gravity = 'east';
             break;
             case 'bottom_left':
             $gravity = 'southwest';
             break;
             case 'bottom_center':
             $gravity = 'south';
             break;
             case 'bottom_right':
             $gravity = 'southeast';
             break;
             }
             */
        }

        if (!$dest) {
            $dest = $thumbnail;
        }

        // output image to browser based on mime type
        save_image($mime_type, $src, $dest, $new_width, $new_height, $zoom_crop, $quality, $gravity, $cmp_x, $cmp_y);

        return $thumb_name;
    } else {
        if (strlen($src)) {
            return displayError("image " . $src . " not found");
        } else {
            return displayError("no source specified");
        }
    }
    return;
}

/*
 save image
 */
function save_image($mime_type, $src, $dest, $new_width, $new_height, $zoom_crop, $quality, $gravity, $cmp_x, $cmp_y) {

    if (@touch($dest)) {

        // give 666 permissions so that the developer can overwrite web server
        // user
        @chmod($dest, 0o666);

        switch ($mime_type) {
            case 'image/jpeg' :
                $format = "jpg";
                break;
            case 'image/png' :
                $format = "png";
                break;
            case 'image/gif' :
                $format = "gif";
                break;
            case 'image/bmp' :
                $format = "bmp";
                break;
            default :
                $format = "gif";
                break;
        }

        $resize = ($cmp_x > $cmp_y) ? "x{$new_height}" : "{$new_width}";
        $crop = ($zoom_crop) ? "{$resize} -gravity {$gravity} -extent {$new_width}x{$new_height}!" : "{$new_width}x{$new_height}!";

        if ($mime_type == 'image/gif') {

            $command = IMAGE_CONVERT . " convert {$src} -coalesce -repage 0x0 -resize {$crop} {$dest}";

        } else {

            $trans = ($mime_type == 'image/png') ? " -background none" : "";
            $jpg = ($mime_type == 'image/jpeg') ? " -compress JPEG -define jpeg:optimize-coding=true -quality {$quality}%" : "";

            // limits in bytes: 160mb and 128mb
            $command = IMAGE_CONVERT . " -format {$format}{$trans} {$src} -thumbnail {$crop}{$jpg} {$dest}";
        }

        exec($command);

    }

}

/*
 open image
 */
function open_image($mime_type, $src) {
    $mime_type = strtolower($mime_type);
    if (stristr($mime_type, 'gif')) {
        $image = @imagecreatefromgif($src);
    } elseif (stristr($mime_type, 'jpeg')) {
        @ini_set('gd.jpeg_ignore_warning', 1);
        $image = @imagecreatefromjpeg($src);
    } elseif (stristr($mime_type, 'png')) {
        $image = @imagecreatefrompng($src);
    } elseif (stristr($mime_type, 'bmp')) {
        //echo 'foobar01';
        $image = @imagecreatefrombmp($src);
    }
    return $image;
}

/*
 determine the file mime type
 */
function mime_type($file) {

    if (stristr(PHP_OS, 'WIN')) {
        $os = 'WIN';
    } else {
        $os = PHP_OS;
    }

    $mime_type = '';
    if (function_exists('mime_content_type')) {
        $mime_type = @mime_content_type($file);
    }

    // use PECL fileinfo to determine mime type
    if (!valid_src_mime_type($mime_type)) {
        if (function_exists('finfo_open')) {
            $finfo = @finfo_open(FILEINFO_MIME);
            if ($finfo != '') {
                $mime_type = finfo_file($finfo, $file);
                finfo_close($finfo);
            }
        }
    }

    // try to determine mime type by using unix file command
    // this should not be executed on windows
    if (!valid_src_mime_type($mime_type) && $os != "WIN") {
        if (preg_match("/FREEBSD|LINUX/", $os)) {
            $mime_type = trim(@shell_exec('file -bi ' . escapeshellarg($file)));
        }
    }

    // use file's extension to determine mime type
    if (!valid_src_mime_type($mime_type)) {
        // set defaults
        $mime_type = 'image/png';
        // file details
        $fileDetails = pathinfo($file);
        $ext = strtolower($fileDetails["extension"]);
        // mime types
        $types = [
            'jpg' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
            'png' => 'image/png',
            'gif' => 'image/gif',
            'bmp' => 'image/bmp'
        ];

        if (strlen($ext) && strlen($types[$ext])) {
            $mime_type = $types[$ext];
        }
    }
    return $mime_type;
}

/*
 check if the mime type is valid
 */
function valid_src_mime_type($mime_type) {
    if (preg_match("/jpg|jpeg|gif|png|bmp/i", $mime_type)) {
        return true;
    }
    return false;
}

/*
 check if the url is valid
 */
function valid_extension($ext) {
    if (preg_match("/jpg|jpeg|png|gif|bmp/i", $ext)) {
        return true;
    } else {
        return false;
    }
}

/*
 generic error message
 */
function displayError($errorString = '') {
    echo $errorString;
    /*
     global $FUNCS;
     return $FUNCS->raise_error( $errorString );
     */
}

if (!function_exists("imagecreatefrombmp")) {
    function imagecreatefrombmp($p_sFile) {

        // 10min
        if (!ini_set('max_execution_time', 600)) {
            //echo 'max_execution_time change failed<br />';
        }

        set_time_limit(600);

        //    Load the image into a string
        $file = fopen($p_sFile, "rb");
        $read = fread($file, 10);
        while (!feof($file) && ($read <> ""))
            $read .= fread($file, 1024);

        $temp = unpack("H*", $read);
        $hex = $temp[1];
        $header = substr($hex, 0, 108);

        //    Process the header
        //    Structure: http://www.fastgraph.com/help/bmp_header_format.html
        if (substr($header, 0, 4) == "424d") {
            //    Cut it in parts of 2 bytes
            $header_parts = str_split($header, 2);

            //    Get the width        4 bytes
            $width = hexdec($header_parts[19] . $header_parts[18]);

            //    Get the height        4 bytes
            $height = hexdec($header_parts[23] . $header_parts[22]);

            //    Unset the header params
            unset($header_parts);
        }

        //    Define starting X and Y
        $x = 0;
        $y = 1;

        //    Create newimage
        $image = imagecreatetruecolor($width, $height);

        //    Grab the body from the image
        $body = substr($hex, 108);

        //    Calculate if padding at the end-line is needed
        //    Divided by two to keep overview.
        //    1 byte = 2 HEX-chars
        $body_size = (strlen($body) / 2);
        $header_size = ($width * $height);

        //    Use end-line padding? Only when needed
        $usePadding = ($body_size > ($header_size * 3) + 4);

        //    Using a for-loop with index-calculation instaid of str_split to
        // avoid large memory consumption
        //    Calculate the next DWORD-position in the body
        for ($i = 0; $i < $body_size; $i += 3) {
            //    Calculate line-ending and padding
            if ($x >= $width) {
                //    If padding needed, ignore image-padding
                //    Shift i to the ending of the current 32-bit-block
                if ($usePadding)
                    $i += $width % 4;

                //    Reset horizontal position
                $x = 0;

                //    Raise the height-position (bottom-up)
                $y++;

                //    Reached the image-height? Break the for-loop
                if ($y > $height)
                    break;
            }

            //    Calculation of the RGB-pixel (defined as BGR in image-data)
            //    Define $i_pos as absolute position in the body
            $i_pos = $i * 2;
            $r = hexdec($body[$i_pos + 4] . $body[$i_pos + 5]);
            $g = hexdec($body[$i_pos + 2] . $body[$i_pos + 3]);
            $b = hexdec($body[$i_pos] . $body[$i_pos + 1]);

            //    Calculate and draw the pixel
            $color = imagecolorallocate($image, $r, $g, $b);
            imagesetpixel($image, $x, $height - $y, $color);

            //    Raise the horizontal position
            $x++;
        }

        //    Unset the body / free the memory
        unset($body);

        //    Return image-object
        return $image;
    }

}
