ImageGear for C and C++ on Windows v19.10 - Updated
Add Image to PDF Document
User Guide > How to Work with... > Formats with Additional Functionality > PDF > How to... > Manage PDF Content > Add Image to PDF Document

Before working with a PDF document, make sure to initialize the PDF component (see Getting Started with PDF).

Refer to the AddNewPageWithImage Sample and the AddWatermarksToPDF Sample for complete sample code that illustrates how to use these capabilities.

You can add images to a PDF document using the PDF editing layer, which is implemented via "PDE" objects (for example, HIG_PDE_CONTENT). This topic walks you through how to...

Prepare the Image

In order to add an image to a PDF page, a PDE version of the image has to be created first, using IG_PDE_image_create. The code snippet below demonstrates how to do this for a 24-bit RGB image, preparing the pixel data, color space, compression, image attributes and transformation matrix. For a more elaborate example with support for other bit depths and additional options, please see the AddNewPageWithImage sample.

The following steps summarize the preparation of the input parameters, and then creating the PDE image accordingly.

  1. Get the pixel depth, assuming 24 bit per pixel.
  2. Get the image dimensions.
  3. Set the pixel access mode to new, so we get RGB values instead of BGR.
  4. Copy the image pixel data into a new buffer, using IG_DIB_raster_size_get to get the memory needed to hold one line of pixels of the original image, and IG_DIB_raster_get to get the actual pixel data line by line.
  5. Create the color space for the PDE image, using IG_PDE_colorspace_create.
  6. Set the compression parameters by means of a filter (AT_PDE_FILTERSPEC) and specifying the values using a PDF dictionary.
  7. Initialize the image attributes (AT_PDE_IMAGEATTRS) for type, width, height and depth.
  8. Initialize the transformation matrix (AT_PDF_FIXEDMATRIX), which can be used to position, scale, rotate, or skew the image on the page (see the PDF Reference for details).
  9. Create the PDE image by calling IG_PDE_image_create with the parameters prepared above.

The following code snippet demonstrates this:

C
Copy Code
void CreatePDEImageFromImageGear(HIG_PDF_DOC pdfDocument, HIGEAR image, HIG_PDE_ELEMENT *pdeImage)
{
    // 1. Assume a 24 bit per pixel image.
    const int bitDepth = 24;
    const int bitsPerComponent = 8;
    const int bytesPerPixel = bitDepth / bitsPerComponent;

    HIGDIBINFO dibInfo = NULL;
    AT_DIMENSION imageWidth = 0;
    AT_DIMENSION imageHeight = 0;
    AT_LMODE pixelAccessMode = 0;

    AT_DIMENSION rasterSize = 0;
    size_t imageSizeInBytes = 0;
    LPAT_PIXEL pixels = NULL;
    LPAT_PIXEL rasterLine = NULL;
    AT_DIMENSION nativeRasterSize = 0;
    LPAT_PIXEL nativeRasterLine = NULL;
    int line = 0;

    HIG_PDE_COLORSPACE colorSpace = 0;
    HIG_PDF_ATOM colorSpaceName = IG_PDF_ATOM_NULL;
    AT_PDE_FILTERARRAY filters;
    AT_PDE_FILTERSPEC compressionSpec;
    HIG_PDF_BASOBJ dictionary = 0;
    HIG_PDF_ATOM key = IG_PDF_ATOM_NULL;
    AT_PDE_IMAGEATTRS pdfImageAttributes;
    AT_PDF_FIXEDMATRIX transformMatrix;

    // 2. Get the image's DIB header.
    IG_image_DIB_info_get(image, &dibInfo);
    imageWidth = IG_DIB_width_get(dibInfo);
    imageHeight = IG_DIB_height_get(dibInfo);

    // 3. Set the pixel access mode to new.
    pixelAccessMode = IG_PIX_ACCESS_MODE_NEW;
    IG_gctrl_item_set("DIB.PIX_ACCESS_USE_LEGACY_MODE", AM_TID_AT_LMODE, &pixelAccessMode,
            sizeof(AT_LMODE), NULL);

    // 4. Get the image pixels.
    rasterSize = (imageWidth * bitDepth + (bitsPerComponent - 1)) / bitsPerComponent;
    imageSizeInBytes = rasterSize * imageHeight;
    pixels = (LPAT_PIXEL)malloc(imageSizeInBytes);

    rasterLine = pixels;
    nativeRasterSize = 0;
    IG_DIB_raster_size_get(image, IG_PIXEL_UNPACKED, &nativeRasterSize);
    nativeRasterLine = (LPAT_PIXEL)malloc((size_t)nativeRasterSize);
    // Retrieve each raster line in its native format.
    for (line = 0; line < imageHeight; line++)
    {
        IG_DIB_raster_get(image, line, nativeRasterLine, IG_PIXEL_UNPACKED);
        memcpy(rasterLine, nativeRasterLine, rasterSize);
        // Go to the next raster line.
        rasterLine += rasterSize;
    }
    free(nativeRasterLine);

    // 5. Create color space.
    IG_PDF_atom_from_string("DeviceRGB", &colorSpaceName);
    IG_PDE_colorspace_create(colorSpaceName, NULL, &colorSpace);

    // Initialize a filter array for the different filter specs.
    memset(&filters, 0, sizeof(filters));

    // 6. Set image compression.
    memset(&compressionSpec, 0, sizeof(AT_PDE_FILTERSPEC));
    IG_PDF_basdict_create(pdfDocument, FALSE, 3, &dictionary);
    IG_PDF_atom_from_string("Columns", &key);
    IG_PDF_basdict_put_int(dictionary, key, FALSE, imageWidth);
    IG_PDF_atom_from_string("Rows", &key);
    IG_PDF_basdict_put_int(dictionary, key, FALSE, imageHeight);
    IG_PDF_atom_from_string("Colors", &key);
    IG_PDF_basdict_put_int(dictionary, key, FALSE, bytesPerPixel);
    IG_PDF_atom_from_string("DCTDecode", &(compressionSpec.name));
    compressionSpec.encodeParms = dictionary;
    compressionSpec.decodeParms = dictionary;

    filters.spec[filters.numFilters] = compressionSpec;
    filters.numFilters++;

    // 7. Initialize image attributes.
    memset(&pdfImageAttributes, 0, sizeof(AT_PDE_IMAGEATTRS));
    // A PDF image is an XObject.
    pdfImageAttributes.flags = IG_PDE_IMAGE_EXTERNAL;
    pdfImageAttributes.width = (AT_INT32)imageWidth;
    pdfImageAttributes.height = (AT_INT32)imageHeight;
    pdfImageAttributes.bitsPerComponent = bitsPerComponent;

    // 8. Initialize transformation matrix.
    memset(&transformMatrix, 0, sizeof(AT_PDF_FIXEDMATRIX));
    transformMatrix.a = AM_PDF_DOUBLE_TO_FIXED(imageWidth);
    transformMatrix.b = IG_PDF_FIXED_ZERO;
    transformMatrix.c = IG_PDF_FIXED_ZERO;
    transformMatrix.d = AM_PDF_DOUBLE_TO_FIXED(imageHeight);
    transformMatrix.h = IG_PDF_FIXED_ZERO;
    transformMatrix.v = IG_PDF_FIXED_ZERO;

    // 9. Create the PDEImage.
    IG_PDE_image_create(&pdfImageAttributes, &transformMatrix, 0, colorSpace, NULL, &filters, NULL,
            pixels, (LONG)(imageSizeInBytes), pdeImage);

    // Release resources.
    IG_PDE_colorspace_release(colorSpace);
    free(pixels);
    IG_DIB_info_delete(dibInfo);
}
C++
Copy Code
void CreatePDEImageFromImageGear(HIG_PDF_DOC pdfDocument, HIGEAR image, HIG_PDE_ELEMENT &pdeImage)
{
    // 1. Assume a standard 24-bit RGB image
    const int bitDepth = 24;
    const int bitsPerComponent = 8;
    const int bytesPerPixel = bitDepth / bitsPerComponent;

    // 2. Get the image's DIB header.
    HIGDIBINFO dibInfo = NULL;
    IG_image_DIB_info_get(image, &dibInfo);
    AT_DIMENSION imageWidth = IG_DIB_width_get(dibInfo);
    AT_DIMENSION imageHeight = IG_DIB_height_get(dibInfo);

    // 3. Set the pixel access mode to new.
    AT_LMODE pixelAccessMode = IG_PIX_ACCESS_MODE_NEW;
    IG_gctrl_item_set("DIB.PIX_ACCESS_USE_LEGACY_MODE", AM_TID_AT_LMODE, &pixelAccessMode,
            sizeof(AT_LMODE), NULL);

    // 4. Get the image pixels.
    AT_DIMENSION rasterSize = (imageWidth * bitDepth + (bitsPerComponent - 1)) / bitsPerComponent;
    AT_DIMENSION imageSizeInBytes = rasterSize * imageHeight;
    LPAT_PIXEL pixels = new AT_PIXEL[imageSizeInBytes];

    LPAT_PIXEL rasterLine = pixels;
    AT_DIMENSION nativeRasterSize = 0;
    IG_DIB_raster_size_get(image, IG_PIXEL_UNPACKED, &nativeRasterSize);
    LPAT_PIXEL nativeRasterLine = new AT_PIXEL[nativeRasterSize];
    // Retrieve each raster line in its native format.
    for (int line = 0; line < imageHeight; line++)
    {
        IG_DIB_raster_get(image, line, nativeRasterLine, IG_PIXEL_UNPACKED);
        memcpy(rasterLine, nativeRasterLine, rasterSize);
        // Go to the next raster line.
        rasterLine += rasterSize;
    }
    delete [] nativeRasterLine;

    // 5. Create color space.
    HIG_PDE_COLORSPACE colorSpace = NULL;
    HIG_PDF_ATOM colorSpaceName = IG_PDF_ATOM_NULL;
    IG_PDF_atom_from_string("DeviceRGB", &colorSpaceName);
    IG_PDE_colorspace_create(colorSpaceName, NULL, &colorSpace);

    // Create a filter array for the different filter specs.
    AT_PDE_FILTERARRAY filters;
    memset(&filters, 0, sizeof(filters));

    // 6. Set image compression.
    AT_PDE_FILTERSPEC compressionSpec;
    HIG_PDF_BASOBJ dictionary = 0;
    HIG_PDF_ATOM key = IG_PDF_ATOM_NULL;
    memset(&compressionSpec, 0, sizeof(AT_PDE_FILTERSPEC));
    IG_PDF_basdict_create(pdfDocument, FALSE, 3, &dictionary);
    IG_PDF_atom_from_string("Columns", &key);
    IG_PDF_basdict_put_int(dictionary, key, FALSE, imageWidth);
    IG_PDF_atom_from_string("Rows", &key);
    IG_PDF_basdict_put_int(dictionary, key, FALSE, imageHeight);
    IG_PDF_atom_from_string("Colors", &key);
    IG_PDF_basdict_put_int(dictionary, key, FALSE, bytesPerPixel);
    IG_PDF_atom_from_string("DCTDecode", &(compressionSpec.name));
    compressionSpec.encodeParms = dictionary;
    compressionSpec.decodeParms = dictionary;

    filters.spec[filters.numFilters] = compressionSpec;
    filters.numFilters++;

    // 7. Initialize image attributes.
    AT_PDE_IMAGEATTRS pdfImageAttributes;
    memset(&pdfImageAttributes, 0, sizeof(AT_PDE_IMAGEATTRS));
    // A PDF image is an XObject.
    pdfImageAttributes.flags = IG_PDE_IMAGE_EXTERNAL;
    pdfImageAttributes.width = (AT_INT32)imageWidth;
    pdfImageAttributes.height = (AT_INT32)imageHeight;
    pdfImageAttributes.bitsPerComponent = bitsPerComponent;

    // 8. Initialize transformation matrix.
    AT_PDF_FIXEDMATRIX transformMatrix;
    memset(&transformMatrix, 0, sizeof(AT_PDF_FIXEDMATRIX));
    transformMatrix.a = AM_PDF_DOUBLE_TO_FIXED(imageWidth);
    transformMatrix.b = IG_PDF_FIXED_ZERO;
    transformMatrix.c = IG_PDF_FIXED_ZERO;
    transformMatrix.d = AM_PDF_DOUBLE_TO_FIXED(imageHeight);
    transformMatrix.h = IG_PDF_FIXED_ZERO;
    transformMatrix.v = IG_PDF_FIXED_ZERO;

    // 9. Create the PDEImage.
    IG_PDE_image_create(&pdfImageAttributes, &transformMatrix, 0, colorSpace, NULL, &filters, NULL,
            pixels, (LONG)(imageSizeInBytes), &pdeImage);

    IG_PDE_colorspace_release(colorSpace);
    IG_DIB_info_delete(dibInfo);
    delete [] pixels;
}

If the image has an alpha channel, a separate 8-bit grayscale image has to be created for it using IG_PDE_image_create, and linked to the PDE image using IG_PDE_image_set_soft_mask. See the AddNewPageWithImage sample for an example of how this can be done.

Add the Image

Now that we have a way to create a PDE image, we can add it to the PDF. The following steps summarize how to gain access to the content of a PDF page and add the newly created PDE image.

  1. Create a multi-page document interface using IG_mpi_create.
  2. Create or open a PDF document interface using IG_PDF_doc_create or IG_mpi_file_open.
  3. Create a new page using IG_PDF_doc_create_new_page, if necessary.
  4. Get a handle to the PDF page using IG_mpi_page_get and IG_vector_data_get.
  5. Get a handle to the content using IG_PDF_page_get_content.
  6. Add the image to the content using IG_PDE_content_add_element.
  7. Set the content back into the page using IG_PDF_page_set_content.
  8. Save the changes using IG_mpi_file_save.

The following code snippet demonstrates this:

C
Copy Code
    HMIGEAR document = 0;
    AT_PDF_FIXEDRECT mediaBox;
    HIGEAR page = 0;
    HIG_PDE_ELEMENT pdeImage = 0;
    HIG_PDF_PAGE pdfPage = 0;
    HIG_PDE_CONTENT hContent = 0;
    HIGEAR image = 0;
    HIG_PDF_DOC pdfDocument = 0;

    // 1. Create a new multi-page image document to hold our PDF document.
    IG_mpi_create(&document, 1);

    // 2. Create an empty PDF document inside the multi-page image document.
    IG_PDF_doc_create(document);

    // 3. Insert a blank US - Letter page (8.5 x 11.0 inches) at 72dpi.
    mediaBox.left = AM_PDF_DOUBLE_TO_FIXED(0.0 * 72);
    mediaBox.right = AM_PDF_DOUBLE_TO_FIXED(8.5 * 72);
    mediaBox.top = AM_PDF_DOUBLE_TO_FIXED(11.0 * 72);
    mediaBox.bottom = AM_PDF_DOUBLE_TO_FIXED(0.0 * 72);
    IG_PDF_doc_create_new_page(document, IG_PDF_BEFORE_FIRST_PAGE, &mediaBox);

    // 4. Get a handle to the PDF page.
    IG_mpi_page_get(document, 0, &page);
    IG_vector_data_get(page, (AT_VOID**)&pdfPage);

    // 5. Get a handle to the content
    IG_PDF_page_get_content(pdfPage, &hContent);

    // 6. Add image to the content
    IG_load_file("example.bmp", &image);
    IG_mpi_info_get(document, IG_MP_DOCUMENT, &pdfDocument, sizeof(pdfDocument));
    CreatePDEImageFromImageGear(pdfDocument, image, &pdeImage);
    IG_PDE_content_add_element(hContent, IG_PDE_AFTER_LAST, pdeImage);

    // 7. Set the content back into the page
    IG_PDF_page_set_content(pdfPage);

    // 8. Save the PDF with the image.
    IG_mpi_file_save("example.pdf", document, (UINT)-1, 0, 1, IG_FORMAT_PDF,
            IG_MPI_SAVE_OVERWRITE);
