I'm using a self compiled of OpenCv 3.3 with OPENGL and CUDA enabled on Windows 7.
I'm having trouble to display an image in fullscreen mode without any border.
I use the following minimal example for my test:
// Name of window
std::string name = "Test Window";
// Create window
cv::namedWindow(name, CV_WINDOW_OPENGL | cv::WINDOW_NORMAL);
cvSetWindowProperty(name.c_str(), CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
// Create a frame at resolution
cv::Size size = cv::Size(1920, 1080);
cv::cuda::GpuMat emptyFrame;
cv::Mat frame(size, CV_8UC(3));
// Fill it in blue
cv::rectangle(frame, cv::Rect(0, 0, size.width, size.height), cv::Scalar(255, 0, 0), CV_FILLED);
emptyFrame.upload(frame);
// Size window to full resolution
cv::resizeWindow(name, size.width, size.height);
while(1)
{
// Display an empty frame
cv::imshow(name, emptyFrame);
cv::waitKey(40);
}
This code show me a full screen windows paint in blue, however it remain a ONE pixel border on top and left border:
Grey left and top border
The border seem not to be the border as explained here:
https://stackoverflow.com/a/38494752/1570628
In fact it's the background of the main window created by OpenCv.
Digging into OpenCv code, it effectivelly create 2 windows inside cvNamedWindow function:
mainhWnd = CreateWindow( "Main HighGUI class", name, defStyle | WS_OVERLAPPED, rect.x, rect.y, rect.width, rect.height, 0, 0, hg_hinstance, 0 );
if( !mainhWnd )
CV_ERROR( CV_StsError, "Frame window can not be created" );
ShowWindow(mainhWnd, SW_SHOW);
//YV- remove one border by changing the style
hWnd = CreateWindow("HighGUI class", "", (defStyle & ~WS_SIZEBOX) | WS_CHILD, CW_USEDEFAULT, 0, rect.width, rect.height, mainhWnd, 0, hg_hinstance, 0);
if( !hWnd )
CV_ERROR( CV_StsError, "Frame window can not be created" );
So the 'border' we saw is the mainhWnd (Main HighGUI class) color.
However, it mean that my displayed image in blue is shifted by one pixel to the rigth and bottom of my screen, so I loose 1 line of pixel on bottom and right side because they overflow the screen.
I can see that it's the case because on a dual screen I can see the right line of pixel overflow on my second screen. More over, if I draw an horizontal line to the last line of my image, it doesn't appear, same occur on vertical line for last column of my image.
For testing solution, I tried to change style of mainhWnd and hWnd directly in OpenCv code by using many combination of flags, also testing using WS_POPUP, but anyway I always have this top and left border.
I also tried solution here but it do not remove the border:
https://stackoverflow.com/a/6512315/1570628
Do anyone have a clue for my problem?
Regards.
Hey this worked for me (at least it did on python, and since you just have to change a flag, i believe this will work for you too)
Change this flag "CV_WINDOW_OPENGL | cv::WINDOW_NORMAL)" to this flag "WINDOW_FREERATIO"
And voila! Problem Solved
Related
I'm working on a MFC project with some GDI drawings.
I use DC.DrawText to draw a vertical text into a DC using a LOGFONT with lfEscapement = 900.
The text is output when i use DT_NOCLIP in the desired vertical formatting.
However to center this text i used a call to DC.DrawText with the DT_CALCRECT argument.
I recognized that, despite the text is indeed drawn vertically, the CRect has a larger width
than height.
My intuition says me that a vertical drawn text should have a larger height than width.
I did not include the calculation for centering the text. The question is just about what i can rely upon when i implement that vertical centering.
Does DC.DrawText with DT_CALCRECT ignore escapement?
void CMFCFontTestDlg::OnPaint()
{
CPaintDC dc(this); // Gerätekontext zum Zeichnen
if (IsIconic())
{
...
}
else
{
CDialogEx::OnPaint();
CRect clTextRect;
CFont myFont;
myFont.CreateFont(12, 0, 900, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, _T("Tahoma"));
CFont* oldFont = dc.SelectObject(&myFont);
dc.DrawText(_T("000000"), clTextRect, DT_CALCRECT);
clTextRect.MoveToXY(100, 100);
dc.DrawText(_T("000000"), clTextRect, DT_NOCLIP);
dc.SelectObject(oldFont);
}
}
I found out about it in the remarks to the DrawTextEx function
https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawtextexa.
However, please note that neither the documentation of DrawText does say anything about this nor the documentation of the DT_CALCRECT flag.
This is likely to be overseen if one uses DrawText and not DrawTextEx.
I informed MS about this via "Is this page helpful?" feedback possibility.
Remarks
The DrawTextEx function supports only fonts whose escapement and
orientation are both zero.
The text alignment mode for the device context must include the
TA_LEFT, TA_TOP, and TA_NOUPDATECP flags.
Considering this the solution is to use some trigonometric calculation starting from the size determined for escapement = 0 and then calculate the topleft and bottomright points of the rotated rect.
Symptoms
I'm having an issue with the recent version 2.0 of the Lato font in its "Regular" variant. This issue doesn't appear with Lato 1.0.
It seems that the underline is drawn 1px below the rectangle reported by DrawText() with the DT_CALCRECT flag.
In the following screenshots the calculated rectangle is indicated by the blue background. I've added 10px to the right of this rectangle so you can see the discrepancy to the position where the underline is drawn.
Lato 2.0 - underline is incorrectly drawn outside of rectangle reported by DT_CALCRECT:
Lato 1.0 - underline is correctly drawn inside of rectangle reported by DT_CALCRECT:
MCVE
can be reproduced on Win 10 and Win 7 (Win 8 not tested)
Download and install the Lato 2.0 Regular font (Lato-Regular.ttf).
Create a dialog based MFC application using the wizard and replace the OnPaint() handler of the dialog with the sample code.
Sample code for OnPaint():
CPaintDC dc{ this };
CRect rect; GetClientRect( &rect );
LOGFONTW lf{};
wcscpy_s( lf.lfFaceName, L"Lato" );
lf.lfHeight = 20 * 10; // tenths of a point
lf.lfWeight = FW_NORMAL;
lf.lfUnderline = TRUE;
CFont font;
VERIFY( font.CreatePointFontIndirect( &lf ) );
const int saved = dc.SaveDC();
dc.SelectObject( &font );
dc.SetBkMode( TRANSPARENT );
dc.SetTextColor( RGB( 0, 0, 0 ) );
const CString text = L"Hello Lato";
const DWORD dtFlags = 0;
// Calculate the size required by the text and fill this rectangle
CRect textRect = rect;
dc.DrawText( text, textRect, dtFlags | DT_CALCRECT );
textRect.right += 10;
dc.FillSolidRect( 0, 0, textRect.right, textRect.bottom, RGB( 180, 180, 255 ) );
// Actually draw the text
dc.DrawTextW( text, rect, dtFlags );
if( saved )
dc.RestoreDC( saved );
Question
Do you think this is an issue in my code, a bug in the OS or a bug in the font?
Unfortunately I can't just use Lato 1.0 as Lato 2.0 added support for many new languages my software needs to support.
I am trying to make a borderless window in Qt5.6.0, with aero-snap functionality.
Everything works, except when I maximize the window : it is too big.
My screen resolution is 2560x1440, so the window should be sized 2560x1400 (40 Pixels for the Taskbar), but in the WM_SIZE message, the new size is 2576x1416.
So the window is exactly 8 pixels too big in every direction.
This also means that the window is not aligned in the top-left corner, it is exactly 8 pixels off-screen in both directions.
I can't find a solution for this problem, everything I have tried doesn't work and causes bugs.
The only thing that fixes this is to remove the WS_CAPTION and WS_THICKFRAME styles, but then I lose the areo snap functionality.
I somehow have to tell Qt or DWM to make the window 16 pixels smaller and move it 8 pixels right, and bottom. Does anybody have an idea on how to do that?
I somehow have to tell Qt or DWM to make the window 16 pixels smaller
and move it 8 pixels right, and bottom. Does anybody have an idea on
how to do that?
DWM is Desktop Window Manager? Then the platform is Windows then.
As long as it is about Qt 5.6 and you very likely talking about the widget with Qt::CustomizeWindowHint attribute set then there is a known bug in Qt which is not fixed yet:
https://bugreports.qt.io/browse/QTBUG-4362
I stumbled upon that bug a couple of times and the workaround proposed by BiTOk at the link above worked for me.
My first try, was setting the window geometry to the available geometry:
QRect rect = QApplication::desktop()->availableGeometry();
setGeometry(rect.left() , rect.top(), rect.right(), rect.bottom());
The only Problem is that the window is a pixel too small on the right and bottom side and
setGeometry(rect.left() , rect.top(), rect.right() + 1, rect.bottom() + 1);
gives me an error:
QWindowsWindow::setGeometry: Unable to set geometry 2560x1400+0+0 on QWidgetWindow/'MainWindowWindow'. Resulting geometry: 2576x1416+-8+-8 (frame: 0, 0, 0, 0, custom margin: 0, 0, 0, 0, minimum size: 45x13, maximum size: 16777215x16777215)
Then I looked at the rectangle coordinates of Visual Studio 2015 and they are the same size as my implementation of a borderless window, 8 pixels larger in every direction.
I can give the contents of my window a margin of 8 so it doesn't clip out of the screen if the window is maximized and set the window region:
setContentsMargins({ 8, 8, 8, 8 });
HRGN WinRgn;
RECT winrect;
GetClientRect(hwnd, &winrect);
WinRgn = CreateRectRgn(8, 8, winrect.right - 8, winrect.bottom - 8);
SetWindowRgn(hwnd, WinRgn, true);
When the window gets restored, we need to reset the previous changes.
The result is:
case WM_SIZE:
WINDOWPLACEMENT wp;
wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(hwnd, &wp);
if (wp.showCmd == SW_MAXIMIZE) {
setContentsMargins({ 8, 8, 8, 8 });
HRGN WinRgn;
RECT winrect;
GetClientRect(hwnd, &winrect);
WinRgn = CreateRectRgn(8, 8, winrect.right - 8, winrect.bottom - 8);
SetWindowRgn(hwnd, WinRgn, true);
UpdateWindow(hwnd);
is_fullscreen = true;
} else {
if (is_fullscreen) {
setContentsMargins({ 0, 0, 0, 0 });
SetWindowRgn(hwnd, NULL, true);
is_fullscreen = false;
}
}
break;
Other posts have already answered the question, but I would just like to add that it might be a good idea to use GetSystemMetrics rather than a hard-coded value of 8.
Example
#include <Windows.h>
void MyWindow::changeEvent(QEvent* ev) {
if (ev->type() == QEvent::WindowStateChange) {
const auto state = windowState();
if(state & Qt::WindowMaximized) {
const int x = GetSystemMetrics(SM_CXFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
const int y = GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
setContentsMargins({x, y, x, y});
}
else {
setContentsMargins({0, 0, 0, 0});
}
}
Like attached my photo, I want to get "Windowed Window's Screen coordinate of each Corner in X-window". (I draw red dots, which I want to get as Screen coordinates, in the following image. What I am going to do later is to get exact middle point of my OpenGL window in 2D screen coordinate.
I tried following code already:
int* getWindowPos(Display *dpy) {
int winPos[2];
Window myWin;
myWin = XRootWindow(dpy, 0);
XWindowAttributes xwa;
XGetWindowAttributes(dpy, myWin, &xwa);
// printf("%d %d\n", xwa.x, xwa.y);
return winPos;
}
but this "XWindowAttributes" always gives me 0 in x point ,0 in y point, and width 1600 and height 900, which is same as my screen resolution.
following is what I coded to create this windowed window.
GLWin.win = XCreateWindow(GLWin.dpy, RootWindow(GLWin.dpy, vi->screen),
0, 0, 800, 600, 0, vi->depth, InputOutput, vi->visual,
CWBorderPixel | CWColormap | CWEventMask, &GLWin.attr);
You're storing your window into GLWin.win, but are querying the root window for its size and location. The "root window" is the full screen background window (desktop), so it makes sense that it's returning your screen resolution. Just pass your actual window (GLWin.win) to XGetAttributes() if you want those dimensions.
I have to draw a String on a transparent bitmap at first, then draw A to destination canvas.
However on certain case, there is black border around the characters.
Bitmap* tempImg = new Bitmap(1000, 1000, PixelFormat32bppARGB);
Graphics tempGr(tempImg);
tempGr.Clear(Color(0, 255,255,255));
Gdiplus::SolidBrush* brush = new SolidBrush(Color(255, 255, 0, 0 ));
Gdiplus::FontFamily fontFamily(L"Times New Roman");
Gdiplus::Font* font = new Gdiplus::Font(&fontFamily, 19, FontStyleRegular, UnitPixel);
RectF rec(400, 400, 1000, 10000);
tempGr.DrawString(
L"Merry Chrismas",
-1,
font,
rec,
NULL,
brush
);
Graphics desGr(hdc);
desGr.Clear(Color::Gray);
desGr.DrawImage(tempImg , 0,0, 1000, 1000);
The character draw on desGr have black board for some fontsize.
How can I avoid this problem?
Many thanks!
I think the problem here is that you are drawing the text onto a transparent background.
You could try adding this line after the call to tempGr.Clear...
tempGr.TextRenderingHint = TextRenderingHint.AntiAlias;
ps - sorry not sure the exact syntax in C++ ;)
I just solved this problem in XNA:
Clear background to the same as the foreground color. The only difference is that the background should have Alpha=0, and the foreground with Alpha >> 0
The black border comes from blending of your background and foreground of different colors. Try to clear the background to some contrasting color to fully appreciate the phenomenon.