Meet us at PRINT 19. Chicago, IL. Oct. 3 - 5.
This documentation is for the old version. Go to the latest Graphics Mill docs

Working with Files

Files is the most common storage for images. All the imaging components can load and save images to files of various formats. Let's examine how to work with files using Graphics Mill for .NET.

The simplest way to load or save image from or to a file is to use Load or Save method of the Bitmap class. Being easy-to-use and convenient they provide not all the features of Graphics Mill for .NET to deal with files. E.g. these methods does not provide multiple frames support, working with EXIF and IPTC metadata, asynchronous work, etc.

More advanced method is to use classes from Aurigma.GraphicsMill.Codecs namespace. They enables you to use all the power of Graphics Mill for .NET when working with files.

Let's examine it more detailed.

Using Methods of Bitmap Class

To load image from file using the Bitmap class, just pass the desired filename into Load method.

Visual Basic
Dim bitmap As New Aurigma.GraphicsMill.Bitmap
bitmap.Load("c:\mountain.jpg")
C#
Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap();
bitmap.Load(@"c:\mountain.jpg");

Alternatively you can use a constructor of the Bitmap class.

Visual Basic
Dim bitmap As New Aurigma.GraphicsMill.Bitmap("c:\mountain.jpg")
C#
Aurigma.GraphicsMill.Bitmap bitmap = new Aurigma.GraphicsMill.Bitmap(@"c:\mountain.jpg");

Saving to file is also easy. Pass target filename into Save method of the Bitmap class. Graphics Mill for .NET will analyze the file extension. If this extension is recognized, image will be saved to appropriate file format. For example, if you specify name output.jpg, image will be saved as JPEG image, but if you change it into output.tif, it will be saved in TIFF format.

Visual Basic
bitmap.Save("c:\result.jpg")
C#
bitmap.Save(@"c:\result.jpg");

Also, if you need to control output image parameters, such as compression type, quality, etc, you can use descendants of class EncoderOptions. However you should remember, that type of encoder options class has higher priority when selecting output file type. For example, if you use filename output.png, but pass GifEncoderOptions class instance as encoder options, the output image will be saved in GIF format rather than PNG.

Here is a code example which saves image into file.

Visual Basic
bitmap.Save("c:\result.jpg", New Aurigma.GraphicsMill.Codecs.JpegEncoderOptions(70, True))
C#
bitmap.Save(@"c:\result.jpg", new Aurigma.GraphicsMill.Codecs.JpegEncoderOptions(70, true));

Aurigma.GraphicsMill.Codecs Namespace

Graphics Mill for .NET provides more functionality to work with files than just Bitmap.Load and Bitmap.Save methods. The main limitation of these methods is that they cannot work with files that have more than one image (frame) inside. An examples of such files are multipage TIFF files (typically faxes or other documents), animated GIF files, etc. Load (and Save) always read (or write) only the first frame.

Also, these methods allow extracting only image data. Such information as EXIF and IPTC details cannot be read with Load method. Working with metadata is out of scope of this article, you can get more details at the separate topic.

And at last, these methods can be run in synchronous mode only. You cannot use Graphics Mill for .NET asynchronous features with them.

Alternative way is to use special classes from Aurigma.GraphicsMill.Codecs namespace - format readers and writers. They enables you using all features described above. Load and Save method of the Bitmap class actually use these classes inside.

Let's examine how to work with readers and writers.

Using Format Readers

To read data from file,Graphics Mill for .NET provides a number of classes called format readers. Each supported file type is presented by appropriate reader class, for example JpegReader, TiffReader, etc. All these classes implement IFormatReader interface and derived from FormatReader class.

To load image from file (i.e. get Bitmap class instance which contains this image), you should do the following:

  1. Get an instance of reader of necessary format (e.g. if you load JPEG file, you should get an instance of JpegReader).
  2. Call method Open to "link" this file with the reader.
  3. Call method LoadFrame(Int32) which will return a Frame object. Here you can pass a number of the frame you request. To get total number of frames stored in the file, you can use FrameCount property of the reader.
  4. Call method GetBitmap(Bitmap) to get the bitmap we want to get. You can also get frame thumbnail and some additional details like width, height, etc.
  5. Call Close() method to release the file you are reading from. If you dispose the object, reader is automatically closed though. However it is highly recommended to close the reader as soon as possible.

