none
how to draw to a monocrome bitmap? RRS feed

  • Question

  • Hi,

    I need to do some image processing on very large bitmaps (100000x100000).
    For my needs it would be sufficient to use PixelFormat.Format1bppIndexed of which I assume that it takes 0ne Bit per Pixel. (Is that right?)

    Unfortunately I do get a exception if I use the following code:

    private void button1_Click(object sender, EventArgs e)
    {
        var bitmap = new Bitmap(500, 500, PixelFormat.Format1bppIndexed);
        var pen = new Pen(Color.Black);
        var g = Graphics.FromImage(bitmap);
        g.DrawEllipse(pen,10,10,50,50);
        g.Dispose();
        this.pictureBox1.Image = bitmap;
    }

    The exception occurs as I want to get a graphics object from the image.

    Exception text (translated from German): "A graphic object can not be created from a image with indexed pixel format".

    What would be the best way to to draw to such a type of bitmap?

    Thanks for any hints or help!

    Regards
    Rainer

    Friday, February 22, 2013 10:36 AM

Answers

  • Convert it to a non-indexed bitmap,  draw on it and convert it back to an indexed bimap.
    • Marked as answer by Rainer Queck Saturday, February 23, 2013 8:45 AM
    Friday, February 22, 2013 3:37 PM
  • Part 1 -- Your exception

    Although there are pixel formats for 1bppIndexed, they are FILE formats, and not suitable for drawing.  Most drawing takes place to a 32-bits-per-pixel RGBA bitmap.  Render targets should be of a canonical format.  Then when you want to SAVE the bitmap to a stream, you can encode it using a more efficient or compressed format.

    Alternatively, don't use System.Drawing.Graphics to manipulate such large images. It's not really intended to handle it, mostly because it is expected to be able to work closely with the display hardware at a moments notice and the display adapter is going to choke on the large buffers.

    It's not hard to draw an ellipse manually.  You could roll your own software renderer.  Do you need to leverage the GPU to accomplish this?  GPUs will choke on extremely large images.  Which brings me to part 2:

    Part 2 -- Regarding large images

    Work on the image in pieces.  Why does it need to be all in one piece?

    The operation that you are performing on the bitmap, can you do this in smaller chunks?  Like one row at a time?  Or one 256x256 rectangle at a time?  Most image processing algorithms have a "kernel size" and pixels outside the size of the kernel are not needed.  Many images can be processed row at a time or column at a time.  To scale this up to very large images you need to be able to work on a portion of your data at a time.

    For example, that ellipse you drew is pretty small (50x50), you only need to modify a small sub-rectangle of pixels.  The rest of your bitmap is largely untouched but for the fact that you try to display it, which brings me to part 3:

    Part 3 -- Displaying large images

    This all falls apart if you expect to get a PictureBox control to be responsible for the large image.  It's going to handle some modest size of images, like 32k x 32k and then fall apart when they are bigger than that.  You'll have to construct a bitmap of the visible portion of your image, or down-sample it for display.

    • Marked as answer by Rainer Queck Saturday, February 23, 2013 8:44 AM
    Friday, February 22, 2013 5:20 PM
  • Hi John,

    it is not a monitor, it is a industrial 3D printer and I am trying to figure out on how to process that size of images....

    Anyhow, thank you for your efforts.

    Regards
    Rainer

    Not a raster based device.  Record GDI graphics in a metafile. 

    • Marked as answer by Rainer Queck Saturday, February 23, 2013 11:45 AM
    Saturday, February 23, 2013 9:07 AM

