PHP - Generating thumbnails and adding watermarks - Learning Notes

Keywords: PHP PhpStorm

1. start

Thumbnail function is often used in the process of uploading pictures on websites. Here I have written an Image class for Image processing, which can generate thumbnails and add watermarks.

 

2. How to generate thumbnails

The key to generating thumbnails is how to calculate the scaling ratio.

Here, based on several common changes in the ratio of image to scale and width to height, I come to the conclusion that the algorithm for calculating the ratio of scale is to divide the width of the original image by the width of the new image (thumbnail) and take it as the ratio of scale to see which value is larger:

Scale ratio = Max (new map height / original map height, new map width / original map width)

That is to say:

If ((New Map Height/Original Map Height)> (New Map Width/Original Map Width){

Scale ratio = new map height / original map height;

      }ELSE {

Scale ratio = new width / original width;

     }

Here are the image scaling scenarios of the scenarios and the processing methods:

 e.g 

Scenario 1, where the original image is larger than the new one, the zoom ratio = the width of the new image / the width of the original image:

Scenario 2, where the original image is larger than the new one, b. Scaling ratio = the height of the new image / the height of the original image:

Scenario 3, when the original image is larger than the new one, and the width and height of the new image are equal, that is, the new figure shape is square, then the scaling algorithm above is also applicable.

Scenario 4, if "New Graph Width > Original Graph Width" and "New Graph Height > Original Graph Height", then do not zoom in or enlarge the picture, and keep the original image.

Scenario 5, if "new map width < original map width" and "new map height > = original map height", then set "new map height = original map height" first, and then cut.

Scenario 6, if "new map height < original map height" and "new map width > = original map width", then set "new map width = original map width" first, and then cut.

3. How to add watermarking pictures

It's easy to add watermarking, but I don't think about the complexity here. It's mainly to control the position of the watermarking in the lower right corner of the image and the size of the watermarking in the image. For example, when the size of the target image is close to that of the watermarking image, it is necessary to scale the watermarking image equally before adding the watermarking image.

There are two pictures on the left, the original one on the top, the watermarking one on the bottom, and the new one on the right with watermarking after scaling.

 

4. classes of Graphs

5.PHP code

5.1. Constructor _construct()

In the Image class, except that the constructor _construct() is public, the other functions are private. That is to say, in the function _construct(), the functions of generating thumbnails and adding watermarks are directly completed. If only thumbnails are generated without watermarking, then the parameter $markPath directly in _construct() is set to null.

Among them, "$this - > quality = $quality?$quality: 75;" when controlling the output of JPG images, control the image quality (0-100), the default value is 75;

     /**
     * Image constructor.
     * @param string $imagePath Picture path
     * @param string $markPath Watermarking Picture Path
     * @param int $new_width width
     * @param int $new_height height
     * @param int $quality JPG Output quality of picture lattice
     */
    public function __construct(string $imagePath,
                                string $markPath = null,
                                int $new_width = null,
                                int $new_height = null,
                                int $quality = 75)
    {
        $this->imgPath = $_SERVER['DOCUMENT_ROOT'] . $imagePath;
        $this->waterMarkPath = $markPath;
        $this->newWidth = $new_width ? $new_width : $this->width;
        $this->newHeight = $new_height ? $new_height : $this->height;
        $this->quality = $quality ? $quality : 75;

        list($this->width, $this->height, $this->type) = getimagesize($this->imgPath);
        $this->img = $this->_loadImg($this->imgPath, $this->type);


        //thumb
        $this->_thumb();
        //Adding Watermark Pictures
        if (!empty($this->waterMarkPath)) $this->_addWaterMark();
        //Output pictures
        $this->_outputImg();
    }

Note: Mr. Smith forms a thumbnail and adds a watermarking image to the new image.

 

5.2. Generate thumbnail function _thumb()

     /**
     * Thumbnails (cut in equal proportion according to the width and height of the settings)
     */
    private function _thumb()
    {

        //If the original image itself is smaller than the thumbnail, follow the length and height of the original image.
        if ($this->newWidth > $this->width) $this->newWidth = $this->width;
        if ($this->newHeight > $this->height) $this->newHeight = $this->height;

        //Background image length and height
        $gd_width = $this->newWidth;
        $gd_height = $this->newHeight;

        //If one side of the thumbnail is equal to the width and height of the original graph, the thumbnail is clipped directly.
        if ($gd_width == $this->width || $gd_height == $this->height) {
            $this->newWidth = $this->width;
            $this->newHeight = $this->height;
        } else {

            //Calculate scaling ratio
            $per = 1;

            if (($this->newHeight / $this->height) > ($this->newWidth / $this->width)) {
                $per = $this->newHeight / $this->height;
            } else {
                $per = $this->newWidth / $this->width;
            }

            if ($per < 1) {
                $this->newWidth = $this->width * $per;
                $this->newHeight = $this->height * $per;
            }
        }

        $this->newImg = $this->_CreateImg($gd_width, $gd_height, $this->type);
        imagecopyresampled($this->newImg, $this->img, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->width, $this->height);
    }

The thumbnail function _thumb() is generated and encoded according to the previous analysis.  

5.3. Add watermarking image function _addWaterMark()

     /**
     * Add watermark
     */
    private function _addWaterMark()
    {
        $ratio = 1 / 5; //Watermark scaling ratio

        $Width = imagesx($this->newImg);
        $Height = imagesy($this->newImg);

        $n_width = $Width * $ratio;
        $n_height = $Width * $ratio;

        list($markWidth, $markHeight, $markType) = getimagesize($this->waterMarkPath);

        if ($n_width > $markWidth) $n_width = $markWidth;
        if ($n_height > $markHeight) $n_height = $markHeight;

        $Img = $this->_loadImg($this->waterMarkPath, $markType);
        $Img = $this->_thumb1($Img, $markWidth, $markHeight, $markType, $n_width, $n_height);
        $markWidth = imagesx($Img);
        $markHeight = imagesy($Img);
        imagecopyresampled($this->newImg, $Img, $Width - $markWidth - 10, $Height - $markHeight - 10, 0, 0, $markWidth, $markHeight, $markWidth, $markHeight);
        imagedestroy($Img);
    }

In the watermarked image, a _thumb1() function is used to scale the watermarked image:

    /**
     * Thumbnails (in equal proportions)
     * @param resource $img Image stream
     * @param int $width
     * @param int $height
     * @param int $type
     * @param int $new_width
     * @param int $new_height
     * @return resource
     */
    private function _thumb1($img, $width, $height, $type, $new_width, $new_height)
    {

        if ($width < $height) {
            $new_width = ($new_height / $height) * $width;
        } else {
            $new_height = ($new_width / $width) * $height;
        }

        $newImg = $this->_CreateImg($new_width, $new_height, $type);
        imagecopyresampled($newImg, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
        return $newImg;
    }

5.4. Complete code:

<?php

/**
 * Image processing, generating thumbnails and adding watermarks
 * Created by PhpStorm.
 * User: andy
 * Date: 17-1-3
 * Time: 11:55 a.m.
 */
class Image
{
    //Original graph
    private $imgPath;   //Picture address
    private $width;     //image width
    private $height;    //Picture height
    private $type;      //Picture type
    private $img;       //picture(Image stream)

    //thumbnail
    private $newImg;    //thumbnail(Image stream)
    private $newWidth;
    private $newHeight;

    //Watermarking Path
    private $waterMarkPath;

    //Output image quality,jpg effective
    private $quality;

    /**
     * Image constructor.
     * @param string $imagePath Picture path
     * @param string $markPath Watermarking Picture Path
     * @param int $new_width width
     * @param int $new_height height
     * @param int $quality JPG Output quality of picture lattice
     */
    public function __construct(string $imagePath,
                                string $markPath = null,
                                int $new_width = null,
                                int $new_height = null,
                                int $quality = 75)
    {
        $this->imgPath = $_SERVER['DOCUMENT_ROOT'] . $imagePath;
        $this->waterMarkPath = $markPath;
        $this->newWidth = $new_width ? $new_width : $this->width;
        $this->newHeight = $new_height ? $new_height : $this->height;
        $this->quality = $quality ? $quality : 75;

        list($this->width, $this->height, $this->type) = getimagesize($this->imgPath);
        $this->img = $this->_loadImg($this->imgPath, $this->type);


        //thumb
        $this->_thumb();
        //Adding Watermark Pictures
        if (!empty($this->waterMarkPath)) $this->_addWaterMark();
        //Output pictures
        $this->_outputImg();
    }

    /**
     *Picture output
     */
    private function _outputImg()
    {
        switch ($this->type) {
            case 1: // GIF
                imagegif($this->newImg, $this->imgPath);
                break;
            case 2: // JPG
                if (intval($this->quality) < 0 || intval($this->quality) > 100) $this->quality = 75;
                imagejpeg($this->newImg, $this->imgPath, $this->quality);
                break;
            case 3: // PNG
                imagepng($this->newImg, $this->imgPath);
                break;
        }
        imagedestroy($this->newImg);
        imagedestroy($this->img);
    }

    /**
     * Add watermark
     */
    private function _addWaterMark()
    {
        $ratio = 1 / 5; //Watermark scaling ratio

        $Width = imagesx($this->newImg);
        $Height = imagesy($this->newImg);

        $n_width = $Width * $ratio;
        $n_height = $Width * $ratio;

        list($markWidth, $markHeight, $markType) = getimagesize($this->waterMarkPath);

        if ($n_width > $markWidth) $n_width = $markWidth;
        if ($n_height > $markHeight) $n_height = $markHeight;

        $Img = $this->_loadImg($this->waterMarkPath, $markType);
        $Img = $this->_thumb1($Img, $markWidth, $markHeight, $markType, $n_width, $n_height);
        $markWidth = imagesx($Img);
        $markHeight = imagesy($Img);
        imagecopyresampled($this->newImg, $Img, $Width - $markWidth - 10, $Height - $markHeight - 10, 0, 0, $markWidth, $markHeight, $markWidth, $markHeight);
        imagedestroy($Img);
    }

    /**
     * Thumbnails (cut in equal proportion according to the width and height of the settings)
     */
    private function _thumb()
    {

        //If the original image itself is smaller than the thumbnail, follow the length and height of the original image.
        if ($this->newWidth > $this->width) $this->newWidth = $this->width;
        if ($this->newHeight > $this->height) $this->newHeight = $this->height;

        //Background image length and height
        $gd_width = $this->newWidth;
        $gd_height = $this->newHeight;

        //If one side of the thumbnail is equal to the width and height of the original graph, the thumbnail is clipped directly.
        if ($gd_width == $this->width || $gd_height == $this->height) {
            $this->newWidth = $this->width;
            $this->newHeight = $this->height;
        } else {

            //Calculate scaling ratio
            $per = 1;

            if (($this->newHeight / $this->height) > ($this->newWidth / $this->width)) {
                $per = $this->newHeight / $this->height;
            } else {
                $per = $this->newWidth / $this->width;
            }

            if ($per < 1) {
                $this->newWidth = $this->width * $per;
                $this->newHeight = $this->height * $per;
            }
        }

        $this->newImg = $this->_CreateImg($gd_width, $gd_height, $this->type);
        imagecopyresampled($this->newImg, $this->img, 0, 0, 0, 0, $this->newWidth, $this->newHeight, $this->width, $this->height);
    }


    /**
     * Thumbnails (in equal proportions)
     * @param resource $img Image stream
     * @param int $width
     * @param int $height
     * @param int $type
     * @param int $new_width
     * @param int $new_height
     * @return resource
     */
    private function _thumb1($img, $width, $height, $type, $new_width, $new_height)
    {

        if ($width < $height) {
            $new_width = ($new_height / $height) * $width;
        } else {
            $new_height = ($new_width / $width) * $height;
        }

        $newImg = $this->_CreateImg($new_width, $new_height, $type);
        imagecopyresampled($newImg, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
        return $newImg;
    }

    /**
     * Loading pictures
     * @param string $imgPath
     * @param int $type
     * @return resource
     */
    private function _loadImg($imgPath, $type)
    {
        switch ($type) {
            case 1: // GIF
                $img = imagecreatefromgif($imgPath);
                break;
            case 2: // JPG
                $img = imagecreatefromjpeg($imgPath);
                break;
            case 3: // PNG
                $img = imagecreatefrompng($imgPath);
                break;
            default: //Other types
                Tool::alertBack('Current image type is not supported.' . $type);
                break;
        }
        return $img;
    }

    /**
     * Create a background image
     * @param int $width
     * @param int $height
     * @param int $type
     * @return resource
     */
    private function _CreateImg($width, $height, $type)
    {
        $img = imagecreatetruecolor($width, $height);
        switch ($type) {
            case 3: //png
                imagecolortransparent($img, 0); //Set the background to transparent
                imagealphablending($img, false);
                imagesavealpha($img, true);
                break;
            case 4://gif
                imagecolortransparent($img, 0);
                break;
        }

        return $img;
    }
}
Image.class.php

 

6. call

The call is very simple. After introducing the class, you can directly new and enter the corresponding parameters.

e.g.

new Image($_path, MARK, 400, 200, 100);

7. summary

This Image class can generate thumbnails without black edges, add watermarking images, and scale the watermarking images according to the size of the images. Of course, there is a disadvantage, that is, GIF animation can not be scaled, because it involves frame processing, more trouble.

Posted by DeathStar on Wed, 20 Mar 2019 21:00:27 -0700