I was reading this article of codeproject.
and I would like to achieve the same fog text effect using gdi or gdi+. I am not concered about the scrolling and other features of this article, just the ability of apply a fog effect to the end of a text string
// Draws fog effect with help of gradient brush with alpha colors.
using (Brush br = new LinearGradientBrush(new Point(0, 0), new Point(0, this.Height),
Color.FromArgb(255, this.BackColor), Color.FromArgb(0, this.BackColor)))
{
e.Graphics.FillRectangle(br, this.ClientRectangle);
}
What are you after exactly - the example you gave already is gdi+.
If you want to apply a fog effect (gradient) to a line of text. First measure the bounding rect of the text, then create the brush to fit this rect and apply it above the text, or just use the brush to draw the text. If this is what you're after say so and I'll dig up some code.
Related
I am working on a project in C++ with Qt, and I am trying to find a way to apply a text shadow when drawing text on a QPixmap using QPainter.
I understand that QGraphicsDropShadowEffect is a thing, and I am using in other parts of my project, but I can't for the life of me find a way to apply a QGraphicsEffect when drawing with QPainter on a pixmap. Drawing the same text multiple times with different offsets and opacities doesn't quite cut it.
Are there any ways to do this?
If not, how could I go about making a function that does it, given a QGraphicsEffect to get the radius and color from?
Thanks in advance!
I don't think it is directly possible to "draw text with shadow", it is only possible to apply a shadow to something already drawn that would take in an element and use say its alpha channel to calculate the shadow.
You should use composition, either of the final products or during drawing. It should work if you use it on a text element. The other option would be to draw your text in black, apply Gaussian blur and then again draw the text on top of it with the desired offset.
Thanks for your answer ddriver, it made me search with some new keywords, which lead me to find a suiting solution for my project.
What I figured out is that you can simply create a QLabel with the text and effects you want (QGraphicsDropShadowEffect, in my case), and render it into a QPixmap using QWidget::grab(). You can then draw this new pixmap with QPainter as you would any other image, by converting your pixmap to a QImage and using QPainter's drawImage().
I have an application with two classes extending wxGLCanvas and one extending wxWindow. They implement 3 types of possible visualization of the user objects. Only one of them is displayed at the same time. The two wxGLCanvas contain a combination of an OpenGL scene plus some text superposed using wxPaintDC. The wxWindow draws everything using wxBufferedPaintDC.
Problem 1: In some machines, when exchanging from one wxGLCanvas to the other one, during the first rendering of the scene a background image is displayed just until the first rendered image appears. This background image I found out that comes from the wxGLCanvas background.
Problem 2:In the same machines where problem 1 appears, when using the function wxClientDC.Blit, instead of taking the OpenGL scene with the superposed text it is taking the wxGLCanvas background image (same as problem 1) with the superposed text; so it is taking the canvas context excluding the OpenGL scene. In the other machines the result of the screenshot is correct.
INFO: When I select the wxWindow view, where all is drawn using wxBufferedPaintDC, the background image of both, problem 1 and 2, is updated to the frame displayed by the wxWindow. If I now switch between wxGLCanvases I will see the "flash" of the wxWindow view.
Code to take screenshot (Inside class extending wxGLCanvas):
wxClientDC lv_contexteVue(this);
int lv_largeurVue;
int lv_hauteurVue;
lv_contexteVue.GetSize(&lv_largeurVue,&lv_hauteurVue);
wxBitmap lv_vue(lv_largeurVue,lv_hauteurVue);
wxMemoryDC lv_contexteAux;
lv_contexteAux.SelectObject(lv_vue);
lv_contexteAux.Blit(0,0,lv_largeurVue,lv_hauteurVue,&lv_contexteVue,0,0);
lv_vue.SaveFile(wxString(er_cheminSauvegarde.c_str(),wxConvLibc,er_cheminSauvegarde.size()),wxBITMAP_TYPE_BMP);
lv_contexteAux.SelectObject(wxNullBitmap);
Code to display scene OpenGL followed by the overlayed text (Inside class extending wxGLCanvas):
wxPaintDC dc(this);
//dc.Clear();
dc.SetBackground(*wxBLACK);
dc.SetBackgroundMode(wxSOLID);
dc.SetTextBackground(*wxBLACK);
dc.SetTextForeground(*wxWHITE);
SetCurrent(mv_contexte);
if (!mv_estInitialise)
{
initialiser();
mv_estInitialise = true;
}
Evenement lv_demandeDessin(DEMANDE_AFFICHAGE_2DPLUS);
mp_controleur->traiterEvenement(lv_demandeDessin);
SwapBuffers();
//dc.ClearCache();
wxColour lv_couleurEspaceLibre = *wxWHITE;
dc.SetBrush(wxBrush(lv_couleurEspaceLibre));
dc.SetPen(wxPen(lv_couleurEspaceLibre, 1));
//Overlay Text
wxSize screenSize = this->GetSize();
//dc.SetTextForeground(wxColour(240, 240, 240, 255));
wxFont font(8, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false);
dc.SetFont(font);
//dc.SetTextBackground(wxColour(0, 0, 0, 200));
string formated = ConstantesATLAS::FILIGRANE_PRE+Constantes::VERSION+Constantes::FILIGRANE_POS;
wxString mystring = wxString::FromAscii(formated.c_str());
//dc.DrawText(mystring,5,screenSize.GetY()-20);
dc.DrawText(mystring,5,5);
Answer from wxWidgets forum to the same question posted here, all credit for them :)
https://forums.wxwidgets.org/viewtopic.php?f=1&t=40288&e=0
Summary: do not mix OpenGL and wxPaintDC. To take screenshot of openGL with overlayed text there are two good posibilities:
1-Put the overlayed text with OpenGL, e.g. a superposed orthographic projection. Then take screenshot using the function glReadPixels().
2-If text is overlayed using the DC, to take screenshot, first ask OpenGL to return all the viewport in an array. Transform this array to wxImage, resuperpose the text in the image the same way it is superposed in the repaint event, use the dc.Blit function to copy the image.
I have a bitmap which background needs to be replaced with part of another bitmap. Everything works fine until I enable ClearFont on my WindowsXP.
In order to explain my problem better, let us label first bitmap as bmpDestination and second as bmpSource.
Here is how the bmpSource looks like :
Here is how bmpDestination looks like :
When ClearType is off, here is how the correct result looks like :
And here is the incorrect result of their combining when ClearType is on:
ClearType alters some parts of the text background color, so they aren't white anymore ( RGB( 255, 255, 255 ) ) but a combination of white and text color.
I am using BitBlt() and monochrome bitmap to create a mask, and to simulate transparency. I have tried using TransparentBlt() too, but got the same result.
How can I combine bmpSource and bmpDestination, when ClearType is enabled, so I can create correct result like above ?
Thank you for your help.
Best regards.
Render the treeview with black text on a white background. Use a font with grey-scale anti-aliasing. Don't use ClearType anti-aliasing. I'm moderately sure you can achieve this with one of the fdwQuality parameters to CreateFont, but I wouldn't swear to it.
Each pixel will have a shade of grey between white and black. You can interpret this as transparency. White is fully transparent; black is fully opaque. Use this information to create a bitmap with transparency. Render this transparent bitmap over your multi-coloured background.
I'm attempting to create a process manager based on QPixmaps. These pixmaps are updated via a timer callback at 20Hz, so it appears like they're spinning.
Below is a screenshot of my current window.
The pixmap is a 2D array with [20][14] elements. 20 is the amount of time slices, 14 is the process status indicator. I know, there are only 13 displayed here on the screen.
I'm currently using the painter object and composition modes to add QImages together with the following code:
QImage textImage(mapIcon.size(), QImage::Format_ARGB32);
QImage resultImage(mapIcon.size(), QImage::Format_ARGB32);
QPainter textPainter(&textImage);
textPainter.setCompositionMode(QPainter::CompositionMode_Source);
textPainter.fillRect(mapIcon.rect(), Qt::black);
textPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
textPainter.setFont(QFont("Arial", 8, QFont::Bold));
textPainter.setPen(QPen(Qt::white));
textPainter.drawText(QRectF(0, 0, mapIcon.width(), mapIcon.height()),
Qt::AlignCenter, name);
textPainter.end();
QPainter resultPainter(&resultImage);
resultPainter.setCompositionMode(QPainter::CompositionMode_Source);
resultPainter.drawImage(0, 0, mapIcon);
resultPainter.setCompositionMode(QPainter::CompositionMode_Exclusion);
resultPainter.drawImage(0, 0, textImage);
resultPainter.setRenderHint(QPainter::SmoothPixmapTransform, true);
resultPainter.setRenderHint(QPainter::HighQualityAntialiasing, true);
runnerIcons[x][y] = QPixmap::fromImage(resultImage);
My question is this: I don't want the inverted color scheme seen on the green labels, I want that color black. The white on black is ok, but the magenta isn't my favorite.
Is this possible in Qt? Or maybe ya'll have some suggestions to alternative solutions?
Thanks in advance.
There are a couple things you can do. You might check out the QPainter::setCompositionMode (mode) method. Maybe one of the other composition modes would be useful to you? Particularly QPainter::CompositionMode_Exclusion or QPainter::RasterOp_SourceXorDestination.
You could also use a complimentary color for the text. Magenta (blue+red) is opposite green on the color wheel. If you made the text magenta, it would probably show up well against both black and green. (I'm not saying it will look great - just that it will show up well.) Or maybe you could make the text 50% gray so that there is contrast in the luminance as well as in the color?
Also, you only have 13 icons, not 14. Not sure if it makes any difference.
I can't draw a pattern with a transparent background. This is my snippet :
bitmap.CreateBitmap(8, 8, 1, 1, &bits)
brush.CreatePatternBrush(&bitmap)
hbrush = pCgrCurrentDC->SelectObject(&brush);
// set text color
TextCol = pCgrCurrentDC->SetTextColor(CgrColourPalRGB);
int oldBkgrdMode = pCgrCurrentDC->SetBkMode(TRANSPARENT);
//draw polygon
pCgrCurrentDC->Polygon(CgrBuffer, n);
The doc on msdn doesn't mention anything about transparency. I guess this mode could be used? Or is this a bug ?
Thanks!
Mode TRANSPARENT means that background will not be filled before your brush is drawn. But your brush does not contain any transparent pixels in it and it redraws background pixels anyway. Fourth argument in CreateBitmap was set to 1 in your sample. That means bitmap is monochrome.
You need to use 32-bit bitmap to use transparency in brushes. GDI supports transparency with some limits. Use GDI+ for full transparency support.