Solved

CImage messed up color

Posted on 2014-03-05
12
825 Views
Last Modified: 2014-03-10
I am using the CImage class to open a pair of jpg files ( Image.load() ) and show them on a dialog. My user then has the ability to draw a circle, rectangle, or just a line to "Mark Up" the images then save and/or print the new image. All that functionality is great BUT whenever I try to resize an image ( Image.StretchBlt()  or Image.draw()) the color gets messed up usually it gets very dark.  Just as a test I tried using the CPicture wrapper which encapsulates IPicture and while it DOES NOT mess with the color, some of the other functionallity is missing...  How can I get CImage to scale without changing the colors?

A little more detail: I get the client rectangle, determine how wide the images can be to fit nicely then create new rectangles using the new image width and the aspect ratio of the CImage image. Then I  draw or stretchblt using the new rectangle as the destination ( it lies inside the client dc ) and the CIamge as the source. mode is SRCCOPY. The displayed image is sized correctly and positioned correctly but the color is messed up dark...


Regards
Ron H
0
Comment
Question by:RonHarsh
  • 5
  • 4
12 Comments
 
LVL 30

Expert Comment

by:Zoppo
ID: 39916967
Hi RonHarsh,

I tried to reproduce the problem but unfortunateley without success. I wrote a simple MFC dialog app where in OnPaint I use either CImage::Draw or CImage::StretchBlt to draw a CImage previously loaded with CImage::Load from a JPEG onto the CDialog. This works fine everytime with CImage::Draw, with CImage::StretchBlt it looks ugly when the bitmap is down-sized, but this can be improved by setting the DC's stretch-blit mode using dc.SetStretchBltMode( HALFTONE ).

Since I cannot reproduce it I guess the reason for your problem is one of the following:

1. Your drawing code does something more or different than mine which affects the output as you described:
- Could you post the drawing functionality you have implemented?

2. The JPEG you use is somehow strange and GdiPlus for any reason can't draw it properly when resizing it:
- Does it happen with any JPEG you test it with?

3. GdiPlus is not up to data. I once had a problem with drawn bitmaps where randomly partially filled with blue color on a Win 2003 Server whithout installed Windows Updates/Hotfixes. After updating the system this problem disappeared:
- Is you system up to date?

Best regards,

ZOPPO
0
 

Author Comment

by:RonHarsh
ID: 39917083
Hi Zoppo.  Here is my code from OnPaint(). Note the three versions with comments.  It is also noteworthy that when I used the IPicture class's render function the image is sized and positioned perfectly and the color is excellent however I was not able to figure out how to reload the image from the client rectangle to the IPicture object after my user had modified it.

Thanks
RonHarsh
codesnipit.docx
0
 
LVL 30

Accepted Solution

by:
Zoppo earned 500 total points
ID: 39917134
Well, I'm not sure if it has nay effects, but I think you don't need the 'SaveDC' and 'RestoreDC' calls so IMO you should remove them, at least for performance issue.

Further you should ensure to call ReleaseDC for pictDC after it's used.

Next I found (and this might be the real problem) that the way you call CImage::Draw seems to work different than the way I used it.

You use this function:
BOOL CImage::Draw(
	_In_ HDC hDestDC,
	_In_ int xDest,
	_In_ int yDest,
	_In_ int nDestWidth,
	_In_ int nDestHeight,
	_In_ int xSrc,
	_In_ int ySrc,
	_In_ int nSrcWidth,
	_In_ int nSrcHeight)

Open in new window

I tested with this one:
BOOL Draw(
	_In_ HDC hDestDC,
	_In_ const RECT& rectDest,
	_In_ Gdiplus::InterpolationMode interpolationMode)

Open in new window

Here you can see a screenshot where on the left side I used your call, on the right side
I used mine:Two different ways calling CImage::DrawIt seems the first one works the same as using StretchBlt which, as mentioned above, produces worse result without setting the destination DC's stretch-blit mode calling dc.SetStretchBltMode( HALFTONE ) before calling CImage::Draw or StretchBlt.

