JS Canvas - положить данные изображения с альфа? - PullRequest
1 голос
/ 22 января 2012

У меня есть веб-приложение для ipad, над которым я работаю, где вы можете рисовать на холсте и сохранять его.Как более простая программа рисования.Мне нужно иметь возможность загружать и изображение на задний план и рисовать на нем.Прямо сейчас это не будет слишком сложно, так как я получил функциональность рисования, и было бы не сложно просто напечатать изображение на заднем плане и нарисовать его.У меня проблема в том, что у него также должны быть управляемые слои.Это означает, что он должен поддерживать альфа-пиксели.

Итак, я написал класс панели, который при вызове рисования перемещается вниз по дочерним панелям и рисует их буферизованные изображения во временное изображение.Затем я беру это и закрашиваю поверх родительского, продолжая до тех пор, пока изображение не сгладится во временное изображение.

Это прекрасно работает, особенно на рабочем столе.Но для этого мне пришлось написать код putImageData с нуля, который просматривает массив пикселей и рисует их с учетом альфа.Как и так -

    var offset = (canvasW*4*y)+x*4;
    for(var r = 0; r < newHeight; r++)
    {
        var lineOffset = (size.width*4 - columns)*r + offset;
        for(var c = 0; c < columns; c+=4)
        {
            var start = (r*columns)+c;
            var destStart = start+lineOffset;
            var red = imageData[start];
            var green = imageData[start+1];
            var blue = imageData[start+2];
            var alpha = imageData[start+3];

            var destRed = canvasData[destStart];
            var destGreen = canvasData[destStart+1];
            var destBlue = canvasData[destStart+2];
            var destAlpha = canvasData[destStart+3];

            var opacity = alpha/255;
            var destOpacity = destAlpha/255;
            var invOpacity = 1-opacity;

            var newRed = Math.abs(red - ((red-destRed)*invOpacity));
            var newGreen = Math.abs(green - ((green-destGreen)*invOpacity));
            var newBlue = Math.abs(blue - ((blue-destBlue)*invOpacity));

            canvasData[start+lineOffset] = newRed;
            canvasData[start+lineOffset+1] = newGreen;
            canvasData[start+lineOffset+2] = newBlue;
            canvasData[start+lineOffset+3] = 255;
        }
    }

Это занимает около 50 миллисекунд на слой.Не очень хорошо для рабочего стола.Занимает целых 1200 миллисекунд для iPad!Поэтому я протестировал его с оригинальным putImageData (который не поддерживает альфа), и он все еще был не очень впечатляющим, но это лучшее, что я получил, я думаю.

Так вот в чем моя проблема.Я знаю, что для рисования на холстах есть непрозрачность в целом, но некоторые пиксели должны быть в состоянии рисовать полностью непрозрачными, а некоторые - полностью прозрачными.Есть ли putImageData, который включает непрозрачность?

Если нет каких-либо рекомендаций о том, как мне это сделать?

1 Ответ

0 голосов
/ 27 января 2012

Как упоминал @Джеффри Суини, попробуйте наложить холсты друг на друга. Для одной из моих библиотек Javascript, CInk (поиск там z-index), я сделал то же самое.

У меня был один контейнер div, который я набил многими canvas DOM, чтобы имитировать слои. Все canvas DOM абсолютно позиционированы, а их z-index определяют порядок слоев. В вашем случае вам придется применить стиль на определенных слоях, чтобы установить его непрозрачность.

...