2011-04-08 27 views
5

我目前正在開發一個mozilla擴展,試圖加載一個用數據URI編碼的圖像(PNG),在畫布元素上繪製它,最終改變一些像素值並將其保存爲磁盤上的文件。javascript canvas.toDataURL與原始數據URI相比的變化

我注意到的奇怪之處在於,即使我不更改圖像上的任何內容,並且只是在畫布上繪製圖像並使用canvas.toDataURL()查看生成的內容,但此編碼數據不同從原來的。

我使用的是看這是非常基本的代碼:

var image = new Image(); 
image.onload = function() { 
    var canvas = document.createElement('canvas') 
    canvas.width = image.width; 
    canvas.height = image.height; 
    canvas.getContext('2d').drawImage(image, 0, 0); 
    var data = canvas.toDataURL(); // this right here is different from image.scr data! 
} 
image.src = "data:image/png;base64," + encodedData; 

我假設有某種壓縮或可能是一些涉及到透明膠片回事。

我檢查了the documentation但找不到解釋。 我想我看到一些顏色正在改變成其他一些相似的顏色,這可能是我想達到的目標(即改變一些像素值)。

關於正在發生的事情的任何想法?

如果沒有,有沒有人知道是否有任何其他方式將畫布圖像保存到磁盤上的文件,而無需使用toDataURL方法? 可能是XPCOM組件能夠保存PNG二進制格式的所有像素?

感謝

+0

我測試過,即使數據URI是不同的,如果我創建一個新的圖像加載從toDataURI得到的這個新的數據URI,當我得到圖像數據:'imageData = canvas.getContext('2d')。getImageData(0,0,canvas.width,canvas.height );'兩者是相同的,並且像素似乎具有相同的值。這怎麼可能? – sagar38 2011-04-08 02:02:31

回答

0

有各種各樣的legal ways to losslessly filter and encode一個PNG。例如,查看this chart,顯示使用不同工具對相同圖像進行無損編碼時可能存在的巨大文件大小差異。

但是,如果您將toDataURL版本重新繪製到Canvas並獲取新的toDataURL並且它不同,我會感到驚訝。我希望每次都使用相同的瀏覽器對相同的圖像進行相同的編碼。

1

有一個特定的情況,我發現像素已被改變。 可能有更多的案例。我無法提供深入的技術解釋,因此,我不能說它實際上不會改變圖像。

如果將alpha值設置爲小於255(1.0)的任何值,那麼該像素的其他組件似乎會發生變化。解決問題的方法是簡單地將所有alpha值設置爲255.

從此刻起,我成功地使用ImageData和Image DOM元素將精確的精確數據存儲到畫布中,然後檢索完全相同的數據通過將alpha分量設置爲255並且不使用它來存儲數據不會造成損失。

下面是我目前使用的套路:

function make_image_with_data(contents) { 
    // Fractional side length. 
    var fside = Math.sqrt(contents.length/3); 
    // Whole integer side length. 
    var side = Math.ceil(fside); 

    var cv = document.createElement('canvas'); 

    cv.width = side; 
    cv.height = side; 

    var ctx = cv.getContext('2d'); 
    var id = ctx.createImageData(side, side); 

    var data = id.data; 

    data[0] = (contents.length >> 24) & 0xff; 
    data[1] = (contents.length >> 16) & 0xff; 
    data[2] = (contents.length >> 8) & 0xff; 
    data[3] = 255; 
    data[4] = (contents.length) & 0xff; 

    var z = 5; 
    var x = 0; 

    for (; x < contents.length; ++x) { 
     data[z] = contents.charCodeAt(x); 
     // Skip the image alpha component. 
     ++z; 
     if (z % 4 == 3) { 
      data[z] = 255; 
      ++z; 
     } 
    } 

    ctx.putImageData(id, 0, 0); 

    var img = document.createElement('img'); 
    img.width = side; 
    img.height = side; 

    img.src = cv.toDataURL(); 

    $(document.body).append(img); 

    return img; 
} 

然後函數來獲取數據傳回的是:

function load_data_from_image(img) { 
    var cv = document.createElement('canvas'); 
    cv.width = img.width; 
    cv.height = img.height; 
    var ctx = cv.getContext('2d'); 

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

    var id = ctx.getImageData(0, 0, img.width, img.height); 
    var data = id.data; 

    var len = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[4]; 
    var out = new Uint8Array(new ArrayBuffer(len)); 

    var z = 5; 

    for (var x = 0; x < len; ++x) { 
     out[x] = data[z]; 
     // This is skipping the alpha component. 
     ++z; 
     if (z % 4 == 3) { 
      ++z; 
     } 
    } 

    return out; 
} 
相關問題