But maybe it's better to use the second method, it seems to draw the image better in any case and you can pass a parameter which controls the drawing quality. The code I tested looks like this:
	CClientDC dc( this );
	CRect rc = /*calculated destination rectangle*/
	m_image.Draw( dc.GetSafeHdc(), rc, Gdiplus::InterpolationModeDefault );

Open in new window


Hope that helps,

ZOPPO
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 39917146
Just as addition: I looked into the code of the two CImage::Draw variants:

In fact that one you use is just a wrapper for StretchBlt, so it's clear why you get the same result with both versions.

That one I used internally uses Gdiplus::Graphics::DrawImage which implements improved bitmap drawing compared to StretchBlt.

ZOPPO
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:RonHarsh
ID: 39917175
Now I am confused! None of the overloaded Draw functions in CImage takes three parameters as your example shows! Am I using the wrong library?

 
BOOL Draw(
   HDC hDestDC,
   int xDest,
   int yDest,
   int nDestWidth,
   int nDestHeight,
   int xSrc,
   int ySrc,
   int nSrcWidth,
   int nSrcHeight
) const throw( );

BOOL Draw(
   HDC hDestDC,
   const RECT& rectDest,
   const RECT& rectSrc
) const throw( );

BOOL Draw(
   HDC hDestDC,
   int xDest,
   int yDest
) const throw( );

BOOL Draw(
   HDC hDestDC,
   const POINT& pointDest
) const throw( );

BOOL Draw(
   HDC hDestDC,
   int xDest,
   int yDest,
   int nDestWidth,
   int nDestHeight
) const throw( );

BOOL Draw(
   HDC hDestDC,
   const RECT& rectDest
) const throw( );
 



RonHarsh
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 39917220
Hm - which version of Visual Studio do you use? At least with VisualStudio 2010 which I use it's available. Anyway, it is not mentioned in MSDN even for VS 2010, I don't know why: http://msdn.microsoft.com/en-us/library/cz787xf9%28v=vs.100%29.aspx

You could simply check if it's available by searching the string InterpolationMode in the file atlimage.h in Visual Studio's include directories.

If it isn't there (so if you're using an older Visual Studio) you IMO have two options:

1. Simply use StretchBlt as above with a previous call to SetStretchBltMode
2. Implement your own functionality to use GdiPlus for drawing - this will produce nicer output.

ZOPPO
0
 

Author Comment

by:RonHarsh
ID: 39917223
OK, I used the  dc.SetStretchBltMode( HALFTONE )  and it seems to have fixed the issue! I am still interested in the Draw function that you used but I can work with what I have.


THANKS for the help!
RonHarsh
0
 
LVL 30

Expert Comment

by:Zoppo
ID: 39917238
Well, just try to check if the function is available as told above. If not implementing such bitmap drawing using GdiPlus is even simple, so if you want you could do it yourself to be able to use GdiPlus's interpolation modes which are nicer (but sometimes slower).

It'S even possible to load images and to draw onto images with GdiPlus, so maybe you should think about using it as a replacement for CImage at all if you can spend the effort. GdiPlus is much better than GDI which at least in this case is used by CImage.

ZOPPO
0
 

Author Closing Comment

by:RonHarsh
ID: 39917352
Thanks for the help!
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

I use more than 1 computer in my office for various reasons. Multiple keyboards and mice take up more than just extra space, they make working a little more complicated. Using one mouse and keyboard for all of my computers makes life easier. This co…
Today, still in the boom of Apple, PC's and products, nearly 50% of the computer users use Windows as graphical operating systems. If you are among those users who love windows, but are grappling to keep the system's hard drive optimized, then you s…
The viewer will learn how to successfully download and install the SARDU utility on Windows 8, without downloading adware.
An overview on how to enroll an hourly employee into the employee database and how to give them access into the clock in terminal.

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now