summaryrefslogtreecommitdiffstats
path: root/image/test/unit/test_encoder_png.js
diff options
context:
space:
mode:
Diffstat (limited to 'image/test/unit/test_encoder_png.js')
-rw-r--r--image/test/unit/test_encoder_png.js263
1 files changed, 263 insertions, 0 deletions
diff --git a/image/test/unit/test_encoder_png.js b/image/test/unit/test_encoder_png.js
new file mode 100644
index 0000000000..73e91f573f
--- /dev/null
+++ b/image/test/unit/test_encoder_png.js
@@ -0,0 +1,263 @@
+/*
+ * Test for PNG encoding in ImageLib
+ *
+ */
+
+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,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAFElEQVQIW2P8zwAFjAwwJiMDjAkANiQDAUpvlioAAAAASUVORK5CYII=",
+};
+
+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,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAFElEQVQIW2P8zwAFjAwwJiMDjAkANiQDAUpvlioAAAAASUVORK5CYII=",
+};
+
+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/AAAAGUlEQVQIW2P8z8AARAyrQZgRyETiMPyHcwDKCwoAGxxLEQAAAABJRU5ErkJggg==",
+};
+
+var png2B = {
+ // A 3x3 image, rows are: red, green, blue. Columns 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,iVBORw0KGgoAAAANSUhEUgAAAAMAAAADCAIAAADZSiLoAAAAFElEQVQIW2P8zwAFjAwwJiMDjAkANiQDAUpvlioAAAAASUVORK5CYII=",
+};
+
+// 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");
+ Assert.equal(dataURL, input.expected);
+
+ encoder = encodeImageAsync(input);
+ dataURL = makeDataURLFromAsync(encoder, "image/png", 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 _encodeImageAsyncFactory(frame, options, encoder) {
+ function finishEncode() {
+ encoder.addImageFrame(
+ frame.pixels,
+ frame.pixels.length,
+ frame.width,
+ frame.height,
+ frame.stride,
+ frame.format,
+ options
+ );
+ encoder.endImageEncode();
+ }
+ return finishEncode;
+}
+
+function encodeImageAsync(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.startImageEncode(frame.width, frame.height, frame.format, options);
+
+ do_timeout(50, _encodeImageAsyncFactory(frame, options, encoder));
+ 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;
+}
+
+function makeDataURLFromAsync(encoder, mimetype, expected) {
+ do_test_pending();
+ var rawStream = encoder.QueryInterface(Ci.nsIAsyncInputStream);
+
+ var currentThread =
+ Cc["@mozilla.org/thread-manager;1"].getService().currentThread;
+
+ var bytes = [];
+
+ var binarystream = Cc["@mozilla.org/binaryinputstream;1"].createInstance();
+ binarystream.QueryInterface(Ci.nsIBinaryInputStream);
+
+ var asyncReader = {
+ onInputStreamReady(stream) {
+ binarystream.setInputStream(stream);
+ var available = 0;
+ try {
+ available = stream.available();
+ } catch (e) {}
+
+ if (available > 0) {
+ bytes = bytes.concat(binarystream.readByteArray(available));
+ stream.asyncWait(this, 0, 0, currentThread);
+ } else {
+ var base64String = toBase64(bytes);
+ var dataURL = "data:" + mimetype + ";base64," + base64String;
+ Assert.equal(dataURL, expected);
+ do_test_finished();
+ }
+ },
+ };
+ rawStream.asyncWait(asyncReader, 0, 0, currentThread);
+}
+
+/* toBase64 copied from extensions/xml-rpc/src/nsXmlRpcClient.js */
+
+/* Convert data (an array of integers) to a Base64 string. */
+const toBase64Table =
+ // eslint-disable-next-line no-useless-concat
+ "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;
+}