Exemplo n.º 1
0
        public BitmapData LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format)
        {
            BitmapData result = new BitmapData();

            return(LockBits(rect, flags, format, result));
        }
Exemplo n.º 2
0
        public void UnlockBits(BitmapData bitmapdata)
        {
            Status status = GDIPlus.GdipBitmapUnlockBits(nativeObject, bitmapdata);

            GDIPlus.CheckStatus(status);
        }
Exemplo n.º 3
0
        private Bitmap BmpFrame()
        {
            Bitmap bitmap = null;

            if (_iconData != null && _bestBitDepth == 32)
            {
                // GDI+ doesnt handle 32 bpp icons with alpha properly
                // we load the icon ourself from the byte table
                bitmap = new Bitmap(Size.Width, Size.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
                Debug.Assert(_bestImageOffset >= 0 && (_bestImageOffset + _bestBytesInRes) <= _iconData.Length, "Illegal offset/length for the Icon data");

                unsafe
                {
                    BitmapData bmpdata = bitmap.LockBits(new Rectangle(0, 0, Size.Width, Size.Height),
                                                         ImageLockMode.WriteOnly,
                                                         PixelFormat.Format32bppArgb);
                    try
                    {
                        uint *pixelPtr = (uint *)bmpdata.Scan0.ToPointer();

                        // jumping the image header
                        int newOffset = _bestImageOffset + Marshal.SizeOf(typeof(SafeNativeMethods.BITMAPINFOHEADER));
                        // there is no color table that we need to skip since we're 32bpp

                        int lineLength = Size.Width * 4;
                        int width      = Size.Width;
                        for (int j = (Size.Height - 1) * 4; j >= 0; j -= 4)
                        {
                            Marshal.Copy(_iconData, newOffset + j * width, (IntPtr)pixelPtr, lineLength);
                            pixelPtr += width;
                        }

                        // note: we ignore the mask that's available after the pixel table
                    }
                    finally
                    {
                        bitmap.UnlockBits(bmpdata);
                    }
                }
            }
            else if (_bestBitDepth == 0 || _bestBitDepth == 32)
            {
                // This may be a 32bpp icon or an icon without any data.
                var info = new SafeNativeMethods.ICONINFO();
                SafeNativeMethods.GetIconInfo(new HandleRef(this, _handle), info);
                var bmp = new SafeNativeMethods.BITMAP();
                try
                {
                    if (info.hbmColor != IntPtr.Zero)
                    {
                        SafeNativeMethods.GetObject(new HandleRef(null, info.hbmColor), Marshal.SizeOf(typeof(SafeNativeMethods.BITMAP)), bmp);
                        if (bmp.bmBitsPixel == 32)
                        {
                            Bitmap     tmpBitmap  = null;
                            BitmapData bmpData    = null;
                            BitmapData targetData = null;
                            try
                            {
                                tmpBitmap = Image.FromHbitmap(info.hbmColor);

                                // In GDI+ the bits are there but the bitmap was created with no alpha channel
                                // so copy the bits by hand to a new bitmap
                                // we also need to go around a limitation in the way the ICON is stored (ie if it's another bpp
                                // but stored in 32bpp all pixels are transparent and not opaque)
                                // (Here you mostly need to remain calm....)
                                bmpData = tmpBitmap.LockBits(new Rectangle(0, 0, tmpBitmap.Width, tmpBitmap.Height), ImageLockMode.ReadOnly, tmpBitmap.PixelFormat);

                                // we need do the following if the image has alpha because otherwise the image is fully transparent even though it has data
                                if (BitmapHasAlpha(bmpData))
                                {
                                    bitmap     = new Bitmap(bmpData.Width, bmpData.Height, PixelFormat.Format32bppArgb);
                                    targetData = bitmap.LockBits(new Rectangle(0, 0, bmpData.Width, bmpData.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);

                                    CopyBitmapData(bmpData, targetData);
                                }
                            }
                            finally
                            {
                                if (tmpBitmap != null && bmpData != null)
                                {
                                    tmpBitmap.UnlockBits(bmpData);
                                }
                                if (bitmap != null && targetData != null)
                                {
                                    bitmap.UnlockBits(targetData);
                                }
                            }
                            tmpBitmap.Dispose();
                        }
                    }
                }
                finally
                {
                    if (info.hbmColor != IntPtr.Zero)
                    {
                        SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmColor));
                    }
                    if (info.hbmMask != IntPtr.Zero)
                    {
                        SafeNativeMethods.IntDeleteObject(new HandleRef(null, info.hbmMask));
                    }
                }
            }


            if (bitmap == null)
            {
                // last chance... all the other cases (ie non 32 bpp icons coming from a handle or from the bitmapData)

                // we have to do this rather than just return Bitmap.FromHIcon because
                // the bitmap returned from that, even though it's 32bpp, just paints where the mask allows it
                // seems like another GDI+ weirdness. might be interesting to investigate further. In the meantime
                // this looks like the right thing to do and is not more expansive that what was present before.

                Size size = Size;
                bitmap = new Bitmap(size.Width, size.Height); // initialized to transparent
                Graphics graphics = null;
                using (graphics = Graphics.FromImage(bitmap))
                {
                    try
                    {
                        using (Bitmap tmpBitmap = Bitmap.FromHicon(Handle))
                        {
                            graphics.DrawImage(tmpBitmap, new Rectangle(0, 0, size.Width, size.Height));
                        }
                    }
                    catch (ArgumentException)
                    {
                        // Sometimes FromHicon will crash with no real reason.
                        // The backup plan is to just draw the image like we used to.
                        // NOTE: FromHIcon is also where we have the buffer overrun
                        // if width and height are mismatched.
                        Draw(graphics, new Rectangle(0, 0, size.Width, size.Height));
                    }
                }


                // GDI+ fills the surface with a sentinel color for GetDC, but does
                // not correctly clean it up again, so we have to do it.
                Color fakeTransparencyColor = Color.FromArgb(0x0d, 0x0b, 0x0c);
                bitmap.MakeTransparent(fakeTransparencyColor);
            }

            Debug.Assert(bitmap != null, "Bitmap cannot be null");
            return(bitmap);
        }
