wake-up-neo.net

Converti un'immagine in scala di grigi in HTML/CSS

C'è un modo semplice per visualizzare una bitmap a colori in scala di grigi con solo HTML/CSS?

Non ha bisogno di essere compatibile con IE (e immagino che non lo sia) - se funziona in FF3 e/o in Sf3, è abbastanza buono per me.

So che posso farlo sia con SVG sia con Canvas, ma al momento sembra molto lavoro.

C'è un modo veramente pigro per farlo?

593
Ken

Il supporto per i filtri CSS è arrivato su Webkit. Così ora abbiamo una soluzione cross-browser.

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

Che dire di Internet Explorer 10?

Puoi usare un polyfill come grigio .

696
Salman Abbas

Seguendo la risposta di brillout.com , e anche la risposta di Roman Nurik , e rilassando un po 'il requisito' no SVG ', è possibile desaturare le immagini in Firefox usando solo un singolo file SVG e alcuni CSS.

Il tuo file SVG sarà simile a questo:

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

Salvalo come resources.svg, può essere riutilizzato d'ora in poi per qualsiasi immagine che desideri modificare in scala di grigi.

Nel tuo CSS fai riferimento al filtro usando la proprietà filter specifica per Firefox:

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

Aggiungi anche quelli proprietari di MS, se ne hai voglia, applica quella classe a qualsiasi immagine che vuoi convertire in scala di grigi (funziona in Firefox> 3.5, IE8) .

edit : Ecco un bel post sul blog che descrive l'uso della nuova proprietà filter di CSS3 nella risposta di SalmanPK in accordo con l'approccio SVG descritto qui. Usando questo approccio ti ritroverai con qualcosa come:

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

Ulteriori informazioni sul supporto del browser qui .

126
robertc

Per Firefox non è necessario creare un file filter.svg, è possibile utilizzare schema URI di dati .

Riprendendo il codice CSS della prima risposta si ottiene:

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

Abbi cura di sostituire la stringa "utf-8" con la codifica dei file.

Questo metodo dovrebbe essere più veloce dell'altro perché il browser non dovrà eseguire una seconda richiesta HTTP.

85
mquandalle

Aggiornamento: Ho fatto questo in un repository completo di GitHub, incluso il polyfill di JavaScript per IE10 e IE11: https://github.com/karlhorky/gray

Inizialmente ho usato la risposta di SalmanPK , ma poi ho creato la variante seguente per eliminare la richiesta HTTP aggiuntiva richiesta per il file SVG. L'SVG inline funziona nelle versioni di Firefox 10 e successive e le versioni inferiori a 10 non rappresentano più nemmeno l'1% del mercato globale dei browser.

Da allora ho aggiornato la soluzione su questo post sul blog , aggiungendo il supporto per il dissolvenza a colori, IE 10/11 di supporto con SVG e parziale scala di grigi nella demo.

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

Se sei in grado di usare JavaScript, allora questo script potrebbe essere quello che stai cercando. Funziona cross browser e sta funzionando bene per me finora. Non è possibile utilizzarlo con immagini caricate da un dominio diverso.

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

14
chrismacp

Ho appena avuto lo stesso problema oggi. Inizialmente ho usato soluzione SalmanPK ma ho scoperto che l'effetto differisce tra FF e altri browser. Questo perché la matrice di conversione funziona solo sulla luminosità e non sulla luminosità come i filtri in Chrome/IE. Con mia sorpresa ho scoperto che la soluzione alternativa e più semplice in SVG funziona anche in FF4 + e produce risultati migliori:

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

Con css:

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

Un altro avvertimento è che IE10 non supporta più il "filtro: grigio:" in modalità conforme agli standard, quindi è necessario attivare la modalità di compatibilità nelle intestazioni per funzionare:

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

Il modo più semplice per ottenere la scala di grigi con i CSS è esclusivamente tramite la proprietà filter.

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

La proprietà non è ancora completamente supportata e richiede ancora la proprietà -webkit-filter per il supporto su tutti i browser.

10
NK Chaudhary

Non sembra che sia possibile (ancora), anche con CSS3 o proprietà -webkit- proprietarie o -moz- CSS.

Tuttavia, ho trovato questo post dello scorso giugno che utilizzava i filtri SVG su HTML. Non disponibile in nessun browser corrente (la demo suggeriva una build WebKit personalizzata), ma molto impressionante come prova del concetto.

7
Roman Nurik

Per le persone che stanno chiedendo il supporto ignorato IE10 + in altre risposte, controlla questa parte di 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;
}

Applicato su questo markup:

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

Per ulteriori demo, checkout IE testdrive's sezione grafica CSS3 e questo vecchio IE blog http://blogs.msdn.com/b/ie/archive/2011 /10/14/svg-filter-effects-in-ie10.aspx

7
Annie

In Internet Explorer usa la proprietà filter.

In webkit e Firefox non esiste attualmente alcun modo di desatuare un'immagine esclusivamente con i CSS. quindi sarà necessario utilizzare canvas o SVG per una soluzione lato client.

Ma penso che l'uso di SVG sia più elegante. controlla il mio post sul blog per la soluzione SVG che funziona sia per Firefox che per il webkit: http://webdev.brillout.com/2010/10/desaturate-image-without-javascript.html

E in senso stretto dal momento che SVG è HTML, la soluzione è pure html + css :-)

7
brillout

Un nuovo modo per farlo è disponibile da qualche tempo sui browser moderni.

background-blend-mode consente di ottenere alcuni effetti interessanti, e uno di questi è la conversione in scala di grigi

Il valore luminosità, impostato su uno sfondo bianco, lo consente. (passa con il mouse per vederlo in grigio)

.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à è presa dall'immagine, il colore è preso dallo sfondo. Poiché è sempre bianco, non c'è colore.

Ma permette molto di più.

Puoi animare l'effetto impostando 3 livelli. Il primo sarà l'immagine e il secondo sarà un gradiente bianco-nero. Se applichi una modalità di miscela multipla su questo, otterrai un risultato bianco come prima sulla parte bianca, ma l'immagine originale sulla parte nera (moltiplicandola per il bianco dà il bianco, moltiplicando per il nero non ha effetto).

Sulla parte bianca del gradiente, ottieni lo stesso effetto di prima. Sulla parte nera del gradiente, si fonde l'immagine su se stessa e il risultato è l'immagine non modificata.

Ora, tutto ciò che serve è spostare la sfumatura per ottenere questo effetto dinamico: (passa con il mouse per vederlo a colori)

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>

riferimento

matrice di compatibilità

6
vals

Forse in questo modo ti può aiutare

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

w3schools.org

4
YuZA

È infatti più facile farlo con IE se ricordo di aver usato correttamente una proprietà CSS proprietaria. Prova questo FILTER: Gray da http://www.ssi-developer.net/css/visual-filters.shtml

Il metodo di Ax rende semplicemente l'immagine trasparente e ha uno sfondo nero dietro di esso. Sono sicuro che potresti obiettare che questo è in scala di grigi.

Anche se non volevi usare Javascript, penso che dovrai usarlo. Puoi anche usare un linguaggio lato server per farlo.

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

Se sei disposto ad usare Javascript, puoi usare una tela per convertire l'immagine in scala di grigi. Poiché Firefox e Safari supportano <canvas>, dovrebbe funzionare.

Ho quindi cercato su google "in scala di grigi" e il primo risultato era http://www.permadi.com/tutorial/jsCanvasGrayscale/index.html che sembra funzionare.

2
Shalom Craimer

Non è necessario utilizzare tanti prefissi per il pieno utilizzo, perché se si sceglie il prefisso per il vecchio firefox, non è necessario utilizzare il prefisso per il nuovo firefox.

Quindi per il pieno utilizzo, basta usare questo codice:

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

Ecco un mixin per LESS che ti permetterà di scegliere qualsiasi opacità. Inserisci le variabili per un semplice CSS a percentuali diverse.

Suggerimento neat qui , usa il tipo saturo per la matrice in modo da non aver bisogno di fare niente per modificare la percentuale.

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

Quindi usalo:

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

il supporto per i filtri CSS nativi nel webkit è stato aggiunto dalla versione corrente 19.0.1084.46

so -webkit-filter: la scala di grigi (1) funzionerà e quale è più facile dell'approccio SVG per il webkit ...

2
hjindal

Come complemento alle altre risposte, è possibile desaturare un'immagine a metà strada su FF senza SVG's matrix's headache:

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

Dove $v è compreso tra 0 e 1. È equivalente a filter:grayscale(50%);.

Esempio dal vivo:

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

Riferimento su MDN

1
Bigood

Basato su risposta di robertc :

Per ottenere proper conversione dall'immagine colorata all'immagine in scala di grigi invece di usare la matrice come questa:

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

Dovresti usare la matrice di conversione in questo modo:

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

Questo dovrebbe funzionare bene per tutti i tipi di immagini basate sul modello RGBA (rosso-verde-blu-alfa).

Per ulteriori informazioni sul motivo per cui dovresti usare matrix, ho postato più probabile che l'unico controllo di robertc sia il seguente:

1
Kajiyama

Per quanto riguarda la scala di grigi come percentuale in Firefox, usa saturazione filtro invece: (cerca 'saturo')

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 Un'alternativa per il browser più vecchio potrebbe essere quella di usare una maschera prodotta da pseudo-elementi o tag in linea.

Posizionamento assoluto al passaggio del mouse su una img (o area di testo che non ha bisogno di clic o selezione) può simulare da vicino gli effetti della scala dei colori, via rgba () o translucide png.

Non darà una sola scala di colore, ma sfumerà il colore fuori gamma.

prova su codice penna con 10 colori diversi tramite pseudo-elemento, l'ultimo è grigio. http://codepen.io/gcyrillus/pen/nqpDd (ricarica per passare a un'altra immagine)

0
G-Cyr

Una soluzione terribile ma praticabile: renderizza l'immagine utilizzando un oggetto Flash, che ti offre tutte le trasformazioni possibili in Flash.

Se i tuoi utenti utilizzano i browser bleeding-Edge e if Firefox 3.5 e Safari 4 lo supportano (non so se lo fanno/lo faranno), potresti regolare il CSS profilo colore attributo dell'immagine, impostandolo su un URL del profilo ICC in scala di grigi. Ma questo è un sacco di se!

0
richardtallent

Se tu o qualcun altro che si trova ad affrontare un problema simile in futuro, sono aperti a PHP. (So ​​che hai detto HTML/CSS, ma forse stai già utilizzando PHP nel backend) Ecco una soluzione PHP:

L'ho preso dalla libreria PHP Gd e ho aggiunto alcune variabili per automatizzare il processo ...

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

Puoi usare una delle funzioni di jFunc - usa la funzione "jFunc_CanvasFilterGrayscale" http://jfunc.com/jFunc-functions.aspx

0
Dany Maor

Prova questo plugin jquery. Anche se, questa non è una soluzione HTML e CSS pura, ma è un modo pigro per ottenere ciò che desideri. Puoi personalizzare la tua scala di grigi per adattarla al meglio al tuo utilizzo. Usalo come segue:

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

C'è un interattivo demo . Puoi giocare con esso.

Controlla la documentazione sull'utilizzo, è piuttosto semplice. docs

0
Nicholas TJ