<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Anthony Dito</title>
    <description>The latest articles on Forem by Anthony Dito (@anthony_dito_8fad7bcb4ad3).</description>
    <link>https://forem.com/anthony_dito_8fad7bcb4ad3</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3717189%2Fb5dc68b9-7b8e-44bf-a9fa-a70b6d84ff4d.png</url>
      <title>Forem: Anthony Dito</title>
      <link>https://forem.com/anthony_dito_8fad7bcb4ad3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/anthony_dito_8fad7bcb4ad3"/>
    <language>en</language>
    <item>
      <title>Learn the Difference Between Exposure and Brightness</title>
      <dc:creator>Anthony Dito</dc:creator>
      <pubDate>Thu, 29 Jan 2026 05:10:25 +0000</pubDate>
      <link>https://forem.com/anthony_dito_8fad7bcb4ad3/learn-the-difference-between-exposure-and-brightness-193a</link>
      <guid>https://forem.com/anthony_dito_8fad7bcb4ad3/learn-the-difference-between-exposure-and-brightness-193a</guid>
      <description>&lt;p&gt;BrushCue contains two tools that appear to do the same thing: the &lt;a href="https://www.brushcue.com/tools/exposure-adjust" rel="noopener noreferrer"&gt;Exposure Adjustment&lt;/a&gt; and the &lt;a href="https://www.brushcue.com/tools/brightness-adjust" rel="noopener noreferrer"&gt;Brightness Adjustment&lt;/a&gt; tools. This post will explain the difference between the two. In doing so, we will learn a bit about color modifications in image editing workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Exposure Adjustments Work
&lt;/h2&gt;

&lt;p&gt;An exposure adjustment is simpler to implement technically, so let's start there. As you probably know, digital cameras and displays work by using R, G, and B colors. R, G, and B correspond to the amount of red, green, and blue light. The exposure adjustment simply multiplies each component by a factor. This has a similar effect to changing the exposure duration on a camera.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3pcuwub9nbw5t5ai77c.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3pcuwub9nbw5t5ai77c.webp" alt="Exposure Adjustment Animation" width="300" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Brightness Adjustments Work
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.brushcue.com/tools/brightness-adjust" rel="noopener noreferrer"&gt;Brightness Adjust&lt;/a&gt; tool has an intermediate step: it converts the color to OkLab, adjusts the lightness, then converts back to RGB. If you have read other posts of mine, you probably know where this is going. OkLab is a perceptual color space, which means equal steps in OkLab are meant to feel like equal steps to the human eye. Doing the adjustment in OkLab lets us change brightness more uniformly across different hues.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fju8zszu13y586rfus4mp.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fju8zszu13y586rfus4mp.webp" alt="Brightness Adjustment Animation" width="300" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  When you would use each
&lt;/h2&gt;

&lt;p&gt;If you want to make a scene lighter or darker for aesthetic purposes, use &lt;a href="https://www.brushcue.com/tools/brightness-adjust" rel="noopener noreferrer"&gt;Brightness Adjust&lt;/a&gt;. Because it works in OkLab, the change tends to look more even across colors and better matches how we perceive lightness.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.brushcue.com/tools/exposure-adjust" rel="noopener noreferrer"&gt;Exposure Adjust&lt;/a&gt; still has a place. It behaves like a camera exposure change, so it is useful when you want a more “photographic” effect or you are matching exposure changes elsewhere in a pipeline. It is also simple and predictable in linear RGB, which can be helpful for technical tweaks.&lt;/p&gt;

