Работа с изображениями на холсте - PullRequest
0 голосов
/ 11 января 2012

У меня есть несколько изображений в пределах #mycontainer, например:

<div id="mycontainer">
    <img src="http://localhost:8080/images/my-image.png" />
    …
</div>

Мне нужно конвертировать их в ч / б. Довольно распространенная задача, но я не нашел для этого решения, которое бы сработало - у меня есть проблемы с выполнением действий. Теперь у меня есть следующее:

function grayscale(src) {
    var ctx = document.createElement('canvas').getContext('2d'),
        imgObj = new Image(),
        pixels, i, n, gs, url;

    // wait until the image has been loaded
    imgObj.onload = function () {
        ctx.canvas.width = this.width;
        ctx.canvas.height = this.height;
        ctx.drawImage(this, 0, 0);
        pixels = ctx.getImageData(0, 0, this.width, this.height);
        for (i = 0, n = pixels.data.length; i < n; i += 4) {
            gs = pixels.data[i] * 0.3 + pixels.data[i+1] * 0.59 + pixels.data[i+2] * 0.11;
            pixels.data[i] = gs;   // red
            pixels.data[i+1] = gs;   // green
            pixels.data[i+2] = gs;   // blue
        }
        ctx.putImageData(pixels, 0, 0);
    };
    imgObj.src = src;
    return ctx.canvas.toDataURL('image/png');
}

Как правило, действия:

  • Я поставляю src изображения для обработки,
  • дождаться полной загрузки изображения,
  • нарисуйте изображение на холсте, преобразуйте пиксели и поместите преобразованные пиксели обратно на холст
  • тогда я хочу, чтобы URL данных результирующего изображения с холста был возвращен.

Прямо сейчас, когда в Инструментах разработчика я добавляю что-то вроде:

c = $('#mycontainer').find('img')[0];
grayscale(c.src);

Я получаю URL-адрес данных полностью прозрачного холста по умолчанию 300px x 150px, как если бы этого imgObj.onload() вообще не было в сценарии.

Кто-нибудь может указать мне на ошибку, пожалуйста?

1 Ответ

1 голос
/ 11 января 2012

Быстрый ответ: Поскольку вы используете jQuery, вы можете посмотреть на плагин jQuery desaturate , который может делать то, что вам нужно.

Более длинный ответ по отношению к вашему коду - imgObj.onload - это асинхронная функция обратного вызова, поэтому она не будет выполнена к тому времени, когда вы достигнете своего оператора return. Вам нужно будет выполнить любой код, который требует URL-адрес данных после onload внутри обратного вызова onload. Один из способов сделать это состоит в том, чтобы grayscale принял аргумент обратного вызова:

function grayscale(src, callback) {
    // ... snip ...

    // wait until the image has been loaded
    imgObj.onload = function () {
        // ... snip ...
        ctx.putImageData(pixels, 0, 0);
        // now fire the callback
        callback(ctx.canvas.toDataURL('image/png'));
    };
    imgObj.src = src;
}

c = $('#mycontainer').find('img')[0];
grayscale(c.src, function(dataUrl) {
    // further stuff with grayscale dataUrl
});
...