客户端 PNG 压缩使用 javascript 之类的 pngcrush?
Client PNG compression using javascript like pngcrush?
我正在开发 HTML5 个应用程序。
当用户从他们的手机上传图片时,尺寸太大。
我想像 pngcrush 方式一样将图像压缩为 PNG。
在前端(比如 javascript 库)有什么好的选择方法吗?
或者是否可以将 pngcrush 库移植到 javascript?
有一些项目似乎是基于使用 emscripten (a LLVM-to-JavaScript compiler) to actually compile the source code from pngcrush 为浏览器工作 JavaScript 的想法。
- JavaScript-Packer/PNGCrush.html - 基于 pngcrush-1.7.27
- richardassar/pngcrush.js - 基于 pngcrush-1.7.27
- pngcrush-crushed - 基于 pngcrush-1.7.58
pngcrush-1.7.27 版本是目前唯一一个似乎不会为我生成损坏图像的版本。我在这里整理了一个使用承诺的示例:http://plnkr.co/edit/iLpbOjlYiacR04oGdXSI?p=preview
这是一个基本的用法示例:
var instance = new pngcrush();
instance.exec(inputFile, function (stdoutEvent) {
console.log(stdoutEvent.data.line);
}).then(function (doneEvent) {
var outputFile = new Blob([doneEvent.data.data], { type: 'image/png' });
// do something with the outputFile
});
以下是上述plunker的pngcrush-class.js
文件内容,供参考:
(function(exports) {
var noop = function () {};
function pngcrush () {
this.callbacks = {
'error': [],
'done': [],
'start': [],
'stdout': []
};
}
pngcrush.prototype.exec = function (file, notify) {
var self = this;
if (this.execPromise) {
return this.execPromise.catch(noop).then(function () {
return self.exec(file, notify);
});
}
if (file.type !== 'image/png') {
return Promise.reject(file);
}
var promise = this.execPromise = this.readAsArrayBuffer(file).then(function (event) {
var arrayBuffer = event.target.result;
return self.initWorker().then(function (worker) {
var done = new Promise(function (resolve, reject) {
var offDone, offError, offStdout;
offDone = self.once('done', function (event) {
offError();
offStdout();
resolve(event);
});
offError = self.once('error', function (event) {
offDone();
offStdout();
reject(event);
});
offStdout = self.on('stdout', function (event) {
if (typeof notify === 'function') {
notify.call(self, event);
}
});
worker.postMessage({
'type': 'file',
'data': new Uint8Array(arrayBuffer)
});
worker.postMessage({
'type': 'command',
'command': 'go'
});
});
done.catch(noop).then(function () {
worker.terminate();
});
return done;
});
});
promise.catch(noop).then(function () {
if (promise === self.execPromise) {
delete self.execPromise;
}
});
return promise;
};
pngcrush.prototype.initWorker = function () {
var self = this;
if (this.workerPromise) {
return this.workerPromise;
}
var promise = this.workerPromise = new Promise(function (resolve, reject) {
var worker = new Worker('worker.js');
worker.onerror = function (event) {
var callbacks = [];
reject(event);
Array.prototype.push.apply(callbacks, self.callbacks.error);
while (callbacks.length) {
callbacks.shift().call(self, event);
}
};
worker.onmessage = function (event) {
if (event.data.type === 'ready') {
worker.onmessage = function (event) {
var name = event.data.type;
if (typeof self.callbacks[name] !== 'undefined') {
var callbacks = [];
Array.prototype.push.apply(callbacks, self.callbacks[name]);
while (callbacks.length) {
callbacks.shift().call(self, event);
}
}
};
resolve(worker);
}
};
});
promise.catch(noop).then(function () {
if (promise === self.workerPromise) {
delete self.workerPromise;
}
});
return promise;
};
pngcrush.prototype.on = function (name, callback) {
var self = this;
if (typeof this.callbacks[name] !== 'undefined' && typeof callback === 'function') {
this.callbacks[name].push(callback);
var off = (function () {
var ran = false;
return function () {
if (ran === true) {
return;
}
ran = true;
var idx = self.callbacks[name].lastIndexOf(callback);
if (idx !== -1) {
self.callbacks[name].splice(idx - 1, 1);
}
};
})();
return off;
}
return noop;
};
pngcrush.prototype.once = function (name, callback) {
var off = this.on(name, function () {
off();
callback.apply(this, arguments);
});
return off;
};
pngcrush.prototype.readAsArrayBuffer = function (file) {
var fileReader = new FileReader();
return new Promise(function (resolve, reject) {
fileReader.onerror = reject;
fileReader.onload = resolve;
fileReader.readAsArrayBuffer(file);
});
};
pngcrush.prototype.readAsDataURL = function (file) {
var fileReader = new FileReader();
return new Promise(function (resolve, reject) {
fileReader.onerror = reject;
fileReader.onload = resolve;
fileReader.readAsDataURL(file);
});
};
exports.pngcrush = pngcrush;
})(this);
我正在开发 HTML5 个应用程序。
当用户从他们的手机上传图片时,尺寸太大。
我想像 pngcrush 方式一样将图像压缩为 PNG。
在前端(比如 javascript 库)有什么好的选择方法吗?
或者是否可以将 pngcrush 库移植到 javascript?
有一些项目似乎是基于使用 emscripten (a LLVM-to-JavaScript compiler) to actually compile the source code from pngcrush 为浏览器工作 JavaScript 的想法。
- JavaScript-Packer/PNGCrush.html - 基于 pngcrush-1.7.27
- richardassar/pngcrush.js - 基于 pngcrush-1.7.27
- pngcrush-crushed - 基于 pngcrush-1.7.58
pngcrush-1.7.27 版本是目前唯一一个似乎不会为我生成损坏图像的版本。我在这里整理了一个使用承诺的示例:http://plnkr.co/edit/iLpbOjlYiacR04oGdXSI?p=preview
这是一个基本的用法示例:
var instance = new pngcrush();
instance.exec(inputFile, function (stdoutEvent) {
console.log(stdoutEvent.data.line);
}).then(function (doneEvent) {
var outputFile = new Blob([doneEvent.data.data], { type: 'image/png' });
// do something with the outputFile
});
以下是上述plunker的pngcrush-class.js
文件内容,供参考:
(function(exports) {
var noop = function () {};
function pngcrush () {
this.callbacks = {
'error': [],
'done': [],
'start': [],
'stdout': []
};
}
pngcrush.prototype.exec = function (file, notify) {
var self = this;
if (this.execPromise) {
return this.execPromise.catch(noop).then(function () {
return self.exec(file, notify);
});
}
if (file.type !== 'image/png') {
return Promise.reject(file);
}
var promise = this.execPromise = this.readAsArrayBuffer(file).then(function (event) {
var arrayBuffer = event.target.result;
return self.initWorker().then(function (worker) {
var done = new Promise(function (resolve, reject) {
var offDone, offError, offStdout;
offDone = self.once('done', function (event) {
offError();
offStdout();
resolve(event);
});
offError = self.once('error', function (event) {
offDone();
offStdout();
reject(event);
});
offStdout = self.on('stdout', function (event) {
if (typeof notify === 'function') {
notify.call(self, event);
}
});
worker.postMessage({
'type': 'file',
'data': new Uint8Array(arrayBuffer)
});
worker.postMessage({
'type': 'command',
'command': 'go'
});
});
done.catch(noop).then(function () {
worker.terminate();
});
return done;
});
});
promise.catch(noop).then(function () {
if (promise === self.execPromise) {
delete self.execPromise;
}
});
return promise;
};
pngcrush.prototype.initWorker = function () {
var self = this;
if (this.workerPromise) {
return this.workerPromise;
}
var promise = this.workerPromise = new Promise(function (resolve, reject) {
var worker = new Worker('worker.js');
worker.onerror = function (event) {
var callbacks = [];
reject(event);
Array.prototype.push.apply(callbacks, self.callbacks.error);
while (callbacks.length) {
callbacks.shift().call(self, event);
}
};
worker.onmessage = function (event) {
if (event.data.type === 'ready') {
worker.onmessage = function (event) {
var name = event.data.type;
if (typeof self.callbacks[name] !== 'undefined') {
var callbacks = [];
Array.prototype.push.apply(callbacks, self.callbacks[name]);
while (callbacks.length) {
callbacks.shift().call(self, event);
}
}
};
resolve(worker);
}
};
});
promise.catch(noop).then(function () {
if (promise === self.workerPromise) {
delete self.workerPromise;
}
});
return promise;
};
pngcrush.prototype.on = function (name, callback) {
var self = this;
if (typeof this.callbacks[name] !== 'undefined' && typeof callback === 'function') {
this.callbacks[name].push(callback);
var off = (function () {
var ran = false;
return function () {
if (ran === true) {
return;
}
ran = true;
var idx = self.callbacks[name].lastIndexOf(callback);
if (idx !== -1) {
self.callbacks[name].splice(idx - 1, 1);
}
};
})();
return off;
}
return noop;
};
pngcrush.prototype.once = function (name, callback) {
var off = this.on(name, function () {
off();
callback.apply(this, arguments);
});
return off;
};
pngcrush.prototype.readAsArrayBuffer = function (file) {
var fileReader = new FileReader();
return new Promise(function (resolve, reject) {
fileReader.onerror = reject;
fileReader.onload = resolve;
fileReader.readAsArrayBuffer(file);
});
};
pngcrush.prototype.readAsDataURL = function (file) {
var fileReader = new FileReader();
return new Promise(function (resolve, reject) {
fileReader.onerror = reject;
fileReader.onload = resolve;
fileReader.readAsDataURL(file);
});
};
exports.pngcrush = pngcrush;
})(this);