Upgrading from Graphics Mill 5

Major API changes have occurred in Graphics Mill 6. The later versions are backward compatible. This topic highlights the changes and illustrates how to migrate an application to a new version of the product.

In addition to a traditional image processing approach, Graphics Mill 6 introduced a memory-friendly approach called pipelines. They allow for reading and writing image files and processing them without the necessity of loading a whole bitmap into memory. Pipelines are preferable for large images and complex imaging tasks.

C#
using (var reader = new JpegReader(@"Images\in.jpg"))
using (var resize = new Resize(2048, 0, ResizeInterpolationMode.High))
using (var writer = new JpegWriter(@"Images\Output\out.jpg"))
{
    Pipeline.Run(reader + resize + writer);
}

See the Understanding Image Processing Approaches in Graphics Mill topic for a detailed description of the differences between a bitmap and pipeline.

Working with Bitmaps

The Bitmap class has been significantly simplified in the new version of Graphics Mill. It no longer supports the undo/redo functionality and it implements no events.

All properties for retrieving information about an image's pixel format are moved to the PixelFormat class:

C#
using (var bitmap = new Bitmap(@"Images\in.jpg"))
{
    Console.WriteLine("Bitmap: " + bitmap.Width + "x" + bitmap.Height);
    Console.WriteLine("  Has Aplha: " + bitmap.HasAlpha);
    Console.WriteLine("  PixelFormat: " + bitmap.PixelFormat.ToString());
    Console.WriteLine("  CMYK: " + bitmap.PixelFormat.IsCmyk);
}

The built-in units conversion (available through the Bitmap.Units property) has been removed, too. Therefore, the image size and coordinates are now always measured in pixels, and the resolution in DPI. However, if you need to convert pixels to device-independent units or vice versa, you can use a utility class UnitConverter. This class doesn't affect image data or attributes, it just converts spatial parameters to different units.

C#
using (var bitmap = new Bitmap(@"Images\in.jpg"))
{
    float width = UnitConverter.ConvertPixelsToUnits(bitmap.DpiX, bitmap.Width, Unit.Inch);
    float height = UnitConverter.ConvertPixelsToUnits(bitmap.DpiY, bitmap.Height, Unit.Inch);

    Console.WriteLine(width + "x" + height);
}

The following table contains the most noticeable API changes in the Bitmap class.

Bitmap.HorizontalResolution, Bitmap.VerticalResolution Renamed to DpiX and DpiY.
Bitmap.IsCmyk, Bitmap.IsGrayScale, Bitmap.IsRgb, Bitmap.IsIndexed, Bitmap.IsExtended Removed. Use PixelFormat.IsCmyk, PixelFormat.IsGrayscale, PixelFormat.IsRgb, PixelFormat.IsIndexed, PixelFormat.IsExtended instead.
Bitmap.BitsPerPixel Removed. Use PixelFormat.Size instead.

Loading and Saving Images

Using the Bitmap Class

To load an image using the Bitmap class, use constructors. Note, the Bitmap.Load and Bitmap.LoadThumbnail methods have been eliminated. To save the Bitmap, use the Save methods. To pass output parameters (compression type, quality, etc.) use an appropriate WriterSettings class descendant. For example, use the JpegSettings for saving JPEG files, PngSettings - for PNG, etc.

C#
using (var bitmap = new Bitmap(@"Images\in.jpg"))
{
    bitmap.Save(@"Images\Output\out.jpg", new JpegSettings(70));
}

Using Image Readers and Writers

Image readers and writers offer memory-friendly image processing, multiframe image support, and access to metadata. In the new Graphics Mill version, they are used within the pipeline image processing approach; see the Processing Large Images section for details.

To read multipage image files (GIF, TIFF, etc.) frame by frame, use the ImageReader.Frames property. To retrieve a bitmap from a frame, use the Frame.GetBitmap() method.

C#
using (var reader = new GifReader(@"Images\slideshow.gif"))
{
    for (int i = 0; i < reader.Frames.Count; i++)
    {
        reader.Frames[i].GetBitmap().Save(@"Images\Output\GIF_frame_" + i.ToString() + ".png");
    }
}

To construct a multipage image from separate bitmaps, use the following code:

C#
using (var writer = new GifWriter(@"Images\Output\slideshow.gif"))
{
    writer.FrameOptions.Delay = 100;

    for (int i = 0; i < 4; i++)
    {
        using (var bitmap = new Bitmap(@"Images\GIF_frame_" + i.ToString() + ".png"))
        {
            Pipeline.Run(bitmap + writer);
        }
    }
}

Reading and Writing Metadata

To read metadata from images, use the Exif, Iptc, AdobeResources, and Xmp properties of the ImageReader class.

C#
using (var jpegReader = new JpegReader(@"Images\in.jpg"))
{
    var exif = jpegReader.Exif;
    if (exif != null)
    {
        Console.WriteLine("EXIF");
        foreach (object key in exif.Keys)
        {
            Console.WriteLine("{0}: {1}, {2}", exif.GetKeyDescription(key), exif[key], exif.GetItemString(key));
        }
    }

    var iptc = jpegReader.Iptc;
    if (iptc != null)
    {
        Console.WriteLine("IPTC");
        foreach (long key in iptc.Keys)
        {
            Console.WriteLine("{0}: {1}, {2}", iptc.GetKeyDescription(key), iptc[key], iptc.GetItemString(key));
        }
    }
}

To write metadata to image files, you can use both image writers and the Bitmap.Save method. Image writers supporting metadata expose Exif, Iptc, AdobeResources, and Xmp properties.

C#
using (var jpegReader = new JpegReader(@"Images\in.jpg"))
using (var jpegWriter = new JpegWriter(@"Images\out.jpg"))
{
    var exif = new ExifDictionary();
    exif[ExifDictionary.Software] = "Aurigma Graphics Mill";
    jpegWriter.Exif = exif;

    var iptc = new IptcDictionary();
    iptc[IptcDictionary.Keyword] = "mountain";
    iptc[IptcDictionary.City] = "Olympia";
    jpegWriter.Iptc = iptc;

    Pipeline.Run(jpegReader + jpegWriter);
}

To write metadata to image files via the Bitmap.Save method, use the self-named properties of the JpegSettings and TiffSettings classes. You should create an instance of the corresponding class, initialize its properties with references to metadata, and pass it to the Save method.

C#
using (var bitmap = new Bitmap(@"Images\in.jpg"))
{
    var settings = new JpegSettings(70);

    var exif = new ExifDictionary();
    exif[ExifDictionary.Software] = "Aurigma Graphics Mill";
    settings.Exif = exif;

    var iptc = new IptcDictionary();
    iptc[IptcDictionary.Keyword] = "mountain";
    iptc[IptcDictionary.City] = "Olympia";
    settings.Iptc = iptc;

    bitmap.Save(@"Images\out.jpg", settings);
}

Codecs API Changes

The following table contains the most noticeable API changes in the Aurigma.GraphicsMill.Codecs namespace.

FormatReader/FormatWriter Renamed to ImageReader/ImageWriter.
XXXEncoderOptions Renamed to XXXSettings.
AdvancedPsdXXX and PsdXXX Merged and moved to Aurigma.GraphicsMill.Codecs.Psd namespace.
AviXXX , DSXXX , Jpeg2kXXX , PcxXXX , QTXXX , SwfXXX , WbmpXXX , WMXXX Removed.

See the Working with Image Formats and Working with Metadata nodes for details.

Transforming Images

Image transformation operations in Graphics Mill can be performed in two ways: in-place and out-of-place. The main difference is that in-place operations change the source bitmap, while out-of-place operations create a new one. To apply an in-place transformation, use the Bitmap.Transforms and Bitmap.ColorAdjustment properties:

C#
using (var bitmap = new Bitmap(@"Images\in.jpg"))
{
    bitmap.Transforms.Crop(50, 60, 50, 100);
    bitmap.Save(@"Images\Output\out.jpg");
}

To apply an out-of-place transformation, use classes from the Aurigma.GraphicsMill.Transforms namespace:

C#
using (var bitmap = new Bitmap(@"Images\in.jpg"))
{
    var cropRectangle = new System.Drawing.Rectangle(50, 60, 50, 100);

    using (var crop = new Crop(cropRectangle))
    {
        using (var result = crop.Apply(bitmap))
        {
            result.Save(@"Images\Output\out.jpg");
        }
    }
}

The following table lists API changes in the Aurigma.GraphicsMill.Transforms namespace.

ApplyLut Renamed to LutTransform.
RotateAndFlip Split into Rotate and Flip.
InterpolationMode Split into InterpolationMode and ResizeInterpolationMode.
Curves, Glow, PageCurl, SwapChannels, Swirl, Waddle, WaterDrop, Wave Removed.

See the Transforming Images (Resize, Rotate, Crop) and Artistic Effects nodes for details.

Converting Colors

Color conversion, as one of image transformations, can be performed both in-place (changing a source image) and out-of-place (creating a new image). To apply an in-place color conversion, use the Bitmap.ColorManagement property:

