
// ColorCounter.java
// Andrew Davison, ad@coe.psu.ac.th, April 2023

/* Count the number of unique colors in an RGB image.
   Display the pixels counts for each of the colors 
   when there are there are 20 colors or less with counts
   higher than MIN_COUNT.

   Convert the image to grayscale, then apply the "Fire" LUT,
   convert the image back to RGB, and count the colors again.

   A LUT is a predefined table of gray values with matching 
   red, green, and blue values so that shadows of gray are 
   displayed as colorized pixels. 
 
   Usage:
     > compile ColorCounter.java
     > run ColorCounter <fnm>
   e.g.
     > run ColorCounter shapes.png
     > run ColorCounter squares.png

   For hex to color name lookups:
    // https://www.rapidtables.com/convert/color/hex-to-rgb.html

*/

import java.awt.image.*;
import java.awt.color.*;

import ij.*;
import ij.process.*;
import ij.plugin.*;


public class ColorCounter
{
  private static final int NUM_COLORS = 256*256*256;
  private static final int MIN_COUNT = 25;


  public static void main(String[] args)
  {
    if (args.length != 1) {
      System.out.println("Usage: run ColorCounter <fnm>");
      return;
    }

    ImagePlus imp = new ImagePlus(args[0]);
    if (!imp.isRGB()) {
      System.out.println("Not an RGB image");
      return;
    }
    imp.show();

    ImageProcessor imProc = imp.getProcessor();
    int[] pixels = (int[]) imProc.getPixels();
    countColors(pixels);

    IJ.wait(2000);

    System.out.println("RGB --> Grayscale --> fire LUT");
    IJ.run("8-bit");
    IJ.run("Fire");
    String lutName = imp.getProp("CurrentLUT");
    System.out.println("Current LUT: " + lutName);

   // ImageInfo imInfo = new ImageInfo();
   // System.out.println(imInfo.getImageInfo(imp));

    System.out.println("\nFire LUT --> RGB");
    IJ.run("RGB Color");

    imProc = imp.getProcessor();
    pixels = (int[]) imProc.getPixels();
    countColors(pixels);
  } /* main */




  private static void countColors(int[] pixels)
  {
    int[] counts = new int[NUM_COLORS];
    for (int i = 0; i < pixels.length; i++)
      counts[pixels[i] & 0xffffff]++;

    int numColors = 0;
    int minCountColors = 0;
    for (int i = 0; i < NUM_COLORS; i++) {
      if (counts[i] > 0) 
        numColors++;

      if (counts[i] > MIN_COUNT) 
        minCountColors++;
    }

    System.out.println("No. of unique colors: " + numColors);
    System.out.println("No. of colors with count > " + 
                                MIN_COUNT + ": " + minCountColors);
    if (minCountColors <= 20) {
      System.out.println("\n    Color :  Counts");
      System.out.println("  -----------------");
      for (int i = 0; i < NUM_COLORS; i++) {
        if (counts[i] > MIN_COUNT)
          System.out.printf("   %6s : %6d\n",
                    Integer.toHexString(i), counts[i]);
      }
      System.out.println();
    }
  }  // end of countColors()


}  // end of ColorCounter class
