14.8.1 Feature Overview
As of Version 3.6, AspPDF is capable of replacing images in an existing PDF documents with other images or graphics. This feature is useful, among other things,
for reducing the overall size of a PDF document by replacing its high-resolution images with their lower-resolution versions.
The image replacement feature is built on top of the document stitching functionality described in Section 12.2.
Consider the following code:
Set Doc2 = PDF.OpenDocument(path)
Set Doc1 = PDF.CreateDocument
Doc1.AppendDocument Doc2
Doc1.Save path2
This code creates an empty new document, Doc1, and appends Doc2 to it, thus creating a document almost completely identical to Doc2.
All items comprising Doc2 are copied to Doc1 during the appending operation, including images.
If a certain image in Doc2 needs to be replaced with another image, the new image needs to be opened via the Doc1 object's OpenImage method,
and a mapping between the new and old images needs to be added
with the method AddImageReplacement (introduced in Version 3.6):
Set Doc2 = PDF.OpenDocument( path1 )
Set Doc1 = PDF.CreateDocument
Set Image = Doc1.OpenImage( imagePath );
Doc1.AddImageReplacement imageID, Image
Doc1.AppendDocument Doc2
Doc1.Save path2
This code copies all items from Doc2 to Doc1 except the image item specified by imageID. That item is not copied and the Image object is used in its place.
The 1st argument to the AddImageReplacement method specifies the internal ID of the image item to be replaced within Doc2, and the 2nd argument is an instance of the PdfImage object
to replace it with. The 2nd argument can also be an instance of the PdfGraphics object if the image needs to be replaced with a graphics as opposed to another image.
The method AddImageReplacement can be called multiple times if multiple images need to be replaced.
An image ID is a string containing two numbers separated by an underscore, such as "123_0". The 2nd number is usually 0.
Image IDs can be obtained via the Log property of the object representing an extracted image, or via the PdfPreview.ImageItems collection, as described below.
14.8.2 Combining Image Extraction and Image Replacement
The following code sample replaces all images in a PDF document with their resized versions. Image resizing is performed with the help of AspJpeg, another Persits component
which can be downloaded from www.aspjpeg.com.
First, the code sample extracts all images from the document using the procedure described in Section 14.5 earlier in this chapter.
The extracted images are then resized by 50%. Their names and image IDs are recorded in arrays. The image ID of an extracted image is returned by the Log property of the
PdfPreview representing this extracted image.
Lastly, the AddImageReplacement method is called for every resized image in the array, followed by a call to AppendDocument and Save to complete the image replacement operation.
VBScript |
' Arrays to store image IDs and filenames
Dim ImageIDs(100)
Dim Filenames(100)
' Use AspJpeg (www.aspjpeg.com) to resize images
Set Jpeg = Server.CreateObject("Persits.Jpeg")
Set Pdf = Server.CreateObject("Persits.Pdf")
Set OriginalDoc = PDF.OpenDocument( Server.MapPath("twoimages.pdf") )
' Extract all images, resize, build a list of names and image IDs
Set Page = OriginalDoc.Pages(1)
Set Preview = Page.ToImage
i = 1
Do While True
Set Image = Preview.ExtractImage(i)
If Image Is Nothing Then
Exit Do
Else
Jpeg.OpenBinary( Image.SaveToMemory )
Jpeg.PreserveAspectRatio = True
Jpeg.Width = Jpeg.OriginalWidth / 2 ' resize by 50%
ImageIDs(i-1) = Image.Log ' Log property returns Image ID
Filenames(i-1) = Jpeg.SaveUnique( Server.MapPath("extracted_image.jpg") )
End If
i = i + 1
Loop
' Now perform image replacement
Set NewDoc = PDF.CreateDocument
For n = 0 To i - 2
Set ExtractedImage = NewDoc.OpenImage( Server.MapPath( Filenames(n) ) )
NewDoc.AddImageReplacement ImageIDs(n), ExtractedImage
Next
NewDoc.AppendDocument OriginalDoc
Filename = NewDoc.Save( Server.MapPath("imagereplacement.pdf"), False )
|
C# |
// Arrays to store image IDs and filenames
string [] ImageIDs = new string[100];
string [] Filenames = new string[100];
// Use AspJpeg (www.aspjpeg.com) to resize images
ASPJpeg objJpeg = new ASPJpeg();
IPdfManager objPDF = new PdfManager();
IPdfDocument objOriginalDoc = objPDF.OpenDocument( Server.MapPath("twoimages.pdf") );
// Extract all images, resize, build a list of names and image IDs
IPdfPage objPage = objOriginalDoc.Pages[1];
IPdfPreview objPreview = objPage.ToImage();
IPdfPreview objImage;
int i = 1;
while( ( objImage = objPreview.ExtractImage(i++) ) != null )
{
objJpeg.OpenBinary( objImage.SaveToMemory() );
objJpeg.PreserveAspectRatio = 1;
objJpeg.Width = objJpeg.OriginalWidth / 2; // resize by 50%
ImageIDs[i-2] = objImage.Log; // Log property returns Image ID
Filenames[i-2] = objJpeg.SaveUnique( Server.MapPath("extracted_image.jpg") );
}
// Now perform image replacement
IPdfDocument objNewDoc = objPDF.CreateDocument( Missing.Value );
for( int n = 0; n < i - 2; n++ )
{
IPdfImage objExtractedImage = objNewDoc.OpenImage(Server.MapPath(Filenames[n]));
objNewDoc.AddImageReplacement( ImageIDs[n], objExtractedImage );
}
objNewDoc.AppendDocument( objOriginalDoc );
string strFilename = objNewDoc.Save(Server.MapPath("imagereplacement.pdf"), false);
|
Click on the links below to run this code sample:
http://localhost/asppdf/manual_14/14_imagereplacement.asp
http://localhost/asppdf/manual_14/14_imagereplacement.aspx
This code sample reduces the size of the PDF document twoimages.pdf (included in the installation) from 117 KB to 30 KB.
14.8.3 Obtaining Image Information
In addition to the AddImageReplacement method, AspPDF 3.6 also offers a way to obtain a list of images in a PDF document, including information about each image's pixel size, displacement,
scaling, rotation, image ID and coordinate transformation matrix, without actually performing image extraction. This information is obtained via the PdfPreview object's
ImageItems property which returns a collection of PdfRect objects, each representing an image within the PDF document. This collection is similar to that returned by the TextItems
property described above.
To populate the ImageItems collection, the PdfPage.ToImage method must be called with the parameter ImageInfo set to True.
The width and height of the image are returned by the PdfRect properties Right and Top, respectively. The image ID is returned by the PdfRect property Text.
The displacement, scaling, rotation and coordinate transformation matrix values are encapsulated in a PdfParam object returned by the PdfRect property ImageInfo
(introduced in Version 3.6). For example, the following code snippet displays the object ID, width, height and scaling factors for all images of a document:
Set PDF = Server.CreateObject("Persits.PDF")
Set Doc = PDF.OpenDocument("c:\path\doc.pdf")
For Each Page In Doc.Pages
Set Preview = Page.ToImage("imageinfo=true")
For Each Rect In Preview.ImageItems
Response.Write "Object ID=" & Rect.Text & "<br>"
Response.Write "Width=" & Rect.Right & "<br>"
Response.Write "Height=" & Rect.Top & "<br>"
Response.Write "ScaleX=" & Rect.ImageInfo("ScaleX") & "<br>"
Response.Write "ScaleY=" & Rect.ImageInfo("ScaleY") & "<br>"
Response.Write "<p>"
Next
Next
The full list of values encapsulated in the PdfParam object returned by the Rect.ImageInfo property is as follows:
Property | Meaning |
shiftX | Horizontal displacement |
shiftY | Vertical displacement |
rotation | Rotation in degrees |
scaleX | Horizontal scaling |
scaleY | Vertical scaling |
hasMask | 1 if the image has transparency, 0 otherwise |
a, b, c, d, e, f | The 6 components of the coordinate transformation matrix |
Access to this information can be quite useful when an image needs to be replaced with a graphics, as discussed below.
14.8.4 Replacing Images with Graphics
As shown in the Section 14.8.2 code sample, replacing images with other images with the same aspect ratio is very straightforward.
However, if the aspect ratio of the replacement image is different from that of the original image, a vertical or horizontal
distortion will occur as the new image will be stretched to fill the area occupied by the old image.
To avoid distortions, an image can be replaced with a graphics as opposed to another image. The graphics may have arbitrary content, including other images, drawings, text, etc.
The following code sample replaces all images in a PDF document with a red image with the caption "Image Removed" on a yellow background filling the entire area of the original image.
The red image is not stretched in any way and centered inside the yellow area.
VBScript |
Set PDF = Server.CreateObject("Persits.PDF")
Set OriginalDoc = PDF.OpenDocument(Server.MapPath("twoimages.pdf"))
' Replace images with graphics
Set NewDoc = PDF.CreateDocument
Set Image = NewDoc.OpenImage(Server.MapPath("14_imageremoved.png"))
For Each page In OriginalDoc.Pages
Set preview = page.ToImage("imageinfo=true")
For Each rect In preview.ImageItems
' Create a graphics which will host the image on the new document.
Width = rect.Right * rect.ImageInfo("ScaleX")
Height = rect.Top * rect.ImageInfo("ScaleY")
Set param = PDF.CreateParam
param("left").Value = 0
param("bottom").Value = 0
param("right").Value = Width
param("top").Value = Height
' Neutralize image coordinate transformation matrix
param("a").Value = 1 /Width
param("b").Value = 0
param("c").Value = 0
param("d").Value = 1 / Height
param("e").Value = 0
param("f").Value = 0
Set gr = newDoc.CreateGraphics(param)
gr.Canvas.SetFillColor 1, 1, 0 ' yellow
gr.Canvas.FillRect 0, 0, Width, Height
gr.Canvas.SetColor 0, 0, 0 ' black
gr.Canvas.LineWidth = 10 ' border
gr.Canvas.DrawRect 0, 0, Width, Height
Set param2 = PDF.CreateParam
param2("x") = (Width - Image.Width) / 2
param2("y") = (Height - Image.Height) / 2
gr.Canvas.DrawImage Image, param2
' Replace image with graphics
NewDoc.AddImageReplacement rect.Text, gr
Next
Next
NewDoc.AppendDocument OriginalDoc
NewDoc.Save Server.MapPath("replacedimage_gr.pdf"), false
|
C# |
IPdfManager objPDF = new PdfManager();
IPdfDocument objOriginalDoc = objPDF.OpenDocument(Server.MapPath("twoimages.pdf"));
// Replace images with graphics
IPdfDocument objNewDoc = objPDF.CreateDocument();
IPdfImage objImage = objNewDoc.OpenImage(Server.MapPath("14_imageremoved.png"));
foreach( IPdfPage objPage in objOriginalDoc.Pages )
{
IPdfPreview objPreview = objPage.ToImage("imageinfo=true");
foreach( IPdfRect rect in objPreview.ImageItems )
{
// Create a graphics which will host the image on the new document.
float fWidth = rect.Right * rect.ImageInfo["ScaleX"].Value;
float fHeight = rect.Top * rect.ImageInfo["ScaleY"].Value;
IPdfParam param = objPDF.CreateParam();
param["left"].Value = 0;
param["bottom"].Value = 0;
param["right"].Value = fWidth;
param["top"].Value = fHeight;
// Neutralize image coordinate transformation matrix
param["a"].Value = 1 / fWidth;
param["b"].Value = 0;
param["c"].Value = 0;
param["d"].Value = 1 / fHeight;
param["e"].Value = 0;
param["f"].Value = 0;
IPdfGraphics gr = objNewDoc.CreateGraphics(param);
gr.Canvas.SetFillColor( 1, 1, 0 ); // yellow
gr.Canvas.FillRect( 0, 0, fWidth, fHeight );
gr.Canvas.SetColor( 0, 0, 0 ); // black
gr.Canvas.LineWidth = 10; // border
gr.Canvas.DrawRect( 0, 0, fWidth, fHeight );
IPdfParam param2 = objPDF.CreateParam();
param2["x"].Value = (fWidth - objImage.Width) / 2;
param2["y"].Value = (fHeight - objImage.Height) / 2;
gr.Canvas.DrawImage( objImage, param2 );
// Replace image with graphics
objNewDoc.AddImageReplacement( rect.Text, gr );
}
}
objNewDoc.AppendDocument( objOriginalDoc );
string strFilename = objNewDoc.Save(Server.MapPath("replacedimage_gr.pdf"), false);
lblResult.Text = "Success! Download your PDF file <A HREF=" + strFilename + ">here</A>";
|
Click on the links below to run this code sample:
http://localhost/asppdf/manual_14/14_image2graphics.asp
http://localhost/asppdf/manual_14/14_image2graphics.aspx