Difference between revisions of "Images in PDF"

From
Jump to: navigation, search
(Created page with "==Image XObject== Images in PDF are represented by the special type of XObject called ''image XObject''. Like the form XObject this type of XObjects can be us...")
 
Line 37: Line 37:
  
 
[[File:apitron_pdf_kit_images_drawing_standard_image.png|none|frame|Drawing an Image XObject]]
 
[[File:apitron_pdf_kit_images_drawing_standard_image.png|none|frame|Drawing an Image XObject]]
 +
 +
==Masked images==
 +
Normally, in the opaque drawing model images occupy all the pixels below it and erase the existing background if it exists. In [[PDF]] it is possible to mark certain parts of the image with a special mask and therefore allow the existing color information to remain or use the image as a source of mask values. Different existing approaches to masking are described below.
 +
 +
===Stencil masked===
 +
An image itself can be used as a source of mask data marking areas where the current non-stroking color can be painted over and where it’s not allowed. Ideally, to create such mask, this image should be  monochrome, but we can also accept color images converting them to black and white if needed. It creates a binary mask which can be used to paint over.
 +
 +
Consider the code below:
 +
 +
<nowiki>
 +
// create output PDF file
 +
using (FileStream outputStream = new FileStream("xobjects.pdf", FileMode.Create, FileAccess.Write))
 +
{
 +
    // create new PDF document
 +
    using(FixedDocument document = new FixedDocument())
 +
    {
 +
        document.Pages.Add(new Page());
 +
 +
        // create XObject defining a stencil mask
 +
        Image stencilmask = new Image("maskXObject", "stencil_mask.png");
 +
        stencilmask.IsStencilMask = true;
 +
        // register xObject
 +
        document.ResourceManager.RegisterResource(stencilmask);
 +
 +
        // set the non-stroking color
 +
        document.Pages[0].Content.SetDeviceNonStrokingColor(new double[]{0.1,0.5,0.3});
 +
        // draw using current non-stroking color and the mask set
 +
        document.Pages[0].Content.AppendImage("maskXObject", 10, 770, stencilmask.Width,stencilmask.Height);
 +
                                     
 +
        document.Save(outputStream);
 +
    }
 +
}
 +
</nowiki>
 +
 +
Note that the ''Image.IsStencilMask'' property was used to define that the image should be processed as a stencil mask; this code produces the following results:
 +
 +
[[File:apitron_pdf_kit_images_stencil_mask.png|none|frame|Using an image as a stencil mask for drawing]]
 +
 +
===Explicitly masked===
 +
