blob: 37c0122cc4f73b578f046a7e2671a36951816b32 [file] [log] [blame]
package com.jme3.scene.plugins.blender.textures;
import com.jme3.math.ColorRGBA;
import com.jme3.math.FastMath;
import com.jme3.texture.Image.Format;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The class that stores the pixel values of a texture.
*
* @author Marcin Roguski (Kaelthas)
*/
public class TexturePixel implements Cloneable {
private static final Logger LOGGER = Logger.getLogger(TexturePixel.class.getName());
/** The pixel data. */
public float intensity, red, green, blue, alpha;
/**
* Copies the values from the given pixel.
*
* @param pixel
* the pixel that we read from
*/
public void fromPixel(TexturePixel pixel) {
this.intensity = pixel.intensity;
this.red = pixel.red;
this.green = pixel.green;
this.blue = pixel.blue;
this.alpha = pixel.alpha;
}
/**
* Copies the values from the given color.
*
* @param colorRGBA
* the color that we read from
*/
public void fromColor(ColorRGBA colorRGBA) {
this.red = colorRGBA.r;
this.green = colorRGBA.g;
this.blue = colorRGBA.b;
this.alpha = colorRGBA.a;
}
/**
* Copies the values from the given values.
*
* @param a
* the alpha value
* @param r
* the red value
* @param g
* the green value
* @param b
* the blue value
*/
public void fromARGB8(float a, float r, float g, float b) {
this.alpha = a;
this.red = r;
this.green = g;
this.blue = b;
}
/**
* Copies the values from the given integer that stores the ARGB8 data.
*
* @param argb8
* the data stored in an integer
*/
public void fromARGB8(int argb8) {
byte pixelValue = (byte) ((argb8 & 0xFF000000) >> 24);
this.alpha = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = (byte) ((argb8 & 0xFF0000) >> 16);
this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = (byte) ((argb8 & 0xFF00) >> 8);
this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = (byte) (argb8 & 0xFF);
this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
}
/**
* Copies the data from the given image.
*
* @param imageFormat
* the image format
* @param data
* the image data
* @param pixelIndex
* the index of the required pixel
*/
public void fromImage(Format imageFormat, ByteBuffer data, int pixelIndex) {
int firstByteIndex;
byte pixelValue;
switch (imageFormat) {
case ABGR8:
firstByteIndex = pixelIndex << 2;
pixelValue = data.get(firstByteIndex);
this.alpha = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = data.get(firstByteIndex + 1);
this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = data.get(firstByteIndex + 2);
this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = data.get(firstByteIndex + 3);
this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
break;
case RGBA8:
firstByteIndex = pixelIndex << 2;
pixelValue = data.get(firstByteIndex);
this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = data.get(firstByteIndex + 1);
this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = data.get(firstByteIndex + 2);
this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = data.get(firstByteIndex + 3);
this.alpha = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
break;
case BGR8:
firstByteIndex = pixelIndex * 3;
pixelValue = data.get(firstByteIndex);
this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = data.get(firstByteIndex + 1);
this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = data.get(firstByteIndex + 2);
this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
this.alpha = 1.0f;
break;
case RGB8:
firstByteIndex = pixelIndex * 3;
pixelValue = data.get(firstByteIndex);
this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = data.get(firstByteIndex + 1);
this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
pixelValue = data.get(firstByteIndex + 2);
this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
this.alpha = 1.0f;
break;
case Luminance8:
pixelValue = data.get(pixelIndex);
this.intensity = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
break;
default:
LOGGER.log(Level.FINEST, "Unknown type of texture: {0}. Black pixel used!", imageFormat);
this.intensity = this.blue = this.red = this.green = this.alpha = 0.0f;
}
}
/**
* Stores RGBA values in the given array.
*
* @param result
* the array to store values
*/
public void toRGBA(float[] result) {
result[0] = this.red;
result[1] = this.green;
result[2] = this.blue;
result[3] = this.alpha;
}
/**
* Stores the data in the given table.
*
* @param result
* the result table
*/
public void toRGBA8(byte[] result) {
result[0] = (byte) (this.red * 255.0f);
result[1] = (byte) (this.green * 255.0f);
result[2] = (byte) (this.blue * 255.0f);
result[3] = (byte) (this.alpha * 255.0f);
}
/**
* Stores the pixel values in the integer.
*
* @return the integer that stores the pixel values
*/
public int toARGB8() {
int result = 0;
int b = (int) (this.alpha * 255.0f);
result |= b << 24;
b = (int) (this.red * 255.0f);
result |= b << 16;
b = (int) (this.green * 255.0f);
result |= b << 8;
b = (int) (this.blue * 255.0f);
result |= b;
return result;
}
/**
* Merges two pixels (adds the values of each color).
*
* @param pixel
* the pixel we merge with
*/
public void merge(TexturePixel pixel) {
float oneMinusAlpha = 1 - pixel.alpha;
this.red = oneMinusAlpha * this.red + pixel.alpha * pixel.red;
this.green = oneMinusAlpha * this.green + pixel.alpha * pixel.green;
this.blue = oneMinusAlpha * this.blue + pixel.alpha * pixel.blue;
// alpha should be always 1.0f as a result
}
/**
* This method negates the colors.
*/
public void negate() {
this.red = 1.0f - this.red;
this.green = 1.0f - this.green;
this.blue = 1.0f - this.blue;
this.alpha = 1.0f - this.alpha;
}
/**
* This method clears the pixel values.
*/
public void clear() {
this.intensity = this.blue = this.red = this.green = this.alpha = 0.0f;
}
/**
* This method adds the calues of the given pixel to the current pixel.
*
* @param pixel
* the pixel we add
*/
public void add(TexturePixel pixel) {
this.red += pixel.red;
this.green += pixel.green;
this.blue += pixel.blue;
this.alpha += pixel.alpha;
this.intensity += pixel.intensity;
}
/**
* This method multiplies the values of the given pixel by the given value.
*
* @param value
* multiplication factor
*/
public void mult(float value) {
this.red *= value;
this.green *= value;
this.blue *= value;
this.alpha *= value;
this.intensity *= value;
}
/**
* This method divides the values of the given pixel by the given value.
* ATTENTION! Beware of the zero value. This will cause you NaN's in the
* pixel values.
*
* @param value
* division factor
*/
public void divide(float value) {
this.red /= value;
this.green /= value;
this.blue /= value;
this.alpha /= value;
this.intensity /= value;
}
/**
* This method clamps the pixel values to the given borders.
*
* @param min
* the minimum value
* @param max
* the maximum value
*/
public void clamp(float min, float max) {
this.red = FastMath.clamp(this.red, min, max);
this.green = FastMath.clamp(this.green, min, max);
this.blue = FastMath.clamp(this.blue, min, max);
this.alpha = FastMath.clamp(this.alpha, min, max);
this.intensity = FastMath.clamp(this.intensity, min, max);
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "[" + red + ", " + green + ", " + blue + ", " + alpha + " {" + intensity + "}]";
}
}