Call GDI+ JPG manipulation from Excel, Word, Powerpoint, VB.NET

Here’s a way to manipulate photos from within some Microsoft products.

In the prior post, I wrote some code to write and draw directly on a JPG image. It draws text, a timestamp, and an ellipse with a gradient brush onto a JPG and then saves it out to a new filename.

The code below is almost identical to the code from the prior post, but now it runs from the VFP runtime and thus can be called from other applications.

I’ve used the directory “C:\” as a place to put files. You can change this as you like. You can also build a project that includes _gdiplus.vcx, so you don’t need a copy in c:\

Start Excel, choose Tools->Macro->Visual Basic Editor (Alt-F11). Then choose Insert->Module, then paste the Excel code below. Hit the F5 button (Run) and watch your newly altered JPG be inserted into the spreadsheet.

Proceed similarly for the Word and Powerpoint samples below.

To figure out the commands in Word, Excel, etc, I just recorded a macro and then edited it to see the code.

If you figure out how to run this code in other applications, like Access, please let me know.

The VFP COM server is the universal VFP COM object from this blog.

There is not much error handling.

The compiler is in the runtime, so you can alter the code without using VFP. Note that if you CLEAR PROGRAM, the FXP is cleared from VFP’s cache if it’s not in use, and thus can be modified and compiled again.

Excel

Sub foo()

Set ox = CreateObject("t1.c1")

ox.MyDoCmd ("set path to c:\")

ox.MyDoCmd ("COMPILE c:\WriteJpg")

ox.MyDoCmd ("WriteJpg('c:\kids.jpg','Fox Rox')")

ox.MyDoCmd ("clear program")

    ActiveSheet.Pictures.Insert("c:\t.jpg").Select

End Sub

Word

Sub foo()

Set ox = CreateObject("t1.c1")

ox.MyDoCmd ("set path to c:\")

ox.MyDoCmd ("COMPILE c:\WriteJpg")

ox.MyDoCmd ("WriteJpg('c:\kids.jpg','Fox Rox')")

ox.MyDoCmd ("clear program")

        Selection.InlineShapes.AddPicture FileName:="c:\t.jpg", LinkToFile:=False, _

         SaveWithDocument:=True

End Sub

Powerpoint

Sub foo()

Set ox = CreateObject("t1.c1")

ox.MyDoCmd ("set path to c:\")

ox.MyDoCmd ("COMPILE c:\WriteJpg")

ox.MyDoCmd ("WriteJpg('c:\kids.jpg','Fox Rox')")

ox.MyDoCmd ("clear program")

    ActiveWindow.Selection.SlideRange.Shapes.AddPicture(FileName:="c:\t.jpg", LinkToFile:=msoFalse, SaveWithDocument:=msoTrue, Left:=-93, Top:=-70, Width:=909, Height:=682).Select

End Sub

VB.Net: (add a reference to T1.c1 typelib)

   Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim ox As New t1.c1

        ox.MyDoCmd("set path to c:\", 0, 0, 0, 0)

        ox.MyDoCmd("COMPILE c:\WriteJpg", 0, 0, 0, 0)

        ox.MyDoCmd("WriteJpg('c:\kids.jpg','Fox Rox')", 0, 0, 0, 0)

        ox.MyDoCmd("clear program", 0, 0, 0, 0)

        Dim pb As New PictureBox

        pb.Width = 800

        pb.Height = 600

        Me.Controls.Add(pb)

        pb.Image = Drawing.Image.FromFile("c:\t.jpg")

    End Sub

#define JPGFILE "c:\kids.jpg"

TEXT TO ctemp noshow

PROCEDURE WriteJpg(cFilename,cNewText)

      TRY

            gdipToken=0

            IF _vfp.StartMode=0

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

            ELSE

                  SET CLASSLIB TO c:\_gdiplus

                  IF _vfp.StartMode = 5

                        DECLARE INTEGER GdiplusStartup in gdiplus integer @ lpToken,string @ GdiplusStartupInput_lpInput,integer ptr_lpOutput

                        DECLARE INTEGER GdiplusShutdown in gdiplus integer lToken

                        gdipToken=0

                        gdipStartupStruct=CHR(1)+REPLICATE(CHR(0),4*4-1)

                        GdiplusStartup(@gdipToken,@gdipStartupStruct,0)

                  ENDIF

            ENDIF

           

            LOCAL oGraphics as gpgraphics

            LOCAL oBrush as gpsolidbrush

            LOCAL orect as gprectangle

            LOCAL oImage as gpimage

            oImage=CREATEOBJECT("gpimage",cFilename)

            oGraphics=CREATEOBJECT("gpgraphics")

            ltrim("next local")

            IF !oGraphics.CreateFromImage(oImage)

                  THROW "CreateFromImage "+cFilename

            ENDIF

            oGraphics.DrawStringA(cNewText+iif(_vfp.startmode=0,' Design ',' Runtime ')+;

                  TRANSFORM(DATETIME()),;

                  CREATEOBJECT("gpfont","Verdana",26,1,3),;

                  CREATEOBJECT("gprectangle",0,0,880,425),;

                  CREATEOBJECT("gpstringformat"),;

                  CREATEOBJECT("gpsolidbrush",0xcff00060)) && change the solidbrush color

            DECLARE integer GdipCreateLineBrushFromRect ;

                  IN gdiplus.dll string,integer,integer,integer, integer, integer @

            nlBrush=0

            orect= CREATEOBJECT("gprectangle",0,0,100,30)

            GdipCreateLineBrushFromRect(oRect.GdipRectF,;

                  0xffff0000,0xff00ff00,3,1,@nlBrush)

            oBrush=CREATEOBJECT("gphatchbrush",4)

            oBrush.SetHandle(nlBrush)

            oGraphics.FillEllipse(oBrush,;

                  CREATEOBJECT("gprectangle",400,600,680,325))

            IF !oImage.SaveToFile("c:\t.jpg","image/jpeg")

                  THROW "error saving"

            ENDIF

      CATCH TO oexcept

            DECLARE integer MessageBoxA IN WIN32API integer, string,string,integer

      MessageBoxA(0,oexcept.UserValue+":"+oexcept.message+":"+oexcept.details+":"+TRANSFORM(oExcept.lineno),"",0)

      ENDTRY

      IF gdipToken>0

            GdiplusShutdown(gdipToken)

      ENDIF

RETURN

ENDTEXT

STRTOFILE(ctemp,"c:\WriteJpg.prg")

SET PATH TO c:\

COMPILE writejpg

*writejpg("c:\kids.jpg","Fox Rox!")&& call it from design time

#if .t.

      USE HOME()+"ffc\_gdiplus.vcx"

      COPY TO c:\_gdiplus.vcx && make a copy for the runtime

      LOCAL ox as t1.c1

      ox=CREATEOBJECT("t1.c1")

      ox.MyDoCmd("set path to c:\")

      ox.MyDoCmd("COMPILE c:\WriteJpg")

      ox.MyDoCmd("WriteJpg('"+JPGFILE+"','Fox Rox ')")

#endif

*now show the new image from vfp

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

oImage=CREATEOBJECT("gpimage","c:\t.jpg")

oGraphics=CREATEOBJECT("gpgraphics")

oGraphics.CreateFromHWND(_screen.HWnd)

orect= CREATEOBJECT("gprectangle",0,0,800,600)

oGraphics.DrawImageScaled(oImage,oRect)