Working with Images

function OpenWin(url, w, h) { if(!w) w = 400; if(!h) h = 300; window.open(url, "_new", "width=" + w + ",height=" + h + ",menubar=no,toobar=no,scrollbars=yes", true); }

Working with image files has never been one of the easiest tasks to undertake. Acquiring proficiency with image formats such as bitmap, jpeg, gif, tiff, and countless others requires a significant investment of time and effort. Fortunately, the base class libraries provide support for the common image formats and allow for simple loading, displaying, and conversion of various image formats. Table 4.1 lists the currently supported image formats.

Table 4.1. Supported Image Formats
Image Format Description
Bmp Bitmap image format
Emf EnhancedWindows metafile image format
Exif Exchangeable image format
Gif Graphics interchange format
Icon Windows icon file format
Jpeg Joint Photographic Experts Group (Jpeg) image format
MemoryBmp Memory bitmap image format
Png WC3 Portable Network Graphics image format
Tiff Tag image file format
Wmf Windows metafile image format

Unless you have plans to create a custom imaging application such as PaintShop Pro or Adobe PhotoShop, the Image class should serve the basic needs of loading and displaying images. Figure 4.7 shows the UI for the ImageStudio Demo application.

Figure 4.7. ImageStudio.

figure 4.7. imagestudio.

The ImageStudio Demo allows for viewing various image formats and for saving loaded images into other supported formats. The following listings describe the ImageStudio Demo source files.

ImageStudio will be developed in a pseudo-MVC-style framework. MVC refers to Model-View-Control and is a popular framework for developing large applications. Visual C++ developers will see this as similar to the Doc/View architecture employed by MFC. The basic premise of these two framework styles, MVC and MFC, is to separate the data, in this case the image, from the onscreen representation and the parent form or controller that handles user input. In addition, ImageStudio is an MDI application allowing for multiple images to be loaded and viewed at the same time. Listing 4.8 presents the Model or Document class used by ImageStudio.

Listing 4.8 ImageDocument Class
  1: using System;  2: using System.Drawing;  3: using System.Drawing.Imaging;  4:  5: namespace ImageStudio  6: {  7:     public class ImageDocument  8:     {  9: 10:         private Image    image; 11: 12:         public event EventHandler DocumentChanged; 13: 14:         public Image Image { 15:             get {  return image; } 16:         } 17: 18:         public ImageDocument()    {         } 19: 20:         public bool Open( string FileName ) { 21:             try { 22:                 image = Image.FromFile( FileName ); 23:                 OnDocumentChanged( new EventArgs( ) ); 24:                 return true; 25:             }  catch( Exception e ) { 26:                 System.Diagnostics.Debug.WriteLine( e.Message ); 27:                 return false; 28:             } 29:         } 30: 31:         public bool Save( string Filename, ImageFormat Format ) { 32:             try { 33:                 image.Save( Filename, Format ); 34:                 return true; 35:             }  catch( Exception e ) { 36:                 System.Diagnostics.Debug.WriteLine( e.Message ); 37:                 return false; 38:             } 39:         } 40: 41:         protected virtual void OnDocumentChanged( EventArgs e ) { 42:             if( DocumentChanged != null ) 43:                 DocumentChanged( this, e ); 44:         } 45:    } 46: } 

The ImageDocument class handles the loading and saving of images. Notice on line 22 of Listing 4.8 that the Image.FromFile static method requires only the filename of the image to load. The method uses the extension of the file to determine the format of the file and as such does not require that the format be specified. The Image.Save method can also use the file extension to determine the format, or override to save to a new format based on the ImageFormat argument.

Listing 4.9 is the ImageView class, which is derived from Panel and supports scrolling of the image. As its name suggests, the ImageView class represents the View component of MVC or Doc/View MFC framework-style development.

Listing 4.9 ImageView Class
  1: using System;  2: using System.Windows.Forms;  3: using System.Drawing;  4: using System.Drawing.Imaging;  5:  6:  7: namespace ImageStudio  8: {  9: 10:     public class ImageView : System.Windows.Forms.Panel 11:     { 12:         private ImageDocument    imageDocument; 13: 14:         public ImageView( ImageDocument Document ) 15:         { 16:             this.BorderStyle = BorderStyle.Fixed3D; 17:             imageDocument = Document; 18:             if( imageDocument.Image != null ) 19:                 AutoScrollMinSize = imageDocument.Image.Size; 20: 21:         } 22: 23:         protected override void OnSizeChanged( EventArgs e ) { 24:             base.OnSizeChanged( e ); 25:             this.Invalidate( ); 26:         } 27: 28:         protected override void OnPaint( PaintEventArgs e ) { 29:             base.OnPaint( e ); 30:             if( imageDocument.Image != null ) 31:                 e.Graphics.DrawImage( imageDocument.Image, 32:                                       AutoScrollPosition.X, 33:                                       AutoScrollPosition.Y, 34:                                       imageDocument.Image.Width, 35:                                       imageDocument.Image.Height ); 36:         } 37:   } 38: } 