You can obtain a reader instance in two ways. First of all, you can merely create it using constructor as well as any other .NET class. However if you do not know what file format you are loading, it is extremely inconvenient. That's why we provided an alternative: CreateFormatReader static method of the FormatManager class. It works as a class factory - you feed it a filename, and it returns a reader class of necessary type. This reader is already opened on this file, so you need not execute step 2 in this case.

You may wonder why to get Frame object instead of receiving Bitmap directly. In fact, Frame allows extracting additional data without having to load entire bitmap into memory. Reader starts loading image as soon as you call GetBitmap(Bitmap) (not during LoadFrame(Int32)). This way you can read, for example, width and height of the image in extremely fast manner.

It is a time to see a code example. This code snippet demonstrates how to split multipage TIFF file into separate JPEG files:

Visual Basic
Dim filename As String = "c:\multipage.tif"

Dim reader As Aurigma.GraphicsMill.Codecs.FormatReader = _
 Aurigma.GraphicsMill.Codecs.FormatManager.CreateFormatReader(filename)

Dim bitmap As New Aurigma.GraphicsMill.Bitmap

For i As Integer = 0 To reader.FrameCount - 1
    Dim frame As Aurigma.GraphicsMill.Codecs.Frame = reader.LoadFrame(i)
    frame.GetBitmap(bitmap)
    frame.Dispose()

    bitmap.Save("c:\frame_" & i & ".jpg")
Next

bitmap.Dispose()

reader.Dispose()
C#
string filename = @"c:\multipage.tif";

using (Aurigma.GraphicsMill.Codecs.IFormatReader reader =
           Aurigma.GraphicsMill.Codecs.FormatManager.CreateFormatReader(filename))
{

    using (Aurigma.GraphicsMill.Bitmap bitmap =
               new Aurigma.GraphicsMill.Bitmap())
    {
        for (int i = 0; i < reader.FrameCount - 1; i++)
        {
            using (Aurigma.GraphicsMill.Codecs.IFrame frame =
                       reader.LoadFrame(i))
            {
                frame.GetBitmap(bitmap);
                bitmap.Save(@"c:\frame_" + i.ToString() + ".jpg");
            }
        }
    }
}

Using Format Writers

To write data into files, Graphics Mill for .NET has a set of classes called format writers. As in case of readers, each format supported for writing is presented by writer class, e.g. JpegWriter, GifWriter, etc. All writers implement IFormatWriter interface and have base class FormatWriter.

Writing files with format writer consists of the following steps:

  1. Create a proper instance of format writer (e.g. for writing TIFF files it should be a TiffWriter class instance). Similar to reader, you can not only create this class directly, but also use FormatManager class to construct proper format writer (using CreateFormatWriter static method).
  2. Open method if writer was created directly through constructor.
  3. Create an instance of the Frame object or get it from reader. For example, you can get frames from GifReader and feed them to, e.g. TiffWriter.
  4. Pass this frame into AddFrame(IFrame) method.
  5. If you need to write several frames, repeat the steps 3 and 4 as many times as necessary.
  6. Call Close() method to flush all unsaved changes and release the file you are writing to. If you dispose the object, reader is automatically closed though. However it is highly recommended to close the writer as soon as possible.

Here is a code example which creates animated GIF file:

Visual Basic
Dim dir As String = "C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\"
Dim images As String() = {"Blue hills.jpg", "Sunset.jpg", "Water lilies.jpg", "Winter.jpg"}
Dim image As String

Dim bitmap As New Aurigma.GraphicsMill.Bitmap

Dim writer As New Aurigma.GraphicsMill.Codecs.GifWriter("C:\Slideshow.gif")

For Each image In images
    bitmap.Load(dir & image)

    bitmap.ColorManagement.PaletteEntryCount = 32
    bitmap.ColorManagement.ConvertToIndexed(8, Aurigma.GraphicsMill.ColorPaletteType.Adaptive, _
        Nothing)

    Dim frame As New Aurigma.GraphicsMill.Codecs.GifFrame
    frame.Delay = 100
    frame.SetBitmap(bitmap)

    writer.AddFrame(frame)

    frame.Dispose()
Next

bitmap.Dispose()

writer.Dispose()
C#
string dir = @"C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures";
string[] images = {"Blue hills.jpg", "Sunset.jpg", "Water lilies.jpg", "Winter.jpg"};

