diff --git a/common/source/java/ch/systemsx/cisd/common/image/IntensityRescaling.java b/common/source/java/ch/systemsx/cisd/common/image/IntensityRescaling.java
index 8b868385436490efef52472e46279dcc3ca56ae4..41c0bd9f607c3730cc0e1c58a39c6555e879408c 100644
--- a/common/source/java/ch/systemsx/cisd/common/image/IntensityRescaling.java
+++ b/common/source/java/ch/systemsx/cisd/common/image/IntensityRescaling.java
@@ -438,38 +438,11 @@ public class IntensityRescaling
      */
     public static BufferedImage rescaleIntensityLevelTo8Bits(BufferedImage image, Levels levels)
     {
-        final int width = image.getWidth();
-        final int height = image.getHeight();
-        final BufferedImage rescaledImage =
-                new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
-        WritableRaster rescaledRaster = rescaledImage.getRaster();
-
-        final float dynamicRange = 255f / (levels.maxLevel - levels.minLevel);
-
-        for (int y = 0; y < height; ++y)
-        {
-            for (int x = 0; x < width; ++x)
-            {
-                for (Channel channel : Channel.values())
-                {
-                    int originalIntensity = (image.getRGB(x, y) >> channel.getShift()) & 0xff;
-
-                    // cut all intensities above the white point
-                    int intensity = Math.min(levels.maxLevel, originalIntensity);
-                    // cut all intensities below the black point and move the origin to 0
-                    intensity = Math.max(0, intensity - levels.minLevel);
-                    // normalize to [0, 1] and rescale to 8 bits
-                    intensity = (int) (0.5 + (intensity * dynamicRange));
-
-                    rescaledRaster.setSample(x, y, channel.getBand(), intensity);
-                }
-            }
-        }
-        return rescaledImage;
+        return rescaleIntensityLevelTo8Bits(image, levels, Channel.values());
     }
 
     public static BufferedImage rescaleIntensityLevelTo8Bits(BufferedImage image, Levels levels,
-            Channel channel)
+            Channel... channels)
     {
         final int width = image.getWidth();
         final int height = image.getHeight();
@@ -477,22 +450,16 @@ public class IntensityRescaling
                 new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
         WritableRaster rescaledRaster = rescaledImage.getRaster();
 
-        final float dynamicRange = 255f / (levels.maxLevel - levels.minLevel);
-
         for (int y = 0; y < height; ++y)
         {
             for (int x = 0; x < width; ++x)
             {
-                int originalIntensity = (image.getRGB(x, y) >> channel.getShift()) & 0xff;
-
-                // cut all intensities above the white point
-                int intensity = Math.min(levels.maxLevel, originalIntensity);
-                // cut all intensities below the black point and move the origin to 0
-                intensity = Math.max(0, intensity - levels.minLevel);
-                // normalize to [0, 1] and rescale to 8 bits
-                intensity = (int) (0.5 + (intensity * dynamicRange));
-
-                rescaledRaster.setSample(x, y, channel.getBand(), intensity);
+                for (Channel channel : channels)
+                {
+                    int originalIntensity = (image.getRGB(x, y) >> channel.getShift()) & 0xff;
+                    int rescaledIntensity = rescaleIntensity(originalIntensity, levels);
+                    rescaledRaster.setSample(x, y, channel.getBand(), rescaledIntensity);
+                }
             }
         }
         return rescaledImage;
@@ -510,25 +477,26 @@ public class IntensityRescaling
         WritableRaster rescaledRaster = rescaledImage.getRaster();
 
         final int[] pixelData = image.getPixelData();
-        final float dynamicRange = 255f / (levels.maxLevel - levels.minLevel);
-
         int offset = 0;
         for (int y = 0; y < height; ++y)
         {
             for (int x = 0; x < width; ++x)
             {
                 int originalIntensity = pixelData[offset++];
-
-                // cut all intensities above the white point
-                int intensity = Math.min(levels.maxLevel, originalIntensity);
-                // cut all intensities below the black point and move the origin to 0
-                intensity = Math.max(0, intensity - levels.minLevel);
-                // normalize to [0, 1] and rescale to 8 bits
-                intensity = (int) (0.5 + (intensity * dynamicRange));
-
-                rescaledRaster.setSample(x, y, 0, intensity);
+                rescaledRaster.setSample(x, y, 0, rescaleIntensity(originalIntensity, levels));
             }
         }
         return rescaledImage;
     }
+
+    private static int rescaleIntensity(int originalIntensity, Levels levels)
+    {
+        // cut all intensities above the white point
+        int intensity = Math.min(levels.maxLevel, originalIntensity);
+        // cut all intensities below the black point and move the origin to 0
+        intensity = Math.max(0, intensity - levels.minLevel);
+        // normalize to [0, 1] and rescale to 8 bits
+        int range = levels.maxLevel - levels.minLevel;
+        return (255 * intensity + range / 2) / range;
+    }
 }
\ No newline at end of file
diff --git a/common/source/java/ch/systemsx/cisd/common/image/MixColors.java b/common/source/java/ch/systemsx/cisd/common/image/MixColors.java
index f980fca442bae1fc72084719a3f3ecdbc73c0fb1..a82b3a93204c135080b8e2a8f7e91115a2883a3a 100644
--- a/common/source/java/ch/systemsx/cisd/common/image/MixColors.java
+++ b/common/source/java/ch/systemsx/cisd/common/image/MixColors.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.common.image;
 import java.awt.Color;
 import java.awt.image.BufferedImage;
 
+import org.apache.commons.lang.time.StopWatch;
 import org.apache.log4j.Logger;
 
 import ch.systemsx.cisd.common.logging.LogCategory;
@@ -302,6 +303,8 @@ public class MixColors
     {
         assert colors.length == images.length : "number of colors and images do not match";
 
+        StopWatch stopWatch = new StopWatch();
+        stopWatch.start();
         ColorMergingAlgorithm mergeColorsAlgorithm =
                 createColorMergingAlgorithm(quadratic, saturationEnhancementFactor, images);
 
@@ -335,6 +338,7 @@ public class MixColors
                 }
             }
         }
+        operationLog.info("MIXING " + images.length + " images (" + width + "x" + height + ") took " + stopWatch);
         return new MixedImageWithWhitePoint(mixed, whitePointColor);
     }
 
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/image/IntensityRescalingTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/image/IntensityRescalingTest.java
index 19d835b3503ca1655f36b6ac6a2a38bfcbe71636..fa4eac274d610bd24a0f977502cbbeddd59c1eb6 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/image/IntensityRescalingTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/image/IntensityRescalingTest.java
@@ -18,8 +18,14 @@ package ch.systemsx.cisd.common.image;
 
 import static org.testng.AssertJUnit.assertEquals;
 
+import java.awt.Color;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+
 import org.testng.annotations.Test;
 
