dfactoryplugins / image-watermark

Image Watermark allows you to automatically watermark images uploaded to the WordPress Media Library and bulk watermark previously uploaded images.
MIT License
14 stars 10 forks source link

Problems with Imagick not passing checks #12

Open thartl opened 1 year ago

thartl commented 1 year ago

We run a custom server & app with ImageMagick 3.7. Because of our version, check_imagick() defaults to GD - line 980 in current Image Watermark, version 1.7.3. This is a problem, because GD causes a color shift in the watermarked images. So adjusting the version check would help us.

Aditionally, also in check_imagick(), some of the methods in our version of Imagick / Imagemagic come out camel-cased. array_map('strtolower', get_class_methods('Imagick') resolves that.

Lastly, it looks like the watermark can "pollute" the color space and/or color profiles of the result. This seems to help:

// copy color space from original image to watermark $watermark->transformImageColorspace( $image->getColorspace() );

// remove existing color profiles from the watermark image $watermark->stripImage();

// copy all color profiles from the original image to the watermark $profiles = $image->getImageProfiles('*', false); foreach ($profiles as $profile) { $profileData = $image->getImageProfile($profile); $watermark->profileImage($profile, $profileData); }

I can do a pull request for all that if you are interested.

jingcodeguy commented 3 months ago

In addition to @thartl's description, I am also using 3.7.0 in local development and examing the IW, I found that the checking method get_class_methods() is not actually reliable. In actual instantiation of Imagick class, writeimage and getimage are actually exist. get_class_methods() does not reflect all kinds of methods.

To comprehensively do a deep test, use reflection instead:

$imagick_class = new ReflectionClass('Imagick');
$im_class_method_names = array_map(function($method) {
    return strtolower($method->getName());
}, $imagick_class->getMethods(ReflectionMethod::IS_PUBLIC));

if (!empty(array_diff([
    'clear', 'destroy', 'valid', 'getimage', 'writeimage', 'getimagegeometry', 'getimageformat', 'setimageformat', 'setimagecompression', 'setimagecompressionquality', 'scaleimage'
], $im_class_method_names)))
    return false;