Reputation: 1478
I am writing a javascript code where image changes color specified by a user.. the code is complete from my side.. but strangely mozilla throw the error IndexSizeError: Index or size is negative or greater than the allowed amount
when cleared the cache and next time it runs good.. on chrome it does not run at all .. it says Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': the canvas has been tainted by cross-origin data.
Im not sure what seems to be the problem as i had spent 3 4 hours debugging it, but i couldn't. So i had to come here..
please let me know if its a error that can be solved.
CODE:
<ul>
<li>
<img src="mug.png" id="mug_image" class="the_image" width="200">
<input type="text" id="mug_color" value="#6491ee">
<input type="button" value="change color" class="changeColorButton" id="mug_button"></li>
<li>
<img src="rug.png" id="rug_image" class="the_image" width="200">
<input type="text" id="rug_color" value="#6491ee">
<input type="button" value="change color" class="changeColorButton" id="rug_button">
</li>
<li>
<img src="rug.png" id="nug_image" class="the_image" width="200">
<input type="text" id="nug_color" value="#6491ee">
<input type="button" value="change color" class="changeColorButton" id="nug_button">
</li>
</ul>
<script type="text/javascript">
$(document).ready(function(){ // Begin scoping function
var originalPixels = [];
var currentPixels = [];
var the_images = $('.the_image');
var canvas = [];
var ctx = [];
$.each(the_images, function(ind, val) {
var get_id = $(this).attr('id');
var the_id_arr = get_id.split('_');
the_id = the_id_arr[0];
canvas[the_id] = document.createElement("canvas");
ctx[the_id] = canvas[the_id].getContext("2d");
originalPixels[the_id] = '0';
currentPixels[the_id] = '0';
getPixels(canvas[the_id], ctx[the_id], the_id, val);
});
$('.changeColorButton').click(function() {
var button_id = $(this).attr('id');
var the_id_arr = button_id.split('_');
var the_id = the_id_arr[0];
var the_image = $('#' + the_id + '_image');
var the_color = the_id + '_color';
changeColor(canvas[the_id], ctx[the_id], originalPixels[the_id], currentPixels[the_id], the_image.get(0), the_color);
});
function HexToRGB(Hex)
{
var Long = parseInt(Hex.replace(/^#/, ""), 16);
return {
R: (Long >>> 16) & 0xff,
G: (Long >>> 8) & 0xff,
B: Long & 0xff
};
}
function changeColor(canvas, ctx, originalPixels, currentPixels, obj, color_id)
{
if (!originalPixels)
return; // Check if image has loaded
var newColor = HexToRGB(document.getElementById(color_id).value);
for (var I = 0, L = originalPixels.data.length; I < L; I += 4)
{
if (currentPixels.data[I + 3] > 0)
{
currentPixels.data[I] = originalPixels.data[I] / 255 * newColor.R;
currentPixels.data[I + 1] = originalPixels.data[I + 1] / 255 * newColor.G;
currentPixels.data[I + 2] = originalPixels.data[I + 2] / 255 * newColor.B;
}
}
ctx.putImageData(currentPixels, 0, 0);
obj.src = canvas.toDataURL("image/png");
}
function getPixels(canvas, ctx, the_id, img)
{
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.naturalWidth, img.naturalHeight, 0, 0, img.width, img.height);
originalPixels[the_id] = ctx.getImageData(0, 0, img.width, img.height);
currentPixels[the_id] = ctx.getImageData(0, 0, img.width, img.height);
img.onload = null;
}
});
</script>
EDIT : the main prob now is Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': the canvas has been tainted by cross-origin data.
on chrome.
Upvotes: 0
Views: 3705
Reputation:
You are most likely either loading the images from a local "file://
" protocol or from an external site. If the code you present contains the actual link references you are probably doing the former.
The browser will consider this a security risk related to CORS (cross-origin resource sharing) and will throw an error as we are not allowed to manipulate the pixels buffers due to security using getImageData()
and toDataURL()
.
You must as a solution run your page at a localhost/127.0.0.1 address. If you haven't already you can install a simple light-weight server such as Mongoose.
If you already do (or using something similar) then you need to request cross-origin use for the image by adding this attribute to the image tag:
<img src="..." ... crossOrigin="anonymous" />
For this to work the server at the other end must accept this use which it does by providing special headers (which you need to configure at the server if not). If it doesn't or you don't have access to the remote server, you won't be able to use the images for this purpose other than loading them through a page proxy on your server.
Upvotes: 4