To display your stored images:
1. Add a Windows Application project named DisplayImagesto your solution.
Rename Form1.csto DisplayImages.cs.
2. Add a text box, a button, and a picture box control to the form and set its Text property to Display Imagesas in Figure 16-2.
3. Add a new class named Imagesto the project. Replace the code in Images.cswith the code in Listing 16-2.
Listing 16-2.Images.cs using System;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
namespace DisplayImages {
public class Images {
string imageFilename = null;
byte[] imageBytes = null;
SqlConnection imageConnection = null;
SqlCommand imageCommand = null;
SqlDataReader imageReader = null;
C H A P T E R 1 6 ■ W O R K I N G W I T H T E X T A N D B I N A RY D ATA 413
Figure 16-2.DisplayImages form
// Constructor public Images() {
imageConnection = new SqlConnection(@"
data source = .\sqlexpress;
integrated security = true;
initial catalog = tempdb;
");
imageCommand = new SqlCommand(
@"
select imagefile, imagedata from
imagetable
",
imageConnection );
// Open connection and create data reader imageConnection.Open();
imageReader = imageCommand.ExecuteReader();
}
public Bitmap GetImage() {
MemoryStream ms = new MemoryStream(imageBytes);
Bitmap bmap = new Bitmap(ms);
return bmap;
}
public string GetFilename() {
return imageFilename;
}
public bool GetRow() {
if (imageReader.Read()) {
imageFilename = (string) imageReader.GetValue(0);
imageBytes = (byte[]) imageReader.GetValue(1);
return true;
} else {
return false;
} }
public void EndImages() {
// Close the reader and the connection.
imageReader.Close();
imageConnection.Close();
} } }
4. Insert an instance variable (as in the bold code shown here) of type Imagesinto DisplayImagesDesigner.cs:
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.PictureBox pictureBox1;
private Images images;
5. Insert the code in Listing 16-3 into DisplayImages.csafter the call to InitializeComponent()in the constructor.
C H A P T E R 1 6 ■ W O R K I N G W I T H T E X T A N D B I N A RY D ATA 415
Listing 16-3.Initialize Images Display in DisplayImagesConstructor images = new Images();
if (images.GetRow()) {
this.textBox1.Text = images.GetFilename();
this.pictureBox1.Image = (Image)images.GetImage();
} else {
this.textBox1.Text = "DONE";
this.pictureBox1.Image = null;
}
6. Insert the code in Listing 16-3 (except for the first line) into the button1_Clickevent handler.
7. Insert the highlighted line shown here into the Disposemethod of DisplayImagesin DisplayImages.Designer.cs:
images.endImages();
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
8. Make it the startup project and run it with Ctrl+F5. You should see the output in Figure 16-3. Click Next to see all the milk carton images in succession; when the last is reached, the word DONE will appear in the text box. Since you didn’t add an Exit button, just close the window to exit.
How It Works
You declared a type, Images, to access the database and provide methods for the form components to easily get and display images. In its constructor, you connected to the database and created a data reader to handle the result set of a query that retrieves all the images you stored earlier.
// Constructor public Images() {
imageConnection = new SqlConnection(@"
data source = .\sqlexpress;
integrated security = true;
initial catalog = tempdb;
");
imageCommand = new SqlCommand(
@"
select imagefile, imagedata from
imagetable
",
imageConnection );
C H A P T E R 1 6 ■ W O R K I N G W I T H T E X T A N D B I N A RY D ATA 417
Figure 16-3.Displaying images
// Open connection and create data reader imageConnection.Open();
imageReader = imageCommand.ExecuteReader();
}
When the form was initialized, the new code created an instance of Images, looked for an image with GetRow(), and, if one was found, assigned the filename and image to the text box and picture box with the GetFilenameand GetImagemethods, respectively.
images = new Images();
if (images.GetRow()) {
this.textBox1.Text = images.GetFilename();
this.pictureBox1.Image = (Image)images.GetImage();
} else {
this.textBox1.Text = "DONE";
this.pictureBox1.Image = null;
}
You used the same ifstatement in the Next button’s click event handler to look for the next image. If none was found, you displayed the word DONE in the text box.
You called the endImagesmethod when the form terminated to close the connec- tion. (Had you used a dataset instead of a data reader, you could have closed the connection in the Imagesinstance immediately after the images were retrieved, which would be a good exercise for you to attempt.)
protected override void Dispose(bool disposing) {
images.endImages();
if (disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
The image is returned from the database as an array of bytes. The PictureBoxcontrol Imageproperty can be a Bitmap,Icon, or Metafile(all derived classes of Image). Bitmapsup- ports a variety of formats, including BMP, GIF, and JPG. The getImagemethod, shown here, returns a Bitmapobject:
public Bitmap GetImage() {
MemoryStream ms = new MemoryStream(imageBytes);
Bitmap bmap = new Bitmap(ms);
return bmap;
}
Bitmap’s constructor doesn’t accept a byte array, but it will accept a MemoryStream (which is effectively an in-memory representation of a file), and MemoryStreamhas a con- structor that accepts a byte array. So, you create a memory stream from the byte array and then create a bitmap from the memory stream.