CopySubresourceRegion incorrectly reports an error about the size of the source box? - directx-11

I have a source ID3D11Texture2D of size 2560x1440 (from a screenshot), a quarter of which (half width and height) I am copying into a staging ID3D11Texture2D surface created with a width of 1280 (=2560/2) and height of 720 (=1440/2) (as specified in D3D11_TEXTURE2D_DESC before calling ID3D11Device::CreateTexture2D()).
Calling..
ID3D11DeviceContext::CopySubresourceRegion(dst=staging, 0, 0, 0, 0, src=screenshot, 0, box={0,0,0,1281,721,1});
.. works fine (the staging surface contains all the data I expect), but the D3D11 debug layer reports the following error:
D3D11 ERROR: ID3D11DeviceContext::CopySubresourceRegion: When offset by the destination coordinates, pSrcBox does not fit on the destination subresource.
OffsetSrcBox = { left:0, top:0, front:0, right:1281, bottom:721, back:1 }.
DstSubresource = { left:0, top:0, front:0, right:1280, bottom:720, back:1 }.
[ RESOURCE_MANIPULATION ERROR #280: COPYSUBRESOURCEREGION_INVALIDSOURCEBOX]
Since the width and height of the staging (destination) surface are 1280 and 720, it looks to me like it's CopySubresourceRegion which is incorrectly working out DstSubresource as {0,0,0,1280,720,1} - instead of {0,0,0,1281,721,1} as I'd expect it to be (front and back are correct) - and then cheekily reporting that to me as an error - when it made the mistake.
I did double-check that D3D11_BOX was correct (the doc says "The values for right, bottom, and back are each one pixel past the end of the pixels that are included in the box region").
I do not want to mess around with offsets or create a staging surface with the wrong width and height (1281x721) just to make this error disappear, so I am correct in that this error is misleading, or am I unknowingly doing something wrong? (I'm still quite new at coding for D3D11.)

The answer is that I have been a bit stupid. The DstSubresource box (the destination in the staging surface) is indeed correct: it's 1280 pixels wide, so the pixels go from #0 to #1279 (and #1280 is the one pixel past the end).
Where I went wrong is in the specification of the source region, whose box I specified with:
left = 0;
top = 0;
right = width + 1;
bottom = height + 1;
As soon as I properly noticed that there was both "width" and "+1" together (same for the height), when it's always width = (right-left) of course and therefore wasn't the same, I realised my mistake.
So, it was nothing to do with being new at coding for D3D11, and everything to do with an inattention error.

Related

PsychToolBox GetImage doesn't save using given rect dimensions

I'm trying to save a cropped portion of the screen from my PTB experiment, but the Screen('GetImage',...) function is not working properly. Here is my code:
screenNumber = 0;
% Open screen with grey background
[w, rect] = Screen('OpenWindow', screenNumber,...
background,[], [], [],[],6);
[xCenter, yCenter] = RectCenter(rect);
sideLength = randi([100 175], 1);
baseRect = [0, 0, sideLength, sideLength];
% Center the frame
centeredRect = CenterRectOnPoint(baseRect, xCenter, yCenter);
%dot position
dots.x = randi([ round(xCenter - (sideLength/2))+15 round(xCenter + (sideLength/2))-15], 1, numeral);
dots.y = randi([round(yCenter - (sideLength/2))+15 round(yCenter + (sideLength/2))-15], 1, numeral);
%skipping code to move dots.x into dot_info.position for brevity
Screen('DrawDots',w, dot_info.position, dot_info.size,...
dot_info.colour, [], 2); %dots are drawn to center of screen
Screen('Flip', w);
% Save dot cue
%im = Screen('GetImage', w);
im = Screen('GetImage', w, centeredRect);
imwrite(im, filename);
The issue is that there should be a small square image, centered on the centeredRect rectangle, which contains the dots I've drawn. However, all I get is a correctly sized rectangle without the dots. If I save without passing the centeredRect parameter (commented out line), I get a saved picture of the whole screen, showing the dots in the center - so I know the dots are being drawn. There must be something wrong with the GetImage call and its use of the rect, such that its not saving from the center point of the screen, so i just get the background. When I run this on my monitor it works fine, but on my laptop it does not. Unfortunately I don't have access to my monitor now so I need to get this to work on my laptop. I've checked with a Screens() call and there is only one screen: screen 0 - my laptop screen.
Any help greatly appreciated. Thanks.
SOLVED: I'm not sure why this worked, but I had to multiply the elements in centeredRect by 2. Hoping this helps someone else in future.

Clip the video to fullly fill the screen in Android Auto

Now, I am developing our own Android Auto Project. I encountered an issue.
I added 3 supported VideoConfiguration. (1920 X 1080, 1280 X 720, 800 X 480)
Our in-car screen's size is 1920 X 720.
After I started my app in car, I noticed the cellphone informed us which the video output from the cellphone(or MD) was 1920 X 1080. I also set the view area as 1920 X 720, or in another way, the content area was 1920 X 720.
Finally, the projectional video was shown, but unfortunately, the video was stretched forcefully. All of those icons, texts were out of shape, as if my configuration was useless.
My question is, how can I adjust my parameters so that the projectional contents from MD can be shown properly.
I asked google's service desk, they told me to set the margin on top and bottom 180 respectively.
But I tried, as below,
VideoFrameRateType frameRate = (fps == 30) ? VideoFrameRateType.VIDEO_FPS_30 : VideoFrameRateType.VIDEO_FPS_60;
Protos.Insets.Builder insetsBuilder = Protos.Insets.newBuilder().setTop(180).setBottom(180);
UiConfig.Builder uiBuilder = UiConfig.newBuilder().setMargins(insetsBuilder);
VideoConfiguration.Builder builder = VideoConfiguration.newBuilder()
// .setUiConfig(uiBuilder)
.setCodecResolution(codecResolution)
.setFrameRate(frameRate)
.setWidthMargin(0)
.setHeightMargin(360)
.setDensity(213)
.setRealDensity(170)
.setVideoCodecType(MediaCodecType.MEDIA_CODEC_VIDEO_H264_BP)
.setDecoderAdditionalDepth(decoderAdditionalDepth)
.setViewingDistance(viewingDistance)
.setPixelAspectRatioE4(Math.round(pixelAspectRatio * 1e4f));
I tried to set heightMargin, or add UiConfig's setTop(180).setBottom(180), nothing could sort the problem out.
Or, is there anything I can do we I create MediaFormat format = MediaFormat.createVideoFormat programmatically?
I think I have already wrapped things up by myself.
First, we need to adjust our layout attributes, from match_parent to 1920px & 1080px.
Second, before we create a VedioConfiguration, we should new UiConfig and set its top & bottom to match your content area.

GetWindowRect returns a size including "invisible" borders

I'm working on an app that positions windows on the screen in a grid style. When Running this on Windows 10, there is a huge gap between the windows. Further investigation shows that GetWindowRect is returning unexpected values, including an invisible border, but I can't get it to return the real values with the visible border.
1) This thread suggests this is by design and you can "fix" it by linking with winver=6. My environment does not allow this but I've tried changing the PE MajorOperatingSystemVersion and MajorSubsystemVersion to 6 with no affect
2) That same thread also suggests using DwmGetWindowAttribute with DWMWA_EXTENDED_FRAME_BOUNDS to get the real coordinates from DWM, which works, but means changing everywhere that gets the window coordinates. It also doesn't allow the value to be set, leaving us to reverse the process to be able to set the window size.
3) This question suggests it's lack of the DPI awareness in the process. Neither setting the DPI awareness flag in the manifest, or calling SetProcessDpiAwareness had any result.
4) On a whim, I've also tried adding the Windows Vista, 7, 8, 8.1 and 10 compatibility flags, and the Windows themes manifest with no change.
This window is moved to 0x0, 1280x1024, supposedly to fill the entire screen, and when querying the coordinates back, we get the same values.
The window however is actually 14 pixels narrower, to take into account the border on older versions of Windows.
How can I convince Windows to let me work with the real window coordinates?
Windows 10 has thin invisible borders on left, right, and bottom, it is used to grip the mouse for resizing. The borders might look like this: 7,0,7,7 (left, top, right, bottom)
When you call SetWindowPos to put the window at this coordinates:
0, 0, 1280, 1024
The window will pick those exact coordinates, and GetWindowRect will return the same coordinates. But visually, the window appears to be here:
7, 0, 1273, 1017
You can fool the window and tell it to go here instead:
-7, 0, 1287, 1031
To do that, we get Windows 10 border thickness:
RECT rect, frame;
GetWindowRect(hwnd, &rect);
DwmGetWindowAttribute(hwnd, DWMWA_EXTENDED_FRAME_BOUNDS, &frame, sizeof(RECT));
//rect should be `0, 0, 1280, 1024`
//frame should be `7, 0, 1273, 1017`
RECT border;
border.left = frame.left - rect.left;
border.top = frame.top - rect.top;
border.right = rect.right - frame.right;
border.bottom = rect.bottom - frame.bottom;
//border should be `7, 0, 7, 7`
Then offset the rectangle like so:
rect.left -= border.left;
rect.top -= border.top;
rect.right += border.left + border.right;
rect.bottom += border.top + border.bottom;
//new rect should be `-7, 0, 1287, 1031`
Unless there is a simpler solution!
How can I convince Windows to let me work with the real window coordinates?
You are already working with the real coordinates. Windows10 has simply chosen to hide the borders from your eyes. But nonetheless they are still there. Mousing past the edges of the window, your cursor will change to the resizing cursor, meaning that its still actually over the window.
If you want your eyes to match what Windows is telling you, you could try exposing those borders so that they are visible again, using the Aero Lite theme:
http://winaero.com/blog/enable-the-hidden-aero-lite-theme-in-windows-10/
AdjustWindowRectEx (or on Windows 10 and later AdjustWindowRectExForDpi) might be of use. These functions will convert a client rectangle into a window size.
I'm guessing you don't want to overlap the borders though, so this probably isn't a full solution--but it may be part of the solution and may be useful to other people coming across this question.
Here's a quick snippet from my codebase where I've successfully used these to set the window size to get a desired client size, pardon the error handling macros:
DWORD window_style = (DWORD)GetWindowLong(global_context->window, GWL_STYLE);
CHECK_CODE(window_style);
CHECK(window_style != WS_OVERLAPPED); // Required by AdjustWindowRectEx
DWORD window_style_ex = (DWORD)GetWindowLong(global_context->window, GWL_EXSTYLE);
CHECK_CODE(window_style_ex);
// XXX: Use DPI aware version?
RECT requested_size = {};
requested_size.right = width;
requested_size.bottom = height;
AdjustWindowRectEx(
&requested_size,
window_style,
false, // XXX: Why always false here?
window_style_ex
);
UINT set_window_pos_flags = SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER;
CHECK_CODE(SetWindowPos(
global_context->window,
nullptr,
0,
0,
requested_size.right - requested_size.left,
requested_size.bottom - requested_size.top,
set_window_pos_flags
));
There are still two ambiguities in the above use case:
My window does have a menu, but I have to pass in false for the menu param or I get the wrong size out. I'll update this answer with an explanation if I figure out why this is!
I haven't yet read about how Windows handles DPI awareness so I'm not sure when you want to use that function vs the non DPI aware one
You can respond to the WM_NCCALCSIZE message, modify WndProc's default behaviour to remove the invisible border.
As this document and this document explain, when wParam > 0, On request wParam.Rgrc[0] contains the new coordinates of the window and when the procedure returns, Response wParam.Rgrc[0] contains the coordinates of the new client rectangle.
The golang code sample:
case win.WM_NCCALCSIZE:
log.Println("----------------- WM_NCCALCSIZE:", wParam, lParam)
if wParam > 0 {
params := (*win.NCCALCSIZE_PARAMS)(unsafe.Pointer(lParam))
params.Rgrc[0].Top = params.Rgrc[2].Top
params.Rgrc[0].Left = params.Rgrc[0].Left + 1
params.Rgrc[0].Bottom = params.Rgrc[0].Bottom - 1
params.Rgrc[0].Right = params.Rgrc[0].Right - 1
return 0x0300
}

