Fix big memory overhead due to Base64 encoding of images in src attribute, in jQuery mode

Fixes #161.
Each image is now converted to a Blob with a URL that is used by the img tag.
I applied the same thing for math images (Evopedia archives)
This commit is contained in:
mossroy 2016-01-09 17:49:39 +01:00
parent 21ce7b14d3
commit 428a67c410
4 changed files with 35 additions and 9 deletions

View File

@ -236,7 +236,7 @@ define(['jquery', 'title', 'archive', 'zimArchive', 'zimDirEntry', 'util', 'geom
var callbackFunction = function(data) {
ok(data && data.length > 0, "Image not empty");
// edb3069b82c68d270f6642c171cc6293.png should give a "1 1/2" formula (can be found in "Rational_number" article)
equal(data,
equal(util.uint8ArrayToBase64(data),
"iVBORw0KGgoAAAANSUhEUgAAABUAAAApBAMAAAAogX9zAAAAMFBMVEX///8AAADm5uZAQEDMzMwWFhYiIiIwMDBQUFCenp62trZiYmIMDAwEBASKiop0dHRvDVFEAAAAb0lEQVQY02NggAAmAwY4cE2AM9VNEWwG9oFhcxgKN9HJhYyCQCBApgs5jYMVYCKrGdgOwNgGDCzSMLYwA4MYjH2cgeEawjgWCQSbQwjBdpyAYMch2f4Awd7HwAVj8n1g4Iaxl+7e3Q1jXxQUlGMAAJkfGS29Qu04AAAAAElFTkSuQmCC",
"Math image corresponds to '1 1/2' png");
start();

View File

@ -974,7 +974,7 @@ define(['jquery', 'abstractBackend', 'util', 'cookies','geometry','osabstraction
if (m) {
// It's a math image (Evopedia archive)
selectedArchive.loadMathImage(m[1], function(data) {
image.attr("src", 'data:image/png;base64,' + data);
util.feedNodeWithBlob(image, 'src', data, 'image/png');
});
} else {
// It's a standard image contained in the ZIM file
@ -982,8 +982,8 @@ define(['jquery', 'abstractBackend', 'util', 'cookies','geometry','osabstraction
if (imageMatch) {
selectedArchive.getTitleByName(imageMatch[1]).then(function(title) {
selectedArchive.readBinaryFile(title, function (readableTitleName, content) {
// TODO : add the complete MIME-type of the image (as read from the ZIM file)
image.attr("src", 'data:image;base64,' + util.uint8ArrayToBase64(content));
// TODO : use the complete MIME-type of the image (as read from the ZIM file)
util.feedNodeWithBlob(image, 'src', content, 'image');
});
}).fail(function () {
console.error("could not find title for image:" + imageMatch[1]);
@ -1001,8 +1001,7 @@ define(['jquery', 'abstractBackend', 'util', 'cookies','geometry','osabstraction
var titleName = util.removeUrlParameters(hrefMatch[1]);
selectedArchive.getTitleByName(titleName).then(function(title) {
selectedArchive.readBinaryFile(title, function (readableTitleName, content) {
var cssContent = encodeURIComponent(util.uintToString(content));
link.attr("href", 'data:text/css;charset=UTF-8,' + cssContent);
util.feedNodeWithBlob(link, 'href', content, 'text/css');
});
}).fail(function () {
console.error("could not find title for CSS : " + hrefMatch[1]);

View File

@ -423,6 +423,11 @@ define(['normalize_string', 'geometry', 'title', 'util', 'titleIterators', 'q'],
* @callback callbackStringContent
* @param {String} content String content
*/
/**
* @callback callbackUint8ArrayContent
* @param {Uint8Array} content String content
*/
/**
@ -545,10 +550,10 @@ define(['normalize_string', 'geometry', 'title', 'util', 'titleIterators', 'q'],
/**
* Load the math image specified by the hex string and call the
* callbackFunction with a base64 encoding of its data.
* callbackFunction with its Uint8Array data.
*
* @param {String} hexString
* @param {callbackStringContent} callbackFunction
* @param {callbackUint8ArrayContent} callbackFunction
*/
LocalArchive.prototype.loadMathImage = function(hexString, callbackFunction) {
var entrySize = 16 + 4 + 4;
@ -566,7 +571,7 @@ define(['normalize_string', 'geometry', 'title', 'util', 'titleIterators', 'q'],
var blob = mathDataFile.slice(pos, pos + length);
reader.onload = function(e) {
var byteArray = new Uint8Array(e.target.result);
callbackFunction(util.uint8ArrayToBase64(byteArray));
callbackFunction(byteArray);
};
reader.readAsArrayBuffer(blob);
});

View File

@ -193,6 +193,27 @@ define(['q'], function(q) {
return blob;
}
/**
* Creates a Blob from the given content, then a URL from this Blob
* And put this URL in the attribute of the DOM node
*
* This is useful to inject images inside an article
*
* @param {Object} jQueryNode
* @param {String} nodeAttribute
* @param {Uint8Array} content
* @param {String} mimeType
*/
function feedNodeWithBlob(jQueryNode, nodeAttribute, content, mimeType) {
var blob = new Blob([content], {type: mimeType});
var url = URL.createObjectURL(blob);
jQueryNode.on('load', function () {
URL.revokeObjectURL(url);
});
jQueryNode.attr(nodeAttribute, url);
}
/**
* Converts a UInt Array to a UTF-8 encoded string
* source : http://michael-rushanan.blogspot.de/2014/03/javascript-uint8array-hacks-and-cheat.html
@ -231,6 +252,7 @@ define(['q'], function(q) {
readFileSlice : readFileSlice,
binarySearch: binarySearch,
b64toBlob: b64toBlob,
feedNodeWithBlob: feedNodeWithBlob,
uintToString: uintToString,
removeUrlParameters: removeUrlParameters
};