+import ch.systemsx.cisd.common.image.IntensityRescaling.Channel;
+import ch.systemsx.cisd.common.image.IntensityRescaling.GrayscalePixels;
 import ch.systemsx.cisd.common.image.IntensityRescaling.Levels;
 
 /**
@@ -29,7 +35,7 @@ import ch.systemsx.cisd.common.image.IntensityRescaling.Levels;
 public class IntensityRescalingTest
 {
 
-    public void testRegularCaseOfIntensityRescaling()
+    public void testComputeLevelsRegularCaseOfIntensityRescaling()
     {
         int[] histogramArray =
                 new int[]
@@ -41,7 +47,7 @@ public class IntensityRescalingTest
     }
 
     @Test
-    public void testBorderCaseOfIntensityRescaling()
+    public void testComputeLevelsBorderCaseOfIntensityRescaling()
     {
         Levels result = IntensityRescaling.computeLevels(14, new int[]
             { 1098, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 });
@@ -50,7 +56,7 @@ public class IntensityRescalingTest
     }
 
     @Test
-    public void testBorderCaseOfIntensityRescalingOtherWay()
+    public void testComputeLevelsBorderCaseOfIntensityRescalingOtherWay()
     {
         Levels result = IntensityRescaling.computeLevels(14, new int[]
             { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19876 });
@@ -59,12 +65,87 @@ public class IntensityRescalingTest
     }
 
     @Test
-    public void testAnotherBorderCase()
+    public void testComputeLevelsAnotherBorderCase()
     {
         Levels result = IntensityRescaling.computeLevels(14, new int[]
             { 19876, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 });
         assertEquals(0, result.minLevel);
         assertEquals(1, result.maxLevel);
     }
+    
+    @Test
+    public void testRescaleIntensityLevelTo8BitsForRGBExampleAndTwoColors()
+    {
+        BufferedImage image = new BufferedImage(6, 5, BufferedImage.TYPE_INT_RGB);
+        Graphics graphics = image.getGraphics();
+        graphics.setColor(Color.ORANGE);
+        graphics.fillRect(0, 0, 4, 3);
+        graphics.setColor(Color.PINK);
+        graphics.fillRect(1, 1, 4, 3);
+        
+        BufferedImage rescaledImage = IntensityRescaling.rescaleIntensityLevelTo8Bits(image, new Levels(75, 190), 
+                Channel.GREEN, Channel.BLUE);
+        
+        ImageHistogram histogram = ImageHistogram.calculateHistogram(rescaledImage);
+        
+        assertEquals("[0=30]", renderHistogram(histogram.getRedHistogram()));
+        assertEquals("[0=12, 222=12, 255=6]", renderHistogram(histogram.getGreenHistogram()));
+        assertEquals("[0=18, 222=12]", renderHistogram(histogram.getBlueHistogram()));
+    }
 
-}
+    @Test
+    public void testRescaleIntensityLevelTo8BitsForRGBExampleAndAllColors()
+    {
+        BufferedImage image = new BufferedImage(6, 5, BufferedImage.TYPE_INT_RGB);
+        Graphics graphics = image.getGraphics();
+        graphics.setColor(Color.ORANGE);
+        graphics.fillRect(0, 0, 4, 3);
+        graphics.setColor(Color.PINK);
+        graphics.fillRect(1, 1, 4, 3);
+        
+        BufferedImage rescaledImage = IntensityRescaling.rescaleIntensityLevelTo8Bits(image, new Levels(75, 190));
+        
+        ImageHistogram histogram = ImageHistogram.calculateHistogram(rescaledImage);
+        
+        assertEquals("[0=12, 255=18]", renderHistogram(histogram.getRedHistogram()));
+        assertEquals("[0=12, 222=12, 255=6]", renderHistogram(histogram.getGreenHistogram()));
+        assertEquals("[0=18, 222=12]", renderHistogram(histogram.getBlueHistogram()));
+    }
+    
+    @Test
+    public void testRescaleIntensityLevelTo8BitsForGrayExample()
+    {
+        BufferedImage image = new BufferedImage(6, 5, BufferedImage.TYPE_BYTE_GRAY);
+        Graphics graphics = image.getGraphics();
+        graphics.setColor(Color.DARK_GRAY);
+        graphics.fillRect(0, 0, 4, 3);
+        graphics.setColor(Color.LIGHT_GRAY);
+        graphics.fillRect(1, 1, 4, 3);
+        
+        BufferedImage rescaledImage = IntensityRescaling.rescaleIntensityLevelTo8Bits(
+                new GrayscalePixels(image), new Levels(75, 200));
+        
+        ImageHistogram histogram = ImageHistogram.calculateHistogram(rescaledImage);
+        
+        assertEquals("[0=18, 239=12]", renderHistogram(histogram.getRedHistogram()));
+        assertEquals("[0=18, 239=12]", renderHistogram(histogram.getGreenHistogram()));
+        assertEquals("[0=18, 239=12]", renderHistogram(histogram.getBlueHistogram()));
+    }
+    
+    private String renderHistogram(int[] histogram)
+    {
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < histogram.length; i++)
+        {
+            int value = histogram[i];
+            if (value > 0)
+            {
+                if (builder.length() > 0)
+                {
+                    builder.append(", ");
+                }
+                builder.append(i).append("=").append(value);
+            }
+        }
+        return "[" + builder.toString() + "]";
+    }}