Изменение картинки

Множественный выбор файлов для загрузки

Чтобы позволить пользователю выбрать за один раз несколько файлов надо вставить в элемент file атрибут multiple

<input type="file" multiple>

Предварительная обработка файлов. Используем File API

После того как вы выбрали файлы в элемент file, датапикером или при помощи drag&drop у Вас есть список файлов, готовых к использованию.

//из type="file"
var filesToUpload = input.files;
//либо при помощи Drag-and-Drop
function onDrop(e) {
filesToUpload = e.dataTransfer.files;
}

Убедитесь, что эти файлы являются изображениями:

if (!file.type.match(/image.*/)) {
// этот файл не изображение
};

Показать миниатюрку/превьюшку

Есть два варианта. Вы можете использовать FileReader (из File API) или использовать метод createObjectURL().

createObjectURL()

var img = document.createElement("img");
img.src = window.URL.createObjectURL(file);

FileReader

var img = document.createElement("img");
var reader = new FileReader();
reader.onload = function(e) {img.src = e.target.result}
reader.readAsDataURL(file);

Используем Canvas

Вы можете нарисовать <img> файл на элементе <canvas> для последующей его обработки

var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

Изменение размера изображения

Люди привыкли загружать изображения прямо из своей камеры. Это дает высокое разрешение и чрезвычайно тяжелые (несколько мегабайт) файлы. В зависимости от использования вы можете изменить размер таких изображений. Фокус в том, чтобы просто иметь небольшой canvas(800 x 600, например) и нарисовать это изображение в этот canvas. Конечно, вам придется изменить размеры canvas'а, чтобы сохранить отношения сторон изображения.

var MAX_WIDTH = 800;
var MAX_HEIGHT = 600;
var width = img.width;
var height = img.height;

if (width > height) {
    if (width > MAX_WIDTH) {
    height *= MAX_WIDTH / width;
    width = MAX_WIDTH;
    }
} else {
    if (height > MAX_HEIGHT) {
    width *= MAX_HEIGHT / height;
    height = MAX_HEIGHT;
    }
}
canvas.width = width;
canvas.height = height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, width, height);

Редактирование изображения

Теперь у вас есть изображение в canvas. Теперь Ваши возможности безграничны. Допустим, вы хотите применить фильтр сепия:

var imgData = ctx.createImageData(width, height);
var data = imgData.data;
var pixels = ctx.getImageData(0, 0, width, height);
for (var i = 0, ii = pixels.data.length; i < ii; i += 4) {
    var r = pixels.data[i + 0];
    var g =pixels.data[i + 1];
    var b = this.pixels.data[i + 2];
    data[i + 0] = (r * .393) + (g *.769) + (b * .189);
    data[i + 1] = (r * .349) + (g *.686) + (b * .168)
    data[i + 2] = (r * .272) + (g *.534) + (b * .131)
    data[i + 3] = 255;
}
ctx.putImageData(imgData, 0, 0);

Загрузить с XMLHttpRequest

Теперь, когда вы загрузили изображения на клиента, в конечном итоге Вы хотите отправить их на сервер.

Как отправить canvas

Опять же, у Вас есть два варианта. Вы можете конвертировать canvas очень длинный URL или (в Firefox) создать файл из canvas.

canvas.toDataURL()
var dataurl = canvas.toDataURL("image/png");

Создайте файл из canvas

var file = canvas.mozGetAsFile("foo.png");

Неделимая загрузка

Разрешить пользователю загрузить только один файл или все файлы, в то же время.

Показать ход загрузки

Используйте событие загрузки для создания индикатора:

xhr.upload.addEventListener("progress", function(e) {
if (e.lengthComputable) {
var percentage = Math.round((e.loaded * 100) / e.total);
// do something
}, false);

Используйте FormData

Вы, наверное, вряд ли хотите просто загрузить файл (который может быть легко сделано с помощью: xhr.send (файл)), но также добавить стороннюю информацию (например, ключ и название).
В этом случае вы должны создать multipart/form-data запрос с помощью объекта FormData

var fd = new FormData();
fd.append("name", "paul");
fd.append("image", canvas.mozGetAsFile("foo.png"));
fd.append("key", "????????????");
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://your.api.com/upload.json");
xhr.send(fd);

.