Caching webp converted
This commit is contained in:
parent
ca5fecef31
commit
27c6cb6eeb
@ -1876,13 +1876,7 @@ angular.module('myApp.directives', ['myApp.filters'])
|
|||||||
.addClass(attrs.imgClass);
|
.addClass(attrs.imgClass);
|
||||||
|
|
||||||
var setSrc = function (blob) {
|
var setSrc = function (blob) {
|
||||||
if (WebpManager.isWebpSupported()) {
|
imgElement.attr('src', FileManager.getUrl(blob));
|
||||||
imgElement.attr('src', FileManager.getUrl(blob, 'image/webp'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
FileManager.getByteArray(blob).then(function (bytes) {
|
|
||||||
imgElement.attr('src', WebpManager.getPngUrlFromData(bytes));
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
imgElement.css({
|
imgElement.css({
|
||||||
@ -1894,12 +1888,16 @@ angular.module('myApp.directives', ['myApp.filters'])
|
|||||||
height: $scope.document.thumb.height
|
height: $scope.document.thumb.height
|
||||||
});
|
});
|
||||||
|
|
||||||
var smallLocation = $scope.document.thumb.location;
|
var smallLocation = angular.copy($scope.document.thumb.location);
|
||||||
|
smallLocation.sticker = true;
|
||||||
|
|
||||||
var fullLocation = {
|
var fullLocation = {
|
||||||
_: 'inputDocumentFileLocation',
|
_: 'inputDocumentFileLocation',
|
||||||
id: $scope.document.id,
|
id: $scope.document.id,
|
||||||
access_hash: $scope.document.access_hash,
|
access_hash: $scope.document.access_hash,
|
||||||
dc_id: $scope.document.dc_id
|
dc_id: $scope.document.dc_id,
|
||||||
|
file_name: $scope.document.file_name,
|
||||||
|
sticker: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -255,7 +255,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
.factory('MtpApiFileManager', function (MtpApiManager, $q, FileManager, IdbFileStorage, TmpfsFileStorage, MemoryFileStorage) {
|
.factory('MtpApiFileManager', function (MtpApiManager, $q, FileManager, IdbFileStorage, TmpfsFileStorage, MemoryFileStorage, WebpManager) {
|
||||||
|
|
||||||
var cachedFs = false;
|
var cachedFs = false;
|
||||||
var cachedFsPromise = false;
|
var cachedFsPromise = false;
|
||||||
@ -318,17 +318,25 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
|
|||||||
return 'video' + location.id + '.mp4';
|
return 'video' + location.id + '.mp4';
|
||||||
|
|
||||||
case 'inputDocumentFileLocation':
|
case 'inputDocumentFileLocation':
|
||||||
|
var fileName = (location.file_name || '').split('.', 2);
|
||||||
|
var ext = fileName[1] || '';
|
||||||
|
if (location.sticker && !WebpManager.isWebpSupported()) {
|
||||||
|
ext += '.png';
|
||||||
|
}
|
||||||
|
if (fileName.length) {
|
||||||
|
return fileName[0] + '_' + location.id + '.' + ext;
|
||||||
|
}
|
||||||
return 'doc' + location.id;
|
return 'doc' + location.id;
|
||||||
|
|
||||||
case 'inputAudioFileLocation':
|
case 'inputAudioFileLocation':
|
||||||
return 'audio' + location.id;
|
return 'audio' + location.id;
|
||||||
}
|
|
||||||
|
|
||||||
if (!location.volume_id) {
|
default:
|
||||||
console.trace('Empty location', location);
|
if (!location.volume_id) {
|
||||||
|
console.trace('Empty location', location);
|
||||||
|
}
|
||||||
|
return location.volume_id + '_' + location.local_id + '_' + location.secret + '.jpg';
|
||||||
}
|
}
|
||||||
|
|
||||||
return location.volume_id + '_' + location.local_id + '_' + location.secret + '.jpg';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function getTempFileName(file) {
|
function getTempFileName(file) {
|
||||||
@ -374,7 +382,7 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
|
|||||||
}
|
}
|
||||||
// console.log('dload small', location);
|
// console.log('dload small', location);
|
||||||
var fileName = getFileName(location),
|
var fileName = getFileName(location),
|
||||||
mimeType = 'image/jpeg',
|
mimeType = location.sticker ? 'image/webp' : 'image/jpeg',
|
||||||
cachedPromise = cachedSavePromises[fileName] || cachedDownloadPromises[fileName];
|
cachedPromise = cachedSavePromises[fileName] || cachedDownloadPromises[fileName];
|
||||||
|
|
||||||
if (cachedPromise) {
|
if (cachedPromise) {
|
||||||
@ -403,11 +411,20 @@ angular.module('izhukov.mtproto.wrapper', ['izhukov.utils', 'izhukov.mtproto'])
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var processDownloaded = function (blob) {
|
||||||
|
if (!location.sticker || WebpManager.isWebpSupported()) {
|
||||||
|
return qSync.when(blob);
|
||||||
|
}
|
||||||
|
return WebpManager.getPngBlobFromWebp(blob);
|
||||||
|
};
|
||||||
|
|
||||||
return fileStorage.getFileWriter(fileName, mimeType).then(function (fileWriter) {
|
return fileStorage.getFileWriter(fileName, mimeType).then(function (fileWriter) {
|
||||||
return downloadPromise.then(function (result) {
|
return downloadPromise.then(function (result) {
|
||||||
return FileManager.write(fileWriter, result.bytes).then(function () {
|
return processDownloaded.then(function (proccessedResult) {
|
||||||
return cachedDownloads[fileName] = fileWriter.finalize();
|
return FileManager.write(fileWriter, proccessedResult.bytes).then(function () {
|
||||||
});
|
return cachedDownloads[fileName] = fileWriter.finalize();
|
||||||
|
});
|
||||||
|
})
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -656,6 +656,121 @@ angular.module('izhukov.utils', [])
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
||||||
|
.service('WebpManager', function (qSync, $q) {
|
||||||
|
var nativeWebpSupport = false;
|
||||||
|
|
||||||
|
var image = new Image();
|
||||||
|
image.onload = function () {
|
||||||
|
nativeWebpSupport = this.width === 2 && this.height === 1;
|
||||||
|
};
|
||||||
|
image.onerror = function () {
|
||||||
|
nativeWebpSupport = false;
|
||||||
|
};
|
||||||
|
image.src = 'data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56QAAAAA==';
|
||||||
|
|
||||||
|
var canvas, context;
|
||||||
|
|
||||||
|
function getCanvasFromWebp(data) {
|
||||||
|
var start = tsNow();
|
||||||
|
|
||||||
|
var decoder = new WebPDecoder();
|
||||||
|
|
||||||
|
var config = decoder.WebPDecoderConfig;
|
||||||
|
var buffer = config.j || config.output;
|
||||||
|
var bitstream = config.input;
|
||||||
|
|
||||||
|
if (!decoder.WebPInitDecoderConfig(config)) {
|
||||||
|
console.error('[webpjs] Library version mismatch!');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log('[webpjs] status code', decoder.VP8StatusCode);
|
||||||
|
var StatusCode = decoder.VP8StatusCode;
|
||||||
|
|
||||||
|
status = decoder.WebPGetFeatures(data, data.length, bitstream);
|
||||||
|
if (status != (StatusCode.VP8_STATUS_OK || 0)) {
|
||||||
|
console.error('[webpjs] status error', status, StatusCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
var mode = decoder.WEBP_CSP_MODE;
|
||||||
|
buffer.colorspace = mode.MODE_RGBA;
|
||||||
|
buffer.J = 4;
|
||||||
|
|
||||||
|
try {
|
||||||
|
status = decoder.WebPDecode(data, data.length, config);
|
||||||
|
} catch (e) {
|
||||||
|
status = e;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = (status == 0);
|
||||||
|
if (!ok) {
|
||||||
|
console.error('[webpjs] decoding failed', status);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log('[webpjs] decoded: ', buffer.width, buffer.height, bitstream.has_alpha, 'Now saving...');
|
||||||
|
var bitmap = buffer.c.RGBA.ma;
|
||||||
|
|
||||||
|
// console.log('[webpjs] done in ', tsNow() - start);
|
||||||
|
|
||||||
|
if (!bitmap) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var biHeight = buffer.height;
|
||||||
|
var biWidth = buffer.width;
|
||||||
|
|
||||||
|
if (!canvas || !context) {
|
||||||
|
canvas = document.createElement('canvas');
|
||||||
|
context = canvas.getContext('2d');
|
||||||
|
} else {
|
||||||
|
context.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
}
|
||||||
|
canvas.height = biHeight;
|
||||||
|
canvas.width = biWidth;
|
||||||
|
|
||||||
|
var output = context.createImageData(canvas.width, canvas.height);
|
||||||
|
var outputData = output.data;
|
||||||
|
|
||||||
|
for (var h = 0; h < biHeight; h++) {
|
||||||
|
for (var w = 0; w < biWidth; w++) {
|
||||||
|
outputData[0+w*4+(biWidth*4)*h] = bitmap[1+w*4+(biWidth*4)*h];
|
||||||
|
outputData[1+w*4+(biWidth*4)*h] = bitmap[2+w*4+(biWidth*4)*h];
|
||||||
|
outputData[2+w*4+(biWidth*4)*h] = bitmap[3+w*4+(biWidth*4)*h];
|
||||||
|
outputData[3+w*4+(biWidth*4)*h] = bitmap[0+w*4+(biWidth*4)*h];
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
context.putImageData(output, 0, 0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPngBlobFromWebp (data) {
|
||||||
|
if (!getCanvasFromWebp(data)) {
|
||||||
|
return qSync.reject({type: 'WEBP_PROCESS_FAILEd'});
|
||||||
|
}
|
||||||
|
if (canvas.toBlob === undefined) {
|
||||||
|
return dataUrlToBlob(canvas.toDataURL('image/png'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var deferred = $q.defer();
|
||||||
|
canvas.toBlob(function (blob) {
|
||||||
|
deferred.resolve(blob);
|
||||||
|
}, 'image/png');
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
isWebpSupported: function () {
|
||||||
|
return nativeWebpSupport;
|
||||||
|
},
|
||||||
|
getPngBlobFromWebp: getPngBlobFromWebp
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
.service('CryptoWorker', function ($timeout, $q) {
|
.service('CryptoWorker', function ($timeout, $q) {
|
||||||
|
|
||||||
var webWorker = false,
|
var webWorker = false,
|
||||||
|
@ -451,103 +451,3 @@ function versionCompare (ver1, ver2) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
})(window);
|
})(window);
|
||||||
|
|
||||||
|
|
||||||
(function (global) {
|
|
||||||
var nativeWebpSupport = false;
|
|
||||||
|
|
||||||
var image = new Image();
|
|
||||||
image.onload = function () {
|
|
||||||
nativeWebpSupport = this.width === 2 && this.height === 1;
|
|
||||||
};
|
|
||||||
image.onerror = function () {
|
|
||||||
nativeWebpSupport = false;
|
|
||||||
};
|
|
||||||
image.src = 'data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56QAAAAA==';
|
|
||||||
|
|
||||||
var canvas, context;
|
|
||||||
|
|
||||||
function getPngUrlFromData(data) {
|
|
||||||
var start = tsNow();
|
|
||||||
|
|
||||||
var decoder = new WebPDecoder();
|
|
||||||
|
|
||||||
var config = decoder.WebPDecoderConfig;
|
|
||||||
var buffer = config.j || config.output;
|
|
||||||
var bitstream = config.input;
|
|
||||||
|
|
||||||
if (!decoder.WebPInitDecoderConfig(config)) {
|
|
||||||
console.error('[webpjs] Library version mismatch!');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.log('[webpjs] status code', decoder.VP8StatusCode);
|
|
||||||
var StatusCode = decoder.VP8StatusCode;
|
|
||||||
|
|
||||||
status = decoder.WebPGetFeatures(data, data.length, bitstream);
|
|
||||||
if (status != (StatusCode.VP8_STATUS_OK || 0)) {
|
|
||||||
console.error('[webpjs] status error', status, StatusCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
var mode = decoder.WEBP_CSP_MODE;
|
|
||||||
buffer.colorspace = mode.MODE_RGBA;
|
|
||||||
buffer.J = 4;
|
|
||||||
|
|
||||||
try {
|
|
||||||
status = decoder.WebPDecode(data, data.length, config);
|
|
||||||
} catch (e) {
|
|
||||||
status = e;
|
|
||||||
}
|
|
||||||
|
|
||||||
ok = (status == 0);
|
|
||||||
if (!ok) {
|
|
||||||
console.error('[webpjs] decoding failed', status);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// console.log('[webpjs] decoded: ', buffer.width, buffer.height, bitstream.has_alpha, 'Now saving...');
|
|
||||||
var bitmap = buffer.c.RGBA.ma;
|
|
||||||
|
|
||||||
// console.log('[webpjs] done in ', tsNow() - start);
|
|
||||||
|
|
||||||
if (!bitmap) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
var biHeight = buffer.height;
|
|
||||||
var biWidth = buffer.width;
|
|
||||||
|
|
||||||
if (!canvas || !context) {
|
|
||||||
canvas = document.createElement('canvas');
|
|
||||||
context = canvas.getContext('2d');
|
|
||||||
} else {
|
|
||||||
context.clearRect(0, 0, canvas.width, canvas.height);
|
|
||||||
}
|
|
||||||
canvas.height = biHeight;
|
|
||||||
canvas.width = biWidth;
|
|
||||||
|
|
||||||
var output = context.createImageData(canvas.width, canvas.height);
|
|
||||||
var outputData = output.data;
|
|
||||||
|
|
||||||
for (var h = 0; h < biHeight; h++) {
|
|
||||||
for (var w = 0; w < biWidth; w++) {
|
|
||||||
outputData[0+w*4+(biWidth*4)*h] = bitmap[1+w*4+(biWidth*4)*h];
|
|
||||||
outputData[1+w*4+(biWidth*4)*h] = bitmap[2+w*4+(biWidth*4)*h];
|
|
||||||
outputData[2+w*4+(biWidth*4)*h] = bitmap[3+w*4+(biWidth*4)*h];
|
|
||||||
outputData[3+w*4+(biWidth*4)*h] = bitmap[0+w*4+(biWidth*4)*h];
|
|
||||||
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
context.putImageData(output, 0, 0);
|
|
||||||
|
|
||||||
return canvas.toDataURL('image/png');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
global.WebpManager = {
|
|
||||||
isWebpSupported: function () {
|
|
||||||
return nativeWebpSupport;
|
|
||||||
},
|
|
||||||
getPngUrlFromData: getPngUrlFromData
|
|
||||||
}
|
|
||||||
})(window);
|
|
||||||
|
@ -3445,7 +3445,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
|||||||
inputFileLocation = {
|
inputFileLocation = {
|
||||||
_: 'inputDocumentFileLocation',
|
_: 'inputDocumentFileLocation',
|
||||||
id: docID,
|
id: docID,
|
||||||
access_hash: doc.access_hash
|
access_hash: doc.access_hash,
|
||||||
|
file_name: doc.file_name
|
||||||
};
|
};
|
||||||
|
|
||||||
if (historyDoc.downloaded === undefined) {
|
if (historyDoc.downloaded === undefined) {
|
||||||
@ -3463,7 +3464,8 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
|||||||
inputFileLocation = {
|
inputFileLocation = {
|
||||||
_: 'inputDocumentFileLocation',
|
_: 'inputDocumentFileLocation',
|
||||||
id: docID,
|
id: docID,
|
||||||
access_hash: doc.access_hash
|
access_hash: doc.access_hash,
|
||||||
|
file_name: doc.file_name
|
||||||
};
|
};
|
||||||
|
|
||||||
if (historyDoc.downloaded && !toFileEntry) {
|
if (historyDoc.downloaded && !toFileEntry) {
|
||||||
@ -3783,20 +3785,13 @@ angular.module('myApp.services', ['myApp.i18n', 'izhukov.utils'])
|
|||||||
|
|
||||||
function downloadStickerThumb (docID) {
|
function downloadStickerThumb (docID) {
|
||||||
var doc = AppDocsManager.getDoc(docID);
|
var doc = AppDocsManager.getDoc(docID);
|
||||||
return MtpApiFileManager.downloadSmallFile(doc.thumb.location).then(function (blob) {
|
var thumbLocation = angular.copy(doc.thumb.location);
|
||||||
if (WebpManager.isWebpSupported()) {
|
thumbLocation.sticker = true;
|
||||||
return {
|
return MtpApiFileManager.downloadSmallFile(thumbLocation).then(function (blob) {
|
||||||
id: doc.id,
|
return {
|
||||||
src: FileManager.getUrl(blob, 'image/webp')
|
id: doc.id,
|
||||||
};
|
src: FileManager.getUrl(blob, 'image/webp')
|
||||||
}
|
};
|
||||||
|
|
||||||
return FileManager.getByteArray(blob).then(function (bytes) {
|
|
||||||
return {
|
|
||||||
id: doc.id,
|
|
||||||
src: WebpManager.getPngUrlFromData(bytes)
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user