All replies

  • "What would be the best way to to draw to such a type of bitmap?"

    The only way to "draw" to an indexed bitmap is to alter the pixel bits directly using LockBits or Unsafe code.

    Friday, February 22, 2013 11:36 AM
  • Hi John,

    thank you for helping me!

    That sounds very inconvenient, especially if you have to draw polygons and fill them...

    Is there really no easier way?

    Regards
    Rainer

    Friday, February 22, 2013 2:59 PM
  • Convert it to a non-indexed bitmap,  draw on it and convert it back to an indexed bimap.
    • Marked as answer by Rainer Queck Saturday, February 23, 2013 8:45 AM
    Friday, February 22, 2013 3:37 PM
  • Hi John,

    the idea sounds good, but....

    A Format1bppIndexed bitmap with the size of 100000x100000 pixels uses up 1GB of memory. If I try any other format, I run into a out of memory exception.

    May be a bitmap is not the right choice? But what else can I use for a very large image which requires this precision (1Meter x 1Meter resolution 0.01 mm)?

    Are there any guidelines available on how to handle such big Images?

    Regards
    Rainer

    Friday, February 22, 2013 4:21 PM
  • That's quite a monitor.  Contact the manufacturer for assistance.  Usually large maps are displayed as tiles on a monitor that is much smaller than the image.
    Friday, February 22, 2013 4:25 PM
  • Hi John,

    it is not a monitor, it is a industrial 3D printer and I am trying to figure out on how to process that size of images....

    Anyhow, thank you for your efforts.

    Regards
    Rainer

    Friday, February 22, 2013 4:36 PM
  • Part 1 -- Your exception

    Although there are pixel formats for 1bppIndexed, they are FILE formats, and not suitable for drawing.  Most drawing takes place to a 32-bits-per-pixel RGBA bitmap.  Render targets should be of a canonical format.  Then when you want to SAVE the bitmap to a stream, you can encode it using a more efficient or compressed format.

    Alternatively, don't use System.Drawing.Graphics to manipulate such large images. It's not really intended to handle it, mostly because it is expected to be able to work closely with the display hardware at a moments notice and the display adapter is going to choke on the large buffers.

    It's not hard to draw an ellipse manually.  You could roll your own software renderer.  Do you need to leverage the GPU to accomplish this?  GPUs will choke on extremely large images.  Which brings me to part 2:

    Part 2 -- Regarding large images

    Work on the image in pieces.  Why does it need to be all in one piece?

    The operation that you are performing on the bitmap, can you do this in smaller chunks?  Like one row at a time?  Or one 256x256 rectangle at a time?  Most image processing algorithms have a "kernel size" and pixels outside the size of the kernel are not needed.  Many images can be processed row at a time or column at a time.  To scale this up to very large images you need to be able to work on a portion of your data at a time.

    For example, that ellipse you drew is pretty small (50x50), you only need to modify a small sub-rectangle of pixels.  The rest of your bitmap is largely untouched but for the fact that you try to display it, which brings me to part 3:

    Part 3 -- Displaying large images

    This all falls apart if you expect to get a PictureBox control to be responsible for the large image.  It's going to handle some modest size of images, like 32k x 32k and then fall apart when they are bigger than that.  You'll have to construct a bitmap of the visible portion of your image, or down-sample it for display.

    • Marked as answer by Rainer Queck Saturday, February 23, 2013 8:44 AM
    Friday, February 22, 2013 5:20 PM
  • Hello Wyck,

    thank you very much for your detailed explanation! I has put my thinking into - what I believe - a better direction.

    Part 2:

    You are right, processing the image in smaller chunks sounds much more reasonable. Especially in my case where I need to "map" a very large 2D image to a "print head stream". One could describe my task to print this very large image on very large paper with a ink-jet print head. I will have to investigate on how to do this. Any links to books, tutorials, ... concerning this subject are very welcome!

    Part 3:

    Although it is not my main task, there will be the need to some how visualize these large images on the screen. Down-sampling the image and applying some zoom functionality sounds like a good way here as well. Again, any links to books, tutorials.... on this subject is very welcome!

    Best Regards
    Rainer

    Saturday, February 23, 2013 8:44 AM
  • Hi John,

    it is not a monitor, it is a industrial 3D printer and I am trying to figure out on how to process that size of images....

    Anyhow, thank you for your efforts.

    Regards
    Rainer

    Not a raster based device.  Record GDI graphics in a metafile. 

    • Marked as answer by Rainer Queck Saturday, February 23, 2013 11:45 AM
    Saturday, February 23, 2013 9:07 AM
  • Hi John,

    thanks once more for your help!

    I just investigated a little into "Record GDI graphics" an Mr. Google gave me the link: Working with Metafile Images

    This looks like a solution to "Part 3" (ref answer from Wyck).

    But how about the mapping to a "print head" (ref Part 2)? How would I "process" the vector graphic to extract the "pixels"? Well I guess, I need to dig a little deeper into metafile based images....

    Best Regards
    Rainer


    • Edited by Rainer Queck Saturday, February 23, 2013 11:47 AM
    Saturday, February 23, 2013 11:44 AM
  • That sounds like a fairly expensive piece of equipment.  Shouldn't you be contacting the manufacturer for assistance?
    Saturday, February 23, 2013 12:04 PM
  • Hi John,

    not too long ago I got employed by the manufacturer ;-)
    We are currently exploring new ways. One branch on this way is going from C++ -> C# and an other is on how we want to process the print-data.

    Regards
    Rainer

    Saturday, February 23, 2013 1:52 PM