Как растянуть изображения без сглаживания - PullRequest
37 голосов
/ 22 декабря 2011

Итак, я недавно столкнулся с этим: http://www.nicalis.com/index.php

И мне было любопытно: есть ли способ сделать это с меньшими изображениями? Я имею в виду, что это пиксельная графика, и вместо того, чтобы использовать изображение с размером каждого пикселя в четыре раза, не могли бы мы растянуть их с помощью кода? Поэтому я начал пытаться сделать это.

Я пробовал CSS, Javascript и даже HTML, но ни один из них не работал. Все они очень сильно размыты (например: http://jsfiddle.net/nUVJt/2/),, что подводит меня к моему вопросу: можно ли растянуть изображение в браузере без сглаживания?

Я открыт для любых предложений, будь то использование canvas, jQuery, CSS3 или что-то еще.

Спасибо за помощь!

РЕДАКТИРОВАТЬ: Есть лучший способ сделать это сейчас! Немного менее хакерский путь! Вот магия:

.pixelated {
    image-rendering: -moz-crisp-edges;
    image-rendering: -o-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
    image-rendering: pixelated;
}

И это остановит сглаживание во всех современных браузерах. Он даже будет работать в IE7-8, но не в 9, и я, к сожалению, не знаю, как это сделать в 9 (кроме взлома canvas, описанного ниже). Даже не смешно, насколько быстрее он делает это таким образом, чем с JS. Вот больше информации о них: https://developer.mozilla.org/en-US/docs/CSS/Image-rendering

EDIT2: Поскольку это еще не официальная спецификация, она не очень надежна. Chrome и FF, кажется, перестали его поддерживать с тех пор, как я написал выше (согласно этой статье , о которой упоминалось ниже), что действительно раздражает. Вероятно, нам придется подождать еще несколько лет, прежде чем мы действительно сможем начать использовать это в CSS, что очень печально.

ЗАКЛЮЧИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ: Существует официальный способ сделать это сейчас! Есть новое свойство под названием image-rendering. Это в спецификации CSS3 . Поддержка super spotty прямо сейчас, но Chrome только что добавил поддержку , так что вскоре мы сможем просто сказать image-rendering: pixelated;, и она будет работать во всех местах (yaayy evergreen браузеры!)

Ответы [ 5 ]

16 голосов
/ 22 декабря 2011

В документации Canvas явно не указан метод масштабирования - в моих собственных тестах он действительно сглаживал изображение в Firefox довольно плохо.

Приведенный ниже код копирует пиксель за пикселем из исходного изображения (которое должно быть из того же источника или из URI данных) и масштабирует его с указанным коэффициентом.

Для получения исходного исходного изображения требуется дополнительный закадровый холст (src_canvas), а затем его данные изображения попиксельно копируются в экранное полотно.

var img = new Image();
img.src = ...;
img.onload = function() {

    var scale = 8;

    var src_canvas = document.createElement('canvas');
    src_canvas.width = this.width;
    src_canvas.height = this.height;

    var src_ctx = src_canvas.getContext('2d');
    src_ctx.drawImage(this, 0, 0);
    var src_data = src_ctx.getImageData(0, 0, this.width, this.height).data;

    var dst_canvas = document.getElementById('canvas');
    dst_canvas.width = this.width * scale;
    dst_canvas.height = this.height * scale;
    var dst_ctx = dst_canvas.getContext('2d');

    var offset = 0;
    for (var y = 0; y < this.height; ++y) {
        for (var x = 0; x < this.width; ++x) {
            var r = src_data[offset++];
            var g = src_data[offset++];
            var b = src_data[offset++];
            var a = src_data[offset++] / 100.0;
            dst_ctx.fillStyle = 'rgba(' + [r, g, b, a].join(',') + ')';
            dst_ctx.fillRect(x * scale, y * scale, scale, scale);
        }
    }
};

Рабочая демонстрация на http://jsfiddle.net/alnitak/LwJJR/

РЕДАКТИРОВАТЬ более оптимальная демонстрация доступна на http://jsfiddle.net/alnitak/j8YTe/, которая также использует массив данных необработанного изображения для конечного холста.

3 голосов
/ 20 июля 2013

Я получил это, чтобы работать на холсте

var canvas = document.getElementById("canvas"),
    context = canvas.getContext('2d');
context.webkitImageSmoothingEnabled = context.imageSmoothingEnabled = context.mozImageSmoothingEnabled = context.oImageSmoothingEnabled = false;
1 голос
/ 22 декабря 2011

Единственный способ, которым я могу думать, это через холст. Вы можете просто нарисовать изображение на холсте и затем масштабировать холст - я думаю , что вы не получите сглаживание таким образом. Если вы все равно это сделаете, вы можете попробовать масштабировать изображение в вызове отрисовки или, если , что не работает, вы можете использовать getImageData и putImageData для масштабирования изображения «вручную» * 1007. *

обновление: первый метод работает: http://jsfiddle.net/nUVJt/3/

0 голосов
/ 22 декабря 2011

Я не уверен, но, возможно, вы можете использовать imagedata.попробуйте эту функцию ..

function imageToImageData(image) {
     var canvas = document.createElement("canvas");
     canvas.width = image.width;
     canvas.height = image.height;
     var ctx = canvas.getContext("2d");
     ctx.drawImage(image, 0, 0);
     return ctx.getImageData(0, 0, canvas.width, canvas.height);
}
0 голосов
/ 22 декабря 2011

Неа.Браузер делает это, как он это делает, и вы не можете контролировать алгоритмы масштабирования.

Однако я уверен, что вы можете сделать решение на основе холста, но, вероятно, оно будет включать копирование пикселей изИсходное изображение и стратегическое рисование их на холсте.Это было бы сложно, но возможно (и медленно).

...