Solved

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

Posted on 2008-06-13
5
814 Views
Last Modified: 2013-12-04
Hi
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)?
thanks!
0
Comment
Question by:vsee
  • 2
5 Comments
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
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.
0
 

Author Comment

by:vsee
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!
0
 
LVL 39

Accepted Solution

by:
itsmeandnobodyelse earned 250 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?
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
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 learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

747 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now