</description>
      <category>graphics</category>
      <category>computervision</category>
    </item>
    <item>
      <title>Vibrancy vs Saturation</title>
      <dc:creator>Anthony Dito</dc:creator>
      <pubDate>Sat, 24 Jan 2026 00:01:07 +0000</pubDate>
      <link>https://forem.com/anthony_dito_8fad7bcb4ad3/vibrancy-vs-saturation-1pd6</link>
      <guid>https://forem.com/anthony_dito_8fad7bcb4ad3/vibrancy-vs-saturation-1pd6</guid>
      <description>&lt;h2&gt;
  
  
  What a Vibrancy Adjustment Looks Like
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsu2eop7xyijxc1bpvd1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwsu2eop7xyijxc1bpvd1.webp" alt="Vibrancy adjustment example" width="300" height="225"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  What a Saturation Adjustment Looks Like
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F266i5s944iot5qpqlt0x.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F266i5s944iot5qpqlt0x.webp" alt="Saturation adjustment example" width="500" height="374"&gt;&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  First, Understanding OkLab
&lt;/h2&gt;

&lt;p&gt;On BrushCue, we do our saturation and vibrancy adjustment using &lt;a href="https://en.wikipedia.org/wiki/Oklab_color_space" rel="noopener noreferrer"&gt;OkLab&lt;/a&gt; color. This is a perceptual color space — meaning it is designed to store colors similarly to how humans visualize them. This is opposed to RGB colors which stores color as how they will be used on the display. The &lt;code&gt;R&lt;/code&gt;, &lt;code&gt;G&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; control how much red, green and blue light comes out from each pixel on the display.&lt;/p&gt;

&lt;p&gt;Mathematical distances between R, G, B do not correspond to distance in how far a color is perceived to be from another. This is what OkLab solves for and why we use it for many color adjustments.&lt;/p&gt;

&lt;p&gt;OkLab has two parts. There is an &lt;code&gt;L&lt;/code&gt; component which specifies the lightness of the color. There are &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; components that specifies the hue and chroma of the color. You can think of the &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; as plotting a point on a graph and the angle of that point being the hue of the color.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; components of the OkLab color can be visualized with the interactive component on our website &lt;a href="https://www.brushcue.com/blog/vibrancy-vs-saturation" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The key point - colors toward the center are more muted than colors toward the edge.&lt;/p&gt;

&lt;h2&gt;
  
  
  How saturation works
&lt;/h2&gt;

&lt;p&gt;OkLab cleanly separates the color (&lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt;) from the lightness (&lt;code&gt;L&lt;/code&gt;). To modify the saturation, we increase or decrease the distance of the &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; components are from the origin. This is straightforward, multiply the &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; components by a scale. The code for how we do this is below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;perform_saturation_adjustment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;vec4&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;vec4&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="py"&gt;.x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="py"&gt;.y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="py"&gt;.z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="py"&gt;.w&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;vec4&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="py"&gt;.w&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How vibrancy works
&lt;/h2&gt;

&lt;p&gt;Instead of uniformly increasing the &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; of a color like we do for saturation, vibrancy changes are subtler. Vibrancy changes selectively increase more muted colors (color closer to the origin) at a higher rate than more vibrant colors (colors further from the origin). Doing this allows for more natural-looking color enhancements. The code for how we do this is shared below. We calculate the saturation of the image, flip it so we have a value closer to 1 for muted colors and a value closer to 0 for saturated colors, apply the boost to the chroma and then recompute the &lt;code&gt;A&lt;/code&gt; and &lt;code&gt;B&lt;/code&gt; components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;perform_vibrancy_adjustment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;vec4&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;vibrance_boost&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;vec4&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="py"&gt;.x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="py"&gt;.y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="py"&gt;.z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="py"&gt;.w&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// measure the current saturation&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;chroma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 

    &lt;span class="c1"&gt;// calculates a factor to scale by. chromas close to 0 get 1, chromas close to the max get 0.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;saturation_factor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chroma&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// apply the boost by multiplying the chroma by the boost scaled boost amount.&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;adaptive_boost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;mix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vibrance_boost&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;saturation_factor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;boosted_chroma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chroma&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;adaptive_boost&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// recalculate the A and B&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;hue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;atan2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;new_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;boosted_chroma&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;new_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;boosted_chroma&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;vec4&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Compared
&lt;/h2&gt;

&lt;p&gt;As you can see in the above images, the vibrancy is a subtler, more natural effect. We boost the more muted colors while leaving the vibrant colors mostly unchanged. When you want realistic enhancements to the colors of your images, vibrance modifications are typically better.&lt;/p&gt;

&lt;p&gt;This doesn't mean that saturation adjustments are always inferior. In practice, it rarely makes sense to reduce the vibrancy of an image. Doing so makes muted colors even more muted. A better way to make an image more muted would be to perform a saturation adjustment with a value less than 1. Additionally, saturation adjustments are uniform across the color range, which is an advantage in some cases—particularly when correcting an error in the original image.&lt;/p&gt;

&lt;p&gt;Check out our &lt;a href="https://www.brushcue.com/tools/saturation" rel="noopener noreferrer"&gt;saturation tool&lt;/a&gt; and our &lt;a href="https://www.brushcue.com/tools/vibrancy" rel="noopener noreferrer"&gt;vibrancy tool&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>graphics</category>
    </item>
    <item>
      <title>How RGB Color Shift Effects Works</title>
      <dc:creator>Anthony Dito</dc:creator>
      <pubDate>Fri, 23 Jan 2026 15:58:20 +0000</pubDate>
      <link>https://forem.com/anthony_dito_8fad7bcb4ad3/how-rgb-color-shift-effects-works-231p</link>
      <guid>https://forem.com/anthony_dito_8fad7bcb4ad3/how-rgb-color-shift-effects-works-231p</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flh50oevc53rcuufhob9d.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flh50oevc53rcuufhob9d.webp" alt="Final result of the BrushCue RGB color shift tool - animated" width="300" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Decompose into red, green and blue components
&lt;/h2&gt;

&lt;p&gt;To do this decomposition, we use the &lt;strong&gt;Composition Linear Transform&lt;/strong&gt; operation. This performs a matrix multiplication on the R, G, B and A components of the pixel values. Using this trick, we can pull out the individual color stimulus value. The below table shows the individual components and the matrices created to extract them.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Red&lt;/th&gt;
&lt;th&gt;Green&lt;/th&gt;
&lt;th&gt;Blue&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faabe23ok2hoa5xwjjjos.png" alt="Red channel" width="800" height="967"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkgu65wjx2a10lg9qnc6g.png" alt="Green channel" width="800" height="967"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwuv7jn1itb9xh041syzt.png" alt="Blue channel" width="800" height="967"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;pre&gt;1 0 0 0&lt;br&gt;0 0 0 0&lt;br&gt;0 0 0 0&lt;br&gt;0 0 0 1&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;0 0 0 0&lt;br&gt;0 1 0 0&lt;br&gt;0 0 0 0&lt;br&gt;0 0 0 1&lt;/pre&gt;&lt;/td&gt;
&lt;td&gt;&lt;pre&gt;0 0 0 0&lt;br&gt;0 0 0 0&lt;br&gt;0 0 1 0&lt;br&gt;0 0 0 1&lt;/pre&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Combine Back with an Offset
&lt;/h2&gt;

&lt;p&gt;Now that we have the individual components, we recombine with an addition blend with an offset. The offset causes the image to be composited askew, which creates the glitch effect.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Red + Green&lt;/th&gt;
&lt;th&gt;(Red + Green) + Blue&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffy22xb06hw04kz68uhoe.png" alt="Red + Green" width="800" height="967"&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7mcv5rt93sdujcy4gq7.png" alt="(Red + Green) + Blue" width="800" height="967"&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;After the blends are done, we apply a crop to take out that green space at the bottom and right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;With this process, we can create an RGB color shift effect which makes it look like the colors are glitching. You can use our tool by going &lt;a href="https://www.brushcue.com/tools/rgb-color-shift" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Play around with different offset values and your own images.&lt;/p&gt;

</description>
      <category>algorithms</category>
      <category>design</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How Pixelate Effects Work</title>
      <dc:creator>Anthony Dito</dc:creator>
      <pubDate>Sat, 17 Jan 2026 22:28:09 +0000</pubDate>
      <link>https://forem.com/anthony_dito_8fad7bcb4ad3/how-pixelate-effects-work-3deh</link>
      <guid>https://forem.com/anthony_dito_8fad7bcb4ad3/how-pixelate-effects-work-3deh</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30aj7fn2zz5mo5hm2e4a.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F30aj7fn2zz5mo5hm2e4a.webp" alt="Pixelate Animation" width="362" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What a pixelate effect is
&lt;/h2&gt;

&lt;p&gt;To understand what the pixelate effect is doing, first, a brief introduction to what a pixel is. You may think of a pixel as a little square LED on your display. For the purposes of image editing, that is not quite right. It is better to think of a pixel as an infinitesimal sample of color at a particular point — no area, just location.&lt;/p&gt;

&lt;p&gt;With this distinction in mind, we need to trick the display into behaving like it is low-resolution.&lt;/p&gt;

&lt;h2&gt;
  
  
  An initial attempt, lowering the image resolution
&lt;/h2&gt;

&lt;p&gt;Now that we know that pixels are just samples of an image at a given point, pixelating an image should be easy! We just scale it to reduce the number of samples. Wrong. Doing so produces the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj83d9reylsumvu8o0rem.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj83d9reylsumvu8o0rem.png" alt="Pixelate by scaling up and down" width="800" height="1109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reducing the size of the image does not account for how computers actually display images. When scaling up an image, your computer will merge nearby pixels in a process called &lt;a href="https://en.wikipedia.org/wiki/Anti-aliasing" rel="noopener noreferrer"&gt;anti-aliasing&lt;/a&gt;. While this makes scaling images up and down look better, it breaks our pixelation effect. Let's now try to trick the display.&lt;/p&gt;

&lt;h2&gt;
  
  
  The BrushCue approach
&lt;/h2&gt;

&lt;p&gt;To build a pixelation effect, we need to work around the fact that computers will blend nearby pixels when they scale. To do this, we keep the image resolution the same but just use the same color in squares of a given size in the image.&lt;/p&gt;

&lt;p&gt;In BrushCue, the shader for how we do this is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nf"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="n"&gt;input_texture&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;texture_2d&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="nf"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;uniform&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pixel_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;do_transformation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;vec4&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;vec2&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;u32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;vec4&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;pix_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;u32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pixel_size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;block_corner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;pix_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;pix_size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;center_coord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block_corner&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;pix_size&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2u&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;textureLoad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_texture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;center_coord&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code keeps the image the same size but creates squares of the same color. We take the size of a square, get the color at the center and use that color for each pixel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzcivzcme8840kfw65yf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzcivzcme8840kfw65yf.png" alt="Final pixelate result" width="800" height="1105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now we have our result. A pixelated image that actually looks pixelated when displayed on your screen.&lt;/p&gt;

&lt;p&gt;To use the BrushCue tool to pixelate your own image, &lt;a href="https://www.brushcue.com/tools/pixelate" rel="noopener noreferrer"&gt;click here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>graphics</category>
    </item>
    <item>
      <title>How to Create a Striking Grayscale Effect</title>
      <dc:creator>Anthony Dito</dc:creator>
      <pubDate>Sat, 17 Jan 2026 22:21:08 +0000</pubDate>
      <link>https://forem.com/anthony_dito_8fad7bcb4ad3/how-to-create-a-striking-grayscale-effect-1gd1</link>
      <guid>https://forem.com/anthony_dito_8fad7bcb4ad3/how-to-create-a-striking-grayscale-effect-1gd1</guid>
      <description>&lt;p&gt;In this post we will create a striking grayscale effect by examining grayscale, thresholds, and S-curves.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzbr3ynqm1j3bzvt1iix.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzbr3ynqm1j3bzvt1iix.jpg" alt="The Calling of Saint Matthew by Caravaggio" width="800" height="755"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this post, we will be converting the &lt;em&gt;Calling of Saint Matthew by Caravaggio&lt;/em&gt; into grayscale. Caravaggio's paintings are striking in their use of light. We aim to preserve that quality while transforming this masterwork to grayscale.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Simple Grayscale
