Predominant image colour expensive!



  • Hi All,

    Using QtQuick 2.5 // Qt 5.5.1

    I am trying to get the average colour from an image so i can display the colour in a container that is bigger than said image. This is working by loading in the source image to a Canvas then fetching the image data using getContext()-> getImageData

    However the loop for CanvasImageData->data object is time consuming and seems to lockup the application. Now i have tried to move this into a workscript however it seems that Worker Script will not accept the data's type (data : object).

    I could loop through the object to create an array but i feel this will also be time consuming and also make using Worker Script pointless. Before i pull my hair out i wanted to check i am not doing something stupid with parsing the data to the worker script!

    Was hoping for suggestions of things to try or a point in the right direction

    canvasPickedColour = "#ffffff" //Reset to force an onChanged signal.  This is to prevent opening and closing same synopsis and not getting a colour change signal not being received
    ctx = colourCanvas.getContext("2d");
    ctx.save();
    
    ctx.drawImage(imageSource, 0, 0, canvasWidth, canvasHeight);
    canvasImageData = ctx.getImageData(0, 0, canvasWidth, canvasHeight)
    
    var rgb = { r:255 ,g:255 ,b:255 } // Set a base colour as a fallback for non-compliant browsers
    var count = 0
    var i = -4
    var data = canvasImageData.data;
    
    var length = data.length;
    //log.out("length: " + length)
    while ((i += searchQuality * 4) < length) {
    	count++;
    	rgb.r += data[i];
    	rgb.g += data[i+1];
    	rgb.b += data[i+2];
    }
    
    // floor the average values to give correct rgb values (ie: round number values)
    rgb.r = Math.floor(rgb.r/count);
    rgb.g = Math.floor(rgb.g/count);
    rgb.b = Math.floor(rgb.b/count);
    
    //Normalise the values from 0-255 to between 0 and 1..
    log.out("before normalize -> rgb.r: " + rgb.r + ", rgb.g: " + rgb.g + ", rgb.b: " + rgb.b)
    rgb.r = normalize(rgb.r, 0 , 255)
    rgb.g = normalize(rgb.g, 0 , 255)
    rgb.b = normalize(rgb.b, 0 , 255)
    log.out("after normalize -> rgb.r: " + rgb.r + ", rgb.g: " + rgb.g + ", rgb.b: " + rgb.b)
    
    
    var dominantColor = Qt.rgba(rgb.r, rgb.g, rgb.b)
    log.out("dominantColor: " + dominantColor)
    canvasPickedColour = dominantColor
    ctx.restore();
    
    function normalize(value, min, max) {
    	var normalized = (value - min) / (max - min);
    	return normalized;
    }
    

    Cheers,

    Rob.



  • @teh_raab said in Predominant image colour expensive!:

    However the loop for CanvasImageData->data object is time consuming and seems to lockup the application.

    Well how big is your canvasImageData.data.length? Big?! Because your loop is going to be busy throughout.



  • The length is 884736.

    My problem is that its locking up the GUI thread. I wanted to just take the data object returned from getImageData and parse it to a workscript for it to then loop through

    Also note that i have a "searchQuality" variable that i have set to 20 so actually we only process every 20th pixel. Going any higher than this will increase the risk of showing a less predominant colour.



  • Do it in c++ and without Canvas, QtConcurrent will help you for making it asynchronous


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.