web-dev-qa-db-fra.com

Convertir une image en niveaux de gris en HTML / CSS

Existe-t-il un moyen simple d’afficher un bitmap couleur en niveaux de gris avec seulement HTML/CSS?

Il n'a pas besoin d'être compatible avec IE (et j'imagine que ce ne sera pas le cas) - si cela fonctionne en FF3 et/ou en Sf3, c'est suffisant pour moi.

Je sais que je peux le faire avec SVG et Canvas, mais cela me semble beaucoup de travail pour le moment.

Y a-t-il une manière vraiment paresseuse de faire ceci?

601
Ken

Le support pour les filtres CSS a atterri dans Webkit. Nous avons donc maintenant une solution multi-navigateurs.

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/">

Qu'en est-il d'Internet Explorer 10?

Vous pouvez utiliser un polyfill comme gris .

708
Salman for Hire

Après réponse de brillout.com , et aussi réponse de Roman Nurik , et en relâchant quelque peu l'exigence 'sans SVG', vous pouvez désaturer des images dans Firefox en utilisant un seul SVG. fichier et des CSS.

Votre fichier SVG ressemblera à ceci:

<?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>

Enregistrez cela sous resources.svg, il peut désormais être réutilisé pour toute image que vous voulez changer en niveaux de gris.

Dans votre CSS, vous référencez le filtre à l'aide de la propriété filter spécifique à Firefox:

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

Ajoutez également ceux qui sont propriétaires de MS si vous en avez envie, appliquez cette classe à toute image que vous souhaitez convertir en niveaux de gris (fonctionne dans Firefox> 3.5, IE8) .

edit : Voici un billet de blog de Nice qui décrit l'utilisation de la nouvelle propriété CSS3 filter dans la réponse de SalmanPK de concert avec l'approche SVG décrite ici. En utilisant cette approche, vous obtiendrez quelque chose comme:

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 */
}

Plus d'informations sur le support du navigateur ici .

125
robertc

Pour Firefox, vous n'avez pas besoin de créer un fichier filter.svg, vous pouvez utiliser schéma d'URI des données .

Reprendre le code css de la première réponse donne:

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+ */

Prenez soin de remplacer la chaîne "utf-8" par votre encodage de fichier.

Cette méthode devrait être plus rapide que l'autre car le navigateur n'aura pas besoin de faire une seconde requête HTTP.

85
mquandalle

Mise à jour: Je l'ai transformé en un référentiel GitHub complet, y compris JavaScript polyfill pour IE10 et IE11: https://github.com/karlhorky/gris

J'ai utilisé à l'origine réponse de SalmanPK , mais j'ai ensuite créé la variante ci-dessous pour éliminer la requête HTTP supplémentaire requise pour le fichier SVG. Le SVG intégré fonctionne dans les versions 10 et supérieures de Firefox, et les versions inférieures à 10 ne représentent même plus 1% du marché mondial des navigateurs.

Depuis lors, je garde la solution à jour sur cet article de blog , en ajoutant un support pour la réduction progressive des couleurs, IE 10/11 avec SVG et des niveaux de gris partiels dans la démo.

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%);
}
26
Karl Horky

Si vous êtes capable d'utiliser JavaScript, alors ce script peut être ce que vous recherchez. Cela fonctionne multi-navigateur et fonctionne très bien pour moi jusqu'à présent. Vous ne pouvez pas l'utiliser avec des images chargées à partir d'un domaine différent.

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

14
chrismacp

Je viens d'avoir le même problème aujourd'hui. J'ai utilisé initialement solution SalmanPK , mais j'ai découvert que cet effet diffère entre FF et les autres navigateurs. En effet, la matrice de conversion ne fonctionne que sur la luminosité, pas sur la luminosité, contrairement aux filtres dans Chrome/IE. À ma grande surprise, j'ai découvert qu'une solution alternative et plus simple en SVG fonctionne également en FF4 + et produit de meilleurs résultats:

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

Avec css:

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

Une mise en garde supplémentaire est que IE10 ne prend plus en charge "filter: gray:" en mode conforme aux normes, il faut donc que le commutateur de mode de compatibilité dans les en-têtes fonctionne:

<meta http-equiv="X-UA-Compatible" content="IE=9" />
11
RobertT

Le moyen le plus simple d’obtenir des niveaux de gris avec CSS uniquement consiste à utiliser la propriété filter.

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

La propriété n'est toujours pas entièrement prise en charge et nécessite toujours la propriété -webkit-filter pour la prise en charge de tous les navigateurs.

10
NK Chaudhary

Cela ne semble pas (encore) possible, même avec CSS3 ou les propriétés propriétaires -webkit- ou -moz- CSS.

Cependant, j'ai trouvé ce message de juin dernier qui utilisait des filtres SVG en HTML. Non disponible dans aucun navigateur actuel (la démo faisait allusion à une version WebKit personnalisée), mais très impressionnant comme preuve de concept.

7
Roman Nurik

Pour les personnes qui posent des questions sur la prise en charge ignorée d'IE10 + dans d'autres réponses, consultez ce morceau de 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;
}

Appliqué sur ce balisage:

<!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>

Pour plus de démos, consultez IE testdrive's section Graphiques CSS et ce vieux IE blog http://blogs.msdn.com/b/ c'est-à-dire/archive/2011/10/14/svg-filter-effects-in-ie10.aspx

7
Annie

Dans Internet Explorer, utilisez la propriété filter.

Dans Webkit et Firefox, il n’existe actuellement aucun moyen de désatuarte une image uniquement avec CSS. vous devrez donc utiliser canvas ou SVG pour une solution côté client.

Mais je pense que l'utilisation de SVG est plus élégante. Consultez mon billet de blog pour la solution SVG qui fonctionne à la fois pour Firefox et pour le Webkit: http://webdev.brillout.com/2010/10/desaturate-image-without-javascript.html

Et à proprement parler, puisque SVG est HTML, la solution est pure html + css :-)

7
brillout

Une nouvelle façon de faire est disponible depuis un certain temps sur les navigateurs modernes.

background-blend-mode vous permet d'obtenir certains effets intéressants, dont l'un est la conversion en niveaux de gris.

La valeur luminosité , définie sur un fond blanc, le permet. (survolez pour le voir en gris)

.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>

La luminosité provient de l'image, la couleur de l'arrière-plan. Comme il est toujours blanc, il n'y a pas de couleur.

Mais cela permet beaucoup plus.

Vous pouvez animer le réglage de l'effet en 3 couches. Le premier sera l'image et le second sera un dégradé blanc-noir. Si vous appliquez un mode de dégradé multiplié sur ce point, vous obtiendrez un résultat en blanc identique à celui de la partie blanche, mais l'image d'origine sur la partie noire (multiplier par blanc donne blanc, la multiplication par noir n'a aucun effet.)

Sur la partie blanche du dégradé, vous obtenez le même effet qu'auparavant. Sur la partie noire du dégradé, vous êtes en train de mélanger l'image sur elle-même et le résultat est l'image non modifiée.

Maintenant, il suffit de déplacer le dégradé pour obtenir cet effet dynamique: (survolez-le pour le voir en couleur)

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>

référence

matrice de compatibilité

6
vals
img {
    -webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
    filter: grayscale(100%);
}
5
Amee

Peut-être que de cette façon vous aider

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

w3schools.org

4
YuZA

Il est en fait plus facile de le faire avec IE si je me souviens bien d'utiliser une propriété CSS propriétaire. Essayez ceci FILTER: Gray de http://www.ssi-developer.net/css/visual-filters.shtml

La méthode par Ax rend simplement l'image transparente et a un fond noir derrière celle-ci. Je suis sûr que vous pourriez dire que c'est en niveaux de gris.

Bien que vous ne vouliez pas utiliser Javascript, je pense que vous devrez l’utiliser. Vous pouvez également utiliser un langage côté serveur pour le faire.

3
alex

Si vous souhaitez utiliser Javascript, vous pouvez utiliser un canevas pour convertir l’image en niveaux de gris. Puisque Firefox et Safari prennent en charge <canvas>, cela devrait fonctionner.

J'ai donc cherché "toile en niveaux de gris" sur Google, et le premier résultat était http://www.permadi.com/tutorial/jsCanvasGrayscale/index.html qui semble fonctionner.

2
Shalom Craimer

Vous n'avez pas besoin d'utiliser autant de préfixes pour une utilisation complète, car si vous choisissez le préfixe pour old firefox, vous n'avez pas besoin de préfixe d'utilisation pour new firefox.

Donc, pour une utilisation complète, utilisez assez ce code:

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
maťo

Voici un mixin pour LESS qui vous permettra de choisir n'importe quelle opacité. Remplissez les variables vous-même pour CSS simple à différents pourcentages.

Astuce soignée ici, il utilise le type saturate pour la matrice, vous n'avez donc rien à faire de fantaisie pour changer le pourcentage.

.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);
}

