diff options
-rw-r--r-- | public/js/mp/dye.js | 41 | ||||
-rw-r--r-- | test/data/gradient-whitecakedye.png | bin | 0 -> 3953 bytes | |||
-rw-r--r-- | test/data/gradient.png | bin | 0 -> 4615 bytes | |||
-rw-r--r-- | test/mp/future.js | 23 |
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 Binary files differnew file mode 100644 index 0000000..248e404 --- /dev/null +++ b/test/data/gradient-whitecakedye.png diff --git a/test/data/gradient.png b/test/data/gradient.png Binary files differnew file mode 100644 index 0000000..734ac7c --- /dev/null +++ b/test/data/gradient.png 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 }) }) } |