Compressed Image

Applies to: Graphics Mill 12.1, 6.x-12.x (may differ)

CompressedImage is an image type that stores raster data in compressed form instead of fully unpacking it into memory.

This feature was introduced primarily to increase the efficiency of getting PDF content in the form of a GraphicsContainer. Previously, images were represented only as Bitmap, which always keeps raster data decompressed in memory. Now both Bitmap and CompressedImage derive from the common base class Image:

  • Image stores common image parameters.
  • Bitmap stores fully decoded pixel data in memory.
  • CompressedImage stores image data as compressed streams.

This approach is especially useful when working with PDF content.

Why use CompressedImage

In most cases, you do not need to create or read CompressedImage objects manually.

The main scenario is PDF processing. When Graphics Mill reads PDF content, it can keep image data as compressed streams whenever possible. These streams remain compressed until you explicitly rasterize them.

This provides two important benefits:

  • Lower memory usage because image data is not decompressed until needed.
  • More efficient PDF round-tripping because image streams can be written back to a PDF without unpacking and recompressing them.

If you save such content back to PDF, the original compressed stream can be reused as-is.

When to create a CompressedImage manually

Manual creation of a CompressedImage is an advanced scenario.

Typically, you only need it when you want more control over how images are compressed in generated PDF files.

CompressedImage exposes two separate streams:

  • ColorStream
  • AlphaStream

This matches the internal representation used by PDF images, where color and alpha data may be stored separately. In general, these streams may even have different dimensions.

However, if you create a CompressedImage manually, the color and alpha parts always correspond to the same image dimensions.

Create a CompressedImage from a pipeline

Use this approach when you want to build a compressed image from an image source and explicitly choose the compression type.

C#
using (var reader = ImageReader.Create(@"Images\in.jpg"))
{
    var pipeline = new Pipeline();
    pipeline.Add(reader);

    using (var compressedImage = CompressedImage.CreateFromPipeline(pipeline, CompressionType.Zip))
    {
        Console.WriteLine("Image width: " + compressedImage.Width);
        Console.WriteLine("Image height: " + compressedImage.Height);
        Console.WriteLine("Compression: " + compressedImage.ColorStream.Compression);
        Console.WriteLine("Stream size: " + compressedImage.ColorStream.Size);
    }
}

Create a CompressedImage from a file

You can also create a compressed image directly from a file:

C#
using (var compressedImage = CompressedImage.CreateFromFile(@"Images\in.jpg", CompressionType.Zip))
{
    Console.WriteLine("Image width: " + compressedImage.Width);
    Console.WriteLine("Image height: " + compressedImage.Height);
    Console.WriteLine("Compression: " + compressedImage.ColorStream.Compression);
    Console.WriteLine("Stream size: " + compressedImage.ColorStream.Size);

    using (var bitmap = compressedImage.GetBitmap())
    {
        bitmap.Transforms.Resize(500, 500, ResizeInterpolationMode.High, ResizeMode.Fit);
        bitmap.Save(@"Images\Output\out.jpg");
    }
}

Keep the encoded data of PNG and JPEG files

Call CompressedImage.CreateFromFile(String) or CompressedImage.CreateFromStream(Stream) without a compression type. If the source is a PNG or JPEG image, the encoded data is kept as is. The image is not decoded and compressed again. The ColorStream.Compression property returns Png or Jpeg.

C#
using (var compressedImage = CompressedImage.CreateFromFile(@"Images\in.jpg"))
{
    // The compression is Jpeg, because the JPEG data of the file is kept as is.
    Console.WriteLine("Compression: " + compressedImage.ColorStream.Compression);
    Console.WriteLine("Stream size: " + compressedImage.ColorStream.Size);
}

When you draw such an image to a PDF document, the data is embedded without recompression. This is fast, and the colors of the image stay unchanged. It works for CMYK JPEG images too.

Other formats are decoded and compressed with Zip. A PNG image with an alpha channel is also decoded, because CompressedImage stores alpha in a separate stream.

The same applies when you read a PDF file. A JPEG image that is stored in the file stays compressed. This includes CMYK JPEG images that Graphics Mill wrote to the file before. If the PDF file has large images, set PdfReader.CompressedImageThreshold to keep the data of the images in temporary files instead of in memory.

CMYK JPEG images and Adobe Illustrator

The PDF writer adds an inverting entry to the Decode parameter of a CMYK JPEG image that you created from a file with the encoded data kept as is. PDF viewers show such an image correctly, and the PDF file is valid. Adobe Illustrator reads the image with inverted colors.

If you need compatibility with Adobe Illustrator, recompress such an image before you draw it. The sample below checks that the image is a CMYK JPEG and creates a new compressed image from it:

C#
using (var pdfWriter = new PdfWriter(@"Images\Output\CmykJpeg.pdf"))
using (var graphics = pdfWriter.GetGraphics())
{
    pdfWriter.AddPage(new PdfPage()
    {
        Width = 595,
        Height = 842
    });

    using (var compressedImage = CompressedImage.CreateFromFile(@"Images\cmyk.jpg"))
    {
        if (compressedImage.ColorStream.Compression == CompressionType.Jpeg &&
            compressedImage.PixelFormat.ColorSpace == ColorSpace.Cmyk)
        {
            // Decode the JPEG and compress it again to get a regular CMYK JPEG stream.
            using (var recompressedImage = CompressedImage.CreateFromPipeline(compressedImage, CompressionType.Jpeg, new JpegSettings()))
            {
                graphics.DrawImage(recompressedImage, 0, 0);
            }
        }
        else
        {
            graphics.DrawImage(compressedImage, 0, 0);
        }
    }
}

What you can do with a CompressedImage

A CompressedImage is intended mainly for inspection and deferred rasterization.

You can:

  • inspect image properties such as width and height;
  • inspect compression settings;
  • check compressed stream sizes;
  • keep image data compressed until rasterization is actually needed.

This can be useful in preflight and optimization scenarios.

Access pixel data

CompressedImage does not provide direct pixel-level editing. If you need to access or modify pixels, convert it to a Bitmap first:

C#
using (var compressedImage = CompressedImage.CreateFromFile(@"Images\in.jpg", CompressionType.Zip))
using (var bitmap = compressedImage.GetBitmap())
{
    bitmap.Transforms.Resize(500, 500, ResizeInterpolationMode.High, ResizeMode.Fit);
    bitmap.Save(@"Images\Output\out.jpg");
}