예제 #1
0
		public static Frame Resize(Frame originalFrame, int x, int y, int width, int height, int destWidth, int destHeight)
				{
					Frame newFrame = originalFrame.CloneFrameEmpty(destWidth, destHeight, originalFrame.pixelFormat);
					newFrame.data = new byte[newFrame.Height * newFrame.Stride];
					if (originalFrame.Palette != null)
					{
						newFrame.Palette = (int[])originalFrame.Palette.Clone();
					}
					if (destWidth <= width && destHeight <= height)
					{
						ShrinkBmp(originalFrame, newFrame, x, y, width, height);
					}
					else if (destWidth>= width && destHeight >= height)
					{
						ExpandBmp(originalFrame, newFrame, x, y, width, height);
					}
					else if (destWidth < width)
					{
						//TODO: Currently this is a two pass operation.
						// A temporary frame to hold the partially resized data
						Frame f = new Frame(null, destWidth, height, originalFrame.pixelFormat);
						ShrinkBmp(originalFrame, f, x, y, width, height);
						ExpandBmp(f, newFrame, 0, 0, destWidth, height);
					}
					else if (destHeight < height)
					{
						//TODO: currently this is a two pass operation.
						// A temporary frame to hold the partially resized data
						Frame f = new Frame(null, width, destHeight, originalFrame.pixelFormat);
						ShrinkBmp(originalFrame, f, x, y, width, height);
						ExpandBmp(f, newFrame, 0, 0, width, destHeight);
					}
					return newFrame;
				}
예제 #2
0
 // Load the icon contents from a stream, and then set the
 // current frame to the first one in the icon image.
 private void Load(Stream stream)
 {
     image = new DotGNU.Images.Image();
     image.Load(stream);
     frame    = image.GetFrame(0);
     frameNum = 0;
 }
예제 #3
0
	// Convert an image frame into an XImage.
	public static IntPtr FrameToXImage(Screen screen, Frame frame)
			{
				int[] fpalette;
				XPixel[] palette;
				int index, color;
				Colormap colormap = screen.DefaultColormap;

				// Create a palette to use to render the image.
				fpalette = frame.Palette;
				if(fpalette != null)
				{
					// Convert the palette within the image frame itself.
					palette = new XPixel [256];
					for(index = 0; index < 256 && index < fpalette.Length;
						++index)
					{
						color = fpalette[index];
						palette[index] = colormap.RGBToPixel
							(new Color((color >> 16) & 0xFF,
									   (color >> 8) & 0xFF, color & 0xFF));
					}
				}
				else
				{
					// We have an RGB image: use a standard palette.
					palette = colormap.GetStandardPalette();
				}

				// Convert the frame into an XImage and return it.
				return Xlib.XSharpCreateImageFromDIB
						(screen.screen, frame.Width, frame.Height,
						 frame.Stride, (int)(frame.PixelFormat),
						 frame.Data, 0, palette);
			}
예제 #4
0
	private Image(Image image, Frame thisFrameOnly) :
		this(image, image.PixelFormat)
			{
				if(thisFrameOnly != null)
				{
					this.numFrames = 1;
					this.frames = new Frame [1];
					this.frames[0] = thisFrameOnly.CloneFrame(this);
				}
				else
				{
					this.numFrames = image.numFrames;
					if(image.frames != null)
					{
						int frame;
						this.frames = new Frame [this.numFrames];
						for(frame = 0; frame < this.numFrames; ++frame)
						{
							this.frames[frame] =
								image.frames[frame].CloneFrame(this);
						}
					}
				}
				
			}
예제 #5
0
 private Icon(Icon cloneFrom)
 {
     if (cloneFrom == null)
     {
         throw new ArgumentNullException("cloneFrom");
     }
     image    = (DotGNU.Images.Image)(cloneFrom.image.Clone());
     frameNum = cloneFrom.frameNum;
     frame    = image.GetFrame(frameNum);
 }
예제 #6
0
	// Convert an image frame's mask into an XImage.  IntPtr.Zero if no mask.
	public static IntPtr MaskToXImage(Screen screen, Frame frame)
			{
				byte[] mask = frame.Mask;
				if(mask == null)
				{
					return IntPtr.Zero;
				}
				return Xlib.XSharpCreateImageFromDIB
					(screen.screen, frame.Width, frame.Height,
					 frame.MaskStride, (int)(PixelFormat.Format1bppIndexed),
					 mask, 1, null);
			}
예제 #7
0
	// Convert an image frame into an XImage bitmap.
	public static IntPtr FrameToXImageBitmap(Screen screen, Frame frame)
			{
				byte[] data = frame.Data;
				if(data == null)
				{
					return IntPtr.Zero;
				}
				return Xlib.XSharpCreateImageFromDIB
					(screen.screen, frame.Width, frame.Height,
					 frame.Stride, (int)(PixelFormat.Format1bppIndexed),
					 data, 1, null);
			}
예제 #8
0
 // Implement the IDisposable interface.
 public void Dispose()
 {
     if (toolkitImage != null)
     {
         toolkitImage.Dispose();
         toolkitImage = null;
     }
     if (image != null)
     {
         image.Dispose();
         image    = null;
         frame    = null;
         frameNum = 0;
     }
 }
예제 #9
0
 // Set this window's icon.
 void IToolkitTopLevelWindow.SetIcon(Icon icon)
 {
     DotGNU.Images.Frame frame    = ToolkitManager.GetImageFrame(icon);
     Xsharp.Image        origIcon = Icon;
     if (frame != null)
     {
         Icon = new Xsharp.Image(Screen, frame);
     }
     else
     {
         Icon = null;
     }
     if (origIcon != null)
     {
         origIcon.Dispose();
     }
 }
예제 #10
0
        // Select a particular frame from this icon.
        private void SelectFrame(int width, int height)
        {
            int   index;
            Frame frame;

            for (index = 0; index < image.NumFrames; ++index)
            {
                frame = image.GetFrame(index);
                if (frame.Width == width && frame.Height == height)
                {
                    this.frame = frame;
                    frameNum   = index;
                    return;
                }
            }
            frame    = image.GetFrame(0);
            frameNum = 0;
        }
