使用运算符

PDF 运算符及其用法介绍

运算符是一个 PDF 关键字,指定要执行的某些操作,例如在页面上绘制图形形状。运算符关键字通过没有初始斜线字符(2Fh)与命名对象区别开来。运算符只有在内容流中才有意义。

内容流是一个 PDF 流对象,其数据由描述要在页面上绘制的图形元素的指令组成。有关 PDF 运算符的更多详细信息可以在 PDF 规范 中找到。

实施细节

本主题解释了如何使用 Aspose.PDF 的运算符。 The selected example adds an image into a PDF file to illustrate the concept. To add an image in a PDF file, different operators are needed. This example uses GSave, ConcatenateMatrix, Do, and GRestore.

  • The GSave operator saves the PDF’s current graphical state.

  • 本主题解释了如何使用 Aspose.PDF 的操作符。 选定的示例在 PDF 文件中添加了一张图片以说明这一概念。要在 PDF 文件中添加图片,需要使用不同的操作符。此示例使用了 GSaveConcatenateMatrixDoGRestore

  • (连接矩阵)操作符用于定义图片应如何放置在 PDF 页面上。

  • Do 操作符在页面上绘制图片。

  • GRestore 操作符恢复图形状态。

要在 PDF 文件中添加图片:

  1. 创建一个 Document 对象并打开输入的 PDF 文档。
  2. 获取要添加图像的特定页面。
  3. 将图像添加到页面的资源集合中。
  4. 使用操作符将图像放置在页面上:
    • 首先,使用 GSave 操作符保存当前图形状态。
    • 然后使用 ConcatenateMatrix 操作符指定图像的位置。
    • 使用 Do 操作符在页面上绘制图像。
  5. 最后,使用 GRestore 操作符保存更新后的图形状态。

以下代码片段显示了如何使用 PDF 操作符。

public class WorkingWithOperators {

    private static String _dataDir = "/home/aspose/pdf-examples/Samples/Operators/";

    public static void AddImageUsingOpeartors() {

        // 创建一个新的 PDF 文档
        Document pdfDocument = new Document(_dataDir + "PDFOperators.pdf");

        // 获取需要添加图像的页面
        Page page = pdfDocument.getPages().get_Item(1);

        // 设置坐标
        int lowerLeftX = 100;
        int lowerLeftY = 100;
        int upperRightX = 200;
        int upperRightY = 200;

        // 将图像加载到流中
        FileInputStream imageStream = null;
        try {
            imageStream = new FileInputStream(_dataDir + "PDFOperators.jpg");
        } catch (FileNotFoundException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }

        // 将图像添加到页面资源的图像集合中
        page.getResources().getImages().add(imageStream);

        // 使用 GSave 操作符:该操作符保存当前图形状态
        page.getContents().add(new GSave());
        // 创建 Rectangle 和 Matrix 对象
        Rectangle rectangle = new Rectangle(lowerLeftX, lowerLeftY, upperRightX, upperRightY);
        Matrix matrix = new Matrix(new double[] { rectangle.getURX() - rectangle.getLLX(), 0, 0,
                rectangle.getURY() - rectangle.getLLY(), rectangle.getLLX(), rectangle.getLLY() });

        // 使用 ConcatenateMatrix(连接矩阵)操作符:定义图像的放置方式
        page.getContents().add(new ConcatenateMatrix(matrix));

        XImage ximage = page.getResources().getImages().get_Item(page.getResources().getImages().size());
        // 使用 Do 操作符:该操作符绘制图像
        page.getContents().add(new Do(ximage.getName()));
        // 使用 GRestore 操作符:该操作符恢复图形状态
        page.getContents().add(new GRestore());

        // 保存更新后的文档
        pdfDocument.save(_dataDir + "PDFOperators_out.pdf");
    }

使用操作符在页面上绘制XForm

本主题演示如何使用GSave/GRestore操作符、ContatenateMatrix操作符来定位xForm,以及Do操作符在页面上绘制xForm。

下面的代码使用GSave/GRestore操作符对PDF文件的现有内容进行包装。这种方法有助于在现有内容的末尾获取初始图形状态。没有这种方法,可能会在现有操作符链的末尾保留一些不需要的变换。

    public static void DrawXFormUsingOpeartors() {
        String imageFile = _dataDir + "aspose-logo.jpg";
        String inFile = _dataDir + "DrawXFormOnPage.pdf";
        String outFile = _dataDir + "blank-sample2_out.pdf";

        Document pdfDocument = new Document(inFile);
        OperatorCollection pageContents = pdfDocument.getPages().get_Item(1).getContents();

        // 示例演示
        // GSave/GRestore 操作符的使用
        // ContatenateMatrix 操作符用于定位 xForm
        // Do 操作符用于在页面上绘制 xForm

        // 用 GSave/GRestore 操作符对现有内容进行包装
        // 这是为了在现有内容的末尾获取初始图形状态
        // 否则可能会在现有操作符链的末尾保留一些不需要的变换
        pageContents.insert(1, new GSave());
        pageContents.add(new GRestore());

        // 添加保存图形状态的操作符以在新命令后正确清除图形状态
        pageContents.add(new GSave());

        // 创建 xForm
        XForm form = XForm.createNewForm(pdfDocument.getPages().get_Item(1), pdfDocument);
        pdfDocument.getPages().get_Item(1).getResources().getForms().add(form);
        form.getContents().add(new GSave());

        // 定义图像宽度和高度
        form.getContents().add(new ConcatenateMatrix(200, 0, 0, 200, 0, 0));

        // 将图像加载到流中
        FileInputStream imageStream = null;
        try {
            imageStream = new FileInputStream(imageFile);
        } catch (FileNotFoundException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }

        // 将图像添加到 XForm 资源的图像集合中
        form.getResources().getImages().add(imageStream);
        XImage ximage = form.getResources().getImages().get_Item(form.getResources().getImages().size());
        // 使用 Do 操作符:该操作符绘制图像
        form.getContents().add(new Do(ximage.getName()));
        form.getContents().add(new GRestore());

        pageContents.add(new GSave());
        // 将表单放置在 x=100 y=500 坐标位置
        pageContents.add(new ConcatenateMatrix(1, 0, 0, 1, 100, 500));
        // 使用 Do 操作符绘制表单
        pageContents.add(new Do(form.getName()));
        pageContents.add(new GRestore());

        pageContents.add(new GSave());

        // 将表单放置在 x=100 y=300 坐标位置
        pageContents.add(new ConcatenateMatrix(1, 0, 0, 1, 100, 300));

        // 使用 Do 操作符绘制表单
        pageContents.add(new Do(form.getName()));
        pageContents.add(new GRestore());

        // // 在 GSave 之后使用 GRestore 恢复图形状态
        pageContents.add(new GRestore());
        pdfDocument.save(outFile);
    }

使用操作符类移除图形对象

操作符类为PDF操作提供了强大的功能。当PDF文件包含无法使用PdfContentEditor类的DeleteImage方法移除的图形时,可以使用操作符类来移除它们。

以下代码片段展示了如何移除图形。请注意,如果PDF文件包含图形的文本标签,使用这种方法它们可能会保留在PDF文件中。因此,搜索图形操作符以找到删除此类图像的替代方法。

    public static void RemoveGraphicsOpeartors() {
        Document pdfDocument  = new Document(_dataDir+ "RemoveGraphicsObjects.pdf");
        Page page = pdfDocument.getPages().get_Item(2);
        OperatorCollection oc = page.getContents();

        // 使用路径绘制操作符
        Operator[] operators = new Operator[] {
                new Stroke(),
                new ClosePathStroke(),
                new Fill()
        };

        oc.delete(operators);
        pdfDocument.save(_dataDir+ "No_Graphics_out.pdf");
    }

更改PDF文档的颜色空间

Operator 类中实现了以下方法,以允许您更改颜色空间。使用它可以将某些特定的RGB/CMYK颜色更改为CMYK/RGB颜色空间,保持其余的PDF文档不变。

以下代码片段演示了如何使用Aspose.PDF for Java更改颜色空间。

Document doc = new Document("input_color.pdf");
OperatorCollection contents = doc.getPages().get_Item(1).getContents();
System.out.println("PDF 文档中 RGB 颜色操作符的值");
for (int j = 1; j <= contents.size(); j++) {
    Operator oper = contents.get_Item(j);
    if (oper instanceof Operator.SetRGBColor || oper instanceof Operator.SetRGBColorStroke)
        try {
            // 将 RGB 转换为 CMYK 颜色
            System.out.println(oper.toString());

            double[] rgbFloatArray = new double[] { Double.valueOf(oper.getParameters().get(0).toString()), Double.valueOf(oper.getParameters().get(1).toString()), Double.valueOf(oper.getParameters().get(2).toString()), };
            double[] cmyk = new double[4];
            if (oper instanceof Operator.SetRGBColor) {
                ((Operator.SetRGBColor) oper).getCMYKColor(rgbFloatArray, cmyk);
                contents.set_Item(j, new Operator.SetCMYKColor(cmyk[0], cmyk[1], cmyk[2], cmyk[3]));
            } else if (oper instanceof Operator.SetRGBColorStroke) {
                ((Operator.SetRGBColorStroke) oper).getCMYKColor(rgbFloatArray, cmyk);
                contents.set_Item(j, new Operator.SetCMYKColorStroke(cmyk[0], cmyk[1], cmyk[2], cmyk[3]));
            } else
                throw new java.lang.Throwable("不支持的命令");

        } catch (Throwable e) {
            e.printStackTrace();
        }
}
doc.save("input_colorout.pdf");

// 测试结果
System.out.println("结果 PDF 文档中转换后的 CMYK 颜色操作符的值");
doc = new Document("input_colorout.pdf");
contents = doc.getPages().get_Item(1).getContents();
for (int j = 1; j <= contents.size(); j++) {
    Operator oper = contents.get_Item(j);
    if (oper instanceof Operator.SetCMYKColor || oper instanceof Operator.SetCMYKColorStroke) {
        System.out.println(oper.toString());
    }
}