Showing posts with label Charting. Show all posts
Showing posts with label Charting. Show all posts

2020-04-12

VFP Paint Revisited - 2020


Here's a brand new version of VFPPAINT, a sample that I created using the GdiPlusX library that works much like MSPAINT, and creates a canvas that permits you to draw whatever you want with the mouse.

If you are not aware of what I'm talking about, you might be interested in checking this blog post..

VFPPAINT now has become much bigger than the original 50k SCX from the first version. Now it has become a VFP project, and received some important improvements, such as fast and reliable drawing, and the possibility to work with modal forms. many new and cool features were added too.

In this revamped version, I'm introducing the
   Paint Bucket - used to fill an area with single specific color. Select the bucket and position the cursor over the area to be filled and click with the Left mouse button to fill with the Primary color.

That's a cool feature that I introduced to GdiPlusX a long time ago, but forgot to document. I even think that the current release does not bring a sample dealing with it.





First of all, thanks for the positive feedback that many readers have sent, and all the suggestions.



Important requires VFP9 and GdiplusX to run.  
Please make sure that you have the latest version, because VFPPAINT uses some functions that were added recently.

http://www.codeplex.com/vfpx/wiki/view.aspx?title=gdiplusx&referringtitle=home


When you run VFPPAINT.scx it will ask you to select the folder where gdiplusx library is located.



What's new on this version:

1 - main screen may be modal, modeless, toplevel or inscreen - this was a problem in the first version. in that case, to obtain scrollbars in my canvas for the case that the image could not fit in the screen, I created a child form, that worked inside the main form. then the child form was configured to show scrollbars when needed. but working with this configuration, the main form had to be a toplevel form, and it was not possible to make that form modal.



Thanks to Carlos Alloatti and Malcolm Greene for their great "scrollablecontainer", I was able to use just a single control, and concentrate just on the drawing codes, I confess that it was a little bit complicated to control the form scrollbars and the image position in the original way. now this is all done by the scrollable container. Thanks very much Carlos for your support to make it work as I desired. Anyway, some tweaks were needed to be aplied in this control to make it behave exactly as I needed, and I created my customized version. Check the file SCONTAINERTWEAKS.TXT in the "source" folder.



2 - faster image drawing - I confess that the original version worked really sloooooow when direct drawing on the canvas. that's because vfp and gdiplusx has to work a lot in order to draw the image. After detecting the mouse position, cloning the original image for undo purposes, I used gdiplusx to obtain the pictureval of the bitmap, and then the image pictureval property was updated. obtaining the pictureval was the slowest operation. in this new version, I'm using gdi+ to draw du]irectly on the screen, using the hwnd of the form, when the left button of the mouse is pressed. only when the user releases the button or when he leaves the canvas surface is that the pictureval of the image object is updated, check it by yourself, this brought a huge performance gain !



3 - cut, copy and paste - these possibilities were added too. now you can select any portion of the image, cut or copy to the clipboard, and paste in any other application, or even inside vfppaint, moving pieces of images inside the canvas. it supports also that you paste any image from the clipboard. you can capture any screen using the prtscrn key and paste it there.



4 - drag and drop pieces of images. this brings the possibility to apply some effects in the whole image or just in the specified region.





5 - special color effects - there were lots of other cool things that I wanted to add, but no more space was available in the original form, so i've created a child form that agrupates some slidebars that will control the image colors, like: contrast, saturation, brightness, gamma, hue and adjusting each of the basic colors individually.





6 - other color effects - with just one click obtain monochrome, greyscale and invert the colors (negative)





7 - image transformations - another child form permits you to rotate the image by a desired angle, scale and shear vertically or horizontally.



8 - other tweaks, small fixes and optimizations. all methods were revised in order to enhance the performance and reliability.



Main features

- draw points, rectangles lines and ellipses with the mouse.

- text drawing, choose any font, size and style, and it will appear at the place that you click on the image. (drag and drop to choose the best place)

- choose any color, from the palette or directly from the loaded image or canvas and select the pen width that you want to draw.

- select the shape or type of drawing in the graphical option buttons, and then go to the canvas (image object) and click the left mouse button.

- drag and drop is available for rectangles, lines and ellipses.

- basic undo features

- rotate and flip images

- resizing images

- printing and saving images

- scale, shear and rotate images

- apply image effects, like greyscale, saturation, contrast, brightness, and more



