# How to convert Bitmap to Image

**URL:** <https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608>\
**Category:** .Net API\
**Created:** [December 7, 2018, 10:46am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608 "2018-12-07T10:46:39Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![roychou](https://avatars.discourse-cdn.com/v4/letter/r/71e660/32.png) [@roychou](https://forum.commonvisionblox.com/u/roychou)\
**Post date:** [December 7, 2018, 10:46am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/1 "2018-12-07T10:46:39Z")

</div>

You provide a function ToBitmap in Stemmer.Cvb.Extensions.ImageExtensions, but how can I convert Bitmap to Image?

---

<div class="post-metadata">

**Author:** ![illusive](https://yyz1.discourse-cdn.com/flex027/user_avatar/forum.commonvisionblox.com/illusive/32/61_2.png) [@illusive](https://forum.commonvisionblox.com/u/illusive)\
**Post date:** [December 7, 2018, 11:02am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/2 "2018-12-07T11:02:22Z")

</div>

Hi @roychou

_Stemmer.Cvb.Extensions.DrawingExtensions_ adds an extension method `ToImage` to the class `System.Drawing.Bitmap`. Is this what you are looking for?

---

<div class="post-metadata">

**Author:** ![roychou](https://avatars.discourse-cdn.com/v4/letter/r/71e660/32.png) [@roychou](https://forum.commonvisionblox.com/u/roychou)\
**Post date:** [December 7, 2018, 11:23am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/3 "2018-12-07T11:23:03Z")

</div>

Yes, thank you very much!

---

<div class="post-metadata">

**Author:** ![roychou](https://avatars.discourse-cdn.com/v4/letter/r/71e660/32.png) [@roychou](https://forum.commonvisionblox.com/u/roychou)\
**Post date:** [December 7, 2018, 11:38am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/4 "2018-12-07T11:38:06Z")

</div>

```
    public static Bitmap saveImage(Bitmap input)
    {
        var img = Stemmer.Cvb.Extensions.DrawingExtensions.ToImage(input);
        return Stemmer.Cvb.Extensions.ImageExtensions.ToBitmap(img);
    }

    static void Main(string[] args)
    {
        Bitmap input = new Bitmap("D:\\1.bmp");
        var output = saveImage(input);
        output.Save("D:\\2.bmp");
    }

```

what’s the problem with the code?

---

<div class="post-metadata">

**Author:** ![illusive](https://yyz1.discourse-cdn.com/flex027/user_avatar/forum.commonvisionblox.com/illusive/32/61_2.png) [@illusive](https://forum.commonvisionblox.com/u/illusive)\
**Post date:** [December 7, 2018, 1:51pm UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/5 "2018-12-07T13:51:32Z")

</div>

> [@roychou](#):
>
> what’s the problem with the code?

Nothing. I guess that _D:\1.bmp_ is a monochrome image and I fear you have found a bug in the import code for monochrome bitmaps - sorry for that ☹

To fix this, please do the following:

1. Make sure the latest build of the [CVB.Net](http://CVB.Net) Wrappers is installed on your system (the file _Stemmer.Cvb.dll_ in your _%CVB%\Lib\Net_ folder should have version 1.30.0.x). If the file is older than that, please download the latest version from here: [https://forum.commonvisionblox.com/t/introducing-experimental-cvb-net-cvb-and-cvbpy-api/205?u=illusive](https://forum.commonvisionblox.com/t/introducing-experimental-cvb-net-cvb-and-cvbpy-api/205). (if you DLL version is _newer_ than 1.30.0.x, then you don’t need to worry - you already have the patch installed…).
2. Download this file here, unzip it and copy it to a folder on your machine: [Stemmer.Cvb.Extensions.dll.zip](https://forum.commonvisionblox.com/uploads/commonvisionblox/original/1X/61d11b43100498ed2e1dbfe74d341a2e642ee909.zip) (17.7 KB)
3. Open a Visual Studio command prompt (any version \>= 2010 will do) **with admin privileges** and go to the folder where you copied the downloaded DLL.  
 ![image](https://canada1.discourse-cdn.com/flex027/uploads/commonvisionblox/original/1X/2e892b2f340375f615be9fdda7a08624579ea1ae.png)
4. Execute the command  
`gacutil -i Stemmer.Cvb.Extensions.dll`  
The output should read `Assembly successfully added to the cache`

Now your code should finally work. Hint: In Visual Studio you won’t see much of a difference between the old DLL and the new DLL because Visual Studio only reports `AssemblyVersion`s, and as the assembly interface did not change at all I have only increased the `AssemblyFileVersion` to 1.0.1.0.

One last thing: The line `Stemmer.Cvb.Extensions.ImageExtensions.ToBitmap(img);` will _always_ yield a 32 bit Bitmap - when working with monochrome images this is probably not what you’d expect, so you might want to use one of the overloads that permits the specification of a target pixel format.

---

<div class="post-metadata">

**Author:** ![roychou](https://avatars.discourse-cdn.com/v4/letter/r/71e660/32.png) [@roychou](https://forum.commonvisionblox.com/u/roychou)\
**Post date:** [December 8, 2018, 3:09am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/6 "2018-12-08T03:09:22Z")

</div>

Can you give me an example for monochrome images?  
I guess I should use ImageExtensions.ToBitmap Method (Image, Int32, Int32, PixelFormat, Rect, PlaneConfiguration, Double, Int32, HighBitScaleMode), but I do not have an example.

---

<div class="post-metadata">

**Author:** ![illusive](https://yyz1.discourse-cdn.com/flex027/user_avatar/forum.commonvisionblox.com/illusive/32/61_2.png) [@illusive](https://forum.commonvisionblox.com/u/illusive)\
**Post date:** [December 8, 2018, 11:08am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/7 "2018-12-08T11:08:19Z")

</div>

Hi @roychou,

sorry, that last sentence from my previous post was ill-conceived. The extension method `ToBitmap` relies on a `System.Drawing.Graphics` object being created for the target bitmap. However, `System.Drawing.Graphics` cannot be instantiated for an indexed bitmap (and that is what `PixelFormat.Format8bppIndexed`, the only available option that would model an 8 bit per pixel bitmap, is). In short: You cannot convert 24 an 8 bpp Bitmap using only the methods and classes exposed by `System.Drawing` and `ToBitmap()`. Or, to put it differently, `ToBitmap()` is currently not capable of producing an 8 bit Bitmap.

Therefore, if the objective is to save the monochrome bitmap into an 8 bit per pixel file I recommend calling `Save` on the `Stemmer.Cvb.Image` object directly rather than converting it back to a `System.Drawing.Bitmap`.

---

<div class="post-metadata">

**Author:** ![roychou](https://avatars.discourse-cdn.com/v4/letter/r/71e660/32.png) [@roychou](https://forum.commonvisionblox.com/u/roychou)\
**Post date:** [December 8, 2018, 1:16pm UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/8 "2018-12-08T13:16:37Z")

</div>

Do you have a method to convert Image to Array and Array to Image?If you do, please tell me!

---

<div class="post-metadata">

**Author:** ![illusive](https://yyz1.discourse-cdn.com/flex027/user_avatar/forum.commonvisionblox.com/illusive/32/61_2.png) [@illusive](https://forum.commonvisionblox.com/u/illusive)\
**Post date:** [December 8, 2018, 2:43pm UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/9 "2018-12-08T14:43:50Z")

</div>

There is no prefabricated method to do that, but for a code sample you might want to look at this post: [Writing Pixel Values to an Array](https://forum.commonvisionblox.com/t/writing-pixel-values-to-an-array/196/5?u=illusive) (the code is in the dark-themed screenshot of @Chris’s post).

---

<div class="post-metadata">

**Author:** ![parsd](https://yyz1.discourse-cdn.com/flex027/user_avatar/forum.commonvisionblox.com/parsd/32/7_2.png) [@parsd](https://forum.commonvisionblox.com/u/parsd)\
**Post date:** [December 9, 2018, 7:16am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/10 "2018-12-09T07:16:37Z")

</div>

Just as a side note: if you want array-like access on an `Image` you also can do something like this (pointer access is faster, though):

```cs
var size = new Size2D(640, 480);
var rampImage = new Image(size);

var access = rampImage.Planes[0].GetLinearAccess<byte>();
for (int y = 0; y < size.Height; y++)
{
  for (int x = 0; x < size.Width; x++)
  {
    access[x, y] = (byte)((y + x) % 255);
  }
}

```

---

<div class="post-metadata">

**Author:** ![parsd](https://yyz1.discourse-cdn.com/flex027/user_avatar/forum.commonvisionblox.com/parsd/32/7_2.png) [@parsd](https://forum.commonvisionblox.com/u/parsd)\
**Post date:** [December 9, 2018, 8:10am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/11 "2018-12-09T08:10:11Z")

</div>

But this would be much faster as much less marshaling needs to be done:

#### Example

**Note:** C# arrays are stored row-major and thus you need to access the pixels via `[y, x]`.

```cs
var size = new Size2D(640, 480);
	
var buffer = new byte[size.Height, size.Width];
for (int y = 0; y < size.Height; y++)
{
  for (int x = 0; x < size.Width; x++)
  {
    buffer[y, x] = (byte)((y + x) % 255);
  }
}

// make a copy from the array
var image = ImageArrayExtensions.CreateFrom(buffer);

// and from image to array and back
var image2 = ImageArrayExtensions.CreateFrom(image.ToArray());

```

#### Helper

```cs
static class ImageArrayExtensions
{
  public static byte[,] ToArray(this Image image)
  {
    if (image == null)
      throw new ArgumentNullException(nameof(image));
    if (image.Planes.Count > 1 || image.Planes[0].DataType != DataTypes.Int8BppUnsigned)
      throw new ArgumentException("Only Mono8 images are supported");
		
    var array = new byte[image.Height, image.Width];
		
    image.CopyTo(array);
		
    return array;
  }
	
  public static unsafe void CopyTo(this Image image, byte[,] array)
  {
    if (image == null)
      throw new ArgumentNullException(nameof(image));
    if (image.Planes.Count > 1 || image.Planes[0].DataType != DataTypes.Int8BppUnsigned)
      throw new ArgumentException("Only Mono8 images are supported");
    if (array == null)
      throw new ArgumentNullException(nameof(array));
    if (image.Width != array.GetLength(1) || image.Height != array.GetLength(0))
      throw new ArgumentException("Image and array have different dimensions");
			
    fixed (void* pBase = &array[0, 0])
    {
      using (var target = WrappedImage.FromGreyPixels((IntPtr)pBase, 0, image.Width, image.Height, PixelDataType.UInt, 8, 1, image.Width))
      {
        image.CopyTo(target);
      }
    }
  }
	
  public static Image CreateFrom(byte[,] array)
  {
    if (array == null)
      throw new ArgumentNullException(nameof(array));

    var image = new Image(array.GetLength(1), array.GetLength(0));
		
    image.CopyFrom(array);
		
    return image;
  }

  public static unsafe void CopyFrom(this Image image, byte[,] array)
  {
    if (image == null)
      throw new ArgumentNullException(nameof(image));
    if (image.Planes.Count > 1 || image.Planes[0].DataType != DataTypes.Int8BppUnsigned)
      throw new ArgumentException("Only Mono8 images are supported");
    if (array == null)
      throw new ArgumentNullException(nameof(array));
    if (image.Width != array.GetLength(1) || image.Height != array.GetLength(0))
      throw new ArgumentException("Image and array have different dimensions");

    fixed (void* pBase = &array[0, 0])
    {
      using (var source = WrappedImage.FromGreyPixels((IntPtr)pBase, 0, image.Width, image.Height, PixelDataType.UInt, 8, 1, image.Width))
      {
        source.CopyTo(image);
      }
    }
  }
}

```

---

<div class="post-metadata">

**Author:** ![roychou](https://avatars.discourse-cdn.com/v4/letter/r/71e660/32.png) [@roychou](https://forum.commonvisionblox.com/u/roychou)\
**Post date:** [December 10, 2018, 9:20am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/12 "2018-12-10T09:20:06Z")

</div>

Hello, now I find that the method `Stemmer.Cvb.Extensions.DrawingExtensions.ToImage` takes a very long time, 160 milliseconds. I want to know whether the time consuming is normal. If the time is normal, do you have a faster method to perform the conversion from Bitmap to Image?

---

<div class="post-metadata">

**Author:** ![illusive](https://yyz1.discourse-cdn.com/flex027/user_avatar/forum.commonvisionblox.com/illusive/32/61_2.png) [@illusive](https://forum.commonvisionblox.com/u/illusive)\
**Post date:** [December 10, 2018, 1:16pm UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/13 "2018-12-10T13:16:36Z")

</div>

Converting a `System.Drawing.Bitmap` to a `Stemmer.Cvb.Image` requires a deep copy of the image data. How much time for this deep copy is to be considered “normal” depends on the number of pixels and the memory layout (which are unknown for me at this point for your image). To give an example: A Bitmap with 24 bits per pixel and 1280x900 pixels takes about 19 ms on my machine.

There is generally speaking no faster means than the `ToImage()` extension method in the sense that this method analyzes the source and target layout and then uses the fastest approach possible based on that information. So if `ToImage()` seems unreasonably slow on your machine we’d need to figure out why (what size is the image, what is the pixel format of the image, what kind of PC are we talking about) and eliminate the reason if possible.

To paint the full picture: There is also a `ToCvbWrappedImage()` extension method (likely to be renamed to `ToWrappedImage()` in the next release…) which does the same job as `ToImage()` but **without** the copy step. In consequence this method is always _much_ faster, **but** : When using this method, you’ll have to make sure that the `System.Drawing.Bitmap`'s pixel buffer is locked for as long as the resulting wrapped images lives, otherwise your application will run into an access violation! The pixel buffer of `System.Drawing.Bitmap` objects is potentially subject to relocation to a different memory block by the CLR at any time and if other components (like the `WrappedImage`) depend on the buffer the buffer must be locked in place by means of a `LockBits()` call (see [here](https://docs.microsoft.com/en-us/dotnet/api/system.drawing.bitmap.lockbits?view=netframework-4.7.2)).

---

<div class="post-metadata">

**Author:** ![roychou](https://avatars.discourse-cdn.com/v4/letter/r/71e660/32.png) [@roychou](https://forum.commonvisionblox.com/u/roychou)\
**Post date:** [December 11, 2018, 12:43am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/14 "2018-12-11T00:43:47Z")

</div>

My image size is 2464\*2056, i.e. 5 million pixels, the pixel format is PixelFormat.Format8bppIndexed, and my PC is i5-4210U.

---

<div class="post-metadata">

**Author:** ![illusive](https://yyz1.discourse-cdn.com/flex027/user_avatar/forum.commonvisionblox.com/illusive/32/61_2.png) [@illusive](https://forum.commonvisionblox.com/u/illusive)\
**Post date:** [December 11, 2018, 10:09am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/15 "2018-12-11T10:09:10Z")

</div>

I am not 100% sure you’re measuring the same as me? I have produced a bmp file with 2464x2056 pixels using 8 bits per pixel and the `ToImage()` call takes merely 14 ms. My PC is a Core i7 8700K, but I do not think the difference in hardware alone would explain a factor \> 10 between your timing and mine.

This is the code I used:

```auto
    static void Main(string[] args)
    {
      var bmpFile = new Bitmap(@"D:\5mp.bmp");
      var timer = new StopWatch(StopWatchMode.SingleCPU);
      var cvbImg = bmpFile.ToImage();
      var duration = timer.TimeSpan;
      Console.WriteLine(duration);
    }

```

---

<div class="post-metadata">

**Author:** ![roychou](https://avatars.discourse-cdn.com/v4/letter/r/71e660/32.png) [@roychou](https://forum.commonvisionblox.com/u/roychou)\
**Post date:** [December 14, 2018, 1:21am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/16 "2018-12-14T01:21:33Z")

</div>

After I use your code, the consuming time is 30ms. But I use System.Diagnostics.Stopwatch, the time is 100ms. Can you tell me the difference between your Stemmer.Cvb.Utilities.StopWatch and System.Diagnostics.Stopwatch?  
This is the code I used:

```auto
static void Main(string[] args)
{
   var bmpFile = new Bitmap(@"D:\1.bmp");
   Stopwatch sw = new Stopwatch();
   sw.Start();
   var cvbImg = bmpFile.ToImage();
   sw.Stop();
   TimeSpan ts2 = sw.Elapsed;
   Console.WriteLine("time{0}ms.", ts2.TotalMilliseconds);
}

```

---

<div class="post-metadata">

**Author:** ![illusive](https://yyz1.discourse-cdn.com/flex027/user_avatar/forum.commonvisionblox.com/illusive/32/61_2.png) [@illusive](https://forum.commonvisionblox.com/u/illusive)\
**Post date:** [December 14, 2018, 10:17am UTC](https://forum.commonvisionblox.com/t/how-to-convert-bitmap-to-image/608/17 "2018-12-14T10:17:56Z")

</div>

30 ms sounds _a lot_ more plausible given the image dimensions and the CPU you are using.

I have never used `System.Diagnostics.Stopwatch` in the past, so I cannot comment on the accuracy of it. `Stemmer.Cvb.Utilities.StopWatch` internally uses the Windows SDK function `QueryPerformanceCounter` when in `SingleCPU` mode and usually achieves an accuracy level of less than one millisecond. In `MultiCPU` mode the accuracy is limited to 1 ms. From reading the [documentation of `System.Diagnostics.Stopwatch`](https://docs.microsoft.com/de-de/dotnet/api/system.diagnostics.stopwatch?view=netframework-4.7.2) I would assume that it can reach similar levels of accuracy.

I guess the easiest way to find out which timer is more trustworthy would be to run the same operation multiple times and calculate the average.
