package ij.process; import java.awt.*; /** This class does bit blitting of byte images. */ public class ByteBlitter implements Blitter { private ByteProcessor ip; private int width, height; private byte[] pixels; private int transparent = 255; /** Constructs a ByteBlitter from a ByteProcessor. */ public ByteBlitter(ByteProcessor ip) { this.ip = ip; width = ip.getWidth(); height = ip.getHeight(); pixels = (byte[])ip.getPixels(); } public void setTransparentColor(Color c) { transparent = ip.getBestIndex(c); //ij.IJ.write(c+" "+transparent); } /** Copies the byte image in 'ip' to (x,y) using the specified mode. */ public void copyBits(ImageProcessor ip, int xloc, int yloc, int mode) { Rectangle r1, r2; int srcIndex, dstIndex; int xSrcBase, ySrcBase; byte[] srcPixels; int srcWidth = ip.getWidth(); int srcHeight = ip.getHeight(); r1 = new Rectangle(srcWidth, srcHeight); r1.setLocation(xloc, yloc); r2 = new Rectangle(width, height); if (!r1.intersects(r2)) return; if (ip instanceof ColorProcessor) { int[] pixels32 = (int[])ip.getPixels(); int size = ip.getWidth()*ip.getHeight(); srcPixels = new byte[size]; if (this.ip.isInvertedLut()) for (int i=0; i<size; i++) srcPixels[i] = (byte)(255-pixels32[i]&255); else for (int i=0; i<size; i++) srcPixels[i] = (byte)(pixels32[i]&255); } else { ip = ip.convertToByte(true); srcPixels = (byte [])ip.getPixels(); } r1 = r1.intersection(r2); xSrcBase = (xloc<0)?-xloc:0; ySrcBase = (yloc<0)?-yloc:0; int src, dst; for (int y=r1.y; y<(r1.y+r1.height); y++) { srcIndex = (y-yloc)*srcWidth + (r1.x-xloc); dstIndex = y * width + r1.x; switch (mode) { case COPY: for (int i=r1.width; --i>=0;) pixels[dstIndex++] = srcPixels[srcIndex++]; break; case COPY_INVERTED: for (int i=r1.width; --i>=0;) pixels[dstIndex++] = (byte)(255-srcPixels[srcIndex++]&255); break; case COPY_TRANSPARENT: for (int i=r1.width; --i>=0;) { src = srcPixels[srcIndex++]&255; if (src==transparent) dst = pixels[dstIndex]; else dst = src; pixels[dstIndex++] = (byte)dst; } break; case COPY_ZERO_TRANSPARENT: for (int i=r1.width; --i>=0;) { src = srcPixels[srcIndex++]&255; if (src==0) dst = pixels[dstIndex]; else dst = src; pixels[dstIndex++] = (byte)dst; } break; case ADD: for (int i=r1.width; --i>=0;) { dst = (srcPixels[srcIndex++]&255)+(pixels[dstIndex]&255); if (dst>255) dst = 255; pixels[dstIndex++] = (byte)dst; } break; case AVERAGE: for (int i=r1.width; --i>=0;) { dst = ((srcPixels[srcIndex++]&255)+(pixels[dstIndex]&255))/2; pixels[dstIndex++] = (byte)dst; } break; case SUBTRACT: for (int i=r1.width; --i>=0;) { dst = (pixels[dstIndex]&255)-(srcPixels[srcIndex++]&255); if (dst<0) dst = 0; pixels[dstIndex++] = (byte)dst; } break; case DIFFERENCE: for (int i=r1.width; --i>=0;) { dst = (pixels[dstIndex]&255)-(srcPixels[srcIndex++]&255); if (dst<0) dst = -dst; pixels[dstIndex++] = (byte)dst; } break; case MULTIPLY: for (int i=r1.width; --i>=0;) { dst = (srcPixels[srcIndex++]&255)*(pixels[dstIndex]&255); if (dst>255) dst = 255; pixels[dstIndex++] = (byte)dst; } break; case DIVIDE: for (int i=r1.width; --i>=0;) { src = srcPixels[srcIndex++]&255; if (src==0) dst = 255; else dst = (pixels[dstIndex]&255)/src; pixels[dstIndex++] = (byte)dst; } break; case AND: for (int i=r1.width; --i>=0;) { dst = srcPixels[srcIndex++]&pixels[dstIndex]; pixels[dstIndex++] = (byte)dst; } break; case OR: for (int i=r1.width; --i>=0;) { dst = srcPixels[srcIndex++]|pixels[dstIndex]; pixels[dstIndex++] = (byte)dst; } break; case XOR: for (int i=r1.width; --i>=0;) { dst = srcPixels[srcIndex++]^pixels[dstIndex]; pixels[dstIndex++] = (byte)dst; } break; case MIN: for (int i=r1.width; --i>=0;) { src = srcPixels[srcIndex++]&255; dst = pixels[dstIndex]&255; if (src<dst) dst = src; pixels[dstIndex++] = (byte)dst; } break; case MAX: for (int i=r1.width; --i>=0;) { src = srcPixels[srcIndex++]&255; dst = pixels[dstIndex]&255; if (src>dst) dst = src; pixels[dstIndex++] = (byte)dst; } break; } if (y%20==0) ip.showProgress((double)(y-r1.y)/r1.height); } ip.hideProgress(); } }