C++
Copy Code
    // 1. Create a new multi-page image document to hold our PDF document.
    HMIGEAR document = 0;
    IG_mpi_create(&document, 1);

    // 2. Create an empty PDF document inside the multi-page image document.
    IG_PDF_doc_create(document);

    // 3. Insert a blank US - Letter page (8.5 x 11.0 inches) at 72dpi.
    AT_PDF_FIXEDRECT mediaBox = {};
    mediaBox.left = AM_PDF_DOUBLE_TO_FIXED(0.0 * 72);
    mediaBox.right = AM_PDF_DOUBLE_TO_FIXED(8.5 * 72);
    mediaBox.top = AM_PDF_DOUBLE_TO_FIXED(11.0 * 72);
    mediaBox.bottom = AM_PDF_DOUBLE_TO_FIXED(0.0 * 72);
    IG_PDF_doc_create_new_page(document, IG_PDF_BEFORE_FIRST_PAGE, &mediaBox);

    // 4. Get a handle to the PDF page.
    HIGEAR page = 0;
    HIG_PDF_PAGE pdfPage = 0;
    IG_mpi_page_get(document, 0, &page);
    IG_vector_data_get(page, (AT_VOID**)&pdfPage);

    // 5. Get a handle to the content
    HIG_PDE_CONTENT hContent = 0;
    IG_PDF_page_get_content(pdfPage, &hContent);

    // 6. Add image to the content
    HIGEAR image = 0;
    IG_load_file("example.bmp", &image);

    HIG_PDF_DOC pdfDocument = 0;
    IG_mpi_info_get(document, IG_MP_DOCUMENT, &pdfDocument, sizeof(pdfDocument));

    HIG_PDE_ELEMENT pdeImage = 0;
    CreatePDEImageFromImageGear(pdfDocument, image, pdeImage);

    IG_PDE_content_add_element(hContent, IG_PDE_AFTER_LAST, pdeImage);

    // 7. Set the content back into the page
    IG_PDF_page_set_content(pdfPage);

    // 8. Save the PDF with the image.
    IG_mpi_file_save("example.pdf", document, (UINT)-1, 0, 1, IG_FORMAT_PDF,
            IG_MPI_SAVE_OVERWRITE);

See also the section Watermarks and Annotations in a PDF.