How to draw on a 24/32bpp image and convert it to a 16bpp bitmap on a 16bpp system?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
User avatar
Parduz
Experienced Solver
Experienced Solver
Posts: 79
Joined: Fri Jan 30, 2015 1:48 pm
Location: Bologna, Italy

How to draw on a 24/32bpp image and convert it to a 16bpp bitmap on a 16bpp system?

Post by Parduz » Mon May 04, 2015 8:57 am

I'm developing a component. derived from wxPanel, that draws a complex gauge instrument. Right now i'm using standard DC methods (arcs, lines, rectangles and text), but in the future i need to have antialiased lines and arcs using the Wu algorityhm, so the whole control will be drawn "pixel per pixel".
For this reason, the whole code is written to use full RGB colors, so 24 or 32 bpp, even now that i'm using DC methods.
Under Windows it works flawlessy, but i need to compile it for a Debian distro running on a BeagleBone Black.
There, the system have a 16bpp and all i get right now, when not using standard "named" colors are black line, arcs and text.

How could i use 24 or 32bpp bitmap for my "off screen" drawings, and then convert the final result in a 16bpp bitmap to be painted on the panel/form surface?

User avatar
doublemax
Moderator
Moderator
Posts: 15176
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: How to draw on a 24/32bpp image and convert it to a 16bpp bitmap on a 16bpp system?

Post by doublemax » Mon May 04, 2015 10:12 am

You can use a wxMemoryDC to render into a 24 or 32 bit wxBitmap.

Can you build the "image" or "drawing" sample and check if they work correctly when the display is in 16bit mode?
Use the source, Luke!

User avatar
Parduz
Experienced Solver
Experienced Solver
Posts: 79
Joined: Fri Jan 30, 2015 1:48 pm
Location: Bologna, Italy

Re: How to draw on a 24/32bpp image and convert it to a 16bpp bitmap on a 16bpp system?

Post by Parduz » Mon May 04, 2015 1:28 pm

Sorry for not have been clear enough.
I already draw everything on wxMemoryDC.
Perhaps it is better to copy some pseudocode:
Constructor:

Code: Select all

BackImg         = new Img(bSize,true);
FaceImg         = new Img(bSize,true);
FBackBitmap     = new Bmp(*BackImg,wxBITMAP_SCREEN_DEPTH);
FFaceBitmap     = new Bmp(*FaceImg,wxBITMAP_SCREEN_DEPTH);
OnPaint:

Code: Select all

if (NeedRedraw) {
	RedrawGauge();
}
dc.DrawBitmap(*FFaceBitmap,0, 0, false);
Part of the RedrawGauge

Code: Select all

...
wxMemoryDC dc;
dc.SelectObject(Bitmap);

dc.SetPen(wxPen(0x0000FF00,FMin->m_NeedleWidth));
dc.DrawLine(wxPtStart,wxPtEnd);  // This gives me a green line on Windows, a black line on Linux

dc.SetPen(*wxRED_PEN);
dc.DrawLine(wxPtStart,wxPtEnd);  // This gives me a red line on both systems
...

If i change the constructor by forcing 24 or 32 bpp, instead of black lines/text/arcs i get nothing. All i can see is the background color (which is always pick from the parent).

Hope this answer your question, doublemax

User avatar
doublemax
Moderator
Moderator
Posts: 15176
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: How to draw on a 24/32bpp image and convert it to a 16bpp bitmap on a 16bpp system?

Post by doublemax » Mon May 04, 2015 1:42 pm

Code: Select all

dc.SetPen(wxPen(0x0000FF00,FMin->m_NeedleWidth));
What happens if you use this instead?

Code: Select all

dc.SetPen(wxPen( wxColour(0,255,0), FMin->m_NeedleWidth));
Also, please try to build and run the "image" and "drawing" sample and check if their screen output is correct.

I don't think there is anything wrong in your code. It's either in wxWidgets or something specific to the BeagleBone. Can you try your code under Linux on a normal PC?
Use the source, Luke!

User avatar
Parduz
Experienced Solver
Experienced Solver
Posts: 79
Joined: Fri Jan 30, 2015 1:48 pm
Location: Bologna, Italy

Re: How to draw on a 24/32bpp image and convert it to a 16bpp bitmap on a 16bpp system?

Post by Parduz » Mon May 04, 2015 2:42 pm

doublemax wrote:

Code: Select all

dc.SetPen(wxPen(0x0000FF00,FMin->m_NeedleWidth));
What happens if you use this instead?

Code: Select all

dc.SetPen(wxPen( wxColour(0,255,0), FMin->m_NeedleWidth));
It works! :shock:

Please let me say something before asking you some questions, in order to learn and understand:
Now, all my colors (they are like "properties" of my gauge) are defined by wxColour variables in the .h file like

Code: Select all

wxColour m_NeedleColor
and initialized in the constructor, or set by Setter functions, in this way:

Code: Select all

m_NeedleColor.SetRGB(0x00FF00);
or

Code: Select all

m_NeedleColor.SetRGB(<COLORREF variable>);
Also, all my functions uses COLORREF as type for colors (this 'cause i'm converting an old control made for and with Borland C++Builder 2006), so i started to get used to the "GetPixel()" method, and being a noob about wxWidgets, i used it also to pass the colors to the Drawsomething methods.
So, now my questions:
  • What's the inner difference between m_NeedleColor.SetRGB(0x00FF00) and m_NeedleColor = wxColour(0x00, 0xFF, 0x00)? Looking in the wxWidgets files is a bit convoluted for a noob, and i'm missing why the former "fails" (produces black on 16bpp system) and the latter succeeds.
  • Having colors treated as unsigned longs all around my code, how can i make them working, then?
doublemax wrote:Also, please try to build and run the "image" and "drawing" sample and check if their screen output is correct.
AH, i get you now, sorry. Compiled the "drawing" sample on te beaglebone, seems to me that sometimes it fails. I saw lots of black rectangles, so i thought it suffered of my same problem.
doublemax wrote:I don't think there is anything wrong in your code. It's either in wxWidgets or something specific to the BeagleBone. Can you try your code under Linux on a normal PC?
Sorry, i have no Linux PC: i could put up a virtual machine but being the Debian PC image different from the ARM one, i'll try to avoid the extra efforts given that i'll always had to try on the beaglebone anyway.
NOTE
This could be important: i had to manually define my own COLORREF (#define unsigned long COLOR_REF) because under linux MinGW complained about WXCOLORREF being not defined. I googled a bit and saw some past bug about it, but i'm in a real hurry and decided to avoid the hassle to solve this problem.
I'm using wxWidgets 3.0. ... ?
How can i know what i have apt-get and compiled on Debian (i'm a linux noob too :oops: ) in order to give you more infos?

Thanks for your fast replies

User avatar
doublemax
Moderator
Moderator
Posts: 15176
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: How to draw on a 24/32bpp image and convert it to a 16bpp bitmap on a 16bpp system?

Post by doublemax » Mon May 04, 2015 4:36 pm

What's the inner difference between m_NeedleColor.SetRGB(0x00FF00) and m_NeedleColor = wxColour(0x00, 0xFF, 0x00)? Looking in the wxWidgets files is a bit convoluted for a noob, and i'm missing why the former "fails" (produces black on 16bpp system) and the latter succeeds.
I don't know, but i don't think it has something to do with the 16bpp display. I suspect it has to do with the ARM architecture of the machine. But without being able to test this myself, i can't help any further.
Having colors treated as unsigned longs all around my code, how can i make them working, then?
First you have to find out why it fails.
Use the source, Luke!

Post Reply