C#
using (var bitmap = new Bitmap(@"Images\cmyk.jpg"))
{
    bitmap.ColorManagement.ColorManagementEngine = ColorManagementEngine.LittleCms;
    bitmap.ColorManagement.DestinationProfile = ColorProfile.FromSrgb();
    bitmap.ColorManagement.Convert(ColorSpace.Rgb, bitmap.HasAlpha, bitmap.PixelFormat.IsExtended);
    bitmap.Save(@"Images\Output\out.jpg");
}

To apply an out-of-place conversion, use the ColorConverter class:

C#
using (var bitmap = new Bitmap(@"Images\cmyk.jpg"))
using (var cc = new ColorConverter(PixelFormat.Format24bppRgb))
{
    using (var result = cc.Apply(bitmap))
    {
        result.Save(@"Images\Output\out.jpg");
    }
}

Note that properties for specifying destination profiles (CmykColorProfile, RgbColorProfile, and GrayScaleColorProfile) have been replaced by ColorConverter.DestinationProfile and ColorManagementProvider.DestinationProfile.

To set a source color profile in the case of in-place conversion, use the Bitmap.ColorProfile property. For out-of-place conversion, you can set a default source profile (ColorConverter.DefaultSourceProfile), which will be used only if the image has no embedded color profile.

C#
using (var bitmap = new Bitmap(@"Images\cmyk.jpg"))
using (var cc = new ColorConverter(PixelFormat.Format24bppRgb))
{
    cc.DefaultSourceProfile = ColorProfile.FromSrgb();
    using (var result = cc.Apply(bitmap))
    {
        result.Save(@"Images\Output\out.jpg");
    }
}

Image Quantization

To convert a bitmap to an indexed pixel format, set the DestinationPixelFormat to XXXIndexed value. In this case, an appropriate color palette will be automatically created:

Adaptive palettes are more suitable for quantization of real life images because they are created directly from the original image by picking the most frequent colors. Therefore, using the adaptive palette and dithering produces an indexed image which can nearly match the original.

To specify dithering parameters, use the Dithering and DitheringIntensity properties.

C#
using (var bitmap = new Bitmap(@"Images\in.jpg"))
{
    bitmap.ColorManagement.Dithering = DitheringType.FloydSteinberg;
    bitmap.ColorManagement.DitheringIntensity = 1;

    bitmap.ColorManagement.Convert(PixelFormat.Format8bppIndexed);
    bitmap.Save(@"Images\Output\out.png");
}

If you need to use another predefined or custom color palette, then you should specify it via the Palette property.

C#
using (var bitmap = new Bitmap(@"Images\in.jpg"))
{
    bitmap.ColorManagement.Palette = new ColorPalette(ColorPaletteType.Windows);
    bitmap.ColorManagement.Convert(PixelFormat.Format8bppIndexed);
    bitmap.Save(@"Images\Output\out.png");
}

Color Conversion API Changes

The table below shows changes in the color conversion API.

PixelFormatConverter Renamed to ColorConverter.
CmykColorProfile, RgbColorProfile, and GrayScaleColorProfile Renamed to ColorConverter.DestinationProfile and ColorManagementProvider.DestinationProfile.
TargetColorProfile Renamed to ColorConverter.TargetDeviceProfile and ColorManagementProvider.TargetDeviceProfile.
CustomPalette Renamed to ColorConverter.Palette and ColorManagementProvider.Palette.
PaletteAlphaTheshold Renamed to ColorConverter.TransparentIndexThreshold and ColorManagementProvider.TransparentIndexThreshold.
BackgroundEnabled, BuildAdaptivePaletteWithAlpha, PaletteAlphaThesholdUsed, PaletteEntryCount, PaletteType Removed.
ColorQuantizationAlgorithm, QuantizationTo8bBitsUsed, QuantizationTo8bOffset, QuantizationTo8bScale Removed.

See the Color Management and Color Reduction section for details.

Drawing on Images

To draw geometric primitives, vector text, or raster data on an image surface, use the Graphics class:

C#
using (var bitmap = new Bitmap(@"Images\in.jpg"))
using (var watermark = new Bitmap(@"Images\watermark.png"))
{
    //Watermark image.
    using (var graphics = bitmap.GetAdvancedGraphics())
    {
        //Draw the semitransparent watermark.
        graphics.DrawImage(watermark, 10, bitmap.Height - watermark.Height - 40, 0.8f);
        //Save the resulting image.
        bitmap.Save(@"Images\Output\out.jpg");
    }
}

The table below lists the most significant API changes related to drawing functionality.

GdiGraphics Renamed to Graphics.
Bitmap.GetGdiGraphics Renamed to Bitmap.GetAdvancedGraphics().
Bitmap.Draw Renamed to Bitmap.DrawOn.

See the Drawing Text and Graphics section for details.

See Also

Manual