|
땅주인 님이 쓰신 글 :
: 사진을 보시면 아시겠지만, Capture로 잡은 이미지 색상이 달라집니다.
:
: USB CAM에서 이미지를 입력받은 RAW DATA <=> BITMAP <=> JPEG 로 변환하는 로직을 짜고 있는데요..
: RAW 데이터를 BITMAP으로 변환 해서 화면에 찍으면 색상이 변해서 나오는데..이유를 모르겠습니다.
: 아시는 분 답변 좀 바랍니다. RGB의 순서가 바뀌었다거나 색상정보가 하나 빠졌다거나..뭐 그런 것 같은데..
:
: 감사합니다.
:
: BYTE FrameMemory[160*120*3];
: static BITMAPINFO m_sBmpHeaderDefault = {{0x28,160,120,1,8*3,0,160*120*3,0,0,0,0},{0,0,0,0}};
:
: LRESULT CALLBACK capVideoStreamCallback(HWND hWnd, LPVIDEOHDR lpVHdr)
: {
: memcpy(FrameMemory,lpVHdr->lpData,160*120*3);
: return (LRESULT)TRUE;
: }
: .....
: .....
:
: // USB CAM 초기화 하는 루틴 =============================================================
:
: HWND m_hWndCap;
: m_hWndCap = capCreateCaptureWindow("Capture Window", WS_CHILD|WS_VISIBLE|WS_DISABLED,
: 8, 16, 160,120,this->Handle, 0);
: capSetCallbackOnFrame(m_hWndCap, capVideoStreamCallback);
: if(!capDriverConnect(m_hWndCap, 0))
: { // Number of Video Device Driver
: Application->MessageBox("Video Device Driver not found!", NULL, MB_OKCANCEL);
: }
: CAPDRIVERCAPS driverCaps;
: capDriverGetCaps(m_hWndCap, &driverCaps, sizeof(driverCaps));
:
: // Format
: if(!capSetVideoFormat(m_hWndCap, &m_sBmpHeaderDefault, sizeof(BITMAPINFO))) // Video Format 지정
: {
: capDriverDisconnect(m_hWndCap);
: ::DestroyWindow(m_hWndCap);
: return;
: };
:
: // Preview Frame Interval
: capPreviewRate(m_hWndCap, (UINT)(1000.0/8));
: capPreview(m_hWndCap, TRUE);
: }
:
:
: // ====================================================================
: // 이미지 켑쳐하는 로직
: // ====================================================================
:
: // BITMAPFILEHEADER 정보를 만들어 줌..
:
: BITMAPFILEHEADER Bmfh;
: Bmfh.bfType = 0x4d42; // BM => Bitmap file
: Bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + // file size
: sizeof(RGBQUAD) + 160 * 120 * 3 - 2; // -2를 하지 않으면 에러 남
: Bmfh.bfReserved1 = 0; // not use
: Bmfh.bfReserved2 = 0; // not use
: Bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) +
: sizeof(RGBQUAD) - 2; // -2를 하지 않으면 에러 남
:
: BYTE *p = new BYTE[Bmfh.bfSize]; // BITMAP을 담을 공간 생성
:
: // BITMAPFILEHEADER 정보-----------------------------------------------
:
: int iPos = 0;
: memcpy(p, &Bmfh.bfType, sizeof(Bmfh.bfType));
: iPos += sizeof(Bmfh.bfType);
: memcpy(p + iPos , &Bmfh.bfSize, sizeof(Bmfh.bfSize));
: iPos += sizeof(Bmfh.bfSize);
: memcpy(p + iPos, &Bmfh.bfReserved1, sizeof(Bmfh.bfReserved1));
: iPos += sizeof(Bmfh.bfReserved1);
: memcpy(p + iPos, &Bmfh.bfReserved2, sizeof(Bmfh.bfReserved2));
: iPos += sizeof(Bmfh.bfReserved2);
: memcpy(p + iPos, &Bmfh.bfOffBits, sizeof(Bmfh.bfOffBits));
: iPos += sizeof(Bmfh.bfOffBits);
:
: // BITMAPINFO 정보 ------------------------------------------------------
:
: memcpy(p + iPos, &m_sBmpHeaderDefault, sizeof(m_sBmpHeaderDefault));
: iPos += sizeof(m_sBmpHeaderDefault);
:
: memcpy(p + iPos, FrameMemory, sizeof(FrameMemory)); // RAW데이터 복사
:
: TMemoryStream *pMemoryStream = new TMemoryStream();
: pMemoryStream->WriteBuffer(p,Bmfh.bfSize);
: pMemoryStream->Position = 0;
: Graphics::TBitmap *pBitmap = new Graphics::TBitmap();
: pBitmap->LoadFromStream(pMemoryStream);
: pMemoryStream->Position = 0;
:
: Image1->Picture->Bitmap->LoadFromStream(pMemoryStream);
:
: if ( m_pJpgPhoto == NULL ) {
: m_pJpgPhoto = new TJPEGImage();
: }
: m_pJpgPhoto->Assign(Image1->Picture->Bitmap);
:
: 제발 좋은 답변 있기를...
void __fastcall TForm1::ShowFrame(LPVIDEOHDR lpVHdr)
{
// ====================================================================
// 이미지 켑쳐하는 로직
// ====================================================================
// BITMAPFILEHEADER 정보를 만들어 줌..
BITMAPFILEHEADER Bmfh;
Bmfh.bfType = 0x4d42; // BM => Bitmap file
Bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + lpVHdr->dwBytesUsed;
Bmfh.bfReserved1 = 0; // not use
Bmfh.bfReserved2 = 0; // not use
Bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
TMemoryStream *pMemoryStream = new TMemoryStream();
pMemoryStream->WriteBuffer(&Bmfh,sizeof(Bmfh));
pMemoryStream->WriteBuffer(&m_sBmpHeaderDefault, sizeof(BITMAPINFOHEADER));
pMemoryStream->WriteBuffer(lpVHdr->lpData, lpVHdr->dwBytesUsed);
pMemoryStream->Position = 0;
Image1->Picture->Bitmap->LoadFromStream(pMemoryStream);
delete pMemoryStream;
}
TBitmap에서는 BITMAPFILEHEADER의 bfOffBits에 지정된 값을 인정해주지 않는것으로 보입니다.
bfOffBits의 값은 나머지 정보들로부터 계산해낼 수 있는데 TBitmap에서는 이렇게 직접 계산한 것을 사용하는 모양입니다.
위와 같은 배경에서 보면, 제시하신 코드에서 BITMAPINFO의 bmiColors는 불필요한 데이터입니다.
TBitmap 내부 코드에서 계산한 bfOffBits의 값은 BITMAPINFOHEADER의 끝 바로 다음을 가리키고 있고 그 곳에서 이미지 데이터가 시작되는 것으로 처리하는 것으로 보입니다.
제시하신 코드에서 그 위치에는 불필요한 RGBQUAD가 자리하고 있습니다.
|