Пишу, по большей части, про историю, свою жизнь и немного про программирование.

Перевод картинки в серый средствами 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 и тем более десятую версию, но я где-то читал, что из «десятки» убрали фильтры, поэтому я, на всякий случай, поставил режим совместимости с девятой версией в коде.

27 комментариев
Евгений Степанищев (bolknote.ru) 2012

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

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

SiMM 2012

Комментарий для Евгения Степанищева:

Я поставил рядом два изображения: слева обычный элемент HTML img, справа — растр в SVG

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

GreLI 2012

Комментарий для Евгения Степанищева:

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

Андрей 2012

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

Eyeless 2012

ЭксперИмент

praeivis (praeivis.lt) 2012

Комментарий для Евгения Степанищева:

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

Евгений Степанищев (bolknote.ru) 2012

Комментарий для SiMM:

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

Ну да, там hover.

Евгений Степанищев (bolknote.ru) 2012

Комментарий для Eyeless:

ЭксперИмент

Спасибо! Глазастый!

Евгений Степанищев (bolknote.ru) 2012

Комментарий для GreLI:

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

«Поддерживать SVG» это как «поддерживать CSS». У SVG туча версий и расширений. Что-то может поддерживаться, что-то другое — нет. Фильтры, видимо, не поддерживаются.

Никита 2012

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

Евгений Степанищев (bolknote.ru) 2012

Комментарий для Никита:

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

Евгений Степанищев (bolknote.ru) 2012

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

<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%22 width=«400» height=«431» filter=«url(#gray)» /></svg>

Евгений Степанищев (bolknote.ru) 2012

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

Евгений Степанищев (bolknote.ru) 2012

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

Orcinus Orca (www.orcinus.ru) 2012

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

Евгений Степанищев (bolknote.ru) 2012

Комментарий для www.orcinus.ru:

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

TATAPuH 2012

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

Евгений Степанищев (bolknote.ru) 2012

Комментарий для TATAPuH:

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

ВебГЛ — это контекст канваса, то есть его часть.

Евгений Степанищев (bolknote.ru) 2012

Комментарий для TATAPuH:

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

TATAPuH 2012

Комментарий для Евгения Степанищева:

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

TATAPuH 2012

Комментарий для Евгения Степанищева:

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

Евгений Степанищев (bolknote.ru) 2012

Комментарий для TATAPuH:

хм, э хм
ну скорость как бы ? не ?
картинка 100x100 обрабатывается достаточно быстро

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

TATAPuH 2012

Комментарий для Евгения Степанищева:

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

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

Евгений Степанищев (bolknote.ru) 2012

Комментарий для TATAPuH:

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

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

TATAPuH 2012

Комментарий для Евгения Степанищева:

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

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

Евгений Степанищев (bolknote.ru) 2012

Комментарий для TATAPuH:

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

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

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

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

TATAPuH 2012

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

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