Share via


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

Comments

  • Anonymous
    August 11, 2005
    Calvin,

    It's not working when I select an area on the photo. It just flashes and goes back to original image.

    p.s. this code solves the code copying and pasting from your post:

    _cliptext = STRTRAN(_cliptext,CHR(13)+CHR(13),CHR(13))

  • Anonymous
    August 11, 2005
    Hi Calvin,

    Nice use of GDI+ and a decent example of how to create a rubberband selection feature. As for the Child window of a Visual FoxPro TopLevel form, I detailed this in an FoxTalk 2.0 article that might be of interest to you, a couple of other solutions for getting the child window's hwnd and a link to the GDI+ article...


    !* Using only Visual FoxPro 9

    Local lnHwnd
    lnHwnd = SYS(2327, SYS(2325, SYS(2326,THISFORM.hwnd)))


    ! Using GetWindow API function
    *
    #DEFINE GW_CHILD 5
    DECLARE LONG GetWindowLong IN User32 LONG HWND, INTEGER nIndex
    Local lnHwnd
    lnHwnd = IIF(THISFORM.SHOWWINDOW = 2, GetWindow(THISFORM.HWND,GW_CHILD), THISFORM.HWND)

    Here's the link for the "GDI+ on VFP 9 Forms" article (the real link is about a mile long, so I'm giving you a tinyurl that points to it)

    http://tinyurl.com/bpas8

  • Anonymous
    August 11, 2005
    The comment has been removed

  • Anonymous
    August 11, 2005
    If it doesn't work for you, try a larger JPG: apparently it only works with JPGs with my kids in them (about 1 Meg). It's a timing issue: it is working with the smaller JPGs (you might see it flicker) but then a WM_PAINT message is processed which refreshes the original JPG.

  • Anonymous
    August 11, 2005
    I've modified the code to call ValidateRect so that the WM_PAINT won't overwrite the zoomed in area. It's also using Craig's suggestion about using the SYS functions.
    Thanks for the helpful explanation and links Craig. I wrote those SYS functions years ago. I hope you find them “decent” too<g>

  • Anonymous
    August 11, 2005
    The comment has been removed

  • Anonymous
    August 12, 2005
    In my last post Enable crop and zooming in on your digital photograph display form&amp;nbsp; there is code...

  • Anonymous
    August 12, 2005
    Thank you Craig for the explaination!

    Calvin, if use ScrollBars = 3, then the croping doesn't work. Also when you single click on it, it goes back to the original image. I noticed this when tried to zoom futher.

    Add the following code in the INIT event:
    <pre>
    this.ScrollBars = 3 this.AddObject("btn","commandbutton")
    this.btn.Left = 500
    this.btn.Width = 500
    this.btn.Height= 500
    this.btn.Visible = .t.
    </pre>

  • Anonymous
    August 13, 2005
    After having read a post on Calvin Hsia's weblog, I decided to try my hand at cr

  • Anonymous
    August 19, 2005
    Calvin,

    I created a class based on your idea here for a rubberband selection. If you haven't seen it yet, you can at:

    http://www.sweetpotatosoftware.com/SPSBlog/PermaLink,guid,de3b099f-bca6-471e-89bf-ae094b823780.aspx

    Keep up the great Visual FoxPro related blog entries and ideas!

  • Anonymous
    February 16, 2007
    Good job and great design!,Good job and great design!

  • Anonymous
    March 12, 2007
    mmm.. nice design, I must say..

  • Anonymous
    March 16, 2007
    Lo trovo piuttosto impressionante. Lavoro grande fatto..)

  • Anonymous
    March 18, 2007
    Stupore! ho una sensibilit molto buona circa il vostro luogo!!!!

  • Anonymous
    April 07, 2007
    9 su 10! Ottenerlo! Siete buoni!

  • Anonymous
    April 12, 2007
    L'information interessante que vous avez! I'am allant revenir bientot.

  • Anonymous
    September 13, 2007
    I received a customer question: I have looked all over the web and still searching, and found your blog.

  • Anonymous
    September 13, 2007
    I received a customer question: I have looked all over the web and still searching, and found your blog

  • Anonymous
    December 22, 2007
    <a href= http://wwwjcpennys.testlocseries1.info/ >www jc pennys

  • Anonymous
    December 22, 2007
    <a href= http://wwwjcpennys.testlocseries1.info/ >www jc pennys

  • Anonymous
    August 21, 2008
    Today’s digital cameras take pictures with much higher resolution than many computer screens. My Canon

  • Anonymous
    January 20, 2009
    PingBack from http://www.hilpers-esp.com/486064-trabajo-con-graficos