locked
WIC+Direct2D CreateBitmapFromMemory

    Question

  • I got some trouble when I Modified the code of a camera demo using Direct2D and WIC.

    My camera use uchar* to transfer Image data. So I thought I need to use "m_pIWICFactory->CreateBitmapFromMemory" to get this kind of data . Then I could use Direct2D to render it. The code is followed:

        HRESULT hr=m_pIWICFactory->CreateBitmapFromMemory(
    Width,
    Height,   
    GUID_WICPixelFormat8bppGray, 
    (Width*8+7)/8,  // I don't know if it was right here!

                                              //I just see someone said "stride is (width x bitsPerPixel+7)/8"
    Height*(Width*8+7)/8,             // bufferSize=height*stride
    ImageData,     // unsigned char* type
    &m_pWICBitmap
    );

    if (SUCCEEDED(hr))
    {
    SafeRelease(m_pConvertedSourceBitmap);
    hr = m_pIWICFactory->CreateFormatConverter(&m_pConvertedSourceBitmap);
    }

    if (SUCCEEDED(hr))
    {
    hr = m_pConvertedSourceBitmap->Initialize(
    m_pWICBitmap,                          // Input bitmap to convert
    GUID_WICPixelFormat8bppGray,   // Destination pixel format
    WICBitmapDitherTypeNone,         // Specified dither pattern
    NULL,                            // Specify a particular palette 
    0.f,                             // Alpha threshold
    WICBitmapPaletteTypeCustom       // Palette translation type
    );
    }

    if (SUCCEEDED(hr))
    {
    SafeRelease(m_pD2DBitmap);
    m_pDCRenderTarget->CreateBitmapFromWicBitmap(m_pConvertedSourceBitmap,NULL,&m_pD2DBitmap);

    m_pDCRenderTarget->BeginDraw();
    m_pDCRenderTarget->DrawBitmap(m_pD2DBitmap);
    m_pDCRenderTarget->EndDraw();
    }

    I can get m_pConvertedSourceBitmap was 0x005bcf60 and m_pIWICFactory was 0x0064ce8c ,which means it got sth I thought. However, m_pD2DBitmap was always 0x00000000.

    I don't know what is wrong!  Help me !! Please!!


    • Edited by FT_YOUNG Tuesday, March 10, 2015 2:23 PM
    Tuesday, March 10, 2015 2:14 PM

All replies

  • Hello,

    The "stride" you specify here must match the actual stride of the input buffer data. There is no indication in your code as to how your "ImageData" buffer variable was created or what it contains. Because of this I can't really recommend anything other than make sure that the "stride" value you pass to "CreateBitmapFromMemory" actually matches the "stride" of the input buffer. If the input buffer is simply baked by system memory this will be the width of the bitmap. If the input buffer is backed by video card memory then the stride will need to match what is required by the video card. Different video driers have different stride offset values. Simply adding seven to the stride value is completely naive and likely won't actually match the required offset of the underlying video driver / hardware. The "size" parameter must match the actual size of the input buffer exactly. Any variation will cause the copy operation to fail and the bitmap will not be created as expected. Finally you must be absolutely sure that the pixel format you are passing in really does match the pixel format of the input buffer. In this case you are specifying a greyscale buffer type. This buffer type is not widely used but is certainly a valid selection if you buffer contains only greyscale data.

    I hope this helps,

    James


    Windows SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Wednesday, March 11, 2015 11:02 PM
    Moderator
  • Hi,James

    Thanks for your suggestions!

    I am so busy recently that I forget to see my question.Sorry...

    I have worked out this problem by changing the Destination pixel format of "m_pConvertedSourceBitmap->Initialize" to WICPixelFormat32bppPBGRA ,which is the only one of four formats supported by D2D. As for the stride I found they are both fine ,"width " or "(Width*8+7)/8".

    But I met a new problem. This piece of code is typed for a real-time camera monitor project.

    However, I found they are too slow,which cost 19-40 ms to render a 1296*964 picture.,tested by QPC timer .When I used DIB , it only needed 1-2 ms.

    Do you know how to improve it ? Or is D2D Suitable for this project?


    • Edited by FT_YOUNG Thursday, March 19, 2015 1:05 PM
    Thursday, March 19, 2015 1:04 PM
  • Hello,

    Typically you would use Media Foundation and the MediaCapture class for capturing and encoding video. It is possible to use Media Foundation and manipulate the frames via D2D. WIC is not a real time encode / decode API as it is not hardware accelerated. I can probably give you some additional suggestions if you can provide more detail on what it is you are trying to accomplish.

    Thanks,

    James


    Windows SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Thursday, March 19, 2015 9:03 PM
    Moderator
  • Yes,

    I am trying to modify a camera demo,which uses DIB to render his 8-bits Gray Image.And the image is used to a big measurement  project. So it must render the picture very quickly. The original code is below, if it is useful.

     

    void CSVS_GigE_ExampleDlg::ShowImage(HDC DisplayDC, int Width, int Height, unsigned char *ImageData)
    {

      // Check image alignment
    if( Width % 4 == 0 )
     {

        BITMAPINFO *bitmapinfo;

        // Generate and fill a bitmap info structure
        bitmapinfo = (BITMAPINFO *)new char[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];

        bitmapinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bitmapinfo->bmiHeader.biWidth = Width;
        bitmapinfo->bmiHeader.biHeight = -Height;
        bitmapinfo->bmiHeader.biBitCount = 8;
        bitmapinfo->bmiHeader.biPlanes = 1;
        bitmapinfo->bmiHeader.biClrUsed = 0;
        bitmapinfo->bmiHeader.biClrImportant = 0;
        bitmapinfo->bmiHeader.biCompression = BI_RGB;
        bitmapinfo->bmiHeader.biSizeImage = 0;
        bitmapinfo->bmiHeader.biXPelsPerMeter = 0;
        bitmapinfo->bmiHeader.biYPelsPerMeter = 0;

        // Fill color table with gray levels
        for(int i = 0; i < 256; i++)
        {
          bitmapinfo->bmiColors[i].rgbRed = i;
          bitmapinfo->bmiColors[i].rgbGreen = i;
          bitmapinfo->bmiColors[i].rgbBlue = i;
          bitmapinfo->bmiColors[i].rgbReserved = 0;
        }

        // Center image if it is smaller than the screen
        int Left = 0;
        int Top = 0;
        int OffsetX = 0;
        if( Width < DisplayWidth )
          Left = (DisplayWidth - Width) / 2;
        if( Height < DisplayHeight )
          Top = (DisplayHeight - Height) / 2;
        // Center image if it is bigger than the screen
        if( Width > DisplayWidth )
          OffsetX = (Width - DisplayWidth) / 2;

        SetDIBitsToDevice(DisplayDC, Left, Top, Width, Height, OffsetX, 0, 0, Height, ImageData, bitmapinfo, DIB_RGB_COLORS);

      delete []bitmapinfo;
     }
    }

    It runs fine in our project. And it only consume 1-2 ms to run this function . According to my experiment we can't afford more than 3-5 ms in this function, because of some other process in our project.

    However, while my boss heard  D2D may presents more perfect render effect , I was asked to improve it , using D2D. But I am not familiar with that. And I can't find a good way to render this on-line measurement picture effiently.

    Could you help me , James ?

    Thanks.




    • Edited by FT_YOUNG Friday, March 20, 2015 2:35 AM
    Friday, March 20, 2015 2:22 AM
  • Hello,

    Are you writing a Windows Store app or a Windows Desktop app? If you are writing a desktop app you are asking this question in the wrong forum.

    Thanks,

    James


    Windows SDK Technologies - Microsoft Developer Services - http://blogs.msdn.com/mediasdkstuff/

    Monday, March 23, 2015 7:37 PM
    Moderator
  • Oh,

    I am sorry, I haven't realized it.

    Anyway thanks for your help.

    Tuesday, March 24, 2015 8:31 AM