package org.lateralgm.file.iconio; import java.awt.image.BufferedImage; import java.io.IOException; import org.lateralgm.file.StreamDecoder; import org.lateralgm.file.StreamEncoder; /** * <p> * Parent class for all icon bitmaps, indexed or RGB. * </p> * <p> * Why is creation and read() not one thing? Because we might want to create the object, fill it * step by step, and then write it. * </p> * * @see com.ctreber.aclib.image.ico.AbstractBitmapIndexed * @see com.ctreber.aclib.image.ico.AbstractBitmapRGB * @author © Christian Treber, ct@ctreber.com */ public abstract class AbstractBitmap { /** Describes the bitmap. */ protected BitmapDescriptor descriptor; protected BitmapMask transparencyMask; /** * @param pDescriptor The image descriptor. */ // @PMD:REVIEWED:CallSuperInConstructor: by Chris on 06.03.06 10:27 public AbstractBitmap(final BitmapDescriptor pDescriptor) { descriptor = pDescriptor; } /** * Create an RGB image rendition of this bitmap. * * @return A BufferedImage rendition (RGB) of this bitmap. */ public abstract BufferedImage createImageRGB(); /** * Read bitmap from the decoder into class internal data structures. Implemented by specific * Bitmap classes. * * @param pDec The decoder. * @throws IOException */ abstract void read(StreamDecoder pDec) throws IOException; /** * The (manipulated height - read on). I found that a) mostly (but not always) the height reported * by the header is double the real size, and b) that the descriptor is usually correct. * * @return Returns the height. */ protected int getHeight() { if (descriptor.getWidth() == descriptor.getHeight() / 2) { return descriptor.getWidth(); } return descriptor.getHeight(); } /** * Get the bitmap width. * * @return Returns the width. */ protected int getWidth() { return descriptor.getWidth(); } protected int getColorCount() { return descriptor.getHeader().getColorCount(); } /** * Get the bitmap descriptor. * * @return Returns the descriptor. */ public BitmapDescriptor getDescriptor() { return descriptor; } /** * @param pDescriptor The descriptor to set. */ void setDescriptor(final BitmapDescriptor pDescriptor) { descriptor = pDescriptor; } /** * Simply returns the class name which reflects the bitmap type. * * @see java.lang.Object#toString() */ public String toString() { return getClass().toString(); } /** * Return bytes per scan line rounded up to the next 4 byte boundary. * * @param pWidth The image width. * @param pBPP Bits per pixel. * @return Bytes per scan line rounded up to the next 4 byte boundar. */ protected static int getBytesPerScanLine(final int pWidth, final int pBPP) { final double lBytesPerPixels = (double) pBPP / 8; int lBytesPerScanLine = (int) Math.ceil(pWidth * lBytesPerPixels); if ((lBytesPerScanLine & 0x03) != 0) { // Not on 4 byte boundary. lBytesPerScanLine = (lBytesPerScanLine & ~0x03) + 4; } return lBytesPerScanLine; } protected static int getPaddingPerScanLine(final int pWidth, final int pBPP) { final double bytesPerPixels = (double) pBPP / 8; int bytesPerScanLine = (int) Math.ceil(pWidth * bytesPerPixels); int totalBytesPerScanLine = bytesPerScanLine; if ((bytesPerScanLine & 0x03) != 0) { // Not on 4 byte boundary. totalBytesPerScanLine = (bytesPerScanLine & ~0x03) + 4; } return totalBytesPerScanLine - bytesPerScanLine; } /** * @param pDec The decoder. * @throws IOException */ protected void readMask(final StreamDecoder pDec) throws IOException { transparencyMask = new BitmapMask(descriptor); transparencyMask.read(pDec); } abstract void write(StreamEncoder out) throws IOException; protected void writeMask(StreamEncoder out) throws IOException { transparencyMask.mask.writeBitmap(out); } }