PHP plus Nginx to achieve dynamic image cropping scheme

  • 2021-01-22 04:56:21
  • OfStack

A long time ago, I wrote an article about the dynamic clipping scheme of high-performance PHP images. That article uses the implementation of nginx, Cache and rewrite. Of course, with CDN, there is a problem with that scheme, which is that the images are not actually generated, but stored in the cache in the form of binary. If the cache fails, you need to ask php to generate it again. In terms of difference that's what I think for the moment.
Use the spare time, the new static image generation support, support for the picture 3 modes switch, automatically cut the size of the picture in the portal, reduce the server bandwidth, theoretically should also meet the needs of the business, picture cutting using Imagick components.

1.
1, first write a request to the server to generate dynamic picture script, the main picture is the equivalent scaling calculation + cropping.
2, make sure you want to generate url rules, such as http: / / www domain. com www / 300 x 200-1 / test jpg.
3. Cache the browser.
4. End.
2. Dynamic cropping of PHP scripts


/**
 * Author pony_chiang
 *  High performance image cropping scheme 
 *  Need to be php-imagick extension 
 */
ini_set ( "memory_limit", "80M" );

//  Request address such as   http://yourdomain.com/resize.php?site=www&width=300&height=200&mode=2&path=uploadfile/helloworld.png
// nginx Rewrite rules   rewrite ^([^\.]*)/s/(.*)/(\d+)x(\d+)-(\d)/(.*) $1/s/resize.php?site=$2&width=$3&height=$4&mode=$5&path=$6 last;

$path = trim ( $_GET ['path'] );
$mode = intval ( $_GET ['mode'] );
$site = trim ( $_GET ['site'] );
$width = intval ( $_GET ['width'] );
$height = intval ( $_GET ['height'] );

$site_list = array ('www' => '/mnt/webroot/test/' );

$orig_dir = dirname ( __FILE__ );
if (! array_key_exists ( $site, $site_list )) {
    header ( 'HTTP/1.1 400 Bad Request' );
    exit ();
}

if ($mode > 3 || $mode < 0) {
    header ( 'HTTP/1.1 400 Bad Request' );
    exit ();
}

$orig_file = $site_list [$site] . $path;
if (! file_exists ( $orig_file )) {
    header ( 'HTTP/1.1 404 Not Found' );
    exit ();
}

$file_ext = '.' . pathinfo ( $path, PATHINFO_EXTENSION );

$file_name = basename ( $path, $file_ext );
$save_path = "{$orig_dir}/{$site}/{$width}x{$height}-{$mode}/{$path}";
$save_dir = dirname ( $save_path );

if (! file_exists ( $save_dir ))
    wpx_mkdir ( $save_dir );

$target_width = $width;
$target_height = $height;

$new_width = $target_width;
$new_height = $target_height;
$image = new Imagick ( $orig_file );
list ( $orig_width, $orig_height, $type, $attr ) = getimagesize ( $orig_file );

if ($mode == "0") {
    // Scaling the image proportionally 
    $new_height = $orig_height * $new_width / $orig_width;
    if ($new_height > $target_height) {
        $new_width = $orig_width * $target_height / $orig_height;
        $new_height = $target_height;
    }
} else if ($mode == "2") {
    //  Zoom in and crop the image 
    $desired_aspect = $target_width / $target_height;
    $orig_aspect = $orig_width / $orig_height;

    if ($desired_aspect > $orig_aspect) {
        $trim = $orig_height - ($orig_width / $desired_aspect);
        $image->cropImage ( $orig_width, $orig_height - $trim, 0, $trim / 2 );
        error_log ( "HEIGHT TRIM $trim" );
    } else {
        $trim = $orig_width - ($orig_height * $desired_aspect);
        $image->cropImage ( $orig_width - $trim, $orig_height, $trim / 2, 0 );
    }
}

$image->resizeImage ( $new_width, $new_height, imagick::FILTER_LANCZOS, 1 );
$image->writeImage ( $save_path );
header ( 'Content-Type: image/jpeg' );
header ( 'Last-Modified: ' . gmdate ( 'D, d M Y H:i:s' ) . ' GMT' );
echo file_get_contents ( $save_path );
return true;

//  Loop generation directory 
function wpx_mkdir($dir, $mode = 0777) {
    if (is_dir ( $dir ) || @mkdir ( $dir, $mode ))
        return true;
    if (! wpx_mkdir ( dirname ( $dir ), $mode ))
        return false;
    return @mkdir ( $dir, $mode );
}

3. nginx. conf configuration


server {
        listen       80;
        server_name test.yourdomain.com;
        root   /mnt/webroot/test;
        index  index.php;
        expires 30d;

        location /s {
           # Dynamic clipping is called only if the image is not generated 
           if (!-e $request_filename) {
             rewrite ^([^\.]*)/s/(.*)/(\d+)x(\d+)-(\d)/(.*) $1/s/resize.php?site=$2&width=$3&height=$4&mode=$5&path=$6 last;
             break;
           }
        }

        error_page   404 403 402 500 502 503 504  /404.html;
        location = /404.html {
        }

        location ~ \.php$ {
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }

}

ES34en: At the end of this article I would like to highlight one particular point about browser caching. Whether you are generating images from ES35en or using the ES36en cache, add 1 line to your ES37en code
header('Last-Modified: ' .gmdate('D, d M Y H:i:s') . ' GMT' );

10 points to help you with CDN. The effect is that the first time the client visits the file, the http status code is 200, after the refresh status code 1 is 304.


Related articles: