使用 JavaScript 优化演示文稿中的图像管理

简介

Aspose.Slides for Node.js via Java 提供了多种处理图像的方式,每种方式都有不同的用途。您可以将图像存储在演示文稿中、在图片框中显示、用作幻灯片背景、链接到外部图像、替换共享的图像资源,或将 SVG 内容转换为可编辑的形状。
本文重点介绍图像资源及其在整个演示文稿中的使用方式。有关对单个图片框进行的裁剪、透明度、效果、拉伸以及其他格式设置,请参阅图片框

了解图像模型

以下 API 概念密切相关,但不可互换:

  • 演示文稿图像集合 存储演示文稿使用的图像资源。使用 ImageCollection.addImage 添加图像数据并获取 PPImage 资源。
  • 图片框 是一种在幻灯片、版式或母版上显示图像的形状。使用 ShapeCollection.addPictureFrame 将图像资源放置在幻灯片上。
  • 幻灯片背景将图像用作幻灯片填充的一部分,而不是形状。因此它的行为不同于图片框。
  • PPImage.replaceImage 替换图像资源。如果多个演示文稿元素使用该资源,它们都将使用替换后的资源。
  • 将 SVG 转换为形状会创建可编辑的幻灯片形状。转换后,内容不再作为单一图片资源管理。

因此典型的工作流是:将图像数据添加到图像集合,获取一个 PPImage,然后在一个或多个图片框或填充中使用该资源。

添加嵌入图像

要插入本地图像,请加载文件,将其添加到图像集合,并创建使用返回的 PPImage 资源的图片框。

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const presentation = new aspose.slides.Presentation();
try {
    let image;
    const sourceImage = aspose.slides.Images.fromFile("photo.png");
    try {
        image = presentation.getImages().addImage(sourceImage);
    } finally {
        if (sourceImage != null) {
            sourceImage.dispose();
        }
    }

    const slide = presentation.getSlides().get_Item(0);
    slide.getShapes().addPictureFrame(aspose.slides.ShapeType.Rectangle, 20, 20, 320, 180, image);

    presentation.save("presentation.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

以这种方式添加的图像会嵌入到演示文稿中,因此生成的文件不依赖于原始图像文件的可用性。

从网络添加图像

当图像可通过 HTTP 或 HTTPS 访问时,下载其字节,将其添加到演示文稿图像集合,并以与本地图像相同的方式使用返回的图像资源。

const aspose = {};
aspose.slides = require("aspose.slides.via.java");
const http = require("http");
const https = require("https");
const java = require("java");

function downloadBytes(url) {
    return new Promise((resolve, reject) => {
        const client = url.startsWith("https:") ? https : http;
        client.get(url, (response) => {
            if (response.statusCode < 200 || response.statusCode >= 300) {
                response.resume();
                reject(new Error(`HTTP ${response.statusCode}`));
                return;
            }

            const chunks = [];
            response.on("data", (chunk) => chunks.push(chunk));
            response.on("end", () => resolve(Buffer.concat(chunks)));
        }).on("error", reject);
    });
}

(async () => {
    const imageData = await downloadBytes("https://example.com/image.png");
    const javaBytes = java.newArray("byte", Array.from(imageData));

    const presentation = new aspose.slides.Presentation();
    try {
        const image = presentation.getImages().addImage(javaBytes);
        const slide = presentation.getSlides().get_Item(0);
        slide.getShapes().addPictureFrame(aspose.slides.ShapeType.Rectangle, 20, 20, 320, 180, image);

        presentation.save("presentation-from-web.pptx", aspose.slides.SaveFormat.Pptx);
    } finally {
        presentation.dispose();
    }
})();

在长期运行的应用程序中,应重用适合该应用的 HTTP 客户端或连接管理策略,而不是反复创建不必要的网络基础设施。当来源不可信时,还应验证远程 URL、响应大小和内容类型。

在幻灯片间复用图像

如果同一图像需要使用多次,只需在演示文稿中添加一次,并在创建其他图片框时复用返回的 PPImage。这可以避免重复加载相同的源数据,并明确共享图像资源与其使用之间的关系。

对于应自动出现在多张幻灯片上的图形(如公司标志),请考虑将图片框放置在幻灯片母版或版式上,而不是在每张幻灯片中添加等效的形状。

将图像用作幻灯片背景

背景图像被分配给幻灯片填充;它不是作为图片框形状添加的。当图像需要覆盖幻灯片背景且不应像普通幻灯片对象那样被操作时,这非常有用。

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const presentation = new aspose.slides.Presentation();
try {
    const slide = presentation.getSlides().get_Item(0);

    let image;
    const sourceImage = aspose.slides.Images.fromFile("background.jpg");
    try {
        image = presentation.getImages().addImage(sourceImage);
    } finally {
        if (sourceImage != null) {
            sourceImage.dispose();
        }
    }

    const backgroundType = java.newByte(aspose.slides.BackgroundType.OwnBackground);
    slide.getBackground().setType(backgroundType);

    const fillType = java.newByte(aspose.slides.FillType.Picture);
    slide.getBackground().getFillFormat().setFillType(fillType);

    slide.getBackground().getFillFormat().getPictureFillFormat().setPictureFillMode(aspose.slides.PictureFillMode.Stretch);
    slide.getBackground().getFillFormat().getPictureFillFormat().getPicture().setImage(image);

    presentation.save("background-image.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

有关更多背景选项(包括母版和版式背景),请参阅演示文稿背景

嵌入图像和链接图像

嵌入图像和链接图像在可移植性和文件大小上有不同的权衡:

  • 嵌入图像: 图像数据存储在演示文稿内部。演示文稿是自包含的,但文件大小包含图像数据。
  • 链接图像: 演示文稿存储指向外部图像的路径或 URL。这可以减小演示文稿的大小,但在打开或渲染演示文稿时,外部资源必须保持可访问。

可以通过 Picture.setLinkPathLong 指定外部路径或 URL 来创建链接图片,而不是嵌入图像数据。

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const presentation = new aspose.slides.Presentation();
try {
    const slide = presentation.getSlides().get_Item(0);
    const pictureFrame = slide.getShapes().addPictureFrame(aspose.slides.ShapeType.Rectangle, 20, 20, 320, 180, null);
    pictureFrame.getPictureFormat().getPicture().setLinkPathLong("https://example.com/image.png");

    presentation.save("linked-image.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

仅在部署环境能够可靠访问外部资源时才使用链接图像。对于必须离线工作或在系统之间迁移的演示文稿,嵌入图像通常更安全。

处理 SVG 图像

SVG 是矢量格式,可用于图标、图表和其他应在放大时保持细节的图形。Aspose.Slides 同时支持将 SVG 作为图像资源和可编辑幻灯片形状的来源。

将 SVG 添加为图像

创建一个 SvgImage,将其添加到图像集合,并在图片框中放置生成的图像资源。

const aspose = {};
aspose.slides = require("aspose.slides.via.java");
const fs = require("fs");

const presentation = new aspose.slides.Presentation();
try {
    const svgContent = fs.readFileSync("icon.svg", "utf8");
    const svgImage = new aspose.slides.SvgImage(svgContent);

    const image = presentation.getImages().addImage(svgImage);
    const slide = presentation.getSlides().get_Item(0);
    slide.getShapes().addPictureFrame(aspose.slides.ShapeType.Rectangle, 20, 20, 200, 200, image);

    presentation.save("svg-image.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

包含外部资源的 SVG 文件

SVG 可以引用外部图像、样式表或字体。对于这些情况,SvgImage 提供接受 ExternalResourceResolver 和基础 URI 的构造函数。解析器可以将相对 URI 映射为允许的绝对 URI,并返回请求资源的流。
解析器在 Aspose.Slides 处理 SVG 时提供外部资源,但不会将 SVG 重写为自包含文档。如果需要保持 SVG 可移植性,请将所需资源嵌入 SVG 本身,例如使用 data: URI 链接图像。
当 SVG 文件来自不可信来源时,应限制解析器可访问的方案、文件位置和主机。网络解析器还应应用超时、响应大小限制和内容验证。

将 SVG 转换为可编辑形状

Aspose.Slides 可以将 SVG 转换为一组可编辑的幻灯片形状,类似于对应的 PowerPoint 命令。

PowerPoint Popup Menu

使用接受 SVG 图像的 ShapeCollection.addGroupShape 重载来执行转换。

const aspose = {};
aspose.slides = require("aspose.slides.via.java");
const fs = require("fs");

const presentation = new aspose.slides.Presentation();
try {
    const svgContent = fs.readFileSync("diagram.svg", "utf8");
    const svgImage = new aspose.slides.SvgImage(svgContent);

    const slideSize = presentation.getSlideSize().getSize();
    const slide = presentation.getSlides().get_Item(0);
    slide.getShapes().addGroupShape(svgImage, 0, 0, slideSize.getWidth(), slideSize.getHeight());

    presentation.save("editable-svg-shapes.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

当需要将各个矢量元素编辑为 PowerPoint 形状时使用 SVG 到形状的转换。如果 SVG 只需显示,将其保留为图像更简单,且避免创建大量独立形状。

替换已有图像资源

当需要替换已有图像资源时,请使用 PPImage.replaceImage。这对共享图形(如徽标)尤其有用。

const aspose = {};
aspose.slides = require("aspose.slides.via.java");

const presentation = new aspose.slides.Presentation("input.pptx");
try {
    const imageToReplace = presentation.getImages().get_Item(0);

    const replacementImage = aspose.slides.Images.fromFile("new-logo.png");
    try {
        imageToReplace.replaceImage(replacementImage);
    } finally {
        if (replacementImage != null) {
            replacementImage.dispose();
        }
    }

    presentation.save("output.pptx", aspose.slides.SaveFormat.Pptx);
} finally {
    presentation.dispose();
}

如果多个图片框、背景、母版或版式使用相同的图像资源,替换该资源会更新所有这些使用。如果只需要更改一个图片框,请为该框分配不同的图像,而不是替换共享资源。
PPImage.replaceImage 还提供接受字节数组或另一个 PPImage 的重载。

实用图像管理指南

控制演示文稿大小

大型光栅图像会导致演示文稿不必要地增大。使用尺寸符合预期显示大小的源图像,尽可能复用共享图像资源,并避免嵌入相同全分辨率图形的重复拷贝。
对于已放入图片框的光栅图片,可使用 PictureFillFormat.compressImage 根据选定的分辨率和裁剪设置压缩图像数据。这属于图片框处理而非图像集合管理,相关格式化操作请参阅图片框

在嵌入和链接内容之间选择

嵌入使演示文稿可移植,因为所有必需的图像数据随文件一起携带。链接可以减小文件大小,但会引入外部依赖。仅在该依赖可接受且稳定时才使用链接。

复用共享品牌元素

对于重复出现的徽标、水印或装饰图形,请使用单一图像资源并复用它。如果该图形属于演示文稿设计而非幻灯片内容,请将其放置在母版或版式上,以便相应的幻灯片继承。

保持 SVG 资源可移植

自包含的 SVG 比依赖外部文件或网络资源的 SVG 更易于移动和一致渲染。尽可能在导入 SVG 前嵌入所需资源。仅在需要编辑各个矢量元素时才将 SVG 转换为形状。

使用现代跨平台图像 API

对于新的 Node.js via Java 代码,请使用 Aspose.Slides 的 IImageImages API,而不是基于 java.awt.image.BufferedImage 的旧版公共 API。迁移指南请参阅Modern API
WMF 和 EMF 需要特殊处理。当这些格式通过 IImage 传递时,ImageCollection.addImage 会在插入前将元文件转换为光栅 PNG 表示。如果需要保留元文件数据,请改用基于流的 ImageCollection.addImage 重载。从电子表格或其他产品生成 EMF 内容是单独的集成工作流,超出本文范围。

常见问题

图像集合与图片框有什么区别?
图像集合存储可重用的图像资源。图片框是一种幻灯片形状,用于显示这些资源之一,并提供如裁剪和效果等特定于图片的格式设置。

在所有位置替换相同徽标的最佳方法是什么?
如果徽标已作为单一图像资源共享,请使用 PPImage.replaceImage 替换该资源。对于全演示文稿的品牌标识,也可以将徽标放置在母版或版式上,以减少重复的幻灯片内容。

为什么链接图像在另一台电脑上消失?
链接图片依赖其外部文件或 URL。如果在另一台电脑上无法访问该资源,链接图像就会不可用。演示文稿必须自包含时请嵌入图像。

插入的 SVG 能否编辑为 PowerPoint 形状?
可以。使用 ShapeCollection.addGroupShape 转换 SVG;生成的组包含可编辑的幻灯片形状,而不是单个 SVG 图片。

如何让包含大量图像的演示文稿保持更小?
复用共享图像资源,避免使用不必要的大尺寸光栅源,适时压缩合适的光栅图片,将重复的品牌元素放在母版或版式上,并仅在外部依赖可接受时使用链接图像。