/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.graphics.RE.software;
import static jpcsp.util.Utilities.round;
/**
* @author gid15
*
*/
public class PixelColor {
public static final int ONE = 0xFF;
public static final int ZERO = 0x00;
private static final int[][] preMultiply = new int[ONE + 1][ONE + 1];
private static final int[] preClamp = new int[ONE + ONE + 1];
static {
// Pre-computed multiplication of color components. Might be faster?
for (int c1 = 0; c1 <= ONE; c1++) {
for (int c2 = 0; c2 <= ONE; c2++) {
preMultiply[c1][c2] = (c1 * c2) / ONE;
}
}
// Pre-computed clamping of color component. Might be faster?
for (int c1 = 0; c1 < preClamp.length; c1++) {
preClamp[c1] = Math.min(c1, ONE);
}
}
public final static int getAlpha(int color) {
return color >>> 24;
}
public final static int getRed(int color) {
return color & 0xFF;
}
public final static int getGreen(int color) {
return (color >> 8) & 0xFF;
}
public final static int getBlue(int color) {
return (color >> 16) & 0xFF;
}
public final static int getColor(float[] color) {
return getColor(getColor(color[3]), getColor(color[2]), getColor(color[1]), getColor(color[0]));
}
public final static int getColor(int[] color) {
return getColor(color[3], color[2], color[1], color[0]);
}
public final static int getColorBGR(int[] color) {
return getColorBGR(color[2], color[1], color[0]);
}
public final static int getColor(float color){
return (int) (color * ONE);
}
public final static int getColor(int a, int b, int g, int r) {
return (a << 24) | (b << 16) | (g << 8) | r;
}
public final static int getColorBGR(int b, int g, int r) {
return (b << 16) | (g << 8) | r;
}
public final static int multiplyComponent(int component1, int component2) {
return preMultiply[component1][component2];
}
public final static int multiply(int color1, int a2, int b2, int g2, int r2) {
int a = multiplyComponent(getAlpha(color1), a2);
int b = multiplyComponent(getBlue(color1), b2);
int g = multiplyComponent(getGreen(color1), g2);
int r = multiplyComponent(getRed(color1), r2);
return getColor(a, b, g, r);
}
public final static int multiplyBGR(int color1, int b2, int g2, int r2) {
int b = multiplyComponent(getBlue(color1), b2);
int g = multiplyComponent(getGreen(color1), g2);
int r = multiplyComponent(getRed(color1), r2);
return getColorBGR(b, g, r);
}
public final static int multiply(int color1, int color2) {
// Handle common and simple cases first
switch (color2) {
case 0x00000000: return 0;
case 0x00FFFFFF: return color1 & color2;
case 0xFFFFFFFF: return color1;
}
switch (color1) {
case 0x00000000: return 0;
case 0x00FFFFFF: return color1 & color2;
case 0xFFFFFFFF: return color2;
}
return multiply(color1, getAlpha(color2), getBlue(color2), getGreen(color2), getRed(color2));
}
public final static int multiplyBGR(int color1, int color2) {
color1 &= 0x00FFFFFF;
color2 &= 0x00FFFFFF;
// Handle common and simple cases first
if (color1 == ZERO || color2 == ZERO) {
return ZERO;
}
if (color1 == 0x00FFFFFF) {
return color2;
}
if (color2 == 0x00FFFFFF) {
return color1;
}
return multiplyBGR(color1, getBlue(color2), getGreen(color2), getRed(color2));
}
public final static int multiplyBGR(int color, float factor) {
color &= 0x00FFFFFF;
// Handle common and simple cases first
if (color == ZERO || factor <= 0f) {
return ZERO;
}
if (factor == 1f) {
return color;
}
int b = multiplyComponent(getBlue(color), factor);
int g = multiplyComponent(getGreen(color), factor);
int r = multiplyComponent(getRed(color), factor);
return getColorBGR(b, g, r);
}
public final static int multiply(int color, float factor) {
// Handle common and simple cases first
if (color == ZERO || factor <= 0f) {
return ZERO;
}
if (factor == 1f) {
return color;
}
if (factor == .5f) {
return divideBy2(color);
}
if (factor == .25f) {
return divideBy4(color);
}
int a = multiplyComponent(getAlpha(color), factor);
int b = multiplyComponent(getBlue(color), factor);
int g = multiplyComponent(getGreen(color), factor);
int r = multiplyComponent(getRed(color), factor);
return getColor(a, b, g, r);
}
public final static int multiplyComponent(int component, float factor) {
return Math.max(ZERO, Math.min(ONE, round(component * factor)));
}
public final static int addComponent(int component1, int component2) {
// Add with clamp to ONE
return preClamp[component1 + component2];
}
public final static int add(int color1, int color2) {
// Handle common and simple cases first
if (color1 == ZERO) {
return color2;
}
if (color2 == ZERO) {
return color1;
}
if (color1 == 0xFFFFFFFF || color2 == 0xFFFFFFFF) {
return 0xFFFFFFFF;
}
int a = addComponent(getAlpha(color1), getAlpha(color2));
int b = addComponent(getBlue(color1), getBlue(color2));
int g = addComponent(getGreen(color1), getGreen(color2));
int r = addComponent(getRed(color1), getRed(color2));
return getColor(a, b, g, r);
}
public final static int addBGR(int color1, int color2) {
color1 &= 0x00FFFFFF;
color2 &= 0x00FFFFFF;
// Handle common and simple cases first
if (color1 == ZERO) {
return color2;
}
if (color2 == ZERO) {
return color1;
}
if (color1 == 0x00FFFFFF || color2 == 0x00FFFFFF) {
return 0x00FFFFFF;
}
int b = addComponent(getBlue(color1), getBlue(color2));
int g = addComponent(getGreen(color1), getGreen(color2));
int r = addComponent(getRed(color1), getRed(color2));
return getColorBGR(b, g, r);
}
public final static int substractComponent(int component1, int component2) {
// Substract with clamp to ZERO
return Math.max(component1 - component2, ZERO);
}
public final static int substract(int color1, int color2) {
int a = substractComponent(getAlpha(color1), getAlpha(color2));
int b = substractComponent(getBlue(color1), getBlue(color2));
int g = substractComponent(getGreen(color1), getGreen(color2));
int r = substractComponent(getRed(color1), getRed(color2));
return getColor(a, b, g, r);
}
public final static int substractBGR(int color1, int color2) {
int b = substractComponent(getBlue(color1), getBlue(color2));
int g = substractComponent(getGreen(color1), getGreen(color2));
int r = substractComponent(getRed(color1), getRed(color2));
return getColorBGR(b, g, r);
}
public final static int min(int color1, int color2) {
int a = Math.min(getAlpha(color1), getAlpha(color2));
int b = Math.min(getBlue(color1), getBlue(color2));
int g = Math.min(getGreen(color1), getGreen(color2));
int r = Math.min(getRed(color1), getRed(color2));
return getColor(a, b, g, r);
}
public final static int minBGR(int color1, int color2) {
int b = Math.min(getBlue(color1), getBlue(color2));
int g = Math.min(getGreen(color1), getGreen(color2));
int r = Math.min(getRed(color1), getRed(color2));
return getColorBGR(b, g, r);
}
public final static int max(int color1, int color2) {
int a = Math.max(getAlpha(color1), getAlpha(color2));
int b = Math.max(getBlue(color1), getBlue(color2));
int g = Math.max(getGreen(color1), getGreen(color2));
int r = Math.max(getRed(color1), getRed(color2));
return getColor(a, b, g, r);
}
public final static int maxBGR(int color1, int color2) {
int b = Math.max(getBlue(color1), getBlue(color2));
int g = Math.max(getGreen(color1), getGreen(color2));
int r = Math.max(getRed(color1), getRed(color2));
return getColorBGR(b, g, r);
}
private final static int absComponent(int component1, int component2) {
// Be careful to return a result value between 0x00 and 0xFF
if (component1 >= component2) {
return component1 - component2;
}
return component2 - component1;
}
public final static int abs(int color1, int color2) {
int a = absComponent(getAlpha(color1), getAlpha(color2));
int b = absComponent(getBlue(color1), getBlue(color2));
int g = absComponent(getGreen(color1), getGreen(color2));
int r = absComponent(getRed(color1), getRed(color2));
return getColor(a, b, g, r);
}
public final static int absBGR(int color1, int color2) {
int b = absComponent(getBlue(color1), getBlue(color2));
int g = absComponent(getGreen(color1), getGreen(color2));
int r = absComponent(getRed(color1), getRed(color2));
return getColorBGR(b, g, r);
}
public final static int combineComponent(int component1, int component2, int factor) {
return ((ONE - factor) * component1 + factor * component2) / ONE;
}
public final static int setAlpha(int color, int alpha) {
return (color & 0x00FFFFFF) | (alpha << 24);
}
public final static int setBGR(int color, int bgr) {
return (color & 0xFF000000) | bgr;
}
public final static int doubleColor(int color) {
return addBGR(color, color) | (color & 0xFF000000);
}
public final static int doubleComponent(int component) {
return addComponent(component, component);
}
public final static int divideBy2(int color) {
return (color >>> 1) & 0x7F7F7F7F;
}
public final static int divideBy4(int color) {
return (color >>> 2) & 0x3F3F3F3F;
}
}