Преобразование изображения в оттенки серого в HTML / CSS

589

Есть ли простой способ отображения цветного растрового изображения в оттенках серого только с HTML/CSS?

Не нужно быть совместимым с IE (и я думаю, что этого не будет) - если он работает в FF3 и/или Sf3, это достаточно хорошо для меня.

Я знаю, что могу сделать это с помощью SVG и Canvas, но сейчас это похоже на большую работу.

Существует ли действительно ленивый способ сделать это?

  • 0
    Давно ушел вопрос ??
  • 14
    «Это не должно быть IE-совместимым (и я думаю, что не будет)» ?? IE предоставляет набор фильтров DX с 1997 года (IE4), который выполняет эту работу с помощью простого CSS и многого другого. Теперь они отказались от фильтров DX в IE10 и строго следуют стандартным фильтрам на основе SVG. Возможно, вы захотите взглянуть на это и это демо .
Показать ещё 3 комментария
Теги:
image
grayscale

25 ответов

688

Поддержка CSS-фильтров появилась в Webkit. Итак, теперь у нас есть кросс-браузерное решение.

img {
  filter: gray; /* IE6-9 */
  -webkit-filter: grayscale(1); /* Google Chrome, Safari 6+ & Opera 15+ */
  filter: grayscale(1); /* Microsoft Edge and Firefox 35+ */
}

/* Disable grayscale on hover */
img:hover {
  -webkit-filter: grayscale(0);
  filter: none;
}
<img src="http://lorempixel.com/400/200/">

Как насчет Internet Explorer 10?

Вы можете использовать polyfill как gray.

  • 3
    Я проверял это в IE 6,7,8 и 9 - отлично работает.
  • 0
    ах похоже на проблему с моим сервером ... спасибо salman!
Показать ещё 26 комментариев
129

В ответ на ответ brillout.com, а также ответ Роман Нурик, и немного смягчив "Нет SVG", вы можете обесцветить изображения в Firefox, используя только один SVG файл и некоторый CSS.

Ваш SVG файл будет выглядеть следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1"
     baseProfile="full"
     xmlns="http://www.w3.org/2000/svg">
    <filter id="desaturate">
        <feColorMatrix type="matrix" values="0.3333 0.3333 0.3333 0 0
                                             0.3333 0.3333 0.3333 0 0
                                             0.3333 0.3333 0.3333 0 0
                                             0      0      0      1 0"/>
    </filter>
</svg>

Сохраните это как resources.svg, теперь его можно повторно использовать для любого изображения, которое вы хотите изменить в оттенки серого.

В вашем CSS вы ссылаетесь на фильтр, используя специфическое для Firefox свойство filter:

