One of the commonest questions that I see in VFP forums regarding images is "How can I get the dimensions of a Picture File?".
Fortunately, this is very simple to get.
Below I'll show some techniques that we can use, with some brief explanations. It's up to the developer to choose which of them is the best for his needs. All techniques are very simple and easy to use. For GDI+ users, I'm showing using 3 libraries that I've already dealt with. As a bonus, the last one shows how to get it with GDI+ using direct API calls, for those that don't want to use a GDI+ wrapper class.
All samples below are free. I'm sure that there are other ways to do it. I'm just posting the ones that I know and tested.
1 - LOADING PICTURE TO VFP IMAGE OBJECT
This technique works with any VFP version. When we associate a Picture File to a default Image object, it will store the dimensions in the Width and Height properties.
* Technique 1
* Get dimensions from Image object
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight
LOCAL loVFPImg as Image
loVFPImg = CREATEOBJECT("Image")
loVFPImg.Picture = lcPictureFile
lnWidth = loVFPImg.Width
lnHeight = loVFPImg.Height
loVFPImg = NULL
MESSAGEBOX("VFP Image Object" + CHR(13) + ;
"Dimensions: " + TRANSFORM(lnWIdth) + " x " + TRANSFORM(lnHeight))
2 - USING LOADPICTURE() FUNCTION
The object returned by LOADPICTURE() is an instance of the StdPicture class. The height and width values are HiMetric units (1 HiMetric = 0.01 milimeter).
I'm really not sure of which is the correct way to use this function to obtain the dimensions of an image.
Lisa Slater Nicholls posted a long time ago a function to obtain the dimensions, but this did not work for me. http://www.spacefold.com/lisa/lisa_fx4.htm#loadpicture
In a discussion at Foxite, between Eric den Doop and Boudewijn Lutgerik, http://www.foxite.com/archives/what-mysterious-calculation-is-behind-this-0000067503.htm , Boudewijn obtained the dimensions using a different factor.
In my case, I chose the technique that I found at http://www.xtremevbtalk.com/archive/index.php/t-13097.html . But I wouldn't trust on this approach, because it seems to depend on the screen resolution. Use it at your own risk !
* Technique 2
* Get dimensions from Image object using LOADPICT()
* Code from Lisa Slater Nicholls
* The object returned by LOADPIC() is an instance of the StdPicture class.
* The height and width values are HiMetric units (1 HiMetric = 0.01 milimeter).
* http://www.foxite.com/archives/what-mysterious-calculation-is-behind-this-0000067503.htm
* http://www.xtremevbtalk.com/archive/index.php/t-13097.html
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight
LOCAL loLoadedPict
loLoadedPict = LOADPICTURE(lcPictureFile)
lnHeight = ROUND((loLoadedPict.Height / 26.45454545455),0)
lnWidth = ROUND((loLoadedPict.Width / 26.45454545455),0)
loLoadedPict = NULL
MESSAGEBOX("VFP LOADPICTURE() function" + CHR(13) + ;
"Dimensions: " + TRANSFORM(lnWidth) + " x " + TRANSFORM(lnHeight))
3 - GET PICTURE INFORMATION FROM IMAGE FILE HEADER
Image dimensions are stored in their binaries. The code below uses FOPEN and FREAD to extract these information. It can obtain the dimensions of BMP, GIF and JPG image types.
* Technique 3
* Get picture information from Image File Header
* Samples adapted from Thomas Gehrke's functions at the West-Wind Wiki:
* http://www.west-wind.com/wiki/wc.dll?wc~JpgSizeFunction
* http://www.west-wind.com/wiki/wc.dll?wc~GifSizeFunction
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight, lcExt
lcExt = LOWER(JUSTEXT(lcPictureFile))
DO CASE
CASE lcExt = "bmp"
LOCAL lnHandle, lcBytes
lnHandle = FOPEN(lcPictureFile)
IF m.lnHandle > -1
* Read the 1st 27 bytes:
lcBytes = FREAD( m.lnHandle, 27)
= FCLOSE( m.lnHandle)
lnWidth = CTOBIN(SUBSTR(lcBytes,19,4),"4RS")
lnHeight = CTOBIN(SUBSTR(lcBytes,23,4),"4RS")
ENDIF
CASE lcExt = "gif"
LOCAL lnHandle, lcBytes
lnHandle = FOPEN(lcPictureFile)
IF m.lnHandle > -1
* Read the 1st 10 bytes:
lcBytes = FREAD( m.lnHandle, 10)
= FCLOSE( m.lnHandle)
lnWidth = CTOBIN(SUBSTR( m.lcBytes, 7, 2),"2RS")
lnHeight = CTOBIN(SUBSTR( m.lcBytes, 9, 2),"2RS")
ENDIF
CASE lcExt = "jpg"
LOCAL lnHandle, lcBytes
lnHandle = FOPEN(lcPictureFile)
IF m.lnHandle > -1
LOCAL lnFileSize, lnCounter, lcBytes
lnFileSize = FSEEK( m.lnHandle, 0, 2)
lnCounter = 0
= FSEEK( m.lnHandle, 0, 0)
FOR lnCounter = 1 TO m.lnFileSize - 2
lcBytes = FREAD( m.lnHandle, 3)
IF m.lcBytes = CHR(0) + CHR(17) + CHR(8) OR ;
m.lcBytes = CHR(0) + CHR(11) + CHR(8)
* Found block marker for dimensions!
lcBytes = FREAD( m.lnHandle, 4)
EXIT
ELSE
= FSEEK( m.lnHandle, -2, 1)
ENDIF
ENDFOR
= FCLOSE( m.lnHandle)
lnWidth = CTOBIN(SUBSTR( m.lcBytes, 3, 2),"2S")
lnHeight = CTOBIN(SUBSTR( m.lcBytes, 1, 2),"2S")
ENDIF
ENDCASE
MESSAGEBOX("Information from Image Header" + CHR(13) + ;
"Dimensions: " + TRANSFORM(lnWIdth) + " x " + TRANSFORM(lnHeight))
4 - USING GDIPLUSX
GDI+ can retrieve this kind of information and many others very easilly.
The sample below uses the GdiPlusX library from VFPX. http://www.codeplex.com/VFPX/Wiki/View.aspx?title=GDIPlusX&referringTitle=Home
* Technique 4
* Get picture information using GDI+, with GdiPlusX
* http://www.codeplex.com/VFPX/Wiki/View.aspx?title=GDIPlusX&referringTitle=Home
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight
DO LOCFILE("System.App")
WITH _SCREEN.System.Drawing
* Create a new Bitmap
LOCAL loBmp as xfcBitmap
loBmp = .Bitmap.FromFile(lcPictureFile)
lnWidth = loBmp.Width
lnHeight = loBmp.Height
loBmp = NULL
MESSAGEBOX("GDI+ library - GdiPlusX" + CHR(13) + ;
"Dimensions: " + TRANSFORM(lnWIdth) + " x " + TRANSFORM(lnHeight))
ENDWITH
5 - USING GPIMAGE2
The sample below uses the GpImage library from Alexander Golovlev. At the link below you can find the most recent version of this class, that contains some Graphics functions that I added: http://gpimage2.googlepages.com/
* Technique 5
* Get picture information using GDI+, with GpImage2
* http://gpimage2.googlepages.com/
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight
IF Not "gpImage" $ SET("Procedure")
SET PROCEDURE TO gpImage ADDITIVE
ENDIF
loGdip = CREATEOBJECT("gpInit")
loBmp = CREATEOBJECT("gpImage")
loBmp.Load(lcPictureFile)
lnWidth = loBmp.ImageWidth
lnHeight = loBmp.ImageHeight
loBmp = NULL
loGdip = NULL
MESSAGEBOX("GDI+ library - GpImage2" + CHR(13) + ;
"Dimensions: " + TRANSFORM(lnWIdth) + " x " + TRANSFORM(lnHeight))
6 - USING _GDIPLUS.VCX
The sample below uses the FFC _GdiPlus.vcx class library from Walter Nicholls, shipped with VFP9.
* Technique 6
* Get picture information using GDI+, with _GdiPlus.vcx, from Walter Nicholls
LOCAL lcPictureFile
lcPictureFile = GETPICT()
LOCAL lnWidth, lnHeight
LOCAL loBitmap as GpBitmap OF HOME() + "/FFC/_GdiPlus.vcx"
loBitmap = NEWOBJECT("GpBitmap", HOME() + "/FFC/_GdiPlus.vcx")
loBitmap.CreateFromFile(lcPictureFile)
lnWidth = loBitmap.ImageWidth
lnHeight = loBitmap.ImageHeight
loBitmap = NULL
MESSAGEBOX("GDI+ library - FFC _GdiPlus.vcx" + CHR(13) + ;
"Dimensions: " + TRANSFORM(lnWIdth) + " x " + TRANSFORM(lnHeight))
7 - USING GDIPLUS WITH DIRECT API CALLS
If you don't want to use any GDI+ wrapper class, here's the code that retrieves the image dimensions using direct API calls to gdiplus.dll. Just make sure that you have the file gdiplus.dll in your system.
Gdiplus.dll 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
or directly:
http://download.microsoft.com/download/platformsdk/redist/3097/W98NT42KMeXP/EN-US/gdiplus_dnld.exe
You can find some good information about GdiPlus on Microsoft official site:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdicpp/GDIPlus/GDIPlusreference/flatgraphics.asp
* Technique 7
* Get picture information using GDI+, with direct API calls
LOCAL lcPictureFile
lcPictureFile = GETPICT()
* API Declarations for GDI+
DECLARE LONG GdiplusStartup IN GDIPLUS.DLL ;
LONG @ token, STRING @ INPUT, LONG @ OUTPUT
DECLARE LONG GdiplusShutdown IN GDIPLUS.DLL LONG token
DECLARE INTEGER GdipLoadImageFromFile IN GDIPLUS.DLL ;
STRING wFilename, INTEGER @ nImage
DECLARE INTEGER GdipDisposeImage IN GDIPLUS.DLL INTEGER nImage
DECLARE INTEGER GdipGetImageWidth IN GDIPLUS.DLL ;
INTEGER nImage, INTEGER @ nWidth
DECLARE INTEGER GdipGetImageHeight IN GDIPLUS.DLL ;
INTEGER nImage, INTEGER @ nHeight
* Initialize GDI+.
LOCAL gdiplusStartupInput, lhGdiPlusToken
gdiplusStartupInput = CHR(1) + REPLICATE(CHR(0), 15)
lhGdiPlusToken = 0
IF GdiplusStartup(@lhGdiPlusToken, @gdiplusStartupInput, 0) != 0
RETURN .F.
ENDIF
* Load Object Picture
LOCAL lnPictHandle
lnPictHandle = 0
= GdipLoadImageFromFile( STRCONV(lcPictureFile + CHR(0),5), @lnPictHandle)
* Get Picture dimensions
LOCAL lnWidth, lnHeight
STORE 0 TO lnWidth, lnHeight
= GdipGetImageWidth(lnPictHandle, @lnWidth)
= GdipGetImageHeight(lnPictHandle, @lnHeight)
* Clear GDI+ main handle
= GdiplusShutdown(lhGdiPlusToken)
MESSAGEBOX("GDI+ with direct API calls" + CHR(13) + ;
"Dimensions: " + TRANSFORM(lnWidth) + " x " + TRANSFORM(lnHeight))
I hope this helps !
Enjoy !