<?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>DEV Community: Nailya Safarova</title>
    <description>The latest articles on DEV Community by Nailya Safarova (@nailyasaf).</description>
    <link>https://dev.to/nailyasaf</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%2F3089128%2F4410d6f6-8d31-48cc-a8e2-57fb555e9a16.png</url>
      <title>DEV Community: Nailya Safarova</title>
      <link>https://dev.to/nailyasaf</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nailyasaf"/>
    <language>en</language>
    <item>
      <title>This Web App Turns Any Image Into a Retro Fever Dream—No Photoshop Needed</title>
      <dc:creator>Nailya Safarova</dc:creator>
      <pubDate>Mon, 28 Apr 2025 09:29:05 +0000</pubDate>
      <link>https://dev.to/nailyasaf/this-web-app-turns-any-image-into-a-retro-fever-dream-no-photoshop-needed-5ae2</link>
      <guid>https://dev.to/nailyasaf/this-web-app-turns-any-image-into-a-retro-fever-dream-no-photoshop-needed-5ae2</guid>
      <description>&lt;p&gt;In our &lt;a href="https://hackernoon.com/this-color-tool-turns-any-image-into-a-wes-anderson-fever-dream" rel="noopener noreferrer"&gt;previous tutorial&lt;/a&gt;, we taught our application to work with references and palettes. Now, it’s time to add more options for fine-tuning color and visual effects.&lt;/p&gt;

&lt;p&gt;We will introduce a few new tools that allow for more flexible image manipulation. Additionally, we will explore a new color model, HSV, which works with colors differently than RGB and LAB. This model makes it easier to manipulate characteristics like hue, saturation, and lightness, which makes it particularly useful for adjusting colors in images. This innovation will open up new creative possibilities and opportunities for experimentation.&lt;/p&gt;

&lt;p&gt;The full project code is available at &lt;a href="https://github.com/xtwoitx/cinepalette" rel="noopener noreferrer"&gt;this link&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adjusting the Number of Colors in the Extracted Palette
&lt;/h2&gt;

&lt;p&gt;We’ve already seen how limiting a palette can alter the appearance of an image.&lt;/p&gt;

&lt;p&gt;For more flexible filter and image processing adjustments, we will add the ability to control the number of colors extracted from the image. Now, you can precisely set how many colors are highlighted in the image, allowing for better control over visual effects. This feature is especially useful when working with palettes for creating filters, as changing the number of colors applies to a wide range of design tasks.&lt;/p&gt;

&lt;p&gt;The app now features a slider that lets you choose the number of colors extracted from the image &lt;strong&gt;(from 10 to 20)&lt;/strong&gt;. This adjustment impacts the filter results and helps achieve better visual effects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div style={{ marginBottom: 12 }}&amp;gt;
  &amp;lt;label&amp;gt;Number of Colors&amp;lt;/label&amp;gt;
  &amp;lt;input
    type="range"
    min="10"
    max="20"
    value={colorCount}
    onChange={(e) =&amp;gt; setColorCount(Number(e.target.value))}
    style={{ width: "100%" }}
  /&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We will be experimenting with the stunning photograph by &lt;strong&gt;So Sasaki&lt;/strong&gt; for &lt;a href="https://mirroredsociety.com/interview/20172015/void-tokyo" rel="noopener noreferrer"&gt;Void Tokio&lt;/a&gt;. It features a wide range of colors and shades, making it the perfect subject for our exploration.&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%2Fq4bgfwgqjho6jqoh6iow.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%2Fq4bgfwgqjho6jqoh6iow.png" alt="So Sasaki | Void Tokyo" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Below you can compare what the image looks like with a palette of different sizes.&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%2F26mjityz6ez4ycnddczm.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%2F26mjityz6ez4ycnddczm.png" alt="The more colors there are in the palette, the more details can be distinguished in the photo" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Filter Intensity Slider
&lt;/h2&gt;

&lt;p&gt;To make the filtering process more flexible, we will add a slider to control the intensity of the palette application to the image. This slider allows you to adjust the balance between the original image and the palette.&lt;/p&gt;

&lt;p&gt;Simply choose the desired filter intensity and click &lt;strong&gt;“Apply filter”.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div style={{ marginBottom: 16 }}&amp;gt;
  &amp;lt;label style={{ display: "block", marginBottom: 6 }}&amp;gt;Filter Intensity&amp;lt;/label&amp;gt;
  &amp;lt;input
    type="range"
    min="0"
    max="100"
    value={intensity}
    onChange={(e) =&amp;gt; setIntensity(Number(e.target.value))}
    style={{ width: "100%" }}
  /&amp;gt;
&amp;lt;/div&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fk0vei9oedk0h7wp1ep6j.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%2Fk0vei9oedk0h7wp1ep6j.png" alt="As the filter intensity increases, the image becomes more transformed" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does it work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the intensity is set to 100%, the image will be fully transformed using the colors from the selected palette. The lower the intensity value, the less influence the palette has on the image, allowing you to maintain more of the original colors.&lt;/p&gt;

&lt;h2&gt;
  
  
  HSV Color Model
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;HSV (Hue, Saturation, Value)&lt;/strong&gt; is one of the most popular color models, often used to represent color in terms of its hue, saturation, and brightness.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hue (color):&lt;/strong&gt; This represents the primary color (such as red, green, blue, etc.), measured in degrees from 0 to 360.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Saturation:&lt;/strong&gt; This indicates the intensity of the color. Saturation is affected by the amount of gray in the color: 100% is a fully saturated color, and 0% is gray.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value (brightness):&lt;/strong&gt; This represents how bright the color is. A value of 0% gives black, while 100% is the brightest version of the color.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Differences from RGB and LAB:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlike RGB, where colors are combined based on the intensities of red, green, and blue, HSV is based on human visual perception. This makes it more intuitive for tasks like color correction and design work.&lt;/li&gt;
&lt;li&gt;Compared to LAB, which uses a more complex mathematical model for precise color representation across different lighting conditions, HSV is more intuitive and user-friendly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sample code for converting RGB to HSV:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function rgbToHsv(r, g, b) {
  r /= 255;
  g /= 255;
  b /= 255;

  const max = Math.max(r, g, b);
  const min = Math.min(r, g, b);
  const delta = max - min;

  let h = 0, s = 0, v = max;

  if (delta !== 0) {
    s = delta / max;
    if (r === max) {
      h = (g - b) / delta;
    } else if (g === max) {
      h = 2 + (b - r) / delta;
    } else {
      h = 4 + (r - g) / delta;
    }
    h *= 60;
    if (h &amp;lt; 0) h += 360;
  }

  return [h, s * 100, v * 100];
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Below are examples of images in the same palette, but in different color models.&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%2F2htaiuce19inccgodgpr.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%2F2htaiuce19inccgodgpr.png" alt="In different color models, the same object can appear differently" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contrast Slider
&lt;/h2&gt;

&lt;p&gt;Contrast refers to the difference between the lightest and darkest points in an image. Adjusting the contrast allows you to either enhance or reduce this difference. The higher the contrast, the more pronounced the light and dark areas will be.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does contrast adjustment work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When contrast is increased, the dark areas of the image become even darker, and the light areas become even brighter. This effect can make the image appear more vivid and sharp, enhancing its visual impact.&lt;/p&gt;

&lt;p&gt;Example code for changing contrast:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const applyContrast = (r, g, b, contrast) =&amp;gt; {
  const contrastFactor = (259 * (contrast + 255)) / (255 * (259 - contrast));
  r = contrastFactor * (r - 128) + 128;
  g = contrastFactor * (g - 128) + 128;
  b = contrastFactor * (b - 128) + 128;
  return [r, g, b];
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fmqip3ryo03h11c0ws7wg.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%2Fmqip3ryo03h11c0ws7wg.png" alt="Contrast gradually enhances the colors in the image" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Algorithm Description:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The contrast algorithm uses a factor that depends on the current contrast value. This factor is applied to each color component (red, green, and blue), adjusting their brightness based on the contrast level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Noise Slider
&lt;/h2&gt;

&lt;p&gt;For those who want to have a little fun, we’ve added a noise slider. Adding noise to an image helps create a vintage photo effect or makes the image feel more “alive”. This effect is used to conceal imperfections or add an artistic touch to the image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How does the noise work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The noise slider allows you to control the amount of random variations applied to the color of each pixel in the image. The higher the noise value, the greater the amount of random changes applied to the image.&lt;/p&gt;

&lt;p&gt;When noise is added to an image, small, random variations are introduced to the RGB values of each pixel, resulting in a grainy effect. This effect can be subtle or pronounced, depending on the amount of noise applied. This can help give the image a more textured look or simulate the appearance of an old, low-resolution photo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const applyNoise = (r, g, b, noise) =&amp;gt; {
  r += Math.random() * noise - noise / 2;
  g += Math.random() * noise - noise / 2;
  b += Math.random() * noise - noise / 2;
  return [r, g, b];
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fjooyjtvllom5vkfqsjpg.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%2Fjooyjtvllom5vkfqsjpg.png" alt="A high level of noise, similar to that in early digital cameras" width="800" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Algorithm Description:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A random value is added to each pixel within a specified range. This creates the effect of random color changes, giving the image a noisy or grainy appearance. In our case, we’re simply simulating distortions, which don’t have any relation to real film grain or noise. However, the earliest digital filters (such as those used in early mobile phones like the &lt;a href="https://www.mobilephonemuseum.com/phone-detail/sony-ericsson-w810" rel="noopener noreferrer"&gt;Sony Ericsson W810&lt;/a&gt;) worked on the same principle.&lt;/p&gt;

&lt;p&gt;By controlling the amount of noise, users can experiment with different levels of intensity to achieve various creative effects or simulate imperfections in a photograph.&lt;/p&gt;

&lt;p&gt;And of course, we’ve added a Reset Settings button to clear all filters and revert to the original 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%2F7g2r1y2fowkverbk2nmb.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%2F7g2r1y2fowkverbk2nmb.png" alt="Full view of our application interface" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Throughout our articles, we’ve delved into the fundamentals of color correction and explored various tools and techniques for applying it. We’ve examined how to extract and adjust color palettes, the effects of contrast, saturation, and noise, and how to work with different color models — RGB, LAB, and HSV.&lt;/p&gt;

&lt;p&gt;Color correction is a crucial aspect of image processing, enabling us to enhance visual perception, highlight certain elements, and achieve harmony between colors. We’ve demonstrated how adjusting the number of colors in a palette or modifying contrast settings can completely transform an image, making it more expressive and dynamic.&lt;/p&gt;

&lt;p&gt;It’s important to note that color and contrast adjustments not only affect the appearance of an image but also influence how it’s perceived. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This makes color correction not just a technical process but also an art form.&lt;/strong&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>This Color Tool Turns Any Image Into a Wes Anderson Fever Dream</title>
      <dc:creator>Nailya Safarova</dc:creator>
      <pubDate>Mon, 28 Apr 2025 09:11:09 +0000</pubDate>
      <link>https://dev.to/nailyasaf/this-color-tool-turns-any-image-into-a-wes-anderson-fever-dream-1mgo</link>
      <guid>https://dev.to/nailyasaf/this-color-tool-turns-any-image-into-a-wes-anderson-fever-dream-1mgo</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/nailyasaf/this-simple-app-lets-you-see-how-hollywood-uses-color-to-mess-with-your-emotions-4gl2"&gt;the first part&lt;/a&gt; of this series, we explored the foundational principles of color correction and explained the importance of working with colors when editing images. In this second part, we dive into more advanced concepts, such as the differences between the RGB and LAB color models, as well as the process of extracting palettes from images and using them to create unique visual styles.&lt;/p&gt;

&lt;p&gt;As we saw in the previous article, some colors and palettes displayed differently than we initially expected. This is due to the fact that we used the simplest tools — the RGB model and Euclidean distance calculation. For more advanced processes, however, we need something a little more sophisticated.&lt;/p&gt;

&lt;p&gt;But first, a bit of theory.&lt;/p&gt;

&lt;h2&gt;
  
  
  The RGB Model
&lt;/h2&gt;

&lt;p&gt;The two most popular color models — &lt;strong&gt;RGB&lt;/strong&gt; and &lt;strong&gt;LAB&lt;/strong&gt; — are fundamentally different in how they represent and process colors.&lt;/p&gt;

&lt;p&gt;The RGB model uses the &lt;strong&gt;Red, Green, and Blue channels&lt;/strong&gt; to represent colors. Each channel can have values ranging from 0 to 255, resulting in over 16 million possible colors. This model is ideal for working with images displayed on screens, as computer monitors, TVs, and smartphones all use this model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RGB Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It uses an additive process where colors are created by combining red, green, and blue light.&lt;/li&gt;
&lt;li&gt;It’s simpler to understand and process at the pixel level.&lt;/li&gt;
&lt;li&gt;It’s limited in its ability to represent all colors accurately, as it does not account for human perception of color.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The LAB Model
&lt;/h2&gt;

&lt;p&gt;The LAB model represents color in three channels: &lt;strong&gt;L (lightness), A (a color spectrum from green to red), and B (a color spectrum from blue to yellow).&lt;/strong&gt; This model is closer to how humans perceive color and accounts for both the color and the brightness of an image.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LAB Key Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The L channel controls the brightness, allowing lightness adjustments without changing the color.&lt;/li&gt;
&lt;li&gt;The A and B channels describe color hues, allowing more precise control over a wide spectrum of colors.&lt;/li&gt;
&lt;li&gt;The LAB model is especially useful in professional color grading since it’s more versatile and allows for precise color adjustments without affecting other image parameters.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the LAB model, brightness is separated from color, making it possible to adjust the visual parameters of an image without impacting its color balance. This results in more accurate and natural color corrections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Color Calculation Algorithm and Using LAB
&lt;/h2&gt;

&lt;p&gt;To calculate and apply colors, our application utilizes the colorjs.io library, which efficiently works with colors in the LAB model. Integrating this library into the project allows us to perform accurate calculations that help achieve the desired results when processing images.&lt;/p&gt;

&lt;p&gt;Here’s an example of the code used in our app to work with colors in the LAB model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Sample code for using colorjs.io in LAB model
const findClosestColor = (r, g, b) =&amp;gt; {
  if (mode === "lab") {
    const color1 = new Color({ coords: [r / 255, g / 255, b / 255], space: "srgb" }).to("lab");
    let minDist = Infinity;
    let closest = [r, g, b];
    for (let i = 0; i &amp;lt; paletteLAB.length; i++) {
      const color2 = paletteLAB[i];
      const dist = color1.distance(color2);  // Calculating the distance between colors in LAB space
      if (dist &amp;lt; minDist) {
        minDist = dist;
        closest = palette[i];
      }
    }
    return closest;
  } else {
    // RGB calculations
    let minDist = Infinity;
    let closest = [r, g, b];
    for (let [pr, pg, pb] of palette) {
      const dist = Math.sqrt((r - pr) ** 2 + (g - pg) ** 2 + (b - pb) ** 2);
      if (dist &amp;lt; minDist) {
        minDist = dist;
        closest = [pr, pg, pb];
      }
    }
    return closest;
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This block of code handles the process of finding the closest color in a given palette by calculating the color distance between the target color and the colors in the palette. The calculation method is based on the selected mode, either &lt;strong&gt;RGB&lt;/strong&gt; or &lt;strong&gt;LAB&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How This Works in Practice:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;LAB Mode:&lt;/strong&gt; The LAB color space is designed to align with human vision, separating brightness (L) from chromatic components (A and B). When matching colors in LAB, the algorithm ensures that the colors are compared in a perceptually accurate manner, meaning it prioritizes how we perceive color differences, not just the mathematical RGB difference.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RGB Mode:&lt;/strong&gt; The RGB color space simply represents color by the intensity of red, green, and blue light. In this mode, the distance is calculated directly based on the color values, which can lead to less perceptual accuracy, as it doesn’t account for human color perception nuances.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In professional color grading and image processing, matching colors based on LAB is highly advantageous because it mimics how the human eye perceives colors, allowing for more natural and visually appealing results. Using this method, the application can achieve better consistency when applying color palettes to images, making it easier to match colors to desired styles.&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%2Ff46y2x8z6yp24bj6ednl.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%2Ff46y2x8z6yp24bj6ednl.png" alt="Mode selection menu" width="714" height="740"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Optimization Challenge: LAB Computation
&lt;/h2&gt;

&lt;p&gt;Working with the &lt;strong&gt;LAB&lt;/strong&gt; color model requires significantly more computational resources than working with &lt;strong&gt;RGB&lt;/strong&gt;. This is because, in LAB, each color is represented not just by three channels (RGB), but also involves additional calculations to obtain the color coordinates and their distances.&lt;/p&gt;

&lt;p&gt;To optimize this process, we introduced &lt;strong&gt;palette caching&lt;/strong&gt; to avoid redundant calculations. Palettes created in LAB mode are stored in memory, and if the image has not changed, the system will not recalculate the palette. This helps to significantly speed up the process, especially when applying palettes to multiple images, by reusing the precomputed data without having to perform the costly calculations again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Optimization with palette caching
const extractPalette = () =&amp;gt; {
  if (!image || image === lastExtractedImageRef.current) return;  // Check for changes

  const img = new Image();
  img.src = image;
  img.onload = () =&amp;gt; {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage(img, 0, 0);

    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
    const colorMap = new Map();

    // Creating a color map
    for (let i = 0; i &amp;lt; imageData.length; i += 4) {
      const key = `${imageData[i]},${imageData[i + 1]},${imageData[i + 2]}`;
      colorMap.set(key, (colorMap.get(key) || 0) + 1);
    }

    const sorted = Array.from(colorMap.entries()).sort((a, b) =&amp;gt; b[1] - a[1]);
    const topRaw = sorted.map(([str]) =&amp;gt; str.split(",").map(Number));
    const topColors = filterColors(topRaw).slice(0, 10);

    const randomId = Math.floor(10000 + Math.random() * 90000);
    const name = `Palette_${randomId}`;

    setPalettes(prev =&amp;gt; ({ ...prev, [name]: topColors }));
    setSelectedPalette(name);
    lastExtractedImageRef.current = image;  // Saving cache
  };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This improvement helps speed up the application’s performance, especially when processing multiple similar images repeatedly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Palette Extraction and Application
&lt;/h2&gt;

&lt;p&gt;Palette extraction is the process of identifying the most characteristic and vibrant colors from an image, which can then be used to create filters or visual styles. We extract the top-10 colors (ensuring diversity) using an algorithm that takes into account both the frequency of color occurrence and its luminance, ensuring that the palette doesn’t include colors that are too similar to each other.&lt;/p&gt;

&lt;p&gt;The main mechanism for extracting the palette is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const extractPalette = () =&amp;gt; {
  // Check for image changes
  if (!image || image === lastExtractedImageRef.current) return;

  const img = new Image();
  img.src = image;
  img.onload = () =&amp;gt; {
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    canvas.width = img.width;
    canvas.height = img.height;
    ctx.drawImage(img, 0, 0);

    const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height).data;
    const colorMap = new Map();

    // Counting the frequency of occurrence of each color
    for (let i = 0; i &amp;lt; imageData.length; i += 4) {
      const key = `${imageData[i]},${imageData[i + 1]},${imageData[i + 2]}`;
      colorMap.set(key, (colorMap.get(key) || 0) + 1);
    }

    // Sorting by frequency and filtering similar colors
    const sorted = Array.from(colorMap.entries()).sort((a, b) =&amp;gt; b[1] - a[1]);
    const topRaw = sorted.map(([str]) =&amp;gt; str.split(",").map(Number));
    const topColors = filterColors(topRaw).slice(0, 10);  // Segmentation and filtering

    const randomId = Math.floor(10000 + Math.random() * 90000);
    const name = `Palette_${randomId}`;

    // Saving the palette
    setPalettes(prev =&amp;gt; ({ ...prev, [name]: topColors }));
    setSelectedPalette(name);
    lastExtractedImageRef.current = image;
  };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is used to extract a palette from an image, where colors are filtered by brightness and difference. With this mechanism, you can quickly gather the most representative colors for further application.&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%2F5c5vwmpddjg81fcs3fro.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%2F5c5vwmpddjg81fcs3fro.png" alt="Extracted palette example" width="654" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We added automatic name generation for extracted palettes to avoid cluttering the user interface with unnecessary buttons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Palettes
&lt;/h2&gt;

&lt;p&gt;One of the tools in our application is the custom palette creation block. This feature allows users to create palettes suitable for various projects, providing full control over colors.&lt;/p&gt;

&lt;p&gt;The process starts with selecting a color through the HexColorPicker interface. The user can choose a color from the image or an external source. Each selected color is automatically added to the user’s color list, from which a palette is created.&lt;/p&gt;

&lt;p&gt;After selecting a few colors, the palette can be saved with a custom name. Later, it can be applied to the uploaded image to achieve a specific visual style.&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%2F7ouwujt095woc6xdd88f.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%2F7ouwujt095woc6xdd88f.png" alt="Custom palette tool" width="672" height="650"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Color Neutralization with Color Palettes
&lt;/h2&gt;

&lt;p&gt;Color neutralization is an important aspect of color grading and plays a critical role in film post-production. It is the process where individual scenes or shots, taken under different lighting conditions, can be brought to a common color tone. This is usually done to ensure a unified visual style throughout the film and to make the scenes visually consistent, regardless of the shooting conditions.&lt;/p&gt;

&lt;p&gt;Let’s explore how palettes are applied through two iconic examples of cinematic visual language.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Palettes in the Movie “The Matrix”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The film “The Matrix” (1999), directed by the Wachowski siblings, became iconic due to its unique visual style, which includes a specific greenish color palette. This color style was designed to visualize the digital reality in which the main characters exist. The visual effects of the film were created to convey the feeling of virtuality, where cold and mechanical colors dominate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Main Colors:&lt;/strong&gt; Green, black, metallic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Palette Application:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extracting Green Tones:&lt;/strong&gt; To create a Matrix-style palette, we can extract all shades of green, black, and gray from the image. By applying these tones, we can achieve the “digital reality” effect characteristic of the movie. In our app, this can be done by filtering by brightness and distance, keeping only the green shades and ignoring others.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Applying to New Images:&lt;/strong&gt; When we apply this palette, the image colors will change, replacing all pixels with those closest to the selected colors from the palette, thus creating the desired “coded” style.&lt;/li&gt;
&lt;/ul&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%2Fvqsgn9t09a069fcdrw5y.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%2Fvqsgn9t09a069fcdrw5y.png" alt="he Matrix Reloaded (2003)" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Palettes in Wes Anderson’s Works
&lt;/h2&gt;

&lt;p&gt;Wes Anderson is known for his vivid, colorful, and symmetrical visual solutions. His works, such as &lt;strong&gt;“The Grand Budapest Hotel”&lt;/strong&gt;, &lt;strong&gt;“Moonrise Kingdom”&lt;/strong&gt;, and &lt;strong&gt;“The French Dispatch”&lt;/strong&gt;, all have his signature style, which features rich pastel colors and carefully selected palettes. One key element of his films is the harmony and contrast in color design.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Main Colors:&lt;/strong&gt; Pastel shades, bright contrasting colors, red, yellow, turquoise, green.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Palette Application:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Extracting Pastel Shades:&lt;/strong&gt; In Wes Anderson’s films, pastel colors are often used. For example, light pink, blue, and orange tones. We can extract these colors and apply them to a new image to create an effect resembling vintage photography or to emphasize a stylized atmosphere. In our app, we can extract the palette from an image by filtering colors by brightness and contrast, preserving only the soft pastel shades.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Applying to New Images:&lt;/strong&gt; After the palette is extracted, it can be applied to any image, giving it the characteristic look reminiscent of Anderson’s works, with bright yet harmonious colors.&lt;/li&gt;
&lt;/ul&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%2Fat4xkhk8sj4qhk2opm17.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%2Fat4xkhk8sj4qhk2opm17.png" alt="The Grand Budapest Hotel (2014)" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we can extract palettes from references, it’s time for some experimentation!&lt;/p&gt;

&lt;p&gt;Since we are using palettes limited in the number of colors and running our application in the browser (which means using limited computational resources), we shouldn’t expect outstanding results. However, this is enough to demonstrate the core principles of how palettes work in color grading.&lt;/p&gt;

&lt;p&gt;Here are examples of processed images in both RGB and LAB modes.&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%2F8wccnkm7iu6rdzzf43bc.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%2F8wccnkm7iu6rdzzf43bc.png" alt="Terminator 2: Judgment Day (1991)" width="800" height="561"&gt;&lt;/a&gt;&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%2Fni2ckb6bup44qwtvd3zk.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%2Fni2ckb6bup44qwtvd3zk.png" alt="The Good, the Bad and the Ugly (1966)" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Extracting and applying palettes is a crucial aspect of creating visual styles, such as the “Matrix” style, Wes Anderson’s, or Denis Villeneuve’s. Our app provides a visual tool for working with colors that allows users to extract palettes, apply them, and create unique visual effects. With it, you can easily stylize images and create visual looks similar to those seen in popular films.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In the final part, we will focus on fine-tuning and optimizing colors.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>colorgrading</category>
      <category>imageprocessing</category>
    </item>
    <item>
      <title>This Simple App Lets You See How Hollywood Uses Color to Mess With Your Emotions</title>
      <dc:creator>Nailya Safarova</dc:creator>
      <pubDate>Fri, 25 Apr 2025 13:53:04 +0000</pubDate>
      <link>https://dev.to/nailyasaf/this-simple-app-lets-you-see-how-hollywood-uses-color-to-mess-with-your-emotions-4gl2</link>
      <guid>https://dev.to/nailyasaf/this-simple-app-lets-you-see-how-hollywood-uses-color-to-mess-with-your-emotions-4gl2</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Why does Joker feel so unsettlingly green and yellow?&lt;br&gt;
Why is Blade Runner soaked in teal and orange?&lt;br&gt;
Why does film make skin look soft and warm?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;It’s not magic. It’s color.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And whoever controls color — controls the emotional weight of the frame. Color grading is cinema’s visual language — a way to shape atmosphere, guide the viewer’s attention, and set the tone of a story. It can be subtle and almost invisible. Or bold and stylized, like in the work of Wong Kar-Wai, Fincher, Nolan, or Villeneuve. But to speak this language fluently, you first need to understand its grammar.&lt;/p&gt;

&lt;p&gt;Where does color work actually begin? How do we know what the “right” color even is? And how do you translate creative intent into technical action?&lt;/p&gt;

&lt;p&gt;Spoiler: it doesn’t start with LUTs or filters. It starts with color targets, calibration, and carefully chosen palettes.&lt;/p&gt;

&lt;p&gt;In this series, we’ll explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what color grading is on the most fundamental level;&lt;/li&gt;
&lt;li&gt;why limiting your palette is a feature, not a bug;&lt;/li&gt;
&lt;li&gt;how color charts work (and why they matter);&lt;/li&gt;
&lt;li&gt;and how to build your own grading tool in the browser — with React and some simple math.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We won’t just explain it. We’ll show it. And you’ll be able to experiment, tinker, and maybe for the first time actually see what color grading is made of.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Color Grading, and Why Start with Color Targets?
&lt;/h2&gt;

&lt;p&gt;Color grading is the process of adjusting and stylizing an image to achieve a specific visual tone, emotional effect, or technical standard. Whether in film, photography, or digital production, grading usually includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;balancing exposure and white point;&lt;/li&gt;
&lt;li&gt;correcting technical color shifts;&lt;/li&gt;
&lt;li&gt;crafting a visual style with contrast, tones, and color curves.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But grading isn’t just about “making it pretty.” It’s about control — of the mood, of the viewer’s focus, of the visual language of the entire narrative.&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%2F9d6bgfenumh9frc3ul8m.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%2F9d6bgfenumh9frc3ul8m.jpg" alt="X-Rite ColorChecker Classic" width="800" height="741"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before you apply any creative look, you need to bring the image to a &lt;strong&gt;neutral state&lt;/strong&gt;, which means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;correcting unwanted color casts (color correction);&lt;/li&gt;
&lt;li&gt;normalizing the footage to a standard color space (like Rec.709 or sRGB);&lt;/li&gt;
&lt;li&gt;matching material from different cameras into a consistent baseline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for that, colorists use color targets like the &lt;strong&gt;ColorChecker, ChromaDuMonde,&lt;/strong&gt; or other reference charts.&lt;/p&gt;

&lt;p&gt;A color target is a chart of color patches with precisely measured values. These values aren’t arbitrary — they’re obtained through spectrophotometric measurements in controlled environments using professional equipment like X-Rite or Konica Minolta spectrophotometers.&lt;/p&gt;

&lt;p&gt;One of the first widely adopted targets was the Kodak Gray Scale — a strip of neutral gray tones used for exposure control. Later came more advanced charts with full-color patches — like the Macbeth ColorChecker, introduced in 1976 (now known as the X-Rite ColorChecker). It features 24 color swatches designed to represent common real-world colors: human skin, blue sky, green foliage, and more.&lt;/p&gt;

&lt;p&gt;With the rise of digital photography and digital cinema, color targets became even more critical. They are now essential tools for calibrating not just cameras, but also monitors, printers, scanners — and any device that handles color. They’re used in color matching, profiling, and neutral balancing workflows — from film production to scientific imaging.&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%2Fh8l1h1mnhnof0rzhyk9l.jpeg" 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%2Fh8l1h1mnhnof0rzhyk9l.jpeg" alt="The process of calibrating with color targets" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Take X-Rite’s ColorChecker, for example. Each patch is measured under standardized lighting (usually D65 or D50), with results recorded in CIE XYZ coordinates — a device-independent color model. Those coordinates are then converted into RGB values, depending on your working color space (like sRGB, Rec.709, or AdobeRGB).&lt;/p&gt;

&lt;p&gt;So the RGB arrays we use in our app aren’t guesswork — they’re precise digital representations of standardized, physically measured patches.&lt;/p&gt;

&lt;p&gt;If the skin tone patch in the ColorChecker Classic is defined as [194, 150, 130] in RGB, that’s how it should look under correct conditions. If your footage shows something different, that’s a sign of a color cast — and a starting point for correction.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Catch: Color Charts Are Just the Beginning
&lt;/h2&gt;

&lt;p&gt;Color targets are essential for calibration — but that’s all they are. A beginning. They don’t account for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how colors behave in highlights or shadows;&lt;/li&gt;
&lt;li&gt;the unique characteristics of film stock or lenses;&lt;/li&gt;
&lt;li&gt;or the creative intent behind a particular look.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In professional tools like &lt;a href="https://www.blackmagicdesign.com" rel="noopener noreferrer"&gt;DaVinci Resolve&lt;/a&gt; or &lt;a href="https://www.dehancer.com" rel="noopener noreferrer"&gt;Dehancer&lt;/a&gt;, color charts are just step one in a long pipeline. From there, you move into advanced processes like film emulation, tone mapping, grain, halation, bloom, and other stylistic transformations. So it’s critical to understand: a chart is a calibration tool — not a style.&lt;/p&gt;

&lt;h2&gt;
  
  
  CinePalette: A Minimal Tool for Exploring Color Palettes
&lt;/h2&gt;

&lt;p&gt;To show how choosing a palette affects an image, we built CinePalette — a simple web app that visualizes what happens when you restrict your color space (a process known as palette reduction).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You Can Do with CinePalette:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;upload any image;&lt;/li&gt;
&lt;li&gt;pick a palette (ColorChecker, Portra, Sepia, etc.);&lt;/li&gt;
&lt;li&gt;remap every pixel to the closest color in that palette;&lt;/li&gt;
&lt;li&gt;compare before &amp;amp; after with an interactive slider;&lt;/li&gt;
&lt;li&gt;save the result;&lt;/li&gt;
&lt;li&gt;or build your own palette from scratch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How It Works in Code&lt;/strong&gt;&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%2F3fxd2sentyd5dfweq41r.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%2F3fxd2sentyd5dfweq41r.png" alt="Main Menu" width="724" height="1224"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our app runs entirely in the browser using React and the Canvas API. The project — called CinePalette — will be open-sourced and available on GitHub (link at the end of the series).&lt;/p&gt;

&lt;p&gt;We start with a set of predefined palettes, but users can also build and save their own. Palettes are defined as arrays of RGB values — for example, here’s what the Portra 400 palette looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Portra 400": [
  [75, 60, 50],     // shadows
  [160, 130, 110],  // skin tones
  [220, 200, 180],  // highlights
  [60, 100, 80],    // foliage
  [180, 150, 100]   // neutral
],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The selected palette defines which colors are “allowed” to appear in the final image. These become the visual language of the frame — the base tones that set its mood and style.&lt;/p&gt;

&lt;p&gt;When a user uploads an image and chooses a palette, here’s what happens under the hood:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The image is rendered to a hidden &lt;/strong&gt; — this gives us pixel-level access to manipulate the data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;We extract the ImageData object&lt;/strong&gt;, which contains an array where each pixel is represented by four values: [R, G, B, A].&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;We loop through every pixel&lt;/strong&gt;, extract its RGB color.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For each pixel, we find the closest matching color from the selected palette&lt;/strong&gt;, using Euclidean distance in RGB space — and replace it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s load up a &lt;a href="https://www.npr.org/2014/11/13/363517842/for-decades-kodak-s-shirley-cards-set-photography-s-skin-tone-standard" rel="noopener noreferrer"&gt;Shirley card&lt;/a&gt; and try applying different palettes — you’ll see immediately how the palette choice shapes the 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%2Fdgjitfw42wmpnuwi67ah.jpeg" 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%2Fdgjitfw42wmpnuwi67ah.jpeg" alt="We applied Teal &amp;amp; Orange, Sepia, and ColorChecker Classic palettes to a classic Shirley card" width="600" height="834"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The core of the magic lies in a function that analyzes &lt;strong&gt;each individual pixel&lt;/strong&gt; and finds &lt;strong&gt;the closest matching color&lt;/strong&gt; from the selected palette:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const findClosestColor = (r, g, b) =&amp;gt; {
  let minDist = Infinity;
  let closest = [r, g, b];
  for (let [pr, pg, pb] of palette) {
    const dist = Math.sqrt((r - pr) ** 2 + (g - pg) ** 2 + (b - pb) ** 2);
    if (dist &amp;lt; minDist) {
      minDist = dist;
      closest = [pr, pg, pb];
    }
  }
  return closest;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, we replace the pixel’s original color in the ImageData with the closest match from the palette. And we repeat this — &lt;strong&gt;for every single pixel&lt;/strong&gt; in the image.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (let i = 0; i &amp;lt; data.length; i += 4) {
  const [r, g, b] = [data[i], data[i + 1], data[i + 2]];
  const [nr, ng, nb] = findClosestColor(r, g, b);
  data[i] = nr;
  data[i + 1] = ng;
  data[i + 2] = nb;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once all pixels have been processed, we render the result back onto the  and convert it to an image using &lt;strong&gt;.toDataURL()&lt;/strong&gt;. This allows the user to &lt;strong&gt;see the result instantly in the browser&lt;/strong&gt; — and download the filtered image with a single click.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ctx.putImageData(imageData, 0, 0);
setFilteredImage(canvas.toDataURL());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we use &lt;strong&gt;Euclidean distance&lt;/strong&gt; in RGB space — a classic method to measure how “close” two colors are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const dist = Math.sqrt((r - pr) ** 2 + (g - pg) ** 2 + (b - pb) ** 2);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, (r, g, b) is the color of the current pixel, and (pr, pg, pb) is one of the colors in the palette. Out of all the distances calculated, we choose the smallest one — the closest visual match within the selected palette.&lt;/p&gt;

&lt;p&gt;This approach is intuitive and easy to implement, but it has limitations: RGB space doesn’t account for how humans actually perceive color — for instance, we’re more sensitive to green than to blue, and brightness differences can be misleading.&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%2Fx51oim3t0lx5gden7tof.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%2Fx51oim3t0lx5gden7tof.png" alt="B&amp;amp;W palette" width="300" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We use this approach in CinePalette as a simple and accessible way to demonstrate the basic principle of color mapping. However, even in its current form, you might notice that some colors get replaced in ways that feel unexpected or “off.”&lt;/p&gt;

&lt;p&gt;In future versions, we plan to add a toggle between RGB and CIELAB color spaces — allowing users to compare how different models affect the accuracy of color matching.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does This Matter?
&lt;/h2&gt;

&lt;p&gt;CinePalette showcases a basic but fundamental step in color grading: palette restriction. This is where every visual style begins — with the question: “What if we only used these colors?”.&lt;/p&gt;

&lt;p&gt;A Portra palette brings warm, nostalgic tones. Pro 400 feels cool and subdued. Teal &amp;amp; Orange delivers high-contrast cinematic punch. Unlike tools like Dehancer or Resolve, CinePalette doesn’t simulate the physics of film. But it captures the essence: &lt;strong&gt;color is a tool for style and storytelling&lt;/strong&gt;.&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%2Fgsvbp5oyr1h5plf8kmt4.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%2Fgsvbp5oyr1h5plf8kmt4.png" alt="Application interface" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;This is just the beginning. In the next parts of the series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we’ll expand CinePalette with the ability to pick a palette from a reference image;&lt;/li&gt;
&lt;li&gt;add automatic extraction of color schemes from any frame or photo;&lt;/li&gt;
&lt;li&gt;introduce a toggle between RGB and LAB for more perceptually accurate matching;&lt;/li&gt;
&lt;li&gt;and break down how color harmony works — and how you can use it in real-world grading.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Stay tuned — and get ready to not just learn color, but truly see it.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>colorgrading</category>
      <category>imageprocessing</category>
      <category>react</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
