Click here to Skip to main content
15,947,958 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm developing an MFC doc-view based Image viewer application. The viewer have option for zooming & panning image.
For displaying the image I'm using stretchBlt GDI function.
StretchBlt(
int x,
int y,
int nWidth,
int nHeight,
CDC* pSrcDC,
int xSrc,
int ySrc,
int nSrcWidth,
int nSrcHeight,
DWORD dwRop
);



The destination stretch window size for StretchBlt is calculating based on Image aspect ratio (nSrcWidth / nSrcHeight) and window aspect ratio. And the image is placed on the center of the
window.

I implemented zoom functionality by varying the destination stretch window size(nWidth x nHeight) based on the zoom factor(by multiplying both width & height values with zoom factor).


Also panning is implemented by shifting destination stretch window start points(x & y) values based on pan shift values(by adding corresponding pan height & width values to x & y).

And I'm keeping xSrc & ySrc values as 0 and nSrcWidth and nSrcHeight value as such of the original image.

The image viewer and zoom and pan operations are working properly.

My actual problems I need to implement zooming based on a point in displaying image.

If I zoom select a point on the image by clicking in corresponding displaying window point, after zooming the same image pixel (in zoomed image)should be displayed in same window point.
How would I can implement this?

Below is an abstract of my code
CMyView:: OnDraw(CDC pDC)
{
CRect rcClient(0, 0, 0, 0);
GetClientRect(rcClient);
m_ImagActSize = pDoc->GetImageSize();
// m_ImageSize is CSize global member of my class which contain actual size of image.
const int cx = rcClient.right; // view client area width
const int cy = rcClient.bottom; // view client area height
const int bx = m_ImagActSize.cx; // source bitmap stretch width
const int by = m_ImagActSize.cy; // source bitmap stretch height


const int vx = (int)(bx * m_fZoom * m_pdnXMapRatio);
// vx:- virtual document width

// m_fZoom : which will vary with selected zoom operation

//m_pdnXMapRatio : This value is a factor (width) which is calculated based on aspect ratio of image and clent area. This is used to maintaion aspect ration of image in window.


const int vy = (int)(by * m_fZoom * m_pdnYMapRatio);
xDtn = m_xShift + m_xPanValue;
yDtn = m_yShift + m_yPanValue;
//m_xShift : a constant width shift value which is for centering the image in client window.
//m_yShift : a constant height shift value which is for centering the image in client window.
//m_xPanValue & m_yPanValue : width & height pan value which will be varied in pan operation.
// vy:- virtual document height
// m_fZoom : which will vary with selected zoom operation
//m_pdnYMapRatio : This value is a factor(height) which is calculated based on aspect ratio of image and clent area. This is used to maintaion aspect ration of image in window.

CImage& Image = pDoc->GetImage();
pDC->SetStretchBltMode(COLORONCOLOR);
Image.StretchBlt(pDC->GetSafeHdc(), xDtn, yDtn, vx, vy, 0, 0, bx, by, SRCCOPY);
}



I think ,this can be achieved by varying Dest window start values(x & y) based on the zoom .
For this I need to know
how stretchBlt function Stretches or Shrink the image based on sizes of image & displaying screen window?
how could exactly calculate how much the window start points should be shifted(while zoom) to correlate the relation between image pixel & window pixel?

Can anyone support to solve this issue?
Posted
Updated 26-Mar-14 1:28am
v2

1 solution

I think your destination values should stay constant, but the source values should change to reflect your zoom state. (width/heigth)

If you want to shift the origin, than you have also to change the x and y by the difference divided by zoom factor.

The rastering ops of StretchBlt is very simple. It interpolates linear. If you need better quality you have to look for some better solutions. At Codeproject like Imagestone or CXImage.

read the MSDN again carefully: http://msdn.microsoft.com/en-us/library/windows/desktop/dd145120(v=vs.85).aspx[^]

and try it out ;-)
 
Share this answer
 
Comments
the vacuum 27-Mar-14 1:07am    
Thank you very much for the solution...
Sorry for the inconvenience I couldn't understand what you mean by the statement
"If you want to shift the origin, than you have also to change the x and y by the difference divided by zoom factor."
Do you mean x & y of the source(xSrc & ySrc parameters in StretchBlt) or the destination window (x & y parameters)?
another doubt is
what you mean by "difference" difference between which values?


Currently my program working properly except this requirement. I had analyzed image processing libraries like CxImage on the starting, but as i application is simple one I don't need them.
My doubt about StretchBlt is about the mapping of image to destination window while it varies. For example my image size is 100 x 100 and my destination window size is 50 x 70 then In to which pixel of the destination rectangle the image pixel(50, 50) will be displayed?
Also if the destination rectangle size changes to (500 x 600) then to where the image pixel(50, 50)will be mapped to?.
I expect, if find a solution to calculate the mapping between the image pixels to the destination pixel, the image pixels can be relocated to any pixel in window coordinates.

My understanding is that the CSrollView::GetScrollPosition method gives the documents width & height point in left top position of scroll window. Like that have any function available in CView?
KarstenK 27-Mar-14 3:34am    
I mean if you zoom around a point. Like clicking in the middle. Than you need to calculate new start coords on the origin.

I strongly recommand that the x and y zoom is the same so the pic isnt distourched.

You must better understand that you take the pixels from the source with start coords and dimension and "stretch" them to the dest coords and it dimensions.

Use a simply pic and play it out. Sometimes it helps to draw some coords on paper.

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