Exemplo n.º 4
0
        public void UnlockBits(BitmapData bitmapdata)
        {
            int status = Gdip.GdipBitmapUnlockBits(new HandleRef(this, nativeImage), bitmapdata);

            Gdip.CheckStatus(status);
        }
Exemplo n.º 5
0
        public BitmapData LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)
        {
            int status = Gdip.GdipBitmapLockBits(
                new HandleRef(this, nativeImage), ref rect, flags, format, bitmapData);

            // libgdiplus has the wrong error code mapping for this state.
            if (status == 7)
            {
                status = 8;
            }
            Gdip.CheckStatus(status);

            return(bitmapData);
        }
Exemplo n.º 6
0
        public static unsafe Bitmap GenerateMip(this Bitmap bmp, int level)
        {
            if (level <= 1)
            {
                return((Bitmap)bmp.Clone());
            }

            int scale = 1 << (level - 1);
            int w = bmp.Width / scale, h = bmp.Height / scale;

            Bitmap dst = new Bitmap(w, h, bmp.PixelFormat);

            //Step-scale indexed elements
            if (bmp.IsIndexed())
            {
                BitmapData srcData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat);
                BitmapData dstData = dst.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, bmp.PixelFormat);

                float xStep = (float)bmp.Width / w;
                float yStep = (float)bmp.Height / h;
                int   x, y;
                float fx, fy;

                byte *sPtr, dPtr = (byte *)dstData.Scan0;
                if (bmp.PixelFormat == PixelFormat.Format8bppIndexed)
                {
                    for (y = 0, fy = 0.5f; y < h; y++, fy += yStep, dPtr += dstData.Stride)
                    {
                        sPtr = (byte *)srcData.Scan0 + ((int)fy * srcData.Stride);
                        for (x = 0, fx = 0.5f; x < w; x++, fx += xStep)
                        {
                            dPtr[x] = sPtr[(int)fx];
                        }
                    }
                }
                else
                {
                    for (y = 0, fy = 0.5f; y < h; y++, fy += yStep, dPtr += dstData.Stride)
                    {
                        sPtr = (byte *)srcData.Scan0 + ((int)fy * srcData.Stride);
                        int b = 0, ind;
                        for (x = 0, fx = 0.5f; x < w; x++, fx += xStep)
                        {
                            ind = (int)fx;
                            if ((x & 1) == 0)
                            {
                                if ((ind & 1) == 0)
                                {
                                    b = sPtr[ind >> 1] & 0xF0;
                                }
                                else
                                {
                                    b = sPtr[ind >> 1] << 4;
                                }
                            }
                            else
                            {
                                if ((ind & 1) == 0)
                                {
                                    b |= sPtr[ind >> 1] >> 4;
                                }
                                else
                                {
                                    b |= sPtr[ind >> 1] & 0xF;
                                }
                                dPtr[x >> 1] = (byte)b;
                            }
                        }
                        if ((x & 1) != 0)
                        {
                            dPtr[x >> 1] = (byte)b;
                        }
                    }
                }

                bmp.UnlockBits(srcData);
                dst.UnlockBits(dstData);
            }
            else
            {
                using (Graphics g = Graphics.FromImage(dst))
                {
                    g.CompositingMode    = CompositingMode.SourceCopy;
                    g.CompositingQuality = CompositingQuality.HighQuality;
                    g.InterpolationMode  = InterpolationMode.HighQualityBicubic;
                    g.PixelOffsetMode    = PixelOffsetMode.HighQuality;
                    g.SmoothingMode      = SmoothingMode.AntiAlias;

                    g.DrawImage(bmp, new Rectangle(0, 0, w, h));
                }
            }
            return(dst);
        }
