Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. Predominant image colour expensive!
Qt 6.11 is out! See what's new in the release blog

Predominant image colour expensive!

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
4 Posts 3 Posters 1.2k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    teh_raab
    wrote on last edited by
    #1

    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.

    JonBJ 1 Reply Last reply
    0
    • T teh_raab

      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.

      JonBJ Online
      JonBJ Online
      JonB
      wrote on last edited by
      #2

      @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.

      1 Reply Last reply
      0
      • T Offline
        T Offline
        teh_raab
        wrote on last edited by teh_raab
        #3

        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.

        1 Reply Last reply
        0
        • GrecKoG Online
          GrecKoG Online
          GrecKo
          Qt Champions 2018
          wrote on last edited by
          #4

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

          1 Reply Last reply
          1

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved