×
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Contact US

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Students Click Here

how to fill a table with images

how to fill a table with images

how to fill a table with images

(OP)
I have a Vfp-Table - its name = "Mypics"
500 records.
Structure:
Field.. Field-type
Nummer... character
Titel ... character
Bild ... General

Beside that I have a file with 500 pictures. File-name = "mypictures"
Now I want to fill the field "Bild" in table "mypics" with the images in the sequence of file "mypictures"

How can I do it with a loop?

Thank you in advance
Klaus

Peace worldwide - it starts here...

RE: how to fill a table with images

Hello Klaus,

To add an image to a single record:

Go to the relevant record, and then:

APPEND GENERAL <name of General field> FROM <filename>

To do that 500 times, put that in a SCAN loop.

However, you say that you have one file containing the 500 images. What sort of file is this? How are the images stored? Obviously you will need a way to extract each of the images from the file, but without more information I can't tell you how to do that.

Or do you meant that the file contains the names of the images?

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads

RE: how to fill a table with images

Klaus,
Assuming your images are .jpg, you can do the following, assuming you have a table with the structure you mentioned. You can modify this as well to say, enter the name of the file as the "title" field:


CODE

USE Mypics IN 0  && Open the table

*-- Get the number of files in the "mypictures" folder
lcFolderPath = "C:\path\to\mypictures\folder\"  && Replace with the actual path to the folder
laFiles = ADIR(laDirInfo, lcFolderPath + "*.jpg")  && Replace ".jpg" with the actual file extension of your pictures
lnFileCount = laFiles[0]

*-- Loop through the files and add a record for each file
FOR i = 1 TO lnFileCount
   lcPicturePath = lcFolderPath + laFiles[i, 1]
   lcNummer = PADL(i, 4, "0")  && Generate a 4-digit padded number for the record
   INSERT INTO Mypics (Nummer, Bild) VALUES (lcNummer, FILETOSTR(lcPicturePath))
ENDFOR

*-- Close the table
CLOSE DATABASES 

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCAP, CDCP, CDCS, CDCE, CTDC, CTIA, ATS, ATD

"I try to be nice, but sometimes my mouth doesn't cooperate."

RE: how to fill a table with images

It is not recommended to store that many images in a table, unless each image is 1k or so. Just store the path and filename in a character field and leave the images in a folder.



If you want to get the best response to a question, please check out FAQ184-2483: How to get the best response from the forum first.

RE: how to fill a table with images

(OP)
Sorry Mike, English is not my mother tongue. To correct this: I Stored 500 Fotos (jpg) in one FOLDER.From there I want top fill the .dbf

Peace worldwide - it starts here...

RE: how to fill a table with images

Quote:

I Stored 500 Fotos (jpg) in one FOLDER

Ah, that makes more sense. In that case, I would do as Scott suggested, except that instead of doing an INSERT with FileToString(), do APPEND GENERAL with the actual filename.

But note also Mike Gagnon's point about storing the path and filename rather than the actual image. I suspect that's what most of us here would do.

Quote:

Sorry Mike, English is not my mother tongue

Klaus, that's never been a problem with your posts. There's definitely no need to apologise.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads

RE: how to fill a table with images

I would rather store the PATH (and driveletter) in your application’s settings and the FILENAME in the database. Doing that you can move your files to another server, drive or NAS and by only changing a default setting in your application you can add the right path to all your files.

This has worked for our software for ages (and still does…).

Regards, Gerrit

RE: how to fill a table with images

Hello Klaus,

I was actually thinking long time nothing from you. It's a good sign. Since the answers are already given, I can just vote once more against storing images in general fields.
You can do so just to see for yourself how much the FPT file will grow and then try to cover the case you'd want your image back from the General field. There is - and I won't mind if you raise your eyebrow - a reportlistener to get an image file back from a General field, because as easy as you get an image into a General field by APPEND GENERAL, there is nothing like that for the other direction, reading the image from the General field.

So one tip for now is to keep your images even after you inserted them into a dbf. If not even skip that plan and don't store images in a table with the exception of doing so right before you can use it. You can inded bind a general field to an oleboundcontrol to diplsay the image and that same construct is a solution of printing images on a report. But you can generate a report cursor and just store the images into a General field then, wehn printing, not as permanent storage.

For forms it is much simpler to display an image using the image control and not the oleboundcontrol, of course. handling that control and creating a viewer that can also pan and zoom an image is also much simpler than when using the oleboundcontrol, as olebound already states in the name it's OLE aka ActiveX, when it comes to control, so the image displayed in an oleboundcontrol is actually on a separate Windowsfor with its own hwnd and such constructs always make it harder in terms of clipping the image, scrolling and zooming it just as easy as you can use the width and height of an image control about that and can clip an image by embedding it in a container. An ActiveX can't always be "tamed" by embedding it in a container to only show a clipped portion of it. The nature of an ActiveX being its own form that is in front of your form makes it "shine through". I've programmed pageframes that needed to hide all activex controls when a page was changed and at designtime it was a mess to deal with such controls.

It may be worth a try to see if a oleboundcontrol in a VFP container can be clipped by the container in the case of different objects in General fields, I think that's not very common knoledge as people usually avoid General fields. Not only for the reason it's hard to get back what you put into them. The main reason people have is how it bloats up the FPT file size.

Chriss

RE: how to fill a table with images

(OP)

Scott24x7 :
I just tried your code (thank you very much for it.)

There is a question for both these lines:
laFiles = ADIR(laDirInfo, lcFolderPath + "*.jpg") && Replace ".jpg" with the actual file extension of your pictures
lnFileCount = laFiles[0]

Although a cursor-array was created which I saw in memo I received this error





Is that a bug?

Regards Klaus


When this is cleared I will report my experience with using images in connection with VFP here.








Peace worldwide - it starts here...

RE: how to fill a table with images

Klaus,

The value returned from ADIR() is not an array. It is an integer which represents the number of rows in the array (which is laDirInfo in your example). In other words, instead of this:

laFiles = ADIR(laDirInfo, lcFolderPath + "*.jpg")
lnFileCount = laFiles[0]


You should do this:

lnFileCount = ADIR(laDirInfo, lcFolderPath + "*.jpg")

Also, please note what I said earlier about using APPEND GENERAL instead of Scott's INSERT.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads

RE: how to fill a table with images

Ah, right.
Klause, one question is, do these files HAVE to be embedded in the table? As Mike mentions, storing images in a table gets messy, and they are highly susceptible to corruption.
There is another way if you don't need to "protect" the image. You can simply reference the image in it's directory in a memo field, and then display that in an image object by reference.
I stopped putting images into tables a LONG time ago.

Best Regards,
Scott
MSc ISM, MIET, MASHRAE, CDCAP, CDCP, CDCS, CDCE, CTDC, CTIA, ATS, ATD

"I try to be nice, but sometimes my mouth doesn't cooperate."

RE: how to fill a table with images

Klaus,

just to see what you get if using APPEND GENERAL FROM file I tried that and the fpt size is about the image file size, no great bloat. But then (on Windows 10) appending the typical image type jpg, an olebound control on a form does not diplay the image. No matter if using the additional clause APPEND GENERAL file.jpg CLASS 'Paint.Picture' or not.

Even if that jpg is saved from mspaint, so mspaint clearly can handle that jpg. Only BMPs are displayed, and I guess that's just me not having experience with General fields, as I don't use them. If you get all this to work with JPG, too, and assuming no bloat, assuming a 100 kb image size in average, that's about 2GB/(100KB/image) = 20000 images.

I remember if that all works correctly, the Gen field stores the Ole class of an image and a BMP thumbnail that often is larger than the actual jpeg image and then this reduces the number of images you're able to store very much to only a few hundred images, perhaps. And no matter what the fpt file is capable to store, you will have more images in a folder without storing them in a table.

There is another more interesting field type for images, that's Blob, and a Blob field can also be displayed with an image control with its pictureval property.

Chriss

RE: how to fill a table with images

I found out what's going on.
If a file extension is a registered type VFP will disregard the CLASS clause of APPEnd GENERAL and take the association of the file type in the registry for granted. .jopg was associated with 'jpegfile' on my Windows 10 machine.

If you do this before starting a new VFP session to APPEND GENERAL, you also get jpg/jpeg files to show in an olebound control:
ASSOC .jpg='Paint.Picture'
ASSOC .jpeg='Paint.Picture'

but this is to show how bad it is. I have appended a jpg file that's a size of 100kb. If saved as a 24bit bmp file this image becomes a 1.8MB file and the append general of the jpg adds 1.8MB to the fpt file. So indeed VFP converts the image file to a BMP and stores that in the Gen field. Thus the bloat.

Makes me wonder if there is an ole class that could be used and make the oleboudcontrol display the gen field as an image like the paint.picture association does, without bloating the memo file. I doubt it, because I think it's not the Paint.Picture class that bloats the OLE object by containing the uncompressed bmp version of the image, it's vfp that adds that. Even if not. This class association is outdated, it's not by current OLE standards and even thinking of writing a new enhanced ole class version of paint.picture that works with VFPs APPEND GENERAL I doubt is possible.

Chriss

RE: how to fill a table with images


Quote (Chris Miller)

I remember if that all works correctly, the Gen field stores the Ole class of an image and a BMP thumbnail that often is larger than the actual jpeg image and then this reduces the number of images you're able to store very much to only a few hundred images, perhaps. And no matter what the fpt file is capable to store, you will have more images in a folder without storing them in a table.

It's true. Windows use host application "Paint.Picture" + Access.OLE2Link class for BMP files. Embedded data are bigger for input small BMP files.

Quote (Chris Miller)

but this is to show how bad it is. I have appended a jpg file that's a size of 100kb. If saved as a 24bit bmp file this image becomes a 1.8MB file and the append general of the jpg adds 1.8MB to the fpt file. So indeed VFP converts the image file to a BMP and stores that in the Gen field. Thus the bloat.

JPEG/JPG use host application "Package" and save to to gen field withouth converting.
But if registered another application as host application, then result can be different.

BTW, embeded RTF (source) in gen field is DOC always.

mJindrova

RE: how to fill a table with images

Quote (mJindrova)

JPEG/JPG use host application "Package" and save to to gen field without converting.

With what association?

If I do ASSOC.jpg=Paint.Picure in a CMD.Exe started as administrator, then start VFP and do an APPEND GENREAL 19.jpg I get this on disk:

The dbf just contains a general field and one record of the file 19.jpg but has the size of the 19.bmp file, which I created with MS Paint from the jpg,

I conclude the fpt bitmap "thumbnail" is pretty much the whole image, not just a small thumbnail version of it.

If I don't associate jpg with Paint.Picture putting an olebound control on a form I don't get the image displayed but a file link of 19.jpg that starts Windows Photos, and the fpt file only grows to about the jpg file size. It could just be concidence that the Ole object stored in the fpt is about the bmp file size, but to ensure that, what is displayed for .jpg if you execute ASSOC on your pc? Is it "package"?

Chriss

RE: how to fill a table with images

Doing CREATEOBJECT('Paint.Picture') and CREATEOBJECT('Package') both result in error 0x800040002 "No such interface supported", which is fine, it does not point out both classes are the same implementation, but it points out they are both registered OLE classes, which would otherwise error with "class definition ... is not found". Also, I know Paint.Picture works for both JPG and BMP files.

I still don't see how to get a smaller footprint in the FPT file when appending jpg files into it, after I tried ASSOC .jpg=Package I get the same result as before associating jpg with Paint.Picture.


Chriss

RE: how to fill a table with images


Host OLE (object embeded and linking) application and COM EXE applications are not same thing.

mJindrova

