Among the many features available for Digital Asset Management system in the Nuxeo Platform is the ability to automatically compute several conversions of pictures and videos in different resolutions and formats. Recently I was asked if it is possible to have different conversions for a picture depending on the asset status and to add a watermark when the asset is expired. The Idea here is to keep the obsolete assets in the repository but prevent users from using them. My answer, of course, was yes! These requirements can easily be configured with Nuxeo Studio. Let’s see how.

Picture AssetPicture Asset

First, we need a converter which adds a watermark. ImageMagick provides several ways to do it and here we have chosen a command that scales the watermark to the right size in the target picture.

<extension target="org.nuxeo.ecm.platform.commandline.executor.service.CommandLineExecutorComponent"point="command">
   <command name="addTextLayer" enabled="true">
      <commandLine>convert</commandLine>
      <parameterString>-background none -fill #{textColor} -gravity #{gravity} -size #{width}x#{height} caption:#{textValue} -rotate -25 #{sourceFilePath} +swap -gravity #{gravity} -composite #{targetFilePath}</parameterString>
      <installationDirective>You need to install ImageMagick.
      </installationDirective>
   </command>
</extension>
<extension target="org.nuxeo.ecm.core.convert.service.ConversionServiceImpl"
point="converter">
   <converter name="addTextLayer" class="org.nuxeo.ecm.platform.convert.plugins.CommandLineConverter">
      <parameters>
         <parameter name="CommandLineName">addTextLayer</parameter>
      </parameters>
   </converter>
</extension>

The next step is to configure an automation chain that uses our converter.

- Context.FetchFile
- Blob.RunConverter:
 converter: pictureResize
 parameters:
 textValue: Rejected
 targetFileName: watermarked.jpg
 gravity: center
 textColor: Red
 strokeColor: Red
 strokeWidth: "1"
 conversionFormat: "@{ChainParameters[\"parameters\"].conversionFormat}"
 height: "@{ChainParameters[\"parameters\"].height}"
 width: "@{ChainParameters[\"parameters\"].width}"
 depth: "@{ChainParameters[\"parameters\"].depth}"
- RunScript:
 script: "lifecycle = pictureDocument.getCurrentLifeCycleState();\ntextValue = \"\";\nif (lifecycle == \"obsolete\") {\n   textValue = \"___\"+lifecycle.toUpperCase()+ \"___\";\n}\nContext[\"textValue\"] = textValue;\n\n\n\n\n"
- Blob.RunConverter:
 converter: addTextLayer
 parameters:
 textValue: "@{Context[\"textValue\"]}"
 targetFileName: watermarked.jpg
 gravity: center
 textColor: Red
 strokeColor: Red
 strokeWidth: "1"
 conversionFormat: "@{ChainParameters[\"parameters\"].conversionFormat}"
 height: "@{ChainParameters[\"parameters\"].height}"
 width: "@{ChainParameters[\"parameters\"].width}"

Finally, we need to override the default chain with the one we have configured previously.

<extension point="pictureConversions" target="org.nuxeo.ecm.platform.picture.ImagingComponent">
   <!-- override default conversions -->
   <pictureConversion chainId="image_compute_conversions" default="false" description="Thumbnail" id="Thumbnail" maxSize="100" order="0" rendition="true">
   </pictureConversion>
   <pictureConversion chainId="image_compute_conversions" default="false" description="Small" id="Small" maxSize="280" order="100" rendition="true">
   </pictureConversion>
   <pictureConversion chainId="image_compute_conversions" default="false" description="Medium" id="Medium" maxSize="550" order="200" rendition="true">
   </pictureConversion>
   <pictureConversion chainId="image_compute_conversions" default="false" description="Original Size" id="OriginalJpeg" order="400" rendition="true">
   </pictureConversion>
</extension>

There is one remaining thing we need to configure. By default, the conversions are computed only if the main file changes. So we need to trigger the conversions when the asset status changes. For that we use an event handler and an automation chain.

Event handler which reacts to an asset becoming obsoleteEvent handler which reacts to an asset becoming obsolete

The event handler triggers the following automation chain:

- Context.FetchDocument
- Document.SetBlob:
file: "@{Document[\"file:content\"]}"
save: "true"
xpath: "file:content"

That’s it! Expired assets are now watermarked automatically!

Thumbnail ViewThumbnail View

Detailed ViewDetailed View