Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Gdiplus: DrawImage not working

Gdiplus: DrawImage not working

Scheduled Pinned Locked Moved C / C++ / MFC
graphicshelpcsharpc++visual-studio
3 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • U Offline
    U Offline
    User 1619799
    wrote on last edited by
    #1

    Hi all, I need some help from you: I try to render an SVG image on the screen (with alpha channel). The problem is, when I try to draw the image on the screen, I see absolutely nothing. First of all, my SVG image is loaded correctly, and the ATL CImage from the below code, contains a correct image. The problem start when I try to use Gdiplus + alpha channel. For instance, if I use PixelFormat24bppRGB instead of PixelFormat32bppARGB, the image is drawn correctly, but alpha channel is not preserved - a black halo is shown around my image. Do you see any problem in my code? PS: I use Win7, 32 bit + Visual Studio 2013 Ultimate. Many thanks!

    void CAppView::OnDraw(CDC* pDC)
    {

    int width = 600, height = 600;
    
    GError\* pError = NULL;
    
    rsvg\_init();
    g\_my\_svg = rsvg\_handle\_new\_from\_file("d:\\\\myImage.svg", &pError);
    rsvg\_handle\_get\_dimensions(g\_my\_svg, &g\_dimension);
    
    
    cairo\_surface\_t \*surface = cairo\_win32\_surface\_create\_with\_dib(CAIRO\_FORMAT\_ARGB32, width, height);
    cairo\_t\* cr = cairo\_create(surface);
    
    rsvg\_handle\_render\_cairo(g\_my\_svg, cr);
    
    HDC srcHDC = cairo\_win32\_surface\_get\_dc(surface);
    
    // Create ATL CImage, then, copy the content of srcHDC in the CImage HDC
    CImage image;
    image.Create(width, height, 32);
    
    HDC imageHDC = image.GetDC();
    
    TransparentBlt(imageHDC, 0, 0, width, height, srcHDC, 0, 0, width, height, RGB(0, 0, 0));
    
    
    // Initialize Gdiplus
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG\_PTR gdiplusToken;
    Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
    

    // Problems starts from this point.

    // Create a Gdiplus bitmap, and copy the content of CImage in bitmap, then write the bitmap on the screen.
    Gdiplus::Bitmap bmp(image.GetWidth(), image.GetHeight(), image.GetPitch(), PixelFormat32bppARGB, static\_cast(image.GetBits()));
    Gdiplus::Graphics graphics(pDC->GetSafeHdc());
    graphics.DrawImage(&bmp, Gdiplus::Rect(0, 0, width, height));
    
    
    
    Gdiplus::GdiplusShutdown(gdiplusToken);
    image.ReleaseDC();
    image.Destroy();
    cairo\_surface\_flush(surface);
    cairo\_destroy(cr);
    cairo\_surface\_destroy(surface);
    

    }

    L 1 Reply Last reply
    0
    • U User 1619799

      Hi all, I need some help from you: I try to render an SVG image on the screen (with alpha channel). The problem is, when I try to draw the image on the screen, I see absolutely nothing. First of all, my SVG image is loaded correctly, and the ATL CImage from the below code, contains a correct image. The problem start when I try to use Gdiplus + alpha channel. For instance, if I use PixelFormat24bppRGB instead of PixelFormat32bppARGB, the image is drawn correctly, but alpha channel is not preserved - a black halo is shown around my image. Do you see any problem in my code? PS: I use Win7, 32 bit + Visual Studio 2013 Ultimate. Many thanks!

      void CAppView::OnDraw(CDC* pDC)
      {

      int width = 600, height = 600;
      
      GError\* pError = NULL;
      
      rsvg\_init();
      g\_my\_svg = rsvg\_handle\_new\_from\_file("d:\\\\myImage.svg", &pError);
      rsvg\_handle\_get\_dimensions(g\_my\_svg, &g\_dimension);
      
      
      cairo\_surface\_t \*surface = cairo\_win32\_surface\_create\_with\_dib(CAIRO\_FORMAT\_ARGB32, width, height);
      cairo\_t\* cr = cairo\_create(surface);
      
      rsvg\_handle\_render\_cairo(g\_my\_svg, cr);
      
      HDC srcHDC = cairo\_win32\_surface\_get\_dc(surface);
      
      // Create ATL CImage, then, copy the content of srcHDC in the CImage HDC
      CImage image;
      image.Create(width, height, 32);
      
      HDC imageHDC = image.GetDC();
      
      TransparentBlt(imageHDC, 0, 0, width, height, srcHDC, 0, 0, width, height, RGB(0, 0, 0));
      
      
      // Initialize Gdiplus
      Gdiplus::GdiplusStartupInput gdiplusStartupInput;
      ULONG\_PTR gdiplusToken;
      Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
      

      // Problems starts from this point.

      // Create a Gdiplus bitmap, and copy the content of CImage in bitmap, then write the bitmap on the screen.
      Gdiplus::Bitmap bmp(image.GetWidth(), image.GetHeight(), image.GetPitch(), PixelFormat32bppARGB, static\_cast(image.GetBits()));
      Gdiplus::Graphics graphics(pDC->GetSafeHdc());
      graphics.DrawImage(&bmp, Gdiplus::Rect(0, 0, width, height));
      
      
      
      Gdiplus::GdiplusShutdown(gdiplusToken);
      image.ReleaseDC();
      image.Destroy();
      cairo\_surface\_flush(surface);
      cairo\_destroy(cr);
      cairo\_surface\_destroy(surface);
      

      }

      L Offline
      L Offline
      leon de boer
      wrote on last edited by
      #2

      Can I first say you have no error checking at all in that code ... really bad programming practice cairo_win32_surface_get_dc can fail and return NULL ... read the manual. Why might there not be a win32 surface, well because you have to set a #define CAIRO_HAS_WIN32_SURFACE 1 in the cairo library .... again in the manual. You code is totally reliant on srcHDC being valid ... Yet inexplicably you don't check it. Secondly you probably want an alpha channel on the CIMage .. the create should be CreateEx

      CImage image;
      image.CreateEx(width, height, 32, BI_RGB, 0, 0);

      Thirdly read TransparentBlt detail and if we do the Alpha channel it will then copy the source alpha onto the destination alpha ... is that Ok? If not you have to use AlphaBlend function. Fourth check GDIPlus I seem to remember it had issues with Alpha channels. Final comment is you seem to be making life difficult for yourself using 3 different systems for reasons that aren't clear. You are moving bitmap data around between systems for no real reason what you want can be done in any of the 3 systems and even natively on the Win32 API. You are even initializing the GDI plus system with a draw process ... like seriously please don't do it are you really hell bent on making the draw as slow as possible. Start the GDIPlus with the window or program and close it when done but not in a draw process ever.

      In vino veritas

      U 1 Reply Last reply
      0
      • L leon de boer

        Can I first say you have no error checking at all in that code ... really bad programming practice cairo_win32_surface_get_dc can fail and return NULL ... read the manual. Why might there not be a win32 surface, well because you have to set a #define CAIRO_HAS_WIN32_SURFACE 1 in the cairo library .... again in the manual. You code is totally reliant on srcHDC being valid ... Yet inexplicably you don't check it. Secondly you probably want an alpha channel on the CIMage .. the create should be CreateEx

        CImage image;
        image.CreateEx(width, height, 32, BI_RGB, 0, 0);

        Thirdly read TransparentBlt detail and if we do the Alpha channel it will then copy the source alpha onto the destination alpha ... is that Ok? If not you have to use AlphaBlend function. Fourth check GDIPlus I seem to remember it had issues with Alpha channels. Final comment is you seem to be making life difficult for yourself using 3 different systems for reasons that aren't clear. You are moving bitmap data around between systems for no real reason what you want can be done in any of the 3 systems and even natively on the Win32 API. You are even initializing the GDI plus system with a draw process ... like seriously please don't do it are you really hell bent on making the draw as slow as possible. Start the GDIPlus with the window or program and close it when done but not in a draw process ever.

        In vino veritas

        U Offline
        U Offline
        User 1619799
        wrote on last edited by
        #3

        Actually the problem was related to the way of copying from srcHDC to ImageHDC. I have done like this:

        HDC svgDC = cairo_win32_surface_get_dc(surface);

        image.Create(width, height, 32);

        image.SetHasAlphaChannel(TRUE);

        HDC imageHDC = image.GetDC();

        BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
        AlphaBlend(imageHDC, 0, 0, width, height, svgDC, 0, 0, width, height, blend);

        image.ReleaseDC();

        Best regards!

        1 Reply Last reply
        0
        Reply
        • Reply as topic
        Log in to reply
        • Oldest to Newest
        • Newest to Oldest
        • Most Votes


        • Login

        • Don't have an account? Register

        • Login or register to search.
        • First post
          Last post
        0
        • Categories
        • Recent
        • Tags
        • Popular
        • World
        • Users
        • Groups