Как
сделать
Instagram
в браузере

Дмитрий Дудин @nedudi, via @html5by

Как
сделать
Instagram
в браузере

Дмитрий Дудин @nedudi

Приукрасить

Придать настроение

Нелинейные искажения

Устоявшиеся практики

Фильтрация изображений в веб
несколько лет назад:

  1. Flash

Все меняется к лучшему

Способы фильтрации на клиенте сегодня и в ближайшем будущем:

Canvas

Canvas data

var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
context.drawImage(img);
var imgd = context.getImageData(0, 0, w, h)
var pixels = imgd.data;

Не нужно изобретать свой велосипед

vintageJS

$(img).vintage({
	contrast:32,
	lighten:0.4,
	noise: 20,
	desaturate: 0.05
});

camanJS

Caman("image.jpg", "#canvas", function () {
	this
		.saturation(20)
		.gamma(1.4)
		.vignette(300, 60)
		.render();
});

Достоинства фильтрации с Canvas

Недостатки фильтрации с Canvas

WebGL

Что это о_O ?

precision mediump float;
varying vec2 position;
uniform sampler2D webcam;

void main() {
	vec2 p = position;
	vec4 color = texture2D(webcam, p);
	color.rgb = 1.0 - color.rgb;
	gl_FragColor = color;
}

Шейдеры

Вернемся к “cтрашному” шейдеру

precision mediump float;
varying vec2 position;
uniform sampler2D webcam;

void main() {
	vec2 p = position;
	vec4 color = texture2D(webcam, p);
	color.rgb = 1.0 - color.rgb;
	gl_FragColor = color;
}

Велосипеды в WebGl - это больно

glfx

Достоинства glfx

WebGLImageFilter

WebGLImageFilter прост в использовании

var filter = new WebGLImageFilter();
filter.addFilter('hue', 180);
filter.addFilter('negative');
filter.addFilter('blur', 7);
var filteredImage = filter.apply(inputImage);

Достоинства фильтрации с WebGL

Недостатки фильтрации с WebGL

CSS-фильтры

Синтаксис CSS-фильтров

-webkit-filter:
	brightness(1.4)
	contrast(2)
	hue-rotate(300deg)
	sepia(0.3);

Картинка

Картинка с css эффектом

Достоинства CSS-фильтров

Недостатки CSS-фильтров

CSS-шейдеры

Синтаксис

img {
		-webkit-filter: custom(
			none
			mix(
				url(someFragmentShader.fs)
				normal
				source-atop
			)
		);
}

someFragmentShader.fs

precision mediump float;
void main()
{
	css_ColorMatrix = mat4(1.0, 0.0, 0.0, 0.0,
												 0.0, 0.0, 0.0, 0.0,
												 0.0, 0.0, 0.0, 0.0,
												 0.0, 0.0, 0.0, 1.0);
}

Картинка с css эффектом

Достоинства CSS-шейдеров

Недостатки CSS-шейдеров

SVG filters

Нарисуем круг

<svg width="400" height="400">
		<circle
			cx="200"
			cy="200"
			fill="#3498db"
			r="100"/>
</svg>

Это круг :)

Простейший svg-фильтр (blur)

<svg width="400" height="400">
	<defs>
		<filter id="f0">
			<feGaussianBlur stdDeviation="50" />
		</filter>
	</defs>
	<circle filter="url(#f0)" cx="200" cy="200"
	fill="#3498db" r="100"/>
</svg>

Простейший svg-фильтр (blur)

<svg width="400" height="400">
	<defs>
		<filter id="f0">
			<feGaussianBlur stdDeviation="50" />
		</filter>
	</defs>
	<circle filter="url(#f0)" cx="200" cy="200"
	fill="#3498db" r="100"/>
</svg>

Простейший svg-фильтр (blur)

<svg width="400" height="400">
	<defs>
		<filter id="f0">
			<feGaussianBlur stdDeviation="50" />
		</filter>
	</defs>
	<circle filter="url(#f0)" cx="200" cy="200"
	fill="#3498db" r="100"/>
</svg>

Простейший svg-фильтр (blur)

