admin管理员组文章数量:1026989
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 acplish 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
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 acplish 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
Share Improve this question asked Jan 4, 2015 at 16:51 obventio56obventio56 3352 silver badges12 bronze badges 2- 3 Browsers might apply a gamma correction or any color correction scheme to the displayed images. – GameAlchemist Commented Jan 4, 2015 at 17:12
- From what I found out by googling, it seems like the distortion is different in each browser. Is there anyway to pensate for that? – obventio56 Commented Jan 4, 2015 at 18:58
2 Answers
Reset to default 4As @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 pensate 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 pensate.
He remends 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/map/
If memory is a concern, you can refactor the pre-calculated array above to use objects in a tree structure. For example:
- Divide your map into a 9x4 grid (or 4x2 or whatever).
- Create an array of objects for each grid-cell. The objects might look like this: { x0:297, x1:353 y0:91, y1:94 country:55 } where countryCodes[55]='China'. This example object represents (353-297)*(94-91)==224 pixels.
- On mouseclick, calculate which grid-cell the mouse is in and then scan the array until you find the exact mouse [x,y]. You can omit all ocean coordinates from the grid arrays so if your test doesn't find a match, you can assume the mouse is in the ocean.
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 acplish 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
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 acplish 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
Share Improve this question asked Jan 4, 2015 at 16:51 obventio56obventio56 3352 silver badges12 bronze badges 2- 3 Browsers might apply a gamma correction or any color correction scheme to the displayed images. – GameAlchemist Commented Jan 4, 2015 at 17:12
- From what I found out by googling, it seems like the distortion is different in each browser. Is there anyway to pensate for that? – obventio56 Commented Jan 4, 2015 at 18:58
2 Answers
Reset to default 4As @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 pensate 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 pensate.
He remends 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/map/
If memory is a concern, you can refactor the pre-calculated array above to use objects in a tree structure. For example:
- Divide your map into a 9x4 grid (or 4x2 or whatever).
- Create an array of objects for each grid-cell. The objects might look like this: { x0:297, x1:353 y0:91, y1:94 country:55 } where countryCodes[55]='China'. This example object represents (353-297)*(94-91)==224 pixels.
- On mouseclick, calculate which grid-cell the mouse is in and then scan the array until you find the exact mouse [x,y]. You can omit all ocean coordinates from the grid arrays so if your test doesn't find a match, you can assume the mouse is in the ocean.
本文标签:
版权声明:本文标题:javascript - Why is a canvas drawn with an image a slightly different color than the image itself? - Stack Overflow 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://it.en369.cn/questions/1745658770a2161760.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论