Click here to Skip to main content
15,890,947 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

I like to zoom a bitmap at mouse position with StretchBlt() on OnMouseWheel(UINT nFlags, short zDelta, CPoint point) function.

Say ZOOMFACTOR is 1200.0f.

How the parameters of StretchBlt() are set ???

CRect rcClient;
GetClientRect(&rcClient);

myDC->StretchBlt(rcClient.left,
rcClient.top,
rcClient.Width(),
rcClient.Height,
&dcPaintBitmap,//source device context.
???,
???,
???,
???,
SRCCOPY);

Thank you

What I have tried:

if (zDelta> 0)
{ // zoomin

//have no idea

}
else
{//zoom out

//have no idea

}
Posted
Updated 6-Apr-16 0:22am

The rightmost parameters are for the source which is probably the original (not zoomed image). So you have to calculate the destination parameters (the left most ones).

To support zoom in/out you must track the actual zoom factor in a variable that is initialised with 1. Then adjust this upon the event:
C++
if (zDelta > 0)
    m_zoomFactor *= ZOOMFACTOR;
else
    m_zoomFactor /= ZOOMFACTOR;


Then multiply the original dimensions with the factor to get the zoomed dimensions (rcSrc is here the size of the original bitmap):
C++
int zoomWidth = (int)(0.5 + rcSrc.Width() * m_zoomFactor);
int zoomHeight = (int)(0.5 + rcSrc.Height() * m_zoomFactor);

Assuming the mouse position indicates the center of the zoomed image, the left and top positions can be retrieved by subtracting half the width resp. the height:
C++
int left = x - zoomWidth / 2;
int right = y - zoomHeight / 2;

However, it may be necessary to track the center positions for the previous zoom state too to adjust these.

The final StretchBlt call should be:
myDC->StretchBlt(left, right, zoomWidth, zoomHeight,
    &dcPaintBitmap,//source device context.
    0, 0, rcSrc.Width(), rcSrc.Height(),
    SRCCOPY);


Note that I have not tested this.
 
Share this answer
 
Comments
kindi 6-Apr-16 8:18am    
Dear Jochen Arndt,

Thank you very much! It works really good. This code assumes that "mouse position is at the center of the zoomed image". Imagine mouse position is not at the center [mouse position is retrieved by GetCursorPos(&tmppoint);ScreenToClient(&tmppoint)], how the image part under the mouse is get zoomed? Sorry to bother you again.

Thank you
Jochen Arndt 6-Apr-16 8:48am    
You can get the mouse position from the point parameter of OnMouseWheel. There is no need to use GetCursorPos. Then use ScreenToClient for the destination window. This point will be the x and y positions from my code.

I guess you want to zoom around the current mouse position so that the center of the zoomed image is at the mouse position. My code will work when the actually displayed image is the original one and fits inside the output window. But once you have zoomed, the center of the zoomed image is not centered on screen (when not zooming with the mouse at the center position). So you must also store the position of zoomed images besides the zoom factor. Then these points must be used together with the new mouse position to calculate the new center position.

This is somewhat complicated because the positions are also affected by the zoom state and must be normalised therefore.

An approach would be storing the center of the actual zoomed image in original based coordinates (half the width / height of the original image upon start). When now zooming the new mouse position must be scaled to the original image size using the previous zoom factor. Then subtract this from the stored center position and save it as new center position. Finally use this position to draw the zoomed image.

But I can't give you code for this from scratch. I would have to think about it too.
kindi 6-Apr-16 11:11am    
Dear Jochen Arndt,

Thank you for your detailed reply. Following code may work.

//m_zoomFactor member variable initialised with 1 when zooming begins
if (zDelta > 0)
m_zoomFactor *= ZOOMFACTOR;// zoomin
else
m_zoomFactor /= ZOOMFACTOR;//zoom out

//Then multiply the original dimensions with the factor to get the zoomed dimensions
//(rcSrc is here the size of the original bitmap):
int zoomWidth = (int)(0.5 + rcSrc.Width() * m_zoomFactor);
int zoomHeight = (int)(0.5 + rcSrc.Height() * m_zoomFactor);

CRect rcClient;
GetClientRect(&rcClient);
//Find the position "factor"
double dXFactor = (double)rcClient.Width()/ x;
double dYFactor = (double)rcClient.Height()/ y;

//Find the origin
int left = x - zoomWidth / dXFactor;
int right = y - zoomHeight / dYFactor;

//use StretchBlt
myDC->StretchBlt(left, right, zoomWidth, zoomHeight,
&dcPaintBitmap,//source device context.
0, 0, rcSrc.Width(), rcSrc.Height(),
SRCCOPY);



Thank you once again for your support!

Jochen Arndt 6-Apr-16 11:17am    
Fine to hear that you are getting close to what you want to achieve.
Such problems can be much better solved when seeing what happens (and watching the calculated values) rather than only thinking about it.
See StretchBlt[^] for the values needed. You need to set the size of the source and destination according to how much you want to zoom the image. You will also need to adjust the destination values in order to maintain the aspect ratio of the image as described below.
The key to keeping the correct aspect ratio while resizing an image is the algorithm
used to calculate the ratio, viz.

	NewHeight = GivenWidth * (OriginalHeight / OriginalWidth)
or
	NewWidth = GivenHeight * (OriginalWidth / OriginalHeight)

This calculation assumes that the "Given..." is the dimension the image should be resized to.
Once we know this, we can multiply it by the original image’s aspect, and that will give us the other side's value we need. So, assuming the original image has a width of 1000 and a height of 1600 and we want it to be resized to a width of 500:

First find the aspect: (1600 / 1000) = aspect of 1.6
Now multiply the aspect by the desired new width: 1.6 * 500
The result of that multiplication is 800, which is what our new height should be

In other words:

    800 = 500 * (1600 / 1000)

So the resulting image would have a height of 800 and a width of 500.
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900