線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:2946
推到 Plurk!
推到 Facebook!

Full Debug 和 Release 的設定

答題得分者是:brook
linly
一般會員


發表:42
回覆:37
積分:15
註冊:2007-10-07

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-01-29 15:59:30 IP:140.113.xxx.xxx 訂閱
您好:

我在 BCB 的 "Project->Options->Compiler" 按下左下角 "Release" 按鈕,編譯出來的程式和 Full Debug 比較起來 ( 檔案大小與速度 ) 都差不多。

至於說程式在的事情是:把 unsigned char array[ 1300 x 1700 x 3 ] 這麼多 byte 的值( RGB ) 依序指派給 Image->Canvas->Pixel[][],程式片斷如下:


[code cpp]
unsigned char array data[1300 *1700*3];
...
...
unsigned char *p = data;
for ( i = 0 ; i < height ; i ) {
for ( j = 0 ; j < width ; j ) {
Image->Canvas->Pixel[j][i] = (TColor)RGB(p[0],p[1],p[2]);
p = 3;
}
}
[/code]

測試時這個動作做了三遍,產生三個 Image 元件,使用 Full Debug 和 Release 的執行檔速度都差不多慢,將近 20 秒。會被迫這麼做的原因是因為我圖片像素的來源並不是檔案,而是由其他文件資料轉來的,而且 unsigned char 的 row data 排列方式是圖片 「左上->右下 RGB」 的像素資料。本來想說 Release 版本的應該可以快個幾倍,想不到和 FullDebug 一樣慢 = =,想了幾天也還沒想到有什麼可以讓我快一點將 row data 丟給 Image 元件的方式。

Release 到底什麼情況下會比較好,我還想說他最佳化後應該可以幫助我不少 ~"~。
pcboy
版主


發表:177
回覆:1838
積分:1463
註冊:2004-01-13

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-01-29 16:51:05 IP:61.220.xxx.xxx 訂閱
跑得快的小程式, 是否移除 Debug 資訊可能影響看不出
如果是要執行很久, 吃系統資源很多的大程式, 可能比較看得出影響
------
能力不足,求助於人;有能力時,幫幫別人;如果您滿意答覆,請適時結案!

子曰:問有三種,不懂則問,雖懂有疑則問,雖懂而想知更多則問!
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-01-30 09:40:36 IP:61.64.xxx.xxx 訂閱
哇!真是巧合 Image 的安排也是 「左上->右下 RGB」
你不會用 MemMove 之類的方式嗎?搜尋一下吧!或看一下 MemMove 的 Help 你就會了

方法很多,可惜,剛好被你用到這種

Pixel 是最最最最最......最慢的方式

===================引 用 linly 文 章===================
您好:

我在 BCB 的 "Project->Options->Compiler" 按下左下角 "Release" 按鈕,編譯出來的程式和 Full Debug 比較起來 ( 檔案大小與速度 ) 都差不多。

至於說程式在的事情是:把 unsigned char array[ 1300 x 1700 x 3 ] 這麼多 byte 的值( RGB ) 依序指派給 Image->Canvas->Pixel[][],程式片斷如下:


[code cpp]
unsigned char array data[1300 *1700*3];
...
...
unsigned char *p = data;
for ( i = 0 ; i < height ; i ) {
for ( j = 0 ; j < width ; j ) {
Image->Canvas->Pixel[j][i] = (TColor)RGB(p[0],p[1],p[2]);
p = 3;
}
}
[/code]

測試時這個動作做了三遍,產生三個 Image 元件,使用 Full Debug 和 Release 的執行檔速度都差不多慢,將近 20 秒。會被迫這麼做的原因是因為我圖片像素的來源並不是檔案,而是由其他文件資料轉來的,而且 unsigned char 的 row data 排列方式是圖片 「左上->右下 RGB」 的像素資料。本來想說 Release 版本的應該可以快個幾倍,想不到和 FullDebug 一樣慢 = =,想了幾天也還沒想到有什麼可以讓我快一點將 row data 丟給 Image 元件的方式。

Release 到底什麼情況下會比較好,我還想說他最佳化後應該可以幫助我不少 ~"~。
linly
一般會員


發表:42
回覆:37
積分:15
註冊:2007-10-07

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-02-01 13:01:54 IP:140.113.xxx.xxx 訂閱
您好: 依照您所說的,我去看了一下 memmove 的用法,並做了以下的測試

