diff --git a/screening/resource/test-data/ConvertToolImageTransformerTest/pond-transformed.png b/screening/resource/test-data/ConvertToolImageTransformerTest/pond-transformed.png
new file mode 100644
index 0000000000000000000000000000000000000000..6b41b07cde5e588e2bf182ee759e4d2b1967b131
Binary files /dev/null and b/screening/resource/test-data/ConvertToolImageTransformerTest/pond-transformed.png differ
diff --git a/screening/resource/test-data/ConvertToolImageTransformerTest/pond.png b/screening/resource/test-data/ConvertToolImageTransformerTest/pond.png
new file mode 100644
index 0000000000000000000000000000000000000000..21f8705bee636013b88b21ab151a1b148805039c
Binary files /dev/null and b/screening/resource/test-data/ConvertToolImageTransformerTest/pond.png differ
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbstractImageDatasetUploader.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbstractImageDatasetUploader.java
index 32d0e9b160ec38fffcf42953cefe8d3a89132fea..6bc57261a8affb2a6bc1c24a722846736619cf91 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbstractImageDatasetUploader.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbstractImageDatasetUploader.java
@@ -27,6 +27,7 @@ import java.util.Map.Entry;
 import java.util.Set;
 
 import ch.rinn.restrictions.Private;
+import ch.systemsx.cisd.base.image.IImageTransformerFactory;
 import ch.systemsx.cisd.openbis.dss.etl.ImagingDatabaseHelper.ImagingChannelsMap;
 import ch.systemsx.cisd.openbis.dss.etl.dataaccess.IImagingQueryDAO;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgAcquiredImageDTO;
@@ -55,12 +56,16 @@ abstract class AbstractImageDatasetUploader
 
         private final RelativeImageReference thumbnailPathOrNull;
 
+        private final IImageTransformerFactory imageTransformerFactoryOrNull;
+
         public AcquiredImageInStack(String channelCode, RelativeImageReference imageFilePath,
-                RelativeImageReference thumbnailPathOrNull)
+                RelativeImageReference thumbnailPathOrNull,
+                IImageTransformerFactory imageTransformerFactoryOrNull)
         {
             this.channelCode = channelCode.toUpperCase();
             this.imageFilePath = imageFilePath;
             this.thumbnailPathOrNull = thumbnailPathOrNull;
+            this.imageTransformerFactoryOrNull = imageTransformerFactoryOrNull;
         }
 
         public String getChannelCode()
@@ -77,6 +82,11 @@ abstract class AbstractImageDatasetUploader
         {
             return thumbnailPathOrNull;
         }
+
+        public IImageTransformerFactory getImageTransformerFactoryOrNull()
+        {
+            return imageTransformerFactoryOrNull;
+        }
     }
 
     protected static interface ISpotProvider
@@ -137,7 +147,7 @@ abstract class AbstractImageDatasetUploader
     private static AcquiredImageInStack makeAcquiredImageInStack(AcquiredSingleImage image)
     {
         return new AcquiredImageInStack(image.getChannelCode(), image.getImageReference(),
-                image.getThumbnailFilePathOrNull());
+                image.getThumbnailFilePathOrNull(), image.getImageTransformerFactoryOrNull());
     }
 
     private ImgChannelStackDTO makeStackDtoWithouId(AcquiredSingleImage image,
@@ -178,19 +188,22 @@ abstract class AbstractImageDatasetUploader
         List<ImgAcquiredImageDTO> acquiredImageDTOs = imagesToCreate.getAcquiredImages();
         for (AcquiredImageInStack image : images)
         {
-            long channelTechId = channelsMap.getChannelId(image.getChannelCode());
-
             ImgImageDTO imageDTO = mkImageWithIdDTO(image.getImageFilePath());
-            ImgImageDTO thumbnailDTO = tryMkImageWithIdDTO(image.getThumbnailPathOrNull());
-            Long thumbnailId = thumbnailDTO == null ? null : thumbnailDTO.getId();
-            ImgAcquiredImageDTO acquiredImage =
-                    mkAcquiredImage(stackId, channelTechId, imageDTO.getId(), thumbnailId);
-
             imageDTOs.add(imageDTO);
+
+            ImgImageDTO thumbnailDTO = tryMkImageWithIdDTO(image.getThumbnailPathOrNull());
+            Long thumbnailId = null;
             if (thumbnailDTO != null)
             {
+                thumbnailId = thumbnailDTO.getId();
                 imageDTOs.add(thumbnailDTO);
             }
+
+            long channelTechId = channelsMap.getChannelId(image.getChannelCode());
+            ImgAcquiredImageDTO acquiredImage =
+                    mkAcquiredImage(stackId, channelTechId, imageDTO.getId(), thumbnailId,
+                            image.getImageTransformerFactoryOrNull());
+
             acquiredImageDTOs.add(acquiredImage);
         }
     }
