Link to home
Start Free TrialLog in
Avatar of matth012098
matth012098Flag for United States of America

asked on

Accessing pixel data of a bitmap

I have recently come across the need to create some custom controls. One of these controls is basically an M x N area that has a bitmap blitted into it. However for speed reasons I am performing all rendering to an area of memory somewhere else at a colour depth of 8bpp. In order for my user to see what I am rendering to this off screen memory area I need to somehow copy this data to either:

a) The window that is going to display it
b) To a bitmap that I can then blit to the window

I also need to use this same techique to render bitmaps that the user loads from disk.

The software that I am currently creating is a tile map editor with custom functionality. The currently available editors will not handle what I need this editor to do, so I am forced to write my own. :(

So in summary I need:

1) Create a CBitmap from a chunk of memory at a colour depth of 8bpp. I guess I could use CBitmap::CreateBitmapIndirect()
2) Since I dont want to have to keep re-creating and destroying the above bitmap every time I change the off screen bitmap I need to find a way of somehow getting direct access to the pixel data of the created bitmap. However creating a CBitmap from a BITMAP copies the data pixel data and does not use the memory area as assigned in the BITMAP structure.

Since this software is not commercial I am willng to accept pointers to good already pre-written classes or libs that allow creation of a bitmap and allow direct access to its pixel data and / or palette for 8bpp modes. I've looked at CDIB but it doesn't appear to support the functionality that I need. Has anyone any experience with WinG, would this provide this kind of functioanlity, remembering that this is going to operate on parts of controls within dialogs?







Avatar of DanRollins
DanRollins
Flag of United States of America image

I'm not sure that I understand the entire question, but I will provide some background info and then try to address the numberd bullet items:

* There is a very simple way to get a bitmap to be displayed in a window.  Create a CSTATIC control and set its SS_BITMAP style.  Then you can call CStatic::SetBitmap and it will be displayed instantly.

* Because modern PCs are very fast and have lots of memory, you probably don't need to worry about double-buffering or manully doing off-screen manipulation.  Just waste some RAM by making temporary duplicates of the bitmaps.  Consider that even a huge 100K bitmap is using up only 1/2560-th (about 0.03%) of the computer's 256MB of RAM.  A drop in the bucket.

* You talk about directly accessing the binary image data.  That is rarely needed.  It is best to stick with GDI commands since they are so flexible.  Now I know of cases where "getting your hands dirty" with the individual bits can make sense (see http://home.earthlink.net/~danrollins/ee/FastBmpRotation.htm ) but you are usually best off use the wealth of drawing commands listed under the CDC class.

* You talk about 8-bpp images.  These turn out to be the hardest to manipulate because of the extra palette processing involved.  A good "getting started" idea would be to work with 24-bpp images until you get a real handle on the issues and techniques, then try switching to 8-bpp images so you can layer-in the palette stuff.

=-=-=-=-=-=-
>> 1) Create a CBitmap from a chunk of memory at a colour depth of 8bpp...

Just use CreateDIBitmap, followed by SetDIBits.  The CDIBSectionLite class at
   http://www.codeguru.com/bitmap/DIBSectionLite.shtml
and others code at
   http://www.codeguru.com/bitmap/index.shtml
will provide some useful utility to help you get started.  If you want some code to create a 256-color bitmap, just ask.

>> 2) Since I dont want to have to keep re-creating and destroying the above bitmap...

No need to create/destroy... just maintain that offscreen bitmap in a CMemoryDC.  Use BitBlt to transfer image data.  Anyway, creating/destroying is no big deal.  What's a couple of milliseconds between freinds?

>>However creating a CBitmap from a BITMAP copies the data pixel data and does not use the memory area as assigned in the BITMAP structure

This is where i think you are penny-wise and pound-foolish.  You need not (and should not) write to the actual storage area of the bitmap.  Instead, use BitBlt to transfer the bitmap data into a temporary CMemoryDC, use some GDI commands to modify it, then BitBlit it back.

=-=-=-=-=-=-=-=--=
Bitmap manipulation can be a complex issue and there is a steep learning curve involved.  Please feel free to ask for clarification on anything.

-- Dan
Avatar of matth012098

ASKER

I wrote a system that emulates some of the graphical capabilities of a well known 2D games console. I then wrote a very fast 3D game engine that runs under both emulation and on the target hardware. Unfortunately to create a game world that utilises this fast rendering engine I need to create a editor that allows editing of its specialised map data format. For this thing to work seamlessly I need to take the emulated render output and somehow map it to a window or bitmap. With this in mind I cannot use GDI to perform the texture mapping and what not that the source renderer does. I guess I could create a bitmap from the emulated render ouput (which is in 8 BPP, but I can convert this to the users current display colour resolution on the fly) and then blit that to the window.
This will however entail creating, blitting and deleting the bitmap each time the render output is changed. Is the process of creating, deleting the bitmap fast and will it cause the heap to become fragmented badly?


ASKER CERTIFIED SOLUTION
Avatar of DanRollins
DanRollins
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I've ended up creating my own CXBitmap class. This class basically keeps it's own area of pixel memory and a palette for palettised modes. The user can create any format bitmap that they like and gain direct access to its pixels / palette. Whenever changes are made the user calls Refresh() to convert the pixels to a CBitmap internally, or Refresh(CDC *pDC) to rebuild the whole bitmap that is compatible with the supplied DC. The class automatically converts the pixel memory area and palette to other colour depths during refresh.

Thanks for your help
Excellent!  If you run into any snags, feel free to make a post here.  I might be able to be more help.

-- Dan