/** * */ 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; } }