Addons

HOWTO: Contribute Picture Conversions

Updated: March 18, 2024

Picture conversions are used to fill the picture views (stored in the picture:views field of a document having the Picture facet). The default ones are: Thumbnail, Small, Medium, FullHD, OriginalJpeg.

Picture conversions are simple XML contributions done on the pictureConversions extension point of the org.nuxeo.ecm.platform.picture.ImagingComponent component.

Hyland University
Watch the related courses on Hyland University

Picture conversions are working only on documents having the Picture facet.

Available since 7.1.

Contributing a New Picture Conversion

Resizing a Picture

Let's add a new picture conversions called Large that will resize the picture to 800px max.

 <extension target="org.nuxeo.ecm.platform.picture.ImagingComponent"
  point="pictureConversions">

  <pictureConversion id="Large" description="Large image" tag="large"
    maxSize="800" order="0" chainId="Image.Blob.Resize" />

</extension>

Noteworthy Attributes

  • maxSize: The maximum size of the width or height of the image (depending of the bigger one on the original image). Not setting the maxSize will put the original width and height as expected values. 
  • order: The order of this picture conversion in the final list of picture views, smaller first.
  • chainId: the Automation chain associated to this picture conversion. Here we use the default available chain Image.Blob.Resize that will just resize the image according to the maxSize attribute. If the chainId attribute is not filled, the original Blob will be returned and use for the generated picture view.

Notes on the chainId attribute

You can put your own chain here to do whatever you want. Just note the following:

  • The chain must take a Blob as input and return a Blob as output (this one will be saved as the generated picture view).
  • The chain takes a parameters parameter which is a map containing the expected values computed by the ImagingService (widthheightdepth and conversionFormat).
  • The picture document, if any, on which the conversion is done is stored in the Context as the pictureDocument variable.
  • The chain is run outside any Transaction / CoreSession because a conversion could be long and should be done outside any Transaction to avoid timeouts. If you need to open a CoreSession yourself, you can use the Context.RunFileOperation operation with the parameter newTx set to true to start a new Transaction, and then the Auth.LoginAs operation to open a CoreSession.

Watermarking a Picture

As a sample, let's see how we can retrieve a text to use as a watermark from the picture document.

  1. Contribute an XML extension to register a command line that will watermark the image:

    <extension
        target="org.nuxeo.ecm.platform.commandline.executor.service.CommandLineExecutorComponent"
        point="command">
      <command name="watermarkWithText" enabled="true">
        <commandLine>convert</commandLine>
        <parameterString>#{sourceFilePath}  -gravity #{gravity} -fill #{textColor} -stroke #{strokeColor} -strokewidth #{strokeWidth} -pointsize #{textSize} -annotate #{textRotation}x#{textRotation}+#{xOffset}+#{yOffset} #{textValue} #{targetFilePath}
        </parameterString>
        <installationDirective>You need to install ImageMagick.
        </installationDirective>
      </command>
    </extension>
    
  2. Contribute an XML extension to register a converter that uses our new watermarkWithText command line.

    <extension target="org.nuxeo.ecm.core.convert.service.ConversionServiceImpl"
      point="converter">
      <converter name="watermarkWithText"
        class="org.nuxeo.ecm.platform.convert.plugins.CommandLineConverter">
        <sourceMimeType>image/*</sourceMimeType>
        <parameters>
          <parameter name="CommandLineName">watermarkWithText</parameter>
        </parameters>
      </converter>
    </extension>
    

Since Nuxeo 10.10 (LTS 2019), it is required to specify the source mime-type(s) the converter can handle (all the <sourceMimeType>image/*</sourceMimeType> in the example, but you can specify more than one).
This can be disabled (not recommended) by setting the nuxeo.convert.enforceSourceMimeTypeCheck configuration parameter to false. (See this JIRA ticket for more details)

  1. Create a chain that will be used for the picture conversion, getting the text from the  pictureDocument  and call the registered watermarkWithText converter to watermark the image. Here, for the example, we watermark the title of the document on the image:

    WatermarkChain

    - Blob.RunConverter:
        converter: watermarkWithText
        parameters:
          textValue: "@{Context[\"pictureDocument\"].getPropertyValue(\"dc:title\")}"
          targetFileName: Watermarked
          gravity: SouthWest
          textColor: Red
          strokeColor: Red
          strokeWidth: "1"
          textSize: "36"
          textRotation: "0"
          xOffset: "0"
          yOffset: "0"
    

  2. Add a new picture conversion that will watermark the image:

    <extension target="org.nuxeo.ecm.platform.picture.ImagingComponent"
      point="pictureConversions">
    
      <pictureConversion id="Watermark" description="Watermarked image" tag="watermark"
        order="0" chainId="WatermarkChain" />
    
    </extension>
    

    You should end up with something like this on your instance:

    You can now click on   on the Watermark line to download the watermarked picture:

  3. If you need to open a CoreSession to retrieve a document, for instance the parent document which will hold the watermark text, you will need two chains, one opening a Transaction / CoreSession, and another one doing the watermarking.

    1. First, create a chain that will retrieve the text, and put it in the Context:

      GetWatermarkTextChain

      - Blob.Push
      - Auth.LoginAs: {}
      - Document.Fetch:
          value: "@{Context[\"pictureDocument\"].parentRef}"
      - Context.SetVar:
          name: watermarkText
          value: "@{Document[\"myparentschema:watermarkText\"]}"
      - Blob.Pop
      

    2. Now, we need the chain that will be used for the picture conversion, getting the text from the Context and call a custom operation that will watermark the image:

      WatermarkChain

      - Context.RunFileOperation:
          id: GetWatermarkText
          isolate: "false"
          newTx: "true"
          rollbackGlobalOnError: "true"
      - WatermarkOperation:
          watermarkText: "@{Context[\"watermarkText\"]}"
      

Filtering Picture Conversions

Picture conversions can be filtered so that you can choose which picture conversions should be executed on a given document. The filtering is done through standard filters we already use in the Nuxeo Platform.

In the execution context of the filters you can use on a picture conversion, you only have access to the detached document. There is no principal, currentUser or coreSession. You cannot access the Seam beans as the conversion is done in a worker.

Let's say we want to execute the previous Watermark picture conversion only on documents that have their dc:source value to MyCompany and their dc:language value not equals to english.

  1. First, contribute the filters:

    <extension target="org.nuxeo.ecm.platform.actions.ActionService"
      point="filters">
      <filter id="grantMyCompany">
        <rule grant="true">
          <condition>#{currentDocument.dc.source == "MyCompany"}</condition>
        </rule>
      </filter>
      <filter id="denyEnglish">
        <rule grant="false">
          <condition>#{currentDocument.dc.language == "english"}</condition>
        </rule>
      </filter>
    </extension>
    
  2. Then associate the filters to the picture conversion by updating the picture conversion contribution:

    <extension target="org.nuxeo.ecm.platform.picture.ImagingComponent"
      point="pictureConversions">
    
      <pictureConversion id="Watermark" description="Watermarked image" tag="watermark"
        order="0" chainId="WatermarkChain">
        <filters>
          <filter-id>grantMyCompany</filter-id>
          <filter-id>denyEnglish</filter-id>
        </filters>
      </pictureConversion>
    
    </extension>