@@ -220,13 +233,14 @@ abstract class AbstractImageDatasetUploader
     }
 
     private ImgAcquiredImageDTO mkAcquiredImage(long stackId, long channelTechId, long imageId,
-            Long thumbnailId)
+            Long thumbnailId, IImageTransformerFactory transformerFactoryOrNull)
     {
         ImgAcquiredImageDTO acquiredImage = new ImgAcquiredImageDTO();
         acquiredImage.setImageId(imageId);
         acquiredImage.setThumbnailId(thumbnailId);
         acquiredImage.setChannelStackId(stackId);
         acquiredImage.setChannelId(channelTechId);
+        acquiredImage.setImageTransformerFactory(transformerFactoryOrNull);
         return acquiredImage;
     }
 
@@ -241,6 +255,7 @@ abstract class AbstractImageDatasetUploader
 
     private ImgImageDTO mkImageWithIdDTO(RelativeImageReference imageReferenceOrNull)
     {
+        
         ImgImageDTO dto =
                 new ImgImageDTO(dao.createImageId(), imageReferenceOrNull.getRelativeImagePath(),
                         imageReferenceOrNull.tryGetPage(),
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbstractImageStorageProcessor.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbstractImageStorageProcessor.java
index 299adf9efaecaa9f9aad5a68202bd34cce3d0990..087fe3425e75053c1f0d916fe0ea61366da423da 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbstractImageStorageProcessor.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AbstractImageStorageProcessor.java
@@ -32,6 +32,7 @@ import org.apache.commons.io.FilenameUtils;
 import org.apache.commons.lang.time.DurationFormatUtils;
 import org.apache.log4j.Logger;
 
+import ch.systemsx.cisd.base.image.IImageTransformerFactory;
 import ch.systemsx.cisd.bds.hcs.Geometry;
 import ch.systemsx.cisd.common.collections.CollectionUtils;
 import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
@@ -640,6 +641,8 @@ abstract class AbstractImageStorageProcessor extends AbstractStorageProcessor im
             imageStorageConfiguraton = globalImageStorageConfiguraton;
         }
 
+        setPerImageTransformationIfNeeded(images, imageStorageConfiguraton);
+
         ImageFileExtractionResult extractionResult =
                 new ImageFileExtractionResult(images, invalidFiles, imageDataSetInfo.getChannels(),
                         tileGeometry, imageStorageConfiguraton.getStoreChannelsOnExperimentLevel());
@@ -682,6 +685,20 @@ abstract class AbstractImageStorageProcessor extends AbstractStorageProcessor im
         return ColorComponent.valueOf(channelColorComponent.name());
     }
 
