summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--public/js/mp/dye.js41
-rw-r--r--test/data/gradient-whitecakedye.pngbin0 -> 3953 bytes
-rw-r--r--test/data/gradient.pngbin0 -> 4615 bytes
-rw-r--r--test/mp/future.js23
4 files changed, 36 insertions, 28 deletions
diff --git a/public/js/mp/dye.js b/public/js/mp/dye.js
index 138e332..d9150e8 100644
--- a/public/js/mp/dye.js
+++ b/public/js/mp/dye.js
@@ -6,9 +6,9 @@ var mp = function(mp) {
asDyeString: asDyeString,
dyeImage: dyeImage
};
-
+
var channel = [null, "R", "G", "Y", "B", "M", "C", "W"];
-
+
/*
* Return the channel and intensity for the given RGB(A) array.
*/
@@ -29,46 +29,47 @@ var mp = function(mp) {
// Not pure
idx = 0;
} else {
+ // Either all components are the same (r == b == g), two components are 0, or two components are the same with one as 0.
idx = (r != 0) | ((g != 0) << 1) | ((b != 0) << 2);
}
return { channel: channel[idx], intensity: max };
}
-
+
/*
* Return a dye specification from a dye string.
*/
function parseDyeString(dyeString) {
var channelStrings = dyeString.split("|");
var dyeData = {};
-
+
for (var i = 0; i < channelStrings.length; i++) {
var channelStr = channelStrings[i];
if (channelStr[1] != ":" || channelStr[2] != "#") {
// TODO error
}
-
+
var channel = channelStr[0];
var parts = channelStr.substring(3).split(",");
-
+
var list = [];
-
+
for (var j = 0; j < parts.length; j++) {
list.push(mp.resource.parseColor(parts[j]));
}
-
+
dyeData[channel] = list;
}
-
+
return dyeData;
}
-
+
/*
* Return a dye string matching the given dye specification.
*/
function asDyeString(dye) {
var dyeString = "";
-
+
// skip null channel
for (var i = 1; i < channel.length; i++) {
var dyeChannel = channel[i];
@@ -76,26 +77,26 @@ var mp = function(mp) {
if (!dyeParts || dyeParts.length == 0) {
continue;
}
-
+
dyeString += dyeChannel + ":#";
-
+
for (var j = 0; j < dyeParts.length; j++) {
var color = dyeParts[j];
dyeString += color[0].toString(16) + color[1].toString(16) + color[2].toString(16) + ",";
}
-
+
dyeString = dyeString.slice(0, -1);
-
+
dyeString += "|";
}
-
+
if (dyeString.length > 0) {
dyeString = dyeString.slice(0, -1);
}
-
+
return dyeString;
}
-
+
/*
* Dye the internal image data based on the specification provided by dyeData.
* The specification can be generated from a dyeString by parseDyeString.
@@ -105,7 +106,7 @@ var mp = function(mp) {
for (var p = 0; p < imageData.length; p += 4) {
var pixel = [imageData[p], imageData[p + 1], imageData[p + 2]];
var alpha = imageData[p + 3];
-
+
// Skip fully transparent pixels
if (!alpha) {
continue;
@@ -124,7 +125,7 @@ var mp = function(mp) {
var val = intensity * dyeData[channelId].length
var i = Math.floor(val / 255);
var t = val - i * 255;
-
+
// If we exactly hit one of the palette colors, just use it
if (!t) {
--i;
diff --git a/test/data/gradient-whitecakedye.png b/test/data/gradient-whitecakedye.png
new file mode 100644
index 0000000..248e404
--- /dev/null
+++ b/test/data/gradient-whitecakedye.png
Binary files differ
diff --git a/test/data/gradient.png b/test/data/gradient.png
new file mode 100644
index 0000000..734ac7c
--- /dev/null
+++ b/test/data/gradient.png
Binary files differ
diff --git a/test/mp/future.js b/test/mp/future.js
index cf0e68a..3d47c28 100644
--- a/test/mp/future.js
+++ b/test/mp/future.js
@@ -50,6 +50,14 @@ function unshiftLoadImageBind(url, tests) {
return tests;
}
+function testDye(err, dyed, dyeable, mp) {
+ var input = dyeable.data;
+ var expected = dyed.data;
+ var actual = new Uint8ClampedArray(input);
+ mp.dye.dyeImage(actual, dyeData);
+ assertImageDataEqual(input, expected, actual, dyed.width);
+}
+
suite.addBatch({
"The manaportal dye": {
topic: load("mp/dye", "mp/resource").expression("mp").document(),
@@ -60,14 +68,13 @@ suite.addBatch({
},
"dyeImage": {
"with the big recolorable cake": unshiftLoadImageBind("test/data/bigcake.png", {
- "to the big white cake": unshiftLoadImageBind("test/data/whitecake.png", {
- "dyes correctly when given the correct dye data": function(err, whiteCake, dyeableCake, mp) {
- var input = dyeableCake.data;
- var expected = whiteCake.data;
- var actual = new Uint8ClampedArray(input);
- mp.dye.dyeImage(actual, dyeData);
- assertImageDataEqual(input, expected, actual, whiteCake.width);
- }
+ "to the big white cake dyed by TMWW": unshiftLoadImageBind("test/data/whitecake.png", {
+ "dyes correctly when given the correct dye data": testDye
+ })
+ }),
+ "with a gradient of all channels with all intensities": unshiftLoadImageBind("test/data/gradient.png", {
+ "to a gradient of all channels with all intensities dyed by TMWW with the white cake dye": unshiftLoadImageBind("test/data/gradient-whitecakedye.png", {
+ "dyes correctly when given the correct dye data": testDye
})
})
}