zoukankan      html  css  js  c++  java
  • 图形学的几个非常有用的转换

    1:将指定区域保存为位图信息,此区域如果从控件得到的dc而来,可以对指定控件抓图
    HBITMAP CopyScreenToBitmap(LPRECT lpRect)
    //lpRect 代表选定区域
    {
    HDC hScrDC, hMemDC;
    // 屏幕和内存设备描述表
    HBITMAP hBitmap, hOldBitmap; 
    // 位图句柄
    int nX, nY, nX2, nY2; 
    // 选定区域坐标
    int nWidth, nHeight;
    // 位图宽度和高度
    int xScrn, yScrn; 
    // 屏幕分辨率
    // 确保选定区域不为空矩形
    if (IsRectEmpty(lpRect))
    return NULL;
    //为屏幕创建设备描述表
    hScrDC = CreateDC("DISPLAY", NULL, NULL, NULL);
    //为屏幕设备描述表创建兼容的内存设备描述表
    hMemDC = CreateCompatibleDC(hScrDC);
    // 获得选定区域坐标
    nX = lpRect->left;
    nY = lpRect->top;
    nX2 = lpRect->right;
    nY2 = lpRect->bottom;
    // 获得屏幕分辨率
    xScrn = GetDeviceCaps(hScrDC, HORZRES);
    yScrn = GetDeviceCaps(hScrDC, VERTRES);
    //确保选定区域是可见的
    if (nX <0)
    nX = 0;
    if (nY<0)
    nY = 0;
    if (nX2 > xScrn)
    nX2 = xScrn;
    if (nY2 > yScrn)
    nY2 = yScrn;
    nWidth = nX2 - nX;
    nHeight = nY2 - nY;
    // 创建一个与屏幕设备描述表兼容的位图
    hBitmap = CreateCompatibleBitmap(hScrDC, nWidth, nHeight);
    // 把新位图选到内存设备描述表中
    hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap);
    // 把屏幕设备描述表拷贝到内存设备描述表中
    BitBlt(hMemDC, 0, 0, nWidth, nHeight,hScrDC, nX, nY, SRCCOPY);
    //得到屏幕位图的句柄
    hBitmap = (HBITMAP)SelectObject(hMemDC, hOldBitmap);
    //清除 
    DeleteDC(hScrDC);
    DeleteDC(hMemDC);
    // 返回位图句柄
    return hBitmap;
    }
    2:对上面的延伸,将一个位图结构保存为文件

    BOOL SaveBmp(HBITMAP hBitmap, CString FileName)
    {
    HDC hDC;
    int iBits;
    WORD wBitCount;
    DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0; 
    BITMAP Bitmap; 
    BITMAPFILEHEADER bmfHdr; 
    BITMAPINFOHEADER bi; 
    LPBITMAPINFOHEADER lpbi; 
    HANDLE fh, hDib, hPal,hOldPal=NULL; 

    hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
    iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES); 
    DeleteDC(hDC); 
    if (iBits <= 1) wBitCount = 1; 
    else if (iBits <= 4) wBitCount = 4; 
    else if (iBits <= 8) wBitCount = 8; 
    else wBitCount = 24; 

    GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
    bi.biSize = sizeof(BITMAPINFOHEADER);
    bi.biWidth = Bitmap.bmWidth;
    bi.biHeight = Bitmap.bmHeight;
    bi.biPlanes = 1;
    bi.biBitCount = wBitCount;
    bi.biCompression = BI_RGB;
    bi.biSizeImage = 0;
    bi.biXPelsPerMeter = 0;
    bi.biYPelsPerMeter = 0;
    bi.biClrImportant = 0;
    bi.biClrUsed = 0;

    dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;

    hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER)); 
    lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib); 
    *lpbi = bi; 

    hPal = GetStockObject(DEFAULT_PALETTE); 
    if (hPal) 

    hDC = ::GetDC(NULL); 
    hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE); 
    RealizePalette(hDC); 
    }

    GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) 
    +dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS); 

    if (hOldPal) 

    ::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE); 
    RealizePalette(hDC); 
    ::ReleaseDC(NULL, hDC); 


    fh = CreateFile(FileName, GENERIC_WRITE,0, NULL, CREATE_ALWAYS, 
    FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL); 

    if (fh == INVALID_HANDLE_VALUE) return FALSE; 

    bmfHdr.bfType = 0x4D42; // "BM" 
    dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize; 
    bmfHdr.bfSize = dwDIBSize; 
    bmfHdr.bfReserved1 = 0; 
    bmfHdr.bfReserved2 = 0; 
    bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize; 

    WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL); 
    WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL); 

    GlobalUnlock(hDib); 
    GlobalFree(hDib); 
    CloseHandle(fh); 

    return TRUE;
    }

    3:也是对1的延伸,将位图结构转为ipl,作为Opencv处理的接口

    int stride = (width * sizeof( RGBTRIPLE ) + 3) & -4;
    cvInitImageHeader( &ds_frame, cvSize(width, height), 8, 3,IPL_ORIGIN_BL, 4 );
    ds_frame.widthStep = stride; 
    cvSetData( &ds_frame, myBuffer, stride ); 

    4:和上面的相反,将IPL转换为bitmap

    IplImage* VideoResizeframe = NULL; 
    CDC *pDC;
    CRect rect;
    BITMAPINFO bmi;
    pDC = ((CPCSDlg*)AfxGetMainWnd())->m_VideoPreview.GetDC(); 
    ((CPCSDlg*)AfxGetMainWnd())->m_VideoPreview.GetWindowRect(rect);
    VideoResizeframe = cvCreateImage(cvSize(rect.Width(), rect.Height()), IPL_DEPTH_8U,3);
    cvResize(pFrame, VideoResizeframe, CV_INTER_LINEAR ); 
    MYFillBitmapInfo(&bmi,VideoResizeframe->width,VideoResizeframe->height,(VideoResizeframe->depth)*(VideoResizeframe->nChannels));
    ::StretchDIBits(pDC->GetSafeHdc(),-4,-4,VideoResizeframe->width,VideoResizeframe->height,0,0,VideoResizeframe->width,VideoResizeframe->height,VideoResizeframe->imageData,&bmi,DIB_RGB_COLORS,SRCCOPY);
    delete &bmi;
    ((CPCSDlg*)AfxGetMainWnd())->m_VideoPreview.ReleaseDC( pDC );
    cvReleaseImage(&VideoResizeframe);

    引用到的函数如下:
    void MYFillBitmapInfo( BITMAPINFO* bmi, int width, int height, int bpp )
    {
    ASSERT( bmi && width > 0 && height > 0 &&
    (bpp == 8 || bpp == 24 || bpp == 32) );

    BITMAPINFOHEADER* bmih = &(bmi->bmiHeader);

    memset( bmih, 0, sizeof(*bmih));
    bmih->biSize = sizeof(BITMAPINFOHEADER);
    bmih->biWidth = width;
    bmih->biHeight = -abs(height);
    bmih->biPlanes = 1;
    bmih->biBitCount = bpp;
    bmih->biCompression = BI_RGB;

    if( bpp == 8 )
    {
    RGBQUAD* palette = bmi->bmiColors;
    int i;
    for( i = 0; i < 256; i++ )
    {
    palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed = (BYTE)i;
    palette[i].rgbReserved = 0;
    }
    }
    }

    5:利用ipicture用接口实现vc任意控件上加载图象
    HRESULT CDTS32Dlg::ShowPic(char *lpstrFile, HWND hWnd, int nScrWidth, int nScrHeight)
    {
    HDC hDC_Temp=(FromHandle(hWnd)->GetDC())->GetSafeHdc(); 

    IPicture *pPic; 
    IStream *pStm; 

    BOOL bResult; 

    HANDLE hFile=NULL; 
    DWORD dwFileSize,dwByteRead; 

    //打开硬盘中的图形文件 
    hFile=CreateFile(lpstrFile,GENERIC_READ, 
    FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); 

    if (hFile!=INVALID_HANDLE_VALUE) 

    dwFileSize=GetFileSize(hFile,NULL);//获取文件字节数 
    if (dwFileSize==0xFFFFFFFF) 
    return E_FAIL; 

    else 

    return E_FAIL; 



    //分配全局存储空间 
    HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, dwFileSize); 
    LPVOID pvData = NULL; 

    if (hGlobal == NULL) 
    return E_FAIL; 

    if ((pvData = GlobalLock(hGlobal)) == NULL)//锁定分配内存块 
    return E_FAIL; 

    ReadFile(hFile,pvData,dwFileSize,&dwByteRead,NULL);//把文件读入内存缓冲区 

    GlobalUnlock(hGlobal); 

    CreateStreamOnHGlobal(hGlobal, TRUE, &pStm); 

    //装入图形文件 
    bResult=OleLoadPicture(pStm,dwFileSize,TRUE,IID_IPicture,(LPVOID*)&pPic); 

    if(FAILED(bResult)) 
    return E_FAIL; 

    OLE_XSIZE_HIMETRIC hmWidth;//图片的真实宽度 
    OLE_YSIZE_HIMETRIC hmHeight;//图片的真实高度 
    pPic->get_Width(&hmWidth); 
    pPic->get_Height(&hmHeight); 


    //将图形输出到屏幕上(有点像BitBlt) 
    bResult=pPic->Render(hDC_Temp,0,0,nScrWidth,nScrHeight, 
    0,hmHeight,hmWidth,-hmHeight,NULL); 

    pPic->Release(); 

    CloseHandle(hFile);//关闭打开的文件 

    if (SUCCEEDED(bResult)) 

    return S_OK; 

    else 

    return E_FAIL; 



    }

    用法:
    ShowPic(lpstrFile, GetDlgItem(IDC_STATIC_LOGO)->GetSafeHwnd( ), 90, 105);

     
    6: 对1的延伸,将位图信息保存在剪切板 
    HBITMAP dest = CopyScreenToBitmap(&Rc);
    if (OpenClipboard()) 

    EmptyClipboard(); 
    SetClipboardData(CF_BITMAP, dest); 
    CloseClipboard(); 
    }


    IplImage* hBitmap2Ipl(HBITMAP hBmp)
    {
    BITMAP bmp;

    ::GetObject(hBmp,sizeof(BITMAP),&bmp);

    int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8 ;
    int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;

    IplImage* img = cvCreateImageHeader( cvSize(bmp.bmWidth, bmp.bmHeight)
    , depth, nChannels );

    img->imageData =
    (char*)malloc(bmp.bmHeight*bmp.bmWidth*nChannels*sizeof(char));
    memcpy(img->imageData,(char*)(bmp.bmBits),bmp.bmHeight*bmp.bmWidth*nChannels);

    return img;
    }


    void createDIB(IplImage* &pict){
    IplImage * Red=cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),
    IPL_DEPTH_8U, 1 );
    IplImage * Green=cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),
    IPL_DEPTH_8U, 1 );
    IplImage * Blue=cvCreateImage( cvSize(IMAGE_WIDTH,IMAGE_HEIGHT),
    IPL_DEPTH_8U, 1 );
    cvSetImageCOI( pict, 3);
    cvCopy(pict,Red);
    cvSetImageCOI( pict, 2);
    cvCopy(pict,Green);
    cvSetImageCOI(pict, 1);
    cvCopy(pict,Blue);
    //Initialize the BMP display buffer
    bmi = (BITMAPINFO*)buffer;
    bmih = &(bmi->bmiHeader);
    memset( bmih, 0, sizeof(*bmih));
    bmih->biSize = sizeof(BITMAPINFOHEADER);
    bmih->biWidth = IMAGE_WIDTH;
    bmih->biHeight = IMAGE_HEIGHT; // -IMAGE_HEIGHT;
    bmih->biPlanes = 1;
    bmih->biCompression = BI_RGB;
    bmih->biBitCount = 24;
    palette = bmi->bmiColors;
    for( int i = 0; i < 256; i++ ){
    palette[i].rgbBlue = palette[i].rgbGreen = palette[i].rgbRed =
    (BYTE)i;
    palette[i].rgbReserved = 0;
    }
    cvReleaseImage(&Red);
    cvReleaseImage(&Green);
    cvReleaseImage(&Blue);
    }


    IplImage* hBitmap2Ipl(HBITMAP hBmp)
    {
    BITMAP bmp; 
    ::GetObject(hBmp,sizeof(BITMAP),&bmp);

    int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8 ;
    int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;


    CString t;
    t.Format("%d %d %d %d",bmp.bmWidth,bmp.bmHeight,depth,nChannels);
    AfxMessageBox(t);


    IplImage* img = cvCreateImage(cvSize(bmp.bmWidth,bmp.bmHeight),depth,nChannels); //cvCreateImageHeader
    //img->origin = 1;
    //img->widthStep = (bmp.bmWidth * sizeof( RGBTRIPLE ) + 3) & -4;


    BYTE *pBuffer = new BYTE[bmp.bmHeight*bmp.bmWidth*nChannels]; 
    GetBitmapBits(hBmp,bmp.bmHeight*bmp.bmWidth*nChannels,pBuffer); 
    //cvSetData(img,(BYTE*)(bmp.bmBits),img->widthStep);
    //cvSetData(img,pBuffer,bmp.bmHeight*bmp.bmWidth*nChannels);
    memcpy(img->imageData,pBuffer,bmp.bmHeight*bmp.bmWidth*nChannels);
    /* IplImage* img = cvCreateImageHeader(cvSize(bmp.bmWidth,bmp.bmHeight),depth,nChannels);
    img->imageData = (char*)malloc(bmp.bmHeight*bmp.bmWidth*nChannels*sizeof(char)); 
    memcpy(img->imageData,(char*)(bmp.bmBits),bmp.bmHeight*bmp.bmWidth*nChannels);
    */ 

    return img;
    }


    IplImage* hBitmap2Ipl(HBITMAP hBmp)
    {
    BITMAP bmp; 
    ::GetObject(hBmp,sizeof(BITMAP),&bmp); 
    int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8 ;
    int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U; 
    IplImage* img = cvCreateImage(cvSize(bmp.bmWidth,bmp.bmHeight),depth,nChannels); //cvCreateImageHeader
    BYTE *pBuffer = new BYTE[bmp.bmHeight*bmp.bmWidth*nChannels]; 
    GetBitmapBits(hBmp,bmp.bmHeight*bmp.bmWidth*nChannels,pBuffer); 
    memcpy(img->imageData,pBuffer,bmp.bmHeight*bmp.bmWidth*nChannels);
    delete pBuffer; 
    return img;
  • 相关阅读:
    程序运行bug查看
    c# webbrowser 的html调用js出错
    c# dll使用注意
    支持ie的时间控件 html
    sql 条件插入
    软件自动更新原理
    c# 数组不能直接=,需要clone
    打包成exe程序
    逆袭大学
    Heritage from father
  • 原文地址:https://www.cnblogs.com/mfryf/p/2354142.html
Copyright © 2011-2022 走看看