001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.layer.imagery;
003
004import java.awt.Transparency;
005import java.awt.image.BufferedImage;
006import java.awt.image.LookupOp;
007import java.awt.image.ShortLookupTable;
008
009import org.openstreetmap.josm.Main;
010import org.openstreetmap.josm.gui.layer.ImageProcessor;
011
012/**
013 * An image processor which adjusts the gamma value of an image.
014 * @since 10547
015 */
016public class GammaImageProcessor implements ImageProcessor {
017    private double gamma = 1;
018    final short[] gammaChange = new short[256];
019    private final LookupOp op3 = new LookupOp(
020            new ShortLookupTable(0, new short[][]{gammaChange, gammaChange, gammaChange}), null);
021    private final LookupOp op4 = new LookupOp(
022            new ShortLookupTable(0, new short[][]{gammaChange, gammaChange, gammaChange, gammaChange}), null);
023
024    /**
025     * Returns the currently set gamma value.
026     * @return the currently set gamma value
027     */
028    public double getGamma() {
029        return gamma;
030    }
031
032    /**
033     * Sets a new gamma value, {@code 1} stands for no correction.
034     * @param gamma new gamma value
035     */
036    public void setGamma(double gamma) {
037        this.gamma = gamma;
038        for (int i = 0; i < 256; i++) {
039            gammaChange[i] = (short) (255 * Math.pow(i / 255., gamma));
040        }
041    }
042
043    @Override
044    public BufferedImage process(BufferedImage image) {
045        if (gamma == 1) {
046            return image;
047        }
048        try {
049            final int bands = image.getRaster().getNumBands();
050            if (image.getType() != BufferedImage.TYPE_CUSTOM && bands == 3) {
051                return op3.filter(image, null);
052            } else if (image.getType() != BufferedImage.TYPE_CUSTOM && bands == 4) {
053                return op4.filter(image, null);
054            }
055        } catch (IllegalArgumentException ignore) {
056            Main.trace(ignore);
057        }
058        final int type = image.getTransparency() == Transparency.OPAQUE ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB;
059        final BufferedImage to = new BufferedImage(image.getWidth(), image.getHeight(), type);
060        to.getGraphics().drawImage(image, 0, 0, null);
061        return process(to);
062    }
063
064    @Override
065    public String toString() {
066        return "GammaImageProcessor [gamma=" + gamma + ']';
067    }
068}