.target {
    filter: url(resources.svg#desaturate);
}

Добавьте проприетарные приложения MS, если вам это нравится, применить этот класс к любому изображению, которое вы хотите преобразовать в оттенки серого (работает в Firefox > 3.5, IE8).

edit: Здесь хороший пост в блоге, в котором описывается использование нового свойства CSS3 filter в ответе SalmanPK в соответствии с подходом SVG, описанным здесь. Используя этот подход, вы получите что-то вроде:

img.desaturate{
    filter: gray; /* IE */
    -webkit-filter: grayscale(1); /* Old WebKit */
    -webkit-filter: grayscale(100%); /* New WebKit */
    filter: url(resources.svg#desaturate); /* older Firefox */
    filter: grayscale(100%); /* Current draft standard */
}

Дополнительная информация о поддержке браузера здесь.

  • 4
    Это чище, спасибо. К сожалению, не работает в WebKit
  • 6
    В webkit вы делаете это: -webkit-filter: grayscale(100%); тогда это: -webkit-filter: grayscale(0); : -webkit-filter: grayscale(0); удалить это.
Показать ещё 3 комментария
90

Для Firefox вам не нужно создавать файл filter.svg, вы можете использовать схему URI данных.

Взятие кода css первого ответа дает:

filter: url("data:image/svg+xml;utf8,<svg%20xmlns='http://www.w3.org/2000/svg'><filter%20id='grayscale'><feColorMatrix%20type='matrix'%20values='0.3333%200.3333%200.3333%200%200%200.3333%200.3333%200.3333%200%200%200.3333%200.3333%200.3333%200%200%200%200%200%201%200'/></filter></svg>#grayscale"); /* Firefox 3.5+ */
filter: grayscale(100%); /* Current draft standard */
-webkit-filter: grayscale(100%); /* New WebKit */
-moz-filter: grayscale(100%);
-ms-filter: grayscale(100%); 
-o-filter: grayscale(100%);
filter: gray; /* IE6+ */

Позаботьтесь о замене строки "utf-8" вашей кодировкой файла.

Этот метод должен быть быстрее другого, потому что браузеру не потребуется выполнять второй HTTP-запрос.

  • 3
    Просто примечание для сохранения головной боли: YUI Compressor удаляет пробелы в URL-адресах данных. Поэтому вы можете рассмотреть возможность использования другого миниатора, если хотите использовать это решение.
  • 6
    @Malte Или, может быть, просто заменить пробелы на строку "% 20"?
Показать ещё 4 комментария
23

Обновление: Я сделал это в полном репозитории GitHub, включая JavaScript polyfill для IE10 и IE11: https://github.com/karlhorky/gray

Я изначально использовал ответ SalmanPK, но затем создал вариант ниже, чтобы исключить дополнительный HTTP-запрос, необходимый для файла SVG. Встроенный SVG работает в версиях Firefox 10 и выше, а версии ниже 10 уже не учитывают даже 1% мирового рынка браузеров.

С тех пор я обновлял решение на этом сообщении в блоге, добавив поддержку для возврата к цвету, поддержка IE 10/11 с SVG и частичный оттенки серого в демо.

img.grayscale {
  /* Firefox 10+, Firefox on Android */
  filter: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='grayscale'><feColorMatrix type='matrix' values='0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0'/></filter></svg>#grayscale");

  /* IE 6-9 */
  filter: gray;

  /* Chrome 19+, Safari 6+, Safari 6+ iOS */
  -webkit-filter: grayscale(100%);
}

img.grayscale.disabled {
  filter: none;
  -webkit-filter: grayscale(0%);
}
14

Если вы можете использовать JavaScript, то этот script может быть тем, что вы ищете. Он работает с перекрестным браузером и отлично работает для меня до сих пор. Вы не можете использовать его с изображениями, загруженными из другого домена.

http://james.padolsey.com/demos/grayscale/

11

Сегодня у нас такая же проблема. Я изначально использовал решение SalmanPK, но выяснил, что этот эффект отличается между FF и другими браузерами. Это потому, что матрица преобразования работает только с легкостью, а не с яркостью, как фильтры в Chrome/IE. К моему удивлению, я обнаружил, что альтернативное и более простое решение в SVG также работает в FF4 + и дает лучшие результаты:

<svg xmlns="http://www.w3.org/2000/svg">
  <filter id="desaturate">
    <feColorMatrix type="saturate" values="0"/>
  </filter>
</svg>

С помощью css:

img {
    filter: url(filters.svg#desaturate); /* Firefox 3.5+ */
    filter: gray; /* IE6-9 */
    -webkit-filter: grayscale(1); /* Google Chrome & Safari 6+ */
}

Еще одно предостережение в том, что IE10 больше не поддерживает "filter: gray:" в стандартном режиме совместимости, поэтому для переключения режима совместимости в заголовках необходимо работать:

<meta http-equiv="X-UA-Compatible" content="IE=9" />
  • 2
    Кажется, лучшее и более простое решение - было бы хорошо, если бы SalmanPK и mquandalle обновили свои решения для этого. Видимо, используемая ими матрица не работает <br> <br> Вот версия встроенных данных: filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'saturate\' values=\'0\'/></filter></svg>#grayscale");
7

Для людей, которые спрашивают об игнорируемой поддержке IE10 + в других ответах, проверьте этот фрагмент CSS:

img.grayscale:hover {
    filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'1 0 0 0 0, 0 1 0 0 0, 0 0 1 0 0, 0 0 0 1 0\'/></filter></svg>#grayscale");
}

svg {
    background:url(http://4.bp.blogspot.com/-IzPWLqY4gJ0/T01CPzNb1KI/AAAAAAAACgA/_8uyj68QhFE/s400/a2cf7051-5952-4b39-aca3-4481976cb242.jpg);
}

svg image:hover {
    opacity: 0;
}

Используется для этой разметки:

<!DOCTYPE HTML>
<html>
<head>

    <title>Grayscaling in Internet Explorer 10+</title>

</head>
<body>

    <p>IE10 with inline SVG</p>
    <svg xmlns="http://www.w3.org/2000/svg" id="svgroot" viewBox="0 0 400 377" width="400" height="377">
      <defs>
         <filter id="filtersPicture">
           <feComposite result="inputTo_38" in="SourceGraphic" in2="SourceGraphic" operator="arithmetic" k1="0" k2="1" k3="0" k4="0" />
           <feColorMatrix id="filter_38" type="saturate" values="0" data-filterid="38" />
        </filter>
      </defs>
      <image filter="url(&quot;#filtersPicture&quot;)" x="0" y="0" width="400" height="377" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="http://4.bp.blogspot.com/-IzPWLqY4gJ0/T01CPzNb1KI/AAAAAAAACgA/_8uyj68QhFE/s1600/a2cf7051-5952-4b39-aca3-4481976cb242.jpg" />
    </svg>

</body>
</html>

Для более демонстрации, проверка IE testdrive раздел графики CSS3 и этот старый блог IE http://blogs.msdn.com/b/ie/archive/2011/10/14/svg-filter-effects-in-ie10.aspx

7

В Internet Explorer используйте свойство filter.

В webkit и Firefox в настоящее время не существует способа desatuarte изображения исключительно с помощью CSS. поэтому вам нужно будет использовать либо холст, либо SVG для решения на стороне клиента.

Но я думаю, что использование SVG более элегантно. проверьте мое сообщение в блоге для решения SVG, которое работает как для Firefox, так и для webkit: http://webdev.brillout.com/2010/10/desaturate-image-without-javascript.html

И строго говоря, поскольку SVG является HTML, решение является чистым html + css: -)

  • 0
    привет, брилаут Я заметил, что твоя шкала серого на сафари не работает. Любое продолжение? Спасибо
  • 1
    SVG это не HTML. Это совершенно другая спецификация.
Показать ещё 5 комментариев
7

Не похоже, что это возможно (пока), даже с CSS3 или проприетарными свойствами CSS -webkit- или -moz-.

Однако я нашел этот пост с прошлого июня, который использовал фильтры SVG для HTML. Не доступен в любом текущем браузере (демонстрация намечена на пользовательскую сборку WebKit), но очень впечатляет как доказательство концепции.

6

Новый способ сделать это уже давно доступен в современных браузерах.

background-blend-mode позволяет вам получать интересные эффекты, а один из них - преобразование в оттенки серого

Значение яркости, установленное на белом фоне, позволяет это. (наведите указатель мыши на серый)

.test {
  width: 300px;
  height: 200px;
    background: url("http://placekitten.com/1000/750"), white; 
    background-size: cover;
}

.test:hover {
    background-blend-mode: luminosity;
}
<div class="test"></div>

Светимость берется из изображения, цвет берется из фона. Поскольку он всегда белый, цвет отсутствует.

Но это позволяет гораздо больше.

Вы можете анимировать настройку эффекта 3 уровня. Первым будет изображение, а второе будет черно-черным градиентом. Если вы примените многократный режим смешивания, вы получите белый результат по-прежнему на белой части, но исходное изображение на черной части (умножить на белый дает белый цвет, умножение на черный не оказывает никакого эффекта.)

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

Теперь нужно всего лишь переместить градиент, чтобы этот эффект был динамическим: (наведите указатель мыши на цвет)

div {
    width: 600px;
    height: 400px;
}

.test {
    background: url("http://placekitten.com/1000/750"), 
linear-gradient(0deg, white 33%, black 66%), url("http://placekitten.com/1000/750"); 
    background-position: 0px 0px, 0px 0%, 0px 0px;
    background-size: cover, 100% 300%, cover;
    background-blend-mode: luminosity, multiply;
    transition: all 2s;
}

.test:hover {
    background-position: 0px 0px, 0px 66%, 0px 0px;
}
<div class="test"></div>

ссылка

матрица совместимости

  • 0
    Это не работает в IE 10
  • 0
    ... также не работает в IE11.
Показать ещё 3 комментария
4

Возможно, этот способ поможет вам

img {
    -webkit-filter: grayscale(100%); /* Chrome, Safari, Opera */
    filter: grayscale(100%);
}

w3schools.org

3

На самом деле это проще сделать с IE, если я правильно помню, используя собственное свойство CSS. Попробуйте FILTER: Gray от http://www.ssi-developer.net/css/visual-filters.shtml

Метод Ax просто делает изображение прозрачным и имеет черный фон позади него. Я уверен, что вы можете утверждать, что это оттенки серого.

Хотя вы не хотели использовать Javascript, я думаю, вам придется его использовать. Вы также можете использовать язык на стороне сервера.

  • 0
    У меня даже нет коробки с Windows, так что спасибо, но это мне мало пригодится.
  • 0
    В этом случае вы можете посмотреть на нее с помощью виртуальной машины с IE, реализовать метод ax или использовать canvas ... обратите внимание, что масштабирование в оттенках серого на больших изображениях с canvas может быть весьма затруднительным для движка Javascript.
Показать ещё 1 комментарий
2

Простейший способ сделать это

img {
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
filter: grayscale(100%);

}

2

Вам не нужно использовать так много префиксов для полного использования, потому что если вы выберете префикс для старого firefox, вам не нужно использовать префикс для нового firefox.

Итак, для полного использования достаточно использовать этот код:

img.grayscale {
    filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0\'/></filter></svg>#grayscale"); /* Firefox 10+, Firefox on Android */
    filter: gray; /* IE6-9 */
    -webkit-filter: grayscale(100%); /* Chrome 19+, Safari 6+, Safari 6+ iOS */
}

img.grayscale.disabled {
    filter: url("data:image/svg+xml;utf8,<svg xmlns=\'http://www.w3.org/2000/svg\'><filter id=\'grayscale\'><feColorMatrix type=\'matrix\' values=\'1 0 0 0 0, 0 1 0 0 0, 0 0 1 0 0, 0 0 0 1 0\'/></filter></svg>#grayscale");
    filter: none;
    -webkit-filter: grayscale(0%);
}
2

Здесь есть mixin для LESS, который позволит вам выбрать любую непрозрачность. Заполните сами переменные для простого CSS в разных процентах.

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

.saturate(@value:0) {
    @percent: percentage(@value);

    filter: url("data:image/svg+xml;utf8,<svg%20xmlns='http://www.w3.org/2000/svg'><filter%20id='grayscale'><feColorMatrix%20type='saturate'%20values='@value'/></filter></svg>#grayscale"); /* Firefox 3.5+ */
    filter: grayscale(@percent); /* Current draft standard */
    -webkit-filter: grayscale(@percent); /* New WebKit */
    -moz-filter: grayscale(@percent);
    -ms-filter: grayscale(@percent);
    -o-filter: grayscale(@percent);
}

Затем используйте его:

img.desaturate {
    transition: all 0.2s linear;
    .saturate(0);
    &:hover {
        .saturate(1);
    }
}
2

поддержка встроенных CSS-фильтров в webkit добавлена ​​из текущей версии 19.0.1084.46

so -webkit-filter: grayyscale (1) будет работать, и это проще, чем SVG-подход для webkit...

2

Если вы хотите использовать Javascript, вы можете использовать холст для преобразования изображения в оттенки серого. Поскольку Firefox и Safari поддерживают <canvas>, он должен работать.

Итак, я googled "холст оттенков серого", и первый результат был http://www.permadi.com/tutorial/jsCanvasGrayscale/index.html, который, похоже, работает.

1

В дополнение к другим ответам, можно обесцветить изображение на полпути на FF без головных болей матрицы SVG:

<feColorMatrix type="saturate" values="$v" />

Где $v находится между 0 и 1. Это эквивалентно filter:grayscale(50%);.

Пример в реальном времени:

.desaturate {
    filter: url("#desaturate");
    -webkit-filter: grayscale(50%);
}
figcaption{
    background: rgba(55, 55, 136, 1);
    padding: 4px 98px 0 18px;
    color: white;
    display: inline-block;
    border-top-left-radius: 8px;
    border-top-right-radius: 100%;
    font-family: "Helvetica";
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <filter id="desaturate">
  	<feColorMatrix type="saturate" values="0.4"/>
  </filter>
</svg>

<figure>
  <figcaption>Original</figcaption>
  <img src="http://www.placecage.com/c/500/200"/>
  </figure>
<figure>
  <figcaption>Half grayed</figcaption>
  <img class="desaturate" src="http://www.placecage.com/c/500/200"/>
</figure>

Ссылка на MDN

1

На основе ответа robertc:

Чтобы получить правильное преобразование из цветного изображения в изображение в оттенках серого вместо использования такой матрицы:

0.3333 0.3333 0.3333 0 0
0.3333 0.3333 0.3333 0 0
0.3333 0.3333 0.3333 0 0
0      0      0      1 0

Вы должны использовать матрицу преобразования следующим образом:

0.299 0.299 0.299 0
0.587 0.587 0.587 0
0.112 0.112 0.112 0
0     0     0     1

Это должно работать отлично для всех типов изображений на основе модели RGBA (red-green-blue-alpha).

Для получения дополнительной информации, почему вы должны использовать матрицу, я добавил, что robertc проверяет следующие ссылки:

  • 0
    Я согласен, что 0.3333 не так; 0.2126 0.7152 0.0722 0 0 является эквивалентом <fecolormatrix type="saturate" values="0">
  • 0
    Ссылку на «А здесь вы можете найти некоторые коды C # и VB» можно найти в интернет-архиве здесь: web.archive.org/web/20110220101001/http://www.bobpowell.net/…
Показать ещё 1 комментарий
0

Для оттенков серого в процентах в Firefox используйте фильтр насыщения вместо: (поиск "насыщенный" )

filter: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg'><filter id='saturate'><feColorMatrix in='SourceGraphic' type='saturate' values='0.2' /></filter></svg>#saturate"
0

Попробуйте этот плагин jquery. Хотя это не чистое решение HTML и CSS, но это ленивый способ добиться того, чего вы хотите. Вы можете настроить оттенки серого, чтобы наилучшим образом удовлетворить ваши потребности. Используйте его следующим образом:

$("#myImageID").tancolor();

Есть интерактивная демонстрация . Вы можете играть с ним.

Ознакомьтесь с документацией по использованию, это довольно просто. docs

0

Вы можете использовать одну из функций jFunc - использовать функцию "jFunc_CanvasFilterGrayscale" http://jfunc.com/jFunc-functions.aspx

0

be Альтернативой для более старого браузера может быть использование маски, создаваемой псевдоэлементами или встроенными тегами.

Абсолютное позиционирование, наведение img (или текстовая область, для которой не требуется клик и выбор) может точно имитировать эффекты цветовой шкалы, через rgba() или translucide png.

Он не даст ни одной цветовой гаммы, но оттеняет цвет вне диапазона.

тест на ручке кода с 10 различными цветами через псевдоэлемент, последний серый. http://codepen.io/gcyrillus/pen/nqpDd (перезагрузка для переключения на другое изображение)

0

Если вы или кто-то другой, столкнувшийся с подобной проблемой в будущем, открыты для PHP. (Я знаю, что вы сказали HTML/CSS, но, возможно, вы уже используете PHP в бэкэнд) Вот PHP-решение:

Я получил его из библиотеки PHP GD и добавил некоторую переменную для автоматизации процесса...

<?php
$img = @imagecreatefromgif("php.gif");

if ($img) $img_height = imagesy($img);
if ($img) $img_width = imagesx($img);

// Create image instances
$dest = imagecreatefromgif('php.gif');
$src = imagecreatefromgif('php.gif');

// Copy and merge - Gray = 20%
imagecopymergegray($dest, $src, 0, 0, 0, 0, $img_width, $img_height, 20);

// Output and free from memory
header('Content-Type: image/gif');
imagegif($dest);

imagedestroy($dest);
imagedestroy($src);

?>
  • 21
    Вопрос об использовании только HTML / CSS ...
  • 4
    @Tom, исходя из голосов и фаворитов по исходному вопросу, ОП - не единственный человек, который задавался вопросом, возможно ли это. Конечно, этот ответ может нарушать правила, но я не вижу смысла в том, чтобы опускать ответ, который может быть полезен для многих людей.
Показать ещё 5 комментариев
0

Одно ужасное, но работоспособное решение: визуализируйте изображение с помощью Flash-объекта, который затем дает вам все возможные преобразования во Flash.

Если ваши пользователи используют браузеры с краткими границами и , если Firefox 3.5 и Safari 4 поддерживают его (я не знаю, что это делать/будет), вы можете отрегулируйте атрибут цветового профиля CSS для изображения, установив его в URL-адрес профиля ICC в оттенках серого. Но это много, если!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню