6

我目前正在开发一个网站,该网站将在某些详细信息页面上显示图片库。它必须在底部显示带有小缩略图的导航,并且必须为每个元素显示一些基本信息和大图像。

大图像也必须调整大小,因为它们有一个最大尺寸。

关键是每个多媒体组件只使用一个源图像,并且能够在发布时调整图像大小,因此,源图像将被发送到客户端浏览器一个缩略图和一个大图像。仅使用样式或 HTML 来显示大小图像是可能的,但这是非常低效的,因为源图像(其中一些非常重)总是发送给客户。

我的第一个想法是自定义代码片段,它是用 C# 编写的,但我发现仅将一些图像调整到一定大小然后再将它们调整到另一个大小很复杂。我也找不到用适当的路径替换最终 HTML 上的 SRC 的方法。

另一个想法是创建一个旧式 PublishBinary 方法,但我发现这真的很复杂,因为看起来当前的 Tridion 架构根本不打算这样做......

最重要的一点是,即使我们可以成功(以某种方式)调整大小,目前发布两次相同的图像也是 Tridion 2011 的问题。大版本和小版本实际上都来自同一个多媒体组件,因此不可能同时发布它们或使用名称,第一个将永远消失,因为路径将使用第二个更新:-S。

有任何想法吗?

4

4 回答 4

10

我在过去构建了一个图像大小调整 TBB,它读取 Dreamweaver 或 XSLT 模板的输出。这个想法是使用第一个模板生成如下所示的标签。

<img src="tcm:1-123" maxWidth="250" maxHeight="400" 
     cropPosition="middle" variantId="250x400" 
     action="PostProcess" enlargeIfTooSmall="true"
/>

“重新调整大小” TBB 然后对包中的输出项进行后处理,查找具有后处理操作的节点。

System.Drawing然后,它根据maxHieghtmaxWidthdimention 属性使用库创建多媒体组件的变体,并使用AddBinary()提到的 @frank 方法并使用variantId文件名前缀和变体 id 的属性发布它(并将 SRC 属性替换为的 URL新的二进制文件)。

为了使这 100% 灵活,如果maxHeightmaxWidth属性中的任何一个设置为 0,则 TBB 仅根据“非零”尺寸重新调整大小,或者如果两者都设置,则根据 cropPosition 属性裁剪图像。这使我们能够为横向和纵向图像制作方形缩略图,而不会扭曲它们。该enlargeIfTooSmall属性用于防止小图像被拉伸太多。

您可以在此处查看最终画廊的样本:http: //medicine.yale.edu/web/help/examples/specific/photo/index.aspx

和其他图像大小调整示例: http ://medicine.yale.edu/web/help/examples/general/images.aspx

所有图像只需一次上传到 CMS,然后在发布时即时调整大小和裁剪。

于 2012-06-12T18:06:27.980 回答
6

Tridion 可以完美地在单个 MMC 上发布多个变体。当您调用时,AddBinary您可以指定此二进制文件是 MMC 的变体,每个变体都由您指定的简单字符串标识。

public Binary AddBinary(
    Stream content,
    string filename,
    StructureGroup location,
    string variantId,
    Component relatedComponent,
    string mimeType
)

如您所见,您还可以指定二进制文件的文件名。如果这样做,您有责任确保变体具有唯一的文件名,并且不同 MMC 之间的文件名保持唯一。因此,通常,最简单的方法是简单地为文件名添加前缀或后缀,并带有一些 variantId: 的指示<MmcImageFileName>_thumbnail.jpg

于 2012-06-12T13:30:27.750 回答
5

对于最近的一个演示项目,我采用了完全不同的方法。二进制文件都发布到代理数据库。它们是使用 HttpModule 从代理中提取的,它将二进制数据写入文件系统。我可以在图像的 URL 中编码所需的宽度或高度(当然,对于不是图像的二进制文件,这部分逻辑将不起作用)。然后该模块动态调整图像大小(真正动态,而不是在发布期间!)并将调整大小的版本写入磁盘。

例如:如果我请求/Images/photo.jpg,我会得到原始图像。如果我请求 /Images/photo_h100.jpg,我会得到一个 100 像素高的版本。url /Images/photo_w150.jpg 导致 150 像素的宽度。

无需变体,也无需因尺寸要求不同而重新发布:完全按需调整尺寸!服务器上的性能损失可以忽略不计:每个大小只生成一次,直到重新发布图像。

我使用了 .NET,但当然它也可以在 Java 中工作。

于 2012-06-12T21:27:49.917 回答
4

按照 Frank 和 Quirijn 的回答,您可能会对使用环境数据框架在墨盒索赔处理器中调整图像大小感兴趣。该解决方案与技术无关,可以在 Java 和 .Net 中重复使用。您只需将调整大小的图像字节放入声明中,然后在 Java 或 .Net 中使用它。

Java 声明处理器:

public void onRequestStart(ClaimStore claims) throws AmbientDataException {
    int publicationId = getPublicationId();
    int binaryId = getBinaryId();

    BinaryContentDAO bcDAO = (BinaryContentDAO)StorageManagerFactory.getDAO(publicationId, StorageTypeMapping.BINARY_CONTENT);
    BinaryContent binaryContent = bcDAO.findByPrimaryKey(publicationId, binaryId, null);

    byte[] binaryBuff =  binaryContent.getContent();
    pixelRatio = getPixelRatio();

    int resizeWidth = getResizeWidth();

    BufferedImage original = ImageIO.read(new ByteArrayInputStream(binaryBuff));
    if (original.getWidth() < MAX_IMAGE_WIDTH) {
        float ratio = (resizeWidth * 1.0f) / (float)MAX_IMAGE_WIDTH; 

        float width =  original.getWidth() * ratio; 
        float height = original.getHeight() * ratio;

        BufferedImage resized = new BufferedImage(Math.round(width), Math.round(height), original.getType());
        Graphics2D g = resized.createGraphics();
        g.setComposite(AlphaComposite.Src);

        g.drawImage(original, 0, 0, resized.getWidth(), resized.getHeight(), null);
        g.dispose();

        ByteArrayOutputStream output = new ByteArrayOutputStream();

        BinaryMeta meta = new BinaryMetaFactory().getMeta(String.format("tcm:%s-%s", publicationId, binaryId));
        String suffix = meta.getPath().substring(meta.getPath().lastIndexOf('.') + 1);

        ImageIO.write(resized, suffix, output);
        binaryBuff = output.toByteArray();
    }
    claims.put(new URI("taf:extensions:claim:resizedimage"), binaryBuff);
}

.Net HTTP 处理程序:

public void ProcessRequest(HttpContext context) {
    if (context != null) {
        HttpResponse httpResponse = HttpContext.Current.Response;

        ClaimStore claims = AmbientDataContext.CurrentClaimStore;
        if (claims != null) {
            Codemesh.JuggerNET.byteArray javaArray = claims.Get<Codemesh.JuggerNET.byteArray>("taf:extensions:claim:resizedimage");
            byte[] resizedImage = javaArray.ToNative(javaArray);
            if (resizedImage != null && resizedImage.Length > 0) {
                httpResponse.Expires = -1;
                httpResponse.Flush();
                httpResponse.BinaryWrite(resizedImage);
            }
        }
    }
}

Java过滤器:

@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {    
        ClaimStore claims = AmbientDataContext.getCurrentClaimStore();
        if (claims != null) {
            Object resizedImage = claims.get(new URI("taf:extensions:claim:resizedimage"));
            if (resizedImage != null) {
                byte[] binaryBuff = (byte[])resizedImage;
                response.getOutputStream().write(binaryBuff);
            }
        }
    }
于 2012-06-25T18:45:36.500 回答