2012-03-16

Resizing images with GdiPlusX


GDI+ brings many possibilities for resizing images from Visual FoxPro9. In this short post, I'll show 3 techniques, that can be applied depending on your needs.

IMPORTANT:
All samples below use the GDIPlus-X library, a VFPX project on GitHub.



Here they are:

1 - THUMBNAIL
Using very few code we can resize any image:

** How To: RESIZE with Thumbnail Technique
** This code resizes an Image to size 60x60
** Saves to a PNG file
DO LOCFILE("System.App") && GdiPlusX project on Github
WITH _SCREEN.System.Drawing
* Variables to store the new Image size
LOCAL lnWidth, lnHeight
STORE 60 TO lnWidth, lnHeight
* Load the original Image LOCAL loSrcImage as xfcBitmap
loSrcImage = .Bitmap.New(GETPICT())

* Get the thumbnail with the desired size LOCAL loThumbnail as xfcImage
loThumbnail = loSrcImage.GetThumbnailImage(lnWidth, lnHeight)
* Save the resized image as Png loResized.Save("c:\Resized1.png", .Imaging.ImageFormat.Png)
ENDWITH
RETURN

But there is a problem, that some kinds of Images like JPEGS may store embedded thumbnails. The function "GetThumbnailImage" in a first moment searches at the image file if there already exists a thumbnail stored. If yes, GDI+ will scale this image to the desired dimensions, causing some huge distortions.
In my opinion, this technique is recommended to be used to resize to small images, not bigger than 72x72.


2 - BITMAP LOADING
This code is also really short.

** How To: RESIZE with Bitmap loading Technique 
** The code resizes an Image to size 60x60 
** Saves to a PNG file

DO LOCFILE("System.App")

WITH _SCREEN.System.Drawing 
* Variables to store the new Image size 
LOCAL lnWidth, lnHeight 
STORE 60 TO lnWidth, lnHeight 
* Load the original Image LOCAL loSrcImage as xfcBitmap 
loSrcImage = .Bitmap.New(GETPICT()) 

* Get the resized version of the image 
LOCAL loResized as xfcBitmap 
loResized = .Bitmap.New(loSrcImage, lnWidth, lnHeight)

* Save the resized image as Png 
loResized.Save("c:\Resized2.png", .Imaging.ImageFormat.Png)

ENDWITH 
RETURN


The Bitmap class provides many overloads, that you can see at
http://msdn2.microsoft.com/en-us/library/System.Drawing.Bitmap.Bitmap%28vs.80%29.aspx
. One of them permits to load from any GDI+ image object, and automagically resizes it to the desired dimensions. Very easy, but it uses some default GDI+ properties, and does NOT ensure to generate the best possible quality.
This option is recommended for almost all cases when you need to rescale an image to a smaller size than the original.


3 - CUSTOMIZED RESIZING
The code below is longer, but permits to have a considerable control over the way our image is resized.

** How To: RESIZE with Image Drawing Technique 
** The code resizes an Image to size 60x60 
** Saves to a PNG file

** GDI+ gives you considerable control over the way your image is resampled, 
** so it makes sense to take advantage of this flexibility. 
** This way, we can obtain the most satisfactory image quality

DO LOCFILE("System.App")

WITH _SCREEN.System.Drawing

* Variables to store the new Image size 
LOCAL lnWidth, lnHeight 
STORE 60 TO lnWidth, lnHeight

* Load the original Image LOCAL loSrcImage as xfcBitmap 
loSrcImage = .Bitmap.New(GETPICT())

* Create a New Image with the desired size LOCAL loResized as xfcBitmap 
loResized = .Bitmap.New(lnWidth, lnHeight, ; 
   .Imaging.PixelFormat.Format32bppARGB)

* Set the image resolution to be the same as the original 
loResized.SetResolution(loSrcImage.HorizontalResolution, ; 
   loSrcImage.VerticalResolution)

* Obtain a Graphics object to get the rights to draw on it LOCAL loGfx as xfcGraphics 
loGfx = .Graphics.FromImage(loResized)

* Set some properties, to ensure to have a better quality of image loGfx.SmoothingMode = .Drawing2D.SmoothingMode.HighQuality 
loGfx.InterpolationMode = .Drawing2D.InterpolationMode.HighQualityBicubic

* Draw the source image on the new image at the desired dimensions 
loGfx.DrawImage(loSrcImage, 0, 0, lnWIdth, lnHeight)

* Save the resized image as Png 
loResized.Save("c:\Resized3.png", .Imaging.ImageFormat.Png)

ENDWITH 
RETURN

In this code we are controlling the Image Resolution, the Interpolation Mode, and the Smoothing Mode of the scaled image.
According to Libor Tinka, "Interpolation refers to how data is interpolated between endpoints. In its simplest form, to interpolate is to estimate a missing value by taking an average of known values at neighboring points."
In general the bicubic interpolation is used when more accuracy that's why I chose to use this mode for this sample.
Because of all these settings, this is the better option for resizing images to a bigger size than the original.

Libor Tinka wrote a very interesting article on this subjects, and provides many code samples and images showing the results that can be obtained using different Interpolation modes. Strongly recommended !
http://www.codeproject.com/csharp/imgresizoutperfg...

1 comment:

  1. I find especially "SmoothingMode.HighQuality" and "InterpolationMode.HighQualityBicubic" very interesting.

    Do you also know how to sharpen an image ?

    ReplyDelete