    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017package org.apache.commons.imaging.formats.tiff.photometricinterpreters.floatingpoint;
    018
    019import java.awt.Color;
    020
    021/**
    022 * Provides a palette entry for colors associated with a range of values. The
    023 * return value will be interpolated between the minimum and maximum value for
    024 * this entry.
    025 * <p>
    026 * In keeping with the conventions of many Geographic Information Systems (GIS)
    027 * and art applications, this instance "covered" values in the range v0 &le; f
    028 * &lt; v1. Thus, a value that exactly matches the upper bound of the range is
    029 * not considered "covered".
    030 */
    031public class PaletteEntryForRange implements PaletteEntry {
    032
    033    private final float v0;
    034    private final float v1;
    035    private final float r0;
    036    private final float r1;
    037    private final float g0;
    038    private final float g1;
    039    private final float b0;
    040    private final float b1;
    041    private final float a0;
    042    private final float a1;
    043
    044    /**
    045     * Constructs a palette entry for the range of values v0 &le; f &lt; v1. The
    046     * return color value will be interpolated between the two specified colors.
    047     *
    048     * @param v0 the lower bounds (inclusive) of the covered range of values
    049     * @param v1 the upper bounds (non-inclusive) of the covered range of value
    050     * @param color0 the color assigned to value v0
    051     * @param color1 the color assigned to value v1
    052     */
    053    public PaletteEntryForRange(final float v0, final float v1, final Color color0, final Color color1) {
    054        this.v0 = v0;
    055        this.v1 = v1;
    056        final float deltaV = v1 - v0;
    057        // check for range volation
    058        if (deltaV <= 0 || Float.isNaN(deltaV)) {
    059            throw new IllegalArgumentException("Specified values must be v0<v1");
    060        }
    061        if (color0 == null || color1 == null) {
    062            throw new IllegalArgumentException("Null colors not allowed");
    063        }
    064        final int argb0 = color0.getRGB();
    065        a0 = (argb0 >> 24) & 0xff;
    066        r0 = (argb0 >> 16) & 0xff;
    067        g0 = (argb0 >> 8) & 0xff;
    068        b0 = argb0 & 0xff;
    069
    070        final int argb1 = color1.getRGB();
    071        a1 = (argb1 >> 24) & 0xff;
    072        r1 = (argb1 >> 16) & 0xff;
    073        g1 = (argb1 >> 8) & 0xff;
    074        b1 = argb1 & 0xff;
    075    }
    076
    077    /**
    078     * Constructs a palette entry for the range of values v0 &le; f &lt; v1. A
    079     * single color will be returned for all values in range
    080     *
    081     * @param v0 the lower bounds (inclusive) of the covered range of values
    082     * @param v1 the upper bounds (non-inclusive) of the covered range of value
    083     * @param color the color assigned to value v0
    084     */
    085    public PaletteEntryForRange(final float v0, final float v1, final Color color) {
    086        this.v0 = v0;
    087        this.v1 = v1;
    088        final float deltaV = v1 - v0;
    089        // check for range volation
    090        if (deltaV <= 0 || Float.isNaN(deltaV)) {
    091            throw new IllegalArgumentException("Specified values must be v0<v1");
    092        }
    093        if (color == null) {
    094            throw new IllegalArgumentException("Null colors not allowed");
    095        }
    096
    097        final int argb0 = color.getRGB();
    098        a0 = (argb0 >> 24) & 0xff;
    099        r0 = (argb0 >> 16) & 0xff;
    100        g0 = (argb0 >> 8) & 0xff;
    101        b0 = argb0 & 0xff;
    102
    103        final int argb1 = color.getRGB();
    104        a1 = (argb1 >> 24) & 0xff;
    105        r1 = (argb1 >> 16) & 0xff;
    106        g1 = (argb1 >> 8) & 0xff;
    107        b1 = argb1 & 0xff;
    108    }
    109
    110    @Override
    111    public boolean isCovered(final float f) {
    112        return v0 <= f && f < v1;
    113    }
    114
    115    @Override
    116    public int getARGB(final float f) {
    117        if (v0 <= f && f <= v1) {
    118            final float t = (f - v0) / (v1 - v0);
    119            final int a = (int) (t * (a1 - a0) + a0 + 0.5);
    120            final int r = (int) (t * (r1 - r0) + r0 + 0.5);
    121            final int g = (int) (t * (g1 - g0) + g0 + 0.5);
    122            final int b = (int) (t * (b1 - b0) + b0 + 0.5);
    123            return (((((a << 8) | r) << 8) | g) << 8) | b;
    124        }
    125        return 0;
    126    }
    127
    128    @Override
    129    public Color getColor(final float f) {
    130        if (v0 <= f && f <= v1) {
    131            final float t = (f - v0) / (v1 - v0);
    132            final int a = (int) (t * (a1 - a0) + a0 + 0.5);
    133            final int r = (int) (t * (r1 - r0) + r0 + 0.5);
    134            final int g = (int) (t * (g1 - g0) + g0 + 0.5);
    135            final int b = (int) (t * (b1 - b0) + b0 + 0.5);
    136            return new Color(r, g, b, a);
    137        }
    138        return null;
    139    }
    140
    141    @Override
    142    public boolean coversSingleEntry() {
    143        return false;
    144    }
    145
    146    @Override
    147    public float getLowerBound() {
    148        return v0;
    149    }
    150
    151    @Override
    152    public float getUpperBound() {
    153        return v1;
    154    }
    155
    156    @Override
    157    public String toString() {
    158        return "PaletteEntry for range " + v0 + ", " + v1;
    159    }
    160}