package ch.werner_randelshofer.gui.image;/*Copyright (C) 1999 Werner Randelshoferwerner.randelshofer@mythen.chhttp://www.mythen.ch/w.randelshofer/    Permission to use this release of Bitmap is herebygranted without fee provided that the complete copyrightnotice and this permission notice appear in all copiesand in supporting documentation.*/import java.awt.image.ColorModel;import java.awt.image.IndexColorModel;import java.awt.image.DirectColorModel;import java.util.Hashtable;/** * A Bitmap is comprised of a ColorModel and an accessible byte array of * image data. * <p> * The image data is expressed in several layers of rectangular regions * called bit-planes. To determine the bits that form a single pixel one * must combine all data-bits at the same x,y position in each bit-plane. * This is known as a "planar" storage layout as it was used on Commodore * Amiga Computers. * <p> * The bit-planes can be stored contiguously or can be interleaved at each * scanline of the image. * <p> * <p> * Fig 1. A sample image: * <p><pre>		 * .+++..@...@.+..###...+++.     This sample uses 4 colors: * +...+.@@.@@.+.#.....+...+     . = color 0 (all bits clear) * +++++:@.@.@.+.#..##.+++++     + = color 1 (bit 0 set, bit 1 clear) * +...+.@...@.+.#...#.+...+     @ = color 2 (bit 0 clear, bit 1 set) * +...+.@...@.+..####.+...+     # = color 3 (all bits set)	 * </pre><p> * Fig 2. Contiguous bit-plane storage layout. * <p><pre> * 01110000 00001001 11000111 0.......     This is the first bit-plane. * 10001000 00001010 00001000 1.......     Each number represents a bit * 11111000 00001010 01101111 1.......     in the storage layout. Eight * 10001000 00001010 00101000 1.......     bits are grouped into one byte. * 10001000 00001001 11101000 1.......     Dots indicate unused bits. * <p> * 00000010 00100001 11000000 0.......     This is the second bit-plane. * 00000011 01100010 00000000 0....... * 00000010 10100010 01100000 0....... * 00000010 00100010 00100000 0....... * 00000010 00100001 11100000 0....... * <p></pre>		        * Fig 3. Interleaved bit-plane storage layout. * <p><pre>        * 01110000 00001001 11000111 0.......     This is the first bit-plane. * 00000010 00100001 11000000 0.......     This is the second bit-plane. * <p> * 10001000 00001010 00001000 1.......     The bit-planes are interleaved * 00000011 01100010 00000000 0.......     at every scanline of the image. * <p> * 11111000 00001010 01101111 1.......	 * 00000010 10100010 01100000 0....... * <p> * 10001000 00001010 00101000 1.......	 * 00000010 00100010 00100000 0....... * <p> * 10001000 00001001 11101000 1.......	 * 00000010 00100001 11100000 0....... * <p></pre>		        * For more details refer to "Amiga ROM Kernel Reference Manual: Libraries, * Addison Wesley"		 * <p> * <b>Responsibility</b> * <p> * Gives clients direct access to the image data of the bitmap. * Knows how to convert the bitmap into chunky image data according * to the current color model. * Supports indexed color model, direct color model, 6 and 8 bit HAM color model. *		 * @author	Werner Randelshofer, Staldenmattweg 2, CH-6405 Immensee, Switzerland * @version	1999-01-03	Better quality for HAM modes. 	<br>history 	1998-05-19	Through rework of the class. * <br>history	1998-04-16	Planar to chunky conversion caused vertical stripes * 						when the pixel width was not a multiple of 8. * <br>history	1998-02-16	HAM6 + HAM8 were transparent under JDK1.1. * <br>history	1997-10-12	Style guide used for code representation. * <br>history	1997-14-09	First release. * <br>history	1997-06-09	Created. */public class Bitmapextends java.lang.Objectimplements Cloneable	{	/**	The bitmap data array. */	private byte[] bitmap_;		/** The width of the image. */	private int width_;		/** The height of the image. */	private int height_;		/** The number of bits that form a single pixel. */	private int depth_;		/** BitmapStride is the number of data array elements	between two bits of the same image pixel. */	private int bitplaneStride_;	/** ScanlineStride is the number of data array elements	between a given	pixel and the pixel in the same column of	the next scanline. */	private int scanlineStride_;		/** This ColorModel is used for the next conversion from planar	bitmap data into chunky pixel data.	*/	private ColorModel colorModel_;		/** This ColorModel was used at the previous conversion from	planar bitmap into chunky pixel data.	*/	private ColorModel lastPixelColorModel_;		/** Indicates availability of chunky pixel data. */	private int pixelType_;	/** Tag for byte pixel data. */	public final static int BYTE_PIXEL = 1;	/** Tag for integer pixel data. */	public final static int INT_PIXEL = 2;		/** Tag indicating that no pixel data is available. */	public final static int NO_PIXEL = 0;	/** Output array for byte pixel data. */	private byte[] bytePixels_;		/** Output array for integer pixel data. */	private int[] intPixels_;		/**	Construct an interleaved bitmap with the specified size,	depth and color model.	BitplaneStride and ScanlineStride are rounded up to the next	even number of bytes.	<p>	Pre condition:		-	<p>					Post condition:		Interleaved bitmap constructed.	<p>	Obligation:		-	@param	width	Width in pixels.	@param	height	Height in pixels.	@param	depth	Number of bits per pixel.	@param	colorModel	Color model to be used for conversions from/to chunky pixels.	*/	public Bitmap(int width, int height, int depth, ColorModel colorModel)		{		this(width, height, depth, colorModel, true);		}	/**	Construct a bitmap with the specified size, depth and color model	and with optional interleave.	BitplaneStride and ScanlineStride are rounded up to the next	even number of bytes.	<p>	Pre condition:		-	<p>					Post condition:		Bitmap constructed.	<p>	Obligation:		-	@param	width	Width in pixels.	@param	height	Height in pixels.	@param	depth	Number of bits per pixel.	@param	colorModel	Color model to be used for conversions from/to chunky pixels.	@param	isInterleaved	Indicator for contiguous or interleaved bit-planes.	*/	public Bitmap(int width, int height, int depth, ColorModel colorModel, boolean isInterleaved)		{		width_ = width;		height_ = height;		depth_ = depth;		colorModel_ = colorModel;		if (isInterleaved)			{			bitplaneStride_ = (width_ + 15) / 16 * 2;			scanlineStride_ = bitplaneStride_ * depth_;			bitmap_ = new byte[scanlineStride_ * height_];			}		else			{			scanlineStride_ = (width_ + 15) / 16 * 2;			bitplaneStride_ = scanlineStride_ * depth_;			bitmap_ = new byte[bitplaneStride_ * height_];			}		pixelType_ = NO_PIXEL;		}	/**	Construct a bitmap with the specified size, depth, color model and	interleave.	<p>	Pre condition:		ScanlineStride must be a multiple of BitplaneStride or vice versa.	<p>					Post condition:		Bitmap constructed.	<p>	Obligation:		-	@param	width	Width in pixels.	@param	height	Height in pixels.	@param	depth	Number of bits per pixel.	@param	colorModel	Color model to be used for conversions from/to chunky pixels.	@param	bitStride	Number of data array elements between two bits of the same image pixel.	@param	scanlineStride	Number of data array elements between a given pixel and the pixel in the same column of	the next scanline.	*/	public Bitmap(int width, int height, int depth, ColorModel colorModel, int bitStride, int scanlineStride)		{		width_ = width;		height_ = height;		depth_ = depth;		colorModel_ = colorModel;		bitplaneStride_ = bitStride;		scanlineStride_ = scanlineStride;		if (bitplaneStride_ < scanlineStride_)			{			bitmap_ = new byte[scanlineStride_ * height_];			}		else			{			bitmap_ = new byte[bitplaneStride_ * height_];			}		pixelType_ = NO_PIXEL;		}		/**	Returns the width of the image.	<p>	Pre condition: -					<p>	Post condition: -	<p>	Obligation: -	@return	The width in pixels.	*/	public int getWidth()		{		return width_;		}			/**	Returns the height of the image.	<p>	Pre condition: -					<p>	Post condition: -	<p>	Obligation: -	@return	The height in pixels.	*/	public int getHeight()		{		return height_;		}			/**	Returns the depth of the image.	<p>		The depth indicates how many bits are used to form a single pixel.	<p>		Pre condition: -					<p>	Post condition: -	<p>	Obligation: -			@return	The number of bitplanes used to form a single pixel.	*/	public int getDepth()		{		return depth_;		}	/**	Returns the numer of bytes you must add to a given address	in the bitmap to advance to the next scanline of the image.	<p>		Pre condition: -					<p>	Post condition: -	<p>	Obligation: -			@return	The scansize.	*/	public int getScanlineStride()		{		return scanlineStride_;		}					/**	Returns the number of bytes that you must add to a bitmap address	to advance to the next bit of a scanline.	<p>	Pre condition: -					<p>	Post condition: -	<p>	Obligation: -		@return	The interleave of the bitmap.	*/	public int getBitplaneStride()		{		return bitplaneStride_;		}	/**	Replaces the color model used for conversions from/to chunky pixels.	<p>	Pre condition: The new color model must correspond with the depth of the bitmap.	<p>					Post condition: Color model changed.	<p>	Obligation: -				@param	The new color model.	*/	public void setColorModel(ColorModel colorModel)		{		colorModel_ = colorModel;		}		/**	Returns the current color model of the bitmap.	<p>		Pre condition: -					<p>	Post condition: -	<p>	Obligation: -				@return	The color model.	*/	public ColorModel getColorModel()		{		return colorModel_;		}	/**	Gives you direct access to the bitmap data array.	<p>	Pre condition: -.	<p>					Post condition: -	<p>	Obligation: The bitmap data array remains property		of the Bitmap and will be used at the next		conversion to chunky. You can access it as you		like (even during conversion) since this class		does never change the contents of the bitmap.				@return	A reference to the bitmap data.	*/	public byte[] getBitmap()		{		return bitmap_;		}	/**	Returns a reference to the byte pixel data that has been	generated by a previous call to #converToChunky.	<p>	Pre condition: -	<p>					Post condition: -	<p>	Obligation: You may modify the contents of the array		as you like to get some nice effects for the		next call to #convertToChunky. Note whovewer that		#convertToChunky will not reuse this array when		the colorModel has been changed to a color format		that requires pixels in integer format.			@return	byte array or NULL when no byte pixels have been		generated by #convertToChunky.	*/	public byte[] getBytePixels()		{		if (pixelType_ == BYTE_PIXEL)			{ return bytePixels_; }		else			{ return null; }		}	/**	Returns a reference to the integer pixel data that has been	generated by a previous call to #converToChunky.	<p>	Pre condition: -	<p>					Post condition: -	<p>	Obligation: You may modify the contents of the array		as you like to get some nice effects for the		next call to #convertToChunky. Note however that		#convertToChunky will not reuse this array when		the colorModel has been changed to a color format		that requires pixels in byte format.			@return	byte array or NULL when no int pixels have been		generated by #convertToChunky.	*/	public int[] getIntPixels()		{		if (pixelType_ == INT_PIXEL)			{ return intPixels_; }		else			{ return null; }		}	/**	Returns the available type of pixel data.	<p>	Pre condition: -	<p>					Post condition: -	<p>	Obligation: -				@return	A constant that specifies the current type of pixel data.	*/	public int getPixelType()		{		return pixelType_;		}	/**	Creates a clone.	<p>		Pre condition: -	<p>					Post condition: Clone created.		@return	A clone.	*/	public Object clone() 		{		try			{			Bitmap theClone = (Bitmap)super.clone();			theClone.bitmap_ = (byte[])bitmap_.clone();			if (getPixelType() == BYTE_PIXEL)				{ theClone.bytePixels_ = (byte[])bytePixels_.clone(); }			if (getPixelType() == INT_PIXEL)				{ theClone.intPixels_ = (int[])intPixels_.clone(); }			return theClone;			}		catch (CloneNotSupportedException e)			{			throw new InternalError(e.toString());			}		}		/**	Converts the planar image data into chunky pixel data.	<p>	This method will either generate byte pixel data or integer	pixel data (depending on the color model).	<p>	The pixel array that resulted to a prior call to this	method will be reused when the image dimension and the color	model allows for it.	<p>	Pre condition: -	<p>	Post condition: Chunky pixels generated.	<p>	Obligation: -		@return The type of generated pixel data.	*/	public int convertToChunky()		{		return convertToChunky(0,0,getHeight(),getWidth());		}			/**	Converts the indicated area of the bitmap data into	pixel data.	<p>	This method will either generate byte pixel data or integer	pixel data (depending on the color model).	<p>	Note that the size of the generated pixel data always corresponds	to the size of the complete image. You do only specify a subset	of the image to be <i>converted</i> not a subset to be extracted.	Note also that the pixel data that resulted from prior calls to	this method will be reused when the generated pixel array was	of the same size and type.	<p>	Pre condition: -	<p>	Post condition: The indicated part of the bitmap has been		converted into chunky pixels.	<p>	Obligation: -		@return The type of generated pixel data.	*/	public int convertToChunky(int top,int left,int bottom,int right)		{		pixelType_ = NO_PIXEL;		if (top < 0)			{ top = 0; }		if (left < 0)			{ left = 0; }		if (bottom > getHeight() - 1)			{ bottom = getHeight() - 1; }		if (right > getWidth() - 1)			{ right = getWidth() - 1; }				if (colorModel_ instanceof HAMColorModel)			{			if (intPixels_ == null || intPixels_.length != getWidth()*getHeight())				{				bytePixels_ = null;				intPixels_ = new int[getWidth()*getHeight()];				}			if (((HAMColorModel)colorModel_).getHAMType() == HAMColorModel.HAM6)				{ planesToHAM6Pixels(top,left,bottom,right); }			else if (((HAMColorModel)colorModel_).getHAMType() == HAMColorModel.HAM8)				{ planesToHAM8Pixels(top,left,bottom,right); }			else				{				throw new InternalError("unsupported ham model:" + colorModel_);				}			pixelType_ = INT_PIXEL;			}		else			{			if (colorModel_ instanceof IndexColorModel)				{				if (bytePixels_ == null || bytePixels_.length != getWidth()*getHeight())					{					intPixels_ = null;					bytePixels_ = new byte[getWidth()*getHeight()];					}				planesToIndexPixels(top,left,bottom,right);				pixelType_ = BYTE_PIXEL;				}			else if (colorModel_ instanceof DirectColorModel)				{				if (intPixels_ == null || intPixels_.length != getWidth()*getHeight())					{					bytePixels_ = null;					intPixels_ = new int[getWidth()*getHeight()];					}				planesToDirectPixels(top,left,bottom,right);				pixelType_ = INT_PIXEL;				}			else				{				throw new InternalError("unsupported color model:" + colorModel_);				}			}					return pixelType_;		}		/**	Lets the bitmap "forget" the pixel data.		<p>	Pre condition: -	<p>	Post condition: The bitmap has given up all its		references to the pixel data.	<p>	Obligation: The pixel data will not be reused at the		next call to #convertToChunky.	*/	public void flushPixels()		{		pixelType_ = NO_PIXEL;		intPixels_ = null;		bytePixels_ = null;		}			/**	Converts the planar image data into chunky pixels.	After successful completion the chunky pixels can by used	in conjunction with the IndexColorModel associated to	this instance.	Pre condition		The color model must be an instance of java.awt.IndexColorModel.		0 <= topBound <= bottomBound <= height.		0 <= leftBound <= rightBound <= width.	Post condition		-	Obligation		-		@author	Werner Randelshofer, Staldenmattweg 2, CH-6405 Immensee, Switzerland	@version	1997-10-16	Created.	*/	private void planesToIndexPixels(int top, int left, int bottom, int right)		{//long startTime = System.currentTimeMillis();		final int scanlineStride = getScanlineStride();		final int bitplaneStride = getBitplaneStride();		final int depth = getDepth();		final int width = getWidth();		final int pixelLineStride = width - right + left;		final int bottomScanline = bottom * scanlineStride;		final int bitCorrection = 8 - depth;		int x;		int iPixel = top * width + left;		int pixel = 0;		int bitShift;		int iBitmap;		int iScanline;		int iDepth;		final int bitplaneStride1 = bitplaneStride;		final int bitplaneStride2 = bitplaneStride * 2;		final int bitplaneStride3 = bitplaneStride * 3;		final int bitplaneStride4 = bitplaneStride * 4;		final int bitplaneStride5 = bitplaneStride * 5;		final int bitplaneStride6 = bitplaneStride * 6;		final int bitplaneStride7 = bitplaneStride * 7;		switch (depth)			{			case 1 :				{				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)					{					for (x = left; x < right; x++)						{						bitShift = x % 8;						iBitmap = iScanline + x / 8;						bytePixels_[iPixel++] = (byte)(	((bitmap_[iBitmap] << bitShift) & 128) >>> 7);						}					iPixel += pixelLineStride;					}				break;				}			case 2 :				{				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)					{					for (x = left; x < right; x++)						{						bitShift = x % 8;						iBitmap = iScanline + x / 8;						bytePixels_[iPixel++] = (byte)(							((bitmap_[iBitmap] << bitShift) & 128) >>> 7 |							((bitmap_[iBitmap+bitplaneStride1] << bitShift) & 128) >>> 6							);						}					iPixel += pixelLineStride;					}				break;				}			case 3 :				{				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)					{					for (x = left; x < right; x++)						{						bitShift = x % 8;						iBitmap = iScanline + x / 8;						bytePixels_[iPixel++] = (byte)(							((bitmap_[iBitmap] << bitShift) & 128) >>> 7 |							((bitmap_[iBitmap+bitplaneStride1] << bitShift) & 128) >>> 6 |							((bitmap_[iBitmap+bitplaneStride2] << bitShift) & 128) >>> 5 							);						}					iPixel += pixelLineStride;					}				break;				}			case 4 :				{				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)					{					for (x = left; x < right; x++)						{						bitShift = x % 8;						iBitmap = iScanline + x / 8;						bytePixels_[iPixel++] = (byte)(							((bitmap_[iBitmap] << bitShift) & 128) >>> 7 |							((bitmap_[iBitmap+bitplaneStride1] << bitShift) & 128) >>> 6 |							((bitmap_[iBitmap+bitplaneStride2] << bitShift) & 128) >>> 5 |							((bitmap_[iBitmap+bitplaneStride3] << bitShift) & 128) >>> 4 							);						}					iPixel += pixelLineStride;					}				break;				}			case 5 :				{				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)					{					for (x = left; x < right; x++)						{						bitShift = x % 8;						iBitmap = iScanline + x / 8;						bytePixels_[iPixel++] = (byte)(							((bitmap_[iBitmap] << bitShift) & 128) >>> 7 |							((bitmap_[iBitmap+bitplaneStride1] << bitShift) & 128) >>> 6 |							((bitmap_[iBitmap+bitplaneStride2] << bitShift) & 128) >>> 5 |							((bitmap_[iBitmap+bitplaneStride3] << bitShift) & 128) >>> 4 |							((bitmap_[iBitmap+bitplaneStride4] << bitShift) & 128) >>> 3							);						}					iPixel += pixelLineStride;					}				break;				}			case 6 :				{				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)					{					for (x = left; x < right; x++)						{						bitShift = x % 8;						iBitmap = iScanline + x / 8;						bytePixels_[iPixel++] = (byte)(							((bitmap_[iBitmap] << bitShift) & 128) >>> 7 |							((bitmap_[iBitmap+bitplaneStride1] << bitShift) & 128) >>> 6 |							((bitmap_[iBitmap+bitplaneStride2] << bitShift) & 128) >>> 5 |							((bitmap_[iBitmap+bitplaneStride3] << bitShift) & 128) >>> 4 |							((bitmap_[iBitmap+bitplaneStride4] << bitShift) & 128) >>> 3 |							((bitmap_[iBitmap+bitplaneStride5] << bitShift) & 128) >>> 2							);						}					iPixel += pixelLineStride;					}				break;				}			case 7 :				{				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)					{					for (x = left; x < right; x++)						{						bitShift = x % 8;						iBitmap = iScanline + x / 8;						bytePixels_[iPixel++] = (byte)(							((bitmap_[iBitmap] << bitShift) & 128) >>> 7 |							((bitmap_[iBitmap+bitplaneStride1] << bitShift) & 128) >>> 6 |							((bitmap_[iBitmap+bitplaneStride2] << bitShift) & 128) >>> 5 |							((bitmap_[iBitmap+bitplaneStride3] << bitShift) & 128) >>> 4 |							((bitmap_[iBitmap+bitplaneStride4] << bitShift) & 128) >>> 3 |							((bitmap_[iBitmap+bitplaneStride5] << bitShift) & 128) >>> 2 |							((bitmap_[iBitmap+bitplaneStride6] << bitShift) & 128) >>> 1							);						}					iPixel += pixelLineStride;					}				break;				}			case 8 :				{				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)					{					for (x = left; x < right; x++)						{						bitShift = x % 8;						iBitmap = iScanline + x / 8;						bytePixels_[iPixel++] = (byte)(							((bitmap_[iBitmap] << bitShift) & 128) >>> 7 |							((bitmap_[iBitmap+bitplaneStride1] << bitShift) & 128) >>> 6 |							((bitmap_[iBitmap+bitplaneStride2] << bitShift) & 128) >>> 5 |							((bitmap_[iBitmap+bitplaneStride3] << bitShift) & 128) >>> 4 |							((bitmap_[iBitmap+bitplaneStride4] << bitShift) & 128) >>> 3 |							((bitmap_[iBitmap+bitplaneStride5] << bitShift) & 128) >>> 2 |							((bitmap_[iBitmap+bitplaneStride6] << bitShift) & 128) >>> 1 |							((bitmap_[iBitmap+bitplaneStride7] << bitShift) & 128)							);						}					iPixel += pixelLineStride;					}				break;				}			default : 				{				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)					{					for (x = left; x < right; x++)						{						bitShift = x % 8;						iBitmap = iScanline + x / 8;						for (iDepth = depth; iDepth > 0; iDepth--)							{							pixel = (pixel >>> 1) | ((bitmap_[iBitmap] << bitShift)  & 128);							iBitmap += bitplaneStride;							}						bytePixels_[iPixel++] = (byte)(pixel >>> bitCorrection);						}					iPixel += pixelLineStride;					}				}			}	//System.out.println((System.currentTimeMillis() - startTime) + " " + depth);		}	/**	Converts the planar image data into chunky pixels.	After successful completion the chunky pixels can by used	in conjunction with the DirectColorModel associated to	this instance.	Pre condition		The color model must be an instance of java.awt.DirectColorModel.		0 <= topBound <= bottomBound <= height.		0 <= leftBound <= rightBound <= width.	Post condition		-	Obligation		-		@author	Werner Randelshofer, Staldenmattweg 2, CH-6405 Immensee, Switzerland	@version	1997-10-16	Created.	*/	private void planesToDirectPixels(int top, int left, int bottom, int right)		{		/*		// This section illustrates the original algorithm.				final int depth = getDepth();		final int width = getWidth();		final int scanlineStride = getScanlineStride();		final int bitplaneStride = getBitplaneStride();		final int pixelLineStride = width - right + left;		final int bottomScanline = bottom * scanlineStride;		int iScanline, x, iBitmap, iDepth, bitShift;		int pixel = 0;		int iPixel = top * width + left;				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)			{			for (x = left; x < right; x++)				{				bitShift = x % 8 + 16;				iBitmap = iScanline + x / 8;				for (iDepth = depth; iDepth > 0; iDepth--)					{					pixel = (pixel >>> 1) | ((bitmap_[iBitmap] << bitShift)  & 0x800000);					iBitmap += bitplaneStride;					}				intPixels_[iPixel++] = 0xff000000 | ((pixel >> 16) & 0xff) + (pixel & 0xff00) + ((pixel << 16) & 0xff0000);				}			iPixel += pixelLineStride;			}		*/		/*		// Eliminating the innermost loop increases the performance		// by 37 percent.		final int scanlineStride = getScanlineStride();		final int bitplaneStride = getBitplaneStride();		final int depth = getDepth();		final int width = getWidth();		final int pixelLineStride = width - right + left;		final int bottomScanline = bottom * scanlineStride;		int x;		int iPixel = top * width + left;		int pixel = 0;		int bitShift;		int iScanline;		int iDepth;		final int bitplaneStride2 = bitplaneStride * 2;		final int bitplaneStride3 = bitplaneStride * 3;		final int bitplaneStride4 = bitplaneStride * 4;		final int bitplaneStride5 = bitplaneStride * 5;		final int bitplaneStride6 = bitplaneStride * 6;		final int bitplaneStride7 = bitplaneStride * 7;		final int bitplaneStride8 = bitplaneStride * 8;		final int bitplaneStride9 = bitplaneStride * 9;		final int bitplaneStride10 = bitplaneStride * 10;		final int bitplaneStride11 = bitplaneStride * 11;		final int bitplaneStride12 = bitplaneStride * 12;		final int bitplaneStride13 = bitplaneStride * 13;		final int bitplaneStride14 = bitplaneStride * 14;		final int bitplaneStride15 = bitplaneStride * 15;		final int bitplaneStride16 = bitplaneStride * 16;		final int bitplaneStride17 = bitplaneStride * 17;		final int bitplaneStride18 = bitplaneStride * 18;		final int bitplaneStride19 = bitplaneStride * 19;		final int bitplaneStride20 = bitplaneStride * 20;		final int bitplaneStride21 = bitplaneStride * 21;		final int bitplaneStride22 = bitplaneStride * 22;		final int bitplaneStride23 = bitplaneStride * 23;				int iBitmap = top * scanlineStride + left / 8;				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)			{			for (x = left; x < right; x++)				{				bitShift = x % 8;				iBitmap = iScanline + x / 8;				intPixels_[iPixel++] = 0xff000000 | 					((bitmap_[iBitmap] << bitShift) & 128) << 9 |					((bitmap_[iBitmap+bitplaneStride] << bitShift) & 128) << 10 |					((bitmap_[iBitmap+bitplaneStride2] << bitShift) & 128) << 11 |					((bitmap_[iBitmap+bitplaneStride3] << bitShift) & 128) << 12 |					((bitmap_[iBitmap+bitplaneStride4] << bitShift) & 128) << 13 |					((bitmap_[iBitmap+bitplaneStride5] << bitShift) & 128) << 14 |					((bitmap_[iBitmap+bitplaneStride6] << bitShift) & 128) << 15 |					((bitmap_[iBitmap+bitplaneStride7] << bitShift) & 128) << 16 |					((bitmap_[iBitmap+bitplaneStride8] << bitShift) & 128) << 1 |					((bitmap_[iBitmap+bitplaneStride9] << bitShift) & 128) << 2 |					((bitmap_[iBitmap+bitplaneStride10] << bitShift) & 128) << 3 |					((bitmap_[iBitmap+bitplaneStride11] << bitShift) & 128) << 4 |					((bitmap_[iBitmap+bitplaneStride12] << bitShift) & 128) << 5 |					((bitmap_[iBitmap+bitplaneStride13] << bitShift) & 128) << 6 |					((bitmap_[iBitmap+bitplaneStride14] << bitShift) & 128) << 7 |					((bitmap_[iBitmap+bitplaneStride15] << bitShift) & 128) << 8 | 					((bitmap_[iBitmap+bitplaneStride16] << bitShift) & 128) >>> 7 |					((bitmap_[iBitmap+bitplaneStride17] << bitShift) & 128) >>> 6 |					((bitmap_[iBitmap+bitplaneStride18] << bitShift) & 128) >>> 5 |					((bitmap_[iBitmap+bitplaneStride19] << bitShift) & 128) >>> 4 |					((bitmap_[iBitmap+bitplaneStride20] << bitShift) & 128) >>> 3 |					((bitmap_[iBitmap+bitplaneStride21] << bitShift) & 128) >>> 2 |					((bitmap_[iBitmap+bitplaneStride22] << bitShift) & 128) >>> 1 |					((bitmap_[iBitmap+bitplaneStride23] << bitShift) & 128) 					;				}			iPixel += pixelLineStride;			}		*/		// Eliminating the innermost loop and avoiding unnecessary		// array accesses improves performance by 56 percent		// regarding to the original algorithm.				final int scanlineStride = getScanlineStride();		final int bitplaneStride = getBitplaneStride();		final int depth = getDepth();		final int width = getWidth();		final int pixelLineStride = width - right + left;		final int bottomScanline = bottom * scanlineStride;		int x;		int iPixel = top * width + left;		int pixel = 0;		int bitShift;		int iScanline;		int iDepth;		final int bitplaneStride2 = bitplaneStride * 2;		final int bitplaneStride3 = bitplaneStride * 3;		final int bitplaneStride4 = bitplaneStride * 4;		final int bitplaneStride5 = bitplaneStride * 5;		final int bitplaneStride6 = bitplaneStride * 6;		final int bitplaneStride7 = bitplaneStride * 7;		final int bitplaneStride8 = bitplaneStride * 8;		final int bitplaneStride9 = bitplaneStride * 9;		final int bitplaneStride10 = bitplaneStride * 10;		final int bitplaneStride11 = bitplaneStride * 11;		final int bitplaneStride12 = bitplaneStride * 12;		final int bitplaneStride13 = bitplaneStride * 13;		final int bitplaneStride14 = bitplaneStride * 14;		final int bitplaneStride15 = bitplaneStride * 15;		final int bitplaneStride16 = bitplaneStride * 16;		final int bitplaneStride17 = bitplaneStride * 17;		final int bitplaneStride18 = bitplaneStride * 18;		final int bitplaneStride19 = bitplaneStride * 19;		final int bitplaneStride20 = bitplaneStride * 20;		final int bitplaneStride21 = bitplaneStride * 21;		final int bitplaneStride22 = bitplaneStride * 22;		final int bitplaneStride23 = bitplaneStride * 23;		int iBitmap = top * scanlineStride + left / 8;		int b0=bitmap_[iBitmap];		int b1=bitmap_[iBitmap+bitplaneStride];		int b2=bitmap_[iBitmap+bitplaneStride2];		int b3=bitmap_[iBitmap+bitplaneStride4];		int b4=bitmap_[iBitmap+bitplaneStride4];		int b5=bitmap_[iBitmap+bitplaneStride5];		int b6=bitmap_[iBitmap+bitplaneStride6];		int b7=bitmap_[iBitmap+bitplaneStride7];		int b8=bitmap_[iBitmap+bitplaneStride8];		int b9=bitmap_[iBitmap+bitplaneStride9];		int b10=bitmap_[iBitmap+bitplaneStride10];		int b11=bitmap_[iBitmap+bitplaneStride11];		int b12=bitmap_[iBitmap+bitplaneStride12];		int b13=bitmap_[iBitmap+bitplaneStride13];		int b14=bitmap_[iBitmap+bitplaneStride14];		int b15=bitmap_[iBitmap+bitplaneStride15];		int b16=bitmap_[iBitmap+bitplaneStride16];		int b17=bitmap_[iBitmap+bitplaneStride17];		int b18=bitmap_[iBitmap+bitplaneStride18];		int b19=bitmap_[iBitmap+bitplaneStride19];		int b20=bitmap_[iBitmap+bitplaneStride20];		int b21=bitmap_[iBitmap+bitplaneStride21];		int b22=bitmap_[iBitmap+bitplaneStride22];		int b23=bitmap_[iBitmap+bitplaneStride23];				for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)			{			for (x = left; x < right; x++)				{				iBitmap = iScanline + x / 8;				bitShift = x % 8;				if (bitShift == 0)					{					b0 = bitmap_[iBitmap];					b1 = bitmap_[iBitmap+bitplaneStride];					b2 = bitmap_[iBitmap+bitplaneStride2];					b3 = bitmap_[iBitmap+bitplaneStride3];					b4 = bitmap_[iBitmap+bitplaneStride4];					b5 = bitmap_[iBitmap+bitplaneStride5];					b6 = bitmap_[iBitmap+bitplaneStride6];					b7 = bitmap_[iBitmap+bitplaneStride7];					b8 = bitmap_[iBitmap+bitplaneStride8];					b9 = bitmap_[iBitmap+bitplaneStride9];					b10 = bitmap_[iBitmap+bitplaneStride10];					b11 = bitmap_[iBitmap+bitplaneStride11];					b12 = bitmap_[iBitmap+bitplaneStride12];					b13 = bitmap_[iBitmap+bitplaneStride13];					b14 = bitmap_[iBitmap+bitplaneStride14];					b15 = bitmap_[iBitmap+bitplaneStride15];					b16 = bitmap_[iBitmap+bitplaneStride16];					b17 = bitmap_[iBitmap+bitplaneStride17];					b18 = bitmap_[iBitmap+bitplaneStride18];					b19 = bitmap_[iBitmap+bitplaneStride19];					b20 = bitmap_[iBitmap+bitplaneStride20];					b21 = bitmap_[iBitmap+bitplaneStride21];					b22 = bitmap_[iBitmap+bitplaneStride22];					b23 = bitmap_[iBitmap+bitplaneStride23];					}				intPixels_[iPixel++] = 0xff000000 | 					((b0 << bitShift) & 128) << 9 |					((b1 << bitShift) & 128) << 10 |					((b2 << bitShift) & 128) << 11 |					((b3 << bitShift) & 128) << 12 |					((b4 << bitShift) & 128) << 13 |					((b5 << bitShift) & 128) << 14 |					((b6 << bitShift) & 128) << 15 |					((b7 << bitShift) & 128) << 16 |					((b8 << bitShift) & 128) << 1 |					((b9 << bitShift) & 128) << 2 |					((b10 << bitShift) & 128) << 3 |					((b11 << bitShift) & 128) << 4 |					((b12 << bitShift) & 128) << 5 |					((b13 << bitShift) & 128) << 6 |					((b14 << bitShift) & 128) << 7 |					((b15 << bitShift) & 128) << 8 | 					((b16 << bitShift) & 128) >>> 7 |					((b17 << bitShift) & 128) >>> 6 |					((b18 << bitShift) & 128) >>> 5 |					((b19 << bitShift) & 128) >>> 4 |					((b20 << bitShift) & 128) >>> 3 |					((b21 << bitShift) & 128) >>> 2 |					((b22 << bitShift) & 128) >>> 1 |					((b23 << bitShift) & 128) 					;				}			iPixel += pixelLineStride;			}		}	/**	Converts the planar image data into chunky pixels.	After successful completion the chunky pixels can by used	in conjunction with the HAMColorModel associated to	this instance.	Pre condition		The color model must be an instance of HAMColorModel.		0 <= topBound <= bottomBound <= height.		0 <= leftBound <= rightBound <= width.	Post condition		-	Obligation		-		@author	Werner Randelshofer, Staldenmattweg 2, CH-6405 Immensee, Switzerland	@version	1997-10-16	Created.	*/	private void planesToHAM6Pixels(int top, int left, int bottom, int right)		{		final int[] HAMColors = new int[((HAMColorModel)colorModel_).getMapSize()];		((HAMColorModel)colorModel_).getRGBs(HAMColors);		final int scanlineStride = getScanlineStride();		final int bitplaneStride = getBitplaneStride();		final int depth = getDepth();		final int width = getWidth();		final int pixelLineStride = width - right + left;		final int bottomScanline = bottom * scanlineStride;		int x;		int iPixel = top * width + left;		int lastPixel, iLastPixel = top*width + left - 1;		int pixel = 0;		int bitShift;		int iBitmap;		int iScanline;		int iDepth;		final int bitplaneStride1 = bitplaneStride;		final int bitplaneStride2 = bitplaneStride * 2;		final int bitplaneStride3 = bitplaneStride * 3;		final int bitplaneStride4 = bitplaneStride * 4;		final int bitplaneStride5 = bitplaneStride * 5;		for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)			{			if (left == 0)				{ lastPixel = 0xff000000; }			else				{				lastPixel = intPixels_[iLastPixel];				iLastPixel += width;				}			for (x = left; x < right; x++)				{				bitShift = x % 8;				iBitmap = iScanline + x / 8;				pixel = ((bitmap_[iBitmap] << bitShift) & 128) >>> 3 |						((bitmap_[iBitmap+bitplaneStride1] << bitShift) & 128) >>> 2 |						((bitmap_[iBitmap+bitplaneStride2] << bitShift) & 128) >>> 1 |						((bitmap_[iBitmap+bitplaneStride3] << bitShift) & 128);				switch	(((bitmap_[iBitmap+bitplaneStride4] << bitShift) & 128) >>> 7 |						((bitmap_[iBitmap+bitplaneStride5] << bitShift) & 128) >>> 6)					{					case 0 :						 { // use indexed color						intPixels_[iPixel++] = lastPixel = HAMColors[pixel >>> 4];						break;						}					case 1:						{ // modifie blue						intPixels_[iPixel++] = lastPixel = lastPixel & 0xffffff00 | pixel | pixel >> 4;						break;						}	 				case 2:		 					{ // modify red						intPixels_[iPixel++] = lastPixel = lastPixel & 0xff00ffff | pixel << 16 | pixel << 12 & 0x000f0000;						break;						} 					default :						{ // modify green						intPixels_[iPixel++] = lastPixel = lastPixel & 0xffff00ff | pixel << 8 | pixel << 4 & 0x0f00;						break;						}					}				}			iPixel += pixelLineStride;			}		}	/**	Converts the planar image data into chunky pixels.	After successful completion the chunky pixels can by used	in conjunction with the HAMColorModel associated to	this instance.	Pre condition		The color model must be an instance of HAMColorModel.		0 <= topBound <= bottomBound <= height.		0 <= leftBound <= rightBound <= width.	Post condition		-	Obligation		-		@author	Werner Randelshofer, Staldenmattweg 2, CH-6405 Immensee, Switzerland	@version	1997-10-16	Created.	*/	private void planesToHAM8Pixels(int top, int left, int bottom, int right)		{		final int[] HAMColors = new int[((HAMColorModel)colorModel_).getMapSize()];		((HAMColorModel)colorModel_).getRGBs(HAMColors);		final int scanlineStride = getScanlineStride();		final int bitplaneStride = getBitplaneStride();		final int depth = getDepth();		final int width = getWidth();		final int pixelLineStride = width - right + left;		final int bottomScanline = bottom * scanlineStride;		int x;		int iPixel = top * width + left;		int lastPixel, iLastPixel = top*width + left - 1;		int pixel = 0;		int bitShift;		int iBitmap;		int iScanline;		int iDepth;		final int bitplaneStride1 = bitplaneStride;		final int bitplaneStride2 = bitplaneStride * 2;		final int bitplaneStride3 = bitplaneStride * 3;		final int bitplaneStride4 = bitplaneStride * 4;		final int bitplaneStride5 = bitplaneStride * 5;		final int bitplaneStride6 = bitplaneStride * 6;		final int bitplaneStride7 = bitplaneStride * 7;		for (iScanline = top * scanlineStride; iScanline < bottomScanline; iScanline += scanlineStride)			{			if (left == 0)				{ lastPixel = 0xff000000; }			else				{				lastPixel = intPixels_[iLastPixel];				iLastPixel += width;				}			for (x = left; x < right; x++)				{				bitShift = x % 8;				iBitmap = iScanline + x / 8;				pixel = ((bitmap_[iBitmap] << bitShift) & 128) >>> 5 |						((bitmap_[iBitmap+bitplaneStride1] << bitShift) & 128) >>> 4 |						((bitmap_[iBitmap+bitplaneStride2] << bitShift) & 128) >>> 3 |						((bitmap_[iBitmap+bitplaneStride3] << bitShift) & 128) >>> 2 |						((bitmap_[iBitmap+bitplaneStride4] << bitShift) & 128) >>> 1 |						((bitmap_[iBitmap+bitplaneStride5] << bitShift) & 128);				switch	(((bitmap_[iBitmap+bitplaneStride6] << bitShift) & 128) >>> 7 |						((bitmap_[iBitmap+bitplaneStride7] << bitShift) & 128) >>> 6)					{					case 0 :						 { // use indexed color						intPixels_[iPixel++] = lastPixel = HAMColors[pixel >>> 2];						break;						}					case 1:						{ // modifie blue						intPixels_[iPixel++] = lastPixel = lastPixel & 0xffffff00 | pixel | pixel >> 6;						break;						}	 				case 2:		 					{ // modify red						intPixels_[iPixel++] = lastPixel = lastPixel & 0xff00ffff | pixel << 16 | pixel << 10 & 0x030000;						break;						} 					default :						{ // modify green						intPixels_[iPixel++] = lastPixel = lastPixel & 0xffff00ff | pixel << 8 | pixel << 2 & 0x0300;						break;						}					}				}			iPixel += pixelLineStride;			}		}	}