Перевод картинки в серый средствами CSS

Серое в CSS (92.76КиБ) Экспериментировал в рамках прототипа для рабочего проекта с преобразованием изображения в серую гамму. Вообще, конечно, есть тег CANVAS, там это запросто, но интересно посмотреть появилось ли что-то в CSS со времён фильтров «Эксплорера». В IE с незапамятных времён (ещё с пятой версии) есть фильтр «gray», который даёт нужный эффект. Сейчас фильтры обзавелись префиксами и их рекомендуемый синтаксис иной, но суть та же:
.gray {
        filter: gray; /* IE 5+ */
        -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)"; /* new IE */
}
Я всё ждал когда же W3C «переизобретёт» микрософтские фильтры. Свершилось. Недавно появилась спецификация Filter Effects, которая, конечно, гораздо шире того, что когда-то предложили в «Микрософте», но основной смысл тот же, и даже некоторые фильтры похожи.

«Хром» включил в готовящуяся 18-ю версию эксперементальную поддержку этих фильтров:
.gray {
        -webkit-filter: grayscale(1); /* Chrome 18+ */
}
В «Опере» и «Файрфоксе» поддержки этих фильтров пока нет, но есть поддержка других — фильтров SVG. Можно, например, засунуть растровое изображение внутрь SVG и применить к нему нужный фильтр:
<svg style="width: 0; height: 0">
<filter id="gray">
<feColorMatrix type="saturate" values="0"/>
</filter>
</svg>

<!-- тут какой-то HTML код и вдруг понадобилась серая картика -->
<svg style="width:400px; height: 431px"><image xlink:href="/imgs/2008.11.27.jpg" width="100%" height="100%" filter="gray" /></svg>
Хорошие новости — SVG можно мешать с HTML. С версии 3.5 в «Файерфоксе» есть способ лучше — можно применять фильры SVG прямо к тегам HTML (и делать всякие другие чудесные штуки), правда все описания в документации почему-то относятся к XHTML или внешним ресурсам, но я обнаружил, что уже с четвёртой версии этот же трюк работает и с обычным HTML:
<style>
    .gray {
        filter: url(#gray);  /* Firefox 4+ */
    }
</style>

<svg style="width: 0; height: 0">
<filter id="gray">
<feColorMatrix type="saturate" values="0"/>
</filter>
</svg>

<body><img src="/imgs/2008.11.27.jpg" class="gray" /></body>
Добавлено позднее: в ходе дальнейших экспериментов оказалось, что в более ранних «Хромах» (нижнюю границу я пока не выяснил, но в моём 17-м работает), можно через CSS задавать фильтры для SVG, вот таким образом:
<style>
    .gray {
        -webkit-filter: url(#gray); /* Chrome ?? */
        -webkit-filter: grayscale(1); /* Chrome 18+ 
    }
</style>

<svg style="width: 0; height: 0">
<filter id="gray">
<feColorMatrix type="saturate" values="0"/>
</filter>
</svg>

<!-- тут HTML и внезапно понадобилась серая картинка -->

<svg style="width:400px; height: 431px"><image xlink:href="/imgs/2008.11.27.jpg" width="400" height="431" class="gray" /></svg>
При этом «Хром» требует, чтобы ширина и высота картинки были заданы в абсолютных единицах (остальные браузеры прекрасно понимают проценты).

Если собрать всё вместе, получается нижеприведённый код. Я поставил рядом два изображения: слева обычный элемент HTML img, справа — растр в SVG, по ссылке можно протестировать что поддерживает ваш браузер.
<html>
<meta http-equiv="X-UA-Compatible" content="IE=9" />
<style>
    .gray {
        cursor: pointer;

        filter: url(#gray);  /* Firefox 4+ */
        filter: gray; /* IE 5+ */
        -webkit-filter: url(#gray); /* Chrome ?? */
        -webkit-filter: grayscale(1); /* Chrome 18+ */
        -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(grayscale=1)"; /* new IE */
    }

    .gray:hover {
        filter: none;
        -webkit-filter: none;
        -ms-filter: none;
    }

</style>

<svg style="width: 0; height: 0">
<filter id="gray">
<feColorMatrix type="saturate" values="0"/>
</filter>
</svg>

<body>
<img src="/imgs/2008.11.27.jpg" class="gray" />
<svg style="width:400px; height: 431px"><image xlink:href="/imgs/2008.11.27.jpg" width="400" height="431" class="gray" /></svg>
</body>

</html>
Мне негде потестировать IE и тем более десятую версию, но я где-то читал, что из «десятки» убрали фильтры, поэтому я, на всякий случай, поставил режим совместимости с девятой версией в коде.
14 марта 2012 08:47

bolk (bolknote.ru)
14 марта 2012, 10:13

Протестировал встроенные браузеры.

«Андроид» 2.3.6 — не поддерживает ни один из способов.
«иОС» 5.1 — тоже.
WinPhone 7.5 — тоже.
MeeGo 1.2 — тоже.

SiMM (инкогнито)
14 марта 2012, 10:32, ответ предназначен bolk (bolknote.ru):

Я поставил рядом два изображения: слева обычный элемент HTML img, справа — растр в SVG
Правая картинка становится цветной, если навести на неё мышью.
Opera 11.61.1250 Win7

GreLI (инкогнито)
14 марта 2012, 10:32, ответ предназначен bolk (bolknote.ru):

Хм, говорят, Андроид начал поддерживать SVG только с 4-й версии. Раньше разве что через object. iOS вроде как SVG поддерживает, но как именно, я не знаю. Наверное, стоит продолжить эксперименты с SVG. А ещё на телефонах есть Opera Mobile и Opera Mini :).

Андрей (инкогнито)
14 марта 2012, 10:34

Win7 IE9: работает левый способ, правый все время цветной.

Eyeless (инкогнито)
14 марта 2012, 10:35

ЭксперИмент

praeivis (praeivis.lt)
14 марта 2012, 10:49, ответ предназначен bolk (bolknote.ru):

что W7 IE9, что W8 IE10 левая серая становится цветной эсли навести мишкой. W7 FF11 обе серие но с мишкой становится цветними.

bolk (bolknote.ru)
14 марта 2012, 10:55, ответ предназначен SiMM

Правая картинка становится цветной, если навести на неё мышью.
Opera 11.61.1250 Win7
Ну да, там hover.

bolk (bolknote.ru)
14 марта 2012, 10:56, ответ предназначен Eyeless

ЭксперИмент
Спасибо! Глазастый!

bolk (bolknote.ru)
14 марта 2012, 10:57, ответ предназначен GreLI

Хм, говорят, Андроид начал поддерживать SVG только с 4-й версии. Раньше разве что через object. iOS вроде как SVG поддерживает, но как именно, я не знаю. Наверное, стоит продолжить эксперименты с SVG. А ещё на телефонах есть Opera Mobile и Opera Mini :).
«Поддерживать SVG» это как «поддерживать CSS». У SVG туча версий и расширений. Что-то может поддерживаться, что-то другое — нет. Фильтры, видимо, не поддерживаются.

Никита (инкогнито)
14 марта 2012, 11:02

Хром 17.0.963.79 Мак Лев не работает.

bolk (bolknote.ru)
14 марта 2012, 11:17, ответ предназначен Никите

В «Хроме» только с версии 18 будет работать.

bolk (bolknote.ru)
14 марта 2012, 16:10

В «Хроме» будет работать следующее:

<svg style="width: 0; height: 0">
<filter id="gray">
<feColorMatrix type="saturate" values="0"/>
</filter>
</svg>
<!-- тут какой-то HTML -->
<svg style="width:400px; height: 431px"><image xlink:href="http://bolknote.ru/imgs/2008.11.27.jpg" width="400" height="431" filter="url(#gray)" /></svg>

bolk (bolknote.ru)
14 марта 2012, 16:33

Сделал способ для «Хрома», позволяющий переводить картинку в серый через подключение CSS-стиля к SVG. Обновил статью.

bolk (bolknote.ru)
14 марта 2012, 16:42

Таким образом, единственный настольный браузер, который никак не охвачен — «Сафари», в нём обещают поддержку фильтров SVG только в шестой версии.

Orcinus Orca (www.orcinus.ru)
15 марта 2012, 07:20

Сам искал простенький метод перевода в серые тона. Но простыми манипуляциями с CSS не вышло. Будем ждать когда разработают нормальные фильтры.

bolk (bolknote.ru)
15 марта 2012, 08:17, ответ предназначен Orcinus Orca (www.orcinus.ru):

Самый простенький — грузить в «канвас». Много где работать будет.

TATAPuH (инкогнито)
15 марта 2012, 16:40

http://vhardy.github.com/presentations/html5-now-next-2011/index.html#/28
интересна конечно вся презентация, но даю ссылку сразу на последний слайд (содержит ссылки на семплы)
П.С. фильтры и канвас это конечно круто, вебГл ещё круче
но к сожалению сносно работает только в десктопе

bolk (bolknote.ru)
15 марта 2012, 18:48, ответ предназначен TATAPuH

П.С. фильтры и канвас это конечно круто, вебГл ещё круче
ВебГЛ — это контекст канваса, то есть его часть.

bolk (bolknote.ru)
15 марта 2012, 18:49, ответ предназначен TATAPuH

И не очень понятно зачем в этой задаче привлекать ВебГЛ.

TATAPuH (инкогнито)
17 марта 2012, 03:16, ответ предназначен bolk (bolknote.ru):

хм, э хм
ну скорость как бы ? не ?
картинка 100x100 обрабатывается достаточно быстро
1600х1200 уже очень даже не быстро
обработка 1000000х10000000 просто не работает (естественно что работаем только с видимой частью, тайлы и так далее,но - там чуть чуть тут немного и всё, тормозим)
для этого и ВебГЛ, доступ к шейдерам, а значит к GPU и паралельности

TATAPuH (инкогнито)
17 марта 2012, 03:23, ответ предназначен bolk (bolknote.ru):

в любом случае, на пост PS это пока не работает, а жаль (под термином "пост PS", я имею ввиду всяческие айПады и андроиды разные)
поэтому большая часть пиксельного рендеринга обычно уходит в облака (на сервера)
как ни странно получить готовый тайл из облака, обычно быстрее чем его подготовить локально через фильтры (если они есть) или поПиксельный доступ

bolk (bolknote.ru)
17 марта 2012, 14:50, ответ предназначен TATAPuH

хм, э хм
ну скорость как бы ? не ?
картинка 100x100 обрабатывается достаточно быстро
Ну так она и 2Д-канвасом быстро обработается. И фильтром, если GPU использовать. Причём тут ВебГЛ?

TATAPuH (инкогнито)
17 марта 2012, 15:58, ответ предназначен bolk (bolknote.ru):

по ссылке не ходил но осуждаю :)
на 28 слайде презентации есть ссылка
Evan Wallace's WebGL filters
http://evanw.github.com/webgl-filter/

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

