iTextSharp 7:调整图章大小的正确方法?
iTextSharp 7: Proper Way to Resize Stamps?
我最近总体上接触了 iText -- 看过第 5 版和第 7 版后,我仍然对图章的实现方式感到困惑。我按照使用 iTextSharp 7 的示例代码之一来添加注释:
PdfReader reader = new PdfReader(source);
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
Rectangle crop = pdfDoc.GetPage(1).GetCropBox();
Debug.WriteLine("CropBox Rectangle Dim "+crop);
ImageData img = ImageDataFactory.Create(imgsrc);
float iWidth = img.GetWidth();
float iHeight = img.GetHeight();
//Ignore the below statement
if (crop.GetWidth() > crop.GetHeight())
{
w = crop.GetWidth();
h = crop.GetHeight();
}
else
{
w = crop.GetHeight();
h = crop.GetWidth();
}
Debug.WriteLine("Width = "+w+" and Height = "+h);
Rectangle location = new Rectangle(crop.GetLeft(),crop.GetBottom(),iWidth,iHeight);
//Creates a Stamp Bounding Box on "Location"
PdfStampAnnotation stamp = new PdfStampAnnotation(location).SetStampName(new PdfName("Logo"));
PdfFormXObject xObj = new PdfFormXObject(new Rectangle(iWidth, iHeight));
PdfCanvas canvas = new PdfCanvas(xObj, pdfDoc);
canvas.AddImage(img, 0, 0, false);
stamp.SetNormalAppearance(xObj.GetPdfObject());
stamp.SetFlags(PdfAnnotation.PRINT);
pdfDoc.GetFirstPage().AddAnnotation(stamp);
pdfDoc.Close();
首先,我注意到我正在使用一个 ImageData 对象来输入我的图像。但是,我找不到任何方法来 "scale" 图像 - 类似于 Image.scaleAbsolute。输出的 PDF 最终正确标记,但完全过大。我想我明白 FormXObject 代表什么,但是 Canvas 有什么用?它对应于PDF中的什么。任何澄清都可能对协助未来的实施大有帮助。
谢谢
缩减规模
I can't find any method to "scale" the image down
正如评论中已经解释的那样,AddImage
方法的重载确实允许缩放图像,特别是:
/// <summary>Creates Image XObject from image and adds it to the specified position with specified width preserving aspect ratio.
/// </summary>
/// <param name="asInline">true if to add image as in-line.</param>
/// <returns>created XObject or null in case of in-line image (asInline = true).</returns>
public virtual PdfXObject AddImage(ImageData image, float x, float y, float width, bool asInline)
/// <summary>Creates Image XObject from image and adds it to canvas.</summary>
/// <param name="asInline">true if to add image as in-line.</param>
/// <returns>created XObject or null in case of in-line image (asInline = true).</returns>
public virtual PdfXObject AddImage(ImageData image, iText.Kernel.Geom.Rectangle rect, bool asInline)
/// <summary>Creates Image XObject from image and adds it to canvas.</summary>
/// <param name="image">
/// the
/// <c>PdfImageXObject</c>
/// object
/// </param>
/// <param name="a">an element of the transformation matrix</param>
/// <param name="b">an element of the transformation matrix</param>
/// <param name="c">an element of the transformation matrix</param>
/// <param name="d">an element of the transformation matrix</param>
/// <param name="e">an element of the transformation matrix</param>
/// <param name="f">an element of the transformation matrix</param>
/// <param name="asInline">true if to add image as in-line.</param>
/// <returns>created Image XObject or null in case of in-line image (asInline = true).</returns>
public virtual PdfXObject AddImage(ImageData image, float a, float b, float c, float d, float e, float f,
bool asInline)
这些重载中的第一个已经帮助了 OP。
背景
I think I understand what the FormXObject represents, but what is the Canvas for? What does it correspond to in the PDF.
[...]
What is the difference between the "Location" rectangle and the PdfFormXObject rectangle
location
矩形
正如 PDF 规范 ISO 32000-1(第 2 部分将于今年发布)所说
An annotation associates an object such as a note, sound, or movie with a location on a page of a PDF document
(第 12.5.1 节注释 - 常规)
因此,要为注释修复的第一件事就是 location,它是一个矩形,
The annotation rectangle, defining the location of the annotation on the page in default user space units.
(第 12.5.2 节注释词典)
此处使用的坐标系与为页面定义的 MediaBox 一致,CropBox 是显示部分。
如果是 OP 代码,请在此处选择此注释矩形:
Rectangle location = new Rectangle(crop.GetLeft(),crop.GetBottom(),iWidth,iHeight);
PdfStampAnnotation stamp = new PdfStampAnnotation(location)...
即注释矩形 location
位于可见页面区域的左下角,宽度和高度 iWidth,iHeight
.
PdfFormXObject
矩形
但是注释看起来怎么样?实际上注释可以有不同的外观,例如取决于光标是否悬停在它们上面。因此,每个注释对象可能有一个或多个 appearances 在其外观字典中定义为单独的 appearance streams:
Appearance streams enable the annotation to be presented visually in different ways to reflect its interactions with the user. Each appearance stream is a form XObject: a self-contained content stream that shall be rendered inside the annotation rectangle.
(第 12.5.5 节外观流)
所以这里 XObject 形式成为故事的一部分:它们是自包含的,也可以从其他内容流中引用,而不仅仅是从注释中引用。
它们实际上非常独立于注释,以至于它们有自己的坐标系(由其边界框 BBox 给出)并且仅在显示时适合注释矩形,可能仿射变换后(由其矩阵 Matrix 给出):
Algorithm: Appearance streams
a) The appearance’s bounding box (specified by its BBox entry) shall be transformed, using Matrix, to produce a quadrilateral with arbitrary orientation. The transformed appearance box is the smallest upright rectangle that encompasses this quadrilateral.
b) A matrix A shall be computed that scales and translates the transformed appearance box to align with the edges of the annotation’s rectangle (specified by the Rect entry). A maps the lower-left corner (the corner with the smallest x and y coordinates) and the upper-right corner (the corner with the greatest x and y coordinates) of the transformed appearance box to the corresponding corners of the annotation’s rectangle.
c) Matrix shall be concatenated with A to form a matrix AA that maps from the appearance’s coordinate system to the annotation’s rectangle in default user space:
AA = Matrix * A
(第 12.5.5 节外观流)
如果是 OP 代码,请在此处选择此边界框:
PdfFormXObject xObj = new PdfFormXObject(new Rectangle(iWidth, iHeight));
矩阵未明确给出,因此默认为单位矩阵。
即外观的边界框(PdfFormXObject
矩形)与注释矩形一样具有宽度和高度 iWidth, iHeight
,但其左下角是其坐标系的原点 (0, 0)。
通过上面的算法,它将平滑地适合注释矩形,没有任何扭曲。
有人可能想知道为什么有这么多独立的坐标系需要这样的转换。原因很简单:这使得表单 XObjects 变得容易 re-used,并且通过选择坐标系使其中的绘图指令尽可能简单。
Canvas
PdfCanvas
只是一个助手 class 在 iText 中提供了一种统一的方式来为任何内容流创建内容指令,这里是 XObject 内容流的外观。
我最近总体上接触了 iText -- 看过第 5 版和第 7 版后,我仍然对图章的实现方式感到困惑。我按照使用 iTextSharp 7 的示例代码之一来添加注释:
PdfReader reader = new PdfReader(source);
PdfWriter writer = new PdfWriter(dest);
PdfDocument pdfDoc = new PdfDocument(reader, writer);
Rectangle crop = pdfDoc.GetPage(1).GetCropBox();
Debug.WriteLine("CropBox Rectangle Dim "+crop);
ImageData img = ImageDataFactory.Create(imgsrc);
float iWidth = img.GetWidth();
float iHeight = img.GetHeight();
//Ignore the below statement
if (crop.GetWidth() > crop.GetHeight())
{
w = crop.GetWidth();
h = crop.GetHeight();
}
else
{
w = crop.GetHeight();
h = crop.GetWidth();
}
Debug.WriteLine("Width = "+w+" and Height = "+h);
Rectangle location = new Rectangle(crop.GetLeft(),crop.GetBottom(),iWidth,iHeight);
//Creates a Stamp Bounding Box on "Location"
PdfStampAnnotation stamp = new PdfStampAnnotation(location).SetStampName(new PdfName("Logo"));
PdfFormXObject xObj = new PdfFormXObject(new Rectangle(iWidth, iHeight));
PdfCanvas canvas = new PdfCanvas(xObj, pdfDoc);
canvas.AddImage(img, 0, 0, false);
stamp.SetNormalAppearance(xObj.GetPdfObject());
stamp.SetFlags(PdfAnnotation.PRINT);
pdfDoc.GetFirstPage().AddAnnotation(stamp);
pdfDoc.Close();
首先,我注意到我正在使用一个 ImageData 对象来输入我的图像。但是,我找不到任何方法来 "scale" 图像 - 类似于 Image.scaleAbsolute。输出的 PDF 最终正确标记,但完全过大。我想我明白 FormXObject 代表什么,但是 Canvas 有什么用?它对应于PDF中的什么。任何澄清都可能对协助未来的实施大有帮助。
谢谢
缩减规模
I can't find any method to "scale" the image down
正如评论中已经解释的那样,AddImage
方法的重载确实允许缩放图像,特别是:
/// <summary>Creates Image XObject from image and adds it to the specified position with specified width preserving aspect ratio.
/// </summary>
/// <param name="asInline">true if to add image as in-line.</param>
/// <returns>created XObject or null in case of in-line image (asInline = true).</returns>
public virtual PdfXObject AddImage(ImageData image, float x, float y, float width, bool asInline)
/// <summary>Creates Image XObject from image and adds it to canvas.</summary>
/// <param name="asInline">true if to add image as in-line.</param>
/// <returns>created XObject or null in case of in-line image (asInline = true).</returns>
public virtual PdfXObject AddImage(ImageData image, iText.Kernel.Geom.Rectangle rect, bool asInline)
/// <summary>Creates Image XObject from image and adds it to canvas.</summary>
/// <param name="image">
/// the
/// <c>PdfImageXObject</c>
/// object
/// </param>
/// <param name="a">an element of the transformation matrix</param>
/// <param name="b">an element of the transformation matrix</param>
/// <param name="c">an element of the transformation matrix</param>
/// <param name="d">an element of the transformation matrix</param>
/// <param name="e">an element of the transformation matrix</param>
/// <param name="f">an element of the transformation matrix</param>
/// <param name="asInline">true if to add image as in-line.</param>
/// <returns>created Image XObject or null in case of in-line image (asInline = true).</returns>
public virtual PdfXObject AddImage(ImageData image, float a, float b, float c, float d, float e, float f,
bool asInline)
这些重载中的第一个已经帮助了 OP。
背景
I think I understand what the FormXObject represents, but what is the Canvas for? What does it correspond to in the PDF.
[...]
What is the difference between the "Location" rectangle and the PdfFormXObject rectangle
location
矩形
正如 PDF 规范 ISO 32000-1(第 2 部分将于今年发布)所说
An annotation associates an object such as a note, sound, or movie with a location on a page of a PDF document
(第 12.5.1 节注释 - 常规)
因此,要为注释修复的第一件事就是 location,它是一个矩形,
The annotation rectangle, defining the location of the annotation on the page in default user space units.
(第 12.5.2 节注释词典)
此处使用的坐标系与为页面定义的 MediaBox 一致,CropBox 是显示部分。
如果是 OP 代码,请在此处选择此注释矩形:
Rectangle location = new Rectangle(crop.GetLeft(),crop.GetBottom(),iWidth,iHeight);
PdfStampAnnotation stamp = new PdfStampAnnotation(location)...
即注释矩形 location
位于可见页面区域的左下角,宽度和高度 iWidth,iHeight
.
PdfFormXObject
矩形
但是注释看起来怎么样?实际上注释可以有不同的外观,例如取决于光标是否悬停在它们上面。因此,每个注释对象可能有一个或多个 appearances 在其外观字典中定义为单独的 appearance streams:
Appearance streams enable the annotation to be presented visually in different ways to reflect its interactions with the user. Each appearance stream is a form XObject: a self-contained content stream that shall be rendered inside the annotation rectangle.
(第 12.5.5 节外观流)
所以这里 XObject 形式成为故事的一部分:它们是自包含的,也可以从其他内容流中引用,而不仅仅是从注释中引用。
它们实际上非常独立于注释,以至于它们有自己的坐标系(由其边界框 BBox 给出)并且仅在显示时适合注释矩形,可能仿射变换后(由其矩阵 Matrix 给出):
Algorithm: Appearance streams
a) The appearance’s bounding box (specified by its BBox entry) shall be transformed, using Matrix, to produce a quadrilateral with arbitrary orientation. The transformed appearance box is the smallest upright rectangle that encompasses this quadrilateral.
b) A matrix A shall be computed that scales and translates the transformed appearance box to align with the edges of the annotation’s rectangle (specified by the Rect entry). A maps the lower-left corner (the corner with the smallest x and y coordinates) and the upper-right corner (the corner with the greatest x and y coordinates) of the transformed appearance box to the corresponding corners of the annotation’s rectangle.
c) Matrix shall be concatenated with A to form a matrix AA that maps from the appearance’s coordinate system to the annotation’s rectangle in default user space:
AA = Matrix * A
(第 12.5.5 节外观流)
如果是 OP 代码,请在此处选择此边界框:
PdfFormXObject xObj = new PdfFormXObject(new Rectangle(iWidth, iHeight));
矩阵未明确给出,因此默认为单位矩阵。
即外观的边界框(PdfFormXObject
矩形)与注释矩形一样具有宽度和高度 iWidth, iHeight
,但其左下角是其坐标系的原点 (0, 0)。
通过上面的算法,它将平滑地适合注释矩形,没有任何扭曲。
有人可能想知道为什么有这么多独立的坐标系需要这样的转换。原因很简单:这使得表单 XObjects 变得容易 re-used,并且通过选择坐标系使其中的绘图指令尽可能简单。
Canvas
PdfCanvas
只是一个助手 class 在 iText 中提供了一种统一的方式来为任何内容流创建内容指令,这里是 XObject 内容流的外观。