PHP cuts the image according to the custom size, and adaptively scales the crop region

cause

Mikusa's blog homepage thumbnail is too large, affecting the loading speed. I suggest that he write a thumbnail clipping method to optimize the loading speed when the original image is not needed. He said he wouldn't, so I wrote. After writing, he combined with his typecho theme and published this article.
 dialogue

principle

At each call, judge whether the cache file corresponding to the picture exists. If it exists, return the picture address directly. If it does not exist, cut a picture and save it. (This principle is derived from the theme of Bingo Blog Beginning)

Program difficulties

Due to the different proportions of pictures, how to select the clipping region needs careful consideration. If you start cutting from the (0,0) position, you may not be able to highlight the focus of the picture. In addition, if the cutting position is a fixed position, it may be left blank or black.

A better method is to take the width of the actual picture as the clipping width when the width/height ratio of the target size is larger than the actual ratio, and the clipping height is calculated according to the target size. At this time, the abscissa of the clipping starting position can be selected as (actual height - the height needed for clipping)/2, and the ordinate can be selected as 0, which can ensure that the clipping area is the image center, It also contains the largest image range within the target size scale. The same is true when the width/height ratio of the target size is smaller than the actual ratio.

Scaling and clipping uses the imagecopyresampled method. When I first used it, I checked Baidu. Later, I found that many people's detailed explanations of parameters were not correct at all, which also led me to waste a long time. Then I checked the official documents to understand the meaning of these parameters.
 imagecopyresampled

 imagecopyresampled ( resource $dst_image ,  resource $src_image , int $dst_x , int $dst_y , int $src_x , int $src_y , int $dst_w , int $dst_h , int $src_w , int $src_h ) #Parameter Details: //$dst_image: the target image. Save the cropped image here. //$src_imag: source image, the trimmed source image. //$dst_x and $dst_y: target point, a point on the target image, from which to fill in the trimmed information. //$src_x and $src_y: source point, a point on the source image, from which to start sampling. //$dst_w and $dst_h: in an area of the target image, the obtained sampling information will be filled into this rectangle. //$src_w and $src_h: an area range on the source image. This rectangle is a sampling area, and its contents will be filled into the dst rectangle.

The code excerpts in this section are as follows:

 $Des_scale = $imgWidth / $imgHeight; // Target zoom $Origin_scale = $x / $y; // Actual zoom If ($Origin_scale>$Des_scale)//Compared with the target scale, the width of the original size is larger { $thumbh = $y; // Cut based on 100% height. $thumbw = $thumbh * $Des_scale; // Width corresponding to 100% height $desCutPos_x = abs($thumbw - $x) / 2; // Cutting position $desCutPos_y = 0;             } else { $thumbw = $x; $thumbh = $thumbw / $Des_scale; $desCutPos_x = 0; $desCutPos_y = abs($thumbh - $y) / 2; }

Complete code and code file download

