[ Android 系統 ] A pixel is not a pixel : 一樣的解析度,不一樣的視野?像素與PPI

這張圖,左邊是 HTC One X(以下簡稱 OX),右邊是 Nexus 7(以下簡稱 N7)。

OX 使用的面板解析度是 720×1280,而 N7 使用的面板解析度為 800×1280。雖然 OX 與 N7 的橫向解析度差不多(720 v. 800),但是從這張圖卻可以發現即使使用一樣大小的字體,N7 在同一橫列上可以呈現的字數卻比 OX 還多。

這就是今天的主題,許多人的疑惑:一樣(或接近)的解析度,為什麼可以呈現的物件數量卻不同?同場加映,為什麼同樣(或接近)解析度,但是螢幕尺寸不同的裝置,閱讀時字體的感覺不同?


貓不是程式設計師,也非人機介面設計師,只是因為想到這個問題,所以閱讀一些文件,而將得到的心得寫下來。


要想得到這兩個問題的答案,首先得先來建立一些基本知識。

像素與 PPI

先說像素

像素(pixel)的意思是現代的數位顯示裝置上,最小的一個單位。

一般來說,液晶顯示器(LCD)的面板是由許多的像素排列而成。除了一些特殊的面板,如 AMOLED,之外,幾乎所有面板的像素都同時具備三個子像素(sub pixel )。這三個子像素分別負責發出紅-綠-藍三原色的光線。

所謂的解析度,單位就是像素,數字表示每一列或每一行有多少像素。

以手機來說,通常解析度講的是寬x長。例如 OX 是 720×1280,意思就是每一行(橫)是由 720 個像素組成,而每一列(直)是由 1280 個像素組成。

例如上面這張圖,每一行是 72 格,每一列是 128 格。把每一個格子想成像素,而把這想成面板,這塊面板的解析度就是 72×128。

接著說 PPI

所謂 PPI 全名是 Pixels per inch,中文就是「每英吋像素」。這是現代的數位顯示裝置的密度單位。意思是「每一英吋的長度上,總共有多少像素」。也可以理解成「在這塊面板上顯示與實際長度相同的一英吋長度的線條,需要多少像素」。

PPI 越高,表示密度越高。

PPI 的計算公式為:

PPI = (√(解析度的長^2 + 解析度的寬^2))/可視面積對角線長度

眼尖的人可能已經注意到了。(√(解析度的長^2 + 解析度的寬^2)) 就是應用畢氏定理求直角三角形的斜邊長度的公式。

套用公式來計算 OX 和 N7 的 PPI:
N7 的 PPI = (√(1280^2+800^2))/7 = 215.63
OX 的 PPI =(√(1280^2+720^2))/4.7 = 312.47

這個數字以及 PPI 現在先有個概念就好。


虛擬像素

接下來,要來談談虛擬像素。

為什麼需要虛擬像素(virtual pixel)?因為設計使用者介面(User Interface,簡稱 UI)的時候,面臨到了一個問題:螢幕有這麼多解析度,要怎麼維持在不同解析度的螢幕上,呈現一樣大小的字體?

看看上面這張圖。把這張圖想像成上面是一個 5×5 的面板,下面是一個 7×7 的面板。今天同樣擺上一個 3×3 的黑色方塊,可以發現在實際面積相同的兩塊面板上,5×5 的視覺上呈現的黑色方塊比 7×7 的還大。

試想:如果今天 UI 設計師用 480×800 的解析度作為開發環境,想在某個角落放一個 96×96 的方塊,然後在裡面用 16 點的字體放一些描述。這樣的設計,到了 720×1280 解析度裝置上,會因為字體縮小而變得難以閱讀。就像下面這張圖這樣(引用自 developer.android.com):

由左至右,裝置的解析度越來越高,而指定實體像素畫出來的物件卻會越來越小。

解決的方案!在現代的電腦(無論是 Windows,iOS,Android 或是 Linux),對於在螢幕上繪圖所使用的像素不是實際像素,而是虛擬像素。使用這個解決方案之後,上面那張圖就會變成這樣(引用自 developer.android.com):