bolk (bolknote.ru)
17 марта 2012, 16:53, ответ предназначен TATAPuH

По ссылке я был, там ничего особенного.

Да я в теме, знаю и что такое и ВебГЛ, и СВГ, и 2Д-канвас. Всё это вполне ускоряется через GPU, свет клином на ВебГЛ не сошёлся.

TATAPuH (инкогнито)
17 марта 2012, 17:06, ответ предназначен bolk (bolknote.ru):

2D канвас в целом и пиксельный доступ в частности, не ускоряется через GPU (на данный момент только ослик старается всегда работать через GPU до тех пор пока нет обращения к памяти (к пикселям))
http://upload.wikimedia.org/wikipedia/commons/d/d9/Seismic_wave_prop_mine.gif вот картинка для затравки (но представьте что она увас на весь экран)
тоже казалось бы просто "фильтры и попиксельный доступ"

лет 5 назад витали подобные настроения, мол в десктоп стремительно ворвался WPF теперь заживём, всё мол само собой ускорится засчёт GPU, нет
всё само собой не случается

bolk (bolknote.ru)
17 марта 2012, 20:35, ответ предназначен TATAPuH

Вы мне вещи какие-то странные объясняете…

Во-первых, можно ускорять заливку, наложение текстур и так далее, то есть чисто двухмерные штуки. 2D-видекарты справлялись с этим ещё десять лет назад (всякие Matrix Millenium). Это к вопросу о том что можно ускорить на «плоском» канвасе.

Во-вторых, есть только воображаемая разница. Фильтр размытия у SVG или CSS делается ровно теми же средствами, на том же GPU, как и WebGL-фильтры. WebGL — это просто более низкий уровень и всё.

И, да, я уверен, что фильтры SVG содержат фильтры не на все случаи жизни (и зачем им их содержать)? Куда вас понесло-то? Я же про grayscale говорил.

TATAPuH (инкогнито)
21 марта 2012, 03:54

извините, видимо кто о чём а вшивый о :)
один из проектов сейчас, это как раз порт существующего 2д тулкита в canvas (понятно что о полноценном 3д в броузерах пока говорить рано), в том числе той части которая рендерит различные сейсмики (и динамику тоже), а веселее всего то, что одна из таргетных платформ это именно iPod и прочие пост ПС девайсы (нефтяники их очень любят, не знаю уж за что)

вот и прокоментировал, что всё это очень круто а вебГл для 2д обработки вообще замечательно, но вот не всегда и не везде выручает

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)