/// <summary> /// Converts this canvas to <see cref="Image"/>. /// </summary> /// <param name="rect">The area to crop from the bitmap.</param> /// <returns>The <see cref="Imaging.Image"/> this method creates.</returns> public Image ToImage(Rectangle rect) { using (System.Drawing.Bitmap bmp = this.ToBitmap()) { if (bmp == null) { return(null); } return(rect.IsEmpty ? BitmapExtensions.FromBitmap(bmp) : BitmapExtensions.FromBitmap(bmp, rect)); } }
/// <summary> /// Creates an <see cref="Image"/> from a specified area of an encapsulated GDI+ bitmap. /// </summary> /// <param name="bitmap">The GDI+ bitmap from which to create the <see cref="Image"/>.</param> /// <param name="rect">Defines the portion of the <paramref name="bitmap"/> to copy. Coordinates are relative to <paramref name="bitmap"/>.</param> /// <returns> /// The <see cref="Image"/> this method creates. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="bitmap"/> is <b>null</b>. /// </exception> public static Image FromBitmap(System.Drawing.Bitmap bitmap, Rectangle rect) { if (bitmap == null) { throw new ArgumentNullException(nameof(bitmap)); } using (System.Drawing.Bitmap clonedBitmap = bitmap.Clone( new System.Drawing.Rectangle(rect.X, rect.Y, rect.Width, rect.Height), bitmap.PixelFormat)) { return(BitmapExtensions.FromBitmap(clonedBitmap)); } }
/// <summary> /// Creates an <see cref="Image"/> from an encapsulated GDI+ bitmap. /// </summary> /// <param name="bitmap">The GDI+ bitmap from which to create the <see cref="Image"/>.</param> /// <returns> /// The <see cref="Image"/> this method creates. /// </returns> /// <exception cref="ArgumentNullException"> /// <paramref name="bitmap"/> is <b>null</b>. /// </exception> public static Image FromBitmap(System.Drawing.Bitmap bitmap) { if (bitmap == null) { throw new ArgumentNullException(nameof(bitmap)); } Image image = new Image( bitmap.Width, bitmap.Height, BitmapExtensions.PixelFormatToBitsPerPixel(bitmap.PixelFormat), (int)(bitmap.HorizontalResolution + 0.5f), (int)(bitmap.VerticalResolution + 0.5f)); BitmapData srcData = bitmap.LockBits( new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat); unsafe { fixed(ulong *dst = image.Bits) { Arrays.CopyStrides( image.Height, srcData.Scan0, srcData.Stride, new IntPtr(dst), image.Stride8); } } if (image.BitsPerPixel < 8) { Vectors.SwapBits(image.Bits.Length, image.BitsPerPixel, image.Bits, 0); } bitmap.UnlockBits(srcData); return(Image.OnLoaded( image, null, bitmap.Palette?.Entries?.Select(x => Color.FromArgb(x.A, x.R, x.G, x.B)).ToArray())); }
internal static Image OnLoaded(Image image, ImageMetadata metadata, IList <Color> palette) { // try to fix invalid image resolution FixResolution(); // apply orientation ApplyOrientation(); // determine whether bitmap should be inverted bool invert = false; if (image.BitsPerPixel <= 8 && palette != null) { // convert color palette if (!BitmapExtensions.IsGrayScalePalette(image.BitsPerPixel, palette, out bool invertedPalette)) { return(image.ApplyPalette(palette)); } invert = invertedPalette; // remove palette metadata?.RemovePropertyItems(x => x.Id == (int)TIFFField.PhotometricInterpretation || x.Id == (int)TIFFField.ColorMap); } else { invert |= ApplyPhotometricInterpretation(); } if (invert) { image.Not(image); } return(image); // private methods void FixResolution() { (float w, float h)[] standardResolutions = new (float, float)[]
internal static (Image Image, ImageMetadata Metadata) FromBitmapFrame(this BitmapFrame bitmapFrame) { if (bitmapFrame == null) { throw new ArgumentNullException(nameof(bitmapFrame)); } int?xres = null; int?yres = null; // load metadata ImageMetadata metadata = null; if (bitmapFrame.Metadata is BitmapMetadata bitmapMetadata) { metadata = BitmapExtensions.ReadBitmapMetadata(bitmapMetadata); // reset resolution to 200 dpi for images that do not have resolution tag if (bitmapFrame.Decoder is TiffBitmapDecoder) { if (!metadata.HasPropertyItem((int)TIFFField.XResolution)) { xres = 200; } if (!metadata.HasPropertyItem((int)TIFFField.YResolution)) { yres = 200; } } // remove standard tags metadata.RemovePropertyItems(x => x.Id == (int)TIFFField.ImageWidth || x.Id == (int)TIFFField.ImageLength || x.Id == (int)TIFFField.XResolution || x.Id == (int)TIFFField.YResolution || x.Id == (int)TIFFField.BitsPerSample); } // verify palette presence System.Windows.Media.PixelFormat pixelFormat = bitmapFrame.Format; if ((pixelFormat == PixelFormats.Indexed1 || pixelFormat == PixelFormats.Indexed2 || pixelFormat == PixelFormats.Indexed4 || pixelFormat == PixelFormats.Indexed8) && bitmapFrame.Palette?.Colors == null) { throw new InvalidOperationException(Properties.Resources.E_UnsupportedImageFormat); } // load image Image image = new Image( bitmapFrame.PixelWidth, bitmapFrame.PixelHeight, pixelFormat.BitsPerPixel, xres.GetValueOrDefault((int)(bitmapFrame.DpiX + 0.5f)), yres.GetValueOrDefault((int)(bitmapFrame.DpiY + 0.5f))); int strideInBytes = (((image.Width * image.BitsPerPixel) + 31) & ~31) >> 3; uint[] bits = new uint[image.Height * strideInBytes / sizeof(uint)]; bitmapFrame.CopyPixels(bits, strideInBytes, 0); unsafe { fixed(uint *src = bits) { fixed(ulong *dst = image.Bits) { Arrays.CopyStrides( image.Height, new IntPtr(src), strideInBytes, new IntPtr(dst), image.Stride8); } } } if (image.BitsPerPixel < 8) { Vectors.SwapBits(image.Bits.Length, image.BitsPerPixel, image.Bits, 0); } // special case for BitmapFrame BlackWhite pixel format if (bitmapFrame.Format == PixelFormats.BlackWhite) { image.Not(image); metadata.RemovePropertyItem((int)TIFFField.PhotometricInterpretation); } return( Image.OnLoaded( image, metadata, bitmapFrame.Palette?.Colors?.Select(x => Color.FromArgb(x.A, x.R, x.G, x.B)).ToArray()), metadata); }
/// <summary> /// Converts this <see cref="Image"/> to a <see cref="System.Drawing.Bitmap"/>. /// </summary> /// <param name="image">The <see cref="Image"/> from which to create the GDI+ bitmap.</param> /// <returns> /// A <see cref="System.Drawing.Bitmap"/> that represents the converted <see cref="Image"/>. /// </returns> public static System.Drawing.Bitmap ToBitmap(this Image image) { if (image == null) { throw new ArgumentNullException(nameof(image)); } // select pixel format System.Drawing.Imaging.PixelFormat pixelFormat = BitmapExtensions.BitsPerPixelToPixelFormat(image.BitsPerPixel); // create new bitmap System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(image.Width, image.Height, pixelFormat); try { bitmap.SetResolution(image.HorizontalResolution, image.VerticalResolution); // copy bits BitmapData dstData = bitmap.LockBits( new System.Drawing.Rectangle(0, 0, image.Width, image.Height), ImageLockMode.WriteOnly, pixelFormat); unsafe { fixed(ulong *src = image.Bits) { Arrays.CopyStrides( image.Height, new IntPtr(src), image.Stride8, dstData.Scan0, dstData.Stride); if (image.BitsPerPixel < 8) { IntPtr dst = dstData.Scan0; if (dstData.Stride < 0) { dst = IntPtr.Add(dst, (image.Height - 1) * dstData.Stride); } Vectors.SwapBits( image.Height * Math.Abs(dstData.Stride) / sizeof(uint), image.BitsPerPixel, (uint *)dst.ToPointer()); } } } bitmap.UnlockBits(dstData); // we need to set palette for binary and gray scale images // as our color map is different from default map used by System.Drawing.Bitmap if (image.BitsPerPixel <= 8 && bitmap.Palette != null) { Color[] palette = Image.CreatePalette(image.BitsPerPixel); ColorPalette dst = bitmap.Palette; if (dst.Entries.Length == palette.Length) { for (int i = 0, ii = palette.Length; i < ii; i++) { dst.Entries[i] = System.Drawing.Color.FromArgb((int)palette[i].Argb); } } // we need to reset the palette as the getter returns its clone bitmap.Palette = dst; } return(bitmap); } catch { bitmap.Dispose(); throw; } }