Drawing on 4-bit indexed images in GDI+ - windows

I am trying to draw some basic graphics primitives(line, rectangle etc.) using GDI+ apis on 4-bit indexed bitmaps. I am using Bitmap() functions for creating the bitmap and loading the bitmaps.
Bitmap myBitmap(100/*width*/,100/*height*/,PixelFormat4bppIndexed/*Pixel format*/);
Graphics graphics(&myBitmap);
SolidBrush brush(Color(255,128,0,0));
graphics.FillRectangle(&brush,0,0,100,100);
But this doesn't work(No Rectangle created).
What could be the problem? I tried manually using LockBits and modifying the bits manually, it works well, then why it doesn't work with Graphics gdi+ operations.

Finally I managed to solve my problem. To perform gdi+ operations using Graphics object on 4 bit indexed bitmap, we need to perform following steps.
Create 4bpp HBITMAP directly or load image from file using LoadImage.
If loading from 4bpp file, then load palette from file in HPALETTE object.
Create desktop compatible dc.
Select and realize you palette in newly created dc.
select HBITMAP in your dc.
Create Graphics object using your dc.
Perform GDI+ operations on 4bpp indexed.
Though I didnt try with 8bpp but I think similar operations can be performed on 8bpp also.
Hope this help others also.

Related

Understanding GetDiBits. C++

MSDN says that the bitmap used in GetDiBits should not be selected into a DC before calling this function. But from my experience(with BitBlt) I know that I cannot draw an a bitmap unless it is selected.
How does GetDiBits circumvents this? Can I just use an unselected, newly created bitmap as argument to this function?
GetDiBits as well CreateDibSection returns an array. But MSDN says about the first function:
"bits of the specified compatible bitmap"
I thought DI stands for DeviceIndependent. Why is there a contradiction? This means that, according to MSDN, GetDiBits can be used only with CreateCompatibleBitmap (which is DD)? Then I can't send this array to another machine to display it,right?
Both functions use a hDC. If CreateDibSection is truly DIndependent why does it need a hDC? All the needed info is provided through the bitmapinfoheader...
I cannot draw an a bitmap unless it is selected. How does GetDiBits circumvents this?
GetDIBits doesn't do any drawing. It reads pixel data from a bitmap and converts it into the desired color format. SetDIBits doesn't "draw" either, but it will set the pixel data in a bitmap.
Naming confusion.
The DI in GetDIBitmap refers to the fact that the pixel data is returned in a device-independent format (specifically, the one you ask for). The source bitmap can be a compatible bitmap or a device-independent bitmap.
Similarly SetDIBitmap takes device-independent pixel data and converts it to the type of the target bitmap.
These functions are confusingly named.
What's the DC for?
The DC is used to answer any questions about the pixel format on the device. For example, if the source format is a palette-based device-dependent bitmap, GetDIBits will assume the palette selected into the DC is the correct one. Note that the palette is not in the BITMAPINFOHEADER.
CreateDIBSection creates a hybrid bitmap that stashes data in a device-independent method, but may also keep a device-dependent copy in sync with it for performance. So it needs to know the DC of the intended device.

Creating a HBITMAP from an existing buffer

I have an existing buffer full of (DIB) bitmap data, i.e. width x height x 4 bytes (RGBA) in size. What I want to do is draw this bitmap to the screen, but looking at the CreateBitmap... / CreateDIB... functions, they don't appear to do what I'm looking for. I don't want to copy the memory in, I want to retain access to it, so I can continue to write to it in the next frame (without incurring a penalty for copying the data). Does such a method exist, or do I have to create a new bitmap and call SetDIBits on it?
If you want simple code, then you can use a BITMAP structure and assign it's bmBits to point to your actual image data (RGBA 8-Bit).
Then you can use GDI method
HBITMAP CreateBitmapIndirect(const BITMAP *pbm);
to create HBITMAP for displaying the image to screen.
But actually I think the system still do the copying while creating HBITMAP, that's why after CreateBitmapIndirect returns, you can safely free your image data.
But at least you only have to create the buffer once, and using it repeatedly as long as the size of the image doesn't change.
I use this method to display raw video from RED's Camera.
You can't write a DIB directly to a device context - you'll have to create a bitmap and copy the pixels in. Annoying, I know!
Looks like this question has a succinct way of doing that in the accepted answer.

any quick and easy way to capture a part of the screen? getPixel was slow and GetDIBits seemed a bit complcated as a start