Click Download

 <? php /** *Name: PHP Image Cutting *Description: Graphic cutting tool class that can be used for thumbnail cutting, etc * Version: 1.0.1 *Author: Hare | AT | Zimiao haunts * Author URI:  https://www.azimiao.com */ #Typecho Get Website Link //ZMImgClip::$siteUrl = Helper::options()->siteUrl; #Test code ZMImgClip::$siteUrl = " https://localhost:8080/ "; echo ZMImgClip::GetInstance()->ClipImage("./222.jpg",100,150,"local"); echo "\r\n"; echo ZMImgClip::GetInstance()->ClipImage("./222.jpg"); echo "\r\n"; echo ZMImgClip::GetInstance()->ClipImage("./111.png",0,0); #End test code //o0o00o00oo0o0oo00o0 class ZMImgClip { //Object private static $imgCliper = null; //Default cutting size Private static $imgWidth=300;//Width Private static $imgHeight=300;//Height //Picture cache folder private static $tempCachePath = "usr/Temp/img/"; //Thumbnail cache folder (under the picture cache folder) private static $imgPath = "smImg/"; //Error image (if the image address provided is incorrect, return this address) private static $imgErrorPath = "//www.himiku.com/usr/themes/Yodu/images/load.gif"; //Website URL If the URL obtained in line 14 is incorrect, comment on line 14 and fill in the correct URL here. public static $siteUrl = ""; /** *Get Object */ public static function GetInstance() { if (ZMImgClip::$imgCliper == null) { ZMImgClip::$imgCliper = new ZMImgClip(); } return ZMImgClip::$imgCliper; } /** *Get Path */ private function GetImgPath($fileName = "", $type = "folder") { $url = ""; switch ($type) { default: case 'local': $url .=  ZMImgClip::$tempCachePath; $url .=  ZMImgClip::$imgPath; $url .= $ fileName; break; case "url": $url .=  ZMImgClip::$siteUrl; $url .=  ZMImgClip::$tempCachePath; $url .=  ZMImgClip::$imgPath; $url .= $ fileName; break; case "folder": $url .=  ZMImgClip::$tempCachePath; $url .=  ZMImgClip::$imgPath; break; } return $url; } /** *Get the cache image file name */ private function GetImgName($imgPath, $width, $height) { $name = ""; $name .=  md5($imgPath); $name .=  "-{$width}-{$height}.jpg"; return $name; } /** *Upload to Qiniu */ private function FileUpToQiNiu($localPath,$auth){ //TODO  } /** *Crop Picture *$imgPath: image path *$imgWidth: crop width *$imgHeight: Crop height *$returnType: return address type */ public function ClipImage($imgPath = "", $imgWidth = 0, $imgHeight = 0,$returnType = "url") { if ($imgPath == "" || $imgPath == null) { return ZMImgClip::$imgErrorPath; } if ($imgWidth == 0 || $imgHeight == 0) { if (ZMImgClip::$imgWidth == 0 || ZMImgClip::$imgHeight == 0) { return $imgPath; } else { $imgWidth = ZMImgClip::$imgWidth; $imgHeight = ZMImgClip::$imgHeight; } } $file_name = $this->GetImgName($imgPath, $imgWidth, $imgHeight); $img_temp_path = $this->GetImgPath("", "folder"); $file_path = $this->GetImgPath($file_name, "local"); if (is_file($file_path)) { return $this->GetImgPath($file_name, $returnType); } $imgstream = file_get_contents($imgPath); if (!$ imgstream) { return ZMImgClip::$imgErrorPath; } //Read Picture $imgData = imagecreatefromstring($imgstream); $x = imagesx($imgData); // Get the width of the picture $y = imagesy($imgData); // Get the height of the picture if ($x <= $imgWidth || $y <= $imgHeight) { imagedestroy($imgData); return $imgPath; } //Calculate zoom factor $Des_scale = $imgWidth / $imgHeight; // Target zoom $Origin_scale = $x / $y; // Actual zoom If ($Origin_scale>$Des_scale)//Compared with the target scale, the width of the original size is larger { $thumbh = $y; // Cut based on 100% height. $thumbw = $thumbh * $Des_scale; // Width corresponding to 100% height $desCutPos_x = abs($thumbw - $x) / 2; // Cutting position $desCutPos_y = 0;             } else { $thumbw = $x; $thumbh = $thumbw / $Des_scale; $desCutPos_x = 0; $desCutPos_y = abs($thumbh - $y) / 2; } if (function_exists("imagecreatetruecolor")) { $desImgData = imagecreatetruecolor($imgWidth, $imgHeight);             } else { $desImgData = imagecreate($imgWidth, $imgHeight); } if (! imageCopyreSampled($desImgData, $imgData, 0, 0, $desCutPos_x, $desCutPos_y, $imgWidth, $imgHeight, $thumbw, $thumbh)) { imagedestroy($imgData); imagedestroy($desImgData); return $imgPath; } //Save if (! is_dir($img_temp_path)) { mkdir($img_temp_path, 0755, true); } if (! imagejpeg($desImgData, $file_path)) { imagedestroy($imgData); imagedestroy($desImgData); return $imgPath; } if(false){ return $this->FileUpToQiNiu("",""); } imagedestroy($imgData); imagedestroy($desImgData); return $this->GetImgPath($file_name,$returnType); } } ?>

effect

After downloading the file I provided and executing the code, you can get the image that has been cut. The console outputs the image address.
 imagecopyresampled

Its application can be seen in the small thumbnail of mikusa blog home page.

Zimiao haunting blog (azimiao. com) All rights reserved. Please note the link when reprinting: https://www.azimiao.com/4130.html
Welcome to the Zimiao haunting blog exchange group: three hundred and thirteen million seven hundred and thirty-two thousand

Comment

*

*

Comment area

  1. mikusa 08-30 23:30 reply

    The hydrology of Zimiao and mine (there should be a picture contrast here

  2. Panda A 08-31 10:16 reply

    I remember that Qiniuyun can cut the image for you and change the size. Am I wrong?
    However, CDN needs money, but it is still economical~

    • hare 08-31 17:24 reply

      Well, Qiniu can, but our starting point is different. The idea of this article is to default to the local server as the most reliable storage location, which can be cut and uploaded by yourself. When the connection fails to reach 7N, the local image can still be cropped.

  3. littleplus 09-01 01:05 reply

    getInstance, At a glance, it's JAVA who wrote too much. Wake up, this is porn.

    The function name should also be the same as the variable name. Is the first word lowercase

    • hare 09-01 06:14 reply

      There is no rule on capitalization. It depends on personal habits. Some people also like to underline the object method.

  4. WeiCN 11-18 16:12 reply

    I choose to use various public cloud services for processing, such as shooting cloud again, Tencent Cloud # Funny