Изменить оттенок/оттенок ImageElement на холсте

Я работаю над анимацией частиц для своего игрового движка и хочу знать, можно ли изменить оттенок, гамма и другие свойства изображения объекта ImageElement холста, сохраняющие форму изображения.

То, что я пробовал до сих пор, это:

_ctx.save();
_ctx.setStrokeColorHsl(240, 100, 50);
_ctx.fillRect(c.x, c.y, width, height);
_ctx.globalAlpha = nAlpha; //Modify the transparency
_ctx.drawImageScaled(p, c.x, c.y, width, height);
_ctx.restore();   

Что работает, но он применяет тон ко всей части изображения, что означает, что если изображение представляет собой PNG с прозрачными краями, оно будет рисовать даже прозрачные части, потому что он использует "fillRect()" (который рисует только прямоугольники) для применить преобразование и объект изображения.

Результат такой: (красные частицы — полупрозрачные круги)

Попытка костра

Есть ли другой способ подкрасить только форму изображения или изменить объект напрямую, чтобы преобразование применялось только к видимой части изображения?


person Jorge Luis Vargas    schedule 09.10.2013    source источник


Ответы (2)


Вы должны использовать режимы globalCompositeOperation. Возможно, сначала нарисуйте свое изображение, затем fillRect с globalAlpha и globalCompositeOperation = 'source-atop'.

https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html

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

person GameAlchemist    schedule 29.10.2013
comment
Удивительный! это сработало, но мне не нужно было использовать метод fillRect, мне нужно было использовать только глобальный составной(api.dartlang.org/docs/releases/latest/dart_html/ ) и fillStyle и сделали свое дело: _ctx.globalCompositeOperation = 'lighter'; _ctx.fillStyle = #f30; - person Jorge Luis Vargas; 04.11.2013

Я не знаю встроенного способа сделать это. Один из способов сделать это — нарисовать изображение на временном холсте и самостоятельно изменить пиксели изображения. Но вам понадобятся функции для преобразования между RGB и HSL. Вы можете использовать этот метод, чтобы сделать то же самое с насыщенностью и яркостью.

double hue = 0.8;

var data = _context.getImageData(0, 0, _canvas.width, _canvas.height);
var pixels = data.data;
List<double> hsl;
List<int> newPixel;

for(var i = 0, len = pixels.length; i < len; i += 4) {
  hsl = rgbToHsl(pixels[i + 0], pixels[i + 1], pixels[i + 2]);

  newPixel = hslToRgb(h, hsl[1], hsl[2]);
  // or newPixel = hslToRgb((hsl[0] + hue) % 1.0, hsl[1], hsl[2]);

  pixels[i + 0] = newPixel[0];
  pixels[i + 1] = newPixel[1];
  pixels[i + 2] = newPixel[2];
}
_context.putImageData(data, 0, 0);

Другой способ, используя ваш метод, может заключаться в том, чтобы дополнительно использовать ваше базовое изображение в качестве маски для холста с измененным оттенком. Вам нужно будет перебрать свои пиксели и изменить pixel[i + 3] на альфа-канал базового изображения. Но вам не нужно было бы конвертировать между HSL и RGB.

person Dennis Kaselow    schedule 11.10.2013
comment
2 вещи, одну из которых вы все еще используете: var data = _context.getImageData(0, 0, _canvas.width, _canvas.height); Это в основном прямоугольник, то же самое, и, во-вторых, я опасался, что такой вид манипулирования изображениями пиксель за пикселем действительно неэффективен и вызывает плохое падение кадров в секунду, я попробую, возможно, подход css к этому с момента обработки изображения data не выглядит хорошим вариантом. - person Jorge Luis Vargas; 14.10.2013