Explicit masking assumes that you would like to draw an image using a custom mask and it combines stencil masking with regular image by setting stencil mask directly to ''[[Images in PDF#Image XObject|image XObject]]''.
 +
 +
Let’s see the code:
 +
 +
<nowiki>
 +
// create output PDF file
 +
using (FileStream outputStream = new FileStream("xobjects.pdf", FileMode.Create, FileAccess.Write))
 +
{
 +
    // create new PDF document
 +
    using(FixedDocument document = new FixedDocument())
 +
    {
 +
        document.Pages.Add(new Page());
 +
 +
        // create XObject defining a mask
 +
        Image stencilmask = new Image("maskXObject", "apitron_mask.png");               
 +
        // register mask xObject
 +
        document.ResourceManager.RegisterResource(stencilmask);               
 +
 +
        // create XObject for the image and assign an explicit mask to it
 +
        Image normalImage = new Image("imageXObject", "apitron.png");
 +
        normalImage.MaskResourceID = "maskXObject";
 +
 +
        // register mask XObject
 +
        document.ResourceManager.RegisterResource(normalImage);
 +
               
 +
        // draw masked image and save file
 +
        document.Pages[0].Content.AppendImage("imageXObject", 10, 770, normalImage.Width, normalImage.Height);
 +
        document.Save(outputStream);
 +
    }
 +
}
 +
</nowiki>
 +
 +
Here we simply create two image objects and assign the first one, representing the explicit mask, to the image we want to be drawn masked using its ''MaskResourceID'' property. Results are as follows, note the “MASK” word cut in the middle of the image:
 +
 +
[[File:apitron_pdf_kit_images_explicit_mask.png|none|frame|Applying an explicit mask to an image]]
 +
 +
===Color key masked===
 +
It’s possible to define a mask for the image using special color that will be used as a source of data defining its shape. One may use ''MaskColorRanges'' property for it.
 +
 +
See the code:
 +
 +
<nowiki>
 +
using (FileStream outputStream = new FileStream("xobjects.pdf", FileMode.Create, FileAccess.Write))
 +
{
 +
    // create new PDF document
 +
    using(FixedDocument document = new FixedDocument())
 +
    {
 +
        document.Pages.Add(new Page());
 +
 +
        // create XObject
 +
        Image normalImage = new Image("myImageXObject", "apitron.png");
 +
        Image maskedImage = new Image("myImageXObjectMasked", "apitron.png");
 +
        // masking colors should be specified in image colorspace and include min and max for each channel
 +
        maskedImage.MaskColorRanges = new double[] {210, 220, 90, 115, 85, 115 };
 +
 +
        // register  XObjects
 +
        document.ResourceManager.RegisterResource(normalImage);
 +
        document.ResourceManager.RegisterResource(maskedImage);
 +
 +
        // append normal and masked images one by one
 +
        document.Pages[0].Content.AppendImage("myImageXObject", 10, 760, normalImage.Width, normalImage.Height);
 +
        document.Pages[0].Content.AppendImage("myImageXObjectMasked", 100, 760, maskedImage.Width, maskedImage.Height);
 +
 +
        // save document
 +
        document.Save(outputStream);
 +
    }
 +
}
 +
</nowiki>
 +
 +
We specify that RGB colors falling in range <span style="color:#d25a55">[(210, 90, 85) , (220,115,115)]</span> should be masked out. The result can be seen on the image below:
 +
 +
[[File:apitron_pdf_kit_images_color_key_mask.png|none|frame|Applying color key mask to an image]]

Revision as of 16:57, 22 February 2018

Image XObject

Images in PDF are represented by the special type of XObject called image XObject. Like the form XObject this type of XObjects can be used to place its content repeatedly when it’s needed, using the single registered instance contained in document's or page's resources.

Image's internal coordinate system in PDF differs from the one defined for drawing paths and other primitives and described in article Graphics System in PDF. It has its Y-axis inverted (and pointing to the bottom), similar to the coordinate system in Windows GDI. It’s important to take this into account for proper positioning of the image using regular drawing commands. We also designed several helper methods taking into account this difference and providing a more convenient way to draw an image.

Standard images in common formats

Apitron PDF Kit supports the following source image formats for creation of image XObjects: BMP, PNG, JPEG, TIFF, JP2. It has a special Image resource class defined in Apitron.PDF.Kit.FixedLayout.Resources.XObjects namespace that can be used to create such XObjects. This class has common properties such as Width, Height, Interpolate etc. accessible for developers. Images and their attributes are discussed in depth in section 8.9 “Images” of the PDF specification.

The code below demonstrates how to use image XObject for drawing images:

// create output PDF file
using (FileStream outputStream = new FileStream("xobjects.pdf", FileMode.Create, FileAccess.Write))
{
    // create new PDF document
    using(FixedDocument document = new FixedDocument())
    {
        document.Pages.Add(new Page());
        // create XObject
        Image xObject = new Image("myImageXObject","apitron.png");            

        // register XObject
        document.ResourceManager.RegisterResource(xObject);

        // append two identical images using image XObject
        document.Pages[0].Content.AppendImage("myImageXObject", 10,760, xObject.Width,xObject.Height);
        document.Pages[0].Content.AppendImage("myImageXObject", 100, 760, xObject.Width, xObject.Height);

        // save document
        document.Save(outputStream);
    }
}
 

The result is shown below; please note that we used a special method AppendImage() which performs all transformations needed to draw an image. Usually, drawing an image requires to set current scale transform because image is considered to be of size 1x1 by default. The invoked member AppendImage() is simply a wrapper that does necessary scaling for us and invokes AppendXObject().

Drawing an Image XObject

Masked images

Normally, in the opaque drawing model images occupy all the pixels below it and erase the existing background if it exists. In PDF it is possible to mark certain parts of the image with a special mask and therefore allow the existing color information to remain or use the image as a source of mask values. Different existing approaches to masking are described below.

Stencil masked

An image itself can be used as a source of mask data marking areas where the current non-stroking color can be painted over and where it’s not allowed. Ideally, to create such mask, this image should be monochrome, but we can also accept color images converting them to black and white if needed. It creates a binary mask which can be used to paint over.

Consider the code below:

// create output PDF file
using (FileStream outputStream = new FileStream("xobjects.pdf", FileMode.Create, FileAccess.Write))
{
    // create new PDF document
    using(FixedDocument document = new FixedDocument())
    {
        document.Pages.Add(new Page());

        // create XObject defining a stencil mask
        Image stencilmask = new Image("maskXObject", "stencil_mask.png");
        stencilmask.IsStencilMask = true;
        // register xObject
        document.ResourceManager.RegisterResource(stencilmask);

        // set the non-stroking color
        document.Pages[0].Content.SetDeviceNonStrokingColor(new double[]{0.1,0.5,0.3});
        // draw using current non-stroking color and the mask set
        document.Pages[0].Content.AppendImage("maskXObject", 10, 770, stencilmask.Width,stencilmask.Height);
                                      
        document.Save(outputStream);
    }
}
 

Note that the Image.IsStencilMask property was used to define that the image should be processed as a stencil mask; this code produces the following results:

Using an image as a stencil mask for drawing

Explicitly masked

Explicit masking assumes that you would like to draw an image using a custom mask and it combines stencil masking with regular image by setting stencil mask directly to image XObject.

Let’s see the code:

// create output PDF file
using (FileStream outputStream = new FileStream("xobjects.pdf", FileMode.Create, FileAccess.Write))
{
    // create new PDF document
    using(FixedDocument document = new FixedDocument())
    {
        document.Pages.Add(new Page());

        // create XObject defining a mask
        Image stencilmask = new Image("maskXObject", "apitron_mask.png");                
        // register mask xObject
        document.ResourceManager.RegisterResource(stencilmask);                

        // create XObject for the image and assign an explicit mask to it
        Image normalImage = new Image("imageXObject", "apitron.png");
        normalImage.MaskResourceID = "maskXObject";

        // register mask XObject
        document.ResourceManager.RegisterResource(normalImage);
                
        // draw masked image and save file
        document.Pages[0].Content.AppendImage("imageXObject", 10, 770, normalImage.Width, normalImage.Height);
        document.Save(outputStream);
    }
}
 

Here we simply create two image objects and assign the first one, representing the explicit mask, to the image we want to be drawn masked using its MaskResourceID property. Results are as follows, note the “MASK” word cut in the middle of the image:

Applying an explicit mask to an image

Color key masked

It’s possible to define a mask for the image using special color that will be used as a source of data defining its shape. One may use MaskColorRanges property for it.

See the code:

using (FileStream outputStream = new FileStream("xobjects.pdf", FileMode.Create, FileAccess.Write))
{
    // create new PDF document
    using(FixedDocument document = new FixedDocument())
    { 
        document.Pages.Add(new Page());

        // create XObject
        Image normalImage = new Image("myImageXObject", "apitron.png");
        Image maskedImage = new Image("myImageXObjectMasked", "apitron.png");
        // masking colors should be specified in image colorspace and include min and max for each channel
        maskedImage.MaskColorRanges = new double[] {210, 220, 90, 115, 85, 115 };

        // register  XObjects
        document.ResourceManager.RegisterResource(normalImage);
        document.ResourceManager.RegisterResource(maskedImage);

        // append normal and masked images one by one
        document.Pages[0].Content.AppendImage("myImageXObject", 10, 760, normalImage.Width, normalImage.Height);
        document.Pages[0].Content.AppendImage("myImageXObjectMasked", 100, 760, maskedImage.Width, maskedImage.Height);

        // save document
        document.Save(outputStream);
    }
} 
 

We specify that RGB colors falling in range [(210, 90, 85) , (220,115,115)] should be masked out. The result can be seen on the image below:

Applying color key mask to an image