<svg width="400" height="400">
	<defs>
		<filter id="f0" >
			<feGaussianBlur stdDeviation="40" />
		</filter>
	</defs>
	<circle filter="url(#f0)" cx="200" cy="200"
	fill="#3498db" r="100"/>
</svg>

Результат

Картинка внутри SVG

<svg width="1024" height="768">
	<image
		width="100%"
		height="100%"
		xlink:href="img/girl.jpg" />
</svg>

Картинка внутри SVG + blur

<svg width="1024" height="768">
	<defs>
		<filter id="f1" >
			<feGaussianBlur stdDeviation="10" />
		</filter>
	</defs>
	<image filter="url(#f1)" xlink:href="img/girl.jpg"
	width="100%" height="100%" />
</svg>

Картинка внутри SVG

Картинка внутри SVG + blur

Комбинация фильтров

<filter id="f2">
	<feGaussianBlur stdDeviation="3" />
	<feColorMatrix type="saturate" values="0">
	</feColorMatrix>
</filter>

Комбинация фильтров

<filter id="f2">
	<feGaussianBlur result="a1" stdDeviation="3" />
	<feColorMatrix type="saturate" values="0">
	</feColorMatrix>
</filter>

Комбинация фильтров

<filter id="f2">
	<feGaussianBlur result="a1" stdDeviation="3" />
	<feColorMatrix in="a1" type="saturate" values="0">
	</feColorMatrix>
</filter>

Комбинация фильтров

<filter id="f2">
	<feGaussianBlur result="a1" stdDeviation="3" />
	<feColorMatrix in="a1" type="saturate" values="0">
	</feColorMatrix>
</filter>

Комбинация фильтров

типы SVG фильтров
<fe…Фильтр>

feComponentTransfer

feComponentTransfer

<feComponentTransfer>
	<feFuncR type="linear" slope="5" intercept="-0.5"/>
	<feFuncG type="linear" slope="0.2"/>
	<feFuncB type="linear" slope="0.2"/>
	<feFuncA type="identity"/>
</feComponentTransfer>

feComponentTransfer

feComponentTransfer

<feComponentTransfer>
	<feFuncA type="linear" slope="0.5"/>
</feComponentTransfer>

feComponentTransfer

feComponentTransfer

<feComponentTransfer>
	<feFuncR type="linear" slope="0"/>
	<feFuncG type="linear" slope="0"/>
	<feFuncB type="linear" slope="1"/>
</feComponentTransfer>

feComponentTransfer

feComponentTransfer

<feComponentTransfer>
	<feFuncR type="linear" slope="10" intercept="-4"/>
	<feFuncG type="linear" slope="1.5" intercept="1"/>
	<feFuncB type="linear" slope="2" intercept="-1"/>
</feComponentTransfer>

feComponentTransfer

feComponentTransfer

<feComponentTransfer>
	<feFuncR type="discrete" tableValues="0 0.5 1"/>
	<feFuncG type="discrete" tableValues="0 0.5 1"/>
	<feFuncB type="discrete" tableValues="0 0.5 1"/>
</feComponentTransfer>

feComponentTransfer

feComponentTransfer

<feComponentTransfer>
	<feFuncR type="table" tableValues="1 0"/>
	<feFuncG type="table" tableValues="1 0"/>
	<feFuncB type="table" tableValues="1 0"/>
</feComponentTransfer>

feComponentTransfer

feComponentTransfer

<feComponentTransfer>
	<feFuncR
		type="gamma"
		amplitude="2"
		exponent="0.5"
		offset="0.2"
	/>
</feComponentTransfer>

feComponentTransfer

feColorMatrix

feColorMatrix

| R' |     | a00 a01 a02 a03 a04 |   | R |
| G' |     | a10 a11 a12 a13 a14 |   | G |
| B' |  =  | a20 a21 a22 a23 a24 | * | B |
| A' |     | a30 a31 a32 a33 a34 |   | A |
| 1  |     |  0   0   0   0   1  |   | 1 |

feColorMatrix

<feColorMatrix
type="matrix"
values="
	0.343 0.669 0.119 0 0
	0.249 0.626 0.130 0 0
	0.172 0.334 0.111 0 0
	0     0     0     1 0