Alors utilisez-le:

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

la prise en charge des filtres CSS natifs dans Webkit a été ajoutée à partir de la version actuelle 19.0.1084.46.

so -webkit-filter: grayscale (1) fonctionnera, ce qui est plus facile que l'approche SVG pour webkit ...

2
hjindal

En complément des réponses des autres, il est possible de désaturer une image à mi-parcours sur FF sans les maux de tête de la matrice SVG :

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

$v est compris entre 0 et 1. C'est équivalent à filter:grayscale(50%);.

Exemple en direct:

.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>

référence sur MDN

1
Bigood

Basé sur réponse de robertc :

Pour obtenir une conversion correcte d'une image colorée en une image en niveaux de gris au lieu d'utiliser une matrice comme celle-ci:

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

Vous devriez utiliser la matrice de conversion comme ceci:

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

Cela devrait fonctionner correctement pour tous les types d'images basées sur le modèle RGBA (rouge-vert-bleu-alpha).

Pour plus d’informations sur les raisons pour lesquelles vous devriez utiliser la matrice, j’ai posté plus de chances que celui de robertc vérifie les liens suivants:

1
Kajiyama

Pour les niveaux de gris sous forme de pourcentage dans Firefox, utilisez filtre de saturation à la place: (recherchez "saturer")

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
dval

be Une alternative à un navigateur plus ancien pourrait être d'utiliser un masque produit par des pseudo-éléments ou des balises inline.

Un positionnement absolu survolant un img (ou une zone de texte ne nécessitant ni clic ni sélection) peut reproduire fidèlement les effets d'échelle de couleur, via rgba () ou translucide png .

Il ne donnera pas une seule échelle de couleurs, mais nuira aux couleurs hors gamme.

test sur un stylo code avec 10 couleurs différentes via un pseudo-élément, le dernier est gris. http://codepen.io/gcyrillus/pen/nqpDd (rechargez pour passer à une autre image)

0
G-Cyr

Une solution terrible mais réalisable: restituez l'image à l'aide d'un objet Flash, qui vous donne ensuite toutes les transformations possibles dans Flash.

Si vos utilisateurs utilisent des navigateurs bleeding-Edge et si Firefox 3.5 et Safari 4 le prennent en charge (je ne sais pas si ce soit le cas/le fera), vous pouvez ajuster le CSS color-profile attribut de l'image, en le définissant comme URL de profil ICC en niveaux de gris. Mais c'est beaucoup de si!

0
richardtallent

Si vous, ou quelqu'un d'autre confronté à un problème similaire à l'avenir, êtes ouvert à PHP. (Je sais que vous avez dit HTML/CSS, mais peut-être que vous utilisez déjà PHP dans le backend) Voici une solution PHP:

Je l'ai eu de la bibliothèque PHP Gd et j'ai ajouté une variable pour automatiser le processus ...

<?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);

?>
0
Trufa

Vous pouvez utiliser l’une des fonctions de jFunc - utilisez la fonction "jFunc_CanvasFilterGrayscale" http://jfunc.com/jFunc-functions.aspx

0
Dany Maor

Essayez ce plugin JQuery. Bien que ce ne soit pas une solution HTML et CSS pure, mais une manière paresseuse d’atteindre ce que vous voulez. Vous pouvez personnaliser votre échelle de gris en fonction de votre utilisation. Utilisez-le comme suit:

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

Il y a une démo interactive . Vous pouvez jouer avec elle.

Consultez la documentation sur l'utilisation, c'est assez simple. docs

0
Nicholas TJ