Wince에서 .BMP를 만드는 방법
-
22-07-2019 - |
문제
다음 C# 메소드 (쓰지 않은)에 의해 파일에 저장할 수있는 비트 맵으로 쉽게 변환 할 수있는 원시 이미지를 반환하는 카메라가 있습니다. 다양한 출처에서, 나는 그림이 픽셀 당 8 비트를 가지고 있으며 회색차가 될 수도 있고 아닐 수도 있습니다.
private void rawImgToBmp(byte[] imgData, String fname) {
Bitmap bmp = new Bitmap(getWidth(), getHeight(),
System.Drawing.Imaging.PixelFormat.Format8bppIndexed);
for (int i = 0; i < 256; i++)
{ bmp.Palette.Entries[i] = Color.FromArgb(255, i, i, i); }
//Copy the data from the byte array into the bitmap
BitmapData bmpData =
bmp.LockBits( new Rectangle(0, 0, bmp.Width, bmp.Height),
ImageLockMode.WriteOnly, bmp.PixelFormat);
Marshal.Copy(imgData, 0, bmpData.Scan0, getWidth() * getHeight());
bmp.UnlockBits(bmpData); //Unlock the pixels
bmp.Save(FileName);
}
내 질문은 : Windows CE 4.2의 내장 기능을 사용하여 C ++에 동등한 방법을 작성하는 방법은 무엇입니까?
ERISU : 팔레트 코드에 감사드립니다. 맞습니다. 나는 나머지 구조를 수동으로 채우는 데 의지했다. 위키 백과 페이지.
해결책 2
이것은 나에게 맞는 코드입니다. 그것은 Erisu의 답변을 기반으로합니다 BMP 형식에 대한 Wikipedia의 설명. 이 답변을 사용하는 다른 사람의 경우 BMP 형식을 최대한 완전히 이해하므로 헤더 필드를 적절하게 조정할 수 있습니다.
마지막에 복잡한 루프는 하드웨어/OS 문제에 대한 해결 방법으로 FWRITE에 제공 한 모든 데이터를 작성하지 않습니다. 그러나 모든 환경에서 작동해야합니다.
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <tchar.h>
#define NPAL_ENT 256
INT WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
INT nShowCmd )
{
int w = 1920, h = 1080; // My values, yours may vary
//////////////////////// File Operations ///////////////////////////////
// Reading raw img
FILE* f = fopen("\\FlashDisk\\raw_img.bin","r");
if(NULL == f){printf("BAD");exit(1);}
// Obtaining size of raw img
fseek (f , 0L , SEEK_END);
DWORD fsize = (DWORD)ftell (f);
fseek (f , 0L , SEEK_SET);
char *imgData = (char*) malloc (sizeof(char)*fsize);
if(NULL == imgData) {printf("NOT imgData");exit(2);}
// Copy contents of file into buffer
DWORD result = fread(imgData,1,fsize,f);
if (result != fsize) {
printf ("Reading error. Expected: %d, Got: %d\n",fsize, result );
if(ferror(f)){printf("An error: %d\n", ferror(f)); }
if(feof(f)) {printf("EOF\n");}
delete[] imgData;
fclose(f);
exit (3);
}
fclose(f);
//////////////////////// BMP Operations ///////////////////////////////
/* A bitmap has the following components:
* 1. BMP file header
* 2. Bitmap Information (DIB) header
* 3. Color Palette
* 4. Raw Data
*/
BITMAPFILEHEADER bmfh;
ZeroMemory( &bmfh, sizeof( bmfh ) );
bmfh.bfType = 0x4D42; // Magic #
bmfh.bfSize = sizeof( bmfh ) + sizeof( BITMAPINFOHEADER )
+ NPAL_ENT*sizeof(PALETTEENTRY) + w*h; // Or total file size if w/h not known
bmfh.bfOffBits = sizeof( bmfh ) + sizeof( BITMAPINFOHEADER )
+ NPAL_ENT*sizeof(PALETTEENTRY);
BITMAPINFOHEADER bmih;
ZeroMemory( &bmih, sizeof( bmih ) );
bmih.biWidth = w;
bmih.biHeight = h;
bmih.biSize = sizeof(bmih);
bmih.biPlanes = 1;
bmih.biBitCount = 8;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = w * h;
int palSize = NPAL_ENT*sizeof(PALETTEENTRY);
LOGPALETTE *logpal=(LOGPALETTE*)new BYTE[sizeof(LOGPALETTE)+palSize];
if(!logpal) {delete [] imgData; printf("!logpal\n"); exit(4);}
logpal->palVersion=0x300;
logpal->palNumEntries=NPAL_ENT;
int i=0;
do { // Exact palette format varies. This is what worked for me
logpal->palPalEntry[i].peRed=i;
logpal->palPalEntry[i].peGreen=i;
logpal->palPalEntry[i].peBlue=i;
logpal->palPalEntry[i].peFlags=NULL;
} while(++i<NPAL_ENT);
// Complete bitmap is now in memory, time to save it
TCHAR bmpfname[80];
wsprintf( bmpfname, (TCHAR*) TEXT( "\\USBDisk\\out.bmp" ) );
// open the file for writing
FILE *bmpFile = _wfopen(bmpfname,L"wb");
if(!bmpFile) { delete[] imgData; delete[] logpal; exit(6); }
// write the bitmap to file, in whatever chunks WinCE allows
size_t totWrit = 0, offset = 0, writeAmt = 0;
while(totWrit < bmfh.bfSize){
if(totWrit < sizeof(bmfh)){ // File header
offset = totWrit;
totWrit += fwrite( ((char*)&bmfh)+offset, 1, sizeof(bmfh)-offset, bmpFile );
}
else if(totWrit<sizeof(bmfh)+sizeof(bmih)){ // Image header
offset = totWrit - sizeof(bmfh);
totWrit += fwrite( ((char*)&bmih)+offset, 1, sizeof(bmih)-offset, bmpFile );
}
else if(totWrit<sizeof(bmfh)+sizeof(bmih)+palSize) { // Pallette
offset = totWrit - sizeof(bmfh) - sizeof(bmih);
totWrit += fwrite( ((char*)&logpal->palPalEntry)+offset, 1, palSize-offset, bmpFile );
}
else { // Image data
offset = totWrit - sizeof(bmfh) - sizeof(bmih) - palSize;
if(bmfh.bfSize-totWrit >= IO_SIZE) {
writeAmt = IO_SIZE;
}
else {
writeAmt = bmfh.bfSize-totWrit;
}
totWrit += fwrite( &imageBuffer[offset], 1, writeAmt, bmpFile );
}
// Close and open after each iteration to please WinCE
fflush(bmpFile);
fclose(bmpFile);
Sleep(4000);
bmpFile = _wfopen(bmpfname,L"ab");
if(!bmpFile) {flog->lprintf("Couldn't reopen bmpfile"); delete [] logpal; return 0;}
}
fclose(bmpFile);
if(totWrit != bmfh.bfSize) {
printf("BMP Size mismatch: %d/%d.",totWrit,bmfh.bfSize);
delete [] imgData;
delete [] logpal;
exit(-1);
}
// Cleanup
delete [] imgData;
delete [] logpal;
return 0;
}
다른 팁
일반적으로 Windows에서 비트 맵을 생성하기 위해 CreateBitMap 또는 CreateCompatibleBitMap을 사용합니다. 나는 Wince에 익숙하지 않지만 기능은 존재하는 것 같습니다. 데이터는 256 개의 컬러 팔레트가있는 픽셀 당 8 비트로 보이므로 CreatePalette, SelectPalette 및 RealizePalette 기능이 필요할 것입니다.
(경고 : 테스트되지 않은 코드) :
HBITMAP hBmp=CreateBitmap(width, height, 1, 8, imgData);
LOGPALETTE logpal=(LOGPALETTE)new BYTE[sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY)];
logpal.palVersion=0x300;
logpal.palNumEntries=256;
int i=0;
do { //no idea your palette's format, however it looks to be greyscale?
logpal->mypal[i].peRed=i;
logpal->mypal[i].peGreen=i;
logpal->mypal[i].peBlue=i;
logpal->mypal[i].peFlags=NULL;
while(++i<256);
HPALETTE hPal=CreatePalette(logpal);
//If your trying to display it to a window's DC called mywindowsDC
HDC hBmpDC = CreateCompatibleDC(mywindowsDC);
SelectObject(hBmpDC, hBmp);
SelectPalette(hBmpDC, hPal, TRUE);
BitBlt(mywindowsDC, 0, 0, width, height, hBmpDC, 0, 0, SRCCOPY);
RealizePalette(mywindowsDC);
//clean up
DeleteDC(hBmpDC);
delete [](BYTE *)logpal;
DeleteObject(hPal);
DeleteObject(hBmp);
나는 이미지 데이터를 사용하여 읽지 않을 것이다 FILE*
운영 : 당신은 그것을 작동시킬 수 있지만, 그것은 장점이며 다음과 같은 문제에 대한 경향이 있습니다. fread()
Ctrl-Z를 생각하면 파일 끝을 의미하며 완료되면 파일을 닫아야합니다. 대신 MFC를 사용했습니다 CFile
수업. 이것은 같은 것처럼 보일 것입니다
BYTE* pbyImageData = NULL;
CFile fileImage;
if(fileImage.Open(_T("\\rawimage.dat"), CFile::modeRead, NULL))
{
pbyImageData = new BYTE[fileImage.GetLength()];
fileImage.Read(pbyImageData, fileImage.GetLength());
}
비트 맵은 Windows CE에서 쉽게 처리됩니다 CDIBSectionCE
수업. 이것은 Codguru에서 구할 수 있습니다 ('Win32 및 Wince 용 Dibsection 래퍼'). cdibsectionce를 사용하면 이런 일을 할 것입니다 ...
// The BITMAPINFO struct is almost completely unusable because it has
// space for a less-than-generous 1-colour palette, so I always end up
// creating a home-grown version with room for 256 colours:
struct BITMAPINFO256
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
} stcBmpInfo;
// ...Fill in the BITMAPINFO structure -- bitmap size etc.
stcBmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
stcBmpInfo.bmiHeader.biWidth = ....
/// etc ... keep the code you have for filling in bitmap info at present
// Now load up the image into the DIB Section
CDIBSectionCE bmp;
bmp.SetBitmap((BITMAPINFO*)&stcBmpInfo, pbyImageData);
// Now write the bitmap out as a file
bmp.Save(_T("\\mybitmap.bmp");
주목하십시오 CDIBSectionCE
모든 파일 헤더 물건을 처리합니다. 이미지 데이터에서 읽고 DIB 섹션으로 삽질 한 다음 비트 맵 파일로 스스로를 저장하도록 요청하면됩니다.