第17題 - 100 * 100 的Canvas 佔用內存多大

題目描述

一個 100 * 100 Canvas 佔用內存多大,它的大小的決定因素是什麼?這裏我們只考慮存儲這麼多像素的內存,不考慮運算過程中使用的內存。

感性認識

我們知道 Canvas 給了我們前端像素級別控制的能力,我們可以精確到像素,因此多了 更多的靈活性和複雜度。可以說 Canvas 的模型和傳統的 DOM 模型有很大的不同。

那麼要回答這個問題,我們其實只要知道 1 * 1 像素佔用多大內存就好了。

那麼 1 * 1 像素的 Canvas 佔用多大像素呢?我們來感性思考一下,我們現在前端在寫顏色的時候, 很多都是用RGBA或者#(六位十六進制)的形式, 對於 RGBA 我們可以怎麼存儲?A 的話,我們平時的取值範圍 0 - 1 的小數,步長爲 0.01,因此 100 個數字就夠了,7Bit 就可以搞定。

那麼 RGB 呢?如果你用過 RGB 或者 RGBA 的話,應該知道我們通常使用的範圍是 0-255 的範圍, 因此 RGB 的存儲空間應該是 8*3 = 24 Bit,也就是 3Byte。

如果使用十六進制表示呢?一個十六進制需要 4 個 bit,那麼 6 個十六進制就是 24 個 bit,也就是 3Byte,和 RGBA 是一樣的。

因此一個像素的 Canvas 佔據空間理論上是 31Bit。那麼事實上是這樣麼?

什麼是 ImageData

回答這個問題之前,我先來介紹一個 Canvas 的 API getImageData, 這個 方法會返回一個 ImageData,它用來描述"canvas"元素的一個隱含像素數據的區域。使用 ImageData() 構造函數創建或者使用和 canvas 在一起的 CanvasRenderingContext2D 對象的創建方法:createImageData() 和 getImageData()。我們這次就使用getImageData().

我們來實際測試一下

先說結果,結果是一個像素的 Canvas 佔內存是4Byte

我做了一個實驗,具體是怎麼做的呢?我們一起來看一下。

下面是我寫的一個HTML結構,裏面放了一個Canvas和一個button,點擊button會打印出來一個像素的信息。

這裏是代碼:

<!DOCTYPE html>
<html>
  <body>
    <canvas id="myCanvas" width="300" height="150">
      Your browser does not support the HTML5 canvas tag.
    </canvas>

    <script>
      var c = document.getElementById("myCanvas");
      var ctx = c.getContext("2d");
      ctx.fillStyle = "rgba(200,2,2,0.8)";
      ctx.fillRect(10, 10, 50, 50);

      function getImageData() {
        var imgData = ctx.getImageData(10, 10, 1, 1);
        console.log(imgData);
        return imgData;
      }
    </script>

    <button onclick="getImageData()">獲取1像素信息</button>
  </body>
</html>

這裏是渲染結果:

640?wx_fmt=png

點擊之後,控制檯的顯示結果:

640?wx_fmt=png

204 就是 255 * 0.8 算出來的

可以看出其實像素信息使用 Uint8 來存儲的,數組長度爲 4, Uint8 佔用內存爲 1 個字節, 因此一共是 4 個字節,所以答案就是一個像素的 Canvas 佔內存是4Byte。這個和我們的猜測31Bit相差了1Bit,其實多這1bit也是爲了方便操作。

這道題還沒有完~

RGB,RGBA 等等表示法有什麼本質區別

我們剛纔的推測以及實驗都是基於特定的顏色表示方法,比如 RGBA 或者#(六位十六進制)的形式, 如果我們採用別的方式呢?比如之前的 24 位,即 RGB 表示法。那結果就是100 * 100 *3, 如果一個顏色不用一個字節,而是更多或者更少的字節呢?這些都會影響到結果。

因此上面我們的猜測以及“結論”都不確切,更確切地說佔用多少內存完全取決於你如何對像素進行編碼和解碼,只有掌握這個根本點,才能無往而不利。

總結

我們先從感性認識來“猜測”了一下問題的答案,然後通過 Canvas 的內置 API 實際地檢測了一下我們的猜想, 但是這個猜想似乎並不是很嚴謹,換句話說我們的猜想以及驗證結果是有一定的前提條件的。

其實答案不重要,重要的是你看到這種問題的思維過程,這種題目很容易看出一個人的知識廣度和深度, 甚至思維能力。本文完~

關注我

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章