I'm implementing a program that has lots of objects on the screens, sometime rectangles, but sometimes very complex structures of varying colours.
What is the best way to take a bitmap that has a mask and convert everything that isn't the mask to a colour of my choice (each object requires it's own colour in picking)
The way that I thought of is.
convert bitmap to image
converttomono
create another image that's all one colour(the picking one)
setmaskfromimage, using the white of the monoimage as the mask colour
then converting it to a bitmap
drawing the bitmap to the picking bitmap using a memorydc
Seems like a lot of conversions
Perhaps there is an easier way?
Best way to do picking? Topic is solved
-
- Filthy Rich wx Solver
- Posts: 236
- Joined: Thu Jan 29, 2009 3:33 pm
-
- Experienced Solver
- Posts: 99
- Joined: Wed Oct 17, 2007 2:01 am
Code: Select all
void MyClass::DrawBitmapToPickerDC(const wxBitmap& bmp,const wxColour& pickercolor,int x,int y)
{
// duplicate the bitmap
wxBitmap pickerbmp(bmp);
// slap it in a DC
wxMemoryDC dc;
dc.SelectObjectAsSource(pickerbmp);
// clear the image to be a solid color -- but this retains
// the selected mask.
dc.SetBackground(wxBrush(pickercolor));
dc.Clear();
// Do a transparent blit of this DC to the picker DC.
// mask will ensure only the desired pixels are drawn.
m_pickerdc.Blit(x,y,bmp.GetWidth(),bmp.GetHeight(),&dc,0,0,wxCOPY,true);
}
m_pickerdc would be a wxMemoryDC with a selected bitmap large enough to hold the entire surface area.
-
- Filthy Rich wx Solver
- Posts: 236
- Joined: Thu Jan 29, 2009 3:33 pm
Hmm... there is no :bowdown emoticon Thanks
Just a question about your code, why are you creating a new bitmap everytime, shouldn't you just dereference?
Also, is SelectObjectAsSource() something new? It's not in the wiki, nor is it recognized by my compiler. Did you mean SelectObject()?
Just a question about your code, why are you creating a new bitmap everytime, shouldn't you just dereference?
Also, is SelectObjectAsSource() something new? It's not in the wiki, nor is it recognized by my compiler. Did you mean SelectObject()?
Last edited by ninja9578 on Thu Feb 05, 2009 9:32 pm, edited 1 time in total.
-
- Experienced Solver
- Posts: 99
- Joined: Wed Oct 17, 2007 2:01 am
Glad I can help
If you don't need the wxBitmap anymore and it's not selected into any other DC, then yeah, by all means remove my bitmap copy and use 'bmp' directly rather than 'pickerbmp'.
I am passing the original bitmap by reference (wxBitmap&), but I'm creating a copy for the 'picker' image because I'd assume you wouldn't want this code to clear your original image (which it would). Drawing (or in this case clearing) the DC would modify the selected wxBitmap.ninja9578 wrote: Just a question about your code, why are you creating a new bitmap everytime, shouldn't you pass by reference?
If you don't need the wxBitmap anymore and it's not selected into any other DC, then yeah, by all means remove my bitmap copy and use 'bmp' directly rather than 'pickerbmp'.
I'm using wx 2.8.9 and it's included in the documentation here. I don't know whether or not it's a recent addition. SelectObject should work as well, though I think it doesn't reference count so it might require an additional copy. That's a bit of speculation though.Also, is SelectObjectAsSource() something new? It's not in the wiki, nor is it recognized by my compiler. Did you mean SelectObject()?
-
- Filthy Rich wx Solver
- Posts: 236
- Joined: Thu Jan 29, 2009 3:33 pm
Uh oh, seems that it's not solved.
Duplicating the bitmap doesn't prevent clear from changing the original bitmap as well. Why is this happening? I changed your code a little bit, but not much.
This is the code that is calling it (one of many)
I took a lot of fluff out of that method, but that's all of the drawing stuff.
Duplicating the bitmap doesn't prevent clear from changing the original bitmap as well. Why is this happening? I changed your code a little bit, but not much.
Code: Select all
void Picker::DrawToPicker(const wxBitmap & bmp, int ID, int x, int y){
// duplicate the bitmap
wxBitmap pickerbmp(bmp);
// slap it in a DC
wxMemoryDC dc;
dc.SelectObject(pickerbmp);
//create a colour of the identifier
int r = ID % 255;
int g = (ID >> 8) % 255;
int b = (ID >> 16) % 255;
wxColour pickercolour(r, g, b);
// clear the image to be a solid color -- but this retains
// the selected mask.
dc.SetBackground(wxBrush(pickercolour));
dc.Clear();
// Do a transparent blit of this DC to the picker DC.
// mask will ensure only the desired pixels are drawn.
PickerDC -> Blit(x,y,bmp.GetWidth(),bmp.GetHeight(),&dc,0,0,wxCOPY,true);
}
Code: Select all
//The bitmap which is the main rendering plane
wxBitmap bitmap;
bitmap = wxBitmap((int)AbsWidth.Value, (int)AbsHeight.Value);
//The device contexts for drawing to the bitmap and finally placing the bitmap on the scree
wxClientDC dc(drawingArea);
wxMemoryDC memdc;
memdc.SelectObject(bitmap);
if (!Transparent){
//Draw the background
wxc = wxColour(appearance -> BackgroundColour[0], appearance -> BackgroundColour[1], appearance -> BackgroundColour[2]);
memdc.SetBrush(wxBrush(wxc));
memdc.SetPen(wxPen(wxc, 1));
memdc.DrawRectangle(offset, offset, (int)AbsWidth.Value, (int)AbsHeight.Value);
} else { //make it transparent
wxc = wxColour(255, 0, 255);
memdc.SetBrush(wxBrush(wxc));
memdc.SetPen(wxPen(wxc, 1));
memdc.DrawRectangle(0, 0, (int)AbsWidth.Value, (int)AbsHeight.Value);
}
memdc.DrawText(wxString::FromAscii(part.c_str()), wxPoint((int)((long int)AbsWidth.Value - x + offset),ypos + offset));
//convert the bitmap to an image and set the mask for rotating (hot pink)
wxImage image = bitmap.ConvertToImage();
image.SetMaskColour(255,0,255);
image.SetMask();
//rotate the image
image = image.Rotate(-Rotation, wxPoint(image.GetWidth() / 2 + offset / 2, image.GetHeight() / 2 + offset / 2), !DebugMode);
//set it back to another bitmap and draw
wxBitmap bit2(&image);
Picker::DrawToPicker(bit2, UniqueIdentifier, (int)AbsLeft.Value, (int)AbsTop.Value);
dc.DrawBitmap(bit2, wxPoint((int)AbsLeft.Value - offset, (int)AbsTop.Value - offset), true);
-
- Experienced Solver
- Posts: 99
- Joined: Wed Oct 17, 2007 2:01 am
Most likely a reference counting problem. Now that I tried it I get the same problem with SelectObjectAsSource -- which I thought would prevent this problem.
Oh well.
wxBitmap bmppicker(bmp); <-- doesn't make a direct copy right away, it simply increases the reference count.
So the solution here is to manually create a copy of the bitmap to prevent it from reference counting. Try this instead:
Also for your ID conversion you'd probably want % 256 (or "& 0xFF"), not % 255. With %255, both IDs 0 and 255 will result in pure black.
Oh well.
wxBitmap bmppicker(bmp); <-- doesn't make a direct copy right away, it simply increases the reference count.
So the solution here is to manually create a copy of the bitmap to prevent it from reference counting. Try this instead:
Code: Select all
wxBitmap pickerbmp = bmp.GetSubBitmap(wxRect(0, 0, bmp.GetWidth(), bmp.GetHeight()));