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

為什麼判斷不出是15位元的圖片?

答題得分者是:senso
encoref70036
一般會員


發表:29
回覆:47
積分:15
註冊:2011-05-18

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-09-06 19:34:08 IP:114.26.xxx.xxx 訂閱
以下是程式碼:
[code cpp]
void __fastcall TForm1::Button1Click(TObject *Sender)
{
if(OpenDialog1->Execute())
{
Image1->Picture->Bitmap->LoadFromFile(OpenDialog1->FileName);
}
Graphics::TBitmap *bmp = new Graphics::TBitmap();
Graphics::TBitmap *bmp555 = new Graphics::TBitmap();
bmp->Assign(Image1->Picture);//24位元圖片
int w=bmp->Width;
int h=bmp->Height;
bmp555->PixelFormat=pf15bit;
bmp555->Height=h;
bmp555->Width=w;
Byte R,G,B;
for (int y=0;y {
Byte *ptr = (Byte*)bmp->ScanLine[y];
Word *ptr555 = (Word*)bmp555->ScanLine[y]; //unsigned short 0..65535
for (int x=0;x {
B = ptr[3*x ]>>3; //5-bit blue
G = ptr[3*x 1]>>3; //5-bit green
R = ptr[3*x 2]>>3; //5-bit red
ptr555[x] = R<<10 | G<<5 | B;
}
}
Image1->Picture->Bitmap->Assign(bmp555);
delete bmp,bmp555;
}
[/code]
開出來後 影像正常 我把影像存起來
然後用程式判斷他是不是15位元 如下:
if (Image1->Picture->Bitmap->PixelFormat == pf15bit)
{
Label1->Caption = "15位元圖片";
}
但是Label1上並沒有顯示說"15位元圖片"
請問是為什麼呢?
是因為word是16位元無正負號整數的關係嗎
可是我看help 好像沒有15bit的 參數型式耶
編輯記錄
encoref70036 重新編輯於 2011-09-06 06:40:03, 註解 無‧
senso
高階會員


發表:5
回覆:126
積分:226
註冊:2003-11-27

發送簡訊給我
#2 引用回覆 回覆 發表時間:2011-09-07 14:23:06 IP:61.219.xxx.xxx 訂閱

[code cpp]
Graphics::TBitmap *bmp555 = new Graphics::TBitmap();
bmp555->PixelFormat=pf15bit;
TPixelFormat pf1 = bmp555->PixelFormat; //pf15bit
bmp555->Height=100;
TPixelFormat pf2 = bmp555->PixelFormat; //pf15bit
bmp555->Width=100;
TPixelFormat pf3 = bmp555->PixelFormat; //pfCustom
bmp555->PixelFormat=pf15bit;
TPixelFormat pf4 = bmp555->PixelFormat; //pfCustom
delete bmp555;

[/code]

小測一下,無論Height和Width先或後,都會變成pfCustom....
真神奇不曉得問題在哪....
senso
高階會員


發表:5
回覆:126
積分:226
註冊:2003-11-27

發送簡訊給我
#3 引用回覆 回覆 發表時間:2011-09-07 16:15:35 IP:61.219.xxx.xxx 訂閱


trace發現biCompression變成3(BI_BITFIELDS=565)
但dsBitfields mask還是555(biCompression 0 BI_RGB)的mask
詳細請參考 http://blog.pixnet.net/crazycat1130/post/1345538#mark-6

然後GetPixelFormat 的source code如下
一開始預設回傳是pfCustom
case biBitCount為16的時候,
當biCompression 為BI_RGB 回傳pf15bit
但biCompression 為BI_BITFIELDS多檢查dsBitFields[1] (綠色)mask才回傳pf16bit
[code cpp]
function TBitmap.GetPixelFormat: TPixelFormat;
begin
Result := pfCustom;
if HandleType = bmDDB then
Result := pfDevice
else
with FImage.FDIB, dsbmih do
case biBitCount of
1: Result := pf1Bit;
4: Result := pf4Bit;
8: Result := pf8Bit;
16: case biCompression of
BI_RGB : Result := pf15Bit;
BI_BITFIELDS: if dsBitFields[1] = $7E0 then Result := pf16Bit;
end;
24: Result := pf24Bit;
32: if biCompression = BI_RGB then Result := pf32Bit;
end;
end;

[/code]

至於Height和Width設完之後biCompression 為什麼會變成BI_BITFIELDS..
我還是不知道~_~
encoref70036
一般會員


發表:29
回覆:47
積分:15
註冊:2011-05-18

發送簡訊給我
#4 引用回覆 回覆 發表時間:2011-09-07 21:15:57 IP:114.26.xxx.xxx 訂閱
請問trace 要怎麼用呢?
所以biCompression要是BI_RGB 才會是pf15bit嗎
影像的Height和Width跟位元有關西嗎
你的意思是你那段程式碼出來的結果也是pfCustom嗎? 所以不是Word的關西囉
那要如何變成pf15bit呢?
我把上面程式改成這樣 還是不行.....
ptr555[(15*x)/16] = R<<10 | G<<5 | B;
所以是C 的問題嗎?
因為我後來直接開一張圖片 然後直接把Image1->picture->bitmap->pixelformat=pf15bit變成這樣 然後直接存起來
在判斷 結果還是pfCustom.....
編輯記錄
encoref70036 重新編輯於 2011-09-08 01:52:59, 註解 無‧
encoref70036 重新編輯於 2011-09-08 01:57:17, 註解 無‧
encoref70036 重新編輯於 2011-09-08 01:59:37, 註解 無‧
encoref70036 重新編輯於 2011-09-08 04:52:35, 註解 無‧
encoref70036 重新編輯於 2011-09-08 04:53:27, 註解 無‧
encoref70036 重新編輯於 2011-09-08 10:49:19, 註解 無‧
encoref70036 重新編輯於 2011-09-11 02:02:16, 註解 無‧
senso
高階會員


發表:5
回覆:126
積分:226
註冊:2003-11-27

發送簡訊給我
#5 引用回覆 回覆 發表時間:2011-09-15 15:49:24 IP:61.219.xxx.xxx 訂閱
1.程式碼左邊點一下設中斷點,F8逐行(不進函式)、F7跳進函式
2.biBitCount=16,biCompression=BI_RGB才會是pf15bit
不知道為什麼biCompression變成BI_BITFIELDS,所以GetPixelFormat都回傳pfCustom
3.pf15bit也是存16bit(2byte),前幾篇link再看一看....
4.不然就自己寫判斷...囧

[code cpp]
BITMAPFILEHEADER BmpFileHeader;
BITMAPINFOHEADER BmpInfoHeader;
DWORD dsBitfields[3];
TPixelFormat PixelFormat;
TMemoryStream *ms = new TMemoryStream();
//ms->LoadFromFile("D:\\senso\\temp\\640x480x15b.bmp");
bmp->SaveToStream(ms);
ms->Position=0;
ms->Read(&BmpFileHeader,sizeof(BmpFileHeader));
ms->Read(&BmpInfoHeader,sizeof(BmpInfoHeader));
if (BmpInfoHeader.biBitCount==16) {
ms->Position=14 BmpInfoHeader.biSize; //biSize通常40
ms->Read(dsBitfields,sizeof(dsBitfields)); //讀取mask
PixelFormat = pfCustom;
switch (BmpInfoHeader.biCompression) {
case BI_RGB: PixelFormat = pf15bit; break;
case BI_BITFIELDS:
if (dsBitfields[1]==0x03E0) PixelFormat = pf15bit;
if (dsBitfields[1]==0x07E0) PixelFormat = pf16bit; break;
}
}
delete ms;

[/code]

encoref70036
一般會員


發表:29
回覆:47
積分:15
註冊:2011-05-18

發送簡訊給我
#6 引用回覆 回覆 發表時間:2011-09-15 17:18:19 IP:114.26.xxx.xxx 訂閱
感謝您
是不是C 的問題
因為我開一張24位元圖片 然後做一個按鈕 按鈕的程式:Image1->Picture->Bitmap->PixelFormat=pf15bit; 然後把圖片存起來 圖片是pfCustom
如果按鈕是 Image1->Picture->Bitmap->PixelFormat=pf16bit; 然後存起來 圖片是pf16bit

請問一下RGB555每個像素也是用16位元表示、RGB分量都使用5位(剩下的1位不用)所以檔案大小也跟RGB565一樣囉?

編輯記錄
encoref70036 重新編輯於 2011-09-15 03:47:43, 註解 無‧
encoref70036 重新編輯於 2011-09-15 03:49:18, 註解 無‧
encoref70036 重新編輯於 2011-09-15 03:50:22, 註解 無‧
senso
高階會員


發表:5
回覆:126
積分:226
註冊:2003-11-27

發送簡訊給我
#7 引用回覆 回覆 發表時間:2011-09-15 19:32:58 IP:114.42.xxx.xxx 訂閱
大概是c++builder的問題吧~delphi可能也會?~沒試過

c builder的pf15bit和pf16bit檔案一樣大

剛才試一下好像.net的format16bpprgb555沒有存mask?? format16bpprgb565有存mask...
不過format16bpprgb555存檔是biCompression=BI_RGB
然後用c builder讀圖還是看到pfCustom哈哈哈~我越來越不懂了哈哈哈

encoref70036
一般會員


發表:29
回覆:47
積分:15
註冊:2011-05-18

發送簡訊給我
#8 引用回覆 回覆 發表時間:2011-09-15 21:18:43 IP:114.26.xxx.xxx 訂閱
感謝您~
系統時間:2017-12-14 20:59:15
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!