I want to remove parts of a previously filled shape with Cairo and C++.
Consider the following MWE:
void test(cairo_t *cr){
cairo_set_source_rgb(cr, 1, 1, 1);
cairo_paint(cr); //background
cairo_rectangle(cr, 50, 50, 150, 150);
cairo_set_source_rgb(cr, 0, 0, 1);
cairo_fill(cr); //first rect
cairo_set_operator(cr,CAIRO_OPERATOR_CLEAR);
cairo_arc(cr, 100, 100, 100, 0, M_PI * 2);
cairo_fill(cr); //circle that show remove a part of the rect
}
It results in the following picture:
According to the documentation I would have expected no black color at all, and all parts of the blue rectangle, that are under the circle to become removed (and therefore white as the background).
Did I misunderstand the operator? Did I make any mistake?
How would cairo know what you consider the background?
The documentation that you link to mentions that the alpha channels and all color channels are set to 0. This is fully transparent black.
The example in the documentation is an image with an alpha channel and thus the cleared parts become transparent.
You are using an image without an alpha channel and thus the cleared parts become black.
Related
I have multi images/bitmaps whose background is white color, now I want to draw these to render target one by one without copy white color. I tried to achieve:
SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_MIN), reference D2D1_PRIMITIVE_BLEND enumeration, but the non-white pixels of the image who draw late will not cover the before image, intersection will show another color.
_deviceContext->SetPrimitiveBlend(D2D1_PRIMITIVE_BLEND_MIN);
_deviceContext->BeginDraw();
_deviceContext->Clear(D2D1::ColorF(D2D1::ColorF::White));
_deviceContext->DrawBitmap(Bkg, D2D1::RectF(0, 0, _width, _height), 1.0);
_deviceContext->DrawBitmap(Img1, D2D1::RectF(0, 0, _width, _height), 1.0);
_deviceContext->DrawBitmap(Img2, D2D1::RectF(0, 0, _width, _height), 1.0);
hr = _deviceContext->EndDraw();
then I tried another method as example Direct2D composite effect modes sample, it works fine for only one foreground image and one background image. But I need draw multi foreground images.
_deviceContext->CreateEffect(CLSID_D2D1Blend, &_EffectBlend);
_deviceContext->CreateEffect(CLSID_D2D1ColorMatrix, &_EffectFore);
_deviceContext->CreateEffect(CLSID_D2D1ColorMatrix, &_EffectBack);
_EffectBlend->SetValue(D2D1_BLEND_PROP_MODE, D2D1_BLEND_MODE_DARKER_COLOR);
_EffectBlend->SetInputEffect(0, _EffectBack);
_EffectBlend->SetInputEffect(1, _EffectFore);
_EffectBack->SetInput(0, Bkg);
_EffectFore->SetInput(0, Img1);
_deviceContext->BeginDraw();
_deviceContext->Clear(D2D1::ColorF(D2D1::ColorF::White));
_deviceContext->DrawImage(_EffectBlend, D2D1_INTERPOLATION_MODE_LINEAR);
_deviceContext->EndDraw();
I have an image in which pixels above a certain value I'd like to turn red, and pixels below a certain value I'd like to turn blue.
So far, I can get a matrix of red pixels, and a matrix of blue pixels by using thresholding, and bitwise operators to set the pixel value:
cvtColor(displayImage, displayImage, COLOR_GRAY2BGR);
threshold(displayImage, highThresh, highThreshVal, 255, 0);
highThresh = highThresh & Scalar(0, 0, 255); // Turn it red
threshold(displayImage, lowThresh, lowThreshVal, 255, 1);
lowThresh = lowThresh & Scalar(255, 0, 0); // Turn it blue
displayImage = lowThresh + highThresh;
When I display the displayImage, I see almost exactly what I want. It's an image where all the pixels below lowThreshVal are blue, and all pixels above highThreshVal are red. However, the pixels that are in between these values are all set to 0. Whereas, I would like to show the original image overlayed with the blue and red images. I'm not sure how to do this, or if I'm taking the best approach.
I know I can't add the images because I want to make sure every pixel above the threshold is pure red, not a mix of red and the original image, this yields pink-ish pixels instead of bright red pixels, which defeats the purpose of what I'm trying to build. But as of right now, I'm kind of stuck on what to do.
This worked.
cvtColor(displayImage, displayImage, COLOR_GRAY2BGR);
origImage = displayImage.clone();
threshold(origImage, highThresh, highThreshVal, 255, 0); // Binary thresholding
cvtColor(highThresh, highThresh, CV_BGR2GRAY);
displayImage.setTo(Scalar(0, 0, 255), highThresh);
threshold(origImage, lowThresh, lowThreshVal, 255, 1); // Binary thresholding
cvtColor(lowThresh, lowThresh, CV_BGR2GRAY);
displayImage.setTo(Scalar(255, 0, 0), lowThresh);
I draw a circle filled yellow (0-width border) and, on top of it, a circle filled grey (0-width border) with the same center and the same size as the yellow circle.
How come I can still see a very thin yellow boundary around my grey circle? Interestingly, if I switch the circles around (i.e. put the yellow circle on top), then the grey circle is completely hidden as it should be.
How can I make sure that the two circles are exactly the same?
Here is the drawing code:
cairo_push_group(cr);
cairo_set_line_width(cr, 0.0);
// The yellow circle
cairo_set_source_rgb(cr, (double)0xff/255, (double)0xfd/255, (double)0x37/255);
cairo_arc(cr, 100, 100, 10, 0, 2 * M_PI);
cairo_fill(cr);
cairo_stroke (cr);
// The grey circle
cairo_set_source_rgb(cr, (double)0x97/255, (double)0x8a/255, (double)0x84/255);
cairo_arc(cr, 100, 100, 10, 0, 2 * M_PI);
cairo_fill(cr);
cairo_stroke (cr);
cairo_pop_group_to_source(cr);
Here's an example:
SDL_Color textcol = {255, 255, 255};
SDL_Color backtextcol = {0, 0, 0};
SDL_Surface *mes = TTF_RenderText_Shaded(font, "The game has begun", textcol, backtextcol);
apply_surface(40, 40, mes, screen);
SDL_Flip(screen);
Thanks to that example, we draw a black rectangle with white letters. Is it possible to draw just white letters with black inside without the whole black rectangle?
Yes it is possible. There are 3 main text-drawing functions in SDL_TTF:
TTF_RenderText_Solid - this one renders basic text(whitout background) and its fast, but its low-quality, and will look pixellated.
TTF_RenderText_Shaded - this one draws nice blended characters, but to a pre-defined background color
TTF_RenderText_Blended - this one draws a nice blended text, but it uses alpha-blending and its slow, but gives very nice results
I have been building a game in allegro 4.2.1 and need help to remove a specific color to make invisible. The background color is, (255, 0, 255). I have been at the following sites, but they have not helped me much:
http://www.allegro.cc/forums/thread/599210,
http://www.cpp-home.com/tutorials/258_1.htm
If someone could provide me with an example, I would be very glad.
You need to do the following things to enable transparent pixels:
Call set_color_depth(32) before calling set_gfx_mode()
Load your images after calling set_gfx_mode()
Use masked_blit() or draw_sprite() to draw the image.
If you do the above, all "magic pink" pixels (100% red, 0% green, 100% blue) will be treated as transparent.
BITMAP *bmp;
allegro_init();
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
clear_to_color(screen, makecol(0,0,0));
// once the video mode has been set, it is safe to create/load images.
// this bitmap will be 640x480 with pure pink.
bmp = create_bitmap(640, 480);
clear_to_color(bmp, makecol(255,0,255));
rectfill(bmp, 100,100, 200,200, makecol(255,255,255));
draw_sprite(screen, bmp, 0, 0);
// or
// masked_blit(bmp, screen, 0,0, 0,0, 640,480);