2009年11月29日 星期日
HW4
這次作業是要像第三次作業那樣將讀進來的
圖檔資訊顯示在C++ Builder的影像元件上但不要
使用BCB裡面提供的LoadFromFile的方式來讀檔
是要使用第三次作業有用到的fopen fread fseek的方式
來直接讀取圖檔的檔頭 讓讀進來的圖檔大小 圖檔長寬等都能顯示出來
在之前的課堂上老師有解釋了BMP檔案格式的特色
和BMP檔頭內的每個byte所提供的訊息
先使用fopen開啟所要使用的圖檔
透過fseek將指標指向我們要的檔頭資訊
再配合fread來讀取我們的檔頭訊息
就可以將開啟的圖檔資訊輸出在BCB的元件上
整體看起來也比之前HW3開啟圖檔時不斷跑出
圖檔的資訊的視窗來的簡潔有力
在做作業的期間一度忘了BMP的檔頭內所要讀取的有哪些資料
就使用老師之前推薦的PSPad這套軟體和wikipedia所查到的
BMP檔頭內容來複習 基本上只要前面幾次作業都有理解的話
這次作業還真的不算難~
HW4
HW4
上圖是我掃出來ㄉ圖檔(點圖可放大)
在做這個作業時,本來是想直接用之前的程式去讀圖的,不過這一讀出來就給他感覺是個非常擠的畫面,所以我上來看了看學長們上傳的HW4發覺完全沒有我那個問題,所以我就乾脆用老師上課說的那個PageControl來給他排版整齊一下,讀出來感覺上就比較沒有之前那麼擠了,這周的作業是要我們用fseek. fread....來做掃圖的動作 ,在掃圖期間有點嚇到,我原本以為是會直接蹦的圖就出來了,沒想到它是慢慢得從下往上出現,這是我覺得有趣的地方,因為一般像是網頁上的圖它都是由上往下出現的 ,幸好它圖掃的時候不會很慢,掃太慢那還得了= =。
剛開始在做作業時,發現為什麼一直沒辦法把圖給讀出來呢?之後回去看了一下之前所寫過的fopen.fseek.fread...的部份時,這才發現錯的地方只是差在讀的地方讀錯了,難怪一直都沒有讀出圖片在我想要的地方去,其實有一些部份還不是很了解,不過還好有把之前的作業檔案留著,不然就幾乎整個程式碼久了之後應該就會變得模模糊糊了。
HW4
2009年11月28日 星期六
HW4
2009年11月27日 星期五
HW4
以下是錯誤圖片:
因為右邊的圖片一直掃不出來,
讓我一直在找程式碼中的錯誤,
雖然程式也才幾行而已,
但是時間卻全花在找出掃不出圖的原因,
後來發現是這一行,
Image2->Canvas->Pixels[j][i]=(TColor)RGB(col[0],col[1],col[2]);
因為掃圖的方式
所以必須將Pixels[j][i]改成Pixels[j][iImageHeight-1-i]
而且又因為RGB讀進的次序必須將(TColor)RGB(col[0],col[1],col[2]);
改成(TColor)RGB(col[2],col[1],col[0]);
所以改完成後應該是
Image2->Canvas->Pixels[j][iImageHeight-1-i]=(TColor)RGB(col[2],col[1],col[0]);
之後掃圖就沒有問題了。以下是正確版:
2009年11月26日 星期四
hw04
這次的作業,是要自己將圖片影像讀出來
讀完每個點的RGB再將其顯示在畫布上就大功告成了
其實這個作業跟之前的作業有相似之處,
如果稍微想一下就可以完成了
因為是要將每個點的RGB值讀出來
所以先用個for迴圈,再將其讀出的長寬設給變數
變成其FOR迴圈的條件,
for(j=iFileHeight;j>0;j--)
for(i=0;i
offset=offset+3; //記憶體存放位置 以3個BIT(RGB)為一個像素
}
這樣就可以成功將圖片讀出來囉,大功告成。
對於原本搞不懂記憶體存放位置等相關資訊的我弄了好久,
用pspad去看,加上老師上課提到的資訊拼拼湊湊,
終於懂9成了,我還發現如果使用另存新檔方式存放的圖片不能順利開檔(jpg->bmp),
有些同學好像也會,自己去猜好像是因為jpg檔式壓縮方式儲存的,所以轉檔可能會造成讀檔有問題(純屬猜測)。
最近,我覺得上課提問題很重要,
因為會提問題代表著自己知道哪邊不懂,意味著自己有去思考,
只是平常的我都不太敢問,但看著班上同學都會找老師問問題,
自己不禁也提起了勇氣把不懂的地方向老師請教,
我知道,
如果真的懂了,那種成就感是很快樂的。
HW4
一直不斷加上去的功能讓整個程式碼變的很雜亂
雜亂的原因是由於我致力於架構出"像樣點"的Software
所以大量用到顯示/隱藏、可使用/不可使用的屬性
例如:
之前的開啟圖檔後Show informations或轉成grayscale的功能
為了避免尚未load image就按下Buttom而造成錯誤
所以在load image前,Buttom屬性是設定成Disable的
當功能越多,判斷越多,開關越多的情況下
每每一個Buttom_click的function就要先佔掉一面的控制開關
不知道有沒有辦法可以好好整頓整頓那些雜亂的開關..
而這次作業上一次課堂上就做出來了
老實說是不經意的抓以前的程式碼變造的
//為什麼說不經意..原因有二
//一是因為我都是在筆電上處理BCB,而那個禮拜沒帶
//程式碼都在筆電裡,要重新拉出一堆物件
//還沒開始作作業應該都要下課了..
//另一個原因是期中考殺很大的必修要看不完了
//實在沒心思去寫程式,後來書越看越煩所以又跟同學借程式來試作
也因為沒有遇到什麼大到難以克服的問題
所以我認為是不怎麼困難的
倒是後來老師提出來的疑問還真的讓我咦了好大一下
fseek指向,然後用fread讀後
指標應該是理所當然的指向讀取的最後一個byte尾
但是如果把fseek抽離構圖迴圈,單留fread在裡面讀
會發生無法預期的狀況,解釋不出來的現象,還頗匪夷所思的...
因為電腦在期中考週的前一天故障
造成這個作業沒有充分的時間達到自己架構的模樣
(補充:作業五已實現)
程式初始如下:
從MainMenu選擇繪圖...就會讀取設定好的指定位置的檔案,開始繪圖
(畫到一半的時候)
讀檔完成後會一併Show出檔頭資訊
比較要注意的地方應該是Bitmap檔頭奇異的儲存格式:
1.順序不是以R, G, B方式排序,而是以B, G, R排序
2.儲存的像素點是從左下到右上
(這尤其奇怪的,Image的左上座標是(0,0),右下是(X_MAX,Y_MAX)
就算是(0,0)倒反,也應該是從(X_MAX,Y_MAX)到(0,0)
但是這是題外話,一開始就沒有被這個排序規則搞到
因為找到了色彩值的檔頭位置後
為了要確定的確是某像素點的顏色
就組合起來比對,一下就發現像素點是從左下開始向右排序
)
原本的計畫是:
在繪圖的時候開啟一個新的Form或Frame來做繪圖的動作
繪圖完成後再把圖像Load到Image的物件中
再另外彈出一個Form/Frame來Show檔頭資訊
這部分還要稍微Serch一下參考範本;
而開啟的檔案路徑目前是寫死的
理想中是拉一個textbox讓使用者輸入檔案路徑
不過這樣一來雖然程式變的較人性化
但是要使用者輸入檔案路徑好像也是件麻煩事
因為要預防格式輸入錯誤去做判斷
而使用者要自己輸入路徑+檔名用起來也很不方便
HW4
在這次的開BMP圖檔的作業中,是要以C語言中檔案存取的指令(fopen,fread,fseek...)來開啟,
而不是使用c++builder裡所內建的Image1 -> Picture -> LoadFromFile...來開檔。
我們在之前的作業三當中已經利用fopen,fread,fseek指令來讀取圖檔資訊(檔案大小,圖片高寬等等)
若想要將影像秀出螢幕上,我們勢必要先讓fseek指標指到影像原始碼的位置(原始碼的部分可由PSPad這套軟體來檢視),
然後再用fread去讀,我們讀到的東西會先擺入一個陣列中,陣列有3個空間分別來擺放色彩R,G,B值,而這RGB值就可以表示一個像素"點",不過程式只這樣寫還不夠,如此讀到的只有一個像素點而已,因此我們必須要用兩個迴圈來寫,外迴圈是跑圖的高的部分,內迴圈是跑圖的寬的部分,而程式的大鋼就是如此。
在這次的作業中,fopen,fread,fseek這些指令經過前面幾次的練習都熟悉的差不多了,沒有甚麼大困難
,而比較會有問題的地方大概會在讀檔時該用怎樣的讀法?一次讀幾個byte?讀到的東西該暫存到怎樣的資料型態?然後在怎樣丟入image中?丟完後指標該怎麼指?
基本上這些問題排除了,那程式也差不多會寫了,其實程式還滿短的,自己寫完後也覺得不算太難!
2009年11月25日 星期三
HW4
其實上上星期上課的時候就懂用fopen去讀整張圖的RGB組成 然後印在image上的觀念
但是fseek(imBMP,offset,SEEK_SET)
和 Image1->Canvas->Pixels[j][i]=(TColor)RGB(R,G,B)
這兩行程式讓我很無法理解,嘗試很多不同方法才找到解法
(1)首先fseek那邊最大的問題出在offset的設置一開始我用for迴圈從54開始跑,每跑完一次就執行offset+=6;範圍設<=圖長*寬+54,因為我以為fread(bsize,1,6,imBMP)是代表一點RGB占掉6個位元組,但發現這完全不對,後來找到問題是因為圖片每一點的RGB組成是由3個位元組來定義,所以正確的設置for迴圈是要讀取到一點RGB後,offset+=3,範圍設<=圖的長*寬*3+54才正確,往後才可以正確讀取到下一點RGB
(2)而第二個問題是Pixels[j][i], i 和 j 的設定,我只知道BCB的點和VC的行列剛好顛倒,但實際去描點的時候發現圖會整張呈現非常詭異的情況
就只能說跟我想像的完全不一樣,老實說我也不懂問題出在哪,最後是看著圖想像程式碼的執行狀況去修改 i , j 的值 (這樣講好像有點豪洨..) 不過我真的不懂BCB她是怎麼描點的 希望這部分老師可以詳細講解 , 因為我設定的數值就是跟圖完全相反的方向(也就是跟我以為正常的方向相反)就好像是倒過來描的(不好意思 我不太會解釋)
這次程式可以說我是碰巧打出來的... 因為我也不太懂為什麼這樣會正確,另外還有一點,我描出來後圖會有色差 不知道在網路上PO圖看不看得出來,這點我也不知道怎麼解釋,希望老師可以就這幾個來解釋 感謝!!
-----------------------------------------------------------
09.11.26更新
-----------------------------------------------------------
今天上課的時候問完老師大概懂問題出在哪了!!
問題1.原來fread(bSize,1,6,imBMP)我根本讀錯了,RGB只有三個bytes,
改成fread(bSize,1,3,imBMP)就對囉!!也解決色差的問題 happy~~
問題2.為什麼圖顯示出來會整個顛倒?? 老師說圖檔的RGB會有兩種存放的方式 一種是從前面開始放,另一種是從後面開始放,所以不是描點的問題,是BMP檔她裡面本來就會有不同的存放方式
終於解決了昨天的兩個問題 不過今天發現另一個問題!!!
我讀取了三張圖檔 第一張最大(下面露出馬腳) 第二張中等覆蓋在第一張上面
第三張是左上的小紅傘
我嘗試過修改掉這個小缺點,我拉了一個Button 來做delete Image1的功能
按下去後圖檔確實會消失,但當我再次讀取圖檔的時候發生了下列的錯誤!!
然後指向Image1->Cavas->Pixels[i][j]....的這行程式碼(此為描點的程式碼)
希望老師或同學能告訴我問題出在哪,希望能解決圖檔重疊的問題
HW3
這次作業是要把BMP的圖檔讀出,這是我設計的程式草稿。用上一次作業的程式改的,看著程式功能越來越多,就會有種得意的感覺,但這些都只是一些皮毛而已。 由於沒吸收到課堂上的資訊,程式打起來非常吃力,只能看著範例程式,慢慢研究了解。
這是執行的結果,一開始執行的時候遇到一點困難,就是頭檔資料顯示一直不正確,dword 一直都只有第一個數字有值,其他都0。後來發現是我fread函數參數設錯,果然寫程式前要先了解函式的結構啊,這次還用到了fopen 和fseek C語言的函式,學的越來越多要記的也越來越多,這也是好事啊!
2009年11月6日 星期五
HW3
這次作業花了我很多時間在處理跟程式寫作無關的東西
因為這次要使用最原始的C語言去開一個BMP圖檔
為了避免與之前做的檔案混淆或是部分功能衝突
重新思考必做一個新的UI
Program Name:SourceBMP
Version: 0.01 alpha
功能:
讀取BMP的檔頭資料,並將其顯示出來
有興趣的人可以從這裡下載執行檔
這幾個禮拜老師要我們透過fopen fseek 與fread去開啟一個BMP檔案
讓我回去翻找高中時學習C的記憶
加上網路上查詢相關指令說明
馬上就能將圖檔載入並將部分檔頭輸出
指令說明:
fopen
這個是一在C語言中用來開啟檔案的指令,使用前必些要先載入stdio.h並用FILE * 變數去使用
使用方式
fopen("檔名","開檔的方式");//開檔方式分別有r w a r+ w+ a+
ex: fopen("abc.txt","r")
因為太久沒有用過所以一開始開檔方式直接用w
結果造成BMP的原始資料被破壞
與老師研究弄老半天才發現這個問題
所以以後透過fopen開檔時一定要注意自己的使用需求
fseek
這個可以直接指定要從檔案哪個地方讀取
使用方式
fseek(檔案的變數名稱,位置,位置從哪個地方算起);
ex: fseek(file,1,SEEK_SET);
第三個參數有三種方式可選擇
SEEK_SET從開頭
SEEK_END從結尾
SEEK_CUR目前的指標位置(這個沒有試過)
fread
這個是用來抓取檔案資料的通常搭配fseek使用
使用方式
fread(抓取資料後放置的空間,抓幾個byte,總共抓幾個byte,抓取資料的位置)
ex: fread(buf,1,2,file);
以上都是我參考一些文件後的心得,不曉得有沒有錯
講完了指令
現在要講得是我在寫程式時遇到到的問題
因為我是使用C++Builder2010(BCB的新版本)
一開始在fopen裡面直接寫絕對路徑時都沒問題
但將路徑改為動態抓取時
原本的fopen(OpenPictureDialog1->FileName.c_str(),"r");
Compile不會過
一直卡在這個問題
後來透過BCB給的錯誤訊息上網爬文
才知道自從BCB2009版以後加入了Unicode的問題
官方為了解決這個問題後來又另外洗了一個叫t_str()的函數
所以2009版以後要改成fopen(OpenPictureDialog1->FileName.t_str(),"r");
這樣才能完整的通過
至於為啥官方要這樣做網路上的資料並不多
或許改天自己研究一下這個函數的原型
解決了檔案名稱的問題
接下來就是重頭戲讀取BMP檔頭資料
BMP的組成如上圖所示
第一區塊儲存的像是檔案類型 檔案大小等
第二區塊儲存的像是檔案長寬 位元格式等
詳細資料都能在wiki上找到
第三區塊儲存的是色彩的索引值為4的倍數儲存
不夠的話會以0補齊
第四區塊就是記錄圖檔每個像素點的顏色資訊
其實這次程式不難
把BMP格是文件與指令文件看得懂
並套用老師給的結構
程式就只要注意不要抓錯位置就好了
難在是根本不肯去做
很多問題的解決方式網路上或是鍵盤上按F1都可以找到相關訊息
資訊日新月異
學資工的就是要多多涉獵各東西
就算沒聽過也要有最基本的查資料能力
如果說這都沒有
每天只會耳邊聽耳機,左手遊戲機or手機,右手滑鼠Facebook
然後只會抱怨機器很爛等等
這些都不是理由
重點是有沒有心而已
有心要把程式寫好的話就算沒有電腦
隨便拿張紙片都能寫下腦袋中的想法
我自己也有類似的體驗(睡覺時腦袋還在想 醒來就OK了)
以上這小段純粹是自己看到別人的情況外加努力去做事卻跟著被老師錶三節課的感想以及抱怨
為何乖乖做事的人總是會跟著被罵勒? 此題真的是無解阿~
WH3
HK3
老師給我們看一位工程師寄信專程來問老師題目
HW3
HW03
這次作業是要將圖片的詳細內容給讀出來,
聽到老師說要讀記憶體位置,對於記憶體位置,真的有點給他搞不懂。
今天主要的課程是要使用fopen,fread,fseek。
老師說這是最基本的幾個指令
對於初學的我只能上網去查資料了
唯一有接觸過的只有fopen,用來開啟檔案,並且配合fclose來將指令關閉,避免浪費記憶體。
fread表面看起來就是"閱讀",沒錯!他就是閱讀fread(變數名稱,幾次,幾個,檔案名稱)
fseek則是尋找,我們這次得作業是拿來尋找要讀的記憶體位置的開頭,以指標的形式將他指向讀檔的開頭 fseek(檔案名稱,記憶體存放位置(開頭),SEEK_SET(指向這裡))
fseek先是將要讀記憶體的位置找到後,在使用fread將資料讀出來。
瞭解了大概做法之後就開始實做了
設變數部分我參考老師的設法,有使用byte、int、char
在課堂上其實我不是很了解這些設定的方式
是回到宿舍後才了解的,byte拿來接收讀到的byte
可能是沒用過吧 還真是不習慣。
接著就開始尋找讀檔位置了
聽老師說,可以在維基找到記憶體儲存位置
當然就上了維基
也找到了相關的記憶體存放位置
然後利用fseek將裏頭的資料取出來 ,接著就將它顯示在label中 。
其中:水平解析度和垂直解析度我卻讀不出來
當下也詢問老師,老師使用pspad將記憶體的存放圖show出來,發現維基上的存放位置竟然在pspad上出現是空的!! 這個地方我就不太懂了。
BYTE bSize[4]={0,0,0,0};
int iFileSize,iFileWidth,iFileHeight;
char cBuffer[3];
OpenPictureDialog1->Execute();
Image1->Picture->LoadFromFile(OpenPictureDialog1->FileName) ;
FILE *fp; //宣告檔案名稱
fp = fopen(OpenPictureDialog1->FileName.c_str(),"r") ; //檔案名稱,"r"//閱讀
fread(cBuffer, 1, 2, fp); //讀標頭檔
Label8->Caption=cBuffer;
fread(bSize, 1, 4, fp) ;
iFileSize = bSize[0] + bSize[1] * 256 + bSize[2] * 256*256 + bSize[3] * 256*256*256;
//將讀到的byte作運算
Label10->Caption=iFileSize;
fseek(fp,18,SEEK_SET);
fread(bSize, 1, 4, fp) ;
Label11->Caption=iFileWidth;
fseek(fp,22,SEEK_SET);
fread(bSize, 1, 4, fp) ;
FileHeight = bSize[0] + bSize[1] * 256 + bSize[2] * 256*256 + bSize[3] * 256*256*256;
fclose(fp); //關閉fopen
(上面只有部分程式碼,怕太多占版面)
HW3
2009年11月5日 星期四
HW3
經過老師一堂課多的"自我檢討",我更能感受到老師認為我們的未來前途茫茫,不只是努力的教作業和應付考試而已,重點是要會"寫程式",說真的挺多老師說過主任也是,"只要會寫程式就很有用了",但是這"寫程式"的定義,是真的要會寫程式,不是寫寫簡單又小的程式,也不是頻頻和老師同學討論,更不是copypaste,以後在職場上通常都是要靠自己,要多利用身邊工具,網路、書籍等等,所以從現在開始我們就要習慣利用身邊各種資源,以後找資料就會更輕易上手,當然趁現在可以討論還是必要的。
這次交了fopen,fread,fseek,如果真的只看程式碼還真看不懂,而且fseek還需要位元組的位置才能找到檔案的資料,還有同學po了fopen,fread,fseek三個指令的說明,非常細心,也要感謝他讓我更了解一些,老師也幫我們解決了像素點的問題,單位要以公尺換公寸,所以100/2.54約等於39.37,所以就再除以39.37就正確了,現在還有個問題,cbuffer會出現亂碼,還有有些BMP檔的解析度會為0,感覺還是有很多問題待解決啊!
HW3
這次作業用新的東西fopen & fread & fseek
bmp檔 這次作業用到的表頭
起始位元組 所占位元組數 具體內容 標識
1 2 檔案類型(windows點陣圖為“BM”)bfType
3 4 文件大小 bfSize
19 4 點陣圖的寬度 biWidth
23 4 點陣圖的高度 biHeight
39 4 點陣圖水準分辯率(像素/米) biXPelsPerMeter
43 4 點陣圖垂直分辯率(像素/米) biYPelsPerMeter
擷取檔案格式
imBMP = fopen(OpenPictureDialog1->FileName.c_str(), "r")
擷取檔案大小
fread(bSize, 1, 4, imBMP)
擷取檔案寬度
fseek(imBMP,18,SEEK_SET)
擷取檔案長度
fseek(imBMP,22,SEEK_SET)
擷取水平解析度
fseek(imBMP,38,SEEK_SET)
擷取垂直解析度
fseek(imBMP,42,SEEK_SET)
使用fseek可以直接抓取Bitmap File Header裡面你想要項目,不用像fread要抓取前面的空間不用的空間,但是抓取出的值會是 (像素/公尺)所以要除上39.37才會變成英吋!