Section 2: Using DBImage to extract JPEG—the wrong way
DBImage - take one (The DBImage - take one)
When trying to do something new with Delphi, the first thing I do is to ask Delphi's built-in help for a method. This is what the help documentation will answer: A TDBImage (in the Data Controls page of the Component Palette) represents a graphical image of a BLOB field in the database's current record. Use TDBImage to represent graphic field values. TDBImage allows forms to display graphical data from a database. TDBImage only has some more data visibility properties than the TImage component. The two most important properties are: DataSource (data source) and Field (field). The DataSource property connects the graphical component to the database. On our form there is a DataSource component named DataSource1 - which represents a data set. The Field property indicates the field (in the table) that holds the image.
Everything is clear, now place a DBImage component on the form and name it DBImage1 by default. In order to truly connect the DBImage to the BLOB field of the table, we only need to do the following configuration (using the Object Inspector):
DBImage1.DataSource = DataSource1
DBImage1.Field = Picture
This is a necessary trick in order to display a JPEG image that exists in the Picture field of the applications table.
To verify that this configuration works, the only thing we need to do is set the Active property of the ADOTable1 component to True. We can do it in the Object Inspector during design. Once you do this, the following dialog box will appear:
What? Why does it show "Bitmap image is invalid"? We have JPEG images instead of BMP images - is that the problem? Let's go back to help.
After a while of clicking in the help, I came to the conclusion: in order to get the JPG image in the database, we have to use the TJpegImage object. To display images, we need a simple, invisible version of the Image component. At the same time, we need to use a stream to load the image from the BLOB object. Help document description: We should use TADOBlobStream to access or change the value of the BLOB or memo (note) field in the ADO data set.
Section 3: Using streams to extract JPEG—wrong method
Pulling the JPEG - take two!
Since we can't do anything with the DBImage - remove it from the form and put in a regular TImage component (Additional page) named ADOImage. Unfortunately, the Image component does not have any data-aware properties, so a separate program is required to display the image from the database table it represents. The simplest way to accomplish this is to place a Button on the form, put all the program code in its OnClick event, and name the button: "btnShowImage".
In order to use ADOBLOBStream, the help documentation recommends creating a TADOBlobStream instance, using the "stream" method to read the graphics fields from the data set, and then releasing the BLOB stream. Somewhere in the middle, we will need to load a JPEG image from a TADOBlobStream object using the LoadFromStream method. The Picture and Graphic properties of the Image component will be used to actually store and display pictures.
Field object, what is it?
At this point, I assume that just a little knowledge of field objects is more than enough for you to master this chapter. In the development of Delphi database, one of the main objects is the TField object. Field components are non-visual objects that represent the fields of a dataset at run (or design) time. TADOTable (and other TDataSet subclasses) provide design-time access to the Fields Editor. The Fields Editor enables you to select the fields you want to include in the data set. More importantly, it creates a robust list of field components used in the application's dataset. In order to call the Fields Editor, double-click the TADOTable component. By default, the field list is empty. Click the Add button to open a dialog box that lists the fields of the Applications table. By default, all fields are selected, then select OK.
Delphi will give the default name of the field as follows: Table (table) name + Field (field) name. This means our picture field is named: ADOTable1Picture.
The Create method of TADOBlobStream creates an instance for reading or writing a specified BLOB field object, in this case the ADOTable1Picture field.
We write program code in the OnClick event of the btnShowImage button. This code will read the picture from the Picture field of the currently selected row. The source code is as follows:
uses jpeg;
...
PRocedure TForm1.btnShowImageClick(Sender: TObject);
var bS: TADOBlobStream;
Pic: TJpegImage;
begin
bS := TADOBlobStream.Create
(AdoTable1Picture, bmRead);
try
Pic:=TJpegImage.Create;
try
Pic.LoadFromStream(bS);
ADOImage.Picture.Graphic:=Pic;
finally
Pic.Free;
end ;
finally
bS.Free
end ;
end ;
OK, let's run this project. Of course, set the ADOTable1.Active property to True. After the form is displayed, click the button and the following display will appear:
Uh, what's going on? The code is 100% correct but why doesn't the image display? Remember "never give up, never surrender"! Let’s drill down to the byte level and see what’s going on!