2011-10-18 18 views
10

Tôi có một số JS làm cho một số thao tác với hình ảnh. Tôi muốn có đồ họa giống như pixelart, vì vậy tôi phải phóng to hình ảnh gốc trong trình chỉnh sửa đồ họa. Nhưng tôi nghĩ sẽ tốt hơn nếu bạn thực hiện tất cả các thao tác với hình ảnh nhỏ và sau đó phóng to nó bằng chức năng html5. Điều này sẽ tiết kiệm thời gian xử lý (vì bây giờ my demo (cảnh báo: tên miền có thể gây ra một số vấn đề trong công việc, v.v.) tải rất lâu trong Firefox chẳng hạn). Nhưng khi tôi cố gắng thay đổi kích thước hình ảnh, nó được lấy lại bằng phương pháp bicubically. Làm thế nào để làm cho nó thay đổi kích thước hình ảnh mà không cần resampling? Có giải pháp crossbrowser nào không?Canvas HTML5: có cách nào để thay đổi kích thước hình ảnh bằng cách "lấy lại hàng xóm gần nhất" không?

+11

Nhiều người trong chúng ta có việc làm - hãy cảnh báo người dùng ở đây về bất kỳ liên kết nào đến một thứ gì đó của NSFW như "nô lệ hậu môn". – MusiGenesis

+2

Không có gì là NSFW. Đó chỉ là máy chủ thử nghiệm của tôi với tên miền 'lạ' như vậy. – ABTOMAT

+1

Bản thân liên kết là vấn đề và rất * NSFW. – MusiGenesis

Trả lời

12
image-rendering: -webkit-optimize-contrast; /* webkit */ 
image-rendering: -moz-crisp-edges /* Firefox */ 

http://phrogz.net/tmp/canvas_image_zoom.html có thể cung cấp trường hợp dự phòng bằng canvas và getImageData. Nói tóm lại:

// Create an offscreen canvas, draw an image to it, and fetch the pixels 
var offtx = document.createElement('canvas').getContext('2d'); 
offtx.drawImage(img1,0,0); 
var imgData = offtx.getImageData(0,0,img1.width,img1.height).data; 

// Draw the zoomed-up pixels to a different canvas context 
for (var x=0;x<img1.width;++x){ 
    for (var y=0;y<img1.height;++y){ 
    // Find the starting index in the one-dimensional image data 
    var i = (y*img1.width + x)*4; 
    var r = imgData[i ]; 
    var g = imgData[i+1]; 
    var b = imgData[i+2]; 
    var a = imgData[i+3]; 
    ctx2.fillStyle = "rgba("+r+","+g+","+b+","+(a/255)+")"; 
    ctx2.fillRect(x*zoom,y*zoom,zoom,zoom); 
    } 
} 

thêm: MDN docs on image-rendering

+0

Nhận xét cho người đọc trong tương lai: Tối ưu hóa hình ảnh CSS sẽ tròn thành pixel gần nhất, có thể không phải lúc nào cũng lý tưởng cho hình ảnh của bạn. Kẻ xâm lược không gian của bạn có thể trở nên sần sùi và Mario có thể bị biến dạng. Tốt nhất để sử dụng phương pháp mã chi tiết ở trên - hoặc phóng to hình ảnh x3 của bạn để các hiệu ứng của hình ảnh hiển thị nhị thức là không thể bỏ qua. – Polyducks

0

Không có cách tích hợp sẵn. Bạn phải tự mình thực hiện với getImageData.

+0

Suy nghĩ về điều đó, nhưng nó sẽ không được rất chậm? – ABTOMAT

+0

Tóm lại, vâng. Nó sẽ rất chậm. Có một cách khác mà tôi có thể nghĩ đến liên quan đến canvas trong bộ nhớ và số lượng lớn các cuộc gọi drawImage nhưng nó có thể không nhất quán trên trình duyệt vì sự khác biệt chống răng cưa và có thể không nhanh hơn nhiều. –

0

Tôi sẽ lặp lại những gì người khác đã nói và cho bạn biết đó không phải là chức năng được tích hợp sẵn. Sau khi chạy vào cùng một vấn đề, tôi đã thực hiện một bên dưới.

Sử dụng fillRect() thay vì lặp qua từng pixel và vẽ nó. Mọi thứ đều được nhận xét để giúp bạn hiểu rõ hơn cách hoạt động của nó.

//img is the original image, scale is a multiplier. It returns the resized image. 
function Resize_Nearest_Neighbour(img, scale){ 
    //make shortcuts for image width and height 
    var w = img.width; 
    var h = img.height; 

    //--------------------------------------------------------------- 
    //draw the original image to a new canvas 
    //--------------------------------------------------------------- 

    //set up the canvas 
    var c = document.createElement("CANVAS"); 
    var ctx = c.getContext("2d"); 
    //disable antialiasing on the canvas 
    ctx.imageSmoothingEnabled = false; 
    //size the canvas to match the input image 
    c.width = w; 
    c.height = h; 
    //draw the input image 
    ctx.drawImage(img, 0, 0); 
    //get the input image as image data 
    var inputImg = ctx.getImageData(0,0,w,h); 
    //get the data array from the canvas image data 
    var data = inputImg.data; 

    //--------------------------------------------------------------- 
    //resize the canvas to our bigger output image 
    //--------------------------------------------------------------- 
    c.width = w * scale; 
    c.height = h * scale; 
    //--------------------------------------------------------------- 
    //loop through all the data, painting each pixel larger 
    //--------------------------------------------------------------- 
    for (var i = 0; i < data.length; i+=4){ 

     //find the colour of this particular pixel 
     var colour = "#"; 

     //--------------------------------------------------------------- 
     //convert the RGB numbers into a hex string. i.e. [255, 10, 100] 
     //into "FF0A64" 
     //--------------------------------------------------------------- 
     function _Dex_To_Hex(number){ 
      var out = number.toString(16); 
      if (out.length < 2){ 
       out = "0" + out; 
      } 
      return out; 
     } 
     for (var colourIndex = 0; colourIndex < 3; colourIndex++){ 
      colour += _Dex_To_Hex(data[ i+colourIndex ]); 
     } 
     //set the fill colour 
     ctx.fillStyle = colour; 

     //--------------------------------------------------------------- 
     //convert the index in the data array to x and y coordinates 
     //--------------------------------------------------------------- 
     var index = i/4; 
     var x = index % w; 
     //~~ is a faster way to do 'Math.floor' 
     var y = ~~(index/w); 
     //--------------------------------------------------------------- 
     //draw an enlarged rectangle on the enlarged canvas 
     //--------------------------------------------------------------- 
     ctx.fillRect(x*scale, y*scale, scale, scale); 
    } 

    //get the output image from the canvas 
    var output = c.toDataURL("image/png"); 
    //returns image data that can be plugged into an img tag's src 
    return output; 
} 

Dưới đây là ví dụ về việc sử dụng.

Hình ảnh của bạn sẽ xuất hiện trong HTML như thế này:

<img id="pixel-image" src="" data-src="pixel-image.png"/> 

Thẻ data-src chứa URL cho hình ảnh mà bạn muốn phóng to. Đây là thẻ dữ liệu tùy chỉnh. Mã bên dưới sẽ lấy URL hình ảnh từ thẻ dữ liệu và đặt nó qua chức năng thay đổi kích thước, trả về một hình ảnh lớn hơn (kích thước ban đầu 30x), sau đó được đưa vào thuộc tính src của thẻ img.

Hãy nhớ đặt hàm Resize_Nearest_Neighbour (ở trên) vào thẻ <script> trước khi bạn bao gồm những điều sau đây.

function Load_Image(element){ 
    var source = element.getAttribute("data-src"); 
    var img = new Image(); 

    img.addEventListener("load", function(){ 

     var bigImage = Resize_Nearest_Neighbour(this, 30); 
     element.src = bigImage; 

    }); 

    img.src = source; 
} 

Load_Image(document.getElementById("pixel-image"));