001    /*
002     * EqualizeHistogram
003     * 
004     * Copyright (c) 2001, 2002, 2003 Marco Schmidt.
005     * All rights reserved.
006     */
007    
008    package net.sourceforge.jiu.color.adjustment;
009    
010    import net.sourceforge.jiu.color.analysis.Histogram1DCreator;
011    import net.sourceforge.jiu.color.data.Histogram1D;
012    import net.sourceforge.jiu.data.IntegerImage;
013    import net.sourceforge.jiu.ops.LookupTableOperation;
014    import net.sourceforge.jiu.ops.OperationFailedException;
015    
016    /**
017     * Equalize the image using histogram information separately for each channel.
018     * Works for intensity-based image types like {@link net.sourceforge.jiu.data.Gray8Image} or 
019     * {@link net.sourceforge.jiu.data.RGB24Image}.
020     *
021     * @author Marco Schmidt
022     * @since 0.6.0
023     */
024    public class EqualizeHistogram extends LookupTableOperation
025    {
026            /**
027             * Creates an object of this class and initializes the lookup
028             * tables with the argument input image.
029             * @param in the input image
030             */
031            public EqualizeHistogram(IntegerImage in) throws OperationFailedException
032            {
033                    super(in.getNumChannels());
034                    setInputImage(in);
035                    initTables(in);
036            }
037    
038            private void initTables(IntegerImage in) throws OperationFailedException
039            {
040                    for (int channelIndex = 0; channelIndex < in.getNumChannels(); channelIndex++)
041                    {
042                            Histogram1DCreator hc = new Histogram1DCreator();
043                            hc.setImage(in, channelIndex);
044                            hc.process();
045                            Histogram1D hist = hc.getHistogram();
046    
047                            final int MAX_SAMPLE = in.getMaxSample(channelIndex);
048                            int[] data = new int[MAX_SAMPLE + 1];
049                            int NUM_PIXELS = in.getWidth() * in.getHeight();
050                            long sum = 0;
051                            for (int i = 0; i < data.length; i++)
052                            {
053                                    sum += hist.getEntry(i);
054                                    long result = sum * MAX_SAMPLE / NUM_PIXELS; 
055                                    if (result > (long)Integer.MAX_VALUE)
056                                    {
057                                            throw new IllegalStateException("Result does not fit into an int.");
058                                    }
059                                    data[i] = (int)result;
060                            }
061                            setTable(channelIndex, data);
062                    }
063            }
064    }