Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

how to fill a table with images 1

Status
Not open for further replies.

german12

Programmer
Nov 12, 2001
563
0
16
DE
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...
 
Hello Klaus,

To add an image to a single record:

Go to the relevant record, and then:

[tt]APPEND GENERAL <name of General field> FROM <filename>
[/tt]
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
 
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.
 
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 first.
 
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...
 
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.

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
 
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
 
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
 
Scott24x7 :
I just tried your code (thank you very much for it.)

There is a question for both these lines:
laFiles = ADIR([highlight #FCE94F]laDirInfo[/highlight], 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
Screenshot_lcfolder_a6nvp9.jpg



lafilesdoesnot_kitabs.jpg


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...
 
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:
[tt]
laFiles = ADIR(laDirInfo, lcFolderPath + "*.jpg")
lnFileCount = laFiles[0][/tt]

You should do this:

[tt]lnFileCount = ADIR(laDirInfo, lcFolderPath + "*.jpg")[/tt]

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
 
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.
 
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 [highlight #FCE94F]CLASS 'Paint.Picture'[/highlight] 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
 
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 [highlight #FCE94F]of the jpg[/highlight] 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
 

Chris Miller said:
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.

Chris Miller said:
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
 
mJindrova said:
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:
generalbloat_df5ymf.jpg

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
 
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
 

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

mJindrova
 
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
 
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
 
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
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top