2012年5月7日 星期一

[Linux] 免費編輯 PDF 文件 (刪除、新增頁面) @ Ubuntu 10.04

pdfeditor


最近偶爾會編輯一下 PDF 檔案,由於在 Windows 上似乎沒有幾套免費的 PDF 編輯軟體,有的免費的不支援存檔或是增減頁數,於是我只好默默開啟 Ubuntu 後,安裝 PDF Editor 啦 XD


$ sudo apt-get install pdfedit


接著就可以開啟想要更改的 pdf 檔案,例如把其中一頁給刪掉 (Remove Page)


remove page


如果編輯文件時,底下的視窗出現類似的資訊:


PDFedit
Loaded file : test.pdf
> removePageWithConditionalRefresh()
! In script '/usr/share/pdfedit/page.qs', line 118:
! Error. Exception in Pdf.removePage : Document is read-only


此時要先透過 [Tools] -> [Delinearize] 重新選這個檔案(此例為test.pdf),再另存起來(如 test2.pdf),接著開啟 test2.pdf 就能夠編輯。


pdfedit_add_pages


此外,也可以新增 pdf 檔案進來 [Tools] -> [Insert Pages from other document],接著開啟想要匯入的檔案後,可以把想要的 page 匯入,並調整頁數位置。雖然匯入的格式必須是 PDF 檔案,但也還算方便啦。


2012年5月5日 星期六

簡易拆解、組裝 iPhone 3G

15


幾個月前,同事的 iPhone 3GS 的電池開始出現充不飽、急速用完的問題,因此透過網拍管道找到換修電池的服務,當時跟他去看看到底怎樣拆 iPhone 3GS ,看完一遍後,就一直想要親手試看看,如今有空,我也拆了一台 iPhone 3G (不是 iPhone 3GS)或許哪天我也可以只買電池幫老家的 3G 手機換一下 :D (由於電池是貼黏在 iPhone 3G 背殼,所以此例只拆到看的見電池為此) 但我是建立在家中手機已經快 3 年的態度 XD 實在不建議其他人隨便看看文章就親手拆!這風險應該比 JB 還高吧 XDD 就當作個筆記笑笑吧!


老話一句:


拆機存在機器損壞風險,並喪失保固(貼紙損壞),請交給專業的
不要隨意嘗試,需自行承擔責任


01


首先是準備的工具,拆的話至少需要一個小吸盤跟螺絲起子,組裝的話需要多一支小夾子(那支尺只是比例參考)。我特地跑去五金賣場花了 32 元買了一支夠小的螺絲起子,實在是 iPhone 的螺絲大小約 2mm 而已!賣場還滿容易看到賣一盒小工具 110 ~ 210 的價錢,但我只需要最小的那支而已,且不能當場測試我也不知是不是夠小,去傳統五金賣場,還帶著 iPhone 去那邊試喔,這時才會發現傳統的美好 :D


02


拆掉接頭旁邊的兩個螺絲後,用手握手機的方式,把手握住靠近電源那頭,把吸盤擺在靠近插頭那端,須要給一點點力氣,就能夠使之分離。


03


此時螢幕與機身還有三處連結,這時可以看到一些標記處,這大概是提醒拆裝者的資訊。依編號來看,共有六個號碼,其中 1~3 個編號拆開後,就能使螢幕與機身分離,編號 4 應該是插頭與板子的連接處,編號5猜測是電池連接頭,編號6是一個圓形接頭,但我就沒研究了 XD


04


首先編號1算是很輕鬆就扳開,甚至可能把螢幕拉高一點就會自動分離,而編號2稍微緊了點,從下面扳開有點難,我就藉由它的帶子輕輕地分離它。


05 06 07


接著是很重要的編號3,這個接法算是此次最最麻煩且小心的地方,因為他就像兒時任天堂跟遊戲卡帶的接法,只是編號3是很柔的帶子,拆除是很簡單的,但若沒透過夾子,想要把它插回去是十分困難的,並且我隨意找的網路影片,都很自然地略過把它接回去的片段 orz 不知是不是要偷留一手。


08


當編號 1~3 拆開後,螢幕跟機身就分離了!


09 11


接著就順著流程把編號 4~6 都拆掉後,還要移除 sim 卡槽和右上角鏡頭的螺絲部分跟 7 處的小螺絲。


12


從右往左分別是兩個螢幕螺絲、鏡頭螺絲與 L 片,最後則是七顆小螺絲。


14 15


從插座那端慢慢地扳起來,接著網插座那端輕輕地抽出來,就可以看到電池啦。這次練習就到這裡而已,忘了先買電池,所以就沒繼續研究(因為電池是黏在背殼的,拆掉沒辦法黏的穩定)


20 21 22


接著就是組裝回去,一樣斜斜地把板子擺放到原處,記得要小心編號 6~4 不要被板子壓到。


23 24 25 26


接下來把可以鎖上編號五跟右下角的螺絲,將板子固定好,再來編號 4~6 、鏡頭擺好及 L 板鎖好。


27 28


如此一來,就只剩螢幕跟機身的部分了!最困難的地方就是要把編號 3 接好,當初研究很久,才想起來可以試試看夾子,透過夾子的幫忙,終於把編號3接回去了!大部分螢幕不會顯示,大概都是這處出錯吧 XD 其實我第一次也沒接好,因為沒用夾子,粗糙地接好但螢幕不會顯示!只能喃喃自語地說「反正這台過保也打算換了」,但內心卻在淌血 XDD 後來想到夾子後,在左手努力之下,終於按下開機按鍵可以看到白蘋果啦!


29


網路上可以看到很多討論串,大部分都說螢幕沒顯示的話,大概是把螢幕搞壞掉了 :p 起初我也小小放棄了,但後來還是覺得很怪,這種需要人力組裝的 3C 產品,在製程上應該是有 try 過的,雖然我是生手,不至於這麼容易壞(不然量產根本不可能吧?!),所以多方嘗試,我也把它救回來了 XD


2012年5月2日 星期三

OpenStreetMap API 筆記


From: Bing Maps Tile System


去年做了一整年跟圖資有關的案子,結果一直對這塊很好奇,原理大概知道,但細節卻遲遲沒播出時間來研究,今天毛起來翻了一下資料,就從 OpenStreetMap 下手吧!整體上原理就是把地球三維座標投影成二維座標,接著用一張張 256x256 正方型圖片來組成一張地圖,因此想要顯示地圖就是把目前關注的區域座標範圍,計算一下落在哪些圖上,接著把圖取出來即可。


此處 OpenStreetMap 的 Image API URL = "http://tile.openstreetmap.org/" + Zoom Level + "/" + X + "/" + Y + ".png" ,例如 Level 0 的地圖僅有一張,即為: http://tile.openstreetmap.org/0/0/0.png ,接著到 Level 1 時,變成 2x2 張圖、Level 2 為 4x4 張圖,每張圖仍維持 256x256 的大小,以此類推。


使用上就是要處理 GPS 座標:


在 Level 0 時,就是把座標轉換到 256x256 位置
在 Level 1 時,則為 512x512 位置
在 Level 2 時,計算 GPS 座標在 1024x1024 圖片的哪個位置
... 以此類推


至於座標投影如何轉換,可以參考 Bing Maps Tile System 或 Tiles à la Google Maps: Coordinates, Tile Bounds and Projection(globalmaptiles.py),也可以翻別人的 code 套公式,下次有空再來細細研究 XD


Level 0:








Level 0 

Leve 1:













Leve 1 (0,0)  Level 1 (1,0)
 Level 1 (0,1) Level 1 (1,1)

Leve 2:


 





























Level 2 (0,0) Level 2 (1,0) Level 2 (2,0)  Level 2 (3,0)
 Level 2 (0,1) Level 2 (1,1) Level 2 (2,1) Level 2 (3,1)
 Level 2 (0,2) Level 2 (1,2) Level 2 (2,2) Level 2 (3,2)
 Level 2 (0,3) Level 2 (1,3) Level 2 (2,3) Level 2 (3,3)

參考資料:


OpenStreetMap - Beginners Guide 1.5
OpenStreetMap - Slippy Map
OpenStreetMap - OpenLayers
OpenStreetMap - Google Maps Example
Bing Maps Tile System
Tiles à la Google Maps: Coordinates, Tile Bounds and Projection


Android 開發教學筆記 - 研究 Renderscript 之 Fountain 與 FountainFbo 的差異

fountainFbo


關於 Fountain 和 FountainFbo 的介紹,可以看 Renderscript>Graphics 官網得到更詳細的介紹,在此僅簡易筆記。


首先快速帶一下 Fountain 的特效,就是在螢幕上點擊、久按、拖拉著任何一點,這時螢幕會隨著點擊事件產生一個點畫在螢幕上,接著亂數決定這個點的顏色以及該如何移動並會隨著時間往下掉,這樣的效果就接近煙火。其中在 FountainRS 有定義最多顯示 50000 個點(PART_COUNT變數),所以拖曳時的效果又跟煙火不太一樣。而 FountainFbo 則是多顯示一塊小區域,重複繪出螢幕上的特效,並使用 Framebuffer Object。


先用 vimdiff 看一下 FountainRS.java 和 FountainFboRS.java 的差異:


$ cd ~/workspace
$ vimdiff Fountain/src/com/example/android/rs/fountain/FountainRS.java FountainFbo/src/com/example/android/rs/fountainfbo/FountainFboRS.java


java_FountainRS_FountainFboRS


扣除 package name 這類東西外,看得出來主要差別在 public void init(RenderScriptGL rs, Resources res) 中所使用的流程。


先看一下共同項目:


ProgramFragmentFixedFunction,其定義 http://developer.android.com/reference/android/renderscript/ProgramFragmentFixedFunction.html


ProgramFragmentFixedFunction is a helper class that provides a way to make a simple fragment shader without writing any GLSL code. This class allows for display of constant color, interpolated color from the vertex shader, or combinations of the both blended with results of up to two texture lookups.


Mesh,其定義 http://developer.android.com/reference/android/renderscript/Mesh.html


This class is a container for geometric data displayed with Renderscript. Internally, a mesh is a collection of allocations that represent vertex data (positions, normals, texture coordinates) and index data such as triangles and lines.


Vertex data could either be interleaved within one allocation that is provided separately, as multiple allocation objects, or done as a combination of both. When a vertex channel name matches an input in the vertex program, Renderscript automatically connects the two together.


Parts of the mesh can be rendered with either explicit index sets or primitive types.


ScriptField_Point,其定義在 renderscript 裡頭(C99語法)


typedef struct __attribute__((packed, aligned(4))) Point {
        float2 delta;
        float2 position;
        uchar4 color;
} Point_t;


ScriptField_Point 是自訂結構,定義於在 *.rs,編譯後自動產生的,用途是紀錄每一個點的資訊;Mesh為一種資料結構,用來收集一批資料,最重要的是 Renderscript 有 rsgDrawMesh API,可以一次把 Mesh 收集的資料繪出,因此程式架構上,並非用 loop 繪每個 Point,有點像寫 C 時,用 memset 取代用 loop 對 array 的初始化,更多細節請參考 Renderscript>Graphics>Drawing with a mesh;ProgramFragmentFixedFunction 對我而言是比較生疏的部份,這跟 OpenGL Shading Language (GLSL) 有關,其中 Google Translate 對 Shader 翻譯為"著色",我把 GLSL 當作繪圖相關的基本需求,另外,從描述的意思是使用 ProgramFragmentFixedFunction 可以省去從頭到尾定義 GLSL 出來,何謂 GLSL 呢?可以參考 Renderscript>Sample>Balls>BallsRS.java,裡頭有用 ProgramVertex 引入 GLSL 語法,更多細節請參考 Renderscript>Graphics>Programs


不一樣的地方:


對 FountainRS.java 來說,使用 ProgramFragmentFixedFunction 建立 GLSL 環境後,傳給 RenderScriptGL rs 環境使用,但在 FountainFboRS.java 中,多定義兩個 ProgramFragment 變數,mProgramFragment 和 mTextureProgramFragment,並且在 Renederscript 裡頭接應,接用 vimdiff 看一下 fountain.rs 和 fountainfbo.rs 的差異:


$ cd ~/workspace
$ vimdiff Fountain/src/com/example/android/rs/fountain/fountain.rs FountainFbo/src/com/example/android/rs/fountainfbo/fountainfbo.rs


rs_fountain_fountainfbo


可看出 fountain.rs 裡的東西基本上都出現在 fountainfbo.rs 了,所以了解 fountrain.rs 在 void root 做事後,可以細看 fountainfbo.rs 的變化,此部份在官網 Renderscript > Graphics > Framebuffer Object 有很多細部介紹,在此就不多提囉。


總結一下,在 fountainfbo 中採用 Framebuffer Object 的繪圖技巧,可以讓開發者先在某一處 buffer 繪圖(offscreen),繪完後在貼到螢幕上(onscreen)。