Background Color:
 
Background Pattern:
Reset
Search
Home Recent Changes Show All Pages

Image

Not Rated Yet

Scryber supports most common image types - in fact it supports all the image types supported by the Bitmap class in the .NET framework. These images can quickly and easily be used within any pdf template to give your document appeal and interest

 

Contents

Adding an image

 

Images can simply be added using the <pdf:Image /> (PDFImage) component and specifying the source file.

        <pdf:Page id="StandardImages" >
          <Header>Standard images in a document</Header>
          <Content>
            <pdf:Div style:margins="20pt" >
              And this is some text before the image
              <pdf:Image src="../../images/Penguins.jpg" />
              And this is some text after the image
            </pdf:Div>
          </Content>
        </pdf:Page>
           using (PDFDocument doc = new PDFDocument())
            {
                PDFPage pg = new PDFPage();
                doc.Pages.Add(pg);
                pg.Style.Margins.All = 20;

                pg.Contents.Add(new PDFTextLiteral("This is some text before the image"));
                pg.Contents.Add(new PDFImage() { Source = "../../Images/Penguins.jpg" });
                pg.Contents.Add(new PDFTextLiteral("And this is some text after the image"));

                doc.ProcessDocument(path);
            }

 

 

The Penguins.jpg image size is quite large it would extend beyond the width of the page. Because of this Scryber forces the image to fit the available space (the width of the page with the margins). This does not reduce the pixel data of the image or perform any manipulation on the actual image data - it is simply rendered into a box that fits image.

 

Relative and absolute paths

It is important to understand how scryber looks for images with relative paths, and varies on the mechanisms used for document creation.

XML Document Templates

When working with templates that are loaded from a file or remote reference, then the location the template is loaded from becomes the reference path for all inner paths, so relative image source paths are relative to the template where it is declared. This rule follows for inner referenced pages or components - relative to the inner file, not the outer document. For Example...

Document location : C:\PDFs\Templates\MyDocument.pdfx
Image reference in document to:   ../Images/MyImage.png
Mapped path to the image would be: C:\PDFs\Images\MyImage.png

Page is referenced in MyDocument.pdfx at path: ./Parts/MyPage.ppfx
Mapped page path would be : C:\PDFs\Templates\Parts\MyPage.ppfx
Image reference in page to: ../Images/MyImage.png
Mapped path to the image would be: C:\PDFs\Templates\Images\MyImage.png

 

Building from Code

When building a document from code, then there is no known base location to map the path from, so for executables the base path becomes the location the executable is running from and for websites it becomes the location of the currently executing request. For Example...

Executing location: C:\PDFs\Application\MyApp.exe
Image added with source location: ./Images/MyImage.png
Mapped path to the image would be: C:\PDFs\Application\Images\MyImage.png

NOTE: If the code loads a part component or page from a template file, then this will be the new reference path as per XML Document Templates above

 

Web application relative paths

When working in a web application it is possible to specify paths to images rooted to the top level of the site using the tilde symbol (~). This means that wherever the document or part is located the path to the image will always be static to the site. For Example...

Document location : MySite/PDFs/Templates/MyDocument.pdfx
Image reference in document to:   ~/Images/MyImage.png
Mapped path to the image would be: MySite/Images/MyImage.png

Page is referenced in MyDocument.pdfx at path: ./Parts/MyPage.ppfx
Mapped page path would be : C:\PDFs\Templates\Parts\MyPage.ppfx
Image reference in page to: ~/Images/MyImage.png
Mapped path to the image would still be: MySite/Images/MyImage.png

 

Local images and downloaded Images

 

Supported Image Types

PDF files support JEPG streams natively, but all other image types must be extracted, loaded and generated within the PDF as simple image streams that a PDF reader can understand. Scryber supports the loading and reading of most of the common image types available, in most of the image depths. Below is the matrix table for what is supported in .NET and scryber.

 

Portable Network Graphics (PNG)
32 bit ARGB Available now Full Support
24 bit RGB Available now Full Support
8 bit Indexed Available now Supported with alpha (converted to 32bit ARGB)
32 bit CMYK N/A Not supported on the PNG Format
Joint Photographic Experts Group (JPEG)
Format does not support alpha channel or indexed colours
24 bit RGB Available now Full Support
32 bit CMYK Coming Soon Not currently supported as of 0.8.8.5
Graphics Interchange Format (GIF)
8 bit Indexed Available now Full Support
8 bit Indexed with Matte Available now Partial Support for image but Matte colour is not transparent as of 0.8.8.5
Tagged Image Format (TIFF/TIF)
32 bit ARGB Available now Full Support
24 bit RGB Available now Full Support
8 bit Indexed Available now Supported, no Matte transparency as of 0.8.8.5
32 bit CMYK Available now Fully supported
Bitmap (BMP)
24 bit RGB Available now Full Support
8 bit RGB Available now Full Support

 

Sample Image format output

 

Download PDF

 

Image transparency and masks

 

For 32 bit PNG and TIFF images, they are able to carry their own opacity values as part of that image. Scryber converts this to the soft mask associated with the image stream. This allows a dynamic image map of opacity. Content underneath the image will show through based on the opacity values in the image

It is also possible to apply an explicit transparency to the whole image. This is done in the same way as any other component, through the fill-opacity option - with a value from 0 (Zero) to 1 (One) where 0 is completely transparent and 1 is completely opaque

<pdf:Div style:margins="20pt" >
              <pdf:Label style:x="0" style:y="20"  >This is some text under the image</pdf:Label>
              <pdf:Image src="../../images/imagetypes/ColorTest_32bpp.png" style:x="0" style:y="0" />
              <pdf:Label style:x="20" style:y="50"  >And this is some text over the image</pdf:Label>
            </pdf:Div>

            <pdf:Div style:margins="20pt" >
              <pdf:Label style:x="0" style:y="20"  >This is some text under the image</pdf:Label>
              <pdf:Image src="../../images/imagetypes/ColorTest_32bpp.png" style:fill-opacity="0.5" style:x="0" style:y="0" />
              <pdf:Label style:x="20" style:y="50"  >And this is some text over the image</pdf:Label>
            </pdf:Div>
            PDFDiv div1 = new PDFDiv() { Padding = new Drawing.PDFThickness(20)};
            pg.Contents.Add(div1);

            PDFLabel lblunder = new PDFLabel() { X = 0, Y = 20, Text = "This is some text under the image" };
            div1.Contents.Add(lblunder);

            PDFImage img = new PDFImage() { X = 0, Y = 0, Source = "../../imagetypes/ColorTest_32bpp.png" };
            div1.Contents.Add(img);

            PDFLabel lblover = new PDFLabel() { X = 20, Y = 50, Text = "And this is some text over the image" };
            div1.Contents.Add(lblover);

            PDFDiv div2 = new PDFDiv() { Padding = new Drawing.PDFThickness(20) };
            pg.Contents.Add(div2);


            lblunder = new PDFLabel() { X = 0, Y = 20, Text = "This is some text under the image" };
            div2.Contents.Add(lblunder);

            img = new PDFImage() { X = 0, Y = 0, Source = "../../imagetypes/ColorTest_32bpp.png" };
            img.FillOpacity = 0.5;
            div2.Contents.Add(img);

            lblover = new PDFLabel() { X = 20, Y = 50, Text = "And this is some text over the image" };
            div2.Contents.Add(lblover);

 

 

NOTE: The order of the components is important as this resolves the z-index of each component. Later items appear on top of earlier items.

 

Positioning and sizing the image

 

By default images appear on their own line within any block. They are fully styled, so supporting margins; padding; borders; backgrounds; etc. and can appear anywhere within a page content

 This is some text before the image
<pdf:Image src="../../images/imagetypes/ColorTest_32bpp.png"
                style:margins="10pt" style:padding="10pt"
                style:border-color="black" style:border-width="1"
                style:bg-color="#DDDDDD" />
And this is some text after the image 

However it is possible to move images inline with other content by setting their position-mode to Inline (in the same way as other containers - Panel, Div, Para, Pre, Span). Backgrounds, margins, padding and borders will be honoured.

This is some text before the image
<pdf:Image src="../../images/imagetypes/ColorTest_32bpp.png"
            style:margins="2pt" style:padding="2pt"
            style:border-color="black" style:border-width="1"
            style:bg-color="#DDDDDD"
            style:position-mode="Inline" style:width="30pt"/>
And this is some text after the image

Images have a native size that will be honoured if there is no explicit sizing, or they are smaller than the available space within the container they are trying to fit in. If the container is smaller than the image, then the image will be scaled proportionally to fit within the available space. It is also possible to explicitly set the width and height

Setting setting either width OR height will always ensure the image is proportionally scaled, setting width AND height will override any implicit proportions. This can be applied either as a block, or inline.

This is some text before the image
<pdf:Image src="../../images/imagetypes/ColorTest_32bpp.png"
           style:margins="2pt" style:padding="2pt"
           style:border-color="black" style:border-width="1"
           style:bg-color="#DDDDDD"
           style:height="50pt" style:width="90pt"/>
And this is some text after the image

Images can also be used as backgrounds or fills with support for repeats, spacing and sizing. For more information see [[]Repeating Background and Fill images]

 

Adding images more than once

 

When adding images to a PDF document the actual image data is included as binary information within the file itself.

This is one of the key characteristics of PDF's that they are single easily transportable files that do not rely on other files or system resources

This does however mean that if we add 2 images, then they will both be added to the generated file. Add 20 images, then 20 images will be added. This could result in very large file sizes.

But what if 10 of these images were the same? We would only want to include 1 stream of image data, and then reference this in each of the ten places.

One image data, multiple references

Scryber is smart enough to recognise the images that are used based on the path information provided. If all the paths to the images are the same (case-insensitive), then they are treated as the same image and only the first time that image is referenced, will it be loaded and used. This applies to local and remote images, and for remote images - any query string is treated as part of that path

 

Handling missing images

Because the image data is an integral part of the final PDF, it is by default treated as an error if that image cannot be found, loaded, or read. There is no way for scryber to know if this image is vital to the document or not so it must be treated as an error state

However if this is not the desired behaviour then it is possible to not raise an error, and use a fallback image instead

Up to v0.8.5
There is no way to stop the error - all images are always required. But you should have upgraded any way
v0.8.6 - v0.8.8.5
This is a system wide setting in the app or web configuration file - Scryber Configuration
0.8.9
This can be altered as a hierarchy of settings. Global setting in the scryber/imaging section of the configuration file Scryber Configuration. Which can be overridden at the document level in the Render-Options as below. If it is not set at document level, the the value in the config file will be used. If it's not set in the config file the default value of 'False' will be used.
<configuration>
  <configSections>
    <sectionGroup name="scryber">
       <section name="imaging" 
                     type="Scryber.Configuration.ImagingConfigurationSection, Scryber.Drawing, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"/>
    </sectionGroup>
    .
    .
  </configSections>
   .
   .
  <scryber>
    <imaging allow-missing-images="true" ></imaging>
      .
      .
  </scryber>
  .
  .
</configuration>

 

<pdf:Document 
     xmlns:pdf="Scryber.Components, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe" >
     
  <Render-Options compression-type="FlateDecode"
                  allow-missing-images="true" />
  .
  .

 

After the document has been rendered the image that was not found or could not be loaded will be replaced by the placeholder image. It will retain all the properties of the image including any explicit sizes and colours.

<pdf:Image src="../../images/Does_Not_Exist.png"
                   style:margins="2pt" style:padding="2pt"
                   style:border-color="black" style:border-width="1"
                   style:bg-color="#DDDDDD"
                   style:height="150pt" style:width="190pt"/>

Caching the image data

 

Because of the significant computational effort in extracting image data, and building an image stream, scryber will always cache this data once loaded. For executables this is stored as a static cache (and is shared amongst documents), for web applications this is stored in the standard .NET http cache with no expiration.

As of scryber v0.8.9 it is possible to specify an expiration time for images at the configuration or document level (which overrides any setting in the config file).

 

<configuration>
  <configSections>
    <sectionGroup name="scryber">
       <section name="imaging" 
                     type="Scryber.Configuration.ImagingConfigurationSection, Scryber.Drawing, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe"/>
    </sectionGroup>
    .
    .
  </configSections>
   .
   .
  <scryber>
    <imaging cache-duration-mins="10" ></imaging>
      .
      .
  </scryber>
  .
  .
</configuration>

 

<pdf:Document 
     xmlns:pdf="Scryber.Components, Scryber.Components, Version=0.8.0.0, Culture=neutral, PublicKeyToken=872cbeb81db952fe" >
     
  <Render-Options compression-type="FlateDecode"
                  img-cache-mins="20" />
  .
  .

 

Dynamic Images

 

Sometimes the image you want to show is not available on the file system, but is dynamically generated, or loaded from another source. Scryber supports 2 mechanisms for handling this type of image data.

 