PHP crop image - wrong area

On the clientside I have a jQuery script which I use to select a square area on the picture.
I got x1, y1 and width, height parameters. They are sent correctly to the server.
I want to crop image to this selection and then convert to PNG (although I tried both imagejpg, imagepng functions)
The code is (I use laravel 4):
$file = Input::file('picture');
$filename = md5(microtime()).'.png';
$image = imagecreatefromstring(file_get_contents($file->getRealPath()));
$crop = imagecreatetruecolor(Input::get('width'), Input::get('height'));
imagecopy($crop, $image, 0, 0, (int)Input::get('x1'), (int)Input::get('y1'), Input::get('width'), Input::get('height'));
imagepng($crop, public_path().'/uploads/pictures/'.$filename);
It works perfectly when height > width of original image. When I try to crop wide images (width > height) I got wrong area and it seems like x1,y1 are wrong (although they're not). I got right width/height, but wrong section.
What's wrong with the code above?
Solved. The problem was that client side didn't take into account original image size, it was scaled with CSS

GetObject() on bitmap handle from LoadImage() sometimes returns incorrect bitmap size

We are seeing an intermittent problem in which owner drawn buttons under Windows XP that are using a bitmap as a backdrop are displaying the bitmap incorrectly. The window containing multiple buttons that are using the same bitmap file for the bitmap image used for the button backdrop will display and most of the buttons will be correct though in some cases there may be one or two buttons which are displaying the bitmap backdrop reduced to a smaller size.
If you exit the application and then restart it you may see the same behavior of the incorrect display of the icon on the buttons however it may or may not be the same buttons as previously. Nor is this behavior of incorrect display of icons on the buttons always seen. Sometimes it shows and sometimes it does not. Since once we load an icon for a button we just keep it, once the button is displayed incorrectly it will always be displayed incorrectly.
Using the debugger we have finally found that what appears to be happening is that when the GetObject() function is called, the data returned for the bitmap size is sometimes incorrect. For instance in one case the bitmap was 75x75 pixels and the size returned by GetObject() was 13x13 instead. Since this size is used as part of the drawing of the bitmap, the displayed backdrop becomes a small decoration on the button window.
The actual source area is as follows.
if (!hBitmapFocus) {
CString iconPath;
iconPath.Format(ICON_FILES_DIR_FORMAT, m_Icon);
hBitmapFocus = (HBITMAP)LoadImage(NULL, iconPath, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
}
if (hBitmapFocus) {
BITMAP bitmap;
int iNoBytes = GetObject(hBitmapFocus, sizeof(BITMAP), &bitmap);
if (iNoBytes < 1) {
char xBuff[128];
sprintf (xBuff, "GetObject() failed. GetLastError = %d", GetLastError ());
NHPOS_ASSERT_TEXT((iNoBytes > 0), xBuff);
}
cxSource = bitmap.bmWidth;
cySource = bitmap.bmHeight;
//Bitmaps cannot be drawn directly to the screen so a
//compatible memory DC is created to draw to, then the image is
//transfered to the screen
CDC hdcMem;
hdcMem.CreateCompatibleDC(pDC);
HGDIOBJ hpOldObject = hdcMem.SelectObject(hBitmapFocus);
int xPos;
int yPos;
//The Horizontal and Vertical Alignment
//For Images
//Are set in the Layout Manager
//the proper attribute will have to be checked against
//for now the Image is centered on the button
//Horizontal Alignment
if(btnAttributes.horIconAlignment == IconAlignmentHLeft){//Image to left
xPos = 2;
}else if(btnAttributes.horIconAlignment == IconAlignmentHRight){//Image to right
xPos = myRect.right - cxSource - 5;
}else {//Horizontal center
xPos = ((myRect.right - cxSource) / 2) - 1;
}
//Vertical Alignment
if(btnAttributes.vertIconAlignment == IconAlignmentVTop){//Image to top
yPos = 2;
}else if(btnAttributes.vertIconAlignment == IconAlignmentVBottom){//Image to bottom
yPos = myRect.bottom - cySource - 5;
}else{//Vertical Center
yPos = ((myRect.bottom - cySource) / 2) - 1;
}
pDC->BitBlt(xPos, yPos, cxSource, cySource, &hdcMem, 0, 0, SRCCOPY);
hdcMem.SelectObject(hpOldObject);
}
Using the debugger we can see that the iconPath string is correct and the bitmap is loaded as hBitmapFocus is not NULL. Next we can see that the call to GetObject() is made and the value returned for iNoBytes equals 24. For those buttons that display correctly the values in bitmap.bmWidth and bitmap.bmHeight are correct however for those that do not the values are much too small leading to an incorrect sizing when drawing the bitmap.
The variable is defined in the class header as
HBITMAP hBitmapFocus;
As part of doing the research for this I found this stack overflow question, GetObject returns strange size and I am wondering if there is some kind of an alignment issue here.
Does the bitmap variable used in the call to GetObject() need to be on some kind of an alignment boundary? While we are using packed for some of our data we are using pragma directives to only specify specific portions of code containing specific structs in include files that need to be packed on one byte boundaries.
Please read this Microsoft KB how to load a bitmap with palette information. It has a great example as well.
On the side note: I do not see anywhere in your code where you call ::DeleteObject(hBitmapFocus). It is very important to call this, as you can run out of GDI objects very quickly.
It is always a good idea to use Windows Task manager to see that your program does not exhaust the GDI resources. Just add "GDI Objects" column to the Task Manager and see that the number of objects is not constantly increasing in your app, but stays within an expected range, similar to other programs

Resources