The sole purpose of the ImageView class is to render the loaded image and support scrolling when the window is smaller than the image size.

The ImageStudio Demo is an MDI application. Listing 4.10 contains the source for the ImageFrameChild class. The ImageFrameChild ties together a single instance of an ImageDocument and one or more ImageView classes. In the ImageStudio Demo application, only a single ImageView class is hosted within the ImageFrameChild.

Listing 4.10 ImageFrameChild MDI Child Form
  1: using System;  2: using System.Drawing;  3: using System.Collections;  4: using System.ComponentModel;  5: using System.Windows.Forms;  6:  7: namespace ImageStudio  8: {  9:     /// <summary> 10:     /// Summary description for ImageFrameChild. 11:     /// </summary> 12:     public class ImageFrameChild : System.Windows.Forms.Form 13:     { 14:         private ImageDocument    imageDocument; 15:         private ImageView        imageView; 16: 17: 18:         /// <summary> 19:         /// Required designer variable. 20:         /// </summary> 21:         private System.ComponentModel.Container components = null; 22: 23: 24:         public ImageDocument Document { 25:             get {  return imageDocument; } 26:         } 27: 28:         public ImageFrameChild( ImageStudio.ImageDocument Document ) 29:         { 30:             InitializeComponent(); 31: 32:             imageDocument = Document; 33:             imageView = new ImageView( Document ); 34:             imageView.Dock = DockStyle.Fill; 35:             this.Controls.Add( imageView ); 36:         } 37: 38:         /// <summary> 39:         /// Clean up any resources being used. 40:         /// </summary> 41:         protected override void Dispose( bool disposing ) 42:         { 43:             if( disposing ) 44:             { 45:                 if(components != null) 46:                 { 47:                     components.Dispose(); 48:                 } 49:             } 50:             base.Dispose( disposing ); 51:         } 52: 53:         #region Windows Form Designer generated code 54:         /// <summary> 55:         /// Required method for Designer support - do not modify 56:         /// the contents of this method with the code editor. 57:         /// </summary> 58:         private void InitializeComponent() 59:         { 60:             // 61:             // ImageFrameChild 62:             // 63:             this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); 64:             this.ClientSize = new System.Drawing.Size(600, 373); 65:             this.Name = "ImageFrameChild"; 66:             this.Text = "ImageFrameChild"; 67: 68:         } 69:   #endregion 70:     } 71: } 

The ImageFrameChild ties a specific instance of an ImageDocument class to the ImageView class that is responsible for displaying the loaded image. The goal of implementing all these classes, ImageFrameChild, ImageDocument, and ImageView, is to focus the responsibilities of the application where they make sense. Such a design might be somewhat overkill for this demo; however, understanding such design patterns and their usage is important when creating large-scale applications and even complex custom controls. The final component of the application is the MainFrame window or the Controller from the MVC architecture. The supporting cast is in place and all that remains is a host to oversee the user interaction and to dispatch responsibilities to the various components of the application.

Listing 4.11, the final listing for the ImageStudio Demo, is the MainFrame MDI parent window. The MainFrame provides handling of menu items and manages the MDI children, ImageFrameChild class, for the demo application.

Listing 4.11 MainFrame MDI Parent Form
   1: using System;   2: using System.Drawing;   3: using System.Collections;   4: using System.ComponentModel;   5: using System.Windows.Forms;   6: using System.Data;   7: using System.Drawing.Imaging;   8:   9: namespace ImageStudio  10: {  11:     public class MainFrame : System.Windows.Forms.Form  12:     {  13:         private System.Windows.Forms.MainMenu mainFrameMenu;  14:         private System.Windows.Forms.MenuItem fileOpenMenuItem;  15:         private System.Windows.Forms.MenuItem fileCloseMenuItem;  16:         private System.Windows.Forms.MenuItem fileSaveAsMenuItem;  17:         private System.Windows.Forms.MenuItem fileExitMenuItem;  18:         private System.Windows.Forms.MdiClient mdiClient1;  19:         private System.Windows.Forms.MenuItem fileSep2MenuItem;  20:         private System.Windows.Forms.MenuItem fileSep1MenuItem;  21:         private System.Windows.Forms.MenuItem fileMenuItem;  22:         private System.Windows.Forms.OpenFileDialog openFileDialog;  23:         private System.Windows.Forms.SaveFileDialog saveFileDialog;  24:         /// <summary>  25:         /// Required designer variable.  26:         /// </summary>  27:         private System.ComponentModel.Container components = null;  28:         private System.Windows.Forms.MainMenu mainMenu1;  29:         private System.Windows.Forms.MenuItem windowMenuItem;  30:  31:  32:         private ArrayList                        fileFormats;  33:  34:         public MainFrame()  35:         {  36:             //  37:             // Required for Windows Form Designer support  38:             //  39:             InitializeComponent();  40:  41:             fileFormats = new ArrayList( );  42:             fileFormats.Add( ImageFormat.Bmp );  43:             fileFormats.Add( ImageFormat.Gif );  44:             fileFormats.Add( ImageFormat.Jpeg );  45:             fileFormats.Add( ImageFormat.Png );  46:             fileFormats.Add( ImageFormat.Tiff );  47:         }  48:  49:       protected override void Dispose( bool disposing )  50:         {  51:             if( disposing )  52:             {  53:                 if (components != null)  54:                 {  55:                     components.Dispose();  56:                 }  57:             }  58:             base.Dispose( disposing );  59:         }  60:  61:         #region Windows Form Designer generated code  62:         /// <summary>  63:         /// Required method for Designer support - do not modify  64:         /// the contents of this method with the code editor.  65:         /// </summary>  66:         private void InitializeComponent()  67:         {  68:          this.openFileDialog = new System.Windows.Forms.OpenFileDialog();  69:          this.fileExitMenuItem = new System.Windows.Forms.MenuItem();  70:          this.mdiClient1 = new System.Windows.Forms.MdiClient();  71:          this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();  72:          this.fileSep1MenuItem = new System.Windows.Forms.MenuItem();  73:          this.fileSep2MenuItem = new System.Windows.Forms.MenuItem();  74:          this.fileOpenMenuItem = new System.Windows.Forms.MenuItem();  75:          this.fileCloseMenuItem = new System.Windows.Forms.MenuItem();  76:          this.mainFrameMenu = new System.Windows.Forms.MainMenu();  77:          this.fileMenuItem = new System.Windows.Forms.MenuItem();  78:          this.fileSaveAsMenuItem = new System.Windows.Forms.MenuItem();  79:          this.mainMenu1 = new System.Windows.Forms.MainMenu();  80:          this.windowMenuItem = new System.Windows.Forms.MenuItem();  81:          this.SuspendLayout();  82:             //  83:      // openFileDialog  84:             //  85:             this.openFileDialog.DefaultExt = "bmp";  86:             this.openFileDialog.Filter =  graphics/ccc.gif"Bitmaps|*.bmp|Gif|*.gif|Jpeg|*.jpg|Tiff|*.tiff|Png|*.png";  87:             this.openFileDialog.Title = "Open Image File";  88:             //  89:             // fileExitMenuItem  90:             //  91:             this.fileExitMenuItem.Index = 5;  92:             this.fileExitMenuItem.Text = "E&xit";  93:             this.fileExitMenuItem.Click += new  graphics/ccc.gifSystem.EventHandler(this.fileExitMenuItem_Click);  94:             //  95:             // mdiClient1  96:             //  97:             this.mdiClient1.Dock = System.Windows.Forms.DockStyle.Fill;  98:             this.mdiClient1.Name = "mdiClient1";  99:             this.mdiClient1.TabIndex = 0; 100:             // 101:             // saveFileDialog 102:             // 103:             this.saveFileDialog.FileName = "image"; 104:             this.saveFileDialog.Filter =  graphics/ccc.gif"Bitmaps|*.bmp|Gif|*.gif|Jpeg|*.jpg|Tiff|*.tiff|Png|*.png"; 105:             // 106:             // fileSep1MenuItem 107:             // 108:             this.fileSep1MenuItem.Index = 2; 109:             this.fileSep1MenuItem.Text = "-"; 110:             // 111:             // fileSep2MenuItem 112:             // 113:             this.fileSep2MenuItem.Index = 4; 114:             this.fileSep2MenuItem.Text = "-"; 115:             // 116:             // fileOpenMenuItem 117:             // 118:             this.fileOpenMenuItem.Index = 0; 119:             this.fileOpenMenuItem.Text = "&Open"; 120:             this.fileOpenMenuItem.Click += new  graphics/ccc.gifSystem.EventHandler(this.fileOpenMenuItem_Click); 121:             // 122:             // fileCloseMenuItem 123:             // 124:             this.fileCloseMenuItem.Index = 1; 125:             this.fileCloseMenuItem.Text = "&Close"; 126:             this.fileCloseMenuItem.Click += new  graphics/ccc.gifSystem.EventHandler(this.fileCloseMenuItem_Click); 127:             // 128:             // mainFrameMenu 129:             // 130:      this.mainFrameMenu.MenuItems.AddRange(new MenuItem[] { 131:                                                     this.fileMenuItem, 132:                                                     this.windowMenuItem} ); 133:             // 134:             // fileMenuItem 135:             // 136:             this.fileMenuItem.Index = 0; 137:             this.fileMenuItem.MenuItems.AddRange(new MenuItem[] { 138:                                                  this.fileOpenMenuItem, 139:                                                  this.fileCloseMenuItem, 140:                                                  this.fileSep1MenuItem, 141:                                                  this.fileSaveAsMenuItem, 142:                                                  this.fileSep2MenuItem, 143:                                                  this.fileExitMenuItem} ); 144:             this.fileMenuItem.Text = "&File"; 145:             // 146:             // fileSaveAsMenuItem 147:             // 148:             this.fileSaveAsMenuItem.Index = 3; 149:             this.fileSaveAsMenuItem.Text = "Save &As..."; 150:             this.fileSaveAsMenuItem.Click += new  graphics/ccc.gifSystem.EventHandler(this.fileSaveAsMenuItem_Click); 151:             // 152:             // windowMenuItem 153:             // 154:             this.windowMenuItem.Index = 1; 155:             this.windowMenuItem.MdiList = true; 156:             this.windowMenuItem.Text = "Window"; 157:             // 158:             // MainFrame 159:             // 160:             this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); 161:             this.ClientSize = new System.Drawing.Size(592, 393); 162:             this.Controls.AddRange(new Control[] {  this.mdiClient1 } ); 163:             this.IsMdiContainer = true; 164:             this.Menu = this.mainFrameMenu; 165:             this.Name = "MainFrame"; 166:             this.Text = "ImageStudio"; 167:             this.ResumeLayout(false); 168: 169:         } 170:       #endregion 171: 172:         /// <summary> 173:         /// The main entry point for the application. 174:         /// </summary> 175:         [STAThread] 176:         static void Main() 177:         { 178:             Application.Run(new MainFrame()); 179:         } 180:         ////////////////////////////// 181:         ///File Menu Event Handlers 182:         ////////////////////////////// 183:         private void fileOpenMenuItem_Click(object sender, System.EventArgs e) { 184: 185:             if( DialogResult.OK == openFileDialog.ShowDialog( ) ) { 186:                 ImageDocument doc = new ImageDocument( ); 187:                 if( doc.Open( openFileDialog.FileName ) ) { 188:                     ImageFrameChild child = new ImageFrameChild( doc ); 189:                     string[] T = openFileDialog.FileName.Split( '\ \ ' ); 190:                     child.Text = T[T.Length-1]; 191:                     child.MdiParent = this; 192:                     child.Show( ); 193:                 } 194:             } 195: 196:         } 197: 198:         private void fileCloseMenuItem_Click(object sender, System.EventArgs e) { 199:             this.ActiveMdiChild.Close( ); 200:         } 201: 202:         private void fileSaveAsMenuItem_Click(object sender, System.EventArgs e) { 203:             if( DialogResult.OK == saveFileDialog.ShowDialog( ) ) { 204:                 ImageDocument doc = ((ImageFrameChild)ActiveMdiChild).Document; 205:                 doc.Save( saveFileDialog.FileName, GetImageFormat(  graphics/ccc.gifsaveFileDialog.FilterIndex - 1) ); 206:             } 207:         } 208: 209:         private void fileExitMenuItem_Click(object sender, System.EventArgs e) { 210:             Close( ); 211:         } 212: 213:         private ImageFormat GetImageFormat( int FilterIndex ) { 214:             return (ImageFormat)fileFormats[ FilterIndex ]; 215:         } 216:   } 217: } 

The MainFrame class is certainly the largest piece of the application. However, it's important to notice that the vast majority of the code revoles around setting up and managing the user interface such as menus and the File Open dialog. The MainFrame relies on each of the previous developed classes to provide the true functionality of the application so that the MainFrame can handle the tasks associated with user interaction. The vast majority of the code within the MainFrame is acutally created during desgin-time. The only code added was to the event handlers for the various menus. As software projects grow in size and complexity, it is important to divide the responsibility amoung various smaller components as was done within the ImageStudio Demo.

Note

The subject of design patterns is an important area within software development. I suggest Design Patterns: Elements of Object-Oriented Software, by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides.



    .NET Windows Forms Custom Controls
    User Interfaces in VB .NET: Windows Forms and Custom Controls
    ISBN: 1590590449
    EAN: 2147483647
    Year: 2002
    Pages: 74

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net