예제 #11
0
	// Save a BITMAPINFO structure for a frame.
	public static void SaveBitmapInfo
				(Stream stream, Frame frame, int bitCount,
				 int size, byte[] buffer, int height)
			{
				// Build and write the BITMAPINFOHEADER structure.
				Utils.WriteInt32(buffer, 0, 40);			// biSize
				Utils.WriteInt32(buffer, 4, frame.Width);
				Utils.WriteInt32(buffer, 8, height);
				Utils.WriteUInt16(buffer, 12, 1);			// biPlanes
				Utils.WriteUInt16(buffer, 14, bitCount);
				Utils.WriteInt32(buffer, 16, 0);			// biCompression
				Utils.WriteInt32(buffer, 20, size);
				Utils.WriteInt32(buffer, 24, 3780);			// biXPelsPerMeter
				Utils.WriteInt32(buffer, 28, 3780);			// biYPelsPerMeter
				Utils.WriteInt32(buffer, 32, 0);			// biClrUsed
				Utils.WriteInt32(buffer, 36, 0);			// biClrImportant
				stream.Write(buffer, 0, 40);

				// Write the palette.
				if(bitCount <= 8)
				{
					int[] palette = frame.Palette;
					int count = (1 << bitCount);
					int index;
					for(index = 0; index < count; ++index)
					{
						if(palette != null && index < palette.Length)
						{
							Utils.WriteBGR(buffer, index * 4, palette[index]);
						}
						else
						{
							// Short palette: pad with black pixels.
							Utils.WriteBGR(buffer, index * 4, 0);
						}
					}
					stream.Write(buffer, 0, count * 4);
				}
			}
예제 #12
0
	private Frame(Image newImage, Frame frame, int newWidth, int newHeight, PixelFormat format, bool cloneData)
			{
				// Clone from the other frame.
				image = newImage;
				width = newWidth;
				height = newHeight;
				pixelFormat = format;
				stride =Utils.FormatToStride(pixelFormat, width);
				maskStride = (((width + 7) / 8) + 3) & ~3;
				generatedMask = false;
				if(frame.palette != null)
				{
					if(newImage != null && frame.palette == frame.image.Palette)
					{
						// The palette is a copy of the image's.
						palette = newImage.Palette;
					}
					else if (cloneData)
					{
						// The palette is specific to this frame.
						palette = (int[])(frame.palette.Clone());
					}
				}
				transparentPixel = frame.transparentPixel;
				hotspotX = frame.hotspotX;
				hotspotY = frame.hotspotY;
				offsetX = frame.offsetX;
				offsetY = frame.offsetY;
				if(cloneData & frame.data != null)
				{
					data = (byte[])(frame.data.Clone());
				}
				if(cloneData & frame.mask != null)
				{
					mask = (byte[])(frame.mask.Clone());
					generatedMask = frame.generatedMask;
				}
			}
예제 #13
0
	/// <summary>
	/// <para>Create a new cursor, based on a user-supplied image frame.</para>
	/// </summary>
	///
	/// <param name="screen">
	/// <para>The screen to create the cursor for, or
	/// <see langword="null"/> for the default screen on the
	/// default display.</para>
	/// </param>
	///
	/// <param name="frame">
	/// <para>The frame defining the cursor image.</para>
	/// </param>
	///
	/// <exception cref="T:System.ArgumentNullException"/>
	/// <para>Raised if <paramref name="frame"/> is
	/// <see langword="null"/>.</para>
	/// </exception>
	public Cursor(Screen screen, Frame frame)
			{
				Display dpy;
				if(frame == null)
				{
					throw new ArgumentNullException("frame");
				}
				if(screen != null)
				{
					dpy = screen.DisplayOfScreen;
				}
				else
				{
					dpy = Application.Primary.Display;
					screen = dpy.DefaultScreenOfDisplay;
				}
				if( /* irgnore pixel format! frame.PixelFormat != PixelFormat.Format1bppIndexed  || */
				   frame.Mask == null)
				{
					// The frame is not suitable for use as a cursor.
					this.type = CursorType.XC_left_ptr;
					this.source = null;
					this.mask = null;
					this.cursor = XCursor.Zero;
				}
				else
				{
					this.type = CursorType.XC_inherit_parent;
					this.cursor = XCursor.Zero;
					try
					{
						dpy.Lock();
						IntPtr pixmapXImage =
							ConvertImage.FrameToXImageBitmap(screen, frame);
						IntPtr maskXImage = ConvertImage.MaskToXImage
							(screen, frame);
						source = ConvertImage.XImageMaskToBitmap
							(screen, pixmapXImage);
						mask = ConvertImage.XImageMaskToBitmap
							(screen, maskXImage);
						Xlib.XSharpDestroyImage(pixmapXImage);
						Xlib.XSharpDestroyImage(maskXImage);
						hotspotX = frame.HotspotX;
						hotspotY = frame.HotspotY;
						if(frame.Palette != null && frame.Palette[0] == 0)
						{
							reverse = true;
						}
					}
					finally
					{
						dpy.Unlock();
					}
				}
			}
예제 #14
0
	// Output RGB data in 15-bit 555 format with a 1-bit alpha channel.
	private static void RgbAlpha555(Frame frame, int y, byte[] scanline)
			{
				int width = frame.Width;
				byte[] data = frame.Data;
				int posn, offset, value, component;
				offset = y * frame.Stride + width * 2;
				for(posn = (width - 1) * 4; posn >= 0; posn -= 4)
				{
					offset -= 2;
					value = data[offset] | (data[offset + 1] << 8);
					component = ((value >> 7) & 0xF8);
					scanline[posn]     = (byte)(component | (component >> 5));
					component = ((value >> 2) & 0xF8);
					scanline[posn + 1] = (byte)(component | (component >> 5));
					component = ((value << 3) & 0xF8);
					scanline[posn + 2] = (byte)(component | (component >> 5));
					if((value & 0x8000) != 0)
					{
						scanline[posn + 3] = 0xFF;
					}
					else
					{
						scanline[posn + 3] = 0x00;
					}
				}
			}
예제 #15
0
	public void SetFrame(int frame, Frame newFrame)
			{
				if(frame >= 0 && frame < numFrames && newFrame != null)
				{
					newFrame.NewImage(this);
					frames[frame] = newFrame;
				}
			}
예제 #16
0
	public Frame AddFrame(int width, int height, PixelFormat pixelFormat)
			{
				Frame frame = new Frame(this, width, height, pixelFormat);
				frame.Palette = palette;
				frame.TransparentPixel = transparentPixel;
				return AddFrame(frame);
			}
예제 #17
0
		// This is an integer, generic, low quality algorithm for expanding bitmaps.
		// A significant speed improvement could be optained by splitting out 1bpp & 4 bpp
		// Eliminating the many if's.
		private static void ExpandBmp(Frame oldFrame, Frame newFrame, int oldX, int oldY, int oldWidth, int oldHeight)
				{
					byte[] data = oldFrame.Data;
					byte[] dataOut = newFrame.Data;
					int sumY = 0;
					int lineStartNew = 0;

					int bytesPerPixel = Utils.FormatToBitCount(oldFrame.pixelFormat) / 8;
					int lineStartBit = 0;
					bool lineStartNibble = false;
					// Offset to the oldY.
					int lineStartOld = oldY * oldFrame.Stride;
					if (oldFrame.pixelFormat == PixelFormat.Format1bppIndexed)
					{
						lineStartOld = oldX / 8;
						lineStartBit = 7 - (oldX & 0x07);
					}
					else if (oldFrame.pixelFormat == PixelFormat.Format4bppIndexed)
					{
						lineStartOld = oldX / 2;
						lineStartNibble = ((oldX & 0x01) == 0);
					}
					else
					{
						lineStartOld =bytesPerPixel * oldX;
					}

					int y = 0;
					while(y < oldHeight)
					{
						int newPixel = lineStartNew;
						int newPixelBit = 7;
						bool newPixelNibble = true;
						int newPixelByte = 0;

						lineStartNew += newFrame.Stride;
						int oldPixelBit = lineStartBit;
						int oldPixel = lineStartOld;
						int oldPixelByte = -1;
						bool oldPixelNibble = lineStartNibble;
						int pix = 0;

						int x = 0;
						int sumX = 0;
						while(x < oldWidth)
						{
							sumX += oldWidth;
							// Write the pixel.
							// 1bpp format.
							if (oldFrame.pixelFormat == PixelFormat.Format1bppIndexed)
							{
								if (oldPixelByte == -1)
									oldPixelByte = data[oldPixel];
								if ( (oldPixelByte & 1<<oldPixelBit) != 0)
									newPixelByte |= 1<<newPixelBit;
								if (newPixelBit == 0)
								{
									dataOut[newPixel++] = (byte)(newPixelByte);
									newPixelBit = 7;
									newPixelByte = 0;
								}
								else
									newPixelBit--;
								if(sumX >= newFrame.Width)
								{
									x++;
									// Get the next nibble
									if (oldPixelBit==0)
									{
										oldPixelByte = -1;
										oldPixel++;
										oldPixelBit = 7;
									}
									else
										oldPixelBit--;
									sumX -= newFrame.Width;
								}
							}
							// 4bpp format.
							else if (oldFrame.pixelFormat == PixelFormat.Format4bppIndexed)
							{
								if (oldPixelByte == -1)
									oldPixelByte = data[oldPixel];
								if (oldPixelNibble)
									pix = oldPixelByte >> 4;
								else
									pix = oldPixelByte & 0x0F;
								
								if (newPixelNibble)
									newPixelByte = pix << 4;
								else
									dataOut[newPixel++] = (byte)(newPixelByte | pix);
								newPixelNibble = !newPixelNibble;
								if(sumX >= newFrame.Width)
								{
									x++;
									// Get the next nibble
									if (!oldPixelNibble)
									{
										oldPixelByte = -1;
										oldPixel++;
									}
									oldPixelNibble = !oldPixelNibble;
									sumX -= newFrame.Width;
								}
							}
							// All other formats.
							else
							{
								for(int i = 0; i < bytesPerPixel; i++, newPixel++)
									dataOut[newPixel] = data[oldPixel + i];
								if(sumX >= newFrame.Width)
								{
									x++;
									oldPixel += bytesPerPixel;
									sumX -= newFrame.Width;
								}
							}
						}
						// There maybe some bits left we need to write
						if (oldFrame.pixelFormat == PixelFormat.Format1bppIndexed && newPixelBit != 7)
							dataOut[newPixel++] = (byte)(newPixelByte);
						if (oldFrame.pixelFormat == PixelFormat.Format4bppIndexed && !newPixelNibble)
							dataOut[newPixel++] = (byte)(newPixelByte);
						sumY += oldHeight;
						if(sumY >= newFrame.Height)
						{
							y++;
							lineStartOld += oldFrame.Stride;
							oldPixel = lineStartOld;
							sumY -= newFrame.Height;
						}
					}
				} 
예제 #18
0
		// This is an integer, generic high quality algorithm for shrinking bitmaps.
		// A significant speed improvement could be optained by splitting out the formats
		// Eliminating the many if's.
		private static void ShrinkBmp(Frame oldFrame, Frame newFrame, int oldX, int oldY, int oldWidth, int oldHeight)
				{
					byte[] data = oldFrame.Data;
					byte[] dataOut = newFrame.Data;
					int[] palette = oldFrame.Palette;
					
					int lineStart = 0;
					int lineStartBit = 0;
					bool lineStartNibble = false;
					// Calculate the right line start based on the oldX
					if (oldFrame.pixelFormat == PixelFormat.Format1bppIndexed)
					{
						lineStart = oldX / 8;
						lineStartBit = 7 - (oldX & 0x07);
					}
					else if (oldFrame.pixelFormat == PixelFormat.Format4bppIndexed)
					{
						lineStart = oldX / 2;
						lineStartNibble = ((oldX & 0x01) == 0);
					}
					else
					{
						lineStart =Utils.FormatToBitCount(oldFrame.pixelFormat) / 8 * oldX;
					}

					// Offset to the right place based on oldY.
					lineStart += oldY * oldFrame.Stride;

					int lineStartOut = 0;
					int[] rowCoefficients = CreateCoefficients(oldWidth,  newFrame.Width);
					int[] columnCoefficients = CreateCoefficients(oldHeight,  newFrame.Height);
					byte pixelByte1 = 0;
					byte pixelByte2 = 0;
					byte pixelByte3 = 0;
					byte pixelAlpha = 255;
					byte byteData = 0;
					// Index for 1bpp format.
					int bit = lineStartBit;
					// Preread the byte if we have to.
					if (oldFrame.pixelFormat == PixelFormat.Format1bppIndexed && lineStartBit > 0)
						byteData = data[lineStart];
					// Index for 4bpp format.
					bool highNibble = lineStartNibble;
					// Preread the byte if we have to.
					if (oldFrame.pixelFormat == PixelFormat.Format4bppIndexed && !highNibble)
					{
						byteData = data[lineStart];
					}
					int bufWidth = 4;
					if (oldFrame.pixelFormat == PixelFormat.Format1bppIndexed)
					{
						bufWidth = 1;
					}
					int bufLine = bufWidth * newFrame.Width * 4;
					int bufNextLine =  bufWidth * newFrame.Width;
					uint[] buffer = new uint[bufWidth * 2 * newFrame.Width];
					int currentLine = 0;
					uint temp;

					int currentYCoeff = 0;
					int y = 0;
					while(y < newFrame.Height)
					{
						int currentPixel = lineStart;
						lineStart += oldFrame.Stride;

						int bufCurrentPixel = currentLine;
						int bufNextPixel = bufNextLine;

						int currentXCoeff = 0;
						int yCoefficient1 = columnCoefficients[currentYCoeff + 1];
						bool crossRow = yCoefficient1 > 0;
						int x = 0;
						while(x < newFrame.Width)
						{
							int yCoefficient = columnCoefficients[currentYCoeff];
							int xCoefficient = rowCoefficients[currentXCoeff];
						
							temp = (uint)(xCoefficient * yCoefficient);
							// Read the color from the particular format.
							// 1 bpp Format.
							if (oldFrame.pixelFormat==PixelFormat.Format1bppIndexed)
							{
								if (bit == 0)
								{
									byteData = data[currentPixel++];
									bit = 128;
								}
								if ((byteData & bit) > 0)
								{
									pixelByte1 = 255;
								}
								else
								{
									pixelByte1 = 0;
								}
								bit = (byte)(bit >>1);
								buffer[bufCurrentPixel] += temp * pixelByte1;
							}
							else
							{
								// 32 bpp Format.
								if (oldFrame.pixelFormat==PixelFormat.Format32bppArgb)
								{
									pixelByte1 = data[currentPixel++];
									pixelByte2 = data[currentPixel++];
									pixelByte3 = data[currentPixel++];
									pixelAlpha = data[currentPixel++];
								}
								// 24 bpp Format.
								else if (oldFrame.pixelFormat==PixelFormat.Format24bppRgb)
								{
									pixelByte1 = data[currentPixel++];
									pixelByte2 = data[currentPixel++];
									pixelByte3 = data[currentPixel++];
								}
								// 16 bpp 555 Format.
								else if (oldFrame.pixelFormat==PixelFormat.Format16bppRgb555)
								{
									pixelByte2 = data[currentPixel++];
									pixelByte1 = data[currentPixel++];
									pixelByte3 = (byte)(pixelByte2 & 0x1F);
									pixelByte2 = (byte)(pixelByte1 << 3 & 0x18  | pixelByte2 >> 5 & 0x07);
									pixelByte1 = (byte)(pixelByte1 >> 2 & 0x1f);
									pixelByte1 = (byte)((int)pixelByte1 * 255 / 31);
									pixelByte2 = (byte)((int)pixelByte2 * 255 / 31);
									pixelByte3 = (byte)((int)pixelByte3 * 255 / 31);
								}
								// 16 bpp 565 Format.
								else if (oldFrame.pixelFormat==PixelFormat.Format16bppRgb565)
								{
									pixelByte2 = data[currentPixel++];
									pixelByte1 = data[currentPixel++];
									pixelByte3 = (byte)(pixelByte2 & 0x1F);
									pixelByte2 = (byte)(pixelByte1 << 3 & 0x38  | pixelByte2 >> 5 & 0x07);
									pixelByte1 = (byte)(pixelByte1 >> 3);
									pixelByte1 = (byte)((int)pixelByte1 * 255 / 31);
									pixelByte2 = (byte)((int)pixelByte2 * 255 / 63);
									pixelByte3 = (byte)((int)pixelByte3 * 255 / 31);
								}
								// 8 bpp Format.
								else if (oldFrame.pixelFormat==PixelFormat.Format8bppIndexed)
								{
									int paletteColor = palette[data[currentPixel++]];
									pixelByte1 = (byte)(paletteColor>>16);
									pixelByte2 = (byte)(paletteColor>>8);
									pixelByte3 = (byte)paletteColor;
								}
								// 4 bpp Format.
								else if (oldFrame.pixelFormat==PixelFormat.Format4bppIndexed)
								{
									int paletteColor;
									if (highNibble)
									{
										byteData =  data[currentPixel++];
										paletteColor = palette[byteData >>4];
									}
									else
									{
										paletteColor = palette[byteData & 0x0F];
									}
									highNibble = !highNibble;
									pixelByte1 = (byte)(paletteColor>>16);
									pixelByte2 = (byte)(paletteColor>>8);
									pixelByte3 = (byte)paletteColor;
								}
								buffer[bufCurrentPixel] += temp * pixelByte1;
								buffer[bufCurrentPixel+1] += temp * pixelByte2;
								buffer[bufCurrentPixel+2] += temp * pixelByte3;
								buffer[bufCurrentPixel+3] += temp * pixelAlpha;
							}
							int xCoefficient1 = rowCoefficients[currentXCoeff + 1];
							bool crossColumn =  xCoefficient1> 0;
							if(crossColumn)
							{
								temp = (uint)(xCoefficient1 * yCoefficient);
								if (oldFrame.pixelFormat==PixelFormat.Format1bppIndexed)
									buffer[bufCurrentPixel + 1] += temp * pixelByte1;
								else
								{
									buffer[bufCurrentPixel + 4] += temp * pixelByte1;
									buffer[bufCurrentPixel + 5] += temp * pixelByte2;
									buffer[bufCurrentPixel + 6] += temp * pixelByte3;
									buffer[bufCurrentPixel + 7] += temp * pixelAlpha;
								}
							}
							if(crossRow)
							{
								temp = (uint)(xCoefficient * yCoefficient1);
								if (oldFrame.pixelFormat==PixelFormat.Format1bppIndexed)
										buffer[bufNextPixel] += temp * pixelByte1;
								else
								{
									buffer[bufNextPixel] += temp * pixelByte1;
									buffer[bufNextPixel + 1] += temp * pixelByte2;
									buffer[bufNextPixel + 2] += temp * pixelByte3;
									buffer[bufNextPixel + 3] += temp * pixelAlpha;
								}
								if(crossColumn)
								{
									temp = (uint)(xCoefficient1 * yCoefficient1);
									if (oldFrame.pixelFormat==PixelFormat.Format1bppIndexed)
										buffer[bufNextPixel + 1] += temp * pixelByte1;
									else
									{
										buffer[bufNextPixel + 4] += temp * pixelByte1;
										buffer[bufNextPixel + 5] += temp * pixelByte2;
										buffer[bufNextPixel + 6] += temp * pixelByte3;
										buffer[bufNextPixel + 7] += temp * pixelAlpha;
									}
								}
							}
							if(xCoefficient1 != 0)
							{
								x++;
								bufCurrentPixel += bufWidth;
								bufNextPixel += bufWidth;
							}
							currentXCoeff += 2;
						}
						if(yCoefficient1 != 0)
						{
							// set result line
							bufCurrentPixel = currentLine;
							currentPixel = lineStartOut;
							int endWriteBuffer = bufCurrentPixel + bufWidth * newFrame.Width;
							// Write the buffer.
							// 1 bpp format.
							if (oldFrame.pixelFormat==PixelFormat.Format1bppIndexed)
							{
								byte bit1 = 128;
								byte dataByte1 = 0;
								for(;bufCurrentPixel < endWriteBuffer; bufCurrentPixel++)
								{
									if (buffer[bufCurrentPixel] != 0)
									{
										dataByte1 |= bit1;
									}
									bit1 =(byte)(bit1 >> 1);
									if (bit1 == 0)
									{
										bit1 = 128;
										dataOut[currentPixel++] = dataByte1;
										dataByte1 = 0;
									}
								}
								// Write the last bits
								if (bit != 128)
								{
									dataOut[currentPixel] = dataByte1;
								}
							}
							// 32 bpp format.
							else if (oldFrame.pixelFormat==PixelFormat.Format32bppArgb)
							{
								for(; bufCurrentPixel < endWriteBuffer; bufCurrentPixel++)
								{
									dataOut[currentPixel++] = (byte)(buffer[bufCurrentPixel]>> 24);
								}
							}
							// 24 bpp format.
							else if (oldFrame.pixelFormat==PixelFormat.Format24bppRgb)
							{
								while( bufCurrentPixel < endWriteBuffer)
								{
									dataOut[currentPixel++] = (byte)(buffer[bufCurrentPixel++]>> 24);
									dataOut[currentPixel++] = (byte)(buffer[bufCurrentPixel++]>> 24);
									dataOut[currentPixel++] = (byte)(buffer[bufCurrentPixel++]>> 24);
									bufCurrentPixel++; // Skip alpha
								}
							}
							// 16 bpp 555 format.
							else if (oldFrame.pixelFormat==PixelFormat.Format16bppRgb555)
							{
								while( bufCurrentPixel < endWriteBuffer)
								{
									int r = (byte)(buffer[bufCurrentPixel++]>> 24);
									int g = (byte)(buffer[bufCurrentPixel++]>> 24);
									int b = (byte)(buffer[bufCurrentPixel++]>> 24);
									bufCurrentPixel++; // Skip alpha
									dataOut[currentPixel++] = (byte)((g<<2 & 0xE0) | (b>>3 & 0x1F));
									dataOut[currentPixel++] = (byte)((r>>1 & 0x7C) | (g >>6 & 0x03));
								}
							}
							// 16 bpp 565 format.
							else if (oldFrame.pixelFormat==PixelFormat.Format16bppRgb565)
							{
								while( bufCurrentPixel < endWriteBuffer)
								{
									int r = (byte)(buffer[bufCurrentPixel++]>> 24);
									int g = (byte)(buffer[bufCurrentPixel++]>> 24);
									int b = (byte)(buffer[bufCurrentPixel++]>> 24);
									bufCurrentPixel++; // Skip alpha
									dataOut[currentPixel++] = (byte)((g<<3 & 0xE0) | (b >> 3 & 0x1F)) ;
									dataOut[currentPixel++] = (byte)((r & 0xF8) | (g >>5 & 0x07));
								}
							}
							// 8 bpp format.
							else if (oldFrame.pixelFormat==PixelFormat.Format8bppIndexed)
							{
								while(bufCurrentPixel < endWriteBuffer)
								{
									int r = (byte)(buffer[bufCurrentPixel++]>> 24);
									int g = (byte)(buffer[bufCurrentPixel++]>> 24);
									int b = (byte)(buffer[bufCurrentPixel++]>> 24);
									bufCurrentPixel++; // Skip alpha
									dataOut[currentPixel++] = (byte)Utils.BestPaletteColor(palette, r, g, b);
								}
							}
							// 4 bpp format.
							else if (oldFrame.pixelFormat==PixelFormat.Format4bppIndexed)
							{
								bool highNibble1 = true;
								int dataByte1 = 0;
								while(bufCurrentPixel < endWriteBuffer)
								{
									int r = (byte)(buffer[bufCurrentPixel++]>> 24);
									int g = (byte)(buffer[bufCurrentPixel++]>> 24);
									int b = (byte)(buffer[bufCurrentPixel++]>> 24);
									bufCurrentPixel++; // Skip alpha
									int palettePos = (byte)Utils.BestPaletteColor(palette, r, g, b);
									if (highNibble1)
									{
										dataByte1 = palettePos << 4;
									}
									else
									{
										dataByte1 |= palettePos;
										dataOut[currentPixel++] = (byte)dataByte1;
									}
									highNibble1 = !highNibble1;
								}
								// Write the last bits
								if (!highNibble1)
								{
									dataOut[currentPixel] = (byte)dataByte1;
								}
							}
							
							bufCurrentPixel = bufNextLine;
							bufNextLine = currentLine;
							currentLine = bufCurrentPixel;
							int endClearBuffer = bufNextLine + bufLine/4;
							for (int c = bufNextLine; c < endClearBuffer; c++)
							{
								buffer[c] = 0;
							}
							y++;
							lineStartOut += newFrame.Stride;
						}
						currentYCoeff += 2;
					}
				} 
