Check predominant color and image fill percentage

Asked

Viewed 82 times

0

In a project I’m working on, the need arose to check if it’s an image upload is actually valid or a totally random image. The idea would be to verify what would be the predominant color and what would be the percentage of this starting color. An example would be to rescue the RGB and return for example that it exists in about 90% of the image. I was taking a look at this "lib" Color Thief in Javascript, but unable to verify the percentage of color in predominance.

What would be the best way to do that?

const $input = document.getElementById('input');
const $canvas = document.getElementById('canvas');
const $resultado = document.getElementById('resultado');

const ctx = $canvas.getContext("2d");
const reader = new FileReader();
const image = new Image();

const size = 200;

$input.addEventListener('change', (event) => {
	const input = event.target;
	if (input.files && input.files[0]) {
    reader.readAsDataURL(input.files[0]);
  }
});

reader.onload = (event) => {
	image.src = event.target.result;
};

image.onload = () => {
  $canvas.width = size;
	$canvas.height = $canvas.width * (image.height / image.width);
	
	const oc = document.createElement('canvas');
	const	octx = oc.getContext('2d');

	oc.width = $canvas.width;
	oc.height = $canvas.height;
	octx.drawImage(image, 0, 0, oc.width, oc.height);

	ctx.drawImage(oc, 0, 0, oc.width, oc.height, 0, 0, oc.width, oc.height);
	
    // hardcode value
	$resultado.innerHTML = 'resultado: 60% cor: #0B70A4' ;
};
<main class="centerer">
	<input type="file" id="input"/><br/>
	<canvas id="canvas"></canvas><br/>
	<span id="resultado"></span>
</main>

1 answer

0

Sem Color Thief.

const getMaxColorAndPercent = ( imageData ) =>
{
    const table = {};
    const colors = Array.prototype.slice.call( new Uint32Array( imageData.data.buffer ) );
    void  colors.forEach( color => table[color] = (table[color]|0) + 1 );

    const maxValue = Object.values( table ).reduce( ( a, b )  => Math.max( a, b ) );
    const maxColor = Object.keys( table ).find( color => table[color] == maxValue );

    const percent = maxValue / colors.length * 100;
    const hexRGBcolorResult = (
        ( maxColor       & 255 ) << 16 | 
        ( maxColor >>  8 & 255 ) <<  8 | 
          maxColor >> 16 & 255 
        )
        .toString( 16 )
        .padStart( 6, '0' )
        .toUpperCase( );
    /*
    const hexRGBAcolorResult = (
        ( maxColor       & 255 ) << 24 | 
        ( maxColor >>  8 & 255 ) << 16 | 
        ( maxColor >> 16 & 255 ) <<  8 | 
          maxColor >> 24 & 255
        )
        .toString( 16 )
        .padStart( 8, '0' )
        .toUpperCase( );
    */
    resultado.innerHTML = `resultado: ${ percent.toFixed( 3 ) }% cor: #${ hexRGBcolorResult }`;
    /**/ resultado.style.backgroundColor = 'white';
    /**/ document.body.style.backgroundColor = '#' + hexRGBcolorResult;
}

const reader = new FileReader();
reader.onloadend = ( ) => 
{
    const image = new Image();
    image.onload = ( ) => 
    {
        const nW = canvas.width  = image.naturalWidth;
        const nH = canvas.height = image.naturalHeight;

        const ctx = canvas.getContext( '2d' );
        ctx.drawImage( image, 0, 0 );
        const imageData = ctx.getImageData( 0, 0, nW, nH );

        getMaxColorAndPercent( imageData );

        const canvasvisualwidth  = 200;
        const canvasvisualheight = canvas.height = nH * (canvas.width = canvasvisualwidth) / nW;
        ctx.drawImage( image, 0, 0, canvasvisualwidth, canvasvisualheight );
    }

    image.src = reader.result;
}

input.onchange = ( ) => input.files[0] && reader.readAsDataURL( input.files[0] );
<input type="file" id="input" accept="image/*"/><br/>
<canvas id="canvas"></canvas><br/>
<span id="resultado"></span>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.