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    }