Home | History | Annotate | Download | only in textures
      1 package com.jme3.scene.plugins.blender.textures;
      2 
      3 import com.jme3.math.ColorRGBA;
      4 import com.jme3.math.FastMath;
      5 import com.jme3.texture.Image.Format;
      6 import java.nio.ByteBuffer;
      7 import java.util.logging.Level;
      8 import java.util.logging.Logger;
      9 
     10 /**
     11  * The class that stores the pixel values of a texture.
     12  *
     13  * @author Marcin Roguski (Kaelthas)
     14  */
     15 public class TexturePixel implements Cloneable {
     16 	private static final Logger	LOGGER	= Logger.getLogger(TexturePixel.class.getName());
     17 
     18 	/** The pixel data. */
     19 	public float				intensity, red, green, blue, alpha;
     20 
     21 	/**
     22 	 * Copies the values from the given pixel.
     23 	 *
     24 	 * @param pixel
     25 	 *            the pixel that we read from
     26 	 */
     27 	public void fromPixel(TexturePixel pixel) {
     28 		this.intensity = pixel.intensity;
     29 		this.red = pixel.red;
     30 		this.green = pixel.green;
     31 		this.blue = pixel.blue;
     32 		this.alpha = pixel.alpha;
     33 	}
     34 
     35 	/**
     36 	 * Copies the values from the given color.
     37 	 *
     38 	 * @param colorRGBA
     39 	 *            the color that we read from
     40 	 */
     41 	public void fromColor(ColorRGBA colorRGBA) {
     42 		this.red = colorRGBA.r;
     43 		this.green = colorRGBA.g;
     44 		this.blue = colorRGBA.b;
     45 		this.alpha = colorRGBA.a;
     46 	}
     47 
     48 	/**
     49 	 * Copies the values from the given values.
     50 	 *
     51 	 * @param a
     52 	 *            the alpha value
     53 	 * @param r
     54 	 *            the red value
     55 	 * @param g
     56 	 *            the green value
     57 	 * @param b
     58 	 *            the blue value
     59 	 */
     60 	public void fromARGB8(float a, float r, float g, float b) {
     61 		this.alpha = a;
     62 		this.red = r;
     63 		this.green = g;
     64 		this.blue = b;
     65 	}
     66 
     67 	/**
     68 	 * Copies the values from the given integer that stores the ARGB8 data.
     69 	 *
     70 	 * @param argb8
     71 	 *            the data stored in an integer
     72 	 */
     73 	public void fromARGB8(int argb8) {
     74 		byte pixelValue = (byte) ((argb8 & 0xFF000000) >> 24);
     75 		this.alpha = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
     76 		pixelValue = (byte) ((argb8 & 0xFF0000) >> 16);
     77 		this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
     78 		pixelValue = (byte) ((argb8 & 0xFF00) >> 8);
     79 		this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
     80 		pixelValue = (byte) (argb8 & 0xFF);
     81 		this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
     82 	}
     83 
     84 	/**
     85 	 * Copies the data from the given image.
     86 	 *
     87 	 * @param imageFormat
     88 	 *            the image format
     89 	 * @param data
     90 	 *            the image data
     91 	 * @param pixelIndex
     92 	 *            the index of the required pixel
     93 	 */
     94 	public void fromImage(Format imageFormat, ByteBuffer data, int pixelIndex) {
     95 		int firstByteIndex;
     96 		byte pixelValue;
     97 		switch (imageFormat) {
     98 			case ABGR8:
     99 				firstByteIndex = pixelIndex << 2;
    100 				pixelValue = data.get(firstByteIndex);
    101 				this.alpha = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    102 				pixelValue = data.get(firstByteIndex + 1);
    103 				this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    104 				pixelValue = data.get(firstByteIndex + 2);
    105 				this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    106 				pixelValue = data.get(firstByteIndex + 3);
    107 				this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    108 				break;
    109 			case RGBA8:
    110 				firstByteIndex = pixelIndex << 2;
    111 				pixelValue = data.get(firstByteIndex);
    112 				this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    113 				pixelValue = data.get(firstByteIndex + 1);
    114 				this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    115 				pixelValue = data.get(firstByteIndex + 2);
    116 				this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    117 				pixelValue = data.get(firstByteIndex + 3);
    118 				this.alpha = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    119 				break;
    120 			case BGR8:
    121 				firstByteIndex = pixelIndex * 3;
    122 				pixelValue = data.get(firstByteIndex);
    123 				this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    124 				pixelValue = data.get(firstByteIndex + 1);
    125 				this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    126 				pixelValue = data.get(firstByteIndex + 2);
    127 				this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    128 				this.alpha = 1.0f;
    129 				break;
    130 			case RGB8:
    131 				firstByteIndex = pixelIndex * 3;
    132 				pixelValue = data.get(firstByteIndex);
    133 				this.red = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    134 				pixelValue = data.get(firstByteIndex + 1);
    135 				this.green = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    136 				pixelValue = data.get(firstByteIndex + 2);
    137 				this.blue = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    138 				this.alpha = 1.0f;
    139 				break;
    140 			case Luminance8:
    141 				pixelValue = data.get(pixelIndex);
    142 				this.intensity = pixelValue >= 0 ? pixelValue / 255.0f : 1.0f - (~pixelValue) / 255.0f;
    143 				break;
    144 			default:
    145 				LOGGER.log(Level.FINEST, "Unknown type of texture: {0}. Black pixel used!", imageFormat);
    146 				this.intensity = this.blue = this.red = this.green = this.alpha = 0.0f;
    147 		}
    148 	}
    149 
    150 	/**
    151 	 * Stores RGBA values in the given array.
    152 	 *
    153 	 * @param result
    154 	 *            the array to store values
    155 	 */
    156 	public void toRGBA(float[] result) {
    157 		result[0] = this.red;
    158 		result[1] = this.green;
    159 		result[2] = this.blue;
    160 		result[3] = this.alpha;
    161 	}
    162 
    163 	/**
    164 	 * Stores the data in the given table.
    165 	 *
    166 	 * @param result
    167 	 *            the result table
    168 	 */
    169 	public void toRGBA8(byte[] result) {
    170 		result[0] = (byte) (this.red * 255.0f);
    171 		result[1] = (byte) (this.green * 255.0f);
    172 		result[2] = (byte) (this.blue * 255.0f);
    173 		result[3] = (byte) (this.alpha * 255.0f);
    174 	}
    175 
    176 	/**
    177 	 * Stores the pixel values in the integer.
    178 	 *
    179 	 * @return the integer that stores the pixel values
    180 	 */
    181 	public int toARGB8() {
    182 		int result = 0;
    183 		int b = (int) (this.alpha * 255.0f);
    184 		result |= b << 24;
    185 		b = (int) (this.red * 255.0f);
    186 		result |= b << 16;
    187 		b = (int) (this.green * 255.0f);
    188 		result |= b << 8;
    189 		b = (int) (this.blue * 255.0f);
    190 		result |= b;
    191 		return result;
    192 	}
    193 
    194 	/**
    195 	 * Merges two pixels (adds the values of each color).
    196 	 *
    197 	 * @param pixel
    198 	 *            the pixel we merge with
    199 	 */
    200 	public void merge(TexturePixel pixel) {
    201 		float oneMinusAlpha = 1 - pixel.alpha;
    202 		this.red = oneMinusAlpha * this.red + pixel.alpha * pixel.red;
    203 		this.green = oneMinusAlpha * this.green + pixel.alpha * pixel.green;
    204 		this.blue = oneMinusAlpha * this.blue + pixel.alpha * pixel.blue;
    205 		// alpha should be always 1.0f as a result
    206 	}
    207 
    208 	/**
    209 	 * This method negates the colors.
    210 	 */
    211 	public void negate() {
    212 		this.red = 1.0f - this.red;
    213 		this.green = 1.0f - this.green;
    214 		this.blue = 1.0f - this.blue;
    215 		this.alpha = 1.0f - this.alpha;
    216 	}
    217 
    218 	/**
    219 	 * This method clears the pixel values.
    220 	 */
    221 	public void clear() {
    222 		this.intensity = this.blue = this.red = this.green = this.alpha = 0.0f;
    223 	}
    224 
    225 	/**
    226 	 * This method adds the calues of the given pixel to the current pixel.
    227 	 *
    228 	 * @param pixel
    229 	 *            the pixel we add
    230 	 */
    231 	public void add(TexturePixel pixel) {
    232 		this.red += pixel.red;
    233 		this.green += pixel.green;
    234 		this.blue += pixel.blue;
    235 		this.alpha += pixel.alpha;
    236 		this.intensity += pixel.intensity;
    237 	}
    238 
    239 	/**
    240 	 * This method multiplies the values of the given pixel by the given value.
    241 	 *
    242 	 * @param value
    243 	 *            multiplication factor
    244 	 */
    245 	public void mult(float value) {
    246 		this.red *= value;
    247 		this.green *= value;
    248 		this.blue *= value;
    249 		this.alpha *= value;
    250 		this.intensity *= value;
    251 	}
    252 
    253 	/**
    254 	 * This method divides the values of the given pixel by the given value.
    255 	 * ATTENTION! Beware of the zero value. This will cause you NaN's in the
    256 	 * pixel values.
    257 	 *
    258 	 * @param value
    259 	 *            division factor
    260 	 */
    261 	public void divide(float value) {
    262 		this.red /= value;
    263 		this.green /= value;
    264 		this.blue /= value;
    265 		this.alpha /= value;
    266 		this.intensity /= value;
    267 	}
    268 
    269 	/**
    270 	 * This method clamps the pixel values to the given borders.
    271 	 *
    272 	 * @param min
    273 	 *            the minimum value
    274 	 * @param max
    275 	 *            the maximum value
    276 	 */
    277 	public void clamp(float min, float max) {
    278 		this.red = FastMath.clamp(this.red, min, max);
    279 		this.green = FastMath.clamp(this.green, min, max);
    280 		this.blue = FastMath.clamp(this.blue, min, max);
    281 		this.alpha = FastMath.clamp(this.alpha, min, max);
    282 		this.intensity = FastMath.clamp(this.intensity, min, max);
    283 	}
    284 
    285 	@Override
    286 	public Object clone() throws CloneNotSupportedException {
    287 		return super.clone();
    288 	}
    289 
    290 	@Override
    291 	public String toString() {
    292 		return "[" + red + ", " + green + ", " + blue + ", " + alpha + " {" + intensity + "}]";
    293 	}
    294 }
    295