BOOL SaveIconBmpToFile(HICON hIcon, LPCTSTR pszFile, COLORREF clrBkGnd ) { if (hIcon == NULL || pszFile == NULL) return FALSE; CClientDC dcDesk(GetDesktopWindow()); CIconHandle icon = hIcon; ICONINFO iconInfo = { 0 }; if ( !icon.GetIconInfo( &iconInfo ) ) return FALSE; CBitmapHandle bmpIcon = iconInfo.hbmColor; BITMAP bmpInfo = { 0 }; bmpIcon.GetBitmap(&bmpInfo); CBitmap bmp; bmp.CreateCompatibleBitmap( dcDesk, bmpInfo.bmWidth, bmpInfo.bmHeight); CDC dcMem; dcMem.CreateCompatibleDC( dcDesk ); HBITMAP hOldBmp = dcMem.SelectBitmap( bmp ); RECT rcBkGnd = { 0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight }; dcMem.FillSolidRect(&rcBkGnd , clrBkGnd); ::DrawIconEx( dcMem, 0, 0, hIcon, bmpInfo.bmWidth, bmpInfo.bmHeight, 0, NULL, DI_NORMAL ); dcMem.SelectBitmap( hOldBmp ); SaveBitmapToFile(dcMem, bmp, pszFile); //must delete bitmap object if (iconInfo.hbmColor) ::DeleteObject( iconInfo.hbmColor ); //must delete bitmap object if ( iconInfo.hbmMask ) ::DeleteObject( iconInfo.hbmMask ); return TRUE; }
//保存截图 void SaveScreen() { HBITMAP hbitmap=CopyScreenToBitmap(); TCHAR name[MAX_PATH]; SYSTEMTIME st; GetLocalTime(&st); // PengJiLin, 2010-6-7, GetCurrentDirectory()函数全部替代 //::GetCurrentDirectory(MAX_PATH,name); lstrcpy(name, CBcfFile::GetAppPath()); lstrcat(name,"\\截图"); ::CreateDirectory(name,NULL); wsprintf(name,TEXT("%s\\%d-%d-%d-%d-%d-%d.bmp"),name,st.wYear,st.wMonth,st.wDay,st.wHour,st.wMinute,st.wSecond); SaveBitmapToFile(hbitmap,name); }
void CCatchScreenDlg::SnapWholeScreen() { //截取屏幕到位图中 CRect rect(0, 0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN)); char szTempPath[MAX_PATH]={0} ; char filename[1024]={0} ; GetTempPath(sizeof(szTempPath), szTempPath) ; sprintf(filename, "%s/snapscreen.bmp" , szTempPath ) ; SaveBitmapToFile(CopyScreenToBitmap(rect,TRUE) , filename) ; if( atoi(__argv[1]) ) { char szCmd[1024]={0} ; sprintf(szCmd,"mspaint.exe %s" , filename) ; WinExec(szCmd,1) ; } PostQuitMessage(0); }
void CCatchScreenDlg::OnLButtonDblClk(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default int nHitTest; nHitTest=m_rectTracker.HitTest(point); if(nHitTest==8) { char szTempPath[MAX_PATH]={0} ; char filename[1024]={0} ; GetTempPath(sizeof(szTempPath), szTempPath) ; sprintf(filename, "%s/snapscreen.bmp" , szTempPath ) ; SaveBitmapToFile(CopyScreenToBitmap(m_rectTracker.m_rect,TRUE) , filename) ; if( atoi(__argv[1]) ) { char szCmd[1024]={0} ; sprintf(szCmd,"mspaint.exe %s" , filename) ; WinExec(szCmd,1) ; } PostQuitMessage(0); } CDialog::OnLButtonDblClk(nFlags, point); }
void CDuiAddFrame::SetInfo(int Type, LPWSTR lpFilePath, CDuiFrameWnd* pWnd) { m_pImage = static_cast<CButtonUI*>( m_PaintManager.FindControl(_T("DUI_BTN_IMAGE")) ); m_pPath = static_cast<CTextUI*>( m_PaintManager.FindControl(_T("DUI_TXT_PATH")) ); m_pType = static_cast<CComboUI*>( m_PaintManager.FindControl(_T("DUI_COMB_TYPE")) ); m_pShortCut = static_cast<CComboUI*>( m_PaintManager.FindControl(_T("DUI_TXT_SHORTCUT"))); if(m_pPath){ m_pPath->SetText(lpFilePath); } m_Type = Type; m_pWnd = pWnd; m_pType->SelectItem(m_Type - 1); ModifyShortCutComo(); HBITMAP hBitmap; // 获取图片 if(m_pImageList != NULL){ SHFILEINFOW sfi = {0}; SHGetFileInfo(lpFilePath, -1, &sfi, sizeof(sfi), SHGFI_SYSICONINDEX); HICON hIcon; HRESULT hResult = ((IImageList*)m_pImageList)->GetIcon(sfi.iIcon, ILD_TRANSPARENT, &hIcon); if(hResult == S_OK){ hBitmap = ConvertIconToBitmap(hIcon); if(SaveBitmapToFile(hBitmap, m_ImagePath.GetData())){ m_pImage->SetBkImage(m_ImagePath); } } } }
/// <summary> /// Handle new depth and color data /// <param name="nTime">timestamp of frame</param> /// <param name="pDepthBuffer">pointer to depth frame data</param> /// <param name="nDepthWidth">width (in pixels) of input depth image data</param> /// <param name="nDepthHeight">height (in pixels) of input depth image data</param> /// <param name="pColorBuffer">pointer to color frame data</param> /// <param name="nColorWidth">width (in pixels) of input color image data</param> /// <param name="nColorHeight">height (in pixels) of input color image data</param> /// <param name="pBodyIndexBuffer">pointer to body index frame data</param> /// <param name="nBodyIndexWidth">width (in pixels) of input body index data</param> /// <param name="nBodyIndexHeight">height (in pixels) of input body index data</param> /// </summary> void CCoordinateMappingBasics::ProcessFrame(INT64 nTime, const UINT16* pDepthBuffer, int nDepthWidth, int nDepthHeight, const RGBQUAD* pColorBuffer, int nColorWidth, int nColorHeight, const BYTE* pBodyIndexBuffer, int nBodyIndexWidth, int nBodyIndexHeight, int nBodyCount, IBody** ppBodies) { if (m_hWnd) { if (!m_nStartTime) { m_nStartTime = nTime; } double fps = 0.0; LARGE_INTEGER qpcNow = {0}; if (m_fFreq) { if (QueryPerformanceCounter(&qpcNow)) { if (m_nLastCounter) { m_nFramesSinceUpdate++; fps = m_fFreq * m_nFramesSinceUpdate / double(qpcNow.QuadPart - m_nLastCounter); } } } WCHAR szStatusMessage[64]; StringCchPrintf(szStatusMessage, _countof(szStatusMessage), L" FPS = %0.2f Time = %I64d", fps, (nTime - m_nStartTime)); if (SetStatusMessage(szStatusMessage, 1000, false)) { m_nLastCounter = qpcNow.QuadPart; m_nFramesSinceUpdate = 0; } } // Make sure we've received valid data if (m_pCoordinateMapper && m_pColorCoordinates && m_pOutputRGBX && pDepthBuffer && (nDepthWidth == cDepthWidth) && (nDepthHeight == cDepthHeight) && pColorBuffer && (nColorWidth == cColorWidth) && (nColorHeight == cColorHeight) && pBodyIndexBuffer && (nBodyIndexWidth == cDepthWidth) && (nBodyIndexHeight == cDepthHeight)) { HRESULT hr = m_pCoordinateMapper->MapDepthFrameToColorSpace(nDepthWidth * nDepthHeight, (UINT16*)pDepthBuffer,nDepthWidth * nDepthHeight, m_pColorCoordinates); if (SUCCEEDED(hr)) { RGBQUAD c_green = {0, 255, 0}; // loop over pixel of the output for (int depthIndex = 0; depthIndex < (nDepthWidth * nDepthHeight); ++depthIndex) { // default setting source to copy from the background pixel const RGBQUAD* pSrc = (m_pBackgroundRGBX) ? (m_pBackgroundRGBX + depthIndex) : &c_green; BYTE player = pBodyIndexBuffer[depthIndex]; // if we're tracking a player for the current pixel, draw from the color camera if (player != 0xff) { // retrieve the depth to color mapping for the current depth pixel ColorSpacePoint colorPoint = m_pColorCoordinates[depthIndex]; // make sure the depth pixel maps to a valid point in color space int colorX = (int)(floor(colorPoint.X + 0.5)); int colorY = (int)(floor(colorPoint.Y + 0.5)); if ((colorX >= 0) && (colorX < nColorWidth) && (colorY >= 0) && (colorY < nColorHeight)) { // calculate index into color array int colorIndex = colorX + (colorY * nColorWidth); // set source for copy to the color pixel pSrc = m_pColorRGBX + colorIndex; } } // write output m_pOutputRGBX[depthIndex] = *pSrc; } // Draw the data with Direct2D m_pDrawCoordinateMapping->Draw(reinterpret_cast<BYTE*>(m_pOutputRGBX), cDepthWidth * cDepthHeight * sizeof(RGBQUAD)); if (m_bSaveScreenshot) { WCHAR szScreenshotPath[MAX_PATH]; // Retrieve the path to My Photos GetScreenshotFileName(szScreenshotPath, _countof(szScreenshotPath)); // Write out the bitmap to disk HRESULT hr = SaveBitmapToFile(reinterpret_cast<BYTE*>(m_pOutputRGBX), nDepthWidth, nDepthHeight, sizeof(RGBQUAD) * 8, szScreenshotPath); WCHAR szStatusMessage[64 + MAX_PATH]; if (SUCCEEDED(hr)) { // Set the status bar to show where the screenshot was saved StringCchPrintf(szStatusMessage, _countof(szStatusMessage), L"Screenshot saved to %s", szScreenshotPath); } else { StringCchPrintf(szStatusMessage, _countof(szStatusMessage), L"Failed to write screenshot to %s", szScreenshotPath); } SetStatusMessage(szStatusMessage, 5000, true); // toggle off so we don't save a screenshot again next frame m_bSaveScreenshot = false; } } } D2D1_POINT_2F center; center.x = 400.0; center.y = 100.0; int width = 0; int height = 0; if (m_pCoordinateMapper) { RECT rct; GetClientRect(GetDlgItem(m_hWnd, IDC_VIDEOVIEW), &rct); width = rct.right; height = rct.bottom; DWORD clipedge = 0; for (int i = 0; i < nBodyCount; ++i) { IBody* pBody = ppBodies[i]; if (pBody) { BOOLEAN bTracked = false; HRESULT hr = pBody->get_IsTracked(&bTracked); // Engaged()は使えるみたい。これは、視野に入ってきた人を認識するものだろう。 //hr = pBody->get_Engaged(&nEngaged[i]); // 以下はまだ使えないようだ //hr = pBody->GetAppearanceDetectionResults((UINT)i, &nEngaged[i]); pBody->get_ClippedEdges(&clipedge); if (SUCCEEDED(hr) && bTracked) { Joint joints[JointType_Count]; D2D1_POINT_2F jointPoints[JointType_Count]; HandState leftHandState = HandState_Unknown; HandState rightHandState = HandState_Unknown; pBody->get_HandLeftState(&leftHandState); pBody->get_HandRightState(&rightHandState); hr = pBody->GetJoints(_countof(joints), joints); if (SUCCEEDED(hr)) { for (int j = 0; j < _countof(joints); ++j) { jointPoints[j] = BodyToScreen(joints[j].Position, width, height); } m_pDrawCoordinateMapping->DrawBody(joints, jointPoints); // ここに頭部に丸を描いて、ボディ番号を表示 m_pDrawCoordinateMapping->DrawHead(jointPoints[JointType_Head], i, clipedge/*, nEngaged[i]*/); m_pDrawCoordinateMapping->DrawHand(leftHandState, jointPoints[JointType_HandLeft]); m_pDrawCoordinateMapping->DrawHand(rightHandState, jointPoints[JointType_HandRight]); // 手先がある領域にきたら実行 // ボタンのような // 現状、複数人が認識されても実行するので、本来は最初に認識された一人のみにする必要がある。 float xy[2] = { 0.0 }; xy[0] = jointPoints[JointType_HandTipRight].x - center.x; xy[1] = jointPoints[JointType_HandTipRight].y - center.y; m_nButton = 0; if (sqrt(xy[0] * xy[0] + xy[1] * xy[1]) < 50.0) { m_nButton = 1; } m_pDrawCoordinateMapping->DrawButton(center, m_nButton); } } } } m_pDrawCoordinateMapping->EndDraw(); } }
LRESULT CDebugView::OnCaptrueTreeOpened(){ OPENFILENAME ofn ; ofn.lStructSize = sizeof (OPENFILENAME) ; ofn.hwndOwner = NULL ; ofn.hInstance = NULL ; ofn.lpstrFilter = _T("bmp"); ofn.lpstrCustomFilter = NULL ; ofn.nMaxCustFilter = 0 ; ofn.nFilterIndex = 0 ; ofn.nMaxFile = MAX_PATH ; ofn.nMaxFileTitle = MAX_PATH ; ofn.lpstrInitialDir = NULL ; ofn.lpstrTitle = NULL ; ofn.nFileOffset = 0 ; ofn.nFileExtension = 0 ; ofn.lpstrDefExt = 0; ofn.lCustData = 0L ; ofn.lpfnHook = NULL ; ofn.lpTemplateName = NULL ; TCHAR szFileName[MAX_PATH], szFileTitle[MAX_PATH]; *szFileTitle = 0; *szFileName = 0; //strcpy(szFileName,".bmp"); ofn.hwndOwner = GetGUI()->GetHwnd(); ofn.lpstrFile = szFileName ; ofn.lpstrFileTitle = szFileTitle ; ofn.Flags = OFN_OVERWRITEPROMPT ; if(!::GetSaveFileName (&ofn)){ int ret = ::GetLastError(); return 0; } tstring FileName = szFileName; FileName+=_T(".bmp"); OpenAllTree(); Layout(FALSE); RECT rcOld; ::GetClientRect(GetHwnd(),&rcOld); ::SetWindowPos(GetHwnd(),HWND_TOP,0,0,m_SizeX,m_SizeY,SWP_NOZORDER|SWP_NOMOVE|SWP_NOREDRAW); RECT rc; ::GetClientRect(GetHwnd(),&rc); HDC hDC = ::GetDC(GetHwnd()); HBITMAP hBmpCapture = CreateCompatibleBitmap(hDC,m_SizeX,m_SizeY); HDC DCMem = ::CreateCompatibleDC(hDC); HBITMAP OldBitmap = (HBITMAP)::SelectObject(DCMem, hBmpCapture); if(m_State & SPACE_SHOWBKG){ FillRect(DCMem,rc,m_crViewBkg); } UINT OldMode = ::SetBkMode(DCMem,TRANSPARENT); Draw(DCMem); if(m_UseSystemScrollbar == false){ DrawScrollbar(DCMem); }; ::SetBkMode(DCMem, OldMode ); if(m_State & SPACE_SHOWWINBORDER){ DrawEdge(DCMem,rc,m_crWinBorder); } ::SelectObject(DCMem, OldBitmap); DeleteObject(DCMem); ::ReleaseDC(GetHwnd(),hDC); ::SetWindowPos(GetHwnd(),HWND_TOP,0,0,rcOld.right-rcOld.left,rcOld.bottom-rcOld.top,SWP_NOZORDER|SWP_NOMOVE); SaveBitmapToFile(hBmpCapture,FileName.c_str()); DeleteObject(hBmpCapture); return 0; }
void TestWol() { { LVStreamRef stream = LVOpenFileStream("woltest.wol", LVOM_WRITE); if (!stream) return; LVArray<lUInt32> m(10, 0xbad); m.clear(); WOLWriter wol(stream.get()); wol.addTitle( lString8("book title"), lString8("subj."), lString8("John Smith"), lString8("adapter"), lString8("translator"), lString8("publisher"), lString8("2006-11-01"), lString8("This is introduction."), lString8("ISBN") ); LVGrayDrawBuf cover(600, 800); cover.FillRect(20, 20, 50, 50, 1); cover.FillRect(40, 70, 120, 190, 2); cover.FillRect(60, 80, 150, 290, 3); LVGrayDrawBuf page1(600, 800, 2); page1.FillRect(0, 0, 150, 150, 1); page1.FillRect(70, 70, 140, 140, 2); page1.FillRect(130, 130, 180, 180, 3); page1.FillRect(400, 400, 550, 750, 1); page1.FillRect(420, 420, 530, 730, 2); page1.FillRect(440, 440, 510, 710, 3); LVGrayDrawBuf page2(600, 800, 2); page2.FillRect(120, 20, 150, 50, 1); page2.FillRect(140, 70, 220, 190, 2); page2.FillRect(160, 80, 250, 290, 3); LVGrayDrawBuf page3(600, 800, 2); page3.FillRect(120, 120, 30, 20, 1); page3.FillRect(10, 10, 120, 120, 2); page3.FillRect(300, 300, 300, 700, 3); page3.FillRect(400, 400, 550, 750, 1); page3.FillRect(420, 420, 530, 730, 2); page3.FillRect(440, 440, 510, 710, 3); wol.addCoverImage(cover); wol.addImage(page1); wol.addImage(page2); wol.addImage(page3); SaveBitmapToFile("page1.bmp", &page1); SaveBitmapToFile("page2.bmp", &page2); SaveBitmapToFile("page3.bmp", &page3); } { //LVStream * stream = LVOpenFileStream("Biblia.wol", LVOM_READ); LVStreamRef stream = LVOpenFileStream("woltest.wol", LVOM_READ); //LVStream * stream = LVOpenFileStream("info2.wol", LVOM_READ); if (!stream) return; WOLReader rd(stream.get()); if (!rd.readHeader()) return; LVStreamRef cover = LVOpenFileStream("cover2.bin", LVOM_WRITE); LVStreamRef log = LVOpenFileStream("woltest.log", LVOM_WRITE); LVArray<lUInt8> * rdcover = rd.getBookCover(); LVGrayDrawBuf * rdimg1 = rd.getImage(0); *cover << *rdcover; //int imgsz = (rdimg1->GetWidth()*2+7)/8*rdimg1->GetHeight(); //LVArray<lUInt8> imgbuf(imgsz, 0); //memcpy(imgbuf.ptr(), rdimg1->GetScanLine(0), imgsz ); if (rdimg1) SaveBitmapToFile( "test.bmp", rdimg1 ); //*img << imgbuf; *log << rd.getBookTitle(); *log << "\r\nimages found: " << lString8::itoa(rd.getImageCount()); delete rdimg1; } }
/// <summary> /// Handle new color data /// <param name="nTime">timestamp of frame</param> /// <param name="pBuffer">pointer to frame data</param> /// <param name="nWidth">width (in pixels) of input image data</param> /// <param name="nHeight">height (in pixels) of input image data</param> /// </summary> void CBodyBasics::ProcessColor(INT64 nTime, RGBQUAD* pBuffer, int nWidth, int nHeight) { if (m_hWnd) { if (!m_nStartTime) { m_nStartTime = nTime; } double fps = 0.0; LARGE_INTEGER qpcNow = { 0 }; if (m_fFreq) { if (QueryPerformanceCounter(&qpcNow)) { if (m_nLastCounter) { m_nFramesSinceUpdate++; fps = m_fFreq * m_nFramesSinceUpdate / double(qpcNow.QuadPart - m_nLastCounter); } } } WCHAR szStatusMessage[64]; StringCchPrintf(szStatusMessage, _countof(szStatusMessage), L" FPS = %0.2f Time = %I64d", fps, (nTime - m_nStartTime)); if (SetStatusMessage(szStatusMessage, 1000, false)) { m_nLastCounter = qpcNow.QuadPart; m_nFramesSinceUpdate = 0; } } // Make sure we've received valid data if (pBuffer && (nWidth == cColorWidth) && (nHeight == cColorHeight)) { // Draw the data with Direct2D m_pDrawColor->Draw(reinterpret_cast<BYTE*>(pBuffer), cColorWidth * cColorHeight * sizeof(RGBQUAD)); if (m_bSaveScreenshot) { WCHAR szScreenshotPath[MAX_PATH]; // Retrieve the path to My Photos GetScreenshotFileName(szScreenshotPath, _countof(szScreenshotPath)); // Write out the bitmap to disk HRESULT hr = SaveBitmapToFile(reinterpret_cast<BYTE*>(pBuffer), nWidth, nHeight, sizeof(RGBQUAD)* 8, szScreenshotPath); WCHAR szStatusMessage[64 + MAX_PATH]; if (SUCCEEDED(hr)) { // Set the status bar to show where the screenshot was saved StringCchPrintf(szStatusMessage, _countof(szStatusMessage), L"Screenshot saved to %s", szScreenshotPath); } else { StringCchPrintf(szStatusMessage, _countof(szStatusMessage), L"Failed to write screenshot to %s", szScreenshotPath); } SetStatusMessage(szStatusMessage, 5000, true); // toggle off so we don't save a screenshot again next frame m_bSaveScreenshot = false; } } }
/// <summary> /// Handle new color data /// </summary> /// <returns>indicates success or failure</returns> void CColorBasics::ProcessColor(DASHout* dasher) { HRESULT hr; NUI_IMAGE_FRAME imageFrame; colourFrame *cFrame; // Attempt to get the color frame hr = m_pNuiSensor->NuiImageStreamGetNextFrame(m_pColorStreamHandle, 0, &imageFrame); if (FAILED(hr)) { printf("failed in processcolor \n "); return; } INuiFrameTexture * pTexture = imageFrame.pFrameTexture; NUI_LOCKED_RECT LockedRect; // Lock the frame data so the Kinect knows not to modify it while we're reading it pTexture->LockRect(0, &LockedRect, NULL, 0); // Make sure we've received valid data if (LockedRect.Pitch != 0) { //init the frame to be parsed in FFMPEG cFrame = init_cFrame(cColorWidth*cColorHeight*3); if(!cFrame){ printf("fudge!\n"); gf_free(cFrame); return; } //Frame number cFrame->number = imageFrame.dwFrameNumber; if (!dasher->sys_start) { dasher->sys_start = gf_sys_clock_high_res(); dasher->prev_pts = 0; cFrame->pts = 0; } else { //TODO: fix timing here and cFrame->pts = 30*(gf_sys_clock_high_res() - dasher->sys_start)/1000000; printf("CTS diff is %d ms\n", (u32) (cFrame->pts - dasher->prev_pts) / 1000); dasher->prev_pts = cFrame->pts; } //convert RGBA to RGB unsigned char * currFrame = (unsigned char *)LockedRect.pBits; int j = 0; for (int i = 0; i < cColorWidth * cColorHeight * 4; i += 4){ (cFrame->kinectFrame)[i - j] = currFrame[i + 2]; (cFrame->kinectFrame)[i - j + 1] = currFrame[i + 1]; (cFrame->kinectFrame)[i - j + 2] = currFrame[i]; j++; } dasher->nextColourFrame = cFrame; // Draw the data with Direct2D m_pDrawColor->Draw(static_cast<BYTE *>(LockedRect.pBits), LockedRect.size); #if 0 // If the user pressed the screenshot button, save a screenshot if (m_bSaveScreenshot) { WCHAR statusMessage[cStatusMessageMaxLen]; // Retrieve the path to My Photos WCHAR screenshotPath[MAX_PATH]; GetScreenshotFileName(screenshotPath, _countof(screenshotPath)); // Write out the bitmap to disk hr = SaveBitmapToFile(static_cast<BYTE *>(LockedRect.pBits), cColorWidth, cColorHeight, 32, screenshotPath); if (SUCCEEDED(hr)) { // Set the status bar to show where the screenshot was saved StringCchPrintf( statusMessage, cStatusMessageMaxLen, L"Screenshot saved to %s", screenshotPath); } else { StringCchPrintf( statusMessage, cStatusMessageMaxLen, L"Failed to write screenshot to %s", screenshotPath); } SetStatusMessage(statusMessage); // toggle off so we don't save a screenshot again next frame m_bSaveScreenshot = false; } #endif } // We're done with the texture so unlock it pTexture->UnlockRect(0); // Release the frame m_pNuiSensor->NuiImageStreamReleaseFrame(m_pColorStreamHandle, &imageFrame); }
/// <summary> /// Handle new depth data /// <param name="nTime">timestamp of frame</param> /// <param name="pBuffer">pointer to frame data</param> /// <param name="nWidth">width (in pixels) of input image data</param> /// <param name="nHeight">height (in pixels) of input image data</param> /// <param name="nMinDepth">minimum reliable depth</param> /// <param name="nMaxDepth">maximum reliable depth</param> /// </summary> void CDepthBasics::ProcessDepth(INT64 nTime, const UINT16* pBuffer, int nWidth, int nHeight, USHORT nMinDepth, USHORT nMaxDepth) { if (m_hWnd) { if (!m_nStartTime) { m_nStartTime = nTime; } double fps = 0.0; LARGE_INTEGER qpcNow = {0}; if (m_fFreq) { if (QueryPerformanceCounter(&qpcNow)) { if (m_nLastCounter) { m_nFramesSinceUpdate++; fps = m_fFreq * m_nFramesSinceUpdate / double(qpcNow.QuadPart - m_nLastCounter); } } } WCHAR szStatusMessage[64]; StringCchPrintf(szStatusMessage, _countof(szStatusMessage), L" FPS = %0.2f Time = %I64d", fps, (nTime - m_nStartTime)); if (SetStatusMessage(szStatusMessage, 1000, false)) { m_nLastCounter = qpcNow.QuadPart; m_nFramesSinceUpdate = 0; } } int size = nWidth*nHeight; // Make sure we've received valid data if (m_pDepthRGBX && pBuffer && (nWidth == cDepthWidth) && (nHeight == cDepthHeight)) { RGBQUAD* pRGBX = m_pDepthRGBX; // Make a copy of received depth frame UINT16* depthFrameCopy = new UINT16[nWidth * nHeight]; const UINT16* srcDepthFrame = pBuffer; memcpy(depthFrameCopy, srcDepthFrame, nWidth*nHeight*sizeof(UINT16)); // Collect 10 frames and calculate reference depth image for background removal if (m_collectImagesCount < 10) { m_collectImagesCount++; m_depthFrames.push_back(depthFrameCopy); if (m_collectImagesCount == 10) { // Allocate memory for 32 bit reference depth frame to avoid range problem with 16 bit integers m_pDepthRef32 = new UINT32[size]; memset(m_pDepthRef32, 0, size* sizeof(UINT32)); // Iterate images for (int image = 0; image < m_collectImagesCount; image++) { UINT16* pDepthBufferCopy = m_depthFrames.at(image); int dr_index = 0; // Loop through all pixels in image for (int y = 0; y < nHeight; y++) { int zero_fill = 0; int count = 0; // Calculate pixel average from stride for (int j = 0; j < nWidth; j++) { int value = pDepthBufferCopy[j + (y * nWidth)]; if (value != 0) { zero_fill += value; count++; } } if (count != 0) { zero_fill /= count; } // Fill zero pixels with average value in reference frame for (int x = 0; x < nWidth; x++) { int value = pDepthBufferCopy[x + (y * nWidth)]; m_pDepthRef32[dr_index++] += (value != 0 ? value : zero_fill); } } } // Use memory from first received depth frame m_pDepthRef = m_depthFrames.at(0); // Calculate average of each pixel and store them in 16 bit depth frame for (int i = 0; i < size; i++) { m_pDepthRef[i] = m_pDepthRef32[i] / 10; } // Deallocate collected frames except first for (int i = 1; i < m_depthFrames.size(); i++) { delete [] m_depthFrames.at(i); } m_depthFrames.clear(); // Deallocate 32bit reference depth frame memory delete [] m_pDepthRef32; m_pDepthRef32 = NULL; return; } else return; } // Calculate difference of received depth frame and reference depth image for (int i = 0; i < size; i++) { UINT16 depth_val = depthFrameCopy[i]; if (depth_val == 0) depth_val = m_pDepthRef[i]; int diff = m_pDepthRef[i] - depth_val; // If difference of pixels is greater than 200 use reference value else 5000 (background) depthFrameCopy[i] = (diff > 200 ? depth_val : 5000); } // Clear kernel information memset(kernels_, 0, sizeof(PixelBox) * HorizontalBlocks * VerticalBlocks); // Traverse through depth frame with and calculate background pixel count for each 8x8 kernel int kernelIndex = 0; int kernelIndexStartY = 0; unsigned int min_x = cDepthWidth, max_x = 0, min_y = cDepthHeight, max_y = 0; int kernelRow = 0; for (int y = 0; y < cDepthHeight; y++) { for (int x = 0; x < cDepthWidth; x++) { unsigned short pixelValue = depthFrameCopy[(y * cDepthWidth) + x]; // If pixel value is 5000 count it in if (pixelValue == 5000) { kernels_[kernelIndex].backgroundPixels++; } if (x % KernelSize == 0 && x != 0) { kernelIndex += 1; } if (x == (cDepthWidth-1)) // Last pixel was handled on current row { if (y % KernelSize == 0 && y != 0) // Last horizontal kernel handled { // Calculate 2d coordinates for each kernel (horizontally) for (int kernel = 0; kernel < HorizontalBlocks; kernel++) { kernels_[kernelIndexStartY + kernel].tlX = kernel * KernelSize; kernels_[kernelIndexStartY + kernel].tlY = kernelRow * KernelSize; } kernelIndexStartY += HorizontalBlocks; // Let's handle next horizontal row kernelRow += 1; } // Index to kernel array to access next kernel kernelIndex = kernelIndexStartY; } } } // Traverse through kernels for (int kernel = 0; kernel < HorizontalBlocks*VerticalBlocks; kernel++) { // If pixel count in kernel is less than BackgroundPixelCountThreshold // treat kernel as foreground box and check for min and max x y if (kernels_[kernel].backgroundPixels < BackgroundPixelCountThreshold) { if (kernels_[kernel].tlX < min_x) min_x = kernels_[kernel].tlX; if (kernels_[kernel].tlX > max_x) max_x = kernels_[kernel].tlX; if (kernels_[kernel].tlY < min_y) min_y = kernels_[kernel].tlY; if (kernels_[kernel].tlY > max_y) max_y = kernels_[kernel].tlY; } } const UINT16* pBufferEnd = depthFrameCopy + (nWidth * nHeight); while (depthFrameCopy < pBufferEnd) { USHORT depth = *depthFrameCopy; // To convert to a byte, we're discarding the most-significant // rather than least-significant bits. // We're preserving detail, although the intensity will "wrap." // Values outside the reliable depth range are mapped to 0 (black). // Note: Using conditionals in this loop could degrade performance. // Consider using a lookup table instead when writing production code. BYTE intensity = static_cast<BYTE>((depth >= nMinDepth) && (depth <= nMaxDepth) ? (depth % 256) : 0); pRGBX->rgbRed = intensity; pRGBX->rgbGreen = intensity; pRGBX->rgbBlue = intensity; ++pRGBX; ++depthFrameCopy; } // Draw the data with Direct2D m_pDrawDepth->Draw(reinterpret_cast<BYTE*>(m_pDepthRGBX), cDepthWidth * cDepthHeight * sizeof(RGBQUAD), min_x, min_y, max_x, max_y); if (m_bSaveScreenshot) { WCHAR szScreenshotPath[MAX_PATH]; // Retrieve the path to My Photos GetScreenshotFileName(szScreenshotPath, _countof(szScreenshotPath)); // Write out the bitmap to disk HRESULT hr = SaveBitmapToFile(reinterpret_cast<BYTE*>(m_pDepthRGBX), nWidth, nHeight, sizeof(RGBQUAD) * 8, szScreenshotPath); WCHAR szStatusMessage[64 + MAX_PATH]; if (SUCCEEDED(hr)) { // Set the status bar to show where the screenshot was saved StringCchPrintf(szStatusMessage, _countof(szStatusMessage), L"Screenshot saved to %s", szScreenshotPath); } else { StringCchPrintf(szStatusMessage, _countof(szStatusMessage), L"Failed to write screenshot to %s", szScreenshotPath); } SetStatusMessage(szStatusMessage, 5000, true); // toggle off so we don't save a screenshot again next frame m_bSaveScreenshot = false; } } }