Convert MagickImage to bitmap

4.4k Views Asked by At

I thought it would be easier, but I can't find a way to do it. How can I convert a MagickImage to System.Drawing.Image (eg a Bitmap)

    public System.Drawing.Image CreateThumbnailIcon(string sourceImagePath, int iconSize )
    {
        MagickImage image = new MagickImage(sourceImagePath);
        MagickGeometry geometry = new MagickGeometry(iconSize, iconSize);
        image.Resize(geometry);
        return image.??????;
    }
2

There are 2 best solutions below

2
On BEST ANSWER

I cannot confirm this works, I am doing this from memory, but give it a try:

MagickImage image = new MagickImage(sourceImagePath);
MagickGeometry geometry = new MagickGeometry(iconSize, iconSize);
image.Resize(geometry);

using (var memStream = new MemoryStream())
{
  // Write the image to the memorystream
  image.Write(memStream);
  
  return new System.Drawing.Bitmap(memStream);
}
1
On

For net framework you can use ToBitmap extension method

For net core / net5+ - there is no way out of the box and author of Magick.NET just saying "do not use System.Drawing in the new code".

But, if you really need this, you can use extension methods from corresponding GitHub issue

    public enum BitmapDensity
    {
        /// <summary>
        /// Ignore the density of the image when creating the bitmap.
        /// </summary>
        Ignore,

        /// <summary>
        /// Use the density of the image when creating the bitmap.
        /// </summary>
        Use,
    }

    public static class MagickImageExtensions
    {
        [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive.")]
        public static Bitmap ToBitmap(this MagickImage imageMagick, BitmapDensity bitmapDensity)
        {
            string mapping = "BGR";
            var format = PixelFormat.Format24bppRgb;

            var image = imageMagick;

            try
            {
                if( image.ColorSpace != ColorSpace.sRGB )
                {
                    image = (MagickImage)imageMagick.Clone();
                    image.ColorSpace = ColorSpace.sRGB;
                }

                if( image.HasAlpha )
                {
                    mapping = "BGRA";
                    format = PixelFormat.Format32bppArgb;
                }

                using( IPixelCollection pixels = image.GetPixelsUnsafe() )
                {
                    var bitmap = new Bitmap(image.Width, image.Height, format);
                    var data = bitmap.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadWrite, format);
                    var destination = data.Scan0;
                    for( int y = 0; y < image.Height; y++ )
                    {
                        byte[] bytes = pixels.ToByteArray(0, y, image.Width, 1, mapping);
                        Marshal.Copy(bytes, 0, destination, bytes.Length);

                        destination = new IntPtr(destination.ToInt64() + data.Stride);
                    }

                    bitmap.UnlockBits(data);

                    SetBitmapDensity(imageMagick, bitmap, bitmapDensity);
                    return bitmap;
                }
            }
            finally
            {
                if( ! ReferenceEquals(image, imageMagick) )
                    image.Dispose();
            }
        }

        public static Bitmap ToBitmap(this MagickImage imageMagick) => ToBitmap(imageMagick, BitmapDensity.Ignore);

        public static Bitmap ToBitmap(this MagickImage imageMagick, ImageFormat imageFormat) => ToBitmap(imageMagick, imageFormat, BitmapDensity.Ignore);

        public static Bitmap ToBitmap(this MagickImage imageMagick, ImageFormat imageFormat, BitmapDensity bitmapDensity)
        {
            imageMagick.Format = InternalMagickFormatInfo.GetFormat(imageFormat);

            MemoryStream memStream = new MemoryStream();
            imageMagick.Write(memStream);
            memStream.Position = 0;

            /* Do not dispose the memStream, the bitmap owns it. */
            var bitmap = new Bitmap(memStream);

            SetBitmapDensity(imageMagick, bitmap, bitmapDensity);

            return bitmap;
        }

        public static BitmapSource ToBitmapSource(this MagickImage imageMagick)
        {
            return ToBitmapSource(imageMagick, BitmapDensity.Ignore);
        }

        [SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope", Justification = "False positive.")]
        public static System.Windows.Media.Imaging.BitmapSource ToBitmapSource(this MagickImage imageMagick, BitmapDensity bitmapDensity)
        {
            IMagickImage image = imageMagick;

            var mapping = "RGB";
            var format = MediaPixelFormats.Rgb24;

            try
            {
                if (imageMagick.ColorSpace == ColorSpace.CMYK && !image.HasAlpha)
                {
                    mapping = "CMYK";
                    format = MediaPixelFormats.Cmyk32;
                }
                else
                {
                    if (imageMagick.ColorSpace != ColorSpace.sRGB)
                    {
                        image = (MagickImage) imageMagick.Clone();
                        image.ColorSpace = ColorSpace.sRGB;
                    }

                    if (image.HasAlpha)
                    {
                        mapping = "BGRA";
                        format = MediaPixelFormats.Bgra32;
                    }
                }

                var step = format.BitsPerPixel / 8;
                var stride = imageMagick.Width * step;

                using (IPixelCollection pixels = image.GetPixelsUnsafe())
                {
                    var bytes = pixels.ToByteArray(mapping);
                    var dpi = GetDpi(imageMagick, bitmapDensity);
                    return BitmapSource.Create(imageMagick.Width, imageMagick.Height, dpi.X, dpi.Y, format, null, bytes, stride);
                }
            }
            finally
            {
                if (!ReferenceEquals(imageMagick, image))
                    image.Dispose();
            }
        }

        public static void FromBitmap(this MagickImage imageMagick, Bitmap bitmap)
        {
            using (MemoryStream memStream = new MemoryStream())
            {
                if (IsSupportedImageFormat(bitmap.RawFormat))
                    bitmap.Save(memStream, bitmap.RawFormat);
                else
                    bitmap.Save(memStream, ImageFormat.Bmp);

                memStream.Position = 0;
                imageMagick.Read(memStream);
            }
        }

        private static bool IsSupportedImageFormat(ImageFormat format)
        {
            return
                format.Guid.Equals(ImageFormat.Bmp.Guid) ||
                format.Guid.Equals(ImageFormat.Gif.Guid) ||
                format.Guid.Equals(ImageFormat.Icon.Guid) ||
                format.Guid.Equals(ImageFormat.Jpeg.Guid) ||
                format.Guid.Equals(ImageFormat.Png.Guid) ||
                format.Guid.Equals(ImageFormat.Tiff.Guid);
        }

        private static void SetBitmapDensity(MagickImage imageMagick, Bitmap bitmap, BitmapDensity bitmapDensity)
        {
            if (bitmapDensity == BitmapDensity.Use)
            {
                var dpi = GetDpi(imageMagick, bitmapDensity);
                bitmap.SetResolution((float)dpi.X, (float)dpi.Y);
            }
        }

        private static Density GetDpi(MagickImage imageMagick, BitmapDensity bitmapDensity)
        {
            if (bitmapDensity == BitmapDensity.Ignore || (imageMagick.Density.Units == DensityUnit.Undefined && imageMagick.Density.X == 0 && imageMagick.Density.Y == 0))
                return new Density(96);

            return imageMagick.Density.ChangeUnits(DensityUnit.PixelsPerInch);
        }
    }

    public class InternalMagickFormatInfo
    {
        internal static MagickFormat GetFormat(ImageFormat format)
        {
            if (format == ImageFormat.Bmp || format == ImageFormat.MemoryBmp)
                return MagickFormat.Bmp;
            else if (format == ImageFormat.Gif)
                return MagickFormat.Gif;
            else if (format == ImageFormat.Icon)
                return MagickFormat.Icon;
            else if (format == ImageFormat.Jpeg)
                return MagickFormat.Jpeg;
            else if (format == ImageFormat.Png)
                return MagickFormat.Png;
            else if (format == ImageFormat.Tiff)
                return MagickFormat.Tiff;
            else
                throw new NotSupportedException("Unsupported image format: " + format.ToString());
        }
    }
}