自制操作系統Antz(15)——實現啟動界面


AntzScript

🎓 The language executed in the Antz system.

本節不涉及OS底層內容,只是關於圖片放大顯示時效果處理的。

Antz系統更新地址
Antz項目地址
真機啟動效果

圖片來源:phodal/daily

(orz左上角是在處理原圖時自己簽的名)

為了節省鏡像空間,我將圖片從2000乘800左右圖片壓縮為108乘60的24色大小的圖片,計算為RGB值之后也有近6400左右像素點。但是要將它寫入顯存,展現在用戶眼中,效果表明是很差的,我們的分辨率為1080x768,數十倍於這張圖片。

為了解決顯示效果的問題,這里有兩種解決方法。


一. 像素點區域化

這個方法是我自己起的名字,大致意思也如標題所示,就是將一個本來應該顯示在(x1,y1)位置的像素點區域化顯示,將其RGB值覆蓋在(x1,y1)至(x1+x,y1+y)的這片區域。這個方法實現起來非常簡單,但是效果極差,最后顯示出來的效果就好像是我的世界中的超大像素點效果。

圖示大概如這樣:

123

附上簡單實現。

void to_show(){
int i, x, y ;
int k ;
k = 0 ;
for (y = 0; y < 60; y++) {
for (x = 0; x < 108; x++){
// 在(x*10,y*13)至(x*10+10,y*13+13)這片區域填充RGB值bmp[k]
print_image(x*10,y*13,x*10+10,y*13+13,bmp[k]);
k++;
}
}
}

在虛擬機中效果如下。

img

二. 雙線性插值

在使用第一種粗略暴力的方式實現啟動動畫之后,第二天的數字圖像處理課程中,聽到老師講matlab中的圖片放大縮小函數的原理,了解了雙線性插值這個算法,於是想到用這個方法來重新實現啟動界面。

雙線性插值的基本原理是,假設源圖像大小為MxN,目標圖像為AxB。那么兩幅圖像的邊長比分別為:M/A和N/B。這兩個比例值一般是浮點數。目標圖像的第(i,j)個像素點(i行j列)可以通過邊長比對應回源圖像。其對應坐標為(im/a,jn/b)。顯然,這個對應坐標一般來說不是整數,而非整數的坐標是無法在圖像這種離散數據上使用的。雙線性插值通過尋找距離這個對應坐標最近的四個像素點,來計算該點的值(灰度值或者RGB值)。

其實可以理解為通過其周圍的四個點,中和出這片區域中的其他點。

2123

s

我們想得到一張放大的圖片,現在有原圖像目標圖像。那么,有一個最基本的問題擺在我們面前:是遍歷原圖像呢,還是遍歷目標圖像呢?

在實踐的過程中,通常都是遍歷目標圖像的。因為這樣可以確保目標圖像的每一個像素都是有值的。

就拿上圖的例子來說,右圖目標圖像中的 [0,0] 點很順利的找到了左圖原圖像中與自己對應的 [0,0] 點。然后 [0,1] 點就懵逼了,它應該找[0,0.33]點嗎?沒有這個點啊,所以[0,0.33]的值是需要四個點來進行擬態的。

插值法除了雙線性插值還有最臨近插值,線性插值。

最臨近插值可以理解為取值為最近的一個像素點,線性插值是在周圍兩個像素點中取一個(根據兩邊距離決定)折中值,很明顯它們的作用范圍均是線性一維。

再來說雙線性插值,它可以取空間中的四個點來做擬態取值。

大概理解就是如此,具體實現可以借助公式,下面給出百度百科的公式。

2

已知的紅色數據點與待插值得到的綠色點

假如我們想得到未知函數f在點P= (x,y) 的值,假設我們已知函數f在Q11 = (x1,y1)、Q12 = (x1,y2),Q21 = (x2,y1) 以及Q22 = (x2,y2) 四個點的值。

首先在x方向進行線性插值,得到R1和R2,然后在y方向進行線性插值,得到P.
這樣就得到所要的結果f(x,y).

其中紅色點Q11,Q12,Q21,Q22為已知的4個像素點.

第一步:X方向的線性插值,在Q12,Q22中插入藍色點R2,Q11,Q21中插入藍色點R1;

第二步 :Y方向的線性插值 ,通過第一步計算出的R1與R2在y方向上插值計算出P點。

線性插值的結果與插值的順序無關。首先進行y方向的插值,然后進行x方向的插值,所得到的結果是一樣的。雙線性插值的結果與先進行哪個方向的插值無關。

如果選擇一個坐標系統使得 的四個已知點坐標分別為 (0, 0)、(0, 1)、(1, 0) 和 (1, 1),那么插值公式就可以化簡為

f(x,y)=f(0,0)(1-x)(1-y)+f(1,0)x(1-y)+f(0,1)(1-x)y+f(1,1)xy

在x與y方向上,z值成單調性特性的應用中,此種方法可以做外插運算,即可以求解Q1~Q4所構成的正方形以外的點的值。

233

f(x,y1) ≈ (x2−x / x2−x1) * f(Q11) + (x−x1 / x2−x1) * f(Q21),
f(x,y2) ≈ (x2−x / x2−x1) * f(Q12) + (x−x1 / x2−x1) * f(Q22).
f(x,y) ≈ (y2−y / y2−y1) * f(x,y1) + (y−y1 / y2−y1) * f(x,y2)
int index = 0 ;
for(y=0;y<768;y++){
for(x=0;x<1080;x++){
for(int i=0;i<60;i++){
for(int j=0;j<108;j++){
int getx1 = ((108+13-y)/13)*bmp[index*108+60] + (y/13)*bmp[index*108+60+1] ;
int getx2 = ((108+13-y)/13)*bmp[(index+1)*108+60] + (y/13)*bmp[(index+1)*108+60+1] ;
int getRgb = (i/10)*getx1 + ((60-i)/10)*getx2 ;
print_image(x,y,getRgb);
}
}
}
index ++ ;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM