2

In my product catalog, some product images need to have the css attribute object-fit: cover while some need the object-fit: contain:

different ways to fit images

I'd like to detect the white background, possibly on upload (to ease processing when live). I am currently using Imager for transforms, and I would guess that plugin could have some detection feature, but I can't seem to find it.

Reading around a little suggests reading all four corners of the image and determine white bg if all four pixels are white -- but how can I do this? (and how can I do it on file upload?)

Comments for provided solution

Craft CMS has a powerful event system that lets you attach to events and then perform further actions on the entities involved.

I created a site module based on nystudio107's template, and inserted the provided code.

Then I created the field hasWhiteBackground as a lightswitch field, and ran a console command ./craft assets/resave as documented in the Craft CMS 3 docs, to update the lightswitch for existing assets.

I am using imager to transform the images and to create srcset. I use the hasWhiteBackground to do either a fit or crop mode to the resize operation:

{% set image = p.productImage.one()|default(null) %}
{% set transformedImages = craft.imager.transformImage(image, [
    { width: 269 }, 
    { width: 246 },
    { width: 209 }
    ], { 
        ratio: 1/1, 
        position: image.getFocalPoint()|default("50% 50%"),
        mode: image.hasWhiteBackground|default(false) ? 'fit' : 'crop'
    }) 
%} 

I then added the class contain to each image outputted:

 class="{{ image.hasWhiteBackground ? 'contain'}}">

The class simply adds the following css to the image:

.contain {
    object-fit:contain;
}

Here is what the result looks like:

6 products lined up with some using object-fit contain and some cover.

1 Answer 1

2

Interesting problem! I took a stab at this, see if this works for your use case.

It relies on ImageMagick to check for the top left pixel color (0,0) after the image is uploaded (but will also work if you hit resave). (If you want to check the other 3 corners, you'll need more code but this should get you started.)

To use it, you'll need a lightswitch field called hasWhiteBackground on your asset volume (or change the name in the script).

The light switch gets switched to true if the top right corner of the image is white or transparent.

The "magic" is in the getImagePixelColor function.

Event::on(
    \craft\elements\Asset::class,
    \craft\elements\Asset::EVENT_BEFORE_SAVE,
    function(\craft\events\ModelEvent $event) {
            $asset = $event->sender;
            
            
    if ($asset->kind == 'image' ) {
        
        if  ($event->isNew) {
            
            $assetFilePath = $asset->tempFilePath;
        
        } else {
            
            $volumePath = $asset->getVolume()->settings['path'];
            $folderPath = '/' . $asset->getFolder()->path;
            $assetFilePath = Craft::getAlias($volumePath) . $folderPath . $asset->filename;
        
        }
        
    
        $img = new \Imagick($assetFilePath);
        $pixel = $img->getImagePixelColor(1, 1);
        $p = $pixel->getColor();
        
        
        if (($p['r'] == 255 && $p['g'] == 255 && $p['b'] == 255) || ($p['r'] == 0  && $p['g'] == 0 && $p['b'] == 0 && $p['a'] == 0)) {
            $asset->setFieldValue('hasWhiteBackground','1');
        
        }
    }


                
});


2
  • 1
    Great solution. Thanks for showing me how to attach to the save event. I'll update my original question with some additional info that might help the next seeker of white background detection.
    – nitech
    Nov 13, 2020 at 21:18
  • very nice solution! Nov 22, 2020 at 18:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.