I am painting an image to a HTML canvas and getting image data from it to find the colors of specific pixels. The image is a map where each country is a different color. I want to cross reference the color returned by .getImageData() to a list of colors I made by hand to find which country any given pixel is in.
My issue is, the image I paint to the canvas and the image that is painted are slightly different colors.
This is the original picture being drawn to the canvas:
This is the picture I get when I download the canvas as a PNG:
The two look almost identical, but if you download them and open them in a photo editing software, you will find they aren't. For example, the grey ocean in the top picture is 73,73,73,255 and the grey ocean in the bottom picture is 71,71,71,255.
I can still accomplish my goal of determining the country a pixel is in, but I need to make a new list based on the picture I download after it is painted to the canvas.
This just seems like a really weird issue.
If anyone is wondering, my code looks like this:
HTML:
<img scr="active_map.png" class="active" id="activeImage">
<canvas id="activeCanvas" width="439px" height="245px">Your Browser Doesn't Support HTML5 Canvases... Sorry :( </canvas>
JS:
var activeCanvas = document.getElementById('activeCanvas')
var activeContext = activeCanvas.getContext("2d");
var activeImage = document.getElementById('activeImage')
activeContext.drawImage(activeImage,0,0);
var activePixelData = activeContext.getImageData(0,0,439,245)["data"];
Also, I am using Firefox 31 for Ubuntu
-Thanks for the help
As @GameAlchemist mentions, there exists a potential gamma correction issue with the PNG you're using, namely that RGB values won't be interpreted consistently.
Henri Sivonen's The Sad Story of PNG Gamma “Correction” provides a very thorough analysis. In a nutshell:
In order to compensate for the different gammas, the display gamma of the system an image was authored on and the display gamma of the system where the image is being displayed both need to be known to the piece of software displaying the image. The PNG format provides a means for storing the (reciprocal of) display gamma of the authoring system to the image file. It is up to the program writing the file to store the native display gamma of the image, and then it is up to program displaying the file to compensate.
He recommends using Pngcrush to remove the color profiling that can cause this inconsistency. I've confirmed his technique (pngcrush -rem gAMA -rem cHRM -rem iCCP -rem sRGB infile.png outfile.png
) does work. Here's your modified image:
You'll notice it is 6KB smaller. I've confirmed this works as expected before and after in Firefox (from RGB values of 71, 71, 71 to values of 73, 73, 73).
Browsers have the freedom to premultiply alpha and (as GameAlchemist says) do gamma correction.
The result is that different browsers might display slightly different color values from the ones FF is displaying.
Possible workarounds:
Assume the browser will mess with your exact color, so have your test succeed on a small range of colors around the country's original color.
Send a pre-calculated array to the client representing each pixel on the canvas containing which country is under that pixel. This array would be similar to .getImageData, but with only 1 value per pixel--the value would be the country code for that pixel.
Calculate paths that outline each country. Then you can use context.isPointInPath to hit-test if the mouse is inside a country. DougX has done this nicely: http://dougx.net/map/
If memory is a concern, you can refactor the pre-calculated array above to use objects in a tree structure. For example:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With