博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
24BITBMP位图的文件结构及创建
阅读量:4006 次
发布时间:2019-05-24

本文共 9274 字,大约阅读时间需要 30 分钟。

            下面这些结构说明来自,讲的很详尽。因为本文主要讲述24BIT的位图,所以关于16位的调色板就跳过了,至于原文,我觉得有一个地方是有误的,就是infoheader的biSizeImage 这个元素的描述,biSizeImage应该等于真正像素的数据的大小,并非宽为241就取244XheightX3.通过各种比较,这个数值应该等于每一行width填充byte[offset]后,offset如果不能被4整除,那么offset继续递加并往byte[offset]数组里面填充0(其他也可以,反正reader会跳过),它这个补齐,是基于储存像素时每行的byte长度不被4整齐时的补齐,并非单纯的width不被4整除时的补齐。

           根据位图的结构,也即是这几个语句就可以构成一张Bitmap了。这些代码的前身是java版本,翻译过来才发现,java版那个也有bug,自己好不容易纠正了。。

class procedure YUVTool.JBitmapToBitmapStream(pixels: TIntegerDynArray;  w, h: integer; outStream: TStream);var  w_headerinfo: tBITMAPINFOHEADER;  w_fileheader: TBitmapFileHeader;  w_rgb: TByteDynArray;begin  w_rgb := addbmp_rgb_888(pixels, w, h);  w_fileheader := addBMPImageHeader(length(w_rgb) * sizeof(byte));  w_headerinfo := addBMPImageInfosHeader(w, h,length(w_rgb));  outStream.Write(w_fileheader, Sizeof(TBitmapFileHeader));  outStream.Write(w_headerinfo, SizeOf(w_headerinfo));  outStream.Write(w_rgb[0], Length(w_rgb));end;
class function YUVTool.addBMPImageHeader(size: integer): TBitmapFileHeader;begin  FillChar(Result, sizeof(Result), 0);  with Result do  begin    bfType := $4D42;    bfSize := size + sizeof(TBitmapFileHeader) + SizeOf(TBitmapInfoHeader);    bfReserved1 := 0;    bfReserved2 := 0;    bfOffBits := $36;  end;end;class function YUVTool.addBMPImageInfosHeader(w, h: integer;imgSize:DWORD): TBitmapInfoHeader;begin  FillChar(Result, sizeof(Result), 0);  with Result do  begin    biSize := SizeOf(Result);    biWidth := w;    biHeight := h;    biPlanes := 1;    biBitCount := 24;    biCompression := 0;//BI_RGB    biSizeImage :=imgSize;    biXPelsPerMeter := $1274;    biYPelsPerMeter := $1274;    biClrUsed := 0;    biClrImportant := 0; { buffer[0] := $28;  buffer[1] := $00;  buffer[2] := $00;  buffer[3] := $00;  buffer[4] := byte(w shr 0);  buffer[5] := byte(w shr 8);  buffer[6] := byte(w shr 16);  buffer[7] := byte(w shr 24);  buffer[8] := byte(h shr 0);  buffer[9] := byte(h shr 8);  buffer[10] := byte(h shr 16);  buffer[11] := byte(h shr 24);  buffer[12] := $01;  buffer[13] := $00;  buffer[14] := $18;  buffer[15] := $00;  buffer[16] := $00;  buffer[17] := $00;  buffer[18] := $00;  buffer[19] := $00;  buffer[20] := $00;  buffer[21] := $00;  buffer[22] := $00;  buffer[23] := $00;  buffer[24] := byte($E0);  buffer[25] := $01;  buffer[26] := $00;  buffer[27] := $00;  buffer[28] := $02;  buffer[29] := $03;  buffer[30] := $00;  buffer[31] := $00;  buffer[32] := $00;  buffer[33] := $00;  buffer[34] := $00;  buffer[35] := $00;  buffer[36] := $00;  buffer[37] := $00;  buffer[38] := $00;  buffer[39] := $00;  Result := buffer;          }  end;end;

    下面这个代码是今天临时写的对比两个位图文件header结构差异的,用它来验证生产的位图跟原图是否一直,方面多了,先对比header,OK后再用beyond compare对比两个文件。。

program bmpcomp;{$mode objfpc}{$H+}uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}  Classes, SysUtils, CustApp  { you can add units after this };type  FXPT2DOT30 = longint;  LPFXPT2DOT30 = ^longint;  PCIEXYZ = ^TCIEXYZ;  {$EXTERNALSYM tagCIEXYZ}  tagCIEXYZ = packed record    ciexyzX: FXPT2DOT30;    ciexyzY: FXPT2DOT30;    ciexyzZ: FXPT2DOT30;  end;  TCIEXYZ = tagCIEXYZ;  {$EXTERNALSYM CIEXYZ}  CIEXYZ = tagCIEXYZ;  PCIEXYZTriple = ^TCIEXYZTriple;  {$EXTERNALSYM tagICEXYZTRIPLE}  tagICEXYZTRIPLE = packed record    ciexyzRed: TCIEXYZ;    ciexyzGreen: TCIEXYZ;    ciexyzBlue: TCIEXYZ;  end;  TCIEXYZTriple = tagICEXYZTRIPLE;  {$EXTERNALSYM CIEXYZTRIPLE}  CIEXYZTRIPLE = tagICEXYZTRIPLE;  PBitmapV4Header = ^TBitmapV4Header;  {$EXTERNALSYM BITMAPV4HEADER}  BITMAPV4HEADER = packed record    bV4Size: DWORD;    bV4Width: longint;    bV4Height: longint;    bV4Planes: word;    bV4BitCount: word;    bV4V4Compression: DWORD;    bV4SizeImage: DWORD;    bV4XPelsPerMeter: longint;    bV4YPelsPerMeter: longint;    bV4ClrUsed: DWORD;    bV4ClrImportant: DWORD;    bV4RedMask: DWORD;    bV4GreenMask: DWORD;    bV4BlueMask: DWORD;    bV4AlphaMask: DWORD;    bV4CSType: DWORD;    bV4Endpoints: TCIEXYZTriple;    bV4GammaRed: DWORD;    bV4GammaGreen: DWORD;    bV4GammaBlue: DWORD;  end;  TBitmapV4Header = BITMAPV4HEADER;  PBitmapCoreHeader = ^TBitmapCoreHeader;  {$EXTERNALSYM tagBITMAPCOREHEADER}  tagBITMAPCOREHEADER = packed record    bcSize: DWORD;    bcWidth: word;    bcHeight: word;    bcPlanes: word;    bcBitCount: word;  end;  TBitmapCoreHeader = tagBITMAPCOREHEADER;  {$EXTERNALSYM BITMAPCOREHEADER}  BITMAPCOREHEADER = tagBITMAPCOREHEADER;  PBitmapInfoHeader = ^TBitmapInfoHeader;  {$EXTERNALSYM tagBITMAPINFOHEADER}  tagBITMAPINFOHEADER = packed record    biSize: DWORD;    biWidth: longint;    biHeight: longint;    biPlanes: word;    biBitCount: word;    biCompression: DWORD;    biSizeImage: DWORD;    biXPelsPerMeter: longint;    biYPelsPerMeter: longint;    biClrUsed: DWORD;    biClrImportant: DWORD;  end;  TBitmapInfoHeader = tagBITMAPINFOHEADER;  {$EXTERNALSYM BITMAPINFOHEADER}  BITMAPINFOHEADER = tagBITMAPINFOHEADER;  PBitmapFileHeader = ^TBitmapFileHeader;  {$EXTERNALSYM tagBITMAPFILEHEADER}  tagBITMAPFILEHEADER = packed record    bfType: word;    bfSize: DWORD;    bfReserved1: word;    bfReserved2: word;    bfOffBits: DWORD;  end;  TBitmapFileHeader = tagBITMAPFILEHEADER;  {$EXTERNALSYM BITMAPFILEHEADER}  BITMAPFILEHEADER = tagBITMAPFILEHEADER;  { BmpInfoCmp }  BmpInfoCmp = class(TCustomApplication)  protected    procedure DoRun; override;  public    constructor Create(TheOwner: TComponent); override;    destructor Destroy; override;    procedure WriteHelp; virtual;  end;{ BmpInfoCmp }procedure getBmpHeader(filepath:String;out outHeader:TBitmapFileHeader;out outInfo:TBitmapInfoHeader);var w_filestream:TFileStream;begin     w_filestream:=TFileStream.Create(filepath,fmOpenRead or fmShareDenyWrite);     try        w_filestream.Read(outHeader,sizeof(outHeader));        w_filestream.Read(outInfo,sizeof(outInfo));     finally       FreeAndNil(w_filestream);     end;end;procedure BmpInfoCmp.DoRun;var  ErrorMsg: String;  f1,f2:String;  w_header1,w_header2:TBitmapFileHeader;  w_info1,w_info2:TBitmapInfoHeader;begin  // quick check parameters  ErrorMsg:=CheckOptions('h','help');  if ErrorMsg<>'' then begin    ShowException(Exception.Create(ErrorMsg));    Terminate;    Exit;  end;  // parse parameters  if HasOption('h','help') then begin    WriteHelp;    Terminate;    Exit;  end;  f1:=Params[1];  f2:=Params[2];  getBmpHeader(f1,w_header1,w_info1);  getBmpHeader(f2,w_header2,w_info2);  writeln('FILEHEADER');  if (w_header1.bfSize<>w_header2.bfSize) then begin    WriteLn('L.bfSize:',IntToHex(w_header1.bfSize,8) ,' ',w_header1.bfSize);    WriteLn('R.bfSize:',IntToHex(w_header2.bfSize,8) ,' ',w_header2.bfSize);  end;  writeln();  if (w_header1.bfOffBits<>w_header2.bfOffBits) then begin    WriteLn('L.bfOffBits:',IntToHex(w_header1.bfOffBits,8),' ',w_header1.bfOffBits);    WriteLn('R.bfOffBits:',IntToHex(w_header2.bfOffBits,8),' ',w_header2.bfOffBits);  end;  writeln('BITMAPINFOHEADER');  if (w_info1.biSize<>w_info2.biSize) then begin    WriteLn('L.biSize:',IntToHex(w_info1.biSize,8),' ',w_info1.biSize);    WriteLn('R.biSize:',IntToHex(w_info2.biSize,8),' ',w_info2.biSize);  end;  if (w_info1.biWidth<>w_info2.biWidth) then begin    WriteLn('L.biWidth:',IntToHex(w_info1.biWidth,8),' ',w_info1.biWidth);    WriteLn('R.biWidth:',IntToHex(w_info2.biWidth,8),' ',w_info2.biWidth);  end;  writeln('--');  if (w_info1.biHeight<>w_info2.biHeight) then begin    WriteLn('L.biHeight:',IntToHex(w_info1.biHeight,8),' ',w_info1.biHeight);    WriteLn('R.biHeight:',IntToHex(w_info2.biHeight,8),' ',w_info2.biHeight);  end;  writeln('--');  if (w_info1.biBitCount<>w_info2.biBitCount) then begin    WriteLn('L.biBitCount:',IntToHex(w_info1.biBitCount,8),' ',w_info1.biBitCount);    WriteLn('R.biBitCount:',IntToHex(w_info2.biBitCount,8),' ',w_info2.biBitCount);  end;  writeln('--');  if (w_info1.biCompression<>w_info2.biCompression) then begin    WriteLn('L.biCompression:',IntToHex(w_info1.biCompression,8),' ',w_info1.biCompression);    WriteLn('R.biCompression:',IntToHex(w_info2.biCompression,8),' ',w_info2.biCompression);  end;  writeln('--');  if (w_info1.biSizeImage<>w_info2.biSizeImage) then begin    WriteLn('L.biSizeImage:',IntToHex(w_info1.biSizeImage,8),' ',w_info1.biSizeImage);    WriteLn('R.biSizeImage:',IntToHex(w_info2.biSizeImage,8),' ',w_info2.biSizeImage);  end;  writeln('--');  if (w_info1.biXPelsPerMeter<>w_info2.biXPelsPerMeter) then begin    WriteLn('L.biXPelsPerMeter:',IntToHex(w_info1.biXPelsPerMeter,8),' ',w_info1.biXPelsPerMeter);    WriteLn('R.biXPelsPerMeter:',IntToHex(w_info2.biXPelsPerMeter,8),' ',w_info2.biXPelsPerMeter);  end;  writeln('--');  if (w_info1.biYPelsPerMeter<>w_info2.biYPelsPerMeter) then begin    WriteLn('L.biYPelsPerMeter:',IntToHex(w_info1.biYPelsPerMeter,8),' ',w_info1.biYPelsPerMeter);    WriteLn('R.biYPelsPerMeter:',IntToHex(w_info2.biYPelsPerMeter,8),' ',w_info2.biYPelsPerMeter);  end;  { add your program here }  // stop program loop  Terminate;end;constructor BmpInfoCmp.Create(TheOwner: TComponent);begin  inherited Create(TheOwner);  StopOnException:=True;end;destructor BmpInfoCmp.Destroy;begin  inherited Destroy;end;procedure BmpInfoCmp.WriteHelp;begin  { add your help code here }  writeln('Usage: ',ExeName,' -h');end;var  Application: BmpInfoCmp;begin  Application:=BmpInfoCmp.Create(nil);  Application.Title:='My Application';  Application.Run;  Application.Free;end.

转载地址:http://mozfi.baihongyu.com/

你可能感兴趣的文章
Android(六)Activity、请求码与结果码、Intent、广播、服务
查看>>
Android(六)通知、样式、主题、HTML
查看>>
浅谈 Facade 模式
查看>>
设计模式之Factory
查看>>
使用Hibernate进行大数据量的性能测试
查看>>
浅谈HTTP的无状态性
查看>>
程序调用飞信API发送免费短信(JAVA例子,其他语言一样用)
查看>>
向指定URL发送GET方法的请求(java)
查看>>
Oracle select in/exists/not in/not exits
查看>>
浅谈在Hibernate中使用Oracle sequence
查看>>
hibernate------hql总结
查看>>
Spring框架下PropertyPlaceholderConfigurer类
查看>>
Spring的lobhandler
查看>>
struts 标签logic:iterate用法详解
查看>>
Spring+Hibernate中的(FlushMode.NEVER)错误产生及解决
查看>>
spring的BeanUtils.copyProperties用法
查看>>
JAVA读取Oracle中的blob图片字段并显示
查看>>
Spring JTA应用之JOTM配置
查看>>
spring JdbcTemplate 的若干问题
查看>>
Servlet和JSP的线程安全问题
查看>>