I was trying some code to capture part of the screen using getPixel on Windows, with the device context being null (to capture screen instead of window), but it was really slow. It seems that GetDIBits() can be fast, but it seems a bit complcated... I wonder if there is a library that can put the whole region into an array, and pixel[x][y] will return the 24 bit color code of the pixel?
Or does such library exist on the Mac? Or if Ruby or Python already has such a library that can do that?
I've never done this but I'd try to:
Create a memory Device Context (DC)
using CreateCompatibleDC passing it
the Device Context of the desktop
(GetDC(NULL)).
Create a Bitmap (using
CreateCompatibleBitmap) the same
size as the region your capturing.
Select the bitmap into the DC you
created (using SelectObject).
Do a BitBlt from the
desktop DC to the DC you created (using SRCCOPY flag).
Working with Device Contexts can cause GDI leaks if you do things in the wrong order so make sure that you read the documentation on all the GDI functions you use (e.g. SelectObject, GetDC, etc.).

Pixel manipulation in Bitmap image using MFC

hi i created a dialogbox using MFC dialog..
using below url i displayed a bitmap picture in a dialog box.
http://www.functionx.com/visualc/applications/displaybitmap.htm
i have not write any code for that.i just added the bitmap Picture into import picture dialog box and used picture control and followed the tutorial...
when i run my application it displays image...
now i would like to know is it possible to do pixel manipulation using this image...
why i ask this means i have not write any code for the display of image...
pls clarify me in this regard....
Thanks a bunch
GetDIBits() and consorts is what you're after. Quite frankly, win32 image and DC manipulation is a rather advanced subject and you'll need to put in a lot more work than following a tutorial for getting it right. Start by reading the msdn docs for GetDIBits() and related functions, then read the relevant sections in the Petzold, then read all articles that mention GetDIBits() on codeproject.com. That should teach you enough to do low level bitmap manipulation.
Alternatively, phrase your question better (i.e., explain your problem and what you want to achieve) and maybe there's a quick and dirty fix that someone can offer you.
There is I recall a Win32 API to load and decode bitmaps.
Once you have the bitmap in memory an as RGB buffer, you can modify it. You will then need to emit the modified buffer as a new bitmap, which again the API will do for you.
Be aware of course that having a bitmap in memory where you then wish for example to increase the dimensions of the image will require appropriate buffer manipulation - there is no Win32 API for generalized bitmap editing.

Win32 CreatePatternBrush

MSDN displays the following for CreatePatternBrush:
You can delete a pattern brush without
affecting the associated bitmap by
using the DeleteObject function.
Therefore, you can then use this
bitmap to create any number of pattern
brushes.
My question is the opposite. If the HBRUSH is long lived, can I delete the HBITMAP right after I create the brush? IE: does the HBRUSH store its own copy of the HBITMAP?
In this case, I'd like the HBRUSH to have object scope while the HBITMAP would have method scope (the method that creates the HBRUSH).
The HBRUSH and HBITMAP are entirely independent. The handles can be deleted entirely independent from each other, and, once created, no changes to either object will effect the other.
The brush does have its own copy of the bitmap. This is easily see by deleting the bitmap after creating the brush and then using the brush (works fine)
Using GetObject to fill a LOGBRUSH structure will return the original BITMAP handle in member lbhatch, though, and not the copy's handle, unfortunately. And using GetObject on the returned bitmap handle fails if the bitmap is deleted.
Anyone any idea how to get the original bitmap dimensions from the brush in this case? I wish to create a copy of the pattern brush even though the original bitmap is deleted. I can get a copy of the original bitmap simply by painting with the brush, but I don't know it's size. I tried using SetbrushorgEx (hdc, -1,-1), hoping the -1's would be reduced modulo its dimensions when brush selected into device context and get values when I retrieve with GetBrushOrgEx. Doesn't work.
I think the bitmap must outlive the brush: the brush just references the existing bitmap rather than copying it.
You could always try it and see what happened.
I doubt that the CreatePatternBrush() API copies the bitmap you give it, since an HBITMAP is:
a GDI handle, the maximum number of which is limited, and
potentially quite large.
Win32 and GDI tend to be conservative about creating internal copies of your data, if only because when most of their APIs were created (CreatePatternBrush() dates to Windows 95, and many functions are older still), memory and GDI handles were in much more limited supply than they are now. (For example, Windows 95 was required to run well on a system with only 4MB of RAM.)

Resources