예제 #19
0
	// Output 16-bit grayscale data.
	private static void GrayScale16bpp(Frame frame, int y, byte[] scanline)
			{
				int width = frame.Width;
				byte[] data = frame.Data;
				int posn, offset;
				offset = y * frame.Stride + width * 2;
				for(posn = (width - 1) * 2; posn >= 0; posn -= 2)
				{
					// Byteswap the data.
					offset -= 2;
					scanline[posn]     = data[offset + 1];
					scanline[posn + 1] = data[offset];
				}
			}
예제 #20
0
	// Output 8-bit indexed data.
	private static void Indexed8bpp(Frame frame, int y, byte[] scanline)
			{
				Array.Copy(frame.Data, y * frame.Stride,
						   scanline, 0, frame.Width);
			}
예제 #21
0
	// Output 4-bit indexed data.
	private static void Indexed4bpp(Frame frame, int y, byte[] scanline)
			{
				int width = frame.Width;
				byte[] data = frame.Data;
				int posn, offset, bit;
				offset = y * frame.Stride;
				bit = 4;
				for(posn = 0; posn < width; ++posn)
				{
					scanline[posn] = (byte)((data[offset] >> bit) & 0x0F);
					bit -= 4;
					if(bit < 0)
					{
						++offset;
						bit = 4;
					}
				}
			}
