TransWikia.com

How to detect white background

Craft CMS Asked on March 31, 2021

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.

One Answer

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(
    craftelementsAsset::class,
    craftelementsAsset::EVENT_BEFORE_SAVE,
    function(crafteventsModelEvent $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');
        
        }
    }


                
});


Correct answer by RitterKnight on March 31, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP