*            the color to end with
	 * @param redBits
	 *            the number of significant red bits, 0 for palette modes
	 * @param greenBits
	 *            the number of significant green bits, 0 for palette modes
	 * @param blueBits
	 *            the number of significant blue bits, 0 for palette modes
	 * @return the new ImageData
	 */
	static ImageData createGradientBand(int width, int height,
			boolean vertical, RGB fromRGB, RGB toRGB, int redBits,
			int greenBits, int blueBits) {
		/* Gradients are drawn as tiled bands */
		final int bandWidth, bandHeight, bitmapDepth;
		final byte[] bitmapData;
		final PaletteData paletteData;
		/* Select an algorithm depending on the depth of the screen */
		if (redBits != 0 && greenBits != 0 && blueBits != 0) {
			paletteData = new PaletteData(0x0000ff00, 0x00ff0000, 0xff000000);
			bitmapDepth = 32;
			if (redBits >= 8 && greenBits >= 8 && blueBits >= 8) {
				/* Precise color */
				final int steps;
				if (vertical) {
					bandWidth = 1;
					bandHeight = height;
					steps = bandHeight > 1 ? bandHeight - 1 : 1;
				} else {
					bandWidth = width;
					bandHeight = 1;
					steps = bandWidth > 1 ? bandWidth - 1 : 1;
				}
				final int bytesPerLine = bandWidth * 4;
				bitmapData = new byte[bandHeight * bytesPerLine];
				buildPreciseGradientChannel(fromRGB.blue, toRGB.blue, steps,
						bandWidth, bandHeight, vertical, bitmapData, 0,
						bytesPerLine);
				buildPreciseGradientChannel(fromRGB.green, toRGB.green, steps,
						bandWidth, bandHeight, vertical, bitmapData, 1,
						bytesPerLine);
				buildPreciseGradientChannel(fromRGB.red, toRGB.red, steps,
						bandWidth, bandHeight, vertical, bitmapData, 2,
						bytesPerLine);
			} else {
				/* Dithered color */
				final int steps;
				if (vertical) {
					bandWidth = (width < 8) ? width : 8;
					bandHeight = height;
					steps = bandHeight > 1 ? bandHeight - 1 : 1;
				} else {
					bandWidth = width;
					bandHeight = (height < 8) ? height : 8;
					steps = bandWidth > 1 ? bandWidth - 1 : 1;
				}
				final int bytesPerLine = bandWidth * 4;
				bitmapData = new byte[bandHeight * bytesPerLine];
				buildDitheredGradientChannel(fromRGB.blue, toRGB.blue, steps,
						bandWidth, bandHeight, vertical, bitmapData, 0,
						bytesPerLine, blueBits);
				buildDitheredGradientChannel(fromRGB.green, toRGB.green, steps,
						bandWidth, bandHeight, vertical, bitmapData, 1,
						bytesPerLine, greenBits);
				buildDitheredGradientChannel(fromRGB.red, toRGB.red, steps,
						bandWidth, bandHeight, vertical, bitmapData, 2,
						bytesPerLine, redBits);
			}
		} else {
			/* Dithered two tone */
			paletteData = new PaletteData(new RGB[] { fromRGB, toRGB });
			bitmapDepth = 8;
			final int blendi;
			if (vertical) {
				bandWidth = (width < 8) ? width : 8;
				bandHeight = height;
				blendi = (bandHeight > 1) ? 0x1040000 / (bandHeight - 1) + 1
						: 1;
			} else {
				bandWidth = width;
				bandHeight = (height < 8) ? height : 8;
				blendi = (bandWidth > 1) ? 0x1040000 / (bandWidth - 1) + 1 : 1;
			}
			final int bytesPerLine = (bandWidth + 3) & -4;
			bitmapData = new byte[bandHeight * bytesPerLine];
			if (vertical) {
				for (int dy = 0, blend = 0, dp = 0; dy < bandHeight; ++dy, blend += blendi, dp += bytesPerLine) {
					for (int dx = 0; dx < bandWidth; ++dx) {
						bitmapData[dp + dx] = (blend + DITHER_MATRIX[dy & 7][dx]) < 0x1000000 ? (byte) 0
								: (byte) 1;
					}
				}
			} else {
				for (int dx = 0, blend = 0; dx < bandWidth; ++dx, blend += blendi) {
					for (int dy = 0, dptr = dx; dy < bandHeight; ++dy, dptr += bytesPerLine) {
						bitmapData[dptr] = (blend + DITHER_MATRIX[dy][dx & 7]) < 0x1000000 ? (byte) 0
								: (byte) 1;
					}
				}
			}
		}
		return new ImageData(bandWidth, bandHeight, bitmapDepth, paletteData,
				4, bitmapData);
	}