question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Use ColorThief with XMLHttpRequest and without canvas

See original GitHub issue

I’m trying to use Color-Thief without making use of the <canvas/> element.

So, given a image url, width and height I have tried this

function getColorsNoCanvas(imageURL, imageHeight, imageWidth, done, error) {

  console.log(imageURL,imageHeight,imageWidth)

  var xhr = new XMLHttpRequest();
  xhr.open('GET', imageURL, true);
  xhr.responseType = 'arraybuffer';
  xhr.onload = function(e) {
    if (this.status == 200) {
      var uInt8Array = new Uint8Array(this.response);
      var i = uInt8Array.length;
      var biStr = new Array(i);
      while (i--)
      { biStr[i] = String.fromCharCode(uInt8Array[i]);
      }
      //var data = biStr.join('');
      //var base64 = window.btoa(data);
      //$("#myImage").attr("src", "data:image/jpeg;base64,"+base64);

      // Store the RGB values in an array format suitable for quantize function
      var threshold = 0.15;
      var pixels=uInt8Array
      var pixelCount=uInt8Array.length;
      var pixelArray = [];
      var bgPixelArray = [];
      for (var i = 0, offset, r, g, b, a; i < pixelCount; i++) {
          offset = i * 4;
          r = pixels[offset + 0];
          g = pixels[offset + 1];
          b = pixels[offset + 2];
          a = pixels[offset + 3];
          // If pixel is mostly opaque and not white
          if (a >= 125) {
              if (!(r > 250 && g > 250 && b > 250)) {
                  pixelArray.push([r, g, b]);

                  if ((i < pixelCount * threshold) || (i % imageHeight < imageWidth * threshold / 2)) {
                      bgPixelArray.push([r, g, b]);
                  }
              }
          }
      }
      var cmap = MMCQ.quantize(pixelArray, 5);
      var palette = cmap.palette();
      var bgCmap = MMCQ.quantize(bgPixelArray, 5);
      var bgPalette = bgCmap.palette();

      done.apply(this,[ [palette, bgPalette[0]] ])

    } // 200
  };
  xhr.send();
}

The result is anyways not the same as the getColors function. The reason I think it that I’m wrong when converting the uInt8Array:

var uInt8Array = new Uint8Array(this.response);
var i = uInt8Array.length;

to the rgba format:

// Store the RGB values in an array format suitable for quantize function
      var threshold = 0.15;
      var pixels=uInt8Array
      var pixelCount=uInt8Array.length;
      var pixelArray = [];
      var bgPixelArray = [];
      for (var i = 0, offset, r, g, b, a; i < pixelCount; i++) {
          offset = i * 4;
          r = pixels[offset + 0];
          g = pixels[offset + 1];
          b = pixels[offset + 2];
          a = pixels[offset + 3];
          // If pixel is mostly opaque and not white
          if (a >= 125) {
              if (!(r > 250 && g > 250 && b > 250)) {
                  pixelArray.push([r, g, b]);

                  if ((i < pixelCount * threshold) || (i % imageHeight < imageWidth * threshold / 2)) {
                      bgPixelArray.push([r, g, b]);
                  }
              }
          }
      }

Any hint?

Issue Analytics

  • State:open
  • Created 8 years ago
  • Comments:13

github_iconTop GitHub Comments

5reactions
telescommented, Jun 27, 2016

@loretoparisi any updates on this?

1reaction
loretoparisicommented, Oct 26, 2015

I have adapted the code to the latest version of Color-Thief:

ColorThief.prototype.getColorNoCanvas = function(sourceImage, quality, done) {
    this.getPaletteNoCanvas(sourceImage, 5, quality, function(palette) {
        done.apply(this, [palette[0]])
    });
};

where

ColorThief.prototype.getPaletteNoCanvas = function(sourceImageURL, colorCount, quality, done) {
  var xhr = new XMLHttpRequest();
  xhr.open('GET', sourceImageURL, true);
  xhr.responseType = 'arraybuffer';
  xhr.onload = function(e) {
    if (this.status == 200) {

      var uInt8Array = new Uint8Array(this.response);
      var i = uInt8Array.length;
      var biStr = new Array(i);
      while (i--)
      { biStr[i] = String.fromCharCode(uInt8Array[i]);
      }

      if (typeof colorCount === 'undefined') {
          colorCount = 10;
      }
      if (typeof quality === 'undefined' || quality < 1) {
          quality = 10;
      }

      var pixels     = uInt8Array;
      var pixelCount = 152 * 152 * 4 // this should be width*height*4

      // Store the RGB values in an array format suitable for quantize function
      var pixelArray = [];
      for (var i = 0, offset, r, g, b, a; i < pixelCount; i = i + quality) {
          offset = i * 4;
          r = pixels[offset + 0];
          g = pixels[offset + 1];
          b = pixels[offset + 2];
          a = pixels[offset + 3];
          // If pixel is mostly opaque and not white
          if (a >= 125) {
              if (!(r > 250 && g > 250 && b > 250)) {
                  pixelArray.push([r, g, b]);
              }
          }
      }

      // Send array to quantize function which clusters values
      // using median cut algorithm
      var cmap    = MMCQ.quantize(pixelArray, colorCount);
      var palette = cmap? cmap.palette() : null;
      done.apply(this,[ palette ])

    } // 200
  };
  xhr.send();
}

and so I’m using it like

var colorThief = new ColorThief();
colorThief.getColorNoCanvas("/colors2/"+$image.attr('src'), 8, function(colors) {
                                 console.log( "getColorNoCanvas", colors )
                                 styleBackground(colors, $image.parent().parent().attr('id'));
                            styleText(colors, colors,$image.parent().parent().attr('id'));
                             })

I have tried the simplest as possibile when getting the r,g,b,a array like:

for (var pxIndex = 0; pxIndex<pixels.length; pxIndex+=4 ) {
          var r = pixels[pxIndex+0];
          var g = pixels[pxIndex+1];
          var b = pixels[pxIndex+2];
          var a = pixels[pxIndex+3];
          if (a >= 125) {
              if (!(r > 250 && g > 250 && b > 250)) {
                  pixelArray.push([r, g, b]);
              }
          }
      }

But the result is wrong.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Color Thief
Color Thief. by Lokesh Dhakar. Grab the color palette from an image using just Javascript. ... The name of the package is colorthief,...
Read more >
Generate the Dominant Colors for an RGB image with ...
[QUESTION] How to generate the dominant colors of a RGB image without using the HTML5 <canvas/> , but in pure JavaScript from an...
Read more >
color-thief
I'm trying to use Color-Thief without making use of the <canvas/> element. ... var xhr = new XMLHttpRequest(); xhr.open('GET', imageURL, true); xhr.
Read more >
Dominant color with color-thief.js - Popular Blocks
The colors returned are good. Unfortunately, the library does not work using remotely hosted images. index.html#. <!DOCTYPE html> ...
Read more >
Color Thief using XHR Images; - JSFiddle - Code Playground
//window.URL.revokeObjectURL(img.src) // Use this after you're done with the image and no longer needed. 78. } 79. 80. } 81. xhr.open("GET" ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found