我是VC++初学者,现正在写一个程序,要求将一个BMP格式的图像文件显示出来,只知道文件路径,不能用MFC,也不能用LoadIamge函数,一句话,就是要涉及对图像文件内部数据的处理,还望各位大虾多多指教!!!!

解决方案 »

  1.   

    先看看BITMAPHEADINFO和BITMAPFILEINFO结构
      

  2.   

    http://www.csdn.net/develop/Read_Article.asp?Id=12484
    http://asp.6to23.com/iseesoft/devdoc/imgdoc/bmp_fileformat.htm
      

  3.   

    case WM_COMMAND:
              iConvert = 0 ;          switch (LOWORD (wParam))
              {
              case IDM_FILE_OPEN:                    // Show the File Open dialog box               if (!GetOpenFileName (&ofn))
                        return 0 ;
                   
                        // If there's an existing DIB and palette, delete them               SendMessage (hwnd, WM_USER_DELETEDIB, 0, 0) ;
                   
                        // Load the DIB into memory               SetCursor (LoadCursor (NULL, IDC_WAIT)) ;
                   ShowCursor (TRUE) ;               hdib = DibFileLoad (szFileName) ;               ShowCursor (FALSE) ;
                   SetCursor (LoadCursor (NULL, IDC_ARROW)) ;                    // Reset the scroll bars               SendMessage (hwnd, WM_USER_SETSCROLLS, TRUE, 0) ;                    // Create the palette and DDB               SendMessage (hwnd, WM_USER_CREATEPAL, TRUE, 0) ;               if (!hdib)
                   {
                        MessageBox (hwnd, TEXT ("Cannot load DIB file!"), 
                                    szAppName, MB_OK | MB_ICONEXCLAMATION) ;
                   }
                   InvalidateRect (hwnd, NULL, TRUE) ;
                   return 0 ;
    上面是消息处理部分,下面是
    HDIB DibFileLoad (const TCHAR * szFileName)
    {
         BITMAPFILEHEADER bmfh ;
         BITMAPINFO     * pbmi ;
         BOOL             bSuccess ;
         DWORD            dwInfoSize, dwBitsSize, dwBytesRead ;
         HANDLE           hFile ;
         HDIB             hDib ;          // Open the file: read access, prohibit write access     hFile = CreateFile (szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
                             OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL) ;     if (hFile == INVALID_HANDLE_VALUE)
              return NULL ;          // Read in the BITMAPFILEHEADER     bSuccess = ReadFile (hFile, &bmfh, sizeof (BITMAPFILEHEADER), 
                              &dwBytesRead, NULL) ;     if (!bSuccess || (dwBytesRead != sizeof (BITMAPFILEHEADER))         
                       || (bmfh.bfType != * (WORD *) "BM"))
         {
              CloseHandle (hFile) ;
              return NULL ;
         }
              // Allocate memory for the information structure & read it in     dwInfoSize = bmfh.bfOffBits - sizeof (BITMAPFILEHEADER) ;     if (NULL == (pbmi = malloc (dwInfoSize)))
         {
              CloseHandle (hFile) ;
              return NULL ;
         }     bSuccess = ReadFile (hFile, pbmi, dwInfoSize, &dwBytesRead, NULL) ;     if (!bSuccess || (dwBytesRead != dwInfoSize))
         {
              CloseHandle (hFile) ;
              free (pbmi) ;
              return NULL ;
         }
              // Create the DIB     hDib = DibCreateFromInfo (pbmi) ;
         free (pbmi) ;     if (hDib == NULL)
         {
              CloseHandle (hFile) ;
              return NULL ;
         }
              // Read in the bits     dwBitsSize = bmfh.bfSize - bmfh.bfOffBits ;     bSuccess = ReadFile (hFile, ((PDIBSTRUCT) hDib)->pBits, 
                              dwBitsSize, &dwBytesRead, NULL) ;
         CloseHandle (hFile) ;     if (!bSuccess || (dwBytesRead != dwBitsSize))
         {
              DibDelete (hDib) ;
              return NULL ;
         }
         return hDib ;
    }
    我想满足你的要求了,使用API,没有用loadimage
      

  4.   

    还有一部分没给你,下面一并贴出来     case WM_USER_CREATEPAL://SendMessage (hwnd,WM_USER_CREATEPAL, TRUE, 0) ;          if (hdib)
              {
                   hdc = GetDC (hwnd) ;               if (!(RC_PALETTE & GetDeviceCaps (hdc, RASTERCAPS)))
                   {
                        PaletteMenu (hMenu, IDM_PAL_NONE) ;
                   }
                   else if (hPalette = DibPalDibTable (hdib))
                   {
                        PaletteMenu (hMenu, IDM_PAL_DIBTABLE) ;
                   }
                   else if (hPalette = CreateHalftonePalette (hdc))
                   {
                        fHalftonePalette = TRUE ;
                        PaletteMenu (hMenu, IDM_PAL_HALFTONE) ;
                   }
                   ReleaseDC (hwnd, hdc) ;               if ((BOOL) wParam)
                        hBitmap = DibCopyToDdb (hdib, hwnd, hPalette) ;
              }
              return 0 ;     case WM_PAINT:
              hdc = BeginPaint (hwnd, &ps) ;          if (hPalette)
              {
                   SelectPalette (hdc, hPalette, FALSE) ;
                   RealizePalette (hdc) ;
              }
              if (hBitmap)
              {
                   DisplayDib (hdc, 
                               fHalftonePalette ? DibBitmapHandle (hdib) : hBitmap, 
                               iHscroll, iVscroll, 
                               cxClient, cyClient, 
                               wShow, fHalftonePalette) ;
              }
              EndPaint (hwnd, &ps) ;
              return 0 ;     case WM_QUERYNEWPALETTE:
              if (!hPalette)
                   return FALSE ;          hdc = GetDC (hwnd) ;
              SelectPalette (hdc, hPalette, FALSE) ;
              RealizePalette (hdc) ;
              InvalidateRect (hwnd, NULL, TRUE) ;          ReleaseDC (hwnd, hdc) ;
              return TRUE ;     case WM_PALETTECHANGED:
              if (!hPalette || (HWND) wParam == hwnd)
                   break ;          hdc = GetDC (hwnd) ;
              SelectPalette (hdc, hPalette, FALSE) ;
              RealizePalette (hdc) ;
              UpdateColors (hdc) ;          ReleaseDC (hwnd, hdc) ;
              break ;     case WM_DESTROY:
              if (hdib)
                   DibDelete (hdib) ;          if (hBitmap)
                   DeleteObject (hBitmap) ;          if (hPalette)
                   DeleteObject (hPalette) ;          PostQuitMessage (0) ;
              return 0 ;
         }
         return DefWindowProc (hwnd, message, wParam, lParam) ;
    }int DisplayDib (HDC hdc, HBITMAP hBitmap, int x, int y, 
                    int cxClient, int cyClient, 
                    WORD wShow, BOOL fHalftonePalette)
    {
         BITMAP bitmap ;
         HDC    hdcMem ; 
         int    cxBitmap, cyBitmap, iReturn ;     GetObject (hBitmap, sizeof (BITMAP), &bitmap) ;
         cxBitmap = bitmap.bmWidth ;
         cyBitmap = bitmap.bmHeight ;     SaveDC (hdc) ;     if (fHalftonePalette)
              SetStretchBltMode (hdc, HALFTONE) ;
         else
              SetStretchBltMode (hdc, COLORONCOLOR) ;     hdcMem = CreateCompatibleDC (hdc) ;
         SelectObject (hdcMem, hBitmap) ;     switch (wShow)
         {
         case IDM_SHOW_NORMAL:
              if (fHalftonePalette)
                   iReturn = StretchBlt (hdc,    0, 0, 
                                                 min (cxClient, cxBitmap - x), 
                                                 min (cyClient, cyBitmap - y), 
                                         hdcMem, x, y, 
                                                 min (cxClient, cxBitmap - x), 
                                                 min (cyClient, cyBitmap - y), 
                                         SRCCOPY);
              else
                   iReturn = BitBlt (hdc,    0, 0, 
                                             min (cxClient, cxBitmap - x), 
                                             min (cyClient, cyBitmap - y),
                                     hdcMem, x, y, SRCCOPY) ;
              break ;
                   
         case IDM_SHOW_CENTER:
              if (fHalftonePalette)
                   iReturn = StretchBlt (hdc, (cxClient - cxBitmap) / 2,
                                              (cyClient - cyBitmap) / 2, 
                                              cxBitmap, cyBitmap,
                                         hdcMem, 0, 0, cxBitmap, cyBitmap, SRCCOPY);
              else
                   iReturn = BitBlt (hdc, (cxClient - cxBitmap) / 2,
                                          (cyClient - cyBitmap) / 2, 
                                          cxBitmap, cyBitmap,
                                     hdcMem, 0, 0, SRCCOPY) ;
              break ;     case IDM_SHOW_STRETCH:
              iReturn = StretchBlt (hdc,    0, 0, cxClient, cyClient, 
                                    hdcMem, 0, 0, cxBitmap, cyBitmap, SRCCOPY) ;
              break ;     case IDM_SHOW_ISOSTRETCH:
              SetMapMode (hdc, MM_ISOTROPIC) ;
              SetWindowExtEx (hdc, cxBitmap, cyBitmap, NULL) ;
              SetViewportExtEx (hdc, cxClient, cyClient, NULL) ;
              SetWindowOrgEx (hdc, cxBitmap / 2, cyBitmap / 2, NULL) ;
              SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ;          iReturn = StretchBlt (hdc,    0, 0, cxBitmap, cyBitmap, 
                                    hdcMem, 0, 0, cxBitmap, cyBitmap, SRCCOPY) ;
              break ;
         }
         DeleteDC (hdcMem) ;
         RestoreDC (hdc, -1) ;
         return iReturn ;
    }
    我想这样应该可以了
      

  5.   

    我正在做的作业也是这个,也许可以交流一下:
    1.你说要使用BMP文件,说明是用设备无关的DIB位图。MFC中是不提供DIB类的,
      所以若要进行DIB位图的处理,最好是自己定义一个DIB类。
    2.如果只是显示的话,不定义DIB类当然也没关系。
      这时需要做以下件事:
       
      1)在程序文档类中加入:
      一个公有数据成员:
      HANDLE m_hDIB;
      说明:指向DIB数据块的内存句柄
      重载以下函数:
      BOOL CMyDoc::OnOpenDocument(LPCTSTR lpszPathName)
      {
        if(!CDocument::OnOpenDocument(lpszPathName))
          return FALSE;
        m_hDIB=LoadDIB(lpszPathName);
        if(m_hDIB==NULL)
        {
          return FALSE;
        }
        SetPathName(lpszPathName);
        SetModifiedFlag(FALSE);
        return TRUE;
      }
      CMyDoc是你的程序中自动生成的DOC类
      上面调用的LoadDIB函数需要自己编写
      HANDLE CMyDoc::LoadDIB(LPTSTR lpFileName)
          参数lpFileName---指向文件名字符串的指针
          返回值HANDLE---指向DIB数据缓冲区的句柄
          说明:将指定的DIB文件读入内存
      这个函数的代码可以参考楼上的DibFileLoad()
      他返回的HDIB应该就是一个HANDlE吧
      这样就完成了文件的载入。
      2)在程序视图类类中加入:
      一个数据成员:
      CRECT m_rectDIB;
      说明:用来存储位图的位置,尺寸信息
      重载以下函数:
      
      void CMyScrollView::OnInitialUpdate()
      {
       CScrollView::OnInitialUpDate();
       CMyDoc* pDoc=GetDocument();
       ASSERT_VALID(pDoc);
       CSize sizeTotal;
       if(pDoc->m_hDIB!=NULL)
       {
         LPBITMAPINFOHEADER lpDIB=
         (LPBITMAPINFOHEADER)GlobalLock(pDoc->m_hDIB);
         m_rectDIB.left=0;
         m_rectDIB.top=0;
         sizeTotal.cx=m_rectDIB.right=
         ((LPBITMAPINFOHEADER)lpDIB)->biwidth;
         sizeTotal.cy=m_rectDIB.bottom=
         ((LPBITMAPINFOHEADER)lpDIB)->biHeight;
         GlobalUnlock(pDoc->m_hDIB);
       }
       else
      {
         m_rectDIB.SetRectEmpty();
         sizeTotal.cx=sizeTotal.cy=100;
      }
      SetScrollSizes(MM_TEXT,sizeTotal);
     }
     说明:1这里使用CScrollView类而不是CView类是为了满足大图片的要求
           2因为OninitialUpdate函数会在文件装入后自动被调用,所以可在
            这儿进行一些预处理
     
     void CMyScrollView::OnDraw(CDC* pDC)
     {
       CMyDoc* pDoc=GetDocument();
       ASSERT_VALID(pDoc);
       if(pDoc->m_hDIB==NULL)
          return;
       PaintDIB(pDC->GetSafeHdc(),m_rectDIB,pDoc->m_hDIB,m_rectDIB,
                NULL,SRCCOPY);
      说明:
      PaintDIB需自己编写,定义如下:
      BOOL CMyScrollView::PaintDIB(HDC hDC,LPRECT lpDCRect,HANDLE hDIB,
            LPRECT lpDIBRect,HPALETTE hPal,DWORD dwRop)
      参数:
      hDC---显示DIB的设备上下文句柄
      lpDCRect---设备中显示DIB的矩形区域
      dDIB---存储DIB数据缓冲区的内存块句柄
      lpDIBRect---要显示的DIB矩形区域
      hPal---用以显示DIB的调色板句柄
      dwRop---显示DIB的ROP模式
      具体可参考楼上的DisplayDib()函数
      这样就可以完成图形显示
      
      但还有一个问题:
      就是我们还没对调色板进行处理,所以显示的图像不一定符合要求。
      (系统调色板只有20色)调色板的问题下次再交流吧。3.如果你有什么好的资料和原码,希望也可以提供给我。谢谢。
      最后推荐你一本书---周长发的<<visual c++.net图像处理编程>>  
      上边有不少图形处理算法。   
         
      

  6.   

    非常感谢大家的参与与解答,尤其是“分儿,我来了”、“半尾鱼”和“BlueNights",请你们告诉我怎样结贴,给你们加分,我将尽快给你们送分,实际这个问题我上星期就已经解决了,只是不知道怎样结贴,我自定义了两个函数LoadBMP和DrawDIB ,代码在下面,我现在又遇到了新难题,要在一个窗体中同时显示多副图像,且还不是一次打开的,一次只能打开一个,最后将所有图像以256像素或其他格式保存到一个文件。我觉得保存应该不难,关键是把多个不一块打开且数目不确定的文件同时显示,我至今没有什么好办法,我可以在不同的位置显示图像,但每当显示下一个图像时,前一个将消失,一次只能显示一个,尽管不会出现位置重复,我将在提交一个问题,还望诸位大虾参与,并多多指教!
        
    HGLOBAL CBitMapOpView::LoadBMP( CPalette *pPal )
    {

    HANDLE hFile;  
        int n;
    n=Bmpname.Replace("\\", "\\\\");

        
    // Open the existing file. 
     
         hFile = CreateFile(   Bmpname,   // open the BitMap file
                           GENERIC_READ,
                               0,                             //  not share 
                               NULL,                         // no security 
                               OPEN_EXISTING,                // existing file only 
                               FILE_ATTRIBUTE_NORMAL,        // normal file 
                               NULL);                        // no attr. template   //fail to open file
          if (hFile == INVALID_HANDLE_VALUE) 
      { 
      return NULL; 
      } 
         
     BITMAPFILEHEADER bmfHeader;
     DWORD nFileLen,dwBytesRead;
     nFileLen = GetFileSize (hFile, NULL) ; //get the length of the file
          // Read file header
        if(!ReadFile(hFile, (LPSTR)&bmfHeader, sizeof(bmfHeader), &dwBytesRead, NULL) ||
     dwBytesRead != sizeof(bmfHeader))
              return NULL;
          // File type should be 'BM'
         if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B'))
              return NULL;     HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nFileLen);
         if (hDIB == 0)
              return NULL;     // Read the remainder of the bitmap file.
         if(!ReadFile(hFile, (LPSTR)hDIB, nFileLen - sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL) ||
     dwBytesRead != nFileLen - sizeof(BITMAPFILEHEADER))
     {
     ::GlobalFree(hDIB);
     return NULL;
     }     BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;  //nColors is the factual color num
         int nColors = bmInfo.bmiHeader.biClrUsed ? 
     bmInfo.bmiHeader.biClrUsed : 1 << bmInfo.bmiHeader.biBitCount;
      // Create the palette  UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
     LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];  pLP->palVersion = 0x300;  //version number
     pLP->palNumEntries = nColors;
               
     //create color matrix
     for( int i=0; i < nColors; i++)
         {
       pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed;
       pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen;
       pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue;
       pLP->palPalEntry[i].peFlags = 0;
     }  pPal->CreatePalette( pLP );
     delete[] pLP;
     CloseHandle(hFile);// Close the files.
         return hDIB;
    }bool CBitMapOpView::DrawDIB( CDC* pDC, HGLOBAL hDIB, CPalette *pPal )
    {
    LPVOID lpDIBBits; // Pointer to DIB bits
    bool bsuccess = false; //Check hDIB,if hDIB is null,exit the function
    if(hDIB == NULL)
    return bsuccess; BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;

    //nColors is the factual color num
    int nColors = bmInfo.bmiHeader.biClrUsed ? 
    bmInfo.bmiHeader.biClrUsed :  1 << bmInfo.bmiHeader.biBitCount;
        
    //16 bit or 24 bit or 32 bit clearly color
    if( bmInfo.bmiHeader.biBitCount > 8 )
    lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors +
                bmInfo.bmiHeader.biClrUsed) +
    ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));

    //Other color
    else
    lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
        
    // select the palette into a device context and realize it 
    if( pPal && (pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE) )
    {
    pDC->SelectPalette(pPal, FALSE);
    pDC->RealizePalette();
    } //draw bmp
    ::SetDIBitsToDevice(pDC->m_hDC, // hDC
                    0, // DestX
                            0, // DestY
                            bmInfo.bmiHeader.biWidth, // nDestWidth
                            bmInfo.bmiHeader.biHeight, // nDestHeight
                            0, // SrcX
                            0, // SrcY
                            0, // nStartScan
                            bmInfo.bmiHeader.biHeight, // nNumScans
                            lpDIBBits, // lpBits
                            (LPBITMAPINFO)hDIB, // lpBitsInfo
                             DIB_RGB_COLORS); // wUsage bsuccess = true;
    return bsuccess;

    }
      

  7.   

    BOOL CTestsdiView::ShowBmp(HDC hdc, char *strFileName, int xDst, int yDst, int dxDst, int dyDst)
    {
    FILE *fp;
    BITMAPFILEHEADER bf;
    LPBITMAPINFOHEADER lpbi;
    DWORD dwImgSize;
    int w,h; if((fp=fopen(strFileName,"rb"))==NULL)
    {
    AfxMessageBox("File open error");
    return FALSE;
    }
    fread(&bf,1,14,fp);
    dwImgSize=bf.bfSize-14;
    lpbi=(LPBITMAPINFOHEADER)malloc(dwImgSize);
    fread(lpbi,1,dwImgSize,fp);
    fclose(fp);
    lpbi->biCompression=0;

    w=dxDst;
    h=dyDst;
    if(lpbi->biWidth<dxDst) w=lpbi->biWidth;
    if(lpbi->biHeight<dxDst) h=lpbi->biHeight;
    HDRAWDIB hdd;
    hdd=DrawDibOpen();
    if(hdd==NULL)
    return FALSE;
    if(!DrawDibDraw(hdd,hdc,0,0,w,h,lpbi,NULL,0,0,lpbi->biWidth,lpbi->biHeight,NULL))
    {
    AfxMessageBox("DrawDibDraw error");
    DrawDibClose(hdd);
    return FALSE;
    }
    DrawDibClose(hdd);
    return TRUE;
    }
    example:
    /* HDC hdc=::GetDC(GetSafeHwnd());
    ShowBmp(hdc,"f:\\test1.bmp",0,0,384/3,288/3);
    ::ReleaseDC(GetSafeHwnd(),hdc);
    */