Basic commands

    load image to canvas
    save image in desired image format
    print image
    undo last changes



  pick color from palette
   clear entire canvas with selected color
  rotate left (whole or selected image)
  rotate right (whole or selected image)
   flip image horizontally (whole or selected image)
  flip image vertically (whole or selected image)

   no action

   draw points

   draw rectangle

   draw ellipse

   draw line

   fill rectangle

   fill ellipse

   draw string

   select a piece of the image, to be cut, copied, dropped or receive an effect

   pick color from canvas

   select font, size and type


   convert to greyscale

   convert to monochrome

   convert to negative


   calls child form that enables different kinds of resizing






   calls child form that allows scaling, shearing and rotating the image




   calls child form that allows several color effects to the image

    



   send the selected piece of image to the clipboard
   copy the selected piece of image to the clipboard
   paste image from the clipboard to the canvas

   paste special, allowing to choose the destination of the image

   paint bucket is used to fill an area with single specific color. Select the bucket and position the cursor over the area to be filled and click with the Left mouse button to fill with the Primary color.


All images are generated without disk access, using the new pictureval property of the image control. For this specific case, I didn't use the imagecanvas that ships with gdiplusx because I needed some extra customization. after the latest release of gdiplusx, getting the pictureval property of an image has became very simplified, with the new methods added to the image class - getpictureval and getpicturevalfromhbitmap.

As sometimes we need to work with an image that is bigger than our screen, the drawing canvas was put in a "in toplevelform" that has scrollbars.

Another cool feature is the "undo" possibilities. vfppaint stores the previous bitmap in a cache. this can be improved too, maybe you need to "undo" in higher level. for this, very few code is needed.

When drawing on the canvas, try dragging and dropping the objects. for this, the "undo" feature was highly used, because the shape is drawn, and when the user moves the mouse, it restores the original image from the buffer and draws again in the new position.


When a big sized image is loaded, first it asks if the canvas needs to be resized.



Scrollbars appear in the image to help dealing with it. in a first moment, I thought of using the very nice ctl32 scrollable container from Carlos Aloatti and Malcolm Greene, but I gave up because I needed the pictureval property, that is present only in the default image control. So, there are currently 2 forms in the screenshot below. one is a "in TopLevel" form that contains just one image object, and resides in the main VFPPAINT form. the other form is a "TopLevel form". The image object from the "child form" changes its size automatically, depending on the image dimensions. When this object is resized, the child form automatically resizes itself, and shows and adjusts the scrollbars if needed.





Resizing sample:


VFPPAINT also accepts that you pass an image file as a parameter. this way, you'll be able to open the form loading automatically the desired image to edit. run the form like this:

do form vfppaint with "eyes.gif"

In case you pass a gif image as a parameter, it will be automatically converted to 24bpp. that's because gifs are indexed images. a classic example of indexed images are monochrome. pure monochrome images use only 1 bit per pixel. So, in just one byte you can store information of 8 pixels ! in the case of gifs, they are usually 8 bits per pixel, so in one bit we can have a value that ranges from 0 to 255 - that's exactly the quantity of colors supported by GIFs! Unfortunately, the redistributable version of GDI+ has a limitation when working with images created in indexed pixel formats, such as 1bppindexed (0x00030101), 4bppindexed (0x00030402) and 8bppindexed (0x00030803). If you try to draw on this kind of images you'll always receive an error message when you'll create the graphics object, that permits to you to draw on the image. more detailed info about this can be found in this post: drawing on gifs or indexed pixel format images with gdi+  http://weblogs.foxite.com/vfpimaging/archive/2006/03/18/1302.aspx . That's why gifs are converted to a 24bpp format before initializing the painting possibilities.

But the main thing is that this totally customizable. Study the technique that was used, and you'll see that there's not too much code there.




Download link
Download VFP PAINT REVISITED

2011-03-14

FoxCharts new release - with Double Y Axis

Just uploaded a new release of FoxCharts, a VFP-X project 

