web-dev-qa-db-fra.com

Comment étirer des images sans antialiasing

J'ai donc récemment croisé ceci: http://www.nicalis.com/index.php

Et j'étais curieux: y a-t-il moyen de faire ce genre de chose avec des images plus petites? Je veux dire, c'est du pixel art, et plutôt que d'utiliser une image avec chaque pixel quadruplé en taille, ne pourrions-nous pas les étirer avec le code? Alors j'ai commencé à essayer d'y arriver.

J'ai essayé CSS, Javascript et même HTML, mais aucun d'entre eux n'a fonctionné. Elles sont toutes très floues (comme ceci: http://jsfiddle.net/nUVJt/2/ ), ce qui m'amène à ma question: pouvez-vous étirer une image dans le navigateur sans aucun antialiasing?

Je suis ouvert à toute suggestion, qu'il s'agisse d'utiliser une toile, jQuery, CSS3 ou autre.

Merci pour l'aide!

EDIT: Il existe un meilleur moyen de le faire maintenant! Une manière un peu moins féroce! Voici la magie:

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

Et cela va arrêter l'anti-aliasing dans tous les navigateurs modernes. Cela fonctionnera même dans IE7-8, mais pas dans 9, et je ne connais aucun moyen de le faire dans 9, malheureusement (mis à part le piratage de la toile décrit ci-dessous). Ce n'est même pas drôle de voir à quel point cela se fait plus rapidement qu'avec JS. Voici plus d'informations sur ceux-ci: https://developer.mozilla.org/en-US/docs/CSS/Image-rendering

EDIT2: Comme ce n'est pas encore une spécification officielle, ce n'est pas très fiable. Chrome et FF semblent tous deux avoir cessé de le supporter depuis que j'ai écrit ce qui précède (selon cet article qui a été mentionné ci-dessous), ce qui est vraiment ennuyeux. Nous devrons probablement attendre quelques années de plus avant de pouvoir réellement commencer à utiliser cela en CSS, ce qui est vraiment regrettable.

FINAL EDIT: Il existe un moyen officiel de le faire maintenant! Il y a une nouvelle propriété appelée image-rendering. C'est dans la spécification CSS3 . Le support est très inégal pour le moment, mais Chrome vient d’ajouter un support donc nous pourrons bientôt dire image-rendering: pixelated; et cela fonctionnera à tous les endroits (les navigateurs yaayy evergreen!)

36
Timothy Miller

La documentation de Canvas ne spécifie pas explicitement une méthode de mise à l'échelle. Lors de mes propres tests, elle a en effet anti-alias l'image assez mal dans Firefox.

Le code ci-dessous copie pixel par pixel à partir d'une image source (qui doit être de la même origine ou d'un URI de données) et la redimensionne selon le facteur spécifié.

Un canevas hors écran supplémentaire (src_canvas) est requis pour recevoir l'image source d'origine. Ses données d'image sont ensuite copiées pixel par pixel dans un canevas à l'écran.

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);
        }
    }
};

Démo de travail à http://jsfiddle.net/alnitak/LwJJR/

EDITune démo plus optimale est disponible sur http://jsfiddle.net/alnitak/j8YTe/ qui utilise également un tableau de données d’image brutes pour le canevas de destination.

16
Alnitak

Je travaille pour la toile

var canvas = document.getElementById("canvas"),
    context = canvas.getContext('2d');
context.webkitImageSmoothingEnabled = context.imageSmoothingEnabled = context.mozImageSmoothingEnabled = context.oImageSmoothingEnabled = false;
3
Leonard Meagher

La seule façon dont je peux penser est via toile. Vous pouvez simplement essayer de dessiner l'image sur un canevas, puis de redimensionner le canevas (I think ) pour éviter l'anti-aliasing. Si vous le faites toujours, vous pouvez essayer de redimensionner l'image dans l'appel de dessin ou si que ne fonctionne pas, vous pouvez utiliser getImageData et putImageData pour redimensionner l'image "à la main".

mise à jour: première méthode fonctionne: http://jsfiddle.net/nUVJt/3/

1
Mark Kahn

je ne suis pas sûr mais vous pouvez peut-être utiliser imagedata. essayez cette fonction ..

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
Salt Hareket

Nan. Le navigateur le fait comme il le fait, et vous n’avez aucun contrôle sur les algorithmes de mise à l’échelle.

Cependant, je suis sûr qu'il existe une solution basée sur la toile que vous pouvez créer, mais il s'agirait probablement de copier les pixels d'une image source et de les dessiner de manière stratégique dans la toile. Ce serait délicat, mais possible (et lent).

0
Alex Wayne