Sketcher2 source code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
8.0 KiB

/**
*
*/
package com.jotuntech.sketcher.common;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
import java.io.IOException;
import java.io.Serializable;
/**
* @author Thor Harald Johansen
*
*/
public class BitmapTile implements Serializable {
static final long serialVersionUID = 3265680755614445636L;
public final static int SIZE = 32;
public final static int SIZE_2 = 5;
public final static int SIZE_MASK = 31;
private BufferedImage image;
private int[] pixels;
private byte[] encoded;
/**
* Creates a bitmap tile
*/
public BitmapTile() {
image = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
}
public BitmapTile(BufferedImage imagex) {
image = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
image.getGraphics().drawImage(imagex, 0, 0, null);
}
public BitmapTile(BitmapTile tile) {
image = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
tile.image.copyData(image.getRaster());
pixels = ((DataBufferInt) image.getRaster().getDataBuffer()).getData();
}
/*
public void blendPixel(int x, int y, int sourceColor, int sourceAlpha65025) {
// Offset in destination pixel array
int offset = (y << SIZE_2) + x;
// Fetch destionation pixel
int destinationPixel = pixels[offset];
// Get destination's alpha
int destinationAlpha = Pixels.getChannel0(destinationPixel);
// Divide source alpha
int sourceAlpha = sourceAlpha65025 / 255;
if(sourceAlpha > 0) {
if(sourceAlpha == 255) {
pixels[offset] = Pixels.pack(255, sourceColor);
} else {
if(destinationAlpha == 0) {
int dither = sourceAlpha < 255 && sourceAlpha65025 % 255 > Pixels.random() ? 1 : 0;
pixels[offset] = Pixels.pack(sourceAlpha + dither, sourceColor);
} else {
// Destination alpha result
int destinationAlphaResult, destinationAlphaResult65025;
if(destinationAlpha == 255) {
destinationAlphaResult = 255;
destinationAlphaResult65025 = 65025;
} else {
destinationAlphaResult65025 = Math.min(65205, destinationAlpha * 255 + sourceAlpha65025);
destinationAlphaResult = destinationAlphaResult65025 / 255;
destinationAlphaResult += destinationAlphaResult < 255 && destinationAlphaResult65025 % 255 > Pixels.random() ? 1 : 0;
}
if(sourceColor == Pixels.stripChannel0(destinationPixel)) {
pixels[offset] = Pixels.pack(destinationAlphaResult, sourceColor);
} else {
// Destination colors
int destinationRed = Pixels.getChannel1(destinationPixel);
int destinationGreen = Pixels.getChannel2(destinationPixel);
int destinationBlue = Pixels.getChannel3(destinationPixel);
// Source colors
int sourceRed = Pixels.getChannel1(sourceColor);
int sourceGreen = Pixels.getChannel2(sourceColor);
int sourceBlue = Pixels.getChannel3(sourceColor);
if(destinationAlphaResult == 255) {
int outputRed = destinationRed + ((sourceRed - destinationRed) * sourceAlpha65025) / 65025;
int outputGreen = destinationGreen + ((sourceGreen - destinationGreen) * sourceAlpha65025) / 65025;
int outputBlue = destinationBlue + ((sourceBlue - destinationBlue) * sourceAlpha65025) / 65025;
// Blend, and store to destination
pixels[offset] = Pixels.pack(255,
outputRed,
outputGreen,
outputBlue);
} else {
// Blend, and store to destination
pixels[offset] = Pixels.pack(destinationAlphaResult,
destinationRed + ((sourceRed - destinationRed) * sourceAlpha65025) / destinationAlphaResult65025,
destinationGreen + ((sourceGreen - destinationGreen) * sourceAlpha65025) / destinationAlphaResult65025,
destinationBlue + ((sourceBlue - destinationBlue) * sourceAlpha65025) / destinationAlphaResult65025);
}
}
}
}
}
}
*/
public void blendPixel(int x, int y, int sourceColor, int sourceAlpha65025, int maxAlpha) {
// Offset in destination pixel array
int offset = (y << SIZE_2) + x;
// Fetch destionation pixel
int destinationPixel = pixels[offset];
// Get destination's alpha
int destinationAlpha = Pixels.getChannel0(destinationPixel);
// Divide source alpha
int sourceAlpha = sourceAlpha65025 / 255;
if(sourceAlpha > 0) {
if(sourceAlpha == 255) {
pixels[offset] = Pixels.pack(255, sourceColor);
} else {
if(destinationAlpha == 0) {
int dither = sourceAlpha65025 % 255 > Pixels.random() ? 1 : 0;
pixels[offset] = Pixels.pack((sourceAlpha & 0xFFFFFFFE) | dither, sourceColor);
} else {
// Destination alpha result
int destinationAlphaResult, destinationAlphaResult65025;
if(destinationAlpha == 255) {
destinationAlphaResult = 255;
destinationAlphaResult65025 = 65025;
} else {
// Destination multiplied by inverted source alpha.
int invSrcAlphaMulDest65025 = (destinationAlpha * (65025 - sourceAlpha65025)) / 255;
// Set destination alpha result
destinationAlphaResult65025 = Math.max(destinationAlpha * 255, Math.min(maxAlpha * 255, sourceAlpha65025 + invSrcAlphaMulDest65025));
destinationAlphaResult = destinationAlphaResult65025 / 255;
destinationAlphaResult = (destinationAlphaResult & 0xFFFFFFFE) | (destinationAlphaResult65025 % 255 > Pixels.random() ? 1 : 0);
}
if(sourceColor == Pixels.stripChannel0(destinationPixel)) {
if(destinationAlphaResult == 255) {
pixels[offset] = Pixels.pack(255, sourceColor);
} else {
pixels[offset] = Pixels.pack(destinationAlphaResult, sourceColor);
}
} else {
// Destination colors
int destinationRed = Pixels.getChannel1(destinationPixel);
int destinationGreen = Pixels.getChannel2(destinationPixel);
int destinationBlue = Pixels.getChannel3(destinationPixel);
// Source colors
int sourceRed = Pixels.getChannel1(sourceColor);
int sourceGreen = Pixels.getChannel2(sourceColor);
int sourceBlue = Pixels.getChannel3(sourceColor);
if(destinationAlphaResult == 255) {
int outputRed = destinationRed + ((sourceRed - destinationRed) * sourceAlpha65025) / 65025;
int outputGreen = destinationGreen + ((sourceGreen - destinationGreen) * sourceAlpha65025) / 65025;
int outputBlue = destinationBlue + ((sourceBlue - destinationBlue) * sourceAlpha65025) / 65025;
// Blend, and store to destination
pixels[offset] = Pixels.pack(255,
outputRed,
outputGreen,
outputBlue);
} else {
// Blend, and store to destination
pixels[offset] = Pixels.pack(destinationAlphaResult,
destinationRed + ((sourceRed - destinationRed) * sourceAlpha65025) / destinationAlphaResult65025,
destinationGreen + ((sourceGreen - destinationGreen) * sourceAlpha65025) / destinationAlphaResult65025,
destinationBlue + ((sourceBlue - destinationBlue) * sourceAlpha65025) / destinationAlphaResult65025);
}
}
}
}
}
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException {
out.writeObject(pixels);
}
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
this.image = new BufferedImage(SIZE, SIZE, BufferedImage.TYPE_INT_ARGB);
this.pixels = ((DataBufferInt)image.getRaster().getDataBuffer()).getData();
int[] pixels = (int[])in.readObject();
for(int i = 0; i < pixels.length; i++) {
this.pixels[i] = pixels[i];
}
}
public void setImage(BufferedImage image) {
this.image = image;
}
public BufferedImage getImage() {
return image;
}
public void setPixels(int[] pixels) {
this.pixels = pixels;
}
public int[] getPixels() {
return pixels;
}
public void setEncoded(byte[] encoded) {
this.encoded = encoded;
}
public byte[] getEncoded() {
return encoded;
}
}