public BitmapData LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format) { BitmapData result = new BitmapData(); return(LockBits(rect, flags, format, result)); }
public void UnlockBits(BitmapData bitmapdata) { Status status = GDIPlus.GdipBitmapUnlockBits(nativeObject, bitmapdata); GDIPlus.CheckStatus(status); }
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); }
public void UnlockBits(BitmapData bitmapdata) { int status = Gdip.GdipBitmapUnlockBits(new HandleRef(this, nativeImage), bitmapdata); Gdip.CheckStatus(status); }
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); }
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); }
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); }