Special effects on images with new GDIPlus-X classes - Part 1
Sometimes we may need to make some adjustments in the colors of an image, like to change Saturation, Contrast, Brightness, Hue, convert to Grayscales, to increase or decrease a specific, to make Gamma adjustments, colors, etc. And again GDIPlus is the perfect tool for this purpose. New GDIPlus-X library for Visual FoxPro The most appropriate instrument for this task is the new GDIPlus-X library from VFP-X project. Since the _gdiplus.vcx class that ships with VFP9 is incomplete, for many tasks we had to make direct API calls to gdiplus.dll. Although it’s still an unfinished work, the actual ALPHA version of the GDIPlus-X library is very stable and already reliable to do most GDI+ tasks. In the last months I've been doing some extensive tests and creating some examples using the new library. I must tell that these classes are terrific. This library is already making my life with GDI+ a lot easier. The more I use it, the more I like it. Craig Boyd (http://www./SPSBlog/default.aspx) said in one of his blog posts: "The GDIPlus-X library is a pure Visual FoxPro reproduction of the Drawing related namespaces in .NET. We've coded well over 44,000 lines of VFP code and the library consists of 80+ classes now. At nearly 95% complete. It is safe to say that no other library on the planet gives Visual FoxPro developers the functionality and power that this one does when working with GDI+". The project manager is Bo Durban (www.). He and our "community-president" Craig Boyd did a difficult, amazing and very inventive work. Start downloading the latest stable release from codeplex, even if you already have one version fromhttp://www./Release/ProjectReleases.aspx?ProjectName=VFPX . Working with the images The simplest way to do that would be to "read" every single pixel of the image, extract the 4 integer ARGB values (Alpha, Red, Green and Blue), apply the adjustments to the color and then "redraw" every pixel. The code shows how we can convert an Image to Grayscale pixel by pixel. The effective luminance of a pixel is calculated with the following formula: C = 0.3 RED + 0.59 GREEN + 0.11 BLUE. You may also use this simplified formula : NewColor = (red + Green + Blue) / 3 , and apply "newColor" to each RGB color component. Before you run this code, make sure to choose a small picture, because this process is really very slow. Below is the new VFP-X logo and its grayscale version: IMPORTANT: When you run this sample, "LOCFILE()" will search the "system.vcx" file, that is in the folder source. If you add the "source" folder to your path, you won't be asked to find this file. ** convert an Image to GreyScale pixel by pixel ** _SCREEN.AddProperty("System", NEWOBJECT("xfcSystem", LOCFILE("system.vcx","vcx"))) WITH _SCREEN.System.Drawing && Load the image LOCAL loBitmap AS xfcBitmap LOCAL loNewBitmap AS xfcBitmap loBitmap = .Bitmap.New(GETPICT()) LOCAL lnWidth, lnHeight, X, Y, lnLuma lnWidth = loBitmap.Width lnHeight = loBitmap.Height loNewBitmap = .Bitmap.New(lnWidth, lnHeight) LOCAL loColor AS xfcColor WAIT WINDOW "Converting Image... Please wait..." NOWAIT FOR Y = 0 TO lnHeight - 1 FOR x = 0 TO lnWidth - 1 loColor = loBitmap.GetPixel(X,Y) lnLuma = INT(loColor.R * 0.3 + loColor.G * 0.59 + loColor.B * 0.11) loNewBitmap.SetPixel(x, y, .Color.FromRgb(RGB(lnLuma,; lnLuma, lnLuma))) NEXT NEXT loNewBitmap.Save("c:\_GreyScale.bmp", .Imaging.ImageFormat.Bmp) WAIT CLEAR ENDWITH RETURNGDI+ brings us with the possibility to apply changes to image colors in a really fast way. But to do that, we need to use the ImageAttributes class. According to Microsoft, "An ImageAttributes object contains information about how bitmap and metafile colors are manipulated during rendering. An ImageAttributes object maintains several color-adjustment settings, including color-adjustment matrices, grayscale-adjustment matrices, gamma-correction values, color-map tables, and color-threshold values." My favorite method in the ImageAttributes class is the "SetColorMatrix". According to MSDN, "A 5x5 color matrix is a homogeneous matrix for a 4-space transformation. The element in the fifth row and fifth column of a 5x5 homogeneous matrix must be 1, and all of the other elements in the fifth column must be 0. Color matrices are used to transform color vectors. The first four components of a color vector hold the red, green, blue, and alpha components (in that order) of a color. The fifth component of a color vector is always 1." Fortunately, MSDN brings to us some really cool examples. Enter www. and search for "Gdiplus ColorMatrix". From now on, to apply these examples will be a simple task. MSDN provides many code examples for GDI+, mostly for VisualBasic, as you can see in this link: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemdrawingimagingcolormatrixclasstopic.asp Below is the sample code that uses color matrices provided by MSDN for VisualBasic: Public Sub SetColorMatrixExample(e As PaintEventArgs) ' Create a rectangle image with all colors set to 128 (medium ' gray). Dim myBitmap As New Bitmap(50, 50, PixelFormat.Format32bppArgb) Dim g As Graphics = Graphics.FromImage(myBitmap) g.FillRectangle(New SolidBrush(Color.FromArgb(255, 128, 128, _ 128)), New Rectangle(0, 0, 50, 50)) myBitmap.Save("Rectangle1.jpg") ' Open an Image file and draw it to the screen. Dim myImage As Image = Image.FromFile("Rectangle1.jpg") e.Graphics.DrawImage(myImage, 20, 20) ' Initialize the color matrix. Dim myColorMatrix As New ColorMatrix() myColorMatrix.Matrix00 = 1.75F ' Red myColorMatrix.Matrix11 = 1F ' Green myColorMatrix.Matrix22 = 1F ' Blue myColorMatrix.Matrix33 = 1F ' alpha myColorMatrix.Matrix44 = 1F ' w ' Create an ImageAttributes object and set the color matrix. Dim imageAttr As New ImageAttributes() imageAttr.SetColorMatrix(myColorMatrix) ' Draw the image using the color matrix. Dim rect As New Rectangle(100, 20, 200, 200) e.Graphics.DrawImage(myImage, rect, 0, 0, 200, 200, _ GraphicsUnit.Pixel, imageAttr) ' Image End Sub 'SetColorMatrixExampleThis is the same example 100% in VFP, using the VFP-X GDIPlus-X library ** Converted to GDIPlusX for VFP from .NET help: ** http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/ ** frlrfsystemdrawingimagingcolormatrixclasstopic.asp ** Creates a rectangle image that has all the color values set to 128, producing ** a rectangle that is filled with a solid medium gray color. ** The code then draws this rectangle image to the screen. ** Creates a ColorMatrix object and sets its Matrix00 location to 1.75, ** which emphasizes the red component of the image. ** Creates an ImageAttributes object and calls the SetColorMatrix method. ** Draws the image (a second rectangle) to the screen using the ColorMatrix ** object just set in the ImageAttributes object. _SCREEN.AddProperty("System", NEWOBJECT("xfcSystem", LOCFILE("system.vcx","vcx"))) WITH _SCREEN.System.Drawing *!* Create a rectangle image with all colors set to 128 (medium gray). LOCAL loMyBitmap AS xfcBitmap loMyBitmap = .Bitmap.New(50, 50, .Imaging.PixelFormat.Format32bppArgb) LOCAL loGfx AS xfcGraphics loGfx = .Graphics.FromImage(myBitmap) loGfx.FillRectangle( .SolidBrush.New(.Color.FromArgb(255,128,128,128)), ; .Rectangle.New(0, 0, 50, 50)) loMyBitmap.Save("c:\Rectangle1.jpg") *!* Open an Image file and draw it to the screen. LOCAL loMyImage AS xfcImage loMyImage = .Image.FromFile("c:\Rectangle1.jpg") LOCAL loImgGfx AS xfcGraphics loImgGfx = .Graphics.FromHwnd(_Screen.HWnd) loImgGfx.DrawImage(loMyImage, 20, 20) *!* Initialize the color matrix. LOCAL lomyColorMatrix AS xfcColorMatrix loMyColorMatrix = .Imaging.ColorMatrix.New() loMyColorMatrix.Matrix00 = 1.75 && Red loMyColorMatrix.Matrix11 = 1 && Green loMyColorMatrix.Matrix22 = 1 && Blue loMyColorMatrix.Matrix33 = 1 && alpha loMyColorMatrix.Matrix44 = 1 && w *!* Create an ImageAttributes object and set the color matrix. LOCAL loImageAttr AS xfcImageAttributes loImageAttr = .Imaging.ImageAttributes.New() loImageAttr.SetColorMatrix(loMyColorMatrix) *!* Draw the image using the color matrix. LOCAL loRect as xfcRectangle loRect = .Rectangle.New(100, 20, 200, 200) loImgGfx.DrawImage(loMyImage, loRect, 0, 0, 200, 200, ; .GraphicsUnit.Pixel, loImageAttr) && Image ENDWITH RETURNThis is a 5x5 a color matrix:
In this matrix, I'll classify some important positions:
You can get some very interesting effects applying color matrices. So, let's have some fun, playing with GDI+ and the new library. The example below converts an image to grayscale in a flash. For these examples, I'll use the Level Extreme logo:
_SCREEN.AddProperty("System", NEWOBJECT("xfcSystem", LOCFILE("system.vcx","vcx"))) LOCAL loBitmap AS xfcBitmap LOCAL loNewBitmap AS xfcBitmap LOCAL loGfx AS xfcGraphics LOCAL loAttr AS xfcImageAttributes LOCAL loClrMatrix AS xfcColorMatrix LOCAL loRect AS xfcRectangle WITH _SCREEN.System.Drawing loBitmap = .Bitmap.New(GETPICT()) loNewBitmap = .Bitmap.New(loBitmap.Width, loBitmap.Height) * Create a Graphics object to be able to draw in the bitmap loGfx = .Graphics.FromImage(loNewBitmap) loClrMatrix = .Imaging.ColorMatrix.New( ; 0.33, 0.33, 0.33, 0.0, 0.0, ; 0.33, 0.33, 0.33, 0.0, 0.0, ; 0.33, 0.33, 0.33, 0.0, 0.0, ; 0.0 , 0.0 , 0.0 , 1.0, 0.0, ; 0.0 , 0.0 , 0.0 , 0.0, 1.0) loAttr = .Imaging.ImageAttributes.New() loAttr.SetColorMatrix(loClrMatrix) loRect = .Rectangle.New(0,0,loBitmap.Width, loBitmap.Height) loGfx.DrawImage(loBitmap, loRect, loRect, .GraphicsUnit.Pixel, loAttr) loNewBitmap.Save("c:\NewImage.jpg", .Imaging.ImageFormat.Jpeg) ENDWITH RETURNBelow are some other examples. To see the results, just change the contents of the object loClrMatrix to these ones: Matrix1 - Obtain Negative of an Image loClrMatrix = .Imaging.ColorMatrix.New( ; -1, 0, 0, 0, 0, ; 0 , -1, 0, 0, 0, ; 0 , 0, -1, 0, 0, ; 0 , 0, 0, 1, 0, ; 1 , 1, 1, 0, 1)Matrix2 - Obtain just the RED components of an Image loClrMatrix = .Imaging.ColorMatrix.New( ; 1 , 0, 0, 0, 0, ; 0 , 0, 0, 0, 0, ; 0 , 0, 0, 0, 0, ; 0 , 0, 0, 1, 0, ; 0 , 0, 0, 0, 1)Matrix3 - REMOVE the BLUE components of an Image loClrMatrix = .Imaging.ColorMatrix.New( ; 1 , 0, 0, 0, 0, ; 0 , 1, 0, 0, 0, ; 0 , 0, 0, 0, 0, ; 0 , 0, 0, 1, 0, ; 0 , 0, 0, 0, 1)Matrix4 - Scales the blue component of each pixel in the image by a factor of 2 loClrMatrix = .Imaging.ColorMatrix.New( ; 1 , 0, 0, 0, 0, ; 0 , 1, 0, 0, 0, ; 0 , 0, 2, 0, 0, ; 0 , 0, 0, 1, 0, ; 0 , 0, 0, 0, 1)Matrix5 - Adds 0.20 to the red component of each pixel in the image loClrMatrix = .Imaging.ColorMatrix.New( ; 1 , 0, 0, 0, 0, ; 0 , 1, 0, 0, 0, ; 0 , 0, 1, 0, 0, ; 0 , 0, 0, 1, 0, ; .20 ,0, 0, 0, 1)There are many other cool and impressive things that can be done using color matrices. In the next part of this article, I’ll try to show more things using more color matrices and other Image Attributes methods. More about GDIPlus-X In the source code of the new GDIPlus-X classes, you'll also find many other examples. Go to the samples folder, and start running the file DEMO.PRG, and you'll have a good idea of the power of the class. There you'll find 3 other examples that I've prepared related to this article, "ColorMatricesBasic.scx", "ColorMatricesAdvanced.scx" and "GammaThreshold.scx". Most of the information below was extracted from some messages from Bo Durban and Craig Boyd in the "Sedna-X GotDotNet", "CodePlex" and some private messages. One of the most interesting features of this library is the Image Canvas object, which is used in most of the samples that ship with the library. This class is extremely powerful for rendering graphics on a VFP form, making it SUPER easy for developers to create custom, graphics intensive controls, without having to worry about Paint events and off screen bitmaps. You only have to handle updates based on user interaction. Almost all of the samples use the Image Canvas class. Take a look at the samples to see how easy it is to use. It can be as simple as adding your drawing commands to the BeforeDraw( ) method and calling the Draw() method, whenever you require an update. At the core, this class gives you the ability to direct draw to a VFP Image control. The benefits of using this class over drawing directly to the form's HWnd include:
The reference manual for these libraries is still under development. To help you get started, in the "readme.htm" file you'll find a trick using intellisense to display a list of classes and members with their descriptions while writing code. Bo also included a preliminary reference document that list the classes included with the library and their current status. It also includes a brief description of each class with links to the equivalent .NET class in the MSDN library. If you find any difficulty to work with the classes, or want to see GDI+ doing some specific task, feel free to ask at the codeplex message boards. |
|
来自: Alkaid2015 > 《75.VFP狐仙◆》