2013-08-31 8 views
11

Mam mały obraz, który mam renderingu na płótnie, na przykład:Zmiana rozmiaru obrazu płótno bez rozmycia to

ctx.drawImage(img, 0, 0, img.width*2, img.height*2); 

chciałbym to pokazać ostry upsized obrazu (4 identyczne pikseli dla każdego piksel obrazu). Jednak ten kod (w Chrome 29 na Macu) powoduje rozmycie obrazu. W kategoriach programu Photoshop wygląda na to, że zamiast "najbliższego najbliższego sąsiada" używa on "bumubijskiego" resamplingu.

W sytuacji, w której byłaby przydatna (np. Gra retro), czy możliwe jest uzyskanie wyraźnego, powiększonego obrazu, czy też potrzebny jest osobny plik obrazu dla każdego rozmiaru obrazu na serwerze?

+0

najlepszy sposób to zrobić, aby mieć osobne obrazy dla każdego rozmiaru (najszybsza, dobra jakość), inny sposób to mieć największy, a następnie zmienić rozmiar w podróży (minimalna ilość miejsca, dobra jakość). – slash197

+0

@ slash197 Jeśli zmniejszam, ma to samo rozmycie. – JJJollyjim

+1

to nie powinno być rozmyte, czy zachowujesz proporcje? – slash197

Odpowiedz

18

Wystarczy wyłączyć wygładzanie płótno dla zdjęć - niestety ta właściwość jest jeszcze sprzedawca prefiksem tak oto zmiany:

context.webkitImageSmoothingEnabled = false; 
context.mozImageSmoothingEnabled = false; 
context.imageSmoothingEnabled = false; /// future 

następnie narysować obraz.

Opcjonalnie dla starszych wersji i przeglądarek, które nie zostały wdrożone to jeszcze można użyć CSS zamiast:

canvas { 
    image-rendering: optimizeSpeed;    // Older versions of FF 
    image-rendering: -moz-crisp-edges;   // FF 6.0+ 
    image-rendering: -webkit-optimize-contrast; // Webkit (non standard naming) 
    image-rendering: -o-crisp-edges;   // OS X & Windows Opera (12.02+) 
    image-rendering: crisp-edges;    // Possible future browsers. 
    -ms-interpolation-mode: nearest-neighbor; // IE (non standard naming) 
} 

ONLINE TEST HERE

+1

Fantastyczne, o wiele lepsze (i bardziej eleganckie) rozwiązanie niż zmniejszanie rozmiaru dużych plików lub 'getImageData'. – JJJollyjim

+2

Nieprefiksowane 'context.imageSmoothingEnabled' działa w przeglądarce Chrome przynajmniej w wersji 33. – Luke

1

Sprawdź to skrzypce: http://jsfiddle.net/yPFjg/

Ładuje obraz na płótnie, a następnie tworzy kopię zmienionym rozmiarze i używa tego jako ikonki.

Za pomocą kilku modyfikacji można zaimplementować program ładujący obrazy, który zmienia rozmiar zdjęć w locie.

var ctx = document.getElementById('canvas1').getContext('2d'); 
var img = new Image(); 
var original = document.createElement("canvas"); 
var scaled = document.createElement("canvas"); 

img.onload = function() { 
    var oc = original.getContext('2d'); 
    var sc = scaled.getContext('2d'); 
    oc.canvas.width = oc.canvas.height = 16; 
    sc.canvas.width = sc.canvas.height = 32; 
    oc.drawImage(this, 0, 0);  
    var od = oc.getImageData(0,0,16,16); 
    var sd = sc.getImageData(0,0,32,32); 
    for (var x=0; x<32; x++) { 
     for (var y=0; y<32; y++) { 
      for (var c=0; c<4; c++) {   
       // you can improve these calculations, I let them so for clarity   
       sd.data[(y*32+x)*4+c] = od.data[((y>>1)*16+(x>>1))*4+c]; 
      } 
     } 
    } 
    sc.putImageData(sd, 0, 0); 
    ctx.drawImage(scaled, 0, 0);  
} 

img.src = document.getElementById('sprite').src; 

Kilka uwag na temat getImageData: zwraca obiekt z tablicą. Tablica ma wysokość * szerokość * 4 rozmiar. Składniki koloru są przechowywane w kolejności RGBA (czerwony, zielony, niebieski, alfa, 8 bitów na każdą wartość).

+0

To nie działa dla mnie w Firefoksie (brak błędów w konsoli JS). http://i.imgur.com/DDqlxTS.png – JJJollyjim

+0

poprawiono dla FF. Zmieniłem tworzenie obrazu (linia 2). –