"/>

feColorMatrix

feColorMatrix

feColorMatrix

Умножать на матрицу, что-бы сделать картинку чёрно-белой? о_О

feColorMatrix

<feColorMatrix type="saturate" values="0" />

feColorMatrix

<feColorMatrix type="saturate" values="4" />

feColorMatrix

<feColorMatrix type="saturate" values="50" />

feColorMatrix

<feColorMatrix type="hueRotate" values="0" />

feColorMatrix

<feColorMatrix type="hueRotate" values="120" />

feColorMatrix

<feColorMatrix type="hueRotate" values="240" />

feColorMatrix

<feColorMatrix type="hueRotate" values="320" />

feColorMatrix

<feColorMatrix type="luminanceToAlpha" />

feConvolveMatrix

feConvolveMatrix

<feConvolveMatrix order="3"
kernelMatrix="1 -1  1 -1 -1 -1 1 -1 1"/>

 1    -1     1
-1    -1    -1
1    -1     1

Classic #selfish #duckface

Classic #selfish #duckface

Fixed #selfish #duckface

Fixed #selfish #duckface

feConvolveMatrix

<feConvolveMatrix order="3"
kernelMatrix="1 -1 1 -1 -0.1 -1 1 -1 1"/>

feConvolveMatrix

<feConvolveMatrix order="3"
kernelMatrix="9 0 0 0 1 0 0 0 -9"/>

feConvolveMatrix

<feConvolveMatrix order="3"
kernelMatrix="-1 -1 -1 -1 7 -1 -1 -1 -1"/>

feConvolveMatrix

<feConvolveMatrix order="5"
kernelMatrix="1 1 1 1 1 1 -2 -2 -2 1 1 -2 0 -2 1 1 -2 -2 -2 1 1 1 1 1 1"/>

feComposite

feComposite

<feComposite
		in="source1"
		in2="source2"
		operator="xor"/>

feComposite

feBlend

feBlend

<feBlend
		in="source1"
		in2="source2"
		mode="lighten"/>

Blend modes

feTile

feTile

<feTile in="source" />

Польза от feTile (До)

Польза от feTile (После)

feDisplacementMap

feDisplacementMap

feDisplacementMap

Красный канал. 20 градусов

Cиний канал. -20 градусов

+ Неподвижный зеленый

Happy face

Happy face

Happy face lvl 40

Happy face lvl80

Возможности анимации

Синтаксис для SVG анимаций

<feColorMatrix type="saturate" values="0.2">

</feColorMatrix>

Синтаксис для SVG анимаций

<feColorMatrix type="saturate" values="0.2">
	<animate attributeName="values" />
</feColorMatrix>

Синтаксис для SVG анимаций

<feColorMatrix type="saturate" values="0.2">
	<animate attributeName="values" />
</feColorMatrix>

Синтаксис для SVG анимаций

<feColorMatrix type="saturate" values="0.2">
	<animate
		attributeName="values"
		values="0;5;0"
		dur="2s"
		repeatCount="indefinite"/>
</feColorMatrix>

Анимация feColorMatrix

Анимация feMorphology radius

Анимация feDisplacementMap scale

Немного хипстерства
для примера

Вновь девушка

1) Подчеркнем темные области

2) Blur по маске

3) Уменьшим цветовую насыщенность

4) Выделяем побольше красного

5) Затемнение по контуру

6) Подмешиваем текстуру

Вновь девушка

scary1

scary2

scary3

Достоинства SVG фильтров и почему мы выбрали их.

Недостатки SVG фильтров

SVG filters for html

Слайд про SVG filters for html

<svg>
	<defs>
		<filter id="f1">
			<feGaussianBlur  stdDeviation="10"/>
		</filter>
	</defs>
</svg>

img {
	-webkit-filter: url(#f1);
	filter: url(#f1);
}

Слайд про SVG filters for html

<svg>
	<defs>
		<filter id="f1">
			<feGaussianBlur stdDeviation="10 0"/>
		</filter>
	</defs>
</svg>

div {
	-webkit-filter: url(#f1);
	filter: url(#f1);
}

Вопросы?

goodbye

Fork me on Github