javascript - img - Cómo estirar imágenes sin antialiasing
insert image css (5)
Así que me encontré con esto recientemente: http://www.nicalis.com/index.php
Y tenía curiosidad: ¿hay alguna manera de hacer este tipo de cosas con imágenes más pequeñas? Quiero decir, es un arte de píxeles, y en lugar de usar una imagen con cada píxel cuadruplicado de tamaño, ¿no podríamos estirarlos con el código? Así que comencé a tratar de hacerlo realidad.
Intenté CSS, Javascript e incluso HTML, ninguno funcionó. Todos se difuminan muy mal (como este: http://jsfiddle.net/nUVJt/2/ ), lo que me lleva a mi pregunta: ¿Se puede estirar una imagen en el navegador sin ningún antialiasing?
Estoy abierto a cualquier sugerencia, ya sea utilizando un lienzo, jQuery, CSS3 o lo que sea.
¡Gracias por la ayuda!
EDITAR: ¡ Hay una mejor manera de hacer esto ahora! ¡Una forma un poco menos hackosa! Aquí está la magia:
.pixelated {
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
-ms-interpolation-mode: nearest-neighbor;
image-rendering: pixelated;
}
Y eso detendrá el anti-aliasing en todos los navegadores modernos. Incluso funcionará en IE7-8, pero no en 9, y no sé de ninguna manera en 9, por desgracia (aparte del hack de lienzo que se describe a continuación). Ni siquiera es gracioso cuánto más rápido lo hace de esta manera que con JS. Aquí hay más información sobre ellos: https://developer.mozilla.org/en-US/docs/CSS/Image-rendering
EDIT2: Debido a que esta no es una especificación oficial, no es muy confiable. Chrome y FF parecen haber dejado de apoyarlo desde que escribí lo anterior (de acuerdo con este artículo que se menciona a continuación), lo que es realmente molesto. Probablemente tengamos que esperar unos años más antes de poder empezar a utilizar esto en CSS, lo cual es realmente desafortunado.
EDICIÓN FINAL: ¡ Hay una manera oficial de hacer esto ahora! Hay una nueva propiedad llamada image-rendering
. Está en la especificación CSS3 . El soporte es súper irregular en este momento, pero Chrome acaba de agregar soporte, así que en poco tiempo podremos decir image-rendering: pixelated;
y funcionará en todos los lugares (yaayy navegadores perennes!)
He conseguido que esto funcione para el lienzo
var canvas = document.getElementById("canvas"),
context = canvas.getContext(''2d'');
context.webkitImageSmoothingEnabled = context.imageSmoothingEnabled = context.mozImageSmoothingEnabled = context.oImageSmoothingEnabled = false;
La única forma en que puedo pensar es a través del lienzo. Puedes intentar simplemente dibujar la imagen en un lienzo y luego escalar el lienzo: creo que no obtendrás anti-aliasing de esta manera. Si aún lo hace, puede intentar escalar la imagen en la llamada al sorteo o si eso no funciona, puede usar getImageData
y putImageData
para escalar la imagen "a mano"
actualización: el primer método funciona: http://jsfiddle.net/nUVJt/3/
La documentación de Canvas explícitamente no especifica un método de escalado: en mis propias pruebas, sí que contraalias a la imagen bastante mal en Firefox.
El siguiente código copia píxel por píxel de una imagen de origen (que debe ser del mismo origen o de un URI de datos) y lo escala por el factor especificado.
Se necesita un lienzo adicional fuera de la pantalla ( src_canvas
) para recibir la imagen de origen original, y sus datos de imagen se copian píxel por píxel en un lienzo en pantalla.
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);
}
}
};
Demostración de trabajo en http://jsfiddle.net/alnitak/LwJJR/
EDITAR una demostración más óptima está disponible en http://jsfiddle.net/alnitak/j8YTe/ que también utiliza una matriz de datos de imágenes en bruto para el lienzo de destino.
No estoy seguro, pero tal vez puedas usar imagedata. prueba esta función ...
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);
}
Nop. El navegador lo hace, sin embargo, lo hace y no tiene control sobre los algoritmos de escala.
Sin embargo, estoy seguro de que hay una solución basada en lienzo que podría hacer, pero probablemente implicaría copiar píxeles de una imagen original y dibujarlos estratégicamente en el lienzo. Sería complicado, pero posible (y lento).