001 /* 002 * ColorIndexer 003 * 004 * Copyright (c) 2003 Marco Schmidt. 005 * All rights reserved. 006 */ 007 package net.sourceforge.jiu.apps; 008 009 import java.io.File; 010 import java.text.DecimalFormat; 011 import java.text.NumberFormat; 012 013 import net.sourceforge.jiu.color.adjustment.Contrast; 014 import net.sourceforge.jiu.color.promotion.PromotionRGB24; 015 import net.sourceforge.jiu.data.PixelImage; 016 import net.sourceforge.jiu.data.RGB24Image; 017 import net.sourceforge.jiu.data.RGBIndex; 018 import net.sourceforge.jiu.geometry.Resample; 019 import net.sourceforge.jiu.gui.awt.ToolkitLoader; 020 import net.sourceforge.jiu.ops.BatchProcessorOperation; 021 import net.sourceforge.jiu.ops.OperationFailedException; 022 023 /** 024 * Loads image files and generates color index information for them. 025 * @author Marco Schmidt 026 * @since 0.12.0 027 */ 028 public class ColorIndexer extends BatchProcessorOperation 029 { 030 private int maxLength = 256; 031 private int contrastChange = 100; 032 private NumberFormat formatter = new DecimalFormat("#.##"); 033 034 public static final int BLACK = 0; 035 public static final int RED = 4; 036 public static final int GREEN = 2; 037 public static final int BLUE = 1; 038 public static final int YELLOW = 6; 039 public static final int MAGENTA = 5; 040 public static final int CYAN = 3; 041 public static final int WHITE = 7; 042 public static final String[] COLOR_NAMES = 043 {"black", "blue", "green", "cyan", "red", "magenta", "yellow", "white"}; 044 045 public static void main(String[] args) 046 { 047 ColorIndexer indexer = new ColorIndexer(); 048 for (int i = 0; i < args.length; i++) 049 { 050 String name = args[i]; 051 File file = new File(name); 052 if (file.isFile()) 053 { 054 indexer.addInputFileName(name); 055 } 056 else 057 if (file.isDirectory()) 058 { 059 indexer.addDirectoryTree(name); 060 } 061 } 062 indexer.process(); 063 System.out.println("Done."); 064 } 065 066 private PixelImage convertToRgb24(PixelImage in) 067 { 068 if (in == null) 069 { 070 return null; 071 } 072 if (in instanceof RGB24Image) 073 { 074 return in; 075 } 076 try 077 { 078 PromotionRGB24 pr = new PromotionRGB24(); 079 pr.setInputImage(in); 080 pr.process(); 081 return pr.getOutputImage(); 082 } 083 catch (OperationFailedException ofe) 084 { 085 return null; 086 } 087 } 088 089 private PixelImage adjustColor(PixelImage img) 090 { 091 if (img == null || contrastChange == 0) 092 { 093 return img; 094 } 095 try 096 { 097 Contrast con = new Contrast(); 098 con.setInputImage(img); 099 con.setContrast(contrastChange); 100 con.process(); 101 return con.getOutputImage(); 102 /* HueSaturationValue hsv = new HueSaturationValue(); 103 hsv.setInputImage(img); 104 hsv.setSaturationValue(30, 0); 105 hsv.process(); 106 return hsv.getOutputImage();*/ 107 } 108 catch (OperationFailedException ofe) 109 { 110 return null; 111 } 112 } 113 114 private PixelImage scale(PixelImage in) 115 { 116 if (in == null) 117 { 118 return null; 119 } 120 if (in.getWidth() <= maxLength && in.getHeight() <= maxLength) 121 { 122 return in; 123 } 124 try 125 { 126 Resample res = new Resample(); 127 res.setFilter(Resample.FILTER_TYPE_LANCZOS3); 128 res.setInputImage(in); 129 float thumbRatio = 1.0f; 130 float imageRatio = (float)in.getWidth() / (float)in.getHeight(); 131 int width = maxLength; 132 int height = maxLength; 133 if (thumbRatio < imageRatio) 134 { 135 height = (int)(maxLength / imageRatio); 136 } 137 else 138 { 139 width = (int)(maxLength * imageRatio); 140 } 141 float x = (float)in.getWidth() / maxLength; 142 float y = (float)in.getHeight() / maxLength; 143 res.setSize(width, height); 144 res.process(); 145 return res.getOutputImage(); 146 } 147 catch (OperationFailedException ofe) 148 { 149 return null; 150 } 151 } 152 153 private int[] count(PixelImage image) 154 { 155 if (image == null) 156 { 157 return null; 158 } 159 RGB24Image in = (RGB24Image)image; 160 int[] result = new int[8]; 161 for (int y = 0; y < image.getHeight(); y++) 162 { 163 for (int x = 0; x < image.getWidth(); x++) 164 { 165 int red = in.getSample(RGBIndex.INDEX_RED, x, y) >> 7; 166 int green = in.getSample(RGBIndex.INDEX_GREEN, x, y) >> 7; 167 int blue = in.getSample(RGBIndex.INDEX_BLUE, x, y) >> 7; 168 int index = (red << 2) | (green << 1) | blue; 169 result[index]++; 170 } 171 } 172 return result; 173 } 174 175 /*private void save(PixelImage img, String fileName) 176 { 177 PNGCodec codec = new PNGCodec(); 178 try 179 { 180 codec.setImage(img); 181 codec.setFile(fileName, CodecMode.SAVE); 182 codec.process(); 183 codec.close(); 184 } 185 catch (OperationFailedException ofe) 186 { 187 } 188 catch (IOException ioe) 189 { 190 } 191 }*/ 192 193 private void store(String name, int[] occ) 194 { 195 if (name == null || occ == null) 196 { 197 return; 198 } 199 int sum = 0; 200 for (int i = 0; i < occ.length; i++) 201 { 202 sum += occ[i]; 203 } 204 System.out.print(name); 205 System.out.print(';'); 206 for (int i = 0; i < occ.length; i++) 207 { 208 float rel = (float)occ[i] / sum; 209 if (rel < 0.01f) 210 { 211 continue; 212 } 213 System.out.print(COLOR_NAMES[i] + " = " + formatter.format(rel) + ";"); 214 } 215 System.out.println(); 216 } 217 218 public void processFile(String inputDirectory, String inputFileName, String outputDirectory) 219 { 220 File dir = new File(inputDirectory); 221 File file = new File(dir, inputFileName); 222 String name = file.getAbsolutePath(); 223 // load image 224 PixelImage image = ToolkitLoader.loadViaToolkitOrCodecs(name); 225 // convert to RGB24 if necessary 226 image = convertToRgb24(image); 227 // scale down if necessary 228 image = scale(image); 229 // increase contrast 230 image = adjustColor(image); 231 // save the modified image, for testing purposes 232 /*File outFile = new File("f:\\", "th_" + inputFileName + ".png"); 233 save(image, outFile.getAbsolutePath());*/ 234 // determine occurrence of colors 235 int[] occur = count(image); 236 // store 237 store(name, occur); 238 } 239 }