com.github.ojil.core.RgbVal Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ojil-core Show documentation
Show all versions of ojil-core Show documentation
Open Java Imaging Library.
/*
* RgbVal.java
*
* Created on September 9, 2006, 10:42 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*
* Copyright 2006 by Jon A. Webb
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program. If not, see .
*
*/
package com.github.ojil.core;
/**
* Helper class for manipulating RGB values. All functions are static.
*
* @author webb
*/
public class RgbVal {
/**
* Converts byte R, G, and B values to an ARGB word. byte is a signed data
* type but the ARGB word has unsigned bit fields. In other words the
* minimum byte value is Byte.MIN_VALUE but the color black in the ARGB word
* is represented as 0x00. So we must subtract Byte.MIN_VALUE to get an
* unsigned byte value before shifting and combining the bit fields.
*
* @param R
* input signed red byte
* @param G
* input signed green byte
* @param B
* input signed blue byte
* @return the color ARGB word.
*/
public static int toRgb(final byte R, final byte G, final byte B) {
return 0xFF000000 | (RgbVal.toUnsignedInt(R) << 16) | (RgbVal.toUnsignedInt(G) << 8) | RgbVal.toUnsignedInt(B);
}
/**
* Compare two RgbVals in absolute value.
*
* @return sum of absolute differences between pixel values
*/
public static int getAbsDiff(final int rgb1, final int rgb2) {
return Math.abs(RgbVal.getR(rgb1) - RgbVal.getR(rgb2)) + Math.abs(RgbVal.getG(rgb1) - RgbVal.getG(rgb2)) + Math.abs(RgbVal.getB(rgb1) - RgbVal.getB(rgb2));
}
/**
* Compare two RgbVals in maximum difference in any band.
*
* @return maximum difference between pixel values in any band
*/
/**
* Computes maximum difference (largest difference in color, R, G, or B) of
* two color values.
*
* @param ARGB1
* first color
* @param ARGB2
* second color
* @return largest difference. Will always be >= 0, <= 256.
*/
public static int getMaxDiff(final int ARGB1, final int ARGB2) {
final int nR1 = RgbVal.getR(ARGB1);
final int nG1 = RgbVal.getG(ARGB1);
final int nB1 = RgbVal.getB(ARGB1);
final int nR2 = RgbVal.getR(ARGB2);
final int nG2 = RgbVal.getG(ARGB2);
final int nB2 = RgbVal.getB(ARGB2);
return Math.max(Math.abs(nR1 - nR2), Math.max(Math.abs(nG1 - nG2), Math.abs(nB1 - nB2)));
}
public static int getProportionateDiff(final int ARGB1, final int ARGB2) {
final int nR1 = RgbVal.getR(ARGB1) - Byte.MIN_VALUE;
final int nG1 = RgbVal.getG(ARGB1) - Byte.MIN_VALUE;
final int nB1 = RgbVal.getB(ARGB1) - Byte.MIN_VALUE;
final int nR2 = RgbVal.getR(ARGB2) - Byte.MIN_VALUE;
final int nG2 = RgbVal.getG(ARGB2) - Byte.MIN_VALUE;
final int nB2 = RgbVal.getB(ARGB2) - Byte.MIN_VALUE;
// We're solving the equation
// min/r ((r*nR1 - nR2) + (r*nG1 - nG2) + (r*nB1 - nB2))**2
// which gives 2*((r*nR1 - nR2)*nR1 + (r*nG1 - nG2)*nG1 + (r*nB1 -
// nB2)*nB1) = 0
// or r = (nR1*nR2 + nG1*nG2 + nB1*nB2) / (nR1*nR1 + nG1*nG1 + nB1*nB1)
// we divide r into nNum / nDenom to avoid floating point
final int nNum = ((nR1 * nR2) + (nG1 * nG2) + (nB1 * nB2));
final int nDenom = ((nR1 * nR1) + (nG1 * nG1) + (nB1 * nB1));
if (nDenom == 0) {
return 3 * Byte.MAX_VALUE;
}
// the error is then ((r*nR1 - nR2) + (r*nG1 - nG2) + (r*nB1 - nB2))**2
// or (r*(nR1 + nG1 + nB1) - (nR2 + nB2 + nG2))**2
// or ((nNum*(nR1 + nG1 + nB1) - nDenom*(nR1 + nG2 + nB2)) / nDenom)**2
// or ((nNum*(nR1 + nG1 + nB1) - nDenom*(nR1 + nG2 + nB2))**2 /
// nDenom**2
return MathPlus.square(8 * ((nNum * (nR1 + nG1 + nB1)) - (nDenom * (nR1 + nG2 + nB2)))) / MathPlus.square(nDenom);
}
/**
* Compare two RgbVals in sum of squares difference.
*
* @return sum of squares differences between pixel values
*/
public static int getSqrDiff(final int rgb1, final int rgb2) {
return MathPlus.square(RgbVal.getR(rgb1) - RgbVal.getR(rgb2)) + MathPlus.square(RgbVal.getG(rgb1) - RgbVal.getG(rgb2)) + MathPlus.square(RgbVal.getB(rgb1) - RgbVal.getB(rgb2));
}
/**
* Extracts blue byte from input ARGB word. The bit fields in ARGB word are
* unsigned, ranging from 0x00 to 0xff. To convert these to the returned
* signed byte value we must add Byte.MIN_VALUE.
*
* @return the blue byte value, converted to a signed byte
* @param ARGB
* the input color ARGB word.
*/
public static Byte getB(final int ARGB) {
return RgbVal.toSignedByte((byte) (ARGB & 0xff));
}
/**
* Extracts green byte from input ARGB word. The bit fields in ARGB word are
* unsigned, ranging from 0x00 to 0xff. To convert these to the returned
* signed byte value we must add Byte.MIN_VALUE.
*
* @param ARGB
* the input color ARGB word.
* @return the green byte value, converted to a signed byte
*/
public static Byte getG(final int ARGB) {
return RgbVal.toSignedByte((byte) ((ARGB >> 8) & 0xff));
}
/**
* Extracts red byte from input ARGB word. The bit fields in ARGB word are
* unsigned, ranging from 0x00 to 0xff. To convert these to the returned
* signed byte value we must add Byte.MIN_VALUE.
*
* @param ARGB
* the input color ARGB word.
* @return the red byte value, converted to a signed byte
*/
public static Byte getR(final int ARGB) {
return RgbVal.toSignedByte((byte) ((ARGB >> 16) & 0xff));
}
/**
* Return "vector" difference of Rgb values. Treating each Rgb value as a
* 3-element vector form the value (ARGB-ARGBTarg) . ARGBVec where . is dot
* product. Useful for determining whether an Rgb value is near another
* weighted the different channels differently.
*
* @param ARGB
* tested Rgb value
* @param ARGBTarg
* target Rgb value
* @param ARGBVec
* weighting
* @return (ARGB-ARGBTarg) . ARGBVec where . is dot product and the Rgb
* values are treated as 3-vectors.
*/
public static int getVecDiff(final int ARGB, final int ARGBTarg, final int ARGBVec) {
final int nR1 = RgbVal.getR(ARGB);
final int nG1 = RgbVal.getG(ARGB);
final int nB1 = RgbVal.getB(ARGB);
final int nR2 = RgbVal.getR(ARGBTarg);
final int nG2 = RgbVal.getG(ARGBTarg);
final int nB2 = RgbVal.getB(ARGBTarg);
final int nR3 = RgbVal.getR(ARGBVec);
final int nG3 = RgbVal.getG(ARGBVec);
final int nB3 = RgbVal.getB(ARGBVec);
return ((nR1 - nR2) * nR3) + ((nG1 - nG2) * nG3) + ((nB1 - nB2) * nB3);
}
/**
* Converts from an unsigned bit field (as stored in an ARGB word to a
* signed byte value (that we can do computation on).
*
* @return the signed byte value
* @param b
* the unsigned byte value.
*/
public static byte toSignedByte(final byte b) {
return (byte) (b + Byte.MIN_VALUE);
}
/**
* Converts from a signed byte value (which we do computation on) to an
* unsigned bit field (as stored in an ARGB word). The result is returned as
* an int because the unsigned 8 bit value cannot be represented as a byte.
*
* @return the unsigned bit field
* @param b
* the signed byte value.
*/
public static int toUnsignedInt(final byte b) {
return (b - Byte.MIN_VALUE);
}
/**
* Provide a way to turn color values into strings
*
* @param ARGB
* the input color value
* @return a string describing the color
*/
public static String toString(final int ARGB) {
return "[" + new Integer(RgbVal.getR(ARGB)).toString() + "," + new Integer(RgbVal.getR(ARGB)).toString() + "," + new Integer(RgbVal.getB(ARGB)).toString() + "]";
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy