Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1084
  • Last Modified:

CImage messed up color

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
RonHarsh
Asked:
RonHarsh
  • 5
  • 4
1 Solution
 
ZoppoCommented:
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
 
RonHarshAuthor Commented:
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
 
ZoppoCommented:
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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
ZoppoCommented:
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
 
RonHarshAuthor Commented:
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
 
ZoppoCommented:
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
 
RonHarshAuthor Commented:
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
 
ZoppoCommented:
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
 
RonHarshAuthor Commented:
Thanks for the help!
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now