Exemplo n.º 7
0
        public static unsafe Bitmap IndexColors(this Bitmap src, ColorPalette palette, PixelFormat format)
        {
            int w = src.Width, h = src.Height;

            int entries = palette.Entries.Length;

            switch (format)
            {
            case PixelFormat.Format4bppIndexed: { entries = Math.Min(entries, 16); break; }

            case PixelFormat.Format8bppIndexed: { entries = Math.Min(entries, 256); break; }

            default: { throw new ArgumentException("Pixel format is not an indexed format."); }
            }

            Bitmap dst = new Bitmap(w, h, format);

            dst.Palette = palette;

            BitmapData sData = src.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
            BitmapData dData = dst.LockBits(new Rectangle(0, 0, w, h), ImageLockMode.ReadWrite, format);

            ARGBPixel *sPtr = (ARGBPixel *)sData.Scan0;

            for (int y = 0; y < h; y++)
            {
                byte *dPtr = (byte *)dData.Scan0 + (y * dData.Stride);
                for (int x = 0; x < w; x++)
                {
                    ARGBPixel p = *sPtr++;

                    int bestDist = Int32.MaxValue, bestIndex = 0;
                    for (int z = 0; z < entries; z++)
                    {
                        int dist = p.DistanceTo(palette.Entries[z]);
                        if (dist < bestDist)
                        {
                            bestDist  = dist;
                            bestIndex = z;
                        }
                    }

                    if (format == PixelFormat.Format4bppIndexed)
                    {
                        byte val = *dPtr;
                        if ((x % 2) == 0)
                        {
                            *dPtr = (byte)((bestIndex << 4) | (val & 0x0F));
                        }
                        else
                        {
                            *dPtr++ = (byte)((val & 0xF0) | (bestIndex & 0x0F));
                        }
                    }
                    else
                    {
                        *dPtr++ = (byte)bestIndex;
                    }
                }
            }


            dst.UnlockBits(dData);
            src.UnlockBits(sData);

            return(dst);
        }