Delphi显示BMP图片的问题:如何通过读取文件头,信息头,调色板,位图数据显示BMP图片,而不是使用如image.picture:=等的方法?
不是自找麻烦,是为了更详细的了解显示的各个过程。
有代码更好,谢谢。

解决方案 »

  1.   

    var
     BitMap1 : TBitMap;
    begin
      BitMap1 := TBitMap.Create;
      try
        BitMap1.LoadFromResourceName(HInstance,'THEBITMAP');
        Canvas.Draw(12,12,BitMap1);
      finally
        BitMap1.Free;
      end;
    end;
      

  2.   

    楼上的我不是这个意思,我的意思是根据bmp文件的调色板信息和每个象素的RGB信息,来形成这个bitmap对象,然后让它显示出来。
      

  3.   


    struct Pal{
    int blue;
    int green;
    int red;
    } ;struct Pal P[256]={0};void ReadP(void)
    {
    for (int i=0;i<Pnumber;i++)
    {
      fseek(stream,ReallyStart-4*(Pnumber-i),SEEK_SET);
      P[i].blue=fgetc(stream);
      P[i].green=fgetc(stream);
      P[i].red=fgetc(stream);
    }
    }这个是我bcb程序中的都调色板的一段
      

  4.   

    这个东西要研究bmp的文件格式了。我研究的好累的:(。而且其格式不只一种,不过它的 颜色类型, 宽,高,等位置是固定的,其中有一个位置存储的是点阵的起誓位置, 从那个位置开始是图象的点阵,而且不同的bmp的点阵也不一样,单色的是一个bit代表一个位置,256是一byte代表一个,而且要到相应的调色板找颜色,不同的图的调色板不同,24位的就是3个byte的顺序排列了,不过其点阵也不是顺序的,是从下面的一航开始的,我就说这么多了,只希望给你点提示。其实这个真不是什么好办法,我最后也没用文件操作,完成的我的程序。
      

  5.   

    这个c的代码,不知道delphi应该怎么写,而且关于image控件的具体信息都没有。下面的函数LoadBmpFile,其功能是从一个.bmp文件中读取数据(包括BITMAPINFOHEADER,调色板和实际图象数据),将其存储在一个全局内存句柄hImgData中,这个hImgData将在以后的图象处理程序中用到。同时填写一个类型为HBITMAP的全局变量hBitmap和一个类型为HPALETTE的全局变量hPalette。这两个变量将在处理WM_PAINT消息时用到,用来显示位图。该函数的两个参数分别是用来显示位图的窗口句柄,和.bmp文件名(全路径)。当函数成功时,返回TRUE,否则返回FALSE。BITMAPFILEHEADER  bf;BITMAPINFOHEADER bi;BOOL LoadBmpFile (HWND hWnd,char *BmpFileName){   HFILE                      hf; //文件句柄//指向BITMAPINFOHEADER结构的指针LPBITMAPINFOHEADER    lpImgData; LOGPALETTE                           *pPal; //指向逻辑调色板结构的指针LPRGBQUAD                            lpRGB; //指向RGBQUAD结构的指针HPALETTE                               hPrevPalette; //用来保存设备中原来的调色板HDC                                         hDc; //设备句柄HLOCAL                                   hPal; //存储调色板的局部内存句柄DWORD                                   LineBytes;  //每一行的字节数DWORD                                   ImgSize;   //实际的图象数据占用的字节数//实际用到的颜色数 ,即调色板数组中的颜色个数DWORD                                   NumColors; DWORD                                   i;if((hf=_lopen(BmpFileName,OF_READ))==HFILE_ERROR){MessageBox(hWnd,"File c:\\test.bmp not found!","Error Message",MB_OK|MB_ICONEXCLAMATION);return FALSE; //打开文件错误,返回}//将BITMAPFILEHEADER结构从文件中读出,填写到bf中_lread(hf,(LPSTR)&bf,sizeof(BITMAPFILEHEADER)); //将BITMAPINFOHEADER结构从文件中读出,填写到bi中_lread(hf,(LPSTR)&bi,sizeof(BITMAPINFOHEADER));//我们定义了一个宏 #define WIDTHBYTES(i)    ((i+31)/32*4)上面曾经//提到过,每一行的字节数必须是4的整倍数,只要调用//WIDTHBYTES(bi.biWidth*bi.biBitCount)就能完成这一换算。举一个例//子,对于2色图,如果图象宽是31,则每一行需要31位存储,合3个//字节加7位,因为字节数必须是4的整倍数,所以应该是4,而此时的//biWidth=31,biBitCount=1,WIDTHBYTES(31*1)=4,和我们设想的一样。//再举一个256色的例子,如果图象宽是31,则每一行需要31个字节存//储,因为字节数必须是4的整倍数,所以应该是32,而此时的//biWidth=31,biBitCount=8,WIDTHBYTES(31*8)=32,我们设想的一样。你可//以多举几个例子来验证一下//LineBytes为每一行的字节数LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount);//ImgSize为实际的图象数据占用的字节数ImgSize=(DWORD)LineBytes*bi.biHeight;//NumColors为实际用到的颜色数 ,即调色板数组中的颜色个数if(bi.biClrUsed!=0)//如果bi.biClrUsed不为零,即为实际用到的颜色数NumColors=(DWORD)bi.biClrUsed; else //否则,用到的颜色数为2biBitCount。switch(bi.biBitCount){case 1:NumColors=2;                     break;                      case 4:NumColors=16;                    break;       case 8:           NumColors=256;           break;       case 24:           NumColors=0; //对于真彩色图,没用到调色板           break;default: //不处理其它的颜色数,认为出错。MessageBox(hWnd,"Invalid color numbers!","Error Message",MB_OK|MB_ICONEXCLAMATION);_lclose(hf);                     return FALSE; //关闭文件,返回FALSE}if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER))){//计算出的偏移量与实际偏移量不符,一定是颜色数出错   MessageBox(hWnd,"Invalid color numbers!","Error Message",MB_OK|MB_ICONEXCLAMATION);_lclose(hf);return FALSE; //关闭文件,返回FALSE}bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize;//分配内存,大小为BITMAPINFOHEADER结构长度加调色板+实际位图if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL){//分配内存错误MessageBox(hWnd,"Error alloc memory!","ErrorMessage",MB_OK|                 MB_ICONEXCLAMATION);_lclose(hf);return FALSE; //关闭文件,返回FALSE}//指针lpImgData指向该内存区lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData); //文件指针重新定位到BITMAPINFOHEADER开始处_llseek(hf,sizeof(BITMAPFILEHEADER),SEEK_SET);//将文件内容读入lpImgData_hread(hf,(char *)lpImgData,(long)sizeof(BITMAPINFOHEADER)+(long)NumColors*sizeof(RGBQUAD)+ImgSize);_lclose(hf); //关闭文件if(NumColors!=0) //NumColors不为零,说明用到了调色板{//为逻辑调色板分配局部内存,大小为逻辑调色板结构长度加//NumColors个PALETTENTRYhPal=LocalAlloc(LHND,sizeof(LOGPALETTE)+NumColors* sizeof(PALETTEENTRY));//指针pPal指向该内存区pPal =(LOGPALETTE *)LocalLock(hPal);   //填写逻辑调色板结构的头pPal->palNumEntries = NumColors;   pPal->palVersion = 0x300;//lpRGB指向的是调色板开始的位置lpRGB = (LPRGBQUAD)((LPSTR)lpImgData +(DWORD)sizeof(BITMAPINFOHEADER));//填写每一项for (i = 0; i < NumColors; i++)   {pPal->palPalEntry[i].peRed=lpRGB->rgbRed;pPal->palPalEntry[i].peGreen=lpRGB->rgbGreen;pPal->palPalEntry[i].peBlue=lpRGB->rgbBlue;pPal->palPalEntry[i].peFlags=(BYTE)0;lpRGB++; //指针移到下一项}//产生逻辑调色板,hPalette是一个全局变量hPalette=CreatePalette(pPal);//释放局部内存LocalUnlock(hPal);LocalFree(hPal);}//获得设备上下文句柄hDc=GetDC(hWnd);if(hPalette) //如果刚才产生了逻辑调色板{//将新的逻辑调色板选入DC,将旧的逻辑调色板句柄保存在//hPrevPalettehPrevPalette=SelectPalette(hDc,hPalette,FALSE);RealizePalette(hDc);}//产生位图句柄hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpImgData, (LONG)CBM_INIT,(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD),(LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);//将原来的调色板(如果有的话)选入设备上下文句柄if(hPalette && hPrevPalette){SelectPalette(hDc,hPrevPalette,FALSE);RealizePalette(hDc);}ReleaseDC(hWnd,hDc); //释放设备上下文GlobalUnlock(hImgData); //解锁内存区return TRUE; //成功返回}对上面的程序要说明两点:(1)    对于需要调色板的图,要想正确地显示,必须根据bmp文件,产生逻辑调色板。产生的方法是:①为逻辑调色板指针分配内存,大小为逻辑调色板结构(LOGPALETTE)长度加NumColors个PALETTENTRY大小(调色板的每一项都是一个PALETTEENTRY结构);②填写逻辑调色板结构的头pPal->palNumEntries = NumColors; pPal->palVersion = 0x300;③从文件中读取调色板的RGB值,填写到每一项中;④产生逻辑调色板:hPalette=CreatePalette(pPal)。(2)    产生位图(BITMAP)句柄,该项工作由函数CreateDIBitmap来完成。hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpImgData, (LONG)CBM_INIT,(LPSTR)lpImgData+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD),(LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);CreateDIBitmap的作用是产生一个和Windows设备无关的位图。该函数的第一项参数为设备上下文句柄。如果位图用到了调色板,要在调用CreateDIBitmap之前将逻辑调色板选入该设备上下文中,产生hBitmap后,再把原调色板选入该设备上下文中,并释放该上下文;第二项为指向BITMAPINFOHEADER的指针;第三项就用常量CBM_INI,不用考虑;第四项为指向调色板的指针;第五项为指向BITMAPINFO(包括BITMAPINFOHEADER,调色板,及实际的图象数据)的指针;第六项就用常量DIB_RGB_COLORS,不用考虑。上面提到了设备上下文,相信编过Windows程序的读者对它并不陌生,这里再简单介绍一下。Windows操作系统统一管理着诸如显示,打印等操作,将它们看作是一个个的设备,每一个设备都有一个复杂的数据结构来维护。所谓设备上下文就是指这个数据结构。然而,我们不能直接和这些设备上下文打交道,只能通过引用标识它的句柄(实际上是一个整数),让Windows去做相应的处理。产生的逻辑调色板句柄hPalette和位图句柄hBitmap要在处理WM_PAINT消息时使用,这样才能在屏幕上显示出来,处理过程如下面的程序。Static      HDC              hDC,hMemDC;PAINTSTRUCT            ps;case WM_PAINT:{hDC = BeginPaint(hwnd, &ps); //获得屏幕设备上下文if (hBitmap) //hBitmap一开始是NULL,当不为NULL时表示有图{hMemDC = CreateCompatible
      

  6.   

    确实有必要了解一下bmp文件格式
    去google搜索一下,我的jpg格式信息就是搜来的
    有的写的相当详细。搞懂后程序就不难写了
      

  7.   

    去看看http://www.gischina.com/maindoc/simchin/gisforum/format/
      

  8.   

    BMP文件个是最简单的
    其他的才叫难
    http://asp.6to23.com/iseesoft/devdoc/imgdoc/bmp_fileformat.htm