Считываешь картинку через FileReader, потом загоняешь в канвас, делаешь нужные там тебе трансформации, потом делаем toBlob с указанием нужного тебе качества сжатия и посылаешь аяксом на сервер.
Для уменьшения размера можно пользоваться встроенном в canvas api (drawImage), однако когда я делал такую штуку, то мне не понравилось качество получаемой картинки и я написал свою реализацию уменьшения используя алгоритм Ланцоша, а чтобы не лочился браузер запихнул операцию в отдельный поток (WebWorker).
Полифил для toBlob (не во всех браузерах есть)
if (!HTMLCanvasElement.prototype.toBlob) {
var hasBlobConstructor = (function () {
try {
return Boolean(new Blob());
} catch (ignore) {
return false;
}
})();
var hasArrayBufferViewSupport = hasBlobConstructor && (function () {
try {
return new Blob([new Uint8Array(100)]).size === 100;
} catch (ignore) {
return false;
}
})();
HTMLCanvasElement.prototype.toBlob = function (callback,opt_mime,opt_quality) {
var __NEJS_THIS__ = this;
if (typeof opt_mime === "undefined") { opt_mime = 'image/png'; }
if (typeof opt_quality === "undefined") { opt_quality = 1; }
if (opt_mime === 'image/png') {
callback(this['msToBlob']());
return;
}
var byteString = atob(this.toDataURL(opt_mime, opt_quality).replace(/[^,]*,/, ''));
var buffer = new ArrayBuffer(byteString.length),
intArray = new Uint8Array(buffer);
for (var i = -1; ++i < byteString.length;) {
intArray[i] = byteString.charCodeAt(i);
}
if (hasBlobConstructor) {
callback(new Blob(
[hasArrayBufferViewSupport ? intArray : buffer],
{type: opt_mime}
));
return;
}
var builder = new window['MSBlobBuilder']();
builder['append'](buffer);
callback(builder['getBlob'](opt_mime));
}
}