5,699,431 members and growing! (18,397 online)
Email Password   helpLost your password?
Database » Database » SQL Server     Intermediate License: The Common Development and Distribution License (CDDL)

C# Photo Album Viewer

By Mark Nischalke

A C# Windows application to store and retrieve photos from a SQL Server database.
C#.NET 1.0, Win2K, WinXP, Windows, .NETVisual Studio, VS.NET2002, DBA, Dev

Posted: 12 Apr 2002
Updated: 20 Apr 2002
Views: 393,142
Bookmarked: 197 times
Announcements
Loading...



Search    
Advanced Search
Sitemap
89 votes for this Article.
Popularity: 8.27 Rating: 4.24 out of 5
5 votes, 6.5%
1
0 votes, 0.0%
2
5 votes, 6.5%
3
12 votes, 15.6%
4
55 votes, 71.4%
5

Sample Image - AlbumViewer.jpg

C# Photo Album Viewer

This sample is a C# Windows application that uses a SQL Server 2000 database to store and retrieve images. Images are organized under albums in a treeview and displayed in a picturebox when selected. An static control is used to display a description of the album or image. Context menus on the treeview allow the user to add, rename, and delete images or albums. Descriptions can also be edited by selecting a context menu item.

The Database Tables

CREATE TABLE [dbo].[Albums] (
	[id] [int] IDENTITY (1, 1) NOT NULL ,
	[name] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
	[desc] [varchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL 
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Photos] (
	[id] [int] IDENTITY (1, 1) NOT NULL ,
	[name] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NOT NULL ,
	[desc] [varchar] (200) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
	[album_id] [int] NOT NULL ,
	[photo] [image] NULL 
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

The Stored Procedures

CREATE PROC sp_GetPhotoAlbums AS
SELECT Albums.[id] AS AlbumID, Albums.[name] AS Album, 
       Albums.[desc] AS Album_Desc, Photos.[id] AS PhotoID, 
       Photos.[name] AS Photo, Photos.photo, Photos.[desc] AS Photo_Desc
FROM Albums INNER JOIN Photos ON Albums.[id] = Photos.album_id
ORDER BY Albums.[id]
GO

CREATE PROCEDURE sp_InsertPhoto
    @name AS VARCHAR(50),
    @image AS IMAGE,
    @album AS INT
AS

INSERT INTO Photos ([name], photo, album_id) 
VALUES (@name, @image, @album) 

RETURN @@identity
GO

CREATE PROCEDURE sp_NewAlbum
    @name AS VARCHAR(20)
AS

INSERT INTO Albums ([name]) 
VALUES (@name) 

RETURN @@identity
GO

Storing the images

After selecting the Add Photo context menu item a multi select FileOpenDialog allows images to be selected for addition. For each file a System.IO.FileStream is created and used to read into a byte array. The byte array is then passed to a method which uses it as an input parameter for a stored procedure to add it to an image field of the database table.

The last step is to add the image to the treeview. A helper class call TreeItem is used for this purpose. This class stores the description and database index id of the image. This class is also used for albums so an enum defines the type of object it is. After a new instance of this class is created it is assigned to the Tag member of the TreeNode. The node is then added to the selected album node.

private void OnAddPhoto(object sender, System.EventArgs e)
{
    // Show the file open dialog

    if( DialogResult.OK == FileOpenDlg.ShowDialog() )
    {
        // Retrieve the treeitem for the selected parent node

        TreeItem item = (TreeItem)treeAlbum.SelectedNode.Tag;
        
        // We allow multiple selections so loop through each one

        foreach( string file in FileOpenDlg.FileNames )
        {
            // Create a new stream to load this photo into

            System.IO.FileStream stream = new System.IO.FileStream(file, 
                                                    System.IO.FileMode.Open, 
                                                    System.IO.FileAccess.Read);
            // Create a buffer to hold the stream bytes

            byte[] buffer = new byte[stream.Length];
            // Read the bytes from this stream

            stream.Read(buffer, 0, (int)stream.Length);
            // Now we can close the stream

            stream.Close();

            // Extract out the name of the file an use it for the name

            // of the photo

            string strName = System.IO.Path.GetFileNameWithoutExtension(file);

            // Insert the image into the database and add it to the tree

            InsertImage(ref buffer, strName, item.Id);
            buffer = null;
        }
        // Select the last child node under this album

        treeAlbum.SelectedNode = treeAlbum.SelectedNode.LastNode;
    }
}

private void InsertImage(ref byte[] buffer, string strName, int nAlbum)
{
    try
    {
        // Create a stored procedure command

        SqlCommand cmd = new SqlCommand("sp_InsertPhoto", sqlConn);
        cmd.CommandType = CommandType.StoredProcedure;

        // Add the return value parameter

        SqlParameter param = cmd.Parameters.Add("RETURN_VALUE", SqlDbType.Int);
        param.Direction = ParameterDirection.ReturnValue;
        
        // Add the name paramter and set the value

        cmd.Parameters.Add("@name", SqlDbType.VarChar).Value = strName;
        // Add the image paramter and set the value

        cmd.Parameters.Add("@image", SqlDbType.Image).Value = buffer;
        // Add the album paramter and set the value

        cmd.Parameters.Add("@album", SqlDbType.Int).Value = nAlbum;

        // Execute the insert

        cmd.ExecuteNonQuery();
        
        // Return value will be the index of the newly added photo

        int nID = (int)cmd.Parameters["RETURN_VALUE"].Value;
        
        // Create a new node

        TreeNode node = new TreeNode(strName);
        // Create new treeitem to store the info about this photo

        node.Tag = new TreeItem(ItemType.Photo, nID, "Enter description");
        
        // Get the index of the album we are adding to

        // and insert the new photo node

        nID = treeAlbum.SelectedNode.Index;
        treeAlbum.Nodes[nID].Nodes.Add(node);
    }
    catch(Exception e)
    {
        MessageBox.Show(e.Message);
    }
}

Display the image

The AfterSelect event captures the selection of an image or album. If an images is selected the Tag member of the selected node is retrieved and cast into a TreeItem. The Id member of this class is then passed to a stored procedure to retrieve the desired image. The return of the ExecuteScalar method is cast into a byte array which is then read into a System.IO.MemoryStream. This stream object is then used to create a Bitmap which is then used assigned to the picturebox for display.

private void OnAfterSelect(object sender, 
                           System.Windows.Forms.TreeViewEventArgs e)
{
    try
    {
        // Disable edit controls if we were in edit mode

        if( true == btnUpdate.Visible )
        {
            btnUpdate.Visible = false;
            txtDesc.Visible = false;
            lblDesc.Visible = true;
        }

        // Retrieve the item info for this node

        TreeItem item = (TreeItem)e.Node.Tag;
            
        // If the selected item is an album...

        if( ItemType.Album == item.Type )
        {
            lblDesc.Text = item.Desc; // Set the description

            pictureBox.Image = null;  // Clear the image

            return;
        }

        // ...otherwise it is a photo


        // Create a command to select the selected photo

        string strCmd = String.Format("SELECT photo FROM Photos WHERE id = {0}", 
                                      item.Id);
        SqlCommand cmd = new SqlCommand(strCmd, sqlConn);
                        
        // Set the description

        lblDesc.Text = item.Desc;

        // Get bytes return from stored proc

        byte[] b = (byte[])cmd.ExecuteScalar();
        if(b.Length > 0)
        {
            // Open a stream for the image and write the bytes into it

            System.IO.MemoryStream stream = new System.IO.MemoryStream(b, true);
            stream.Write(b, 0, b.Length);
            
            // Create a bitmap from the stream

            Bitmap bmp = new Bitmap(stream);

            // Check for scaling and assign the bitmap to the Picturebox

            if( bmp.Width > 500 && bmp.Height > 300)
            {
                Bitmap bmp1 = new Bitmap(bmp, new Size(500,300));
                pictureBox.Image = bmp1;
            }
            else
                pictureBox.Image = bmp;
        
            // Close the stream

            stream.Close();
        }
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Conclusion

This is a relatively simple implementation of a photo album viewer application. Using .NET and C# definitely made this application very easy to make. Storing the images in a SQL Server database adds a bit to the distribution but also simplifies the application by having one source to store and retrieve images from. You also don't have to worry about missing files or broken links.

One area in which this application can be improved is the scaling of the displayed images. Unfortunately I have not had the time to add this. Despite this limitation I felt the application sufficient to share with others for their benefit.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

About the Author

Mark Nischalke


Supporter
My first job was coding COBOL on Mainframes but I soon progressed to DOS, then to Windows. I've been a consultant for a number of years and have been involved in a variety of projects, from Finite Element Analysis systems to train control systems to large e-commerce websites to one page static websites. I attained my MCSD status in 1998 with the WOSA exams, updated it with VC++ and transitioned to MCSD.NET, grabbing MCAD.NET along the way. I've been working almost exclusively with C# and .NET since it was in beta.
Occupation: Other
Location: United States United States

Other popular Database articles:

Article Top
Sign Up to vote for this article
You must Sign In to use this message board.
FAQ FAQ Noise ToleranceSearch Search Messages 
 Layout  Per page   
 Msgs 1 to 25 of 105 (Total in Forum: 105) (Refresh)FirstPrevNext
QuestionSaving Image to Databasemembertonyg2smith4:30 6 Oct '06  
AnswerRe: Saving Image to Databasemembertonyg2smith4:32 6 Oct '06  
AnswerRe: Saving Image to DatabasesupporterMark Nischalke4:57 6 Oct '06  
Generalretrieving the image again from the data basememberkarimkamal16:57 26 Apr '06  
GeneralRe: retrieving the image again from the data basememberMark Nischalke17:38 26 Apr '06  
GeneralRe: retrieving the image again from the data basememberkarimkamal19:34 26 Apr '06  
GeneralRe: retrieving the image again from the data basememberkarimkamal21:19 26 Apr '06  
GeneralAsp .netmemberbabamara7:47 9 Apr '06  
Generalimage detailmemberJA_Baller8:03 30 Mar '06  
GeneralRe: image detailmemberMark Nischalke9:35 30 Mar '06  
GeneralHow to do slide show?memberdinoniko15:27 12 Oct '05  
GeneralRe: How to do slide show?memberMark Nischalke16:39 12 Oct '05  
GeneralQ ?memberAhmed jamil Kattan5:41 4 Jun '05  
GeneralRe: Q ?memberMark Nischalke6:05 4 Jun '05  
GeneralRe: Q ?memberAhmed jamil Kattan21:31 4 Jun '05  
GeneralRe: Q ?membervandil12:56 23 Aug '05  
Generalis it recomended?memberJordi Corominas1:19 25 Nov '04  
GeneralRe: is it recomended?memberMark Nischalke4:23 25 Nov '04  
GeneralRe: is it recomended?memberdonalvn15:43 14 Dec '04  
GeneralRe: is it recomended?membercandynata15:47 12 Dec '05  
GeneralRe: is it recomended?memberMah Jin Khai7:27 29 Mar '06  
GeneralLarge Imagesmembersfawcett21:22 6 Sep '04  
GeneralASP.NET?sussAnonymous12:16 15 Jun '04  
GeneralRe: ASP.NET?memberMark Nischalke12:54 15 Jun '04  
GeneralRe: ASP.NET?sussAnonymous17:00 15 Jun '04  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 20 Apr 2002
Editor: Chris Maunder
Copyright 2002 by Mark Nischalke
Everything else Copyright © CodeProject, 1999-2008
Web19 | Advertise on the Code Project