[code cpp]
typedef struct {
int R; int G; int B;
} Color;

int main(int argc, char* argv[]) {
int a[] = {1,2,3,4,5,6};
Color b[] = {{0,0,0},{0,0,0}};

cout << "[a] ";
for (int i = 0; i < 6; i ) cout << a[i] << " ";
cout << endl;

cout << "[b] Origin ";
for (int i = 0; i < 2; i ) {
cout << b[i].R << " "; cout << b[i].G << " "; cout << b[i].B << " ";
}
cout << endl;

try {
memmove(b,a,24);
}
__finally {
cout << "[b] After memmove ";
for (int i = 0; i < 2; i ) {
cout << b[i].R << " "; cout << b[i].G << " "; cout << b[i].B << " ";
}
cout << endl;
}

system("pause");
return 0;
}
// [a] 1 2 3 4 5 6
// [b] Origin 0 0 0 0 0 0
// [b] After memmove 1 2 3 4 5 6

[/code]

可以把一段連續的記憶空間複製過去,即使把上述的 Color b[] 改成多為陣列也可以,不過小弟去看了一下 TImage 的屬性,應該就是把我的 row data 複製到 Pixels[][],不過無法做這樣的動作:

memmove( Pixels, data, width*height*3 ); Pixels 不就是紀錄陣列起始位置嗎!?!? 發生的錯誤訊息是 Can't convert TColor to void*

我是不是哪裡耍白爛了。

謝謝回覆的版友及版主

===================引 用 syntax 文 章===================
哇!真是巧合 Image 的安排也是 「左上->右下 RGB」
你不會用 MemMove 之類的方式嗎?搜尋一下吧!或看一下 MemMove 的 Help 你就會了

方法很多,可惜,剛好被你用到這種

Pixel 是最最最最最......最慢的方式
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-02-01 15:48:43 IP:61.64.xxx.xxx 訂閱
訊息跟你說的很明顯啦

需要的是 address 位址 ,你卻傳個 TColor 數值過去

改成 Pixels[][] 的位址即可

Pixels[width][height]

memmove(&Pixels[0], &data[0], width*height*3 );


===================引 用 linly 文 章===================
您好: 依照您所說的,我去看了一下 memmove 的用法,並做了以下的測試

[code cpp]
typedef struct {
int R; int G; int B;
} Color;

int main(int argc, char* argv[]) {
int a[] = {1,2,3,4,5,6};
Color b[] = {{0,0,0},{0,0,0}};

cout << "[a] ";
for (int i = 0; i < 6; i ) cout << a[i] << " ";
cout << endl;

cout << "[b] Origin ";
for (int i = 0; i < 2; i ) {
cout << b[i].R << " "; cout << b[i].G << " "; cout << b[i].B << " ";
}
cout << endl;

try {
memmove(b,a,24);
}
__finally {
cout << "[b] After memmove ";
for (int i = 0; i < 2; i ) {
cout << b[i].R << " "; cout << b[i].G << " "; cout << b[i].B << " ";
}
cout << endl;
}

system("pause");
return 0;
}
// [a] 1 2 3 4 5 6
// [b] Origin 0 0 0 0 0 0
// [b] After memmove 1 2 3 4 5 6

[/code]

可以把一段連續的記憶空間複製過去,即使把上述的 Color b[] 改成多為陣列也可以,不過小弟去看了一下 TImage 的屬性,應該就是把我的 row data 複製到 Pixels[][],不過無法做這樣的動作:

memmove( Pixels, data, width*height*3 ); Pixels 不就是紀錄陣列起始位置嗎!?!? 發生的錯誤訊息是 Can't convert TColor to void*

我是不是哪裡耍白爛了。

謝謝回覆的版友及版主

===================引 用 syntax 文 章===================
哇!真是巧合 Image 的安排也是 「左上->右下 RGB」
你不會用 MemMove 之類的方式嗎?搜尋一下吧!或看一下 MemMove 的 Help 你就會了

方法很多,可惜,剛好被你用到這種

Pixel 是最最最最最......最慢的方式
linly
一般會員


發表:42
回覆:37
積分:15
註冊:2007-10-07

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-02-03 14:15:41 IP:218.168.xxx.xxx 訂閱
小弟愚昧,實在不清楚該怎麼把  TImage::TCanvas 當中的 Pixels 陣列位址給傳進去,怎麼傳都會說 GetPixel 參數不夠、Can't convert TColor to void*,我了解您所傳達給我的意思,不過還是失敗,真是不好意思,還請指正。

[code cpp]
// size = width*height*3
// data is a unsigned char array
// 第一個參數的形式會是
// &(pImage->Canvas->Pixels[0]) ??
memmove( /*填失敗*/, &data[0], size );
[/code]

另外就是說:TImage::TCanvas::Pixels 是一個二維陣列,那 Pixels 就會是位址了不是嗎?? 我就做了把一維陣列的值複製給二維陣列

[code cpp]
int a[6] = {1,2,3,4,5,6 };
int b[2][3] = { {0}, {0} };
memmove( b, a, 24 );
[/code]

十分感謝您的建議與回覆


===================引 用 syntax 文 章===================
訊息跟你說的很明顯啦

需要的是 address 位址 ,你卻傳個 TColor 數值過去

改成 Pixels[][] 的位址即可

Pixels[width][height]

memmove(&Pixels[0], &data[0], width*height*3 );
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#7 引用回覆 回覆 發表時間:2008-02-04 04:14:09 IP:61.64.xxx.xxx 訂閱
是的,你會失敗的

&Pixels[0] 並不是真的要你用「&Pixels[0]」
他只是一個提示,提示你 & 要用位址,取 Pixels 或 Pixels[0] 或 Pixels[0][0] 的位址

至於位址如何找,我以為你可以處理得來

這樣看來,你對 TImage 並不是很瞭解

Image->Canvas->Pixel 只是 Windows 機制的封裝,並沒有另外真的提供/複製一個儲存的記憶體位址
所以該 array 只是一個假象,所以當然是無法提取記憶體位置

你沒有相關知識,我也無從解釋起,如果要你去自己處理 DC來抓取位址 ,那應該會讓你瘋掉吧

這樣我們只好轉個彎
步驟如下:
1. 建立一個 TMemoryStream
2. 建立一個指標參數 k,並賦予值為 TMemoryStream.Memory
3. k = k 54,54 是 BMP 的 Header,之後才是資料
4. 將你要使用的 TImage 設定好長寬,使用的長寬是你將要複製進去的大小( data 的長寬)
看你要使用 TImage 的長寬,或是 TImage->Picture->Bitmap 的長寬來設定,哪一個好呢?這留給你
5. TImage.Picture.Bitmap.SaveToStream(TMemoryStream);
為什麼要這樣做?主要是複製正確的 Header 過來
如果你會設定 BMP Header, 4 與 5 可以略過,你自己設定 TMemoryStream 內的內容
6. 使用 MemMove(k, data, data size) k 與 data 都是指標型態
將資料設定進去 TMemoryStream
7. TImage.Picture.Bitmap.LoadFromStream(TMemoryStream);
將資料貼回去

這樣的作法,最不需要理會底層原理,速度也不會比直接操作 DC API 慢
手續也簡單許多,至少比用 API 簡單,程式碼大約 10 來行就可以解決

這樣就可以繞過 TImage 唯讀與封裝類型屬性的不便

答案就是這樣了,如果你有興趣,可以把使用 DC API 的方式,貼出來,我們再來品質如何

如果你趕著作成果,那此法最快,不需額外吸收知識,馬上見效

===================引 用 linly 文 章===================
小弟愚昧,實在不清楚該怎麼把 TImage::TCanvas 當中的 Pixels 陣列位址給傳進去,怎麼傳都會說 GetPixel 參數不夠、Can't convert TColor to void*,我了解您所傳達給我的意思,不過還是失敗,真是不好意思,還請指正。

[code cpp]
// size = width*height*3
// data is a unsigned char array
// 第一個參數的形式會是
// &(pImage->Canvas->Pixels[0]) ??
memmove( /*填失敗*/, &data[0], size );
[/code]

另外就是說:TImage::TCanvas::Pixels 是一個二維陣列,那 Pixels 就會是位址了不是嗎?? 我就做了把一維陣列的值複製給二維陣列

[code cpp]
int a[6] = {1,2,3,4,5,6 };
int b[2][3] = { {0}, {0} };
memmove( b, a, 24 );
[/code]

十分感謝您的建議與回覆


===================引 用 syntax 文 章===================
訊息跟你說的很明顯啦

需要的是 address 位址 ,你卻傳個 TColor 數值過去

改成 Pixels[][] 的位址即可

Pixels[width][height]

memmove(&Pixels[0], &data[0], width*height*3 );
編輯記錄
syntax 重新編輯於 2008-02-04 04:20:12, 註解 無‧
linly
一般會員


發表:42
回覆:37
積分:15
註冊:2007-10-07

發送簡訊給我
#8 引用回覆 回覆 發表時間:2008-02-04 10:33:14 IP:218.168.xxx.xxx 訂閱
設定 TMemoryStream 的方式我在先前文章有爬到,也看到設定表頭可以利用 BitmapHeaderInfon、BitmapFilterInfo 的結構來輔助設定,不過當時在用這種方式時,就發現如果我把我的 row data(左上->右下 RGB) 就直接設定到 TMemoryStream 當中,這樣出來的圖片,會變成

1. 上下顛倒且顏色不對,所以我當時甚至還把點的像素重排才放到 TMemoryStream 中( 不過這樣就和直接指派到 Pixel[][] 沒啥兩樣了 )。

2. 如果圖片的 (寬*3)%4 非整除還要補點 ( 當然讓寬變成四的倍數就無須補點 )

因此特來請教您與版友們。

感謝您不遺餘力的說明,萬分感謝
編輯記錄
linly 重新編輯於 2008-02-04 10:55:54, 註解 無‧
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#9 引用回覆 回覆 發表時間:2008-02-04 11:56:42 IP:61.64.xxx.xxx 訂閱
不知是誰規定你 「左上->右下」,你的老闆嗎?
一定要這樣傳進去?那就無解了!
如果不是,用一下大腦 OK ?
你可以每一 row 作 MemMove,總會比 one by one 快
倒著 Move ,不就轉成 左-下>右上?你腦筋太死喔!

顏色不對,表示色盤不對,必須修改色盤

如果你要作無失真縮放點陣圖,請爬文,內已有相關文章,不然 Google 也會有一堆演算法可以給你看
如果不是,缺的地方,統一填入任一顏色作底色即可

寫程式,不是 if ... then 會用就叫寫程式,有空多用大腦思考,才會進步
寫程式,用手即會寫
設計程式,必須用到大腦思考!

顯然,你很需要多作腦筋急轉彎,不要懷疑,多作腦筋急轉彎,作腦筋伏地挺身,有好處的啦!
因為,其實你的問題,所需資訊早已充足,早就可以解決,可惜你自己看不出來

===================引 用 linly 文 章===================
設定 TMemoryStream 的方式我在先前文章有爬到,也看到設定表頭可以利用 BitmapHeaderInfon、BitmapFilterInfo 的結構來輔助設定,不過當時在用這種方式時,就發現如果我把我的 row data(左上->右下 RGB) 就直接設定到 TMemoryStream 當中,這樣出來的圖片,會變成

1. 上下顛倒且顏色不對,所以我當時甚至還把點的像素重排才放到 TMemoryStream 中( 不過這樣就和直接指派到 Pixel[][] 沒啥兩樣了 )。

2. 如果圖片的 (寬*3)%4 非整除還要補點 ( 當然讓寬變成四的倍數就無須補點 )

因此特來請教您與版友們。

感謝您不遺餘力的說明,萬分感謝
brook
資深會員


發表:57
回覆:323
積分:371
註冊:2002-07-12

發送簡訊給我
#10 引用回覆 回覆 發表時間:2008-02-05 12:36:15 IP:219.80.xxx.xxx 訂閱
用Image->Canvas->Pixel[j][i] = (TColor)RGB(p[0],p[1],p[2]); 當然會很慢
建議用 ScanLine 可快將近10倍.
linly
一般會員


發表:42
回覆:37
積分:15
註冊:2007-10-07

發送簡訊給我
#11 引用回覆 回覆 發表時間:2008-02-16 19:30:00 IP:218.168.xxx.xxx 訂閱
謝謝!!  的確快上不少~

也謝謝 syntax 前文的指教

===================引 用 brook 文 章===================
用Image->Canvas->Pixel[j][i] = (TColor)RGB(p[0],p[1],p[2]); 當然會很慢
建議用 ScanLine 可快將近10倍.
系統時間:2024-03-29 10:09:47
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!