Discussion:
Preventing GDI+ from scaling images/how to ignore DPI settings(rep
(too old to reply)
docschnipp
2004-12-08 07:21:02 UTC
Permalink
Hi,

I am loading PNG files with the Gdiplus::Bitmap(filename) constructor. To
display
them I create a CompatibleBitmap(). In case the resolution(DPI) of the
bitmap/PNG does not match the resolution (DPI) of the screen context
(accessed via Gdiplus::Graphics) the bitmaps are drawn scaled. It only works
"pixelwise" when the resolutions of the PNG file and the desktop match.

I call this DrawImage() method:
DrawImage(Image, dx,dy, sx,sy,sw,sh, UnitPixel);
which is the only suitable option in this case, since I need to draw only
parts of the bitmap. Since every other part of the GUI is fixed I need also
fixed drawing.

I tried to call bitmap.SetResolution() but after this the
Gdiplus::Graphics::DrawImage() function returns "InvalidParameter".

How can I make GDI+ ignoring the DPI within the file and just use the pixels?
I don't want to scale sw/sh every time I call it.

thanks for any answer

docschnipp
Gary Chang[MSFT]
2004-12-08 09:50:26 UTC
Permalink
Hi,
Post by docschnipp
DrawImage(Image, dx,dy, sx,sy,sw,sh, UnitPixel);
which is the only suitable option in this case, since I
need to draw only parts of the bitmap.
The DrawImage(Image, dx,dy, sx,sy,sw,sh, UnitPixel) method should also work
for drawing parts of an image, what's the problem do you get in that
scenarion?


Thanks!

Best regards,

Gary Chang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
docschnipp
2004-12-08 14:07:05 UTC
Permalink
Post by Gary Chang[MSFT]
Hi,
Post by docschnipp
DrawImage(Image, dx,dy, sx,sy,sw,sh, UnitPixel);
which is the only suitable option in this case, since I
need to draw only parts of the bitmap.
The DrawImage(Image, dx,dy, sx,sy,sw,sh, UnitPixel) method should also work
for drawing parts of an image, what's the problem do you get in that
scenarion?
The coordinates behave pixelwise, but the image itself is scaled then. The
first time I ran over this I got PNGs with 72dpi. My screen
(Gdiplus::Graphics object) says 96dpi.

When I call (for example) the method above with width/height=15 the result
is an 15x15 pixel area where a sqare of 11,25 x 11,25 pixel (from the
original png) is stretched over the 15x15 pixel area. Not my desired result.

I guessed this is behaviour by design, so I tried to prevent the scaling by
calling the Gdiplus::Image::SetResolution() method. But when I do this, the
Gdiplus::Graphics::DrawImage() method fails with "invalid parameter".

The problem is: I could just convert the PNGs (since I want to keep them in
resources of my app), but when a customer sets its display to 120dpi (which
he can by using large fonts etc) it will be wrong again. It would be
rudicioulus to provide bitmaps for every resolution.

Is there something wrong with Gdiplus::Image::SetResolution()? Do I have to
use another Unit within the Gdiplus::Graphics::DrawImage(Image, dx,dy,
sx,sy,sw,sh, UnitPixel) method?

Thanks for your help

Doc

p.s.: let me know if I did not explain clear enough then I will try to
provide screenshots of it.
Gary Chang[MSFT]
2004-12-10 09:50:23 UTC
Permalink
Hi Doc,
Post by docschnipp
Is there something wrong with Gdiplus::Image::SetResolution()? Do I have to
use another Unit within the Gdiplus::Graphics::DrawImage(Image, dx,dy,
sx,sy,sw,sh, UnitPixel) method?
Do you have debugged into the code Gdiplus::Graphics::DrawImage(Image,
dx,dy, sx,sy,sw,sh, UnitPixel) when getting the "Invalid Parameter", if you
specified the UnitPixel, the six real number parameter's decimal part
should be zero...


Thanks!

Best regards,

Gary Chang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------
docschnipp
2004-12-11 16:09:03 UTC
Permalink
Hello Gary,
Post by Gary Chang[MSFT]
Hi Doc,
Post by docschnipp
Is there something wrong with Gdiplus::Image::SetResolution()? Do I have
to
Post by docschnipp
use another Unit within the Gdiplus::Graphics::DrawImage(Image, dx,dy,
sx,sy,sw,sh, UnitPixel) method?
Do you have debugged into the code Gdiplus::Graphics::DrawImage(Image,
dx,dy, sx,sy,sw,sh, UnitPixel) when getting the "Invalid Parameter", if you
specified the UnitPixel, the six real number parameter's decimal part
should be zero...
This is my call.
pContext->getGdiplusGraphics()->DrawImage(theBitmap,
(INT)destRect.left + pContext->offset.h, // xDest
(INT)destRect.top + pContext->offset.v, // yDest
(INT)srcOffset.h,
(INT)srcOffset.v,
(INT)destRect.width(), // xWidth,
(INT)destRect.height(), // yHeight
Gdiplus::UnitPixel);

another call is:
pContext->pGraphics->DrawImage(pGdiPlusBitmap,
//pGraphics->DrawImage(pBitmap,
(INT)rl+pContext->offset.h,(INT)rt+pContext->offset.v,
(INT)ox,(INT)oy,
(INT)rw,(INT)rh,
Gdiplus::UnitPixel);

It is all perfect, when the bitmap is 96dpi (and the screen is 96dpi), but
when the graphics is 72 dpi, the bitmap is zoomed (by 96/72=1,33..) it covers
an area of rw/rh but not pixel by pixel.

The attempt to set the resolution of the Image with SetResolution to the
same dpi as the Graphics-Object let the calls above fail (where I already
pass INT arguments, since I actually have no need for REALs).

How can I solve this trap? How can I let either set the Resolution or let
GDI+ just ignore the DPI setting in the bitmap?

Thanks for your time

Doc
Gary Chang[MSFT]
2004-12-15 01:50:49 UTC
Permalink
This post might be inappropriate. Click to display it.
docschnipp
2004-12-15 09:35:03 UTC
Permalink
Hello Gary,
Post by Gary Chang[MSFT]
Hi Doc,
I have consulted our internal experts on this issue, their opinion are as
There are overrides available for DrawImage() which allow you to specify
the source and target sizes. If you use one of those overrides, you control
whether or not scaling occurs. If GDI+ must infer either width or height,
it will do so based on the inherent resolution in the image.
I've inspected all override again and finally found this one:

Status DrawImage( Image *image,
const Rect &destRect,
INT srcx,
INT srcy,
INT srcwidth,
INT srcheight,
Unit srcUnit,
ImageAttributes *imageAttributes,
DrawImageAbort callback,
VOID *callbackData
);

I've had the conception that this one is a "slower" variant. It works now,
even if I have the feeling it is slightly slower.
Post by Gary Chang[MSFT]
Bitmap.SetResolution() does affect this.
This still seems not to work. When I load the images and call
SetResolution() with the DPI values I retrieve from my graphics context, the
drawImage() (the one I used before) fails.

Is there a way to get more information than the quite uninforming status?

Thanks again for hinting me to the solution.

best regards
doc
Gary Chang[MSFT]
2004-12-17 02:47:06 UTC
Permalink
This post might be inappropriate. Click to display it.
docschnipp
2004-12-17 06:35:02 UTC
Permalink
Hello Gary,
Post by Gary Chang[MSFT]
Hi Doc,
GDI+ must infer width or height when you don't specify a width or height.
You have to specify width and height if you want control over the output.
Now that you are correctly using an override in which you specify width and
height, there is no need to call SetResolution. It should have no effect.
Yes. But anyway I would expect it to work. Nevermind :-)

I overlooked the right override because of its *unusual* set of parameters.
The destination as a Rect, the source in 4 ints.. that's not very consistent
and forward leading.. anyway. It works now, nice and clean.

best regards
doc
Gary Chang[MSFT]
2004-12-17 10:00:01 UTC
Permalink
Great, doc,

I am delight that we could resolved this problem, have a nice weekend:)


Best regards,

Gary Chang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
--------------------

Loading...