001    /*
002     * Brightness
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.data.GrayIntegerImage;
011    import net.sourceforge.jiu.data.IntegerImage;
012    import net.sourceforge.jiu.data.Palette;
013    import net.sourceforge.jiu.data.Paletted8Image;
014    import net.sourceforge.jiu.data.RGBIntegerImage;
015    import net.sourceforge.jiu.ops.LookupTableOperation;
016    import net.sourceforge.jiu.ops.MissingParameterException;
017    import net.sourceforge.jiu.ops.WrongParameterException;
018    
019    /**
020     * Adjusts the brightness of an image.
021     * The amount of adjustment is given to the constructor as a percentage value between -100 and 100.
022     * -100 will make the resulting image black, 0 will leave it unchanged, 100 will make it white.
023     * <h3>Usage example</h3>
024     * This code snippet will increase <code>image</code>'s brightness by 30 percent.
025     * <pre>
026     * Brightness brightness = new Brightness();
027     * brightness.setInputImage(image);
028     * brightness.setBrightness(30);
029     * brightness.process();
030     * PixelImage adjustedImage = brightness.getOutputImage();
031     * </pre>
032     * @author Marco Schmidt
033     */
034    public class Brightness extends LookupTableOperation
035    {
036            private int brightness;
037    
038            /**
039             * Creates a lookup table that holds all new values for samples 0 to
040             * numSamples - 1.
041             */
042            private int[] createLookupTable(int numSamples, int brightness)
043            {
044                    if (brightness < -100 || brightness > 100)
045                    {
046                            return null;
047                    }
048                    int[] result = new int[numSamples];
049                    final int MAX = numSamples - 1;
050                    final float MID = MAX / 2.0f;
051                    for (int i = 0; i < numSamples; i++)
052                    {
053                            if (brightness < 0)
054                            {
055                                    result[i] = (int)((float)i  * (100.0f + brightness) / 100.0f);
056                            }
057                            else
058                            {
059                                    result[i] = (int)(i + (MAX - i) * brightness / 100.0f);
060                            }
061                    }
062                    return result;
063            }
064    
065            private void process(Paletted8Image in, Paletted8Image out)
066            {
067                    if (out == null)
068                    {
069                            out = (Paletted8Image)in.createCompatibleImage(in.getWidth(), in.getHeight());
070                    }
071                    Palette palette = out.getPalette();
072                    int numSamples = palette.getMaxValue() + 1;
073                    final int[] LUT = createLookupTable(numSamples, brightness);
074                    for (int c = 0; c < 3; c++)
075                    {
076                            for (int i = 0; i < palette.getNumEntries(); i++)
077                            {
078                                    palette.putSample(c, i, LUT[palette.getSample(c, i)]);
079                            }
080                    }
081                    for (int y = 0; y < in.getHeight(); y++)
082                    {
083                            for (int x = 0; x < in.getWidth(); x++)
084                            {
085                                    out.putSample(0, x, y, in.getSample(0, x, y));
086                            }
087                            setProgress(y, in.getHeight());
088                    }
089                    setOutputImage(out);
090            }
091    
092            public void process() throws
093                    MissingParameterException,
094                    WrongParameterException
095            {
096                    prepareImages();
097                    IntegerImage in = (IntegerImage)getInputImage();
098                    if (in instanceof GrayIntegerImage || in instanceof RGBIntegerImage)
099                    {
100                            setNumTables(in.getNumChannels());
101                            for (int channelIndex = 0; channelIndex < in.getNumChannels(); channelIndex++)
102                            {
103                                    setTable(channelIndex, createLookupTable(in.getMaxSample(channelIndex) + 1, brightness));
104                            }
105                            super.process();
106                    }
107                    else
108                    if (in instanceof Paletted8Image)
109                    {
110                            process((Paletted8Image)in, (Paletted8Image)getOutputImage());
111                    }
112                    else
113                    {
114                            throw new WrongParameterException("Brightness operation cannot operate on input image type: " + in.getClass());
115                    }
116            }
117    
118            /**
119             * Sets the brightness adjustment value in percent (between -100 and 100).
120             * @param newBrightness the amount of change to be applied to the brightness of the input image
121             * @throws IllegalArgumentException if the argument is smaller than -100 or larger than 100
122             */
123            public void setBrightness(int newBrightness)
124            {
125                    if (newBrightness < -100)
126                    {
127                            throw new IllegalArgumentException("Brightness must be at least -100: " + newBrightness);
128                    }
129                    if (newBrightness > 100)
130                    {
131                            throw new IllegalArgumentException("Brightness must be at most 100: " + newBrightness);
132                    }
133                    brightness = newBrightness;
134            }
135    }