|
From: <svn...@os...> - 2011-12-29 11:45:42
|
Author: aaime
Date: 2011-12-29 03:45:35 -0800 (Thu, 29 Dec 2011)
New Revision: 38453
Added:
trunk/modules/library/coverage/src/test/java/org/geotools/image/ColorUtilitiesTest.java
Modified:
trunk/modules/library/coverage/src/main/java/org/geotools/resources/image/ColorUtilities.java
Log:
[GEOT-3992] Derive a new index color model from a translucent index color model and a background color
Modified: trunk/modules/library/coverage/src/main/java/org/geotools/resources/image/ColorUtilities.java
===================================================================
--- trunk/modules/library/coverage/src/main/java/org/geotools/resources/image/ColorUtilities.java 2011-12-27 10:57:10 UTC (rev 38452)
+++ trunk/modules/library/coverage/src/main/java/org/geotools/resources/image/ColorUtilities.java 2011-12-29 11:45:35 UTC (rev 38453)
@@ -17,6 +17,7 @@
package org.geotools.resources.image;
import java.awt.Color;
+import java.awt.Transparency;
import java.awt.color.ColorSpace;
import java.awt.image.ColorModel;
import java.awt.image.DataBuffer;
@@ -522,6 +523,73 @@
}
/**
+ * Applies the specified background color to an index color model, building a new index color
+ * model (or returning the same index color mode if it has no transparency at all)
+ */
+ public static IndexColorModel applyBackgroundColor(IndexColorModel icm, Color bg) {
+ int trasparentIdx = icm.getTransparentPixel();
+ if (icm.getTransparency() == Transparency.OPAQUE && trasparentIdx == -1) {
+ // no transparency at all
+ return icm;
+ }
+
+ // grab the components
+ int size = icm.getMapSize();
+ byte[] reds = new byte[size];
+ byte[] greens = new byte[size];
+ byte[] blues = new byte[size];
+ icm.getReds(reds);
+ icm.getGreens(greens);
+ icm.getBlues(blues);
+
+ // single transparent pixel? replace it
+ if (icm.getTransparency() == Transparency.OPAQUE && trasparentIdx != -1) {
+ reds[trasparentIdx] = (byte) bg.getRed();
+ greens[trasparentIdx] = (byte) bg.getGreen();
+ blues[trasparentIdx] = (byte) bg.getBlue();
+ return new IndexColorModel(icm.getPixelSize(), size, reds, greens, blues);
+ } else {
+ // grab the alpha and do the merge
+ byte[] alphas = new byte[size];
+ icm.getAlphas(alphas);
+
+ int r = bg.getRed() & 0xFF;
+ int g = bg.getGreen() & 0xFF;
+ int b = bg.getBlue() & 0xFF;
+ int a = bg.getAlpha() & 0xFF;
+ for (int i = 0; i < size; i++) {
+ int t1 = alphas[i] & 0xFF; // a1
+ float t2 = (a & 0xFF) * (1.0f - t1 / 255f); // a2 * (1 - a1 / maxValue)
+ float t3 = t1 + t2; // output alpha
+ float t4, t5;
+ if (t3 == 0.0F) {
+ t4 = 0.0F;
+ t5 = 0.0F;
+ } else {
+ t4 = t1 / t3;
+ t5 = 1.0f - t4;
+ }
+
+ int ri = reds[i] & 0xFF;
+ reds[i] = (byte) (ri * t4 + r * t5);
+ int gi = greens[i] & 0xFF;
+ greens[i] = (byte) (gi * t4 + g * t5);
+ int bi = blues[i] & 0xFF;
+ blues[i] = (byte) (bi * t4 + b * t5);
+ alphas[i] = (byte) t3;
+ }
+
+ // if the bg color had transparency we still have a translucent image, otherwise
+ // an opaque one
+ if (a < 255) {
+ return new IndexColorModel(icm.getPixelSize(), size, reds, greens, blues, alphas);
+ } else {
+ return new IndexColorModel(icm.getPixelSize(), size, reds, greens, blues);
+ }
+ }
+ }
+
+ /**
* Provide the maximum allowe value for a certain data type.
* @param dataType the data type to suggest a maximum value for.
* @return the data type maximum value for.
Added: trunk/modules/library/coverage/src/test/java/org/geotools/image/ColorUtilitiesTest.java
===================================================================
--- trunk/modules/library/coverage/src/test/java/org/geotools/image/ColorUtilitiesTest.java (rev 0)
+++ trunk/modules/library/coverage/src/test/java/org/geotools/image/ColorUtilitiesTest.java 2011-12-29 11:45:35 UTC (rev 38453)
@@ -0,0 +1,84 @@
+package org.geotools.image;
+
+import static org.junit.Assert.*;
+
+import java.awt.Color;
+import java.awt.Transparency;
+import java.awt.image.IndexColorModel;
+
+import org.geotools.resources.image.ColorUtilities;
+import org.junit.Test;
+
+public class ColorUtilitiesTest {
+
+ @Test
+ public void mergeSolidBackgroundSolidPalette() {
+ byte[] r = new byte[] {-1, 0, 0};
+ byte[] g = new byte[] {0, -1, 0};
+ byte[] b = new byte[] {0, 0, -1};
+ IndexColorModel icm = new IndexColorModel(2, 3, r, g, b);
+ IndexColorModel merged = ColorUtilities.applyBackgroundColor(icm, Color.WHITE);
+ assertFalse(merged.hasAlpha());
+ assertEquals(merged.getTransparency(), Transparency.OPAQUE);
+ byte[] mr = new byte[3];
+ byte[] mb = new byte[3];
+ byte[] mg = new byte[3];
+ merged.getReds(mr);
+ merged.getGreens(mg);
+ merged.getBlues(mb);
+ for (int i = 0; i < r.length; i++) {
+ assertEquals(r[i], mr[i]);
+ assertEquals(g[i], mg[i]);
+ assertEquals(b[i], mb[i]);
+ }
+ }
+
+ @Test
+ public void mergeSolidBackgroundTranslucentPalette() {
+ byte[] r = new byte[] {-1, 0, 0};
+ byte[] g = new byte[] {0, -1, 0};
+ byte[] b = new byte[] {0, 0, -1};
+ byte[] a = new byte[] {-128, -128, -128};
+ IndexColorModel icm = new IndexColorModel(2, 3, r, g, b, a);
+ IndexColorModel merged = ColorUtilities.applyBackgroundColor(icm, Color.WHITE);
+ assertFalse(merged.hasAlpha());
+ assertEquals(merged.getTransparency(), Transparency.OPAQUE);
+ byte[] mr = new byte[3];
+ byte[] mb = new byte[3];
+ byte[] mg = new byte[3];
+ merged.getReds(mr);
+ merged.getGreens(mg);
+ merged.getBlues(mb);
+ for (int i = 0; i < r.length; i++) {
+ assertEquals((r[i] & 0xFF) == 255 ? 255 : 126, mr[i] & 0xFF);
+ assertEquals((g[i] & 0xFF) == 255 ? 255 : 126, mg[i] & 0xFF);
+ assertEquals((b[i] & 0xFF) == 255 ? 255 : 126, mb[i] & 0xFF);
+ }
+ }
+
+ @Test
+ public void mergeTranslucentBackgroundTranslucentPalette() {
+ byte[] r = new byte[] {-1, 0, 0};
+ byte[] g = new byte[] {0, -1, 0};
+ byte[] b = new byte[] {0, 0, -1};
+ byte[] a = new byte[] {-128, -128, -128};
+ IndexColorModel icm = new IndexColorModel(2, 3, r, g, b, a);
+ IndexColorModel merged = ColorUtilities.applyBackgroundColor(icm, new Color(255, 255, 255, 128));
+ assertTrue(merged.hasAlpha());
+ assertEquals(merged.getTransparency(), Transparency.TRANSLUCENT);
+ byte[] mr = new byte[3];
+ byte[] mb = new byte[3];
+ byte[] mg = new byte[3];
+ byte[] ma = new byte[3];
+ merged.getReds(mr);
+ merged.getGreens(mg);
+ merged.getBlues(mb);
+ merged.getAlphas(ma);
+ for (int i = 0; i < r.length; i++) {
+ assertEquals((r[i] & 0xFF) == 255 ? 255 : 84, mr[i] & 0xFF);
+ assertEquals((g[i] & 0xFF) == 255 ? 255 : 84, mg[i] & 0xFF);
+ assertEquals((b[i] & 0xFF) == 255 ? 255 : 84, mb[i] & 0xFF);
+ assertEquals(191, ma[i] & 0xFF);
+ }
+ }
+}
|