using (Aurigma.GraphicsMill.Bitmap bitmap = 
           new Aurigma.GraphicsMill.Bitmap())
{
    using (Aurigma.GraphicsMill.Codecs.GifWriter writer = 
               new Aurigma.GraphicsMill.Codecs.GifWriter(@"C:\Slideshow.gif"))
    {
        foreach (string image in images)
        {
            bitmap.Load(dir + image);

            bitmap.ColorManagement.PaletteEntryCount = 32;
            bitmap.ColorManagement.ConvertToIndexed(8, 
                Aurigma.GraphicsMill.ColorPaletteType.Adaptive, null);
            
            using(Aurigma.GraphicsMill.Codecs.GifFrame frame = 
                      new Aurigma.GraphicsMill.Codecs.GifFrame())
            {
                frame.Delay = 100;
                frame.SetBitmap(bitmap);            
                writer.AddFrame(frame);
            }
        }
    }
}

Getting Thumbnails

If you need display a thumbnail for an image file, there is better way than loading the image and applying Resize transform after that. You can read thumbnail "on-the-fly". It means that resizing will be applied directly during image decoding. This way we noticeable reduce memory overhead and increase the performance, especially for large images.

Both Bitmap class and format readers allow extracting thumbnails in such fast way.

To get a thumbnail through Bitmap class just call LoadThumbnail method instead of Load. In addition to the filename or stream, you should pass desired dimensions of the thumbnail. Note, the thumbnail preserves aspect ratio of the original image, so its actual dimensions may be smaller than specified. In other word, the arguments you pass into this method specify the rectangle to fit the thumbnail in. The code below demonstrates how to use it.

Visual Basic
'Resize image proportionally to width not larger then 100
bitmap.LoadThumbnail("c:\Mountain.jpg", 100, 0)

'Resize image proportionally to height not larger then 100
'bitmap.LoadThumbnail("c:\Mountain.jpg", 0, 100)

'Resize image proportionally to fit in rectangle 100x100
'bitmap.LoadThumbnail("c:\Mountain.jpg", 100, 100)
C#
//Resize image proportionally to width not larger then 100
bitmap.LoadThumbnail(@"c:\Mountain.jpg", 100, 0);

//Resize image proportionally to height not larger then 100
//bitmap.LoadThumbnail(@"c:\Mountain.jpg", 0, 100);

//Resize image proportionally to fit in rectangle 100x100
//bitmap.LoadThumbnail(@"c:\Mountain.jpg", 100, 100);

To load thumbnails through the readers, you should use method GetThumbnail(Bitmap, Int32, Int32) of the Frame (instead of GetBitmap(Bitmap)). It works in the same way as LoadThumbnail method of the Bitmap class (and actually used inside of this method).

Visual Basic
Dim filename As String = "c:\mountain.jpg"

Dim thumbnail As New Aurigma.GraphicsMill.Bitmap

' Create appropriate format reader. 
Dim reader As Aurigma.GraphicsMill.Codecs.FormatReader = _
 Aurigma.GraphicsMill.Codecs.FormatManager.CreateFormatReader(filename)

' LoadFrame returns a frame object. From this frame we can get a thumbnail.
Dim frame As Aurigma.GraphicsMill.Codecs.Frame = reader.LoadFrame(0)

frame.GetThumbnail(thumbnail, 120, 120)

frame.Dispose()

reader.Dispose()
C#
string filename = @"c:\mountain.jpg";

Aurigma.GraphicsMill.Bitmap thumbnail = new Aurigma.GraphicsMill.Bitmap();

// Create appropriate format reader. 
using (Aurigma.GraphicsMill.Codecs.IFormatReader reader =
           Aurigma.GraphicsMill.Codecs.FormatManager.CreateFormatReader(filename))
{
    // LoadFrame returns a frame object. From this frame we can get a bitmap.
    using (Aurigma.GraphicsMill.Codecs.IFrame frame = reader.LoadFrame(0))
    {
        frame.GetThumbnail(thumbnail, 120, 120);
    }
}

If you work with digital photos or other kind of images that store EXIF information, you can use even more fast way for getting thumbnails - extracting pre-created thumbnails from EXIF. This is out of the scope of this topic, read article Loading Thumbnails from EXIF Metadata for more details.

Loading and Saving Embedded ICC profiles

With Graphics Mill for .NET you need not do additional steps to load or save embedded color management profiles. If file contains the profile, and you load this file, you can get access to this profile through ColorProfile property of the Bitmap class. When you save this bitmap to the format that supports color profiles, embedded profile will be saved. You can change this profile, or even detach it (by setting null into this property).

Note, when you modify ColorProfile property, pixels are not changed to fit new color profile. To do it, you should use properties and methods exposed by ColorManagement property of the Bitmap class. You can read more detailed about color management in the article Using Color Management in Graphics Mill for .NET.