全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:4422
推到 Plurk!
推到 Facebook!

TPicture 之 LoadFromStream 問題

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


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

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-01-19 12:45:13 IP:61.216.xxx.xxx 訂閱
您好:

小弟目前有一個 unsigned char array 的 row data 像素排列是以 RGB 的順序擺放在此陣列中

像素一 像素二 ...
unsogned cgar array => R G B R G B ...

那我現在想要直接把這個陣列裡頭的資料放到 TPicture 當中,利用 LoadFromStream( TStream* ) 的方式

去查了一下 TStream 類別,有一個成員函式叫做 ReadBuffer( void *buffer, int count ); 好像用這個就可以了喔?

( 想確定一下方向是否正確,因為小弟還在花時間讀資料,建構那個 unsigned char array )

另外有一個問題,如果這時候我的 unsigned char array 裡頭放的是灰階的像素值,那 TPicture 會如何判斷

LoadFromStream 的內容是灰階還是彩色?
謝謝
arisaka_matsuri
高階會員


發表:25
回覆:205
積分:231
註冊:2003-10-19

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-01-20 12:15:21 IP:218.166.xxx.xxx 訂閱
如果已經有一個array
是可以用TStream::ReadBuffer()來讀取陣列資料的
但是,單純把該TStream物件丟給TPicture
是沒有辦法正確顯示影像的
因為還缺少bmp檔頭的部份,翻一下站上文章或MSDN
另外,Windows下BMP影像的RGB擺放的順序
一般是B G R B G R ....讓你參考

你的最後一個問題的答案:由BMP檔頭決定
TPicture不會知道你的資料格式是什麼
只會知道是不是 Windows Bitmap
linly
一般會員


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

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-01-20 18:01:38 IP:61.216.xxx.xxx 訂閱
謝謝您的解說,我的確缺少檔頭的部分需要補上,不過只限定 BMP 嘛? 像是 PPM、PGM 這種簡單的表頭認得嘛? 
( [註] 我有把GraphicEx 放到我的專案中,所以 LoadFromFile 可以處理更多格式,LoadFromStream 不知是否也行 )

===================================== 分隔線 =====================================
小弟在此把問題描述一遍:
把 100~200 張圖片,每張圖片依序讀入並對 row data 作一些處理,所以處理後的像素資料就放在一個 unsigned char array ( 以RGB的方式擺放,如原文所述 ),然後要把這些資料塞給 TImage 元件來呈現,所以說會有 100~200 個 TImage 元件在我的 Panel 上面。( Panel 放在 ScrollBox 上面,用捲軸瀏覽 )

因此除了原先找到的 LoadFromStream 以外,小弟想到另一種方式,既然說我已經有 row data 的 unsigned char array,我直接把點指派給 Timage::TCanvas::Pixels 可以達到我的需求,而不以 LoadFromStream 這種方式。不過這樣一個個點指派有點慢,畢竟有大約 100~200 張圖片,每張圖片大小是 12xx 乘以 14xx,所以說有比較有效率的方式來處理這個問題嗎?( 主要是秀在 GUI 上會慢 )


感恩

新年快樂
編輯記錄
linly 重新編輯於 2008-01-20 18:02:46, 註解 無‧
linly 重新編輯於 2008-01-21 11:58:01, 註解 無‧
linly 重新編輯於 2008-01-21 11:59:07, 註解 排版一下‧
arisaka_matsuri
高階會員


發表:25
回覆:205
積分:231
註冊:2003-10-19

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-01-21 16:11:23 IP:140.113.xxx.xxx 訂閱
就我所知,Windows GDI下的影像顯示
都是靠著BMP的格式在處理
不管是哪個讀取檔案的library,最後都會把影像解壓縮or處理成BMP格式
只是有可能因為封裝的關係,所以無法接觸到實際的資料

TStream這類物件的操作,純粹提供低階的資料存取
不會過問資料的格式
因此ppm, pgm等格式當然不認得
要由程式撰寫的人來定義才行
所以我才會回覆說
TStream要處理raw image data當然可以
但是要正確顯示,得靠那個bmp的檔頭(格式定義)才行

關於你的問題
不知道處理是作哪些處理?
顯示之前,可以用Scanline填資料比用TCanvas::Pixels來得有效率
如果你的處理流程是

讀檔 --> 存入RGB陣列 --> 影像處理 --> TStream::ReadBuffer() 讀RGB陣列 --> LoadFromStream() --> 顯示

可以變成

讀檔 --> 存入 TBitmap --> 用Scanline來處理影像 --> Assign給TImage物件 --> 顯示

會不會好一點?不知道你的code,僅對流程上提供建議


===================引 用 linly 文 章===================
謝謝您的解說,我的確缺少檔頭的部分需要補上,不過只限定 BMP 嘛? 像是 PPM、PGM 這種簡單的表頭認得嘛?

[註] 有安裝 GraphicEx,所以像是 LoadFromFile 就可以支援域設格式 延伸的格式,不知道 TStream 支援程度如何?看到版大的回覆,該不會只吃 bmp???

感恩

新年快樂
編輯記錄
arisaka_matsuri 重新編輯於 2008-01-21 16:33:02, 註解 回覆新增的問題描述‧
linly
一般會員


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

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-01-21 17:55:18 IP:140.113.xxx.xxx 訂閱
謝謝您的建議,不過因為程式的一些限制,處理後的 row data 就是以一個 unsigned char array 的方式儲存( 每個像素依序式 R G B ),然後我只能以這個陣列把像素塞給 TImage,不過看到您所給的建議,我統整一下做法:

產生一個 TStream 物件,然後此物件的內容要包含 bmp 的表頭加上我的 array 中所儲存的 row image data ( 不過在此要注意擺放方式,應該要以 B G R 的方式 ),最後,當我把這個 TStream 建立完成後,就以 TImage::TPicture::LoadFromStream( TStream * ); 這樣應該就可以了吧?

謝謝 : )
linly
一般會員


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

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-01-24 08:57:05 IP:218.168.xxx.xxx 訂閱
已成功利用 TMemoryStream,把 row data + bmp header 給塞進去,不過有三點值得注意:

1. BCB 的 Help 當中描述 TPicture 有 LoadFromStream,結果非但不能使用,就連提示字都沒有出來,十分怪異,不知道是為什麼,所以就改用 TImage::TPicture::TBitmap::LoadFromStream( TStream* ) 給解決。

2. 當使用 TImage::TPicture::TBitmap::LoadFromStream( TStream* ) ,記得把 TMemoryStream 的 Position 給歸零,例如:

[code cpp]
TMemoryStream *memStream = new TMemoryStream();

// 設定大小與初始化(?)
memStream->SetSize((width*3 append)*height 54);
memStream->Clear();

// 寫檔頭與資料
memStream->Write(BMPHeader,54);
memStream->Write(data,(width*3 append)*height);

// 要把 Position 歸回零,這樣 Image 元件才可以從 stream 的頭開始讀
memStream->Position = 0;
Image->Picture->Bitmap->LoadFromStream(memStream);

delete memStream; // 養成好習慣
[/code]

3. bmp 有一點限制是說:如果每一列的像素點不是 4 的倍數,就必須在後面補像素 ( 我是補零,不過補甚麼應該都沒差才對!! ),例如:24 位元(RGB) 的點,圖片寬度為 15

除以四的餘數 45 mod 4 = 1
每列需要補的像素個數 4 - 1 = 3

以前應該有描述,不過在此重做說明,也感謝本討論串給予建議的版友。

編輯記錄
linly 重新編輯於 2008-01-24 08:58:26, 註解 排版‧
linly 重新編輯於 2008-01-24 09:00:46, 註解 無‧
系統時間:2024-04-27 11:58:18
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!