Simply setting the data

The simplest way to dynamically set the image data is to get a reference to the component during processing and assign the data

Page Template
<pdf:Page >
    <Content>
        This is some text before the image
        <pdf:Image id="MyDynamicImage" />
        This is some text after the image
    </Content>
</pdf:Page>
Document Processing
using (Scryber.Components.PDFDocument mydoc = Scryber.Components.PDFDocument.ParseDocument(path))
{
    Scryber.Components.PDFImage img = mydoc.FindAComponentById("MyDynamicImage") as Scryber.Components.PDFImage;
    if (null != img)
    {
        Bitmap bmp = GetMyDynamicBitmap();
        string identifer = "An Identifier for the image";
        img.Data = Scryber.Drawing.PDFImageData.LoadImageFromBitmap(identifer, bmp);
    }
    mydoc.ProcessDocument(outputstream);
}

 

Binding to the Items collection

 

As of versions 0.8.9+ it is possible to bind the image data to the document items collection (Item and Query String Binding) with the @img-data attribute. This is much simpler than finding and setting image data via the FindAComponentById process, and also separates the data and presentation more completely.

        <pdf:Image img-data="{item:Logo}" ></pdf:Image>

 

//load your image data from wherever it is located (in this case a local file).
doc.Items["Logo"] = Scryber.Drawing.PDFImageData.LoadImageFromLocalFile("Documents/scryber_logo_380.png");
doc.ProcessDocument(outputfile);

 

Custom Image Factory

 

Setting the image works fine for one or 2 images, but what if you have a lot of images, or have multiple documents with dynamic images? Checking ID's and explicit loading creates a high dependancy on code with the template - reducing flexibility. A more refined and generic mechanism is available using the image factories.

 

Adding the factory to the config file

<imaging allow-missing-images="true" >
    <imageFactory match-path="\.dynamic" factory-type="Scryber.Testing.DynamicImageDataFactory, Scryber.Testing.vs12.Forms" />
</imaging>

 

Implementing the factory

namespace Scryber.Testing
{
    public class DynamicImageDataFactory : Scryber.IPDFImageDataFactory
    {
        // This is the implementation method that will 
        // be called from scryber and is expected to return a full image

        public Drawing.PDFImageData LoadImageData(string path)
        {
            Scryber.Drawing.PDFImageData img;

            using (Bitmap bmp = GetBitmapForPath(path))
            {
                img = Scryber.Drawing.PDFImageData.LoadImageFromBitmap(path, bmp);
            }

            return img;
        }

        private Bitmap GetBitmapForPath(string path)
        {
            string file = System.IO.Path.GetFileName(path);
            Bitmap bmp = new Bitmap(400, 200);

            using (Graphics g = Graphics.FromImage(bmp))
            {
                g.DrawEllipse(new Pen(new SolidBrush(Color.Aquamarine)), 10, 10, 380, 180);
                g.DrawString("This is a dynamic image for path '" + file + "'", 
                            new System.Drawing.Font("Arial",12), 
                            new SolidBrush(Color.Brown), 20, 100, StringFormat.GenericTypographic);
            }
            return bmp;
        }
    }
}

Adding the image to the document template

<pdf:Div style:padding="20pt">
      This is some text before the image
      <pdf:Image src="Generated.dynamic" style:width="200" style:height="100" />
      This is some text after the image
</pdf:Div>

 

With the factory in place in the config file all image sources that end in '.dynamic' will be matched and the registered factory used

We implement the interface on the DynamicImageDataFactory class in our assembly, and scryber will then call the one defined interface method LoadImageData, that is expected to return an instance of PDFImageData. In this case we are creating a new Bitmap, performing some drawing routines and then converting this to a PDFImageData instance

So finally we can add a new image to our template and give it the source that matches our '.dynamic' regular expression. At this point scryber will use the class to generate an image for this instance.

Final Image Output

 

The regular expression for matching the path with a factory can be anything, and once in place is valid for all matching images - a single factory can return various images, and it is entirely down to the implementation as to how these images are loaded

 

See Also



  Rating
Rate This Page: Poor Great   |  Rate Content |
Average rating:  No Ratings Yet   
Number of Ratings : 0
  Comments
Add Comment
lorretadt
c# extract image from pdf file
on this page http://www.rasteredge.com/how-to/csharp-imaging/pdf-image-extract/
Posted At 19-04-2016 16:10:29