Welcome To The Home Of The Visual FoxPro Experts  
home. signup. forum. archives. search. google. articles. downloads. faq. members. weblogs. file info. rss.
GENERAL BEST PRACTICES >>  HOW TO HANDLE IMAGE FILES IN A VFP BACKEND

  Ken Murphy
  Where is Ken Murphy?
 Springhill
 Canada
 Ken Murphy



So you have a bunch of image files, and you want be able to use them in your app.

VFP has a file size limit of 2 Gig for any file that is part of a DBF. If the .DBF, .CDX or .FTP file gets larger than 2 Gig, you will run into problems, and storing image files in a table can run you into that 2 Gig limit very quickly. Worse still, if you do run into that 2 Gig limit, VFP will not give you any warning - it will just freeze.

I deal with 30,000 high quality (read "large") image files annually and if I were to attempt to store these images in a table, I would run into that 2 Gig limit before I was half way through.

The best way to handle images is to store them in a directory located on the server (or more precisely, in a directory structure located on the server.) In my case, I deal with photos of sponsored children. (We are a child sponsorship charity similar to World Vision, except we are Catholic and we think we do it better.) The child belongs to a sub-project which in turn belongs to a project which is part of a region which in turn is part of an organization. I can therefore use this structure as my directory structure:

Organization
--Region
----Project
------SubProject

Why use a directory structure? Windows indexing seems to have a problem with a directory that contains more than 1024 files. When you place the 1025th file in that directory, it begins to get very slow. If you use a directory structure similar to the one that I have, you can ensure that you don't run into that problem by reducing the number of files in any one directory.

By placing this directory structure on the server, you (or your sysadmin) can control access to that directory structure using Acitive Directory. Some users can be given read/write access (those who update the image files) and you can give readonly access to those who simply need to look at the images. If you store these images on a series of workstations, you will run into permissions problems.

I rename the image file to the ChildID for the child who's image is portrayed in that image file. For exampel, ABC1234.JPG would be the photo of child ABC1234. Using the child ID and the directory structure as shown above, I don't actually have to store anything in my table. If I know the child ID, I also know the sub-project and if I know the sub-project, I also know the project and therefore the region and therefore the organization. I can then calculate the location and file name from this data.

lcImageFile = [\\Server\Photos\]+Organization.OrgID-;
              ([\]+Region.RegionID)-([\]+Project.ProjectID)-;
              ([\]+SubProject.SubID)-([\]+Child.ChildID)-[.jpg]


Now, if I wish to display the image on a form,

ThisForm.ChildImage.Picture = IIF(FILE(lcImageFile),lcImageFile,[Path2\NoImageAvailable.Jpg])


If you look you can probably find a structure that would be suitable for your use. For example, employee photos can be named using the employee ID and can be stored in a structure like:

Division
--Plant
----Department

or a product could be stored in a directly structure like

ProductDivision
--Product group
----Product Category

etc.

If you do not have a structure like this that you can use as a directory structure, you will need to store your images in a series of directories (again, on your server - Images1, Images2, ...) and then store the file name and location in a table. For example, if you store an image called Img12345 in a directory called Images1, you would:

REPLACE MyTable.ImgFile WITH [\\Server\Images1\Img12345.jpg]


There is one problem to this method - what happens if a user deletes the image file without changing the data on the table. Your program would go looking in Images1 for an Img12345.jpg file that does not exist. Let's face it, it is very easy for a user to go into the Images1 directory and delete a file (even if by mistake.) If you are going to do this, you need to check and see if that image file is still there.

IF FILE(MyTable.ImgFile)
   ThisForm.MyImage.Picture = MyTable.ImgFile
ELSE
   ThisForm.MyImage.Picture = [Path2\NoAvailableImage.Jpg]
ENDIF


Note the "NoAvailableImage.Jpg" file. Create an image file that you can use when ever you run into the situation where the real image does not exist and store it in a secure directory on the server (a directory where access is readonly for all users.)

If you are talking about a small number of small sized image files, (icons for example) it makes a great deal of sense to store these in a table. You know you will not run into the 2 Gig limit and lets face it, VFP handles data stored in tables very well indeed.

DO NOT USE THE GENERAL FIELD.

VFP help tells you that you can store image files in a general field, but this runs you into all sorts of difficulties. Stay away from the general field and instead, use the FILETOSTR() function and store the image in a blob field. (You are using VFP 7, so you will have to store your images in a memo field.)

REPLACE MyTable.MyMemoField WITH FILETOSTR([Path2\TheImageIWant2Save.JPG])


You can use the companion function STRTOFILE() to turn your memo data back into an image file. Take a look at these two functions in VFP help.

Hope this helps.

FEEDBACK

Boudewijn Lutgerink @ 12/6/2006 2:23:06 PM
I just wonder whether you would need windows indexing on folders like this.
After all, it is VFP (only?) that uses these folders for the specific app.

I nonetheless think it is useful to limit the amount of files (any type) in folders, simply for administrative purpose.

Ken Murphy @ 12/6/2006 2:45:45 PM
Boudewijn

Thanks for the feedback. I mentioned the Windows Indexing because I ran into the slowdown. You can switch windows indexing off, but that is difficult to do in a remote environment - especially if the user needs windows indexing for other software. Turning it on and off as required would be a pain. I mentioned the problem and if the reader never runs into it, good enough. If it does turn out to be a problem, at least the reader has my experience to draw upon. (When this happened to me, I had no idea what was happening and it took me forever to figure it out.)

nyron williams @ 12/6/2006 4:08:33 PM
Excellent suggestion, as always, I use a similar method for my app however I also give my file name a different extension so that the average user will not know that they are editabled pics. Like I said excellent sugestion

Dennis Longfellow @ 12/6/2006 5:21:27 PM
Ken,

Thanks for posting this in the FAQ section. Your posts to threads concerning this subject have convinced me that if I ever need to use images in an application, I should use a similar approach. Now, I won't have to search the archives when that day arrives.

Ken Murphy @ 12/7/2006 6:02:04 AM
Nyron, Dennis,

Thanks for the feedback. I appreciate the kind words.

Nyron, You can change the extensions, but at times, this can be a hinderance. In my case, certain users need to be able to edit the image (crop, remove red-eye, etc.) and changing the extension would cause problems. I simply let the SysAdmin assign the appropriate permissions to the folder. The users who are allowed to edit or delete image files can and those who are not given these permissions may only "Look but do not touch."

George Bailey @ 8/4/2007 2:57:11 AM
Great Tip Ken!

I found this page while prepping to develop software that will present images of documents to users who will then enter information about the documents (Title, Author, Date, etc.) so this is perfect!

Canadian, eh? Good stuff!

Ken Murphy @ 12/24/2007 9:25:18 PM
George,

Thank you for the kind words. Most definately Canadian, eh?

Baby Thomas @ 1/24/2008 2:12:48 PM
Thanks for this good article

Francisco Ibarra @ 3/7/2008 2:33:44 AM
Very good tip, easy and simple, thanks

CHANDU @ 2/21/2010 4:13:44 AM
I am using the same way of directory structure.

But, it is very diffucult to avoid file deletion by a use or by mistake. for this purpose i want to store it in database.

But still i have a problem for table curruptions while shutdown a system by power failure.

Is there any method to avoid such type of TABLE curruprions.

Thanks FOR YOUR HELP!

kemi @ 10/10/2010 8:32:41 AM
GROUPS - replica bvlgari sunglasses Digging beneath the topline numbers cheap soccer socks reveals some interesting differences among fendi belts groups across these questions. Here's discount soccer shoes a summary:



Your Name: 
Your Feedback: 

Spam Protection:
Enter the code shown: