<?php


namespace extcore;


class ImageCrop
{

    protected $file;
    protected $options;
    public function __construct($file = '', $options = [])
    {
        $this->file = trim($file);
        $this->options = $options;
    }

    /**
     * 根据参数裁剪图片
     * @param null|string $savepath
     * @param $opts array
     * @return \think\Response
     */
    public function crop($savepath = null, $opts = [], $output = true)
    {
        $opts = array_merge($this->options, $opts);
        $img = $this->file;
        $imgWidth = isset($opts['w']) ? intval($opts['w']) : 0;
        $imgHeight = isset($opts['h']) ? intval($opts['h']) : 0;
        $imgQuality = isset($opts['q']) ? intval($opts['q']) : 0;
        $imgMode = strtolower(isset($opts['m']) ? trim($opts['m']) : '');

        if (empty($img)) {
            exit();
        }
        if ($imgWidth < 1 && $imgHeight < 1) {
            $imgWidth = config('upload.default_size');
        }
        if ($imgQuality < 1) {
            $imgQuality = config('upload.default_quality');
        }

        $imgData = $this->getImgData($img);

        if ($imgData !== false && !empty($imgData)) {
            $imageinfo = getimagesizefromstring($imgData);
            $image = imagecreatefromstring($imgData);

            $photoWidth = $imageinfo[0];
            $photoHeight = $imageinfo[1];

            if ($photoWidth > 0 && $photoHeight > 0) {
                if ($photoWidth > $imgWidth or $photoHeight > $imgHeight) {
                    $photoScale = $photoWidth / $photoHeight;
                    if ($imgWidth > 0 && $imgHeight > 0) {
                        $imgScale = $imgWidth / $imgHeight;
                    } else {
                        $imgScale = $photoScale;
                    }
                    $clipLeft = 0;
                    $clipTop = 0;
                    if ($photoScale == $imgScale) {
                        if ($imgWidth > 0) {
                            $tempWidth = $imgWidth;
                            $tempHeight = $imgWidth / $imgScale;
                        } else {
                            $tempHeight = $imgHeight;
                            $tempWidth = $imgHeight * $imgScale;
                        }
                    } else {
                        switch ($imgMode) {
                            case "o":
                            case "1":
                            case "outer":
                            case "fill":
                                if ($photoScale > $imgScale) {
                                    $tempHeight = $photoHeight;
                                    $tempWidth = $tempHeight * $imgScale;
                                    $clipLeft = ($photoWidth - $tempWidth) * .5;
                                } else {
                                    $tempWidth = $photoWidth;
                                    $tempHeight = $tempWidth / $imgScale;
                                    $clipTop = ($photoHeight - $tempHeight) * .5;
                                }
                                break;
                            default: // inner lfit
                                if ($photoScale > $imgScale) {
                                    $tempWidth = $imgWidth;
                                    $tempHeight = $imgWidth / $photoScale;
                                } else {
                                    $tempHeight = $imgHeight;
                                    $tempWidth = $imgHeight * $photoScale;
                                }
                        }
                    }

                    if ($clipLeft > 0 || $clipTop > 0) {
                        $newimg = $this->createImage($imgWidth, $imgHeight);
                        imagecopyresampled($newimg, $image, 0, 0, $clipLeft, $clipTop, $imgWidth, $imgHeight, $tempWidth, $tempHeight);
                        //imagecopyresized($newimg, $image, 0, 0, $clipLeft, $clipTop, $imgWidth, $imgHeight, $tempWidth, $tempHeight);
                    } else {
                        $newimg = $this->createImage($tempWidth, $tempHeight);
                        imagecopyresampled($newimg, $image, 0, 0, 0, 0, $tempWidth, $tempHeight, $photoWidth, $photoHeight);
                        //imagecopyresized($newimg, $image, 0, 0, 0, 0, $tempWidth, $tempHeight, $photoWidth, $photoHeight);
                    }
                    imagedestroy($image);

                    return $this->output($newimg, $imageinfo['mime'], $savepath, $imgQuality, $output);
                } else {
                    return $this->output($image, $imageinfo['mime'], $savepath, $imgQuality, $output);
                }
            }
        }
        if (!$output) {
            return false;
        }
        return redirect(ltrim(config('upload.default_img'), '.'));
    }

    private function createImage($width, $height)
    {
        $newimg = imagecreatetruecolor($width, $height);
        imagesavealpha($newimg, true);
        $trans_colour = imagecolorallocatealpha($newimg, 0, 0, 0, 127);
        imagefill($newimg, 0, 0, $trans_colour);
        return $newimg;
    }

    /**
     * 输出图片
     * @param $image
     * @param $mime
     * @param $savepath
     * @param $imgQuality
     * @return \think\Response
     */
    private function output($image, $mime = 'image/jpeg', $savepath = null, $imgQuality = 80, $output = true)
    {
        ob_start();
        switch (strtolower($mime)) {
            case 'image/png':
                imagepng($image, $savepath);
                break;
            case 'image/gif':
                imagegif($image, $savepath);
                break;
            case 'image/webp':
                imagewebp($image, $savepath);
                break;
            default:
                imagejpeg($image, $savepath, $imgQuality);
        }
        $content = ob_get_clean();
        imagedestroy($image);
        if (!$output) {
            return true;
        }
        return response($content, 200, ['Content-Length' => strlen($content)])->contentType($mime);
    }


    /**
     * 获取文件内容
     * @param $img
     * @return bool|string
     */
    private function getImgData($img)
    {
        if (strripos($img, 'http://') !== FALSE or strripos($img, 'https://') !== FALSE) {    //站外图片
            $data = file_get_contents($img);
        } else {    //站内图片
            $file = DOC_ROOT . '/' . $img;
            if (is_file($file)) {
                $data = file_get_contents($file);
            } else {
                return false;
            }
        }
        return $data;
    }
}
