【问题标题】:Image alpha on default Android browser默认 Android 浏览器上的图像 alpha
【发布时间】:2014-09-11 13:19:45
【问题描述】:

我正在尝试对图像进行双色调处理并将其粘贴到画布上。

适用于桌面浏览器:

  • 铬
  • 火狐
  • 野生动物园
  • Internet Explorer

在移动浏览器中失败:

  • 安卓

Workable demo on JSFiddle,此示例在 Chrome 中有效,但在 Android 的默认浏览器中失败。

代码是:

<style>
    body {
        background-color: gray;
    }
</style>

<canvas id="mycanvas" width="64" height="64"></canvas>

<script>
    var image = new Image();
    image.src = 'image.png';

    image.onload = function () { //once the image finishes loading
        var context = document.getElementById("mycanvas").getContext("2d");

        context.drawImage(image, 0, 0);

        var imageData = context.getImageData(0, 0, 64, 64);
        var pixels = imageData.data;
        var numPixels = pixels.length;

        for (var i = 0; i < numPixels; i++) { //for every pixel in the image
            var index = i * 4;
            var average = (pixels[index] + pixels[index + 1] + pixels[index + 2]) / 3;

            pixels[index] = average + 255; //red is increased
            pixels[index + 1] = average; //green
            pixels[index + 2] = average; //blue
            //pixels[index + 3] = pixels[index + 3]; //no changes to alpha
        }

        context.clearRect(0, 0, 64, 64); //clear the image
        context.putImageData(imageData, 0, 0); //places the modified image instead
    }
</script>

总结是:

  • 将背景颜色设置为灰色,以便更容易观察到 Alpha
  • 创建一个 64 x 64 的画布
  • 在透明背景上加载笑脸图像
  • 将图像绘制到画布上
  • 获取图片数据
  • 对于每个像素,使红色更强烈
  • 替换画布上更改的图像

笑脸看起来像这样(被块引用,所以你可以看出它是透明的):

但是,与 chrome 和 android 浏览器相比,

android绘图的背景是红色的,而chrome绘图是完全透明的。

所以...

  • 这里发生了什么?
  • 如何更改代码以使android绘图与chrome绘图匹配?

注意:我已经尝试过if (pixels[index + 3] == 0) continue;,我知道这一点,但它不适用于具有不同不透明度的图像。

【问题讨论】:

  • 您是否已将 png 保存为 24 格式?
  • @romaneso 不,它是 32 位 RGBA。考虑到 RGBA requires 32 bits,我什至认为 24​​ 位 RGBA 是不可能的。
  • 哦,没错。不妨试试 gif 格式
  • @Thouartamazing 它还必须在网络服务器上运行,制作 .html 文件并直接使用 chrome 运行它是行不通的。它还应该在网络服务器上,以便您可以使用 android 设备对其进行测试。

标签: javascript android canvas alpha


【解决方案1】:

好的,我有一个result。

首先看看你的循环:

for (var i = 0; i < numPixels; i++) { //for every pixel in the image
     var index = i * 4;

index 将比numPixels 大 3 倍以上。并将获得undefined 值。平均为NaN。但是,然后我解决了这个问题 - 结果是一样的。

所以我尝试对每个像素使用fillStyle 和fillRect。一切都会好起来的。我的code:

function putImageData(ctx, imageData, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight) {
    var data = imageData.data;
    var height = imageData.height;
    var width = imageData.width;

    dirtyX = dirtyX || 0;
    dirtyY = dirtyY || 0;
    dirtyWidth = dirtyWidth !== undefined ? dirtyWidth : width;
    dirtyHeight = dirtyHeight !== undefined ? dirtyHeight : height;

    var limitBottom = dirtyY + dirtyHeight;
    var limitRight = dirtyX + dirtyWidth;

    for (var y = dirtyY; y < limitBottom; y++) {
        for (var x = dirtyX; x < limitRight; x++) {
            var pos = y * width + x;
            //adding red increased here
            ctx.fillStyle = 'rgba(' + data[pos * 4 + 0] + 255 + ',' + data[pos * 4 + 1] + ',' + data[pos * 4 + 2] + ',' + (data[pos * 4 + 3] / 255) + ')';
            ctx.fillRect(x + dx, y + dy, 1, 1);
        }
    }
};

var image = new Image();
image.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3gcVBAYmslkm5QAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABc0lEQVR42u2a3QrDMAiFZ9j7v7K7CpTRVtt4NCEnsJt1BP1y4l8nqvrZebXP5osACIAACIAACIAACIAACIAACIAAqpaIlPXkgpwHiIiqqtw5efa8f7csgIgTVVU5AlwGAELOSAjfLKndOWFBQyohVAHWPR/dCwEBCiDCYDSIViH5p/v87xUZZ8IUkJHGEGpoyLu/QjZomffeE+37xwthFH5aKdwNtQyOyhjT1QGzXosWaYBljMdY72laPUZZDLBq+6jTPO41xRXwGB/1Gw5ECOC6StxSASMQ2o5OQ9Jg5VxviYFI5KxgSQBXzmYNPlLaYctw72jr7ncd2DQx4KkCKud/cACeQNghvAmaCDjhCvBCOFODJX2Pgkp7gben+vR5pAqgL0aip8KI2ABNgyMRGzFiT1FARI+eWTDB3w7P6nhKHVBd5pYDGFVABsCU/wccHblLaxUNEwzACvKHB8EVFoeiBEAABEAABEAABEAABEAAe64fre4tZAeLAbcAAAAASUVORK5CYII=';

image.onload = function () {
    var context = document.getElementById("mycanvas").getContext("2d"),
        imageData;

    context.drawImage(image, 0, 0);
    imageData = context.getImageData(0, 0, 64, 64);

    putImageData(context, imageData, 0, 0);
}

【讨论】:

  • 我接受了 + 赏金,因为它本质上不是代码的问题,而是 Android 浏览器使用的 JavaScript 实现的问题。通过使用 fillRect,它的速度要慢得多,但至少是一种将相同效果应用到图像上的有效方法。
猜你喜欢
  • 1970-01-01
  • 2018-10-31
  • 1970-01-01
  • 2013-03-01
  • 2020-05-05
  • 2013-04-20
  • 2011-09-27
  • 2023-03-28
  • 2014-08-10
相关资源
最近更新 更多