可以看到,物件在不同解析度呈現出來的大小一致了。

虛擬像素是怎麼做到這神奇的效果的?

簡單來說,就是「一個虛擬像素不等於一個物理(實體)像素」。

虛擬像素是給程式用的。程式只需要說明它希望在哪邊,畫出一個「幾點像素x幾點像素」的物件。然後在不同解析度的環境中,系統自己來決定「一點虛擬像素要對應幾點實體像素」。

以上面這張圖為例。上面的是一個 5×5 的面板,下面是一個 10×10 的面板。

今天以 5×5 為標準,當解析度為 5×5 的時候,一點虛擬像素等於一點實體像素。此時程式要在畫面上描繪一個 3×3 的黑色方塊,結果就像上圖。然後當程式要在 10×10 的環境中,也描繪一個 3×3 的黑色方塊,此時系統會自動調整,一點虛擬像素等於兩點實體像素,於是描繪出來的黑色方塊,呈現的視覺感就跟在 5×5 的環境上是一樣的。

如此一來就解決了問題。



接下來,差不多該進入解答的時候了…

問題一:為什麼 OX 跟 N7 的解析度差不多,可是視覺上覺得 N7 呈現的內容比 OX 多很多?

答案:

就是因為虛擬像素的不同。

有虛擬像素的協助,可以使得同樣的字體在 OX 和 N7 視覺上的大小幾乎一致。

目前 Google 建議的規範上,把 Android 系統的螢幕的密度分成四級:120DPI,160DPI,240DPI 與 320DPI。系統的螢幕密度設定,找硬體 PPI 最接近的一級來設定。例如 OX 的螢幕密度就是設定為 320DPI。而 N7 卻還是用 213DPI(原因不詳)。

Android 是以 160DPI 為基準。在 160PPI 的螢幕上,系統的螢幕密度設定為 160DPI 的環境中,一點虛擬像素等於一點物理像素

然後 Android 的虛擬像素解析度的算法是:
虛擬像素數目 = 物理像素數目 / (設定的螢幕密度 / 160)
所以 OX 的物理解析度是 720×1280,設定的螢幕密度為 320,換算成虛擬像素解析度就是
寬的虛擬像素數目 = 720 / (320/160) = 360
長的虛擬像素數目 = 1280 / (320/160) = 640
所以 OX 的虛擬像素解析度為 360×640。

N7 的物理解析度是 800×1280,設定的螢幕密度為 213,換算成虛擬像素解析度就是
寬的虛擬像素數目 = 800 / (213/160) = 601
長的虛擬像素數目 = 1280 / (213/160) = 961
所以 N7 的虛擬像素解析度為 601×961

N7 的螢幕寬的虛擬像素比 OX 多了 67%,螢幕長的虛擬像素比 OX 多了 50%。

這個意思就是,如果以同樣的字體來顯示一篇文章,在 OX 上面一行可以顯示 16 個字,24 行,在 N7 上面就可以顯示 26 個字,30 行以上。

問題二:為什麼同樣閱讀 Gmail,就會覺得在 N7 上面的字體似乎比較糊?

答案:

因為 PPI 的不同。

在 OX 上面跟 N7 的字體因為 Android 的內建機制以及虛擬像素的影響,所以視覺上的大小很接近。但是 OX 的螢幕物理密度有 312PPI,N7 的只有 216PPI。

螢幕密度與字體呈現的關係就像在生日蛋糕上面用蠟燭排 I ♥ U 一樣。如果用的是很粗的蠟燭,就沒辦法排出漂亮的 ♥。但是如果改用很細的蠟燭,就可以排出漂亮的 ♥。能在一樣的面積上塞入越多像素的話,就可以描繪出越精緻的畫面。由於 N7 的物理密度低於 OX,因此字體的視覺效果上自然會比較差。

Apple 的 The New iPad 將解析度從 1024×768 提升到 2048×1536,PPI 一口氣從 136 提升到 263,這物理密度的提昇所帶來的視覺效果的提昇,正是 The New iPad 宣揚的賣點之一。