# How to apply color quantization to an image

**URL:** <https://discourse.processing.org/t/how-to-apply-color-quantization-to-an-image/4849>\
**Category:** Coding Questions\
**Created:** [October 25, 2018, 2:01am UTC](https://discourse.processing.org/t/how-to-apply-color-quantization-to-an-image/4849 "2018-10-25T02:01:44Z")\
**Posts on this page:** 7\
**Page:** 2

<div class="post-metadata">

**Author:** ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)\
**Post date:** [October 31, 2018, 12:37pm UTC](https://discourse.processing.org/t/how-to-apply-color-quantization-to-an-image/4849/21 "2018-10-31T12:37:18Z")

</div>

This is an interesting problem and I used to use it years ago to keep image file sizes down but I can’t remember what software I used. So it piqued my interest enough to create a sketch that uses the Quantize class code in the link provided by @jb4x (thanks).

So here is the result ouput from my sketch  
 ![sample](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/d/d5fa50e9be687173aa05b7424724ea712b43c247.png)

I have simply created a new tab called `Quantize.java` and copied the code from the link into it. NOTE that the tab name must match _precisely_ the class name to make it a top level class.  
The `Quatize` class expects the pixel data to be in a 2D array wheres PImage stores pixel data in a 1D array so I have created a class called `QImage` which performs all the conversion and use the `Quatize` class to do its stuff.

Anyway the main tab sketch code is shown below but if you want you can download the entire sketch from [here](http://www.lagers.org.uk/zzz/QuantizeImage.zip)

Enjoy 😂

```auto
PImage img;
QImage qimg256, qimg64, qimg16;

void setup() {
  size(520, 400);
  img = loadImage("london.jpg");
  textSize(14);
  fill(0);
  background(255);
  // Make sonme quantized images
  qimg256 = new QImage(img, 256);
  qimg64 = new QImage(img, 64);
  qimg16 = new QImage(img, 16);

  text("32 bit ARGB", 10, 18);
  image(img, 0, 20);
  text("256 colors", 270, 18);
  image(qimg256.getImage(), 260, 20);

  text("64 colors", 10, 218);
  image(qimg64.getImage(), 0, 220);
  text("16 colors", 270, 218);
  image(qimg16.getImage(), 260, 220);
  save("sample.png");
}

/**
 This class is used to store the result of the image quantization.
 The final image comprises a color table and a 2D array containing 
 an index into the color table.
 It also creates a new PImage with the reduced color set for 
 convenience.
 */
public class QImage {
  final int[][] pixels;
  final int w, h;
  final int[] colortable;
  final PImage reducedImage;

  /**
   img = the PImage we want to quantize
   maxNbrColors - color table size
   */
  public QImage(PImage img, int maxNbrColors) {
    // Pixel data needs to be in 2D array for Quantize class.
    w = img.width;
    h = img.height;
    pixels = new int[h][w];
    img.loadPixels();
    int[] p = img.pixels;
    int n = 0;
    for (int y = 0; y < h; y++) {
      for (int x = 0; x < w; x++) {
        pixels[y][x] = p[n++];
      }
    } 
    // Quantize the image
    colortable = Quantize.quantizeImage(pixels, maxNbrColors);
    //Create a PImage with the reduced color pallette
    reducedImage = createImage(w, h, ARGB);
    for (int y = 0; y < h; y++) {
      for (int x = 0; x < w; x++) {
        reducedImage.set(x, y, colortable[pixels[y][x]]);
      }
    }
  }

  /**
   Convenience method to draw the quatized image at a 
   given position.
   */
  public void displayRAW(int px, int py) {
    for (int y = 0; y < h; y++) {
      for (int x = 0; x < w; x++) {
        set(px + x, py+y, colortable[pixels[y][x]]);
      }
    }
  }

  /**
   Get the pixel color index data
   */
  public int[][] getPixels() {
    return pixels;
  }

  /**
   Get the color table data
   */
  public int[] getColorTable() {
    return colortable;
  }

  /**
   Get the maximum number of colors in the reduced image.
   The actual number of unique colors maybe less than this.
   */
  public int nbrColors() {
    return colortable.length;
  }

  /**
   Convenience method to get the quatized image as a PImage
   that can be used directly in processing
   */
  public PImage getImage() {
    return reducedImage;
  }
}

```

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [October 31, 2018, 5:02pm UTC](https://discourse.processing.org/t/how-to-apply-color-quantization-to-an-image/4849/22 "2018-10-31T17:02:52Z")

</div>

Nice, @quark!

This could also be done with the ImageJ implementation of Median Cut.

- [https://imagej.nih.gov/ij/source/ij/process/MedianCut.java](https://imagej.nih.gov/ij/source/ij/process/MedianCut.java)

The nice thing about that implementation is it is based on java.awt.Image, so it takes a pixels[] array – no 2D conversion class required.

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [October 31, 2018, 5:07pm UTC](https://discourse.processing.org/t/how-to-apply-color-quantization-to-an-image/4849/23 "2018-10-31T17:07:51Z")

</div>

In the other thread, @Kevin also shares some code he wrote to do k-means color clustering using opencv.Mat.

> [@How to make a color palette from an image ordered by frequence](https://discourse.processing.org/t/how-to-make-a-color-palette-from-an-image-ordered-by-frequence/4850/10):
>
> I’ve done something similar in the past by using k-means to cluster the colors. Some posts that you might find interesting:

---

<div class="post-metadata">

**Author:** ![troudki](https://avatars.discourse-cdn.com/v4/letter/t/ce7236/32.png) [@troudki](https://discourse.processing.org/u/troudki)\
**Post date:** [May 28, 2021, 8:39pm UTC](https://discourse.processing.org/t/how-to-apply-color-quantization-to-an-image/4849/24 "2021-05-28T20:39:07Z")

</div>

Cool,this is exactly what I was looking for but how can I save a png image with a 16 color indexed palette ?

---

<div class="post-metadata">

**Author:** ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)\
**Post date:** [May 29, 2021, 8:07am UTC](https://discourse.processing.org/t/how-to-apply-color-quantization-to-an-image/4849/25 "2021-05-29T08:07:39Z")

</div>

Although PNG supports 16 color indexed images I have no idea how you might actually save the image in this format.

No matter what file format an image is saved in, when loaded into a computer it will be converted to ARGB (32bit color) for display. So I am not sure why you would want to bother with an indexed palette.

Seems to be two possibilities

1. find a library that does this for you
2. create your own low level routine to save the image data in that [format](http://www.libpng.org/pub/png/book/chapter08.html).

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [August 20, 2021, 6:54pm UTC](https://discourse.processing.org/t/how-to-apply-color-quantization-to-an-image/4849/26 "2021-08-20T18:54:26Z")

</div>

Halfway between a library and your own image format routine – there was also a solution by @Architector_4 a while back that involved byte-copying a specific palette onto an image file, although that was for a pretty specific problem.

[https://forum.processing.org/two/discussion/28065/how-to-save-image-with-different-settings-bit-depth-etc](https://forum.processing.org/two/discussion/28065/how-to-save-image-with-different-settings-bit-depth-etc).

---

<div class="post-metadata">

**Author:** ![Architector\_4](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/architector_4/32/813_2.png) [@Architector\_4](https://discourse.processing.org/u/Architector_4)\
**Post date:** [August 20, 2021, 8:15pm UTC](https://discourse.processing.org/t/how-to-apply-color-quantization-to-an-image/4849/27 "2021-08-20T20:15:39Z")

</div>

As a little update, I guess it’s worth noting that since then I’ve migrated my solution to pure Java and put it into a GitHub repo. It takes in an image, parses it as 24 bits per pixel, and manually byte-by-byte constructs an 8-bit indexed BMP image with a hardcoded palette of 256 colors.

I don’t know the PNG format enough, but assuming that it isn’t too complex, I guess a similar solution could be used here aswell.

> **[GitHub - Architector4/img2bmp: A tool that converts images to 8-bit BMP...](https://github.com/Architector4/img2bmp)**
>
> A tool that converts images to 8-bit BMP images compatible with Cortex Command - GitHub - Architector4/img2bmp: A tool that converts images to 8-bit BMP images compatible with Cortex Command

[Previous page](https://discourse.processing.org/t/how-to-apply-color-quantization-to-an-image/4849.md?page=1)