예제 #22
0
	// Output 1-bit indexed data.
	private static void Indexed1bpp(Frame frame, int y, byte[] scanline)
			{
				int width = frame.Width;
				byte[] data = frame.Data;
				int posn, offset, bit;
				offset = y * frame.Stride;
				bit = 0x80;
				for(posn = 0; posn < width; ++posn)
				{
					if((data[offset] & bit) != 0)
					{
						scanline[posn] = 1;
					}
					else
					{
						scanline[posn] = 0;
					}
					bit >>= 1;
					if(bit == 0)
					{
						++offset;
						bit = 0x80;
					}
				}
			}
예제 #23
0
	// Output 64-bit RGB data with an alpha channel.
	private static void RgbAlpha64bpp(Frame frame, int y, byte[] scanline)
			{
				int width = frame.Width;
				byte[] data = frame.Data;
				int posn, offset;
				offset = y * frame.Stride + width * 8;
				for(posn = (width - 1) * 8; posn >= 0; posn -= 8)
				{
					// Convert BGR data into RGB data and byteswap.
					offset -= 8;
					scanline[posn]     = data[offset + 5];
					scanline[posn + 1] = data[offset + 4];
					scanline[posn + 2] = data[offset + 3];
					scanline[posn + 3] = data[offset + 1];
					scanline[posn + 4] = data[offset + 1];
					scanline[posn + 5] = data[offset];
					scanline[posn + 6] = data[offset + 7];
					scanline[posn + 7] = data[offset + 6];
				}
			}
예제 #24
0
	// Output 32-bit RGB data with an alpha channel.
	private static void RgbAlpha32bpp(Frame frame, int y, byte[] scanline)
			{
				int width = frame.Width;
				byte[] data = frame.Data;
				int posn, offset;
				offset = y * frame.Stride + width * 4;
				for(posn = (width - 1) * 4; posn >= 0; posn -= 4)
				{
					// Convert BGR data into RGB data.
					offset -= 4;
					scanline[posn]     = data[offset + 2];
					scanline[posn + 1] = data[offset + 1];
					scanline[posn + 2] = data[offset];
					scanline[posn + 3] = data[offset + 3];
				}
			}
예제 #25
0
	public static void Copy(Frame dest, int x, int y, int width, int height, Frame source, int sourceX, int sourceY)
			{
				// Developers should be aware of any costly conversions.
				// So we don't automatically match the depths.
				if (source.pixelFormat != dest.pixelFormat)
				{
					throw new InvalidOperationException();
				}

				if (x < 0 || y < 0 || width <= 0 || height <= 0)
				{
					throw new ArgumentOutOfRangeException();
				}

				if (x + width > dest.width)
				{
					width = dest.width - x;
				}

				if (y + height > dest.height)
				{
					height = dest.height - x;
				}

				if (source.width - sourceX < width)
				{
					width = source.width - sourceX;
				}
				if (source.height - sourceY < height)
				{
					height = source.height - sourceY;
				}

				//TODO:
				// If we are copying an index bitmap, we need to find the color
				// in the destination palette that is closest to the color we are
				// copying to. We would also need to add colors to the palette,
				// if there is space and optionally optimize the palette.
				// For now we just overwrite the old palette.

				if (source.palette != null)
				{
					dest.palette = (int[])source.palette.Clone();
				}
								
				int bits = Utils.FormatToBitCount(source.pixelFormat);
				Copy (bits, dest.data, dest.stride, x, y, width, height, source.Data, source.stride, sourceX, sourceY);

				//TODO:
				// The mask is not taken into account when copying. We need to
				// look at adding alpha support.
				// For now, just copy over the mask.
				if (source.Mask != null)
				{
					dest.AddMask();
					Copy(1, dest.mask, dest.maskStride,  x, y, width, height, source.mask, source.maskStride, sourceX, sourceY);
				}

			}
