diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ColorRangeCalculator.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ColorRangeCalculator.java
new file mode 100644
index 0000000000000000000000000000000000000000..19c53444bf871fe4ae6d38bb2de44ea13c29c186
--- /dev/null
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/ColorRangeCalculator.java
@@ -0,0 +1,160 @@
+/*
+ * 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.generic.server.plugins;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import ch.systemsx.cisd.common.io.FileBasedContent;
+import ch.systemsx.cisd.openbis.dss.generic.shared.utils.ImageUtil;
+
+/**
+ * Helper methods and standalone program to calculate the range of brightness of a collection of
+ * images in grayscale.
+ * 
+ * @author Tomasz Pylak
+ */
+public class ColorRangeCalculator
+{
+    /** Describes the minimal and maximal brightness of the pixel on the image. */
+    public static class ImagePixelsRange
+    {
+        private final int min, max;
+
+        public ImagePixelsRange(int min, int max)
+        {
+            this.min = min;
+            this.max = max;
+        }
+
+        public int getMin()
+        {
+            return min;
+        }
+
+        public int getMax()
+        {
+            return max;
+        }
+
+        public ImagePixelsRange createOverlap(ImagePixelsRange rangeOrNull)
+        {
+            if (rangeOrNull == null)
+            {
+                return this;
+            }
+            int newMin = Math.min(min, rangeOrNull.getMin());
+            int newMax = Math.max(max, rangeOrNull.getMax());
+            return new ImagePixelsRange(newMin, newMax);
+        }
+
+        @Override
+        public String toString()
+        {
+            return "[" + min + ", " + max + "]";
+        }
+    }
+
+    /**
+     * We should have converted 'globalRange' to [0,255] but instead a smaller range 'imageRange'
+     * has been converted to [0,255]. We have to squeeze 'imageRange' to a smaller range [a,b] (a >=
+     * 0, b <= 255) into which it would be mapped if globalRange would be used at the beginning.
+     */
+    public static ImagePixelsRange rescaleRange(ImagePixelsRange imageRange,
+            ImagePixelsRange globalRange)
+    {
+        double globalRangeLength = globalRange.getMax() - globalRange.getMin();
+        int min = (int) (255 * (imageRange.getMin() - globalRange.getMin()) / globalRangeLength);
+        int max = (int) (255 * (imageRange.getMax() - globalRange.getMin()) / globalRangeLength);
+        return new ImagePixelsRange(min, max);
+    }
+
+    public static ImagePixelsRange calculateOverlapRange(Collection<ImagePixelsRange> ranges)
+    {
+        ImagePixelsRange globalRange = null;
+        for (ImagePixelsRange imageRange : ranges)
+        {
+            globalRange = imageRange.createOverlap(globalRange);
+        }
+        return globalRange;
+    }
+
+    public static ImagePixelsRange calculatePixelsRange(BufferedImage bufferedImage,
+            int minRescaledColor, int maxRescaledColor)
+    {
+        int minColor = maxRescaledColor;
+        int maxColor = minRescaledColor;
+        for (int x = 0; x < bufferedImage.getWidth(); x++)
+        {
+            for (int y = 0; y < bufferedImage.getHeight(); y++)
+            {
+                int dominantColorComponent = bufferedImage.getRaster().getSample(x, y, 0);
+                if (dominantColorComponent >= minRescaledColor
+                        && dominantColorComponent <= maxRescaledColor)
+                {
+                    if (dominantColorComponent > maxColor)
+                    {
+                        maxColor = dominantColorComponent;
+                    } else if (dominantColorComponent < minColor)
+                    {
+                        minColor = dominantColorComponent;
+                    }
+                }
+            }
+        }
+        return new ImagePixelsRange(minColor, maxColor);
+    }
+
+    public static ImagePixelsRange calculatePixelsRange(List<File> imageFiles)
+    {
+        Collection<ImagePixelsRange> ranges =
+                new ArrayList<ColorRangeCalculator.ImagePixelsRange>();
+        for (File imageFile : imageFiles)
+        {
+            BufferedImage image =
+                    ImageUtil.loadImage(new FileBasedContent(imageFile), null, null, null);
+            ImagePixelsRange range = calculatePixelsRange(image, 0, Integer.MAX_VALUE);
+            ranges.add(range);
+        }
+        return calculateOverlapRange(ranges);
+    }
+
+    public static void main(String[] args)
+    {
+        if (args.length == 0)
+        {
+            System.err.println("No files specified!");
+            System.exit(1);
+        }
+        List<File> imageFiles = new ArrayList<File>();
+        for (int i = 0; i < args.length; i++)
+        {
+            File imageFile = new File(args[i]);
+            if (imageFile.isFile() == false)
+            {
+                System.err.println("File does not exist: " + imageFile.getPath());
+                System.exit(1);
+            }
+            imageFiles.add(imageFile);
+        }
+        ImagePixelsRange range = calculatePixelsRange(imageFiles);
+        System.out.println(range.getMin() + " " + range.getMax());
+    }
+}
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/DynamixWellBrightnessEqualizerProcessingPlugin.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/DynamixWellBrightnessEqualizerProcessingPlugin.java
index 3c6240fe532e7bd96a4833c457c21a271795bfef..9b2692a8b7956143d1a10394d44870d1e290c023 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/DynamixWellBrightnessEqualizerProcessingPlugin.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/DynamixWellBrightnessEqualizerProcessingPlugin.java
@@ -18,7 +18,6 @@ package ch.systemsx.cisd.openbis.dss.generic.server.plugins;
 
 import java.awt.image.BufferedImage;
 import java.io.File;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -29,6 +28,7 @@ import ch.systemsx.cisd.common.io.IContent;
 import ch.systemsx.cisd.common.utilities.PropertyUtils;
 import ch.systemsx.cisd.openbis.dss.etl.IContentRepository;
 import ch.systemsx.cisd.openbis.dss.etl.dynamix.IntensityRangeReductionFactory;
+import ch.systemsx.cisd.openbis.dss.generic.server.plugins.ColorRangeCalculator.ImagePixelsRange;
 import ch.systemsx.cisd.openbis.dss.generic.shared.utils.ImageUtil;
 import ch.systemsx.cisd.openbis.plugin.screening.shared.imaging.dataaccess.ImgImageEnrichedDTO;
 
@@ -63,45 +63,6 @@ public class DynamixWellBrightnessEqualizerProcessingPlugin extends
         this.maxRescaledColor = PropertyUtils.getInt(properties, "max-color", 16384 - 1);
     }
 
-    /** Describes the minimal and maximal brightness of the pixel on the image. */
-    private static class ImagePixelsRange
-    {
-        private final int min, max;
-
-        public ImagePixelsRange(int min, int max)
-        {
-            this.min = min;
-            this.max = max;
-        }
-
-        public int getMin()
-        {
-            return min;
-        }
-
-        public int getMax()
-        {
-            return max;
-        }
-
-        public ImagePixelsRange createOverlap(ImagePixelsRange rangeOrNull)
-        {
-            if (rangeOrNull == null)
-            {
-                return this;
-            }
-            int newMin = Math.min(min, rangeOrNull.getMin());
-            int newMax = Math.max(max, rangeOrNull.getMax());
-            return new ImagePixelsRange(newMin, newMax);
-        }
-
-        @Override
-        public String toString()
-        {
-            return "[" + min + ", " + max + "]";
-        }
-    }
-
     @Override
     protected IImageTransformerFactoryProvider getTransformationProvider(
             List<ImgImageEnrichedDTO> spotImages, IContentRepository contentRepository)
@@ -115,47 +76,14 @@ public class DynamixWellBrightnessEqualizerProcessingPlugin extends
         for (ImgImageEnrichedDTO image : spotImages)
         {
             BufferedImage bufferedImage = loadImage(contentRepository, image);
-            ImagePixelsRange imageRange = calculatePixelsRange(bufferedImage);
+            ImagePixelsRange imageRange =
+                    ColorRangeCalculator.calculatePixelsRange(bufferedImage, minRescaledColor,
+                            maxRescaledColor);
             rangeMap.put(image, imageRange);
         }
         return createImageTransformerFactoryProvider(rangeMap);
     }
 
-    private static ImagePixelsRange calculateOverlapRange(Collection<ImagePixelsRange> ranges)
-    {
-        ImagePixelsRange globalRange = null;
-        for (ImagePixelsRange imageRange : ranges)
-        {
-            globalRange = imageRange.createOverlap(globalRange);
-        }
-        return globalRange;
-    }
-
-    private ImagePixelsRange calculatePixelsRange(BufferedImage bufferedImage)
-    {
-        int minColor = maxRescaledColor;
-        int maxColor = minRescaledColor;
-        for (int x = 0; x < bufferedImage.getWidth(); x++)
-        {
-            for (int y = 0; y < bufferedImage.getHeight(); y++)
-            {
-                int dominantColorComponent = bufferedImage.getRaster().getSample(x, y, 0);
-                if (dominantColorComponent >= minRescaledColor
-                        && dominantColorComponent <= maxRescaledColor)
-                {
-                    if (dominantColorComponent > maxColor)
-                    {
-                        maxColor = dominantColorComponent;
-                    } else if (dominantColorComponent < minColor)
-                    {
-                        minColor = dominantColorComponent;
-                    }
-                }
-            }
-        }
-        return new ImagePixelsRange(minColor, maxColor);
-    }
-
     // --- DynamiX specific part ----------------
 
     private static BufferedImage loadImage(IContentRepository contentRepository,
@@ -169,14 +97,16 @@ public class DynamixWellBrightnessEqualizerProcessingPlugin extends
     private static IImageTransformerFactoryProvider createImageTransformerFactoryProvider(
             final Map<ImgImageEnrichedDTO, ImagePixelsRange> rangeMap)
     {
-        final ImagePixelsRange globalRange = calculateOverlapRange(rangeMap.values());
+        final ImagePixelsRange globalRange =
+                ColorRangeCalculator.calculateOverlapRange(rangeMap.values());
         return new IImageTransformerFactoryProvider()
             {
                 public IImageTransformerFactory tryGetTransformationFactory(
                         ImgImageEnrichedDTO image)
                 {
                     ImagePixelsRange imageRange = rangeMap.get(image);
-                    ImagePixelsRange rescaledRange = rescaleRange(imageRange, globalRange);
+                    ImagePixelsRange rescaledRange =
+                            ColorRangeCalculator.rescaleRange(imageRange, globalRange);
                     operationLog.info(image.getFilePath() + " global: " + globalRange + ", local: "
                             + imageRange + ", rescaled: " + rescaledRange);
                     return new IntensityRangeReductionFactory(rescaledRange.getMin(),
@@ -184,19 +114,4 @@ public class DynamixWellBrightnessEqualizerProcessingPlugin extends
                 }
             };
     }
-
-    /**
-     * We should have converted 'globalRange' to [0,255] but instead a smaller range 'imageRange'
-     * has been converted to [0,255]. We have to squeeze 'imageRange' to a smaller range [a,b] (a >=
-     * 0, b <= 255) into which it would be mapped if globalRange would be used at the beginning.
-     */
-    private static ImagePixelsRange rescaleRange(ImagePixelsRange imageRange,
-            ImagePixelsRange globalRange)
-    {
-        double globalRangeLength = globalRange.getMax() - globalRange.getMin();
-        int min = (int) (255 * (imageRange.getMin() - globalRange.getMin()) / globalRangeLength);
-        int max = (int) (255 * (imageRange.getMax() - globalRange.getMin()) / globalRangeLength);
-        return new ImagePixelsRange(min, max);
-    }
-
 }