&lt;/h2&gt;

&lt;p&gt;First, we will use the &lt;a href="https://www.brushcue.com/tools/grayscale" rel="noopener noreferrer"&gt;grayscale&lt;/a&gt; tool provided by BrushCue. This tool works by converting each pixel from an RGB color to an &lt;a href="https://en.wikipedia.org/wiki/CIE_1931_color_space" rel="noopener noreferrer"&gt;XYZ&lt;/a&gt; color and extracting the luminance. The intricacies of doing this — and what XYZ color is for that matter — are outside the scope of this post. The key thing is that the Y in an XYZ color represents luminance. We take that Y and then set the X and Z values to 0 to create our grayscale image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvq9j6d5n0m6th8j8xgpy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvq9j6d5n0m6th8j8xgpy.png" alt="Simple grayscale version" width="800" height="755"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While this is a technically correct grayscale, it is far from striking. The image is too gray for my taste.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using a Threshold
&lt;/h2&gt;

&lt;p&gt;To make the grayscale more striking, we want more contrast in the image. If we take this to the extreme, we would want all the colors to either be white or black. BrushCue provides a tool to do this. This is the &lt;a href="https://www.brushcue.com/tools/lightness-threshold" rel="noopener noreferrer"&gt;Lightness Threshold&lt;/a&gt; tool. The use of the tool can be seen below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfhv9d8n92hq89ic6hi0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfhv9d8n92hq89ic6hi0.png" alt="Color threshold version" width="800" height="755"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The colors are either white or black, effectively maximizing the possible contrast in this image. An interesting effect. Not what we were going for. What we want is something between the normal grayscale and this color threshold.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using a Lightness S-Curve
&lt;/h2&gt;

&lt;p&gt;To get a striking grayscale that pushes more of the colors toward white and black but preserves the detail, we are going to use the concept of an S-Curve. An S-Curve is one of the curve types that BrushCue allows for modifications to the color of an image. The magic of an S-Curve is that it can increase the contrast of an image by pushing values toward 0 and 1.&lt;/p&gt;

&lt;p&gt;To visualize this, check out the interactive component in the original post &lt;a href="https://www.brushcue.com/blog/striking-grayscale" rel="noopener noreferrer"&gt;here&lt;/a&gt;. The value of 0 corresponds to black, and the value of 1 corresponds to white. The x-axis is the input and the y-value is the output. Hover over the curve to see what happens. You will see that for x values below 0.5 the output (or y-value) is lower. For x values greater than 0.5, the y-value is higher. This trick increases the separation between the dark and light areas of the image. This creates a stark grayscale effect.&lt;/p&gt;

&lt;p&gt;To use this mathematical concept, BrushCue provides an operation called &lt;code&gt;Composition Lightness Curve&lt;/code&gt;. The use of this operation is demonstrated in the tool &lt;a href="https://www.brushcue.com/tools/high-contrast-grayscale" rel="noopener noreferrer"&gt;High Contrast Grayscale&lt;/a&gt; which you can use to test out different values for the S-Curve. Using this tool, we produce the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73lqmjeakfzpy42d4x7c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F73lqmjeakfzpy42d4x7c.png" alt="Striking grayscale version" width="800" height="755"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the effect I was looking for. There is a striking difference between the dark and light areas of the image while still preserving the detail of the standard grayscale operation. I hope Caravaggio would approve modifying his work in such a manner — at least for learning purposes.&lt;/p&gt;

</description>
      <category>graphics</category>
    </item>
  </channel>
</rss>
