Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


How to wrap an existing memory buffer as a DC for GDI

Posted on 2008-06-13
Medium Priority
Last Modified: 2013-12-04
I have a memory buffer corresponding to my screen resolution (1280x800 at 24-bits-per-pixel) that contains my screen contents at 24bpp. I want to convert this to 8-bpp (ie. Halftone color palette in Windows).
I currently do this:
1. Use CreateDIBSection to allocate a new 1280x800 24-bpp buffer and access it as a DC, as well as a plain memory buffer
2. Use memcpy to copy from my original buffer to this new buffer from step 1
3. Use BitBlt to let GDI perform the color conversion

I want to avoid the extra memcpy of step 2. To do this, I can think of two approaches:

a. Wrap my original mem buf in a DC to perform BitBlt directly from it

b. Write my own 24-bpp to 8-bpp color conversion. I can't find any info on how Windows implements this halftone color conversion. Besides even if I find out, I won't be using the accelerated features of GDI that BitBlt has access to.

So how do I do either (a) or (b)?
Question by:vsee
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
LVL 39

Expert Comment

ID: 21789166
To (1)

Here is an excerpt from MSDN regarding your issue
Managing Graphics
Whenever possible be sure to use PolyTextOut, PolyPolyline, PolylineTo, PolyDraw, PolyBezier, and PolyBezierTo functions. These functions exploit the fact that many drawing calls use identical attributes, and so multiple items can be drawn in a single call once the brushes, pens, colors, and fonts have been selected. For example, the console window uses PolyTextOut. This change reduced scrolling time in a console window by 30% when it was implemented during the development of Windows NT.

If you are writing an application that draws on the display, then theCreateDIBSection function can improve performance. This function allows you to share a memory section directly with the system, and thus avoid having it copied from your process to the system each time there is a change. Previously, a common practice was to call theGetDIBits function, make the required changes, then call theSetDIBits function. These steps were often repeated on different scan lines of the bitmap before the image was ready for updating. Using CreateDIBSection is much simpler.

One word of caution if you decide to use CreateDIBSection. You need to be sure that any calls that might affect your bitmap have completed before you start to draw in it. This is because the batching of GDI calls may cause their delayed execution. For example, suppose you make aPatBlt call to clear your bitmap, then you start to change the bits in your DIB section. If the PatBlt call was batched, it might not actually execute until after you start to make the bitmap changes. So, before you make changes to your DIB section, be sure to callGdiFlush if you have made changes to the bitmap with earlier GDI calls.

You see the CreateDIBSection is to make it faster (not slower as your question seem to imply). You could make the CreateDIBSection not allocating new memory by passing a handle to 'shared memory' allocated by CreateFileMapping. You actually wouldn't need a 'file' for this function but  could create memory only (you get a pointer to that memory by calling MapViewOfFile).
>>>> I can't find any info on how Windows implements this halftone color conversion.
Hmm. Any 8bpp color conversion was using a color palette. So, you could use 256 colors (8bit) out of 24-bit (16 millions) colors. But I don't know whether these colors are sufficient for that you want to do.

Author Comment

ID: 21818425
Hi itsme...
Thanks for your reply!
I didn't mean to imply CreateDIBSection is slow in general, it's certainly faster than GetDIBits/SetDIBits.
But for my purpose, as mentioned in original posting, there is an extra memcpy I'm seeking to avoid.

Could you give details of how to use CreateDIBSection with CreateFileMapping/MapViewOfFile. I'm new to memory-mapping and file-mapping, sorry. Remember, I aready have existing memory which I'm not free to create wherever convenient (It comes from another process, I can only read/write to it, not change its location).
thanks again!
LVL 39

Accepted Solution

itsmeandnobodyelse earned 1000 total points
ID: 21819679
>>>> Remember, I aready have existing memory
The memory you have is local memory accessible only in the (virtual) address space of your process and its thread. GDI cannot use it as it runs in a different address space. Hence, the only way to 'share' memory with GDI is to use the *same* global memory which individually was mapped to the local address space. So the general steps would be

1. call   CreateFileMapping with a unique name for the memory you want to reserve

gives a handle to a shared (global) memory region. Any process can get a handle as well by using the same name.

2. call MapViewOfFile to get a (local) pointer to the shared memory

The pointer points to an address in your local address space where the shared memory was mapped to

3. Use that pointer for storing the bitmap of your screen

4. Use the handle of the shared memory to force GDI to use the same memory

>>>> Could you give details of how to use CreateDIBSection with CreateFileMapping/MapViewOfFile

    /* allocate a segment of the swap file for shared memory 2*Size of ini file */    
    if (!(hMMFile = CreateFileMapping ((HANDLE)0xffffffff,    NULL,    PAGE_READWRITE,    0,    nFileSize * 2,    szMapFileName)))
           return FALSE;    
    /* map a view of this file for writing */    
     lpMMFile = (char *)MapViewOfFile (hMMFile, FILE_MAP_WRITE, 0, 0, 0);  

     unsigned char* pBits = NULL;
     HBITMAP hbmp = CreateDIBSection(hdc, pbmi,  DIB_PAL_COLORS, &pBits, hMMFile, 0);

Note, because of the handle to the shared memory you pass to CreateDIBSection, the returned pointer in pBits would point to the shared memory you provided, same as the lpMMFile pointer.

>>>> there is an extra memcpy I'm seeking to avoid.
That is not quite clear for me. The purpose of CreateDIBSection is to provide an allocation for a new bitmap associated to a DC. So, after calling CreateDIBSection the bits are empty and you have to copy an existing bitmap somehow to the memory. I can't see a way how you could force CreateDIBSection to not initialize the buffer but taking the contents you already had copied/set before. Why not simply change the order: first call CreateDIBSection, then get your screenshot and use the memory  CreateDIBSection has allocated?

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many modern programming languages support the concept of a property -- a class member that combines characteristics of both a data member and a method.  These are sometimes called "smart fields" because you can add logic that is applied automaticall…
Entering time in Microsoft Access can be difficult. An input mask often bothers users more than helping them and won't catch all typing errors. This article shows how to create a textbox for 24-hour time input with full validation politely catching …
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA.…

671 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question