public MemoryImage(MemoryImage SourceImage)
        {
            Create(SourceImage.Width, SourceImage.Height, SourceImage.PixelFormat);

            for (int i = 0; i < PaletteEntryCount; ++i)
            {
                SetPaletteColor(i, SourceImage.PaletteRed(i), SourceImage.PaletteGreen(i), SourceImage.PaletteBlue(i));
            }
        }
        public IImage GetImage(int X, int Y, int ImageWidth, int ImageHeight)
        {
            GR.Image.MemoryImage subImage = new MemoryImage(ImageWidth, ImageHeight, m_PixelFormat);

            for (int i = 0; i < PaletteEntryCount; ++i)
            {
                subImage.SetPaletteColor(i, PaletteRed(i), PaletteGreen(i), PaletteBlue(i));
            }

            // clip
            if ((X >= Width) ||
                (Y >= Height) ||
                (X + ImageWidth < 0) ||
                (Y + ImageHeight < 0))
            {
                return(subImage);
            }
            int copyWidth  = subImage.Width;
            int copyHeight = subImage.Height;

            if (X < 0)
            {
                copyWidth += X;
                X          = 0;
            }
            if (X + copyWidth >= Width)
            {
                copyWidth = Width - X;
            }
            if (Y < 0)
            {
                copyHeight += Y;
                Y           = 0;
            }
            if (Y + copyHeight >= Height)
            {
                copyHeight = Height - Y;
            }

            if ((subImage.PixelFormat == PixelFormat) &&
                (BitsPerPixel >= 8))
            {
                unsafe
                {
                    byte *pTargetPos = (byte *)subImage.PinData();

                    byte *pSourcePos = (byte *)PinData();
                    pSourcePos += BytesPerLine * Y + X * BitsPerPixel / 8;

                    for (int y = 0; y < copyHeight; ++y)
                    {
                        CopyMemory(new IntPtr(pTargetPos), new IntPtr(pSourcePos), (uint)(copyWidth * BitsPerPixel / 8));

                        /*
                         * GR.Memory.ByteBuffer    lineData = new GR.Memory.ByteBuffer();
                         * for ( int i = 0; i < copyWidth * BitsPerPixel / 8; ++i )
                         * {
                         * lineData.AppendU8( pSourcePos[i] );
                         * }
                         * Debug.Log( lineData.ToString() );
                         * */

                        pTargetPos += subImage.BytesPerLine;
                        pSourcePos += BytesPerLine;
                    }
                    UnpinData();
                    subImage.UnpinData();
                }
            }
            else
            {
                // safe (but slow) copy
                for (int i = 0; i < copyWidth; ++i)
                {
                    for (int j = 0; j < copyHeight; ++j)
                    {
                        subImage.SetPixel(X + i, Y + j, GetPixel(i, j));
                    }
                }
            }
            return(subImage);
        }