Bug 375733: Add basic tests for PNG imgIEncoder, patch by Justin Dolske <dolske@mozilla.com>, r=sayrer, sr=pavlov
authorgavin@gavinsharp.com
Sat, 21 Apr 2007 18:30:35 -0700
changeset 700 2ffdf900c90946f4686bbbea411eb997174cca6f
parent 699 bc95101a255dce164df9dc28114ca127e05fc39c
child 701 9d86fd5901f43fda1c0ae85629286b53787d23bd
push idunknown
push userunknown
push dateunknown
reviewerssayrer, pavlov
bugs375733
milestone1.9a4pre
Bug 375733: Add basic tests for PNG imgIEncoder, patch by Justin Dolske <dolske@mozilla.com>, r=sayrer, sr=pavlov
modules/libpr0n/Makefile.in
modules/libpr0n/test/Makefile.in
modules/libpr0n/test/unit/test_encoder_png.js
--- a/modules/libpr0n/Makefile.in
+++ b/modules/libpr0n/Makefile.in
@@ -49,13 +49,17 @@ DIRS		= public src
 ifdef MOZ_IMG_DECODERS
 DIRS		+= decoders
 endif
 
 ifdef MOZ_IMG_ENCODERS
 DIRS		+= encoders
 endif
 
+ifdef ENABLE_TESTS
+DIRS  += test
+endif
+
 DIRS		+= build
 
 include $(topsrcdir)/config/rules.mk
 
 
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/test/Makefile.in
@@ -0,0 +1,55 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (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.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is Mozilla.
+# Portions created by the Initial Developer are Copyright (C) 2007
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#  Justin Dolske <dolske@mozilla.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ../../..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = modules/libpr0n/test
+
+include $(DEPTH)/config/autoconf.mk
+
+# Module name for xpcshell tests.
+MODULE		= test_libpr0n
+
+XPCSHELL_TESTS  = unit
+
+include $(topsrcdir)/config/rules.mk
+
+# Note: Invoke any additional (non-xpcshell) test programs here.
+check::
+
new file mode 100644
--- /dev/null
+++ b/modules/libpr0n/test/unit/test_encoder_png.js
@@ -0,0 +1,188 @@
+/*
+ * Test for PNG encoding in libpr0n
+ *
+ */
+
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+
+var png1A = {
+	// A 3x3 image, rows are red, green, blue.
+	// RGB format, transparency defaults.
+
+	transparency : null,
+
+	frames  : [
+		{
+			width  : 3,    height : 3,
+
+			format : Ci.imgIEncoder.INPUT_FORMAT_RGB, stride : 9,
+
+			pixels : [
+				255,0,0,  255,0,0, 255,0,0,
+				0,255,0,  0,255,0, 0,255,0,
+				0,0,255,  0,0,255, 0,0,255,
+				]
+		}
+
+		],
+	expected : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAE0lEQVQImWP8zwAFjAz/4SwYEwA2JAMBWInC2QAAAABJRU5ErkJggg=="
+};
+
+var png1B = {
+	// A 3x3 image, rows are red, green, blue.
+	// RGB format, transparency=none.
+
+	transparency : "none",
+
+	frames  : [
+		{
+			width  : 3,    height : 3,
+
+			format : Ci.imgIEncoder.INPUT_FORMAT_RGB, stride : 9,
+
+			pixels : [
+				255,0,0,  255,0,0, 255,0,0,
+				0,255,0,  0,255,0, 0,255,0,
+				0,0,255,  0,0,255, 0,0,255,
+				]
+		}
+
+		],
+	expected : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAE0lEQVQImWP8zwAFjAz/4SwYEwA2JAMBWInC2QAAAABJRU5ErkJggg=="
+};
+
+var png2A = {
+	// A 3x3 image, rows are: red, green, blue. Columns are: 0%, 33%, 66% transparent.
+
+	transparency : null,
+
+	frames  : [
+		{
+			width  : 3,    height : 3,
+
+			format : Ci.imgIEncoder.INPUT_FORMAT_RGBA, stride : 12,
+
+			pixels : [
+				255,0,0,255,  255,0,0,170, 255,0,0,85,
+				0,255,0,255,  0,255,0,170, 0,255,0,85,
+				0,0,255,255,  0,0,255,170, 0,0,255,85
+				]
+		}
+
+		],
+	expected : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAYAAABWKLW/AAAAH0lEQVQImWP8z8Dwn4GBYTUDA8NqFsb/DHDAwoDEAwCSYQVewgzM5AAAAABJRU5ErkJggg=="
+};
+
+var png2B = {
+	// A 3x3 image, rows are: red, green, blue. Coulmns are: 0%, 33%, 66% transparent,
+	// but transparency will be ignored.
+
+	transparency : "none",
+
+	frames  : [
+		{
+			width  : 3,    height : 3,
+
+			format : Ci.imgIEncoder.INPUT_FORMAT_RGBA, stride : 12,
+
+			pixels : [
+				255,0,0,255,  255,0,0,170, 255,0,0,85,
+				0,255,0,255,  0,255,0,170, 0,255,0,85,
+				0,0,255,255,  0,0,255,170, 0,0,255,85
+				]
+		}
+
+		],
+	expected : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAE0lEQVQImWP8zwAFjAz/4SwYEwA2JAMBWInC2QAAAABJRU5ErkJggg=="
+};
+
+
+// Main test entry point.
+function run_test() {
+	dump("Checking png1A...\n")
+	run_test_for(png1A);
+	dump("Checking png1B...\n")
+	run_test_for(png1B);
+	dump("Checking png2A...\n")
+	run_test_for(png2A);
+	dump("Checking png2B...\n")
+	run_test_for(png2B);
+}; 
+
+
+function run_test_for(input) {
+	var encoder, dataURL;
+
+	encoder = encodeImage(input);
+	dataURL = makeDataURL(encoder, "image/png");
+	do_check_eq(dataURL, input.expected);
+};
+
+
+function encodeImage(input) {
+	var encoder = Cc["@mozilla.org/image/encoder;2?type=image/png"].createInstance();
+	encoder.QueryInterface(Ci.imgIEncoder);
+
+	var options = "";
+	if (input.transparency) {
+		options += "transparency=" + input.transparency;
+	}
+
+	var frame = input.frames[0];
+	encoder.initFromData(frame.pixels, frame.pixels.length,
+				frame.width, frame.height, frame.stride,
+				frame.format, options);
+	return encoder;
+}
+
+
+function makeDataURL(encoder, mimetype) {
+	var rawStream = encoder.QueryInterface(Ci.nsIInputStream);
+
+	var stream = Cc["@mozilla.org/binaryinputstream;1"].createInstance();
+	stream.QueryInterface(Ci.nsIBinaryInputStream);
+
+	stream.setInputStream(rawStream);
+
+	var bytes = stream.readByteArray(stream.available()); // returns int[]
+
+	var base64String = toBase64(bytes);
+
+	return "data:" + mimetype + ";base64," + base64String;
+}
+
+/* toBase64 copied from extensions/xml-rpc/src/nsXmlRpcClient.js */
+
+/* Convert data (an array of integers) to a Base64 string. */
+const toBase64Table = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' +
+    '0123456789+/';
+const base64Pad = '=';
+function toBase64(data) {
+    var result = '';
+    var length = data.length;
+    var i;
+    // Convert every three bytes to 4 ascii characters.
+    for (i = 0; i < (length - 2); i += 3) {
+        result += toBase64Table[data[i] >> 2];
+        result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
+        result += toBase64Table[((data[i+1] & 0x0f) << 2) + (data[i+2] >> 6)];
+        result += toBase64Table[data[i+2] & 0x3f];
+    }
+
+    // Convert the remaining 1 or 2 bytes, pad out to 4 characters.
+    if (length%3) {
+        i = length - (length%3);
+        result += toBase64Table[data[i] >> 2];
+        if ((length%3) == 2) {
+            result += toBase64Table[((data[i] & 0x03) << 4) + (data[i+1] >> 4)];
+            result += toBase64Table[(data[i+1] & 0x0f) << 2];
+            result += base64Pad;
+        } else {
+            result += toBase64Table[(data[i] & 0x03) << 4];
+            result += base64Pad + base64Pad;
+        }
+    }
+
+    return result;
+}