RE: how to fill a table with images

I know, but I still don't see how to get a smaller fpt footprint, after trying ASSOC .jpg=Package the Gen field content is small like before but doesn't show as an image bound to an olebound control.
Seems to me, VFP can't make use of "Package" as a host of an ole image object in a general field.

Chriss

RE: how to fill a table with images

Hello,

sorry to jump in :
what is the advantage of using APPEND GENERAL compared to store filetostr() in a table ?

Many years ago we started using the filetostr().
In VFP9 I can use a value for an image control and someone mentioned problems with append general and that we should not use it
Getting old, just forgot it.


Thanks
regards
tom

RE: how to fill a table with images

Tom,

indeed it's not recommendable, even if you get it to work. I just wanted to see how far you can get with it. It's a doable solution for a smaller set of images. A General field also is "generally" used when printing images in a report, since you can add an image to a temporary report cursor with a general field, that's a use for it.

I already also mentioned the Blob field type. You can populate it with FileToStr(imagefile) and an image controls PictureVal property can be used to display it.

CODE

Create Cursor imageblob (img blob)
Insert into imageblob Values (FileToStr(Home()+"\graphics\Gifs\morphfox.gif"))
_screen.AddObject('image1','image')
_screen.image1.Pictureval = img
_screen.image1.visible = .t. 

It makes things much easier and the size of storage is 1:1 the file size. It's better than bloated storage and the difficulty to get back what you inserted into the general field as a file. Just because you don't store a file, but an ole object and the information about the host class that can display it. You can also directly set PictureVal=FileToStr(imagefile) and so keeping images on disk and just storing the file name of them is a solution that needs the minimum storage in the DBF.

But that's the point, I'd also like to see if that can be made to work more effectively than with Paint.Picture.

Chriss

RE: how to fill a table with images

Quote:

what is the advantage of using APPEND GENERAL compared to store filetostr() in a table ?

Good question. The main reason is that a General field stores the actual image, which can then be viewed, for example in a Browse, or bound to an OLE field in a report. FILETOSTR() on the other hand, just stores a character string. (Scott's code would only work if Bild was a Character or Memo field, which it isn't.)

That said, I strongly agree with the idea of not storing the image in the table, but rather keeping the image file separate and just storing its path and file name in the table. I only mentioned the General field in direct response to Klaus's original question.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads

RE: how to fill a table with images


Quote (Chris Miller)

Seems to me, VFP can't make use of "Package" as a host of an ole image object in a general field.

"Package" doesn't support preview snapshot.

mJindrova

RE: how to fill a table with images

I see, thanks mJindrova.

Do I get that right?
That means Pckage is okay to have a low size storage in general fields, but the stored jpeg then isn't displayed?
So if you want to show the images you have to associate with Paint.Picture anyway? Or is there a way to see the image when it's associated with the class Package?

Chriss

RE: how to fill a table with images

Chris Miller ,

I don't knows host OLE application which save jpeg and presentation stream at once.
Paint.Picture suppots bmp only.
MS Graph use WMF/EMF only.

mJindrova

RE: how to fill a table with images

(OP)

First of all, I would like to thank everyone who has replied to my question so far.
I am very surprised at the multitude of answers (all were qualified, no "yearwoods")

Meanwhile, the argument has convinced me, that the image files
should not be embedded in a VFP table.
That's why I changed the field types in the table for taking over the image descriptions, they are all of the Character type
now.

The SCOTT24x7 program (see at bottom) runs very quickly with it
and automatically assigns a 4-digit number to each image as well
the name of the picture:



The image file with over 500 watercolors, drawings and experiments by me which were created in the last 20 years and looks like this, for example.


For these pictures I also have written references to the
content made that still needs to go into the "Titel - engl.= "Title" column.
e.g. "mountains", "trees", "animal name", "beach" etc.

It should then also be possible to display groups of images with similar content or similar size on the screen using an SQL query.
I recently spent an awfully long time looking for a certain painting of mine - hence the idea of speeding up such a searchit with VFP in future.
With the picture no. and the image on the content, I can find a specific painting much faster.

I still have to think about how to get old frame numbers
can hold on to if new photos of my paintings are added to the inventory.
But that is not an issue in the moment.
Should perhaps be a separate program.

I hope I have specified the goal of my thread.

Regards
Klaus




CODE --> Code

*Program: getbild.prg

*This code was written by Scott24x7 (see text at the end of this code) and small modified/adjusted by me.
*It fills the following columns of table Mypics with a generated 4-digit number
*in field NUMMER, and the description of *.jpg images in field Bild

*the images reside together with this program in folder C:\entw\produkt\bilderhol\mypics.dbf
*All field-types in Mypic.dbf are characters.



Close Data
Use Mypics In 0  && Open the table
                 && Table structure: Nummer c(6) , Titel c(60),Bild c(60) 

*-- Get the number of files in the "mypics" folder
lcFolderPath = "C:\entw\produkt\bilderhol\mypics.dbf"  && Replace with the actual path to the folder
lnFileCount = Adir(laDirInfo,lcFolderPath + "*.jpg")  && Replace ".jpg" with the actual file extension of your pictures

CLEAR

*-- Loop through the files and add a record for each file

For i = 1 To lnFileCount
      lcPicturePath = lcFolderPath + laDirInfo[i, 1]
      lcNummer = Padl(i, 4, "0")  && Generate a 4-digit padded number for the record
      Insert Into Mypics (Nummer, Bild) Values (lcNummer, Filetostr(lcPicturePath))
Endfor
Browse
Close Databases


*!*	------------------------------------------------------------------------------------------------------------------------
*!*	this was the Orginal-code by SCOTT24x7
*!*	USE Mypics IN 0  && Open the table

*!*	*-- Get the number of files in the "mypictures" folder
*!*	lcFolderPath = "C:\path\to\mypictures\folder\"  && Replace with the actual path to the folder
*!*	laFiles = ADIR(laDirInfo, lcFolderPath + "*.jpg")  && Replace ".jpg" with the actual file extension of your pictures
*!*	lnFileCount = laFiles[0]

*!*	*-- Loop through the files and add a record for each file
*!*	FOR i = 1 TO lnFileCount
*!*	   lcPicturePath = lcFolderPath + laFiles[i, 1]
*!*	   lcNummer = PADL(i, 4, "0")  && Generate a 4-digit padded number for the record
*!*	   INSERT INTO Mypics (Nummer, Bild) VALUES (lcNummer, FILETOSTR(lcPicturePath))
*!*	ENDFOR

*!*	*-- Close the table
*!*	CLOSE DATABASES 

Peace worldwide - it starts here...

RE: how to fill a table with images

(OP)
Scott:

Quote (Scott: Klaus, one question is, do these files HAVE to be embedded in the table? As Mike mentions, storing images in a table gets messy, and they are highly susceptible to corruption. There is another way if you don't need to "protect" the image. You can simply reference the image in it's directory in a memo field, and then display that in an image object by reference. I stopped putting images into tables a LONG time ago.)

Scott:

I hope to have answered this above and I agree now with what Mike Lewis and Mike Gagnon and others said
No embedding in table is necessary.

I still have to think about how to get old frame numbers
can hold on to if new photos of my paintings are added to the inventory.
I can automatically form a 4-digit number
use, because with it I can easily label the original paintings and keep them in the archives.
Your suggestion with memo fields is also good, but with the program I save myself having to specify numbers.

I just have to figure out how to not destroy the existing numbering
from presently about 500 pictures when new pictures are added.
For example, the image that has the number 0001 must always have this number
remember, your program would then destroy the mapping if
I restart it with another bulk of photos.

Also, I'm still not sure how to add images or a group of
show images on the screen. (pre-made image objects, a grid or even page-frame?)

Thank you very much for your help.
Klaus

Peace worldwide - it starts here...

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members! Already a Member? Login


Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close