Home  >  Article  >  Backend Development  >  Detailed explanation of PHP thumbnail generation and image watermark creation

Detailed explanation of PHP thumbnail generation and image watermark creation

墨辰丷
墨辰丷Original
2018-05-26 16:34:211767browse

This article mainly introduces the process of PHP thumbnail generation and image watermark production in detail. PHP implements the steps related to watermark addition and thumbnail generation. It has certain reference value. Interested friends can refer to it

1. Start

In the process of uploading pictures on the website, the thumbnail function is often used. Here I wrote 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 zoom ratio.

Here, based on the image scaling and several common changes in width and height, I came up with an algorithm for calculating the scaling ratio: use the width and height of the new image (i.e. thumbnail) and divide it by the original image respectively. Width and height, whichever value is larger will be used as the scaling ratio:

Zoom ratio = Max ({Height of new image / Height of original image, Width of new image / Width of original image})

That is:

If ( (Height of new image / Height of original image) > (Width of new image / Width of original image) ) {

## Scaling ratio = New image height / Original image height;

}ELSE {

Zoom ratio = New image width/Original image width;

}

Listed here are the picture scaling scenarios and processing methods:

e.g

Scenario 1, the original image is larger than the new image, scaling ratio = new image width / original image width:

Scenario 2, the original image is larger than the new image , b. Scaling ratio = New picture height / Original picture height:

Scenario 3: The original picture is larger than the new picture, and the width and height of the new picture are equal, that is, the new picture The shape of the graph is square, so the scaling algorithm above is also applicable.

Scene 4, if "new image width >= original image width" and "new image height >= original image height", then the image will not be scaled or enlarged, and the original image will be maintained.

Scenario 5, if "new image width 43043daa1430692233b121aff1b8ed16quality = $quality ? $quality : 75;" controls the image quality (0-100) when the output is a JPG image, and the default value is 75;

  /**
   * Image constructor.
   * @param string $imagePath 图片路径
   * @param string $markPath 水印图片路径
   * @param int $new_width 缩略图宽度
   * @param int $new_height 缩略图高度
   * @param int $quality JPG图片格输出质量
   */
  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);


    //生成缩略图
    $this->_thumb();
    //添加水印图片
    if (!empty($this->waterMarkPath)) $this->_addWaterMark();
    //输出图片
    $this->_outputImg();
  }

 Note: 先生成缩略图,再在新图上添加水印 图片。 

5.2. 生成缩略图函数_thumb()

   /**
   * 缩略图(按等比例,根据设置的宽度和高度进行裁剪)
   */
  private function _thumb()
  {

    //如果原图本身小于缩略图,按原图长高
    if ($this->newWidth > $this->width) $this->newWidth = $this->width;
    if ($this->newHeight > $this->height) $this->newHeight = $this->height;

    //背景图长高
    $gd_width = $this->newWidth;
    $gd_height = $this->newHeight;

    //如果缩略图宽高,其中有一边等于原图的宽高,就直接裁剪
    if ($gd_width == $this->width || $gd_height == $this->height) {
      $this->newWidth = $this->width;
      $this->newHeight = $this->height;
    } else {

      //计算缩放比率
      $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);
  }

生成缩略图函数_thumb() ,是按照前面的分析来进行编码。 

5.3. 添加水印图片函数 _addWaterMark()    

   /**
   * 添加水印
   */
  private function _addWaterMark()
  {
    $ratio = 1 / 5; //水印缩放比率

    $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);
  }

在添加水印图片中,用到一个_thumb1()函数来缩放水印图片:

  /**
   * 缩略图(按等比例)
   * @param resource $img 图像流
   * @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. 完整代码:

<?php

/**
 * 图片处理,生成缩略图和添加水印图片
 * Created by PhpStorm.
 * User: andy
 * Date: 17-1-3
 * Time: 上午11:55
 */
class Image
{
 //原图
 private $imgPath; //图片地址
 private $width;  //图片宽度
 private $height; //图片高度
 private $type;  //图片类型
 private $img;  //图片(图像流)

 //缩略图
 private $newImg; //缩略图(图像流)
 private $newWidth;
 private $newHeight;

 //水印图路径
 private $waterMarkPath;

 //输出图像质量,jpg有效
 private $quality;

 /**
  * Image constructor.
  * @param string $imagePath 图片路径
  * @param string $markPath 水印图片路径
  * @param int $new_width 缩略图宽度
  * @param int $new_height 缩略图高度
  * @param int $quality JPG图片格输出质量
  */
 public function __construct(string $imagePath,
        string $markPath = null,
        int $new_width = null,
        int $new_height = null,
        int $quality = 75)
 {
  $this->imgPath = $_SERVER[&#39;DOCUMENT_ROOT&#39;] . $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);


  //生成缩略图
  $this->_thumb();
  //添加水印图片
  if (!empty($this->waterMarkPath)) $this->_addWaterMark();
  //输出图片
  $this->_outputImg();
 }

 /**
  *图片输出
  */
 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);
 }

 /**
  * 添加水印
  */
 private function _addWaterMark()
 {
  $ratio = 1 / 5; //水印缩放比率

  $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);
 }

 /**
  * 缩略图(按等比例,根据设置的宽度和高度进行裁剪)
  */
 private function _thumb()
 {

  //如果原图本身小于缩略图,按原图长高
  if ($this->newWidth > $this->width) $this->newWidth = $this->width;
  if ($this->newHeight > $this->height) $this->newHeight = $this->height;

  //背景图长高
  $gd_width = $this->newWidth;
  $gd_height = $this->newHeight;

  //如果缩略图宽高,其中有一边等于原图的宽高,就直接裁剪
  if ($gd_width == $this->width || $gd_height == $this->height) {
   $this->newWidth = $this->width;
   $this->newHeight = $this->height;
  } else {

   //计算缩放比率
   $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);
 }


 /**
  * 缩略图(按等比例)
  * @param resource $img 图像流
  * @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;
 }

 /**
  * 加载图片
  * @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: //其他类型
    Tool::alertBack(&#39;不支持当前图片类型.&#39; . $type);
    break;
  }
  return $img;
 }

 /**
  * 创建一个背景图像
  * @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); //设置背景为透明的
    imagealphablending($img, false);
    imagesavealpha($img, true);
    break;
   case 4://gif
    imagecolortransparent($img, 0);
    break;
  }

  return $img;
 }
}

6.调用

调用非常简单,在引入类后,直接new 并输入对应参数即可:

e.g.

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

7.小结
这个Image 类能够生成缩略图,不出现黑边,添加水印图,能根据图片的大小缩放水印图。当然有个缺点,就是不能缩放GIF的动画,因为涉及到帧的处理,比较麻烦。

以上就是本文的全部内容,希望对大家的学习有所帮助。


相关推荐:

PHP实现水印类,支持添加图片、文字、填充颜色区域

thinkPHP框架实现图像裁剪、缩放、加水印的方法详解

PHP实现随机生成水印图片功能的方法

The above is the detailed content of Detailed explanation of PHP thumbnail generation and image watermark creation. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn