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. CImage and transparency

CImage and transparency

Scheduled Pinned Locked Moved C / C++ / MFC
helpquestion
8 Posts 5 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.
  • C Offline
    C Offline
    Craig Longman
    wrote on last edited by
    #1

    I have a button that I want an image in, a basic colour swatch. I liked the idea of having a partially transparent shadow around it, so in GIMP, I created a 32 bit BMP with the desired alpha shadow, and a white, totally non-transparent square in the middle. The intention was to fill the white area in with the colour that the user chooses. Sounds simple enough. So, the basic code is such:

    HDC hDC;
    HANDLE hOldBmp;
    HBRUSH hBrush;
    LOGBRUSH zLogBrush;

    HBITMAP hColourShadowBmp_ = ::LoadBitmap( hInst, MAKEINTRESOURCE(IDB_COLOUR_SHADOW) );

    zLogBrush.lbStyle = BS_SOLID;
    zLogBrush.lbColor = RGB( m_Props.uiRed, m_Props.uiGreen, m_Props.uiBlue );
    zLogBrush.lbHatch = NULL;

    hBrush = ::CreateBrushIndirect( &zLogBrush );

    CImage zFinalImage;
    CImage zSwatchImage;

    zFinalImage.Attach( hColourShadowBmp_ );
    zSwatchImage.Create( 20, 20, 24 );

    hDC = zSwatchImage.GetDC();
    ::SelectObject( hDC, hBrush );
    ::Rectangle( hDC, 0, 0, 20, 20 );
    zSwatchImage.ReleaseDC();

    hDC = zFinalImage.GetDC();
    zSwatchImage.AlphaBlend( hDC, 2, 2, 255 );
    zFinalImage.ReleaseDC();

    hOldBmp = (HANDLE)
    ::SendMessage( ::GetDlgItem( m_hWnd, IDC_COLOUR ),
    BM_SETIMAGE,
    (WPARAM)IMAGE_BITMAP,
    (LPARAM)zFinalImage.Detach() );

    ::DeleteObject( hBrush );

    All I end up with is the source shadow image, with a lovely fully transparent square where the swatch should be. I know the swatch painting is working, as I can send that image and get the colour square I expect. Yet nothing I do seems to be able to make the colours get transferred. Crazily enough, the alpha is, if I set the alpha in the AlphaBlend() call to 0, I get the original shadow image unchanged. So I know that it is modifying the alpha channel properly at least. The source is opaque, so no amount of pre-multiplying will help. FWIW, I also tried making the zSwatchImage a 32 bit with alpha, but it made no difference. The only solution I can see now is jumping into the bits for the shadow image and changing the RGB values to what I want. But surely I'm doing something wrong? It's hard to believe that a simply blend like this fails. Thanks, CraigL

    C 1 Reply Last reply
    0
    • C Craig Longman

      I have a button that I want an image in, a basic colour swatch. I liked the idea of having a partially transparent shadow around it, so in GIMP, I created a 32 bit BMP with the desired alpha shadow, and a white, totally non-transparent square in the middle. The intention was to fill the white area in with the colour that the user chooses. Sounds simple enough. So, the basic code is such:

      HDC hDC;
      HANDLE hOldBmp;
      HBRUSH hBrush;
      LOGBRUSH zLogBrush;

      HBITMAP hColourShadowBmp_ = ::LoadBitmap( hInst, MAKEINTRESOURCE(IDB_COLOUR_SHADOW) );

      zLogBrush.lbStyle = BS_SOLID;
      zLogBrush.lbColor = RGB( m_Props.uiRed, m_Props.uiGreen, m_Props.uiBlue );
      zLogBrush.lbHatch = NULL;

      hBrush = ::CreateBrushIndirect( &zLogBrush );

      CImage zFinalImage;
      CImage zSwatchImage;

      zFinalImage.Attach( hColourShadowBmp_ );
      zSwatchImage.Create( 20, 20, 24 );

      hDC = zSwatchImage.GetDC();
      ::SelectObject( hDC, hBrush );
      ::Rectangle( hDC, 0, 0, 20, 20 );
      zSwatchImage.ReleaseDC();

      hDC = zFinalImage.GetDC();
      zSwatchImage.AlphaBlend( hDC, 2, 2, 255 );
      zFinalImage.ReleaseDC();

      hOldBmp = (HANDLE)
      ::SendMessage( ::GetDlgItem( m_hWnd, IDC_COLOUR ),
      BM_SETIMAGE,
      (WPARAM)IMAGE_BITMAP,
      (LPARAM)zFinalImage.Detach() );

      ::DeleteObject( hBrush );

      All I end up with is the source shadow image, with a lovely fully transparent square where the swatch should be. I know the swatch painting is working, as I can send that image and get the colour square I expect. Yet nothing I do seems to be able to make the colours get transferred. Crazily enough, the alpha is, if I set the alpha in the AlphaBlend() call to 0, I get the original shadow image unchanged. So I know that it is modifying the alpha channel properly at least. The source is opaque, so no amount of pre-multiplying will help. FWIW, I also tried making the zSwatchImage a 32 bit with alpha, but it made no difference. The only solution I can see now is jumping into the bits for the shadow image and changing the RGB values to what I want. But surely I'm doing something wrong? It's hard to believe that a simply blend like this fails. Thanks, CraigL

      C Offline
      C Offline
      Code o mat
      wrote on last edited by
      #2

      Don't be surprised, GDI drawing methods zero out the aplha channel. When you call Rectangle it "makes a hole" in your alpha channel. Use GDI+ or fill the pixels by writing memory directly.

      > The problem with computers is that they do what you tell them to do and not what you want them to do. < > Leela: Fry, you're wasting your life sitting in front of that TV. You need to get out and see the real world. Fry: But this is HDTV. It's got better resolution than the real world <

      C T 2 Replies Last reply
      0
      • C Code o mat

        Don't be surprised, GDI drawing methods zero out the aplha channel. When you call Rectangle it "makes a hole" in your alpha channel. Use GDI+ or fill the pixels by writing memory directly.

        > The problem with computers is that they do what you tell them to do and not what you want them to do. < > Leela: Fry, you're wasting your life sitting in front of that TV. You need to get out and see the real world. Fry: But this is HDTV. It's got better resolution than the real world <

        C Offline
        C Offline
        Craig Longman
        wrote on last edited by
        #3

        I can see that being a problem if I had an alpha channel in the zSwatchImage. And at one point I did, so I guess I'd expect the behaviour I saw. But it's absurd to me that an "alpha blend" function can't take a 24bit image and "do the right thing" by copying it will the alpha channel opaque. Especially when you TELL it what the alpha value to copy with should be. If it isn't there, you'd think it would use the alpha provided as the source alpha, not just the blend alpha. But to take a 24bit image and assume the alpha is zero? And, I had thought that CImage did use GDI+, so the 24 -> 32 bpp copy would make sense. I guess I just expect too much from CImage. Course, now I'm having fun trying to get the bits directly from a BMP loaded via ::LoadBitmap... I guess graphics never really was a win32 strong point. Thanks for the reply. Normally, I totally exclude win32 APIs wrt image handling, just needed the BMP to use the easy way one can put it on a button. This exercise has just cinched that opinion even more =)

        C A 2 Replies Last reply
        0
        • C Craig Longman

          I can see that being a problem if I had an alpha channel in the zSwatchImage. And at one point I did, so I guess I'd expect the behaviour I saw. But it's absurd to me that an "alpha blend" function can't take a 24bit image and "do the right thing" by copying it will the alpha channel opaque. Especially when you TELL it what the alpha value to copy with should be. If it isn't there, you'd think it would use the alpha provided as the source alpha, not just the blend alpha. But to take a 24bit image and assume the alpha is zero? And, I had thought that CImage did use GDI+, so the 24 -> 32 bpp copy would make sense. I guess I just expect too much from CImage. Course, now I'm having fun trying to get the bits directly from a BMP loaded via ::LoadBitmap... I guess graphics never really was a win32 strong point. Thanks for the reply. Normally, I totally exclude win32 APIs wrt image handling, just needed the BMP to use the easy way one can put it on a button. This exercise has just cinched that opinion even more =)

          C Offline
          C Offline
          Craig Longman
          wrote on last edited by
          #4

          OK, I stumbled upon the ::LoadImage() after thinking there must be a function more up-to-date that ::LoadBitmap(), and it lets me load a DIB from a resource, and then ::GetObject() gives me the bits. Thanks, CraigL

          C 1 Reply Last reply
          0
          • C Craig Longman

            I can see that being a problem if I had an alpha channel in the zSwatchImage. And at one point I did, so I guess I'd expect the behaviour I saw. But it's absurd to me that an "alpha blend" function can't take a 24bit image and "do the right thing" by copying it will the alpha channel opaque. Especially when you TELL it what the alpha value to copy with should be. If it isn't there, you'd think it would use the alpha provided as the source alpha, not just the blend alpha. But to take a 24bit image and assume the alpha is zero? And, I had thought that CImage did use GDI+, so the 24 -> 32 bpp copy would make sense. I guess I just expect too much from CImage. Course, now I'm having fun trying to get the bits directly from a BMP loaded via ::LoadBitmap... I guess graphics never really was a win32 strong point. Thanks for the reply. Normally, I totally exclude win32 APIs wrt image handling, just needed the BMP to use the easy way one can put it on a button. This exercise has just cinched that opinion even more =)

            A Offline
            A Offline
            Alain Rist
            wrote on last edited by
            #5

            Hi Craig,

            Craig Longman wrote:

            Course, now I'm having fun trying to get the bits directly from a BMP loaded via ::LoadBitmap

            From LoadBitmap[^] LoadBitmap creates a compatible bitmap of the display. Use LoadImage()[^] with LR_CREATEDIBSECTION to use the xxxBlend GDI functions. As was already answered GDI+ (not MFC CImage which uses it only for file exchanges) handles that correctly. cheers, AR

            When the wise (person) points at the moon the fool looks at the finger (Chinese proverb)

            1 Reply Last reply
            0
            • C Craig Longman

              OK, I stumbled upon the ::LoadImage() after thinking there must be a function more up-to-date that ::LoadBitmap(), and it lets me load a DIB from a resource, and then ::GetObject() gives me the bits. Thanks, CraigL

              C Offline
              C Offline
              Code o mat
              wrote on last edited by
              #6

              Cool :thumbsup: :)

              > The problem with computers is that they do what you tell them to do and not what you want them to do. < > Leela: Fry, you're wasting your life sitting in front of that TV. You need to get out and see the real world. Fry: But this is HDTV. It's got better resolution than the real world <

              1 Reply Last reply
              0
              • C Code o mat

                Don't be surprised, GDI drawing methods zero out the aplha channel. When you call Rectangle it "makes a hole" in your alpha channel. Use GDI+ or fill the pixels by writing memory directly.

                > The problem with computers is that they do what you tell them to do and not what you want them to do. < > Leela: Fry, you're wasting your life sitting in front of that TV. You need to get out and see the real world. Fry: But this is HDTV. It's got better resolution than the real world <

                T Offline
                T Offline
                transoft
                wrote on last edited by
                #7

                FYI: GDI+ is not working properly under windows 7.

                M 1 Reply Last reply
                0
                • T transoft

                  FYI: GDI+ is not working properly under windows 7.

                  M Offline
                  M Offline
                  Moak
                  wrote on last edited by
                  #8

                  transoft wrote:

                  GDI+ is not working properly under windows 7

                  Can you give an example... do you mean performance problems with alpha blending on Windows 7?

                  Chat in Europe :java: Now with 24% more Twitter

                  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