예제 #26
0
	// Copy as much of frame as possible to the x, y position of this frame.
	public void Copy(Frame frame, int x, int y)
			{
				Copy(this, x, y, width, height, frame, 0, 0);
			}
	private void CompileFrameData(Frame f)
			{
				int width = f.Width;
				int height = f.Height;
				int stride = f.Stride;
				int fMaskStride = f.MaskStride;
				int transparentPixel = f.TransparentPixel;
				int[] fPalette = f.Palette;
				byte[] fData = f.Data;
				byte[] fMask = f.Mask;
				PixelFormat pixelFormat = f.PixelFormat;

				int maskStride = (width + 7) / 8;
				byte[] mask = new byte[height*maskStride];
				if(fMask != null)
				{
					// the mask in the frame is padded to 4-bytes, while the
					// masks in postscript are padded to 1-byte, so perform a
					// conversion if necessary, but direct copy if possible
					if(maskStride == fMaskStride)
					{
						Array.Copy(fMask, 0, mask, 0, mask.Length);
					}
					else
					{
						int i = 0;
						int j = 0;
						int k = 0;
						while(i < height)
						{
							Array.Copy(fMask, j, mask, k, maskStride);
							++i;
							j += fMaskStride;
							k += maskStride;
						}
					}
				}
				byte[] data = new byte[width*3*height];
				int offset = 0;
				int maskOffset = 0;
				for(int y = 0, i = 0; y < height; ++y)
				{
					for(int x = 0, ptr = offset; x < width; ++x)
					{
						switch(pixelFormat)
						{
							case PixelFormat.Format64bppPArgb:
							{
								byte a = fData[ptr+7];
								if(a != 0)
								{
									data[i+2] = (byte)((fData[ptr+1] * 255) / a);
									data[i+1] = (byte)((fData[ptr+3] * 255) / a);
									data[i] = (byte)((fData[ptr+5] * 255) / a);
								}
								i += 3;
								ptr += 8;
							}
							break;

							case PixelFormat.Format64bppArgb:
							{
								data[i+2] = fData[ptr+1];
								data[i+1] = fData[ptr+3];
								data[i] = fData[ptr+5];
								i += 3;
								ptr += 8;
							}
							break;

							case PixelFormat.Format48bppRgb:
							{
								data[i+2] = fData[ptr+1];
								data[i+1] = fData[ptr+3];
								data[i] = fData[ptr+5];
								i += 3;
								ptr += 6;
							}
							break;

							case PixelFormat.Format32bppPArgb:
							{
								byte a = fData[ptr+3];
								if(a != 0)
								{
									data[i+2] = (byte)((fData[ptr] * 255) / a);
									data[i+1] = (byte)((fData[ptr+1] * 255) / a);
									data[i] = (byte)((fData[ptr+2] * 255) / a);
								}
								i += 3;
								ptr += 4;
							}
							break;

							case PixelFormat.Format32bppArgb:
							{
								data[i+2] = fData[ptr++];
								data[i+1] = fData[ptr++];
								data[i] = fData[ptr++];
								i += 3;
								++ptr;
							}
							break;

							case PixelFormat.Format24bppRgb:
							{
								data[i+2] = fData[ptr++];
								data[i+1] = fData[ptr++];
								data[i] = fData[ptr++];
								i += 3;
							}
							break;

							case PixelFormat.Format16bppRgb565:
							{
								int g = fData[ptr++];
								int r = fData[ptr++];
								int b = (g & 0x1F) * 255 / 31;
								g = (r << 3 & 0x38  | g >> 5 & 0x07) * 255 / 63;
								r =  (r >> 3) * 255 / 31;
								data[i++] = (byte)r;
								data[i++] = (byte)g;
								data[i++] = (byte)b;
							}
							break;

							case PixelFormat.Format16bppRgb555:
							{
								int g = fData[ptr++];
								int r = fData[ptr++];
								int b = (g & 0x1F) * 255 / 31;
								g =( r << 3 & 0x18  | g >> 5 & 0x07) * 255 / 31;
								r = ( r >> 2 & 0x1F) * 255 / 31;
								data[i++] = (byte)r;
								data[i++] = (byte)g;
								data[i++] = (byte)b;
							}
							break;

							case (PixelFormat.Format16bppGrayScale):
							{
								++ptr;
								byte all = data[ptr++];
								data[i++] = (byte)all;
								data[i++] = (byte)all;
								data[i++] = (byte)all;
							}
							break;

							case PixelFormat.Format8bppIndexed:
							{
								int idx = fData[ptr++];
								int color = fPalette[idx];
								data[i++] = (byte)(color >> 16);
								data[i++] = (byte)(color >> 8);
								data[i++] = (byte)(color);
								if(transparentPixel == idx)
								{
									int mptr = maskOffset + x/8;
									mask[mptr] |= (byte)(1 << (7 - (x & 0x07)));
								}
							}
							break;

							case PixelFormat.Format4bppIndexed:
							{
								int idx = fData[ptr++] >> 4;
								int color = fPalette[idx];
								data[i++] = (byte)(color >> 16);
								data[i++] = (byte)(color >> 8);
								data[i++] = (byte)(color);
								if(transparentPixel == idx)
								{
									int mptr = maskOffset + x/8;
									mask[mptr] |= (byte)(1 << (7 - (x & 0x07)));
								}
								++x;
								if(x < width)
								{
									idx = fData[ptr++] & 0x0F;
									color = fPalette[idx];
									data[i++] = (byte)(color >> 16);
									data[i++] = (byte)(color >> 8);
									data[i++] = (byte)(color);
									if(transparentPixel == idx)
									{
										int mptr = maskOffset + x/8;
										mask[mptr] |= (byte)(1 << (7 - (x & 0x07)));
									}
								}
							}
							break;

							case PixelFormat.Format1bppIndexed:
							{
								byte r0 = (byte)(fPalette[0] >> 16);
								byte g0 = (byte)(fPalette[0] >> 8);
								byte b0 = (byte)(fPalette[0]);
								byte r1 = (byte)(fPalette[1] >> 16);
								byte g1 = (byte)(fPalette[1] >> 8);
								byte b1 = (byte)(fPalette[1]);
								byte val = fData[ptr++];
								byte m = 0x80;
								int j = 0;
								int limit = ((width - x) < 8) ? (width - x) : 8;
								int mptr = ptr-1;
								while(j < limit)
								{
									m = (byte)(m >> j);
									if((val & m) == 0)
									{
										data[i++] = r0;
										data[i++] = g0;
										data[i++] = b0;
										if(transparentPixel == 0)
										{
											mask[mptr] |= (byte)(1 << j);
										}
									}
									else
									{
										data[i++] = r1;
										data[i++] = g1;
										data[i++] = b1;
										if(transparentPixel == 1)
										{
											mask[mptr] |= (byte)(1 << j);
										}
									}
									++j;
								}
								x += j;
							}
							break;

							default:
							{
								imageDataDict = null;
								imageData = null;
								maskDataDict = null;
								maskDataStream = null;
								return;
							}
							// Not reached.
						}
						offset += stride;
						maskOffset += maskStride;
					}
				}
				imageData = PostscriptGraphics.ASCII85Encode(data);
				maskDataStream = String.Format
					("currentfile /ASCII85Decode filter " +
					 "/ReusableStreamDecode filter " +
					 "{0} /maskstream exch def ",
					 PostscriptGraphics.ASCII85Encode(mask));
			}
		private void SetPixelLine(Frame frame, int x, int yPtr, int color)
				{
					switch (frame.PixelFormat)
					{
						case (PixelFormat.Format24bppRgb):
						{
							int ptr = yPtr + x * 3;
							frame.Data[ptr++] = (byte)color;
							frame.Data[ptr++] = (byte)(color>>8);
							frame.Data[ptr++] = (byte)(color>>16);
							break;
						}
						default:
							throw new NotSupportedException();
					}
				}
예제 #29
0
	/// <summary>
	/// <para>Constructs a new <see cref="T:Xsharp.Image"/> instance
	/// from a <see cref="T:DotGNU.Images.Frame"/> instance.</para>
	/// </summary>
	///
	/// <param name="frame">
	/// <para>The frame to load the image from.</para>
	/// </param>
	///
	/// <exception cref="T:System.ArgumentNullException">
	/// <para>The <paramref name="frame"/> parameter is
	/// <see langword="null"/>.</para>
	/// </exception>
	///
	/// <exception cref="T:Xsharp.XInvalidOperationException">
	/// <para>Raised if <paramref name="filename"/> could not be
	/// loaded for some reason.</para>
	/// </exception>
	public Image(Frame frame) : this(null, frame) {}
	// Set the cursor.  The toolkit may ignore "frame" if it already
	// has a system-defined association for "cursorType".  Setting
	// "cursorType" to "ToolkitCursorType.InheritParent" will reset
	// the cursor to be the same as the parent window's.
	void IToolkitWindow.SetCursor(ToolkitCursorType cursorType, Frame frame)
			{
				DrawingWindow.ModifyCursor(this, cursorType, frame);
			}
