1

I need to draw PNG images with transparency. I use GDI, GDI+, and WinApi.

To load and draw images, I always used GDI+, but now I'm using more "native" GDI algorithms (StretchBlt, etc).

The problem is that GDI can't load PNG. I searched the internet and found 2 ways:

  • loading via GDI+
  • using WIC.

WIC seems to be too difficult (but what did I expect?), so I choose the first one.

It's easy to load a PNG image using GDI+, just create a Bitmap object passing the file path to the constructor, then call the getHBITMAP() method to receive an HBITMAP handle, and that's all.

The problem is that the HBITMAP produced by Bitmap loses transparency.

I searched how to fix it. There are different ways - like passing Color::Black as first argument, etc. But it doesn't work.

So, how can I Ioad a PNG image and convert it to HBITMAP with transparency?

I don't use DrawImage method, because it's slow, GDI is faster

I pinned the code:

I understood my mistake: I have to blit hdc_mem to hdcc firstly, and then blit the image. I've did it, but i have a new problem¬_¬

I made a class to manage uploaded images, here the code:

class Imagee
{
HDC hdc; HBITMAP bm;
Imagee(HDC hdc, HBITMAP bm, another args)
{
this->hdc=CreateCompatibleDC(hdc);
this->bm=bm;
SelectObject(this->hdc,this->bm);
}
void draw(int hdcc, int x,int y, int cx, int cy)
{
**StretchBlt(this->hdc,0,0,cx,cy,hdcc,x,y,cx,cy,SRCCOPY); //I'VE ADDED THIS
SelectObject(this->hdc,this->bm); //AND THIS **

StretchBlt(this->hdcc,x,y,cx,cy,hdc,0,0,cx,cy,SRCCOPY); 
};
};
Imagee *image;

void render()
{
for(;;)
{
//some draws

//Loading a bitmap via Gdi+, calling a GetHBITMAP function, HBITMAP variable named hbm

if(image==0)
image=new Imagee(hdc_mem, hbm, x, y etc..);

image->draw(hdc_mem, x, y etc..);

StretchBlt(hdc_main,0,0,1920,1080,hdc_mem,0,0,1920,1080,SRCCOPY);
}

I have a black screen. It seems I can't call SelectObject again, yes?

LarsTech
  • 80,625
  • 14
  • 153
  • 225
Stdugnd4ikbd
  • 242
  • 3
  • 9
  • 1
    Why do you need to resort to GDI for drawing? You can create a `Graphics` object for an `HDC` and then pass the `Bitmap` to `Graphics::DrawImage()`. See [Loading and Displaying Bitmaps](https://msdn.microsoft.com/en-us/library/ms533830.aspx) in the GDI+ documentation. If you have to resort to GDI, see [How would I load a PNG image using Win32/GDI (no GDI+ if possible)?](https://stackoverflow.com/questions/4567875/). – Remy Lebeau Nov 12 '17 at 10:42
  • GDI+ will draw the png with transparency. You haven't shown what problems you are having. GDI functions don't understand alpha, but you can use `GetHBITMAP(Gdiplus::Color::Transparent, &hBitmap)` for some special cases. – Barmak Shemirani Nov 12 '17 at 11:21
  • @Remy Lebeau Gdi draws image faster than DrawImage method – Stdugnd4ikbd Nov 12 '17 at 11:31
  • @Barmak Shemirani I've tried Color::Transparent too, it didn't work(I mean there wasn't transparency) – Stdugnd4ikbd Nov 12 '17 at 11:34
  • Alpha transparency is inherently slow, irrespective of the rendering API used, because it has to read memory. Since we cannot see the code you used it stands to reason that you are comparing a simple block transfer operation to an alpha blending operation. – IInspectable Nov 12 '17 at 12:13
  • @IInspectable, I've pinned the code – Stdugnd4ikbd Nov 12 '17 at 17:42
  • 1
    `SRCCOPY` doesn't perform alpha blending. A simple block transfer (which `SRCCOPY` does) is a *lot* faster than alpha blending. Given the code, it's unclear, what you really need. The code (like its formatting) is severely broken. Get a copy of Petzold's [Programming Windows®](https://www.amazon.com/dp/157231995X). – IInspectable Nov 12 '17 at 18:48
  • I've used the `CImage` class for similar things. May be my post https://stackoverflow.com/a/43183800/383779 can give some guidance? – sergiol Nov 15 '17 at 11:35
  • **The Solve_______________________________** https://ru.stackoverflow.com/questions/743530/%d0%9a%d0%b0%d0%ba-%d0%ba%d0%be%d0%bd%d0%b2%d0%b5%d1%80%d1%82%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d1%82%d1%8c-bitmap-%d0%b2-hbitmap-%d0%b1%d0%b5%d0%b7-%d0%bf%d0%be%d1%82%d0%b5%d1%80%d0%b8-%d0%bf%d1%80%d0%be%d0%b7%d1%80%d0%b0%d1%87%d0%bd%d0%be%d1%81%d1%82%d0%b8?noredirect=1#comment1141028_743530 – Stdugnd4ikbd Nov 16 '17 at 21:22
  • We don't put "solved" in the title. If you have it solved, post the solution as an answer. – LarsTech Nov 16 '17 at 21:57

1 Answers1

0

From: https://ru.stackoverflow.com/questions/743530

class Imagee
{
   HDC hdc; HBITMAP bm;

   Imagee(HDC hdc, HBITMAP bm, another args)
   {
      this->hdc=CreateCompatibleDC(hdc);
      this->bm=bm;
      SelectObject(this->hdc,this->bm);
   }

   void draw(int hdcc, int x,int y, int cx, int cy)
   {
      BITMAP btm;
      GetObject(bm,sizeof(BITMAP),&btm);

      BLENDFUNCTION bf;
      //initialize bf
      AlphaBlend(hdcc,x,y,cx,cy,his->hdcc,0,0,btm.bmWidth,btm.bmHeight,bf); 
   };
};

Usage

Imagee *image;

void render()
{
   for(;;)
   {
      //here I am downloading via gdi+ bitmap, converting it to hbitmap, writing it to the variable HBITMAP hbm

      if(image==0)
         image = new Image(hdc_mem, hbm, x, y и т.д.);

      image->draw(hdc_mem, x, y и т.д.);

      StretchBlt(hdc_main,0,0,1920,1080,hdc_mem,0,0,1920,1080,SRCCOPY); 
      //hdc_main главный дс, hdc_mem буфер
   }
}
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
Stdugnd4ikbd
  • 242
  • 3
  • 9