Javascript更改图像颜色IndexSizeError:索引或大小为负数或大于允许的数量

时间:2014-01-13 17:35:26

标签: javascript jquery canvas html5-canvas

我正在编写一个javascript代码,其中图像更改用户指定的颜色..代码在我身边完成..但奇怪的是,当清除缓存并且下次运行良好时,mozilla会抛出错误IndexSizeError: Index or size is negative or greater than the allowed amount。在Chrome上它根本不运行..它说Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': the canvas has been tainted by cross-origin data.

我不确定是什么似乎是问题,因为我花了3 4个小时调试它,但我不能。所以我必须来这里..

如果有错误可以解决,请告诉我。

代码:

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

编辑:现在主要问题是Uncaught SecurityError: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': the canvas has been tainted by cross-origin data.在Chrome上。

1 个答案:

答案 0 :(得分:4)

您最有可能从本地“file://”协议或外部网站加载图像。如果您提供的代码包含实际的链接引用,那么您可能正在执行前者。

浏览器会认为这是与CORS(跨域资源共享)相关的安全风险,并且会因为使用getImageData()安全性而不允许操纵像素缓冲区而引发错误toDataURL()

您必须作为解决方案在localhost / 127.0.0.1地址运行您的页面。如果您还没有安装简单的轻量级服务器,例如Mongoose

如果您已经(或使用类似的东西),那么您需要通过将此属性添加到图像标记来请求图像的跨源使用:

<img src="..." ... crossOrigin="anonymous" />

为了使其工作,另一端的服务器必须接受这种用途,它通过提供特殊的标头(如果没有,你需要在服务器上配置)。如果没有,或者您无权访问远程服务器,除了通过服务器上的页面代理加载图像之外,您将无法将图像用于此目的。