Прозрачность потеряла с помощью метода getImageData - поддержка HTML5 2D-контекст

я заметил странную проблему с getImageData; прозрачность изображения, кажется, игнорируется при извлечении данных изображения.

так как любое изображение должно быть нарисовано на canvas прежде чем его данные изображения могут быть получены, я предположил, что это было проблемой с canvas в вопросе тупить. Но я ошибался, так как использовал canvas в качестве аргумента в drawImage поддерживает прозрачность.

вот как я загрузил изображения;

var load_image = function(name, url, holder, callback) {
    var img = new Image();
    img.src = url;

    img.addEventListener('load', function(e) {
        var canvas = make_canvas(e.target.width, e.target.height);
        var ctx = canvas.getContext('2d');

        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(e.target, 0, 0);

        holder[name] = {canvas: canvas, ctx: ctx};

        delete e.target;

        callback.call();
    }, false);
};

в callback - это просто функция draw, которая вызывает draw_image чтобы нарисовать изображение.

обычный версия;

var draw_image = function(ctx, img, sx, sy, w, h, dx, dy) {
    ctx.drawImage(img.canvas, sx, sy, w, h, dx, dy, w, h);
};

он просто берет холст в качестве аргумента drawImage, и результат, как и предполагалось, с сохранением прозрачности. пример.

версия данных изображения;

var draw_image = function(ctx, img, sx, sy, w, h, dx, dy) {
    var imagedata = img.ctx.getImageData(sx, sy, w, h);
    ctx.putImageData(imagedata, dx, dy);
};

этот получает данные изображения требуемого прямоугольника с того же холста, что и в обычной версии, и помещает данные изображения на холст, который я хочу нарисовать. Я считаю, что транспарентность должна поддерживаться, но это не так. пример. (Это ссылка Dropbox из-за origin-clean флаг.)

я ошибаюсь, предполагая, что прозрачность должна поддерживаться с getImageData? Или я просто неправильно его использую?

в любом случае, помощь будет действительно оценили.

1 ответов


Я считаю, что ваша проблема в том, что putImageData не использует составная операция для смешивания данных изображения источника и назначения. Скорее, он делает прямую запись красного, зеленого, синего,Альфа каналы на холст. Для полностью прозрачных пикселей это означает, что они могут отображаться или не отображаться в ожидаемом цвете.

вместо этого вы можете создать промежуточный элемент canvas, нарисовать его, а затем использовать drawImage() для рендеринга целевой холст с соответствующим globalCompositeOperation применяется. маска для putImageData с холстом HTML5? обсуждает этот вопрос более подробно.

Update: вы можете проверить, что данные, которые вы записываете в свой "сломанный" пример, на самом деле имеют прозрачные данные, выполнив ctx.getImageData(230,50,1,1).data. Результат [0,0,0,0] - т. е. полностью прозрачный пиксель.