This version brings the so asked "double Y axis" charts as the main change.
  • Multicharts with negative values that were not being drawn correctly in some situations;
  • Line charts are drawn much faster (5x faster) when drawing with line caps (with shapes in the chart intersections);
  • Other small tweaks
        https://github.com/VFPX/FoxCharts/tree/master/FoxCharts_1.37b

        Have a look at the sample "chartssample_builder_2y.scx" in the samples folder of FoxCharts
        Just some few but important comments:
        1. needs to use depth = 0 (max 2)
        2. preferrably 2 data lines, one using the left axis and the other for the 2nd
        3. set the legends to the top

        Pay attention to the new properties:
        • ChartType = 18          && the newest chart type
        • Fields(n).AxisIndex = 2 && to what axis the data will correspond (1 = default)
        • LegendPosition = 6      && top center

        Having this, now you are able to create a chart like this, with no effort:



        Here is a simple script showing how to achieve the chart below directly:



        create cursor sales( ; 
            chart1 i null, ;
            chart2 i null, ;
            legend c (30) NULL)
        
        insert into sales values (130,      0, "jan")
        insert into sales values (120,  25000, "feb")
        insert into sales values ( 45,  50000, "mar")
        insert into sales values ( 60,  75000, "apr")
        insert into sales values ( 75, 100000, "may")
        insert into sales values (110, 135000, "jun")
        
        set classlib to locfile("foxcharts.vcx")
        
        public oform as form
        oform = createobject("form")
        oform.newobject("ochart","foxcharts","foxcharts.vcx")
        
        local loChart as Foxcharts of "foxcharts.vcx"
        loChart = oForm.oChart
        
        with loChart
             .Backcolor = rgb(255,255,255)
             .BrushType = 2
             .ChartsCount = 2
             .ChartType = 18
             .ColorType = 1
             .Depth = 0
             .FieldAxis2 = 'legend'
             .FieldLegend = 'legend'
             .FontName = 'verdana'
             .Height = 288
             .LegendPosition = 6
             .SourceAlias = 'sales'
             .Width = 732
        
             with .subtitle
                  .caption = 'chart subtitle'
             endwith
        
             with .title
                  .caption = 'testing 2nd y axis'
                  .forecolor = rgb(0,128,255)
             endwith
        
             with .fields(1)
                  .axisindex = 1
                  .color = rgb(255,0,191)
                  .fieldvalue = 'chart1'
                  .legend = 'gr1'
                  .shape = 5
             endwith
             with .fields(2)
                  .axisindex = 2
                  .color = rgb(0,142,146)
                  .fieldvalue = 'chart2'
                  .legend = 'gr2'
                  .shape = 2   && 'vfpxicon.png'
             endwith
             loChart.DrawChart()     loChart.Visible = .t.
        endwith
        
        oForm.Width  = loChart.Width
        oForm.Height = loChart.Height
        oForm.Show()

        2006-06-16

        GDIPLUS FOR ALL VFP VERSIONS

        As we all know, gdiplus.dll brings many new possibilities to vfp users.
        Gdiplus.dll is a free and redistributable library provided by microsoft, that must be used only in windows (R) systems.

        Alexander Golovlev may have been the first person to publish a class that dealed with this fantastic library. He created the class GPIMAGE.PRG, that was published in 2003 in the UniversalThread / LevelExtreme downloads area.

        https://www.levelextreme.com/Home/ShowHeader?Activator=17&ID=18584

        GpImage came a long time before VFP9, and is supposed to work with VFP7 and above. Probably works with previous versions, but i've not tested. It's a great library, providing a wrapper class to deal with Gdi+. The original class works with the image class, and has most functions that the gpimage class from _GdiPlus.vcx (from the VFP9 FFC) brings, and some other really interesting, providing windows captures, cropping images and some other cool functions.

        Under the authorization of Alexander Golovlev, and with his help and support, I added some functions to the original GpImage class published in UT.

        Basically we included a graphics class.
        New methods included let you draw rectangles, lines, ellipsis, pies, strings and pictures on images. brings the possibility to control alignment, size, orientation, rotation, of any shape, text or picture.
        It is possible to work with image attributes too, changing colors of images, like convert to B&W or gray scale, increase a color, etc.

        This class is based on GDI+ and requires gdiplus.dll which is freely available and can be installed on win98 and higher. If you have not installed WinXP or .NET runtime then you can download this dll from
        http://www.microsoft.com/downloads/details.aspx?familyid=6a63ab9c-df12-4d41-933c-be590feaa05a&displaylang=en

        The link for the enhanced class gpimage that deals with gdiplus.dll is :
        http://vfpimaging.blogspot.com/p/gpimage2.html

        There you can find also a FAQS link, with many samples using the class.
        Download, open the examples folder, where you can find many small prgs and forms dealing with the class.

        There is a cool example of a form that changes contrast, saturation, brightness (testgpimage.scx), another usage of a pie charts class (objpie.prg), and also printing vertical or upside down texts in vfp reports (see testefrx.prg and teste.frx).

        The class is more recommended for people that still have not upgraded to VFP9 and need to use GDI+. It's a long time since I don't send an update to this class.
        There are many other new features that can be added to the library, like getting metadata information, gradient color brushes, etc.

        Recently, I've been using my free time to develop using the new _Gdiplus.vcx class and the fantastic new VFPX classes - aka GDIPLUSX.
        http://vfpimaging.blogspot.com/p/gpimage2.html

        2006-03-24

        PIE GRAPHICS WITH PURE VFP CODE

        Did you know that it is possible to draw pie style graphics in vfp without the need of any active-x or api call ? With pure VFP code ? draw a circle with foxpro
        To draw any circle, there are two main parameters : 1 point with the coordinates of the center of the circle (x,y) and the radius. having this, it is very simple to calculate the coordinates of any point in the circumference border.
        Even if you already use gdi+ or any active-x to draw graphics, I think it's imteresting to know how a circle is built, and how to calculate the positions of each point.

        For this purpose, I'll need to make you remember the concepts of sine and cosine : 

        In any right angled triangle, for any angle:

        sine of the angle = length of the opposite side / length of the hypotenuse
        cosine of the angle = length of the adjacent side / length of the hypotenuse


        hypotenuse of a right angled triangle is the longest side, which is the one opposite the right angle. The adjacent side is the side which is between the angle in question and the right angle. The opposite side is opposite the angle in question.

        So, imagine a right angled triangle inside a circumference, like in the picture below.

        sine of angle = opposite side (height or y) / hypotenuse (radius) !!!

        height = sine of angle * radius

         

         

        cosine of angle = adjacent side (width or x) / hypotenuse (radius) !!!

        width = cosine of angle * radius

         

        Now we can create a loop starting from angle 0 (zero) and finishing at angle 360 degrees. At each step we can calculate the position of every point of the circle !

        Then it becomes quite simple to draw the graphic. for that purpose, I'll use the line object, drawing lines from the center of the circle till the point x,y just calculated. and that's all !!!

        There's one problem with the line object in VFP. To draw a line, we need to use the properties top, left, width, height and lineslant (specifies which way a line slants, from upper left to lower right or lower left to upper right), instead of simply passing the two points, x1y1 and x2y2. so, as you can see in the code below, depending on the angle and the resulting position in the quadrant (quarter of the circumference of a circle), I needed to make some extra code to deal with this. Pay attention to the "do case" command below.

        Procedure DrawPie

        LPARAMETERS tnCenterX, tnCenterY, tnRadius, tnStart, tnEnd, tnColor
        
        LOCAL lnLineWidth, N, x, Y, lcObj, lnPointLeft, lnPointTop, lcSlant
        m.lnLineWidth = 3
        
        FOR m.N = m.tnStart TO m.tnEnd STEP (1 * m.lnLineWidth)
            m.x = COS(DTOR(m.N)) * m.tnRadius
            m.Y = SIN(DTOR(m.N)) * m.tnRadius
        
            m.lcObj = "line" + TRANSFORM(m.N * 100)
            THISFORM.container1.ADDOBJECT(m.lcObj,"line")
        
            DO CASE
                CASE m.N >= 0 AND m.N < 90 && 1st quadrant
                    m.lnPointLeft = m.tnCenterX
                    m.lnPointTop = m.tnCenterY – m.Y
                    m.lcSlant = "/"
        
                CASE m.N >= 90 AND m.N < 180 && 2nd quadrant
                    m.lnPointLeft = m.tnCenterX + m.x
                    m.lnPointTop = m.tnCenterY – m.Y
                    m.lcSlant = "\"
        
                CASE m.N >= 180 AND m.N < 270 && 3rd quadrant
                    m.lnPointLeft = m.tnCenterX + m.x
                    m.lnPointTop = m.tnCenterY
                    m.lcSlant = "/"
        
                CASE m.N >= 270 AND m.N <= 360 && 4th quadrant
                    m.lnPointLeft = m.tnCenterX
                    m.lnPointTop = m.tnCenterY
                    m.lcSlant = "\"
            ENDCASE
        
            WITH THISFORM.container1.&lcObj.
                .LINESLANT = m.lcSlant
                .BORDERCOLOR = m.tnColor
                .BORDERWIDTH = m.lnLineWidth
                .WIDTH = ABS(m.x)
                .HEIGHT = ABS(m.Y)
                .LEFT = m.lnPointLeft
                .TOP = m.lnPointTop
                .VISIBLE = .T.
            ENDWITH
        
        ENDFOR
        RETURN

        You may find this procedure slow, specially if you run it in slow machines, but it works ! the biggest problem is that it adds many objects in a form, in the case of a loop with step 1, at least 360 lines !
        If we draw a line with borderwidth = 1, in some cases, the calculated points will create some holes between the lines. a wider border will resolve this problem. the bigger the step in the loop (from 0 to 360 degrees), the faster the procedure will run, and less objects will be added.
        Run the form piegraphics.scx from the attached file, change the cursor, radius, step, and linewidth values, and check all procedures to better understand this post.

        What next ?

        Of course, in one of my next posts I'll deal with pie style graphics using Gdi+ – Google for the keyword FOXCHARTS, for a great surprise made in pyure VFP9 code.
        Some of the subjects discussed here will help us to create more interesting graphics.