2009-01-14 9 views
1

J'ai une caméra qui renvoie des images brutes qui peuvent facilement être converties en bitmap qui peuvent être enregistrées dans un fichier par la méthode C# suivante (que je n'ai pas écrite). De diverses sources, j'ai déterminé que les images ont 8 bits par pixel, et peuvent ou peuvent ne pas être en niveaux de gris.Comment créer un fichier .bmp dans WinCE

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); 
    } 

Ma question est: comment j'écrirais la méthode équivalente en C++, en utilisant les fonctions intégrées de Windows CE 4.2?

erisu: merci pour le code de la palette, je pense que c'est bon. J'ai eu recours à remplir le reste des structures manuellement, selon la page Wikipedia.

Répondre

1

Ceci est le code qui fonctionne pour moi. Il est basé sur la réponse d'erisu et Wikipedia's description of the BMP format. Pour toute autre personne utilisant cette réponse, je recommande que vous compreniez le format BMP le plus complètement possible, de sorte que vous pouvez ajuster les champs d'en-tête en conséquence.

La boucle compliquée à la fin est ma solution de contournement pour un problème avec mon matériel/OS, où il n'écrirait pas toutes les données que j'ai fournies à fwrite. Cela devrait fonctionner dans n'importe quel environnement, cependant.

#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; 

} 
+2

Je me demande si le problème est le deuxième paramètre à ouvrir? Vous ne spécifiez que "r", mais le fichier est évidemment binaire. Essayez "rb" –

1

Typiquement, j'utilise CreateBitmap ou CreateCompatibleBitmap pour générer des bitmaps dans Windows. Je ne suis pas familier avec WinCE mais les fonctions semblent être présentes. Vos données semblent être en 8 bits par pixel avec une palette de 256 couleurs, vous aurez donc probablement besoin des fonctions CreatePalette, SelectPalette et RealizePalette.

Quelque chose comme (avertissement: code non testé):

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); 
+0

J'ai eu votre code à exécuter, mais rien n'a été dessiné à l'écran. Lequel de ces objets/poignées que vous créez contient les octets dont j'ai besoin pour créer un fichier .bmp? –

+0

Désolé, le code n'a pas été testé, l'erreur est probablement dans la partie palette. Voulez-vous dessiner dans une fenêtre ou le sortir dans un fichier? Si vous voulez simplement afficher un fichier sans l'afficher, il existe quelques fonctions simples pour écrire des données brutes dans .bmp. – erisu

+0

Je veux l'écrire dans un fichier. J'ai vu beaucoup de fonctions potentielles, mais je ne suis pas sûr de savoir lequel de vos objets contient les données brutes que je veux. Voulez-vous que je publie votre code avec mes modifications afin qu'il compile? –

-2

Je ne lirais pas dans les données d'image à l'aide FILE* opérations: vous pouvez le faire fonctionner, mais il est bavard et sujettes à des problèmes comme fread() penser un moyen Ctrl-Z de fin de fichier, plus vous devez N'oubliez pas de fermer le fichier lorsque vous avez terminé. À la place, j'utiliserais la classe MFC CFile. Cela ressemble à quelque chose comme

BYTE* pbyImageData = NULL; 
CFile fileImage; 
if(fileImage.Open(_T("\\rawimage.dat"), CFile::modeRead, NULL)) 
{ 
    pbyImageData = new BYTE[fileImage.GetLength()]; 
    fileImage.Read(pbyImageData, fileImage.GetLength()); 
} 

bitmaps sont faciles à manipuler dans Windows CE en utilisant la classe CDIBSectionCE. Ceci est disponible auprès de CodeGuru ('A DIBSection wrapper for Win32 and WinCE'). En utilisant CDIBSectionCE, vous feriez quelque chose comme ça ...

// 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"); 

Notez que CDIBSectionCE gère toutes les choses d'en-tête de fichier. Tout ce que vous avez à faire est de lire dans les données d'image, de le pelliculer dans une section DIB, puis de lui demander de se sauver comme un fichier bitmap.

Questions connexes