docs: public static void main(String pArgs[]) {
          // Defaults
          int argIdx = 0;
          int speedTest = -1;
          boolean overWrite = false;
          boolean monochrome = false;
          boolean gray = false;
          int numColors = 256;
          String dither = null;
          String quality = null;
          String format = null;
          Color background = null;
          boolean transparency = false;
          String paletteFileName = null;
          boolean errArgs = false;
  
          // Parse args
          while ((argIdx < pArgs.length) && (pArgs[argIdx].charAt(0) == '-') && (pArgs[argIdx].length() >= 2)) {
              if ((pArgs[argIdx].charAt(1) == 's') || pArgs[argIdx].equals("--speedtest")) {
                  argIdx++;
  
                  // Get number of iterations
                  if ((pArgs.length > argIdx) && (pArgs[argIdx].charAt(0) != '-')) {
                      try {
                          speedTest = Integer.parseInt(pArgs[argIdx++]);
                      }
                      catch (NumberFormatException nfe) {
                          errArgs = true;
                          break;
                      }
                  }
                  else {
  
                      // Default to 10 iterations
                      speedTest = 10;
                  }
              }
              else if ((pArgs[argIdx].charAt(1) == 'w') || pArgs[argIdx].equals("--overwrite")) {
                  overWrite = true;
                  argIdx++;
              }
              else if ((pArgs[argIdx].charAt(1) == 'c') || pArgs[argIdx].equals("--colors")) {
                  argIdx++;
  
                  try {
                      numColors = Integer.parseInt(pArgs[argIdx++]);
                  }
                  catch (NumberFormatException nfe) {
                      errArgs = true;
                      break;
                  }
              }
              else if ((pArgs[argIdx].charAt(1) == 'g') || pArgs[argIdx].equals("--grayscale")) {
                  argIdx++;
                  gray = true;
              }
              else if ((pArgs[argIdx].charAt(1) == 'm') || pArgs[argIdx].equals("--monochrome")) {
                  argIdx++;
                  numColors = 2;
                  monochrome = true;
              }
              else if ((pArgs[argIdx].charAt(1) == 'd') || pArgs[argIdx].equals("--dither")) {
                  argIdx++;
                  dither = pArgs[argIdx++];
              }
              else if ((pArgs[argIdx].charAt(1) == 'p') || pArgs[argIdx].equals("--palette")) {
                  argIdx++;
                  paletteFileName = pArgs[argIdx++];
              }
              else if ((pArgs[argIdx].charAt(1) == 'q') || pArgs[argIdx].equals("--quality")) {
                  argIdx++;
                  quality = pArgs[argIdx++];
              }
              else if ((pArgs[argIdx].charAt(1) == 'b') || pArgs[argIdx].equals("--bgcolor")) {
                  argIdx++;
                  try {
                      background = StringUtil.toColor(pArgs[argIdx++]);
                  }
                  catch (Exception e) {
                      errArgs = true;
                      break;
                  }
              }
              else if ((pArgs[argIdx].charAt(1) == 't') || pArgs[argIdx].equals("--transparency")) {
                  argIdx++;
                  transparency = true;
              }
              else if ((pArgs[argIdx].charAt(1) == 'f') || pArgs[argIdx].equals("--outputformat")) {
                  argIdx++;
                  format = StringUtil.toLowerCase(pArgs[argIdx++]);
              }
              else if ((pArgs[argIdx].charAt(1) == 'h') || pArgs[argIdx].equals("--help")) {
                  argIdx++;
  
                  // Setting errArgs to true, to print usage
                  errArgs = true;
              }
              else {
                  System.err.println("Unknown option \"" + pArgs[argIdx++] + "\"");
              }
          }
          if (errArgs || (pArgs.length < (argIdx + 1))) {
              System.err.println("Usage: IndexImage [--help|-h] [--speedtest|-s <integer>] [--bgcolor|-b <color>] [--colors|-c <integer> | --grayscale|g | --monochrome|-m | --palette|-p <file>] [--dither|-d (default|diffusion|none)] [--quality|-q (default|high|low)] [--transparency|-t] [--outputformat|-f (gif|jpeg|png|wbmp|...)] [--overwrite|-w] <input> [<output>]");
              System.err.print("Input format names: ");
              String[] readers = ImageIO.getReaderFormatNames();
  
              for (int i = 0; i < readers.length; i++) {
                  System.err.print(readers[i] + ((i + 1 < readers.length)
                          ? ", "
                          : "\n"));
              }
  
              System.err.print("Output format names: ");
              String[] writers = ImageIO.getWriterFormatNames();
  
              for (int i = 0; i < writers.length; i++) {
                  System.err.print(writers[i] + ((i + 1 < writers.length)
                          ? ", "
                          : "\n"));
              }
              System.exit(5);
          }
  
          // Read in image
          File in = new File(pArgs[argIdx++]);
  
          if (!in.exists()) {
              System.err.println("File \"" + in.getAbsolutePath() + "\" does not exist!");
              System.exit(5);
          }
  
          // Read palette if needed
          File paletteFile = null;
  
          if (paletteFileName != null) {
              paletteFile = new File(paletteFileName);
              if (!paletteFile.exists()) {
                  System.err.println("File \"" + in.getAbsolutePath() + "\" does not exist!");
                  System.exit(5);
              }
          }
  
          // Make sure we can write
          File out;
  
          if (argIdx < pArgs.length) {
              out = new File(pArgs[argIdx/*++*/]);
  
              // Get format from file extension
              if (format == null) {
                  format = FileUtil.getExtension(out);
              }
          }
          else {
              // Create new file in current dir, same name + format extension
              String baseName = FileUtil.getBasename(in);
  
              // Use png as default format
              if (format == null) {
                  format = "png";
              }
              out = new File(baseName + '.' + format);
          }
  
          if (!overWrite && out.exists()) {
              System.err.println("The file \"" + out.getAbsolutePath() + "\" allready exists!");
              System.exit(5);
          }
  
          // Do the image processing
          BufferedImage image = null;
          BufferedImage paletteImg = null;
  
          try {
              image = ImageIO.read(in);
              if (image == null) {
                  System.err.println("No reader for image: \"" + in.getAbsolutePath() + "\"!");
                  System.exit(5);
              }
              if (paletteFile != null) {
                  paletteImg = ImageIO.read(paletteFile);
                  if (paletteImg == null) {
                      System.err.println("No reader for image: \"" + paletteFile.getAbsolutePath() + "\"!");
                      System.exit(5);
                  }
              }
          }
          catch (IOException ioe) {
              ioe.printStackTrace(System.err);
              System.exit(5);
          }
  
          // Create hints
          int hints = DITHER_DEFAULT;
  
          if ("DIFFUSION".equalsIgnoreCase(dither)) {
              hints |= DITHER_DIFFUSION;
          }
          else if ("DIFFUSION_ALTSCANS".equalsIgnoreCase(dither)) {
              hints |= DITHER_DIFFUSION_ALTSCANS;
          }
          else if ("NONE".equalsIgnoreCase(dither)) {
              hints |= DITHER_NONE;
          }
          else {
  
              // Don't care, use default
          }
          if ("HIGH".equalsIgnoreCase(quality)) {
              hints |= COLOR_SELECTION_QUALITY;
          }
          else if ("LOW".equalsIgnoreCase(quality)) {
              hints |= COLOR_SELECTION_FAST;
          }
          else {
  
              // Don't care, use default
          }
          if (transparency) {
              hints |= TRANSPARENCY_BITMASK;
          }
  
          //////////////////////////////
          // Apply bg-color WORKAROUND!
          // This needs to be done BEFORE palette creation to have desired effect..
          if ((background != null) && (paletteImg == null)) {
              paletteImg = createSolid(image, background);
          }
  
          ///////////////////////////////
          // Index
          long start = 0;
  
          if (speedTest > 0) {
              // SPEED TESTING
              System.out.println("Measuring speed!");
              start = System.currentTimeMillis();
              // END SPEED TESTING
          }
  
          BufferedImage indexed;
          IndexColorModel colors;
  
          if (monochrome) {
              indexed = getIndexedImage(image, MonochromeColorModel.getInstance(), background, hints);
              colors = MonochromeColorModel.getInstance();
          }
          else if (gray) {
              //indexed = ImageUtil.toBuffered(ImageUtil.grayscale(image), BufferedImage.TYPE_BYTE_GRAY);
              image = ImageUtil.toBuffered(ImageUtil.grayscale(image));
              indexed = getIndexedImage(image, colors = getIndexColorModel(image, numColors, hints), background, hints);
  
              // In casse of speedtest, this makes sense...
              if (speedTest > 0) {
                  colors = getIndexColorModel(indexed, numColors, hints);
              }
          }
          else if (paletteImg != null) {
              // Get palette from image
              indexed = getIndexedImage(ImageUtil.toBuffered(image, BufferedImage.TYPE_INT_ARGB),
                                        colors = getIndexColorModel(paletteImg, numColors, hints), background, hints);
          }
          else {
              image = ImageUtil.toBuffered(image, BufferedImage.TYPE_INT_ARGB);
              indexed = getIndexedImage(image, colors = getIndexColorModel(image, numColors, hints), background, hints);
          }
  
          if (speedTest > 0) {
              // SPEED TESTING
              System.out.println("Color selection + dither: " + (System.currentTimeMillis() - start) + " ms");
              // END SPEED TESTING
          }
  
          // Write output (in given format)
          try {
              if (!ImageIO.write(indexed, format, out)) {
                  System.err.println("No writer for format: \"" + format + "\"!");
              }
          }
          catch (IOException ioe) {
              ioe.printStackTrace(System.err);
          }
  
          if (speedTest > 0) {
              // SPEED TESTING
              System.out.println("Measuring speed!");
  
              // Warmup!
              for (int i = 0; i < 10; i++) {
                  getIndexedImage(image, colors, background, hints);
              }
  
              // Measure
              long time = 0;
  
              for (int i = 0; i < speedTest; i++) {
                  start = System.currentTimeMillis();
                  getIndexedImage(image, colors, background, hints);
                  time += (System.currentTimeMillis() - start);
                  System.out.print('.');
                  if ((i + 1) % 10 == 0) {
                      System.out.println("\nAverage (after " + (i + 1) + " iterations): " + (time / (i + 1)) + "ms");
                  }
              }
  
              System.out.println("\nDither only:");
              System.out.println("Total time (" + speedTest + " invocations): " + time + "ms");
              System.out.println("Average: " + time / speedTest + "ms");
              // END SPEED TESTING
          }
      }