Search code examples
phpimage-resizingimagick

Downscaling with php imagick


I'm having trouble limiting the output of a pdf-to-jpg converter using imagick, but I can't seem to find the right solution for only resizing images larger than 16 megapixel.

https://stackoverflow.com/a/6387086/3405380 has the solution I'm looking for, but I can't find the php equivalent of convert -resize '180000@>' screen.jpg (in my case that would be '16000000@>'). I tried $imagick->resizeImage(Imagick::RESOURCETYPE_AREA, 4000 * 4000);, but that just cuts off the conversion instead of resizing.

public static function storeFilePdfToJpg($file) {
    $destinationPath = public_path() . Config::get('my.image_upload_path');
    $filename = str_random(10) . '_' . str_replace('.pdf', '', $file->getClientOriginalName()) . '.jpg';

    $imagick = new Imagick();
    $imagick->setResolution(350,350);
    $imagick->readImage($file->getPathName());
    $imagick->setImageCompression(imagick::COMPRESSION_JPEG);
    $imagick->setImageCompressionQuality(100);
    $imagick->resizeImage(Imagick::RESOURCETYPE_AREA, 4000 * 4000);
    $imagick->writeImages($destinationPath . '/' . $filename, false);
    return Config::get('my.full_image_upload_path') . $filename;
}

Solution

  • The C api for Image Magick doesn't (afaik) expose this functionality, so it isn't possible for the PHP Imagick extension to implement this.

    This is pretty easy to implement in PHP:

    function openImageWithArea(int $desiredArea, string $filename) : Imagick
    {
        $image = new Imagick();
        $dataRead = $image->pingImage($filename);
        if (!$dataRead) {
            throw new \Exception("Failed to ping image of filename $filename");
        }
        $width = $image->getImageWidth();
        $height = $image->getImageHeight();
    
        $area = $width * $height;
        $ratio = $desiredArea / $area;
    
        $desiredWidth = (int)($ratio * $width);
        $desiredHeight = (int)($ratio * $height);
    
        $imagick = new Imagick();
        $imagick->setSize($desiredWidth, $desiredHeight);
        $imagick->readImage($file);
    
        return $imagick;
    }
    

    Should work.