Enable crop and zooming in on your digital photograph display form

I wanted to add the ability to zoom into a portion of a photograph on my photo viewer. Below is some code that processes the MouseUp, MouseDown and MouseMove events to add a yellow dotted-dash selection rectangle using a Shape control that the mouse can resize over the desired portion of a picture to crop/zoom.

Using the image control with Stretch set to Isometric means to keep the image’s original proportions (so skinny people stay skinny). That means that if the image control’s aspect ratio (width/height) is different from that of the original picture, either the top/bottom edges or the left/right edges of the image surface will be blank. Thus, calculating the crop rectangle gets a little complicated.

An additional complication arises when the ShowWindow is set to show the form as a top level form. The hWnd needed to draw the image is the client window of the form. WindowFromPoint is called to get the window from an x/y position.

The DrawImagePortionScaled routine of _gdiplus.vcx is called to do the scaling and drawing.

Now I can zoom in on that book on the bookcase in the background of the photo to read the title and author!

PUBLIC x

x=NEWOBJECT("pform")

DEFINE CLASS pform as form

left=00

width=600

height=300

ShowWindow=1

allowoutput=.f.

ADD OBJECT img as myimage

PROCEDURE init

this.img.visible=1

this.img.picture="d:\kids.jpg"

this.img.height=thisform.height

this.img.width=thisform.width

this.visible=1

DECLARE integer ValidateRect IN WIN32API integer, integer

ENDDEFINE

DEFINE CLASS myimage as Image

stretch=1

nState=0

PROCEDURE mousemove(nBut,nShift,x,y)

IF this.nState=1

IF x > thisform.dr.Left

thisform.dr.width=x - thisform.dr.Left

ENDIF

IF y > thisform.dr.Top

thisform.dr.height = y -thisform.dr.Top

ENDIF

ENDIF

PROCEDURE mousedown(nBut,nShift,x,y)

IF this.nState>0

thisform.dr.visible=0

this.picture=this.picture

this.nState=0

RETURN

ENDIF

IF VARTYPE(thisform.dr)='U'

thisform.AddObject("dr","myshape")

ENDIF

thisform.dr.top=y

thisform.dr.left = x

thisform.dr.height=1

thisform.dr.width=1

thisform.dr.visible=1

this.nState=1

PROCEDURE mouseup(nBut,nShift,x,y)

IF this.nState#1

RETURN

ENDIF

this.nState =2

thisform.dr.visible=.f.

thisform.img.picture=thisform.img.picture &&paint over sel rect

SET CLASSLIB TO HOME()+"ffc\_gdiplus"

LOCAL oGraphics as gpGraphics OF (HOME()+"ffc\_gdiplus")

LOCAL oRectDest as gpRectangle OF (HOME()+"ffc\_gdiplus")

LOCAL oImage as gpImage OF (HOME()+"ffc\_gdiplus")

oImage=CREATEOBJECT("gpImage",thisform.img.picture)

oGraphics=CREATEOBJECT("gpgraphics")

wRatio=oImage.ImageHeight/oImage.ImageWidth && 1704/2272 .75

pRatio=thisform.img.Height/thisform.img.Width && 300/600 .5

*Must compensate for Stretch=1 (Isometric)

IF wRatio>pratio

wwidth=thisform.img.height/wRatio

wleft=thisform.img.left+(thisform.img.width - wwidth)/2

wtop=thisform.img.top

wheight=thisform.img.height

oRectSrc=CREATEOBJECT("gpRectangle",;

(thisform.dr.left-wleft)*oImage.ImageWidth/wWidth,;

(thisform.dr.top - thisform.img.top) *oImage.ImageHeight/thisform.img.height,;

thisform.dr.width*oImage.ImageWidth/wWidth,;

thisform.dr.Height * oImage.ImageHeight/thisform.img.height)

ELSE

wwidth=thisform.img.width

wleft=thisform.img.left

wheight=thisform.img.width*wRatio

wTop=thisform.img.top+(thisform.img.height-wheight)/2

oRectSrc=CREATEOBJECT("gpRectangle",;

thisform.dr.left * oImage.ImageWidth/thisform.img.width,;

(thisform.dr.top-wtop) *oImage.ImageHeight/wheight,;

thisform.dr.width * oImage.ImageWidth/thisform.img.width,;

thisform.dr.Height *oImage.ImageHeight/wheight)

ENDIF

oRectDest=CREATEOBJECT("gpRectangle",wleft,wtop,wwidth,wHeight)

hWnd=SYS(2327, SYS(2325, SYS(2326,THISFORM.hwnd))) && From Craig Boyd

oGraphics.CreateFromHWND(hWnd)

oGraphics.DrawImagePortionScaled(oImage,oRectDest,oRectSrc,2)

ValidateRect(hWnd,0)

ENDDEFINE

DEFINE CLASS myshape as Shape

bordercolor=65535

BackStyle=0 && transparent

BorderStyle=4

ENDDEFINE