GDI+ DrawImage of a JPG with white background is not white

我与影子孤独终老i 提交于 2019-12-22 21:40:09

问题


I am displaying a JPG in a C++ CWnd window using GDI+. The JPG has a pure white background, 0xffffff, but when displayed using graphics.DrawImage, the background is off-white with a mix of pixel colors such as 0xfff7f7, 0xf7fff7, 0xf7f7f7. Below is the code, I have tried various settings such as CompositingMode, SmoothingMode, etc. The image is not scaled.

The weird thing is that the background color is different depending on other non-white content in the image. If I make a simple all white JPG, then it works, or even a mostly white with just some black text. Comparison of images are shown below.


  CClientDC dc(this);
  Gdiplus::Graphics graphics(dc);

  Gdiplus::Bitmap* bmp = Gdiplus::Bitmap::FromFile( L"c:\\test.jpg" );
  graphics.SetInterpolationMode(Gdiplus::InterpolationModeHighQuality); 
  //graphics.SetCompositingQuality(Gdiplus::CompositingQualityHighQuality); 
  graphics.SetCompositingQuality(Gdiplus::CompositingQualityDefault); 
  graphics.SetCompositingMode(Gdiplus::CompositingModeSourceCopy); 
  //graphics.SetSmoothingMode( Gdiplus::SmoothingMode::SmoothingModeDefault );
  graphics.DrawImage(bmp, 0, 0, bmp->GetWidth(), bmp->GetHeight() );

Here I have text and some blending only on the left side of the image (no alphas, this is JPG) . Everything to the right is pure white. You can see the background is all grey.

Here I started removing the internal content (only on the left side). After a certain point the entire background starts displaying white. ???

It doesn't really matter which part of the image area I remove before it starts displaying white, as long as I remove a large portion of it. The same occurs for pngs.

Here is the original test.jpg image...


回答1:


I am answering my question with the solution that I found. It seems that using graphics.DrawImage directly on the passed HDC has some issues in my case. If I use a memory DC for the initial drawing, then BitBlt it on the HDC, then it works.

I also had some problems with PNG and transparency. Using the solution below, I was able to solve this problem as well. My PNG was loaded from a stream using Bitmap::FromStream. The alpha channel was lost and I was trying different attempts using LockBits and re-creating the bitmap with PixelFormat32bppARGB, as well as Cloning. I was able to get something to work (after a lot of effort and extra code), but it still had the grey background problem that I asked here.

In my case, I have a known solid background color for the transparent areas. I used Bitmap.GetHBITMAP and passed the background color. The bitmap was then drawn on the memory DC first. Here I was able to solve both of my problems!


  Gdiplus::Bitmap* bmp = Gdiplus::Bitmap::FromFile( L"c:\test.jpg" )
  Gdiplus::Color backColor( 0xff, 0xff, 0xff );
  HBITMAP hBmp;
  bmp->GetHBITMAP( backColor, &hBmp );
  CDC     bitmapDC;
  bitmapDC.CreateCompatibleDC(hdc);  // pass original HDC for drawing
  HBITMAP oldBmp = bitmapDC.SelectBitmap(hBitmap);
  ::BitBlt( hdc, x, y, cx, cy, bitmapDC.m_hDC, 0, 0, SRCCOPY );
  bitmapDC.SelectBitmap(oldBmp);
  DeleteObject( hBmp );

If anyone knows, I would be interested why this fixes the problem.




回答2:


How did you confirm the JPG background is truly white? JPG implements compression that can vary the color of pixels. If there are mixed colors, then there can be certain types of blending and mixing that are part of that compression.

Can you show us the original image?



来源:https://stackoverflow.com/questions/4596346/gdi-drawimage-of-a-jpg-with-white-background-is-not-white

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!