+    private void setPerImageTransformationIfNeeded(List<AcquiredSingleImage> images,
+            ImageStorageConfiguraton imageStorageConfiguraton)
+    {
+        if (imageStorageConfiguraton != null
+                && imageStorageConfiguraton.getImageTransformerFactory() != null)
+        {
+            IImageTransformerFactory imgTransformerFactory =
+                    imageStorageConfiguraton.getImageTransformerFactory();
+            for (AcquiredSingleImage image : images) {
+                image.setImageTransformerFactoryOrNull(imgTransformerFactory);
+            }
+        }
+    }
+
     protected IImageFileExtractor tryGetImageFileExtractor(File incomingDataSetDirectory)
     {
         return imageFileExtractorOrNull;
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AcquiredSingleImage.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AcquiredSingleImage.java
index 745daa8167c6a7257d2d8db5fa7f9385309031a4..409583834d2cb8642e8b88dd1f9561154144c7af 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AcquiredSingleImage.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/AcquiredSingleImage.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.openbis.dss.etl;
 
+import ch.systemsx.cisd.base.image.IImageTransformerFactory;
 import ch.systemsx.cisd.bds.hcs.Location;
 import ch.systemsx.cisd.common.utilities.AbstractHashable;
 
@@ -45,6 +46,8 @@ public class AcquiredSingleImage extends AbstractHashable
 
     private RelativeImageReference thumbnailFilePathOrNull;
 
+    private IImageTransformerFactory imageTransformerFactoryOrNull;
+
     public AcquiredSingleImage(Location wellLocationOrNull, Location tileLocation,
             String channelCode, Float timePointOrNull, Float depthOrNull, Integer seriesNumberOrNull,
             RelativeImageReference imageFilePath)
@@ -128,4 +131,15 @@ public class AcquiredSingleImage extends AbstractHashable
     {
         this.seriesNumberOrNull = seriesNumber;
     }
+
+    public IImageTransformerFactory getImageTransformerFactoryOrNull()
+    {
+        return imageTransformerFactoryOrNull;
+    }
+
+    public void setImageTransformerFactoryOrNull(
+            IImageTransformerFactory imageTransformerFactoryOrNull)
+    {
+        this.imageTransformerFactoryOrNull = imageTransformerFactoryOrNull;
+    }
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/ConvertToolImageTransformer.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/ConvertToolImageTransformer.java
new file mode 100644
index 0000000000000000000000000000000000000000..8454cdc84353476110201c4e89bfa04d802b4fa8
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/ConvertToolImageTransformer.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.etl.biozentrum;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+
+import org.apache.log4j.Logger;
+
+import ch.systemsx.cisd.base.exceptions.CheckedExceptionTunnel;
+import ch.systemsx.cisd.base.image.IImageTransformer;
+import ch.systemsx.cisd.base.utilities.OSUtilities;
+import ch.systemsx.cisd.common.concurrent.ConcurrencyUtilities;
+import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
+import ch.systemsx.cisd.common.logging.LogCategory;
+import ch.systemsx.cisd.common.logging.LogFactory;
+import ch.systemsx.cisd.common.process.ProcessExecutionHelper;
+import ch.systemsx.cisd.common.process.ProcessIOStrategy;
+import ch.systemsx.cisd.common.process.ProcessResult;
+import ch.systemsx.cisd.imagereaders.IImageReader;
+import ch.systemsx.cisd.imagereaders.ImageReaderConstants;
+import ch.systemsx.cisd.imagereaders.ImageReaderFactory;
+
+/**
+ * An {@link IImageTransformer} using the convert command line tool for transformations.
+ * 
+ * @author Kaloyan Enimanev
+ */
+public class ConvertToolImageTransformer implements IImageTransformer
+{
+
+    private static final String PNG = "png";
+
+    private static final File convertUtilityOrNull = OSUtilities.findExecutable("convert");
+
+    private static final Logger machineLog = LogFactory.getLogger(LogCategory.MACHINE,
+            ConvertToolImageTransformer.class);
+
+    private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
+            ConvertToolImageTransformer.class);
+
+    private final List<String> convertCliArguments;
+
+    ConvertToolImageTransformer(String arguments)
+    {
+        this.convertCliArguments = parseCommandArguments(arguments);
+    }
+
+    public BufferedImage transform(BufferedImage image)
+    {
+        File tmpFile = null;
+        try
+        {
+            // TODO KE: we should use the standard input to instead of a temporary file
+            tmpFile = createTempImageFile(image);
+            byte[] output = transform(tmpFile);
+            return toBufferedImage(output);
+        } catch (IOException ioex)
+        {
+            throw CheckedExceptionTunnel.wrapIfNecessary(ioex);
+        } finally
+        {
+            if (tmpFile != null)
+            {
+                tmpFile.delete();
+            }
+        }
+    }
+
+    private BufferedImage toBufferedImage(byte[] output) throws ConfigurationFailureException
+    {
+        IImageReader imageReader =
+                ImageReaderFactory.tryGetReader(ImageReaderConstants.IMAGEIO_LIBRARY, PNG);
+        if (imageReader == null)
+        {
+            throw new ConfigurationFailureException("No ImageIO image readers available");
+        }
+        return imageReader.readImage(output, null);
+    }
+
+    private byte[] transform(File imageFile) throws IOException
+    {
+        String filePath = imageFile.getAbsolutePath();
+
+        ProcessResult result =
+                ProcessExecutionHelper.run(getCommandLine(filePath), operationLog, machineLog,
+                        ConcurrencyUtilities.NO_TIMEOUT,
+                        ProcessIOStrategy.BINARY_DISCARD_STDERR_IO_STRATEGY, false);
+
+        if (result.isOK() == false)
+        {
+            System.err.println(result.getErrorOutput());
+            System.err.println(result.getOutput());
+            System.err.println(result.getCommandLine());
+            throw new IOException(String.format(
+                    "Error calling 'convert' for image '%s'. Exit value: %d, I/O status: %s",
+                    filePath, result.getExitValue(), result.getProcessIOResult().getStatus()));
+        } else
+        {
+            return result.getBinaryOutput();
+        }
+
+    }
+
+    private List<String> parseCommandArguments(String argsString)
+    {
+        String[] arguments = argsString.trim().split("\\s");
+        return Arrays.asList(arguments);
+    }
+
+    private List<String> getCommandLine(String filePath)
+    {
+        ArrayList<String> result = new ArrayList<String>();
+        result.add(convertUtilityOrNull.getPath());
+        result.addAll(convertCliArguments);
+        result.add(filePath);
+        result.add("png:-");
+        return result;
+    }
+
+    private File createTempImageFile(BufferedImage image) throws IOException
+    {
+        File tmpFile = File.createTempFile(getClass().getSimpleName(), PNG);
+        tmpFile.deleteOnExit();
+        ImageIO.write(image, PNG, tmpFile);
+        return tmpFile;
+    }
+
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/ConvertToolImageTransformerFactory.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/ConvertToolImageTransformerFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..8c2591ee481bbfd32f26c726ed8d4699f0862a95
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/ConvertToolImageTransformerFactory.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.etl.biozentrum;
+
+import ch.systemsx.cisd.base.image.IImageTransformer;
+import ch.systemsx.cisd.base.image.IImageTransformerFactory;
+
+/**
+ * A {@link IImageTransformerFactory} that constructs {@link ConvertToolImageTransformer} instances.
+ * 
+ * @author Kaloyan Enimanev
+ */
+public class ConvertToolImageTransformerFactory implements IImageTransformerFactory
+{
+    private static final long serialVersionUID = 1L;
+
+    private final String convertCliArguments;
+
+    public ConvertToolImageTransformerFactory(String convertCliArguments)
+    {
+        this.convertCliArguments = convertCliArguments;
+    }
+
+    public IImageTransformer createTransformer()
+    {
+        return new ConvertToolImageTransformer(convertCliArguments);
+    }
+
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java
index 417eef63693ab7f65a2bf74e5e81a8d8357eed5e..abe4e2a8a478b23454086d224e924c706c569821 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dataaccess/IImagingQueryDAO.java
@@ -60,8 +60,8 @@ public interface IImagingQueryDAO extends TransactionQuery, IImagingReadonlyQuer
             + "(?{1.id}, ?{1.filePath}, ?{1.page}, ?{1.colorComponentAsString})", batchUpdate = true)
     public void addImages(List<ImgImageDTO> images);
 
-    @Update(sql = "insert into ACQUIRED_IMAGES (IMG_ID, THUMBNAIL_ID, CHANNEL_STACK_ID, CHANNEL_ID) values "
-            + "(?{1.imageId}, ?{1.thumbnailId}, ?{1.channelStackId}, ?{1.channelId})", batchUpdate = true)
+    @Update(sql = "insert into ACQUIRED_IMAGES (IMG_ID, THUMBNAIL_ID, CHANNEL_STACK_ID, CHANNEL_ID, IMAGE_TRANSFORMER_FACTORY) values "
+            + "(?{1.imageId}, ?{1.thumbnailId}, ?{1.channelStackId}, ?{1.channelId}, ?{1.serializedImageTransformerFactory})", batchUpdate = true)
     public void addAcquiredImages(List<ImgAcquiredImageDTO> acquiredImages);
 
     // inserts
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ImageStorageConfiguraton.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ImageStorageConfiguraton.java
index 5674ac8a2762653e5166efb2ff6971140a7412be..b0d1c4a644e8bc13c362a5baec2062d098e7ae88 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ImageStorageConfiguraton.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/ImageStorageConfiguraton.java
@@ -16,6 +16,7 @@
 
 package ch.systemsx.cisd.openbis.dss.etl.dto.api.v1;
 
+import ch.systemsx.cisd.base.image.IImageTransformerFactory;
 import ch.systemsx.cisd.common.utilities.AbstractHashable;
 
 /**
@@ -38,6 +39,11 @@ public class ImageStorageConfiguraton extends AbstractHashable
     /** No preferences by default, each storage processor decides by its own if it is not set. */
     private Boolean storeChannelsOnExperimentLevelOrNull = null;
 
+    /**
+     * an image transformation to be applied before the image is stored.
+     */
+    private IImageTransformerFactory imageTransformerFactoryOrNull;
+
     /** Returns the default configuration. */
     public static ImageStorageConfiguraton createDefault()
     {
@@ -89,4 +95,17 @@ public class ImageStorageConfiguraton extends AbstractHashable
         return storeChannelsOnExperimentLevelOrNull;
     }
 
+    public IImageTransformerFactory getImageTransformerFactory()
+    {
+        return imageTransformerFactoryOrNull;
+    }
+
+    /**
+     * Allows for applying an image transformation before persisting an image in the store.
+     */
+    public void setImageTransformerFactory(IImageTransformerFactory transformerFactory)
+    {
+        this.imageTransformerFactoryOrNull = transformerFactory;
+    }
+
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java
index 221dd019dedaa820316fb591a462b582f388983a..d866e4ad55e3ba70906ebdbc4ec07975b7447c5e 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/dto/api/v1/SimpleImageDataConfig.java
@@ -18,6 +18,9 @@ package ch.systemsx.cisd.openbis.dss.etl.dto.api.v1;
 
 import java.util.List;
 
+import ch.systemsx.cisd.base.image.IImageTransformerFactory;
+import ch.systemsx.cisd.common.shared.basic.utils.StringUtils;
+import ch.systemsx.cisd.openbis.dss.etl.biozentrum.ConvertToolImageTransformerFactory;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.api.v1.dto.Geometry;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConstants;
 
@@ -110,6 +113,8 @@ abstract public class SimpleImageDataConfig
     private OriginalDataStorageFormat originalDataStorageFormat =
             OriginalDataStorageFormat.UNCHANGED;
 
+    private String convertTransformationCliArgumentsOrNull;
+
     // --- getters & setters ----------------------------------------------
 
     public ImageStorageConfiguraton getImageStorageConfiguration()
@@ -130,6 +135,13 @@ abstract public class SimpleImageDataConfig
             thumbnailsStorageFormat.setHighQuality(generateThumbnailsInHighQuality);
             imageStorageConfiguraton.setThumbnailsStorageFormat(thumbnailsStorageFormat);
         }
+        if (false == StringUtils.isBlank(convertTransformationCliArgumentsOrNull))
+        {
+            IImageTransformerFactory convertTransformerFactory =
+                    new ConvertToolImageTransformerFactory(convertTransformationCliArgumentsOrNull);
+            imageStorageConfiguraton.setImageTransformerFactory(convertTransformerFactory);
+
+        }
         return imageStorageConfiguraton;
     }
 
@@ -321,4 +333,18 @@ abstract public class SimpleImageDataConfig
         return isMeasured;
     }
 
+    public String getConvertTransformationCliArguments()
+    {
+        return convertTransformationCliArgumentsOrNull;
+    }
+
+    /**
+     * Sets parameters for the 'convert' command line tool, which will be used to apply an image
+     * transformation before persisting the images in the data store.
+     */
+    public void setConvertTransformationCliArguments(String convertTransformationCliArguments)
+    {
+        this.convertTransformationCliArgumentsOrNull = convertTransformationCliArguments;
+    }
+
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/SimpleImageDataSetRegistrator.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/SimpleImageDataSetRegistrator.java
index ca07053cf9304b6f8f1e252a1082e08fd1f00c97..f26648c429a4e0059b8435d5fecfaff4a7b3eb54 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/SimpleImageDataSetRegistrator.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/SimpleImageDataSetRegistrator.java
@@ -69,18 +69,18 @@ public class SimpleImageDataSetRegistrator
     }
 
     public static DataSetRegistrationDetails<ImageDataSetInformation> createImageDatasetDetails(
-            SimpleImageDataConfig imageDataSet, File incoming,
+            SimpleImageDataConfig simpleImageConfig, File incoming,
             IDataSetRegistrationDetailsFactory<ImageDataSetInformation> factory)
     {
-        return new SimpleImageDataSetRegistrator(imageDataSet).createImageDatasetDetails(incoming,
+        return new SimpleImageDataSetRegistrator(simpleImageConfig).createImageDatasetDetails(incoming,
                 factory);
     }
 
-    private final SimpleImageDataConfig imageDataSet;
+    private final SimpleImageDataConfig simpleImageConfig;
 
-    private SimpleImageDataSetRegistrator(SimpleImageDataConfig imageDataSet)
+    private SimpleImageDataSetRegistrator(SimpleImageDataConfig simpleImageConfig)
     {
-        this.imageDataSet = imageDataSet;
+        this.simpleImageConfig = simpleImageConfig;
     }
 
     private DataSetRegistrationDetails<ImageDataSetInformation> createImageDatasetDetails(
@@ -101,7 +101,7 @@ public class SimpleImageDataSetRegistrator
     private List<File> listImageFiles(final File incomingDirectory)
     {
         return FileOperations.getInstance().listFiles(incomingDirectory,
-                imageDataSet.getRecognizedImageExtensions(), true);
+                simpleImageConfig.getRecognizedImageExtensions(), true);
     }
 
     /**
@@ -115,7 +115,7 @@ public class SimpleImageDataSetRegistrator
         {
             String imageRelativePath =
                     FileUtilities.getRelativeFile(incomingDirectory, new File(imageFile.getPath()));
-            ImageMetadata imageTokens = imageDataSet.extractImageMetadata(imageRelativePath);
+            ImageMetadata imageTokens = simpleImageConfig.extractImageMetadata(imageRelativePath);
             imageTokens.ensureValid();
             imageTokensList.add(new ImageTokensWithPath(imageTokens, imageRelativePath));
         }
@@ -124,7 +124,7 @@ public class SimpleImageDataSetRegistrator
             throw UserFailureException.fromTemplate(
                     "Incoming directory '%s' contains no images with extensions %s!",
                     incomingDirectory.getPath(),
-                    CollectionUtils.abbreviate(imageDataSet.getRecognizedImageExtensions(), -1));
+                    CollectionUtils.abbreviate(simpleImageConfig.getRecognizedImageExtensions(), -1));
         }
         return imageTokensList;
     }
@@ -135,7 +135,7 @@ public class SimpleImageDataSetRegistrator
     protected ImageFileInfo createImageInfo(ImageTokensWithPath imageTokens, Geometry tileGeometry)
     {
         Location tileCoords =
-                imageDataSet.getTileCoordinates(imageTokens.getTileNumber(), tileGeometry);
+                simpleImageConfig.getTileCoordinates(imageTokens.getTileNumber(), tileGeometry);
         ImageFileInfo img =
                 new ImageFileInfo(imageTokens.getChannelCode(), tileCoords.getRow(),
                         tileCoords.getColumn(), imageTokens.getImagePath());
@@ -172,7 +172,7 @@ public class SimpleImageDataSetRegistrator
         List<Channel> channels = new ArrayList<Channel>();
         for (String channelCode : channelCodes)
         {
-            channels.add(imageDataSet.createChannel(channelCode));
+            channels.add(simpleImageConfig.createChannel(channelCode));
         }
         return channels;
     }
@@ -195,18 +195,18 @@ public class SimpleImageDataSetRegistrator
      */
     protected void setImageDataset(File incoming, ImageDataSetInformation dataset)
     {
-        dataset.setDatasetTypeCode(imageDataSet.getDataSetType());
-        dataset.setFileFormatCode(imageDataSet.getFileFormatType());
-        dataset.setMeasured(imageDataSet.isMeasuredData());
+        dataset.setDatasetTypeCode(simpleImageConfig.getDataSetType());
+        dataset.setFileFormatCode(simpleImageConfig.getFileFormatType());
+        dataset.setMeasured(simpleImageConfig.isMeasuredData());
 
-        String sampleCode = imageDataSet.getPlateCode();
-        String spaceCode = imageDataSet.getPlateSpace();
+        String sampleCode = simpleImageConfig.getPlateCode();
+        String spaceCode = simpleImageConfig.getPlateSpace();
         dataset.setSample(spaceCode, sampleCode);
         dataset.setMeasured(true);
 
         List<ImageTokensWithPath> imageTokensList = parseImageTokens(incoming);
         int maxTileNumber = getMaxTileNumber(imageTokensList);
-        Geometry tileGeometry = imageDataSet.getTileGeometry(imageTokensList, maxTileNumber);
+        Geometry tileGeometry = simpleImageConfig.getTileGeometry(imageTokensList, maxTileNumber);
         List<ImageFileInfo> images = createImageInfos(imageTokensList, tileGeometry);
         List<Channel> channels = getAvailableChannels(images);
 
@@ -214,16 +214,16 @@ public class SimpleImageDataSetRegistrator
         dataset.setChannels(channels);
         dataset.setTileGeometry(tileGeometry.getNumberOfRows(), tileGeometry.getNumberOfColumns());
 
-        dataset.setImageStorageConfiguraton(imageDataSet.getImageStorageConfiguration());
+        dataset.setImageStorageConfiguraton(simpleImageConfig.getImageStorageConfiguration());
     }
 
     private <T extends DataSetInformation> void setRegistrationDetails(
             DataSetRegistrationDetails<T> registrationDetails, T dataset)
     {
         registrationDetails.setDataSetInformation(dataset);
-        registrationDetails.setFileFormatType(new FileFormatType(imageDataSet.getFileFormatType()));
-        registrationDetails.setDataSetType(new DataSetType(imageDataSet.getDataSetType()));
-        registrationDetails.setMeasuredData(imageDataSet.isMeasuredData());
+        registrationDetails.setFileFormatType(new FileFormatType(simpleImageConfig.getFileFormatType()));
+        registrationDetails.setDataSetType(new DataSetType(simpleImageConfig.getDataSetType()));
+        registrationDetails.setMeasuredData(simpleImageConfig.isMeasuredData());
 
     }
 
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/AbstractImageTransformerFactoryHolder.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/AbstractImageTransformerFactoryHolder.java
index 90944b759cfc4c2f1264b2f17894502a71036896..2d23bc7066217a202068a6cc8bdbc2c564e115ae 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/AbstractImageTransformerFactoryHolder.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/AbstractImageTransformerFactoryHolder.java
@@ -1,5 +1,6 @@
 /*
  * Copyright 2010 ETH Zuerich, CISD
+
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,7 +26,7 @@ import ch.systemsx.cisd.base.image.IImageTransformerFactory;
 /**
  * @author Franz-Josef Elmer
  */
-abstract class AbstractImageTransformerFactoryHolder extends AbstractImgIdentifiable
+public abstract class AbstractImageTransformerFactoryHolder extends AbstractImgIdentifiable
 {
     @ResultColumn("IMAGE_TRANSFORMER_FACTORY")
     private byte[] serializedImageTransformerFactory;
@@ -40,7 +41,18 @@ abstract class AbstractImageTransformerFactoryHolder extends AbstractImgIdentifi
         this.serializedImageTransformerFactory = serializedImageTransformerFactory;
     }
 
-    public IImageTransformerFactory tryGetImageTransformerFactory()
+    public final void setImageTransformerFactory(IImageTransformerFactory factory)
+    {
+        if (factory != null)
+        {
+            this.serializedImageTransformerFactory = SerializationUtils.serialize(factory);
+        } else
+        {
+            this.serializedImageTransformerFactory = null;
+        }
+    }
+
+    public final IImageTransformerFactory tryGetImageTransformerFactory()
     {
         if (serializedImageTransformerFactory == null)
         {
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgAcquiredImageDTO.java b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgAcquiredImageDTO.java
index 767a3d10a70b0c31ccfc7ab5b52fbc8ffc1905e0..448fd7ead8d8663db4d1da350ccdc127ccce756d 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgAcquiredImageDTO.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/plugin/screening/shared/imaging/dataaccess/ImgAcquiredImageDTO.java
@@ -21,7 +21,7 @@ import net.lemnik.eodsql.ResultColumn;
 /**
  * @author Tomasz Pylak
  */
-public class ImgAcquiredImageDTO extends AbstractImgIdentifiable
+public class ImgAcquiredImageDTO extends AbstractImageTransformerFactoryHolder
 {
     @ResultColumn("IMG_ID")
     private long imageId;
diff --git a/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/ConvertToolImageTransformerTest.java b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/ConvertToolImageTransformerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..6104232c32139da7df2d3c53a3d1811095824422
--- /dev/null
+++ b/screening/sourceTest/java/ch/systemsx/cisd/openbis/dss/etl/biozentrum/ConvertToolImageTransformerTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2011 ETH Zuerich, CISD
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package ch.systemsx.cisd.openbis.dss.etl.biozentrum;
+
+import java.awt.image.BufferedImage;
+import java.awt.image.DataBuffer;
+import java.io.File;
+
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.base.image.IImageTransformer;
+import ch.systemsx.cisd.openbis.dss.generic.shared.utils.ImageUtil;
+
+/**
+ * @author Kaloyan Enimanev
+ */
+public class ConvertToolImageTransformerTest extends AssertJUnit
+{
+    private final String IMAGE_FOLDER = "./resource/test-data/" + getClass().getSimpleName();
+
+    private final String CONVERT_PARAMS =
+            " -contrast-stretch 0 -edge 1 -threshold 1 -transparent black ";
+
+    @Test
+    public void testTransformation()
+    {
+        BufferedImage templateImage = readImage("pond.png");
+        BufferedImage expected = readImage("pond-transformed.png");
+
+        BufferedImage transformationResult = createTransformer().transform(templateImage);
+
+        assertNotNull(transformationResult);
+        assertEqualImages(expected, transformationResult);
+
+    }
+
+    private IImageTransformer createTransformer()
+    {
+        ConvertToolImageTransformerFactory factory =
+                new ConvertToolImageTransformerFactory(CONVERT_PARAMS);
+        return factory.createTransformer();
+    }
+
+    private void assertEqualImages(BufferedImage expected, BufferedImage actual)
+    {
+        DataBuffer expectedDB = expected.getData().getDataBuffer();
+        DataBuffer actualDB = actual.getData().getDataBuffer();
+
+        String notEqualError = "Converted image not equal to expected result";
+        assertEquals(notEqualError, expectedDB.getSize(), actualDB.getSize());
+
+        for (int i = 0; i < expectedDB.getSize(); i++)
+        {
+            assertEquals(notEqualError, expectedDB.getElem(i), actualDB.getElem(i));
+
+        }
+
+    }
+
+    private BufferedImage readImage(String image)
+    {
+        File imageFile = new File(IMAGE_FOLDER, image);
+        return ImageUtil.loadImage(imageFile);
+    }
+
+}