作者pnpncat (meow)
站內Programming
標題[請益] 寫作繪圖軟體碰到的一些問題@@
時間Fri Aug 3 01:09:39 2012
最近自己在寫一個繪圖軟體
被一些問題卡住了
想跟大家討論看看
我想要寫一個類似 Photoshop 的圖層系統
這個系統要可以同時容納
1. 可切換各種混色模式的繪圖圖層
以及
2. 其他一些具有調整效果的參數圖層
我以 C++ 將它實做為類似 Link List 的資料結構
也就是將每個圖層設計為一個物件
此物件含有圖層本身的資訊(圖像或調整參數)以及一個指向下一圖層的指標
實際混色時是使用遞迴方式
也就是每個圖層都先呼叫下一圖層的混色函數
然後再將自己這一層的資訊疊加到 Buffer 上去
遞迴到碰到最底層為止
從行為上來說這個設計是沒有問題的
但是我發現當圖層增多到一個程度之後
時間和空間上的開銷都會有點不合理
以空間而言
假設一張圖是 3000*2000px 的 RGBA 格式
那麼不壓縮的大小就是 24M bytes
由於任何一個圖層有改變時
都必須將混色結果即時顯示到螢幕上
因此所有圖層資訊都要同時載入記憶體
這種情況下 只要開20 個繪圖圖層
就已經用掉 480M 的記憶體了
但我用 Photoshop 作實測
它用的記憶體連我所預估的一半都遠遠不到
如何做到這點讓我頗為好奇......
我想過幾種改善的可能
例如將「目前工作圖層」以下的所有圖層都存進硬碟
只將這些「以下圖層」混色過後的結果載入記憶體
但這方法得要燒香拜佛
祈禱使用者多編輯上方圖層 少編輯下方圖層.....
我還想過是否可以用這種預計算的方法對付「所有以上圖層的結合」
但由於圖層的某些混色模式和某些調整顏色的演算法
都必須先決定下層圖層的顏色才能計算
所以這想法似乎也行不太通
不曉得在這方面各位有沒有什麼高見?
另外一個問題則是時間上的:
假設使用者開了100個圖層而且都沒關掉
(一般修圖情況下調整圖層比繪圖圖層多出數倍是正常的)
又將視窗畫面縮放到可以看到全圖的話
那麼必須做的即時運算
竟然有 3000*2000*100 = 100M 次混色之多!!
即使我已經對混色演算法做了 bitwise 的優化
但每次混色畢竟還是包含多次的是否判斷式、加法、乘法、位移......等等
從現實情況上來說跟本不可能來得及
(流暢動畫的最低標準是 24fps,也就是最慢0.04秒內要完成全部混色動作)
我想過一個改善方式
就是對每個像素偵測「是否已經掩蓋下層圖層」
換句話說
如果有某個像素在某一層的 Alpha 值已經是 FF
那就可以不用管他下面是三小了
但後來發現這方法會快速地在不同圖層間切換
造成 Cache 效率極差 反而不如整張一起算 老老實實的算到底XD
總之 我實在是想破頭也想不出好方法
關於這兩個問題 如果有人能給我一點方向 我會非常感激 ^^”
--
直接閱讀《琴劍六記》
http://gs.cathargraph.com/p/list.html
《琴劍六記》Facebook專頁
https://www.facebook.com/GSannals
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 61.62.253.66
1F:→ tkcn:若圖層只存有色彩的矩型,而不是整張畫布呢? 140.114.78.231 08/03 01:26
2F:→ pnpncat:這也是要燒香拜佛啊XD 使用者有可能會把 61.62.253.66 08/03 01:34
3F:→ pnpncat:十幾張照片各自載入為圖層 那就整張畫布 61.62.253.66 08/03 01:35
4F:→ pnpncat:都有資訊了 61.62.253.66 08/03 01:35
5F:→ MOONRAKER:photoshop之所以為photoshop就是因為他118.165.219.222 08/03 01:37
6F:→ MOONRAKER:能掌握每一layer最多需要多少空間118.165.219.222 08/03 01:37
7F:→ MOONRAKER:不是用「原子彈爆炸」的做法118.165.219.222 08/03 01:38
8F:→ pnpncat:如果姑且不論儲存空間 關於效能的問題呢? 61.62.253.66 08/03 01:40
9F:→ pnpncat:我想到的效能改善都是跟使用者行為有關的 61.62.253.66 08/03 01:41
10F:→ pnpncat:還沒想到什麼通用的方法 61.62.253.66 08/03 01:41
11F:→ pnpncat:如果真的沒辦法 可能就得探到更下面了 61.62.253.66 08/03 01:46
12F:→ pnpncat:例如用 Cuda 做平行運算之類的@@ 61.62.253.66 08/03 01:46
13F:推 bill42362:cuda不錯阿 shader 本來就是為這設計的 118.161.109.88 08/03 07:28
14F:→ pnpncat:其實有考慮用 cuda 但一直沒用的原因是不 219.84.209.192 08/03 11:06
15F:→ pnpncat:太想寫需要特定顯示卡支持的程式 唉 219.84.209.192 08/03 11:06
16F:→ Chikei:PS對於這種極端case也這麼厲害嘛?像是20層 211.72.92.133 08/03 13:01
17F:→ Chikei:都是複雜照片一樣只消耗預估的50%-? 211.72.92.133 08/03 13:02
18F:→ MOONRAKER:那不可能吧,他只會開始用硬碟當scratch 118.163.12.174 08/03 17:52
19F:→ MOONRAKER:disk而已,接著就開始變得很慢 118.163.12.174 08/03 17:52
20F:→ Chikei:那就應該是只存最小面積/色彩index吧 211.72.92.133 08/03 18:34
21F:→ Chikei:我也很懷疑對於3Kx2Kx100L這種東西PS真的能 211.72.92.133 08/03 18:42
22F:→ Chikei:辦到很流暢的混圖層嘛XD 211.72.92.133 08/03 18:43
23F:→ pnpncat:100 Layers 是不少見啦 但現實情況中 219.85.123.240 08/04 00:04
24F:→ pnpncat:很少會將100層同時打開 219.85.123.240 08/04 00:05
25F:→ pnpncat:我可能要對 PS 作更詳細的測試了@@ 219.85.123.240 08/04 00:06
26F:推 abcdefghi:把各layer scale成螢幕大小(dpi)再放記 114.44.183.241 08/04 21:27
27F:→ abcdefghi:憶體, 只有在zoom in/out的時候才重算 114.44.183.241 08/04 21:28
28F:推 bill42362:不用 cuda 可以考慮看看 OpenCL @@"118.161.191.142 08/05 00:26
29F:→ pnpncat:a兄的方法很好 不過那樣就不能做滾輪縮放 180.176.20.143 08/05 03:50
30F:→ pnpncat:了吧我想 變成縮放成本很高 180.176.20.143 08/05 03:50
31F:推 abcdefghi:開另一個threads專職作scaling,每個laye 114.42.176.184 08/05 08:30
32F:→ abcdefghi:只要完成就丟給主thread,互動性應該不差 114.42.176.184 08/05 08:33
33F:→ pnpncat:感謝指點 我再試試看^^ 219.84.209.244 08/06 09:40
34F:推 yoco315:我確定ps只有保存有像素的區塊 58.115.137.102 08/07 21:01
35F:→ yoco315:超出那個矩形的地方根本不吃記憶體 58.115.137.102 08/07 21:02
36F:→ yoco315:但相對的,如果那個圖層被移動到超出邊緣 58.115.137.102 08/07 21:03
37F:→ yoco315:即使已經超出畫紙,也依然會吃記憶體 58.115.137.102 08/07 21:03
38F:→ yoco315:這個設計很合理,也省記憶體,move的實作 58.115.137.102 08/07 21:03
39F:→ yoco315:也很快速,缺點就是blending的時候比較貴 58.115.137.102 08/07 21:04
40F:→ yoco315:另外,你要求的流暢度可能有點太超規格了 58.115.137.102 08/07 21:05
41F:→ yoco315:即使是adobe的千里馬,在多層的時候,即使在 58.115.137.102 08/07 21:05
42F:→ yoco315:高級電腦上也是卡卡的,除非使用GPU加速 58.115.137.102 08/07 21:06
43F:→ yoco315:這是我上次去參加conference的時候,CUDA給 58.115.137.102 08/07 21:06
44F:→ yoco315:的其中一個展示... 人家也要GPU才能作到:( 58.115.137.102 08/07 21:07
45F:→ pnpncat:多謝y兄 我再次測試的結果 正如y兄所述 219.85.243.227 08/11 17:31
46F:→ pnpncat:此外 先scale的方法似乎行不通 即使只做 219.85.243.227 08/11 17:32
47F:→ pnpncat:Bilinear 多次縮放的成本也太高了 不會 219.85.243.227 08/11 17:33
48F:→ pnpncat:低於Blending本身 先Blending 然後用顯 219.85.243.227 08/11 17:33
49F:→ pnpncat:卡縮放(我用openGL)還是比較節省 219.85.243.227 08/11 17:34
50F:→ pnpncat:經過一番討論 目前我已經比較有方向了 219.85.243.227 08/11 17:35
51F:→ pnpncat:正在努力coding中XD 219.85.243.227 08/11 17:36