3

Let say these are the filters I've applied to an image. I want to know the mathematics behind these filters:

filter: contrast(1.3) brightness(0.8) sepia(0.3) saturate(1.5) hue-rotate(-20deg);

I'm looking for the calculations specific to the CSS or any generic algorithms applied to each pixel RGB or overall. Any help is highly appreciated.

Sonny Prince
  • 1,094
  • 7
  • 15
Saurabh Gupta
  • 506
  • 1
  • 4
  • 18
  • 3
    This site gives a lot of information: https://www.w3.org/TR/filter-effects/ but your question is too broad, not specific enough. – Nico O Apr 14 '16 at 08:22
  • I just want to know if we I want my custom code to set contrast to 1.3, and I want to it using python or matlab, then what algorithm or mathematics I have to apply on my image pixels. – Saurabh Gupta Apr 14 '16 at 08:40

1 Answers1

9

The values you pass the CSS filter functions are based on the element.

If you were adding sepia(0.3) this would apply 30% sepia filter.

Converts the input image to sepia. The passed parameter defines the proportion of the conversion. A value of 100% is completely sepia. A value of 0% leaves the input unchanged. Values between 0% and 100% are linear multipliers on the effect. Values of amount over 100% are allowed but UAs must clamp the values to 1.

If you were adding contrast(1.3) this would up the contrast of the image 130% and so on.

You can read more information here: https://developer.mozilla.org/en/docs/Web/CSS/filter

=== UPDATE ===

Here's some algorithms I've come across:

sepia

outputRed = (inputRed * .393) + (inputGreen *.769) + (inputBlue * .189)
outputGreen = (inputRed * .349) + (inputGreen *.686) + (inputBlue * .168)
outputBlue = (inputRed * .272) + (inputGreen *.534) + (inputBlue * .131)

Source: http://www.techrepublic.com/blog/how-do-i/how-do-i-convert-images-to-grayscale-and-sepia-tone-using-c/

greyscale

Gray = (Red * 0.3 + Green * 0.59 + Blue * 0.11)

Source: http://www.tannerhelland.com/3643/grayscale-image-algorithm-vb6/

Hue and saturation

color = blend2(rgb(128, 128, 128), hueRGB, saturation);

if (lightness <= -1)
    return black;
else if (lightness >= 1)
    return white;

else if (lightness >= 0)
    return blend3(black, color, white, 2 * (1 - lightness) * (value - 1) + 1)
else
    return blend3(black, color, white, 2 * (1 + lightness) * (value) - 1)

Source: https://stackoverflow.com/a/9177602/5814976

Brightness

colour = GetPixelColour(x, y)
newRed   = Truncate(Red(colour)   + brightness)
newGreen = Truncate(Green(colour) + brightness)
newBlue  = Truncate(Blue(colour)  + brightness)
PutPixelColour(x, y) = RGB(newRed, newGreen, newBlue)

Source: http://www.dfstudios.co.uk/articles/programming/image-programming-algorithms/image-processing-algorithms-part-4-brightness-adjustment/

Run the snippet (below) for a demo of each filter.

body { font-family: 'fira code'; }
img {
  width: 40px;
  height: 40%;
  transition: all 500ms;}
img:hover { transform: scale(4); }
td { padding: 0 20px; }
th:nth-child(1) { text-align: right; }
sup { color: red; }
<table>
  <tr>
    <th><u>Filter:</u></th>
    <th>0%</th>
    <th>25%</th>
    <th>50%</th>
    <th>75%</th>
    <th>100%</th>
  </tr>
  <tr>
    <th>brightness</th>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:brightness(0%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:brightness(25%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:brightness(50%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:brightness(75%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:brightness(100%);'></td>
  </tr>
  <tr>
    <th>contrast</th>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:contrast(0%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:contrast(25%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:contrast(50%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:contrast(75%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:contrast(100%);'></td>
  </tr>
  <tr>
    <th>grayscale</th>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:grayscale(0%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:grayscale(25%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:grayscale(50%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:grayscale(75%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:grayscale(100%);'></td>
  </tr>
  <tr>
    <th>invert</th>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:invert(0%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:invert(25%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:invert(50%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:invert(75%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:invert(100%);'></td>
  </tr>
  <tr>
    <th>opacity</th>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:opacity(0%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:opacity(25%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:opacity(50%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:opacity(75%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:opacity(100%);'></td>
  </tr>
  <tr>
    <th>saturate</th>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:saturate(0%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:saturate(25%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:saturate(50%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:saturate(75%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:saturate(100%);'></td>
  </tr>
  <tr>
    <th>sepia</th>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:sepia(0%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:sepia(25%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:sepia(50%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:sepia(75%);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:sepia(100%);'></td>
  </tr>
  <tr>
    <th>blur<sup>*</sup></th>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:blur(0px);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:blur(4px);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:blur(8px);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:blur(12px);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:blur(16px);'></td>
  </tr>

  <tr>
    <th>drop-shadow<sup>*</sup></th>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:drop-shadow(0px 0px 0px black);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:drop-shadow(3px 3px 1.5px black);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:drop-shadow(6px 6px 3px black);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:drop-shadow(9px 9px 4.5px black);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:drop-shadow(12px 12px 6px black);'></td>
  </tr>

  <tr>
    <th>hue-rotate<sup>*</sup></th>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:hue-rotate(0deg);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:hue-rotate(90deg);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:hue-rotate(180deg);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:hue-rotate(270deg);'></td>
    <td><img src='https://i.stack.imgur.com/QFQsM.png' style='filter:hue-rotate(360deg);'></td>
  </tr>
</table>

<div style='font-size:12px; text-align:right;'>(<sup>*</sup> = does <b>not</b> take % values)</div>
ashleedawg
  • 20,365
  • 9
  • 72
  • 105
Sonny Prince
  • 1,094
  • 7
  • 15
  • This link is somewhat helpful. Some of the filters are clear. Still a more descriptive version will be of great help. – Saurabh Gupta Apr 14 '16 at 08:45
  • @SaurabhGupta I've updated my original answer with some algorithms for you :) – Sonny Prince Apr 14 '16 at 08:59
  • 1
    The brightness algorithm presented doesn't appear to be the solution used in CSS. In my tests brightness seems to scale values, i.e. is not adding a constant. – pwuertz Nov 03 '19 at 11:25