예제 #31
0
	/// <summary>
	/// <para>Constructs a new <see cref="T:Xsharp.Image"/> instance
	/// from a <see cref="T:DotGNU.Images.Frame"/> instance.</para>
	/// </summary>
	///
	/// <param name="screen">
	/// <para>The screen upon which to create the new image.</para>
	/// </param>
	///
	/// <param name="frame">
	/// <para>The frame to load the image from.</para>
	/// </param>
	///
	/// <exception cref="T:System.ArgumentNullException">
	/// <para>The <paramref name="frame"/> parameter is
	/// <see langword="null"/>.</para>
	/// </exception>
	///
	/// <exception cref="T:Xsharp.XInvalidOperationException">
	/// <para>Raised if <paramref name="filename"/> could not be
	/// loaded for some reason.</para>
	/// </exception>
	public Image(Screen screen, Frame frame)
			{
				Display dpy;
				if(frame == null)
				{
					throw new ArgumentNullException("frame");
				}
				if(screen != null)
				{
					dpy = screen.DisplayOfScreen;
				}
				else
				{
					dpy = Application.Primary.Display;
					screen = dpy.DefaultScreenOfDisplay;
				}
				this.screen = screen;
				try
				{
					dpy.Lock();
					pixmapXImage = ConvertImage.FrameToXImage(screen, frame);
					maskXImage = ConvertImage.MaskToXImage(screen, frame);
				}
				finally
				{
					dpy.Unlock();
				}
			}
예제 #32
0
	public Frame AddFrame(Frame frame)
			{
				if(frames == null)
				{
					frames = new Frame[] {frame};
					numFrames = 1;
				}
				else
				{
					Frame[] newFrames = new Frame [numFrames + 1];
					Array.Copy(frames, 0, newFrames, 0, numFrames);
					frames = newFrames;
					frames[numFrames] = frame;
					++numFrames;
				}
				return frame;
			}
	// Create a device independant bitmap from a frame. Optionally set all bits that are masked to black.
	// This is required for icons.
	private IntPtr HandleFromBitmap(Frame frame, bool andMask)
	{
		// By default we use the data straight from the frame.
		byte[] data = frame.Data;
		if (andMask)
		{
			//TODO: this could be slow.
			// Create a new image that we will copy the pixels to, leaving the masked pixels black.
			DotGNU.Images.Image newImage  = new DotGNU.Images.Image(frame.Width, frame.Height, frame.PixelFormat);
			Frame newFrame = newImage.AddFrame();
			data = new byte[data.Length];
			for (int y = 0; y < frame.Height; y++)
			{
				for (int x = 0; x < frame.Width; x++)
				{
					if (frame.GetMask(x, y) != 0)
						newFrame.SetPixel(x, y, frame.GetPixel(x, y));
				}
			}
			data = newFrame.Data;
		}

		// Create BITMAPINFO structure.
		int bitmapInfoSize = 40;
		int bitCount = frame.BitsPerPixel;
		// Do we have a palette?
		if(bitCount <= 8)
			bitmapInfoSize += 1 << bitCount * 4;
		byte[] bitmapInfo = new byte[bitmapInfoSize];

		// Build and write the BITMAPINFOHEADER structure.
		WriteInt32(bitmapInfo, 0, 40);// biSize
		WriteInt32(bitmapInfo, 4, frame.Width);
		WriteInt32(bitmapInfo, 8, -frame.Height);// upside down so make the height negative.
		WriteUInt16(bitmapInfo, 12, 1);// biPlanes
		WriteUInt16(bitmapInfo, 14, bitCount);
		WriteInt32(bitmapInfo, 16, 0);// biCompression
		WriteInt32(bitmapInfo, 20, 0);// size of image
		WriteInt32(bitmapInfo, 24, 3780);// biXPelsPerMeter
		WriteInt32(bitmapInfo, 28, 3780);// biYPelsPerMeter
		WriteInt32(bitmapInfo, 32, 0);	// biClrUsed
		WriteInt32(bitmapInfo, 36, 0);	// biClrImportant

		// Write the palette.
		if(bitCount <= 8)
		{
			int count = (1 << bitCount);
			for(int index = 0; index < count; ++index)
			{
				if(frame.Palette != null && index < frame.Palette.Length)
					WriteBGR(bitmapInfo, index * 4 + 40, frame.Palette[index]);
				else
				{
					// Short palette: pad with black pixels.
					WriteBGR(bitmapInfo, index * 4 + 40, 0);
				}
			}
		}

		return Win32.Api.CreateDIBitmap( Win32.Api.GetDC(hwnd), bitmapInfo, 4 /*CBM_INIT*/, data, bitmapInfo, 0 /*DIB_RGB_COLORS*/);
	}
예제 #34
0
	// Set the cursor.  The toolkit may ignore "frame" if it already
	// has a system-defined association for "cursorType".  Setting
	// "cursorType" to "ToolkitCursorType.InheritParent" will reset
	// the cursor to be the same as the parent window's.
	void IToolkitWindow.SetCursor(ToolkitCursorType cursorType, Frame frame)
	{
		// TODO
	}
예제 #35
0
	// Output RGB data in 16-bit 565 format.
	private static void Rgb565(Frame frame, int y, byte[] scanline)
			{
				int width = frame.Width;
				byte[] data = frame.Data;
				int posn, offset, value, component;
				offset = y * frame.Stride + width * 2;
				for(posn = (width - 1) * 3; posn >= 0; posn -= 3)
				{
					offset -= 2;
					value = data[offset] | (data[offset + 1] << 8);
					component = ((value >> 8) & 0xF8);
					scanline[posn]     = (byte)(component | (component >> 5));
					component = ((value >> 3) & 0xFC);
					scanline[posn + 1] = (byte)(component | (component >> 6));
					component = ((value << 3) & 0xF8);
					scanline[posn + 2] = (byte)(component | (component >> 5));
				}
			}