Icon File parsing

Source: Internet
Author: User

Icon is a form of icons for system icons, software icons, and so on, with the extension *.icon, *.ico. The most common software or icons on the Windows desktop are usually in icon format.

Icon file format is simple, including the header segment, image data header, image data segment.

File header:
The file header is 6 bytes and is defined as follows:

123456 type  ICONDIR = packedrecord    idReserved: SmallInt// Reserved    idType: SmallInt// Resource type    idCount: SmallInt// Image Count  end// 6 bytes

Idcount marks the number of images contained in the file.

Image Data Header segment:

Immediately after the file header is the image Data header section, it holds the file each image width, height, color number, data segment offset and other information, size of * idcount. It is an array of 16 bytes per item of data, defined as follows:

Type  icondirentry = packed record    bwidth:byte;//Width of the image    Bheight:byte;//Height of the image (2 * Height)    bcolorcount:byte;//number of colors in image (0 when >= 8 bpp)    breserved:byte;//Reserved    W Planes:smallint; Color Planes   (-xhotspot [cursor])    wbitcount:smallint;//Bits per pixel (-yhotspot [cursor])    DwB Ytesinres:integer; How many bytes in this resource?    Dwimageoffset:integer; Where in the file is this image?  End bytes

After reading the image data header, you can know the size of each icon in the file, the number of color bits, and directly according to the data segment offset, read the image data segment. The offset of the image data is calculated from the beginning of the file.

Image Data segment:

The image data is the DIB data of multiple images and is positioned according to the offset of the data header segment. After locating, read the BiH information. From the BiH information, to determine the number of colors more than 8 bits, remember the XOR palette data (less than 8 bits of the non-existent XOR palette, contains only a mask palette). After reading the XOR palette, initialize the image Dib header, and then read the DIB data in the file.

The following is a look at the implementation of the Load code: (Note: This sample code, only load the ICO file the highest number of color bits, the largest one)

Related definitions:

Type dibbppcts = (bpp_01 = 1, bpp_04 = 4, bpp_08 = 8, bpp_16 = +, bpp_24 = 32, bpp_32 =);    Dibitem = Packed record private function getbpp:dibbppcts;    function Getbytesperscanline:integer;    function Getheight:integer;    function Getwidth:integer;  function Getsize:integer;    Public M_ubih:bitmapinfoheader;    M_hdc:integer;    M_hdib:integer;    M_holddib:integer;    M_lpbits:pointer;    M_lpbitssize:integer; function Create (newwidth, Newheight:integer;    newbpp:dibbppcts): Boolean;    Procedure free ();    Procedure Clone (var todib:dibitem);    Procedure Getpalette (var palette:tbytes);    Procedure SetPalette (palette:tbytes);      function Stretch (DC:HDC; x, Y, W, H, Xsrc, Ysrc, WSRC, Hsrc:integer;    rop:cardinal): Integer; function Stretch32 (DC:HDC; Bufferbits:pointer;    Bytesperrow, X, Y, W, H, Xsrc, Ysrc, WSRC, Hsrc:integer): Integer;    Property Width:integer read getwidth;    Property Height:integer read getheight; Property Bpp:dIbbppcts read GETBPP;    Property Bytesperscanline:integer read Getbytesperscanline;  Property Size:integer read GetSize;  End Dibdata = packed record xordib:dibitem; XOR DIB section Anddib:dibitem;    and DIB section End;type bitmapinfo_001 = packed record bmiheader:bitmapinfoheader;  Bmicolors:array [0.. 7] of Byte;  End    bitmapinfo_004 = packed record bmiheader:bitmapinfoheader;  Bmicolors:array [0..] of Byte;  End    bitmapinfo_008 = packed record bmiheader:bitmapinfoheader;  Bmicolors:array [0.. 1023] of Byte;  End  Bitmapinfo_rgb = packed record bmiheader:bitmapinfoheader; End;type icobppcts = (colors_002 = 1, colors_016 = 4, colors_256 = 8, Color_true =, Color_argb = 32);

Load code:

Procedure Tyxdicon.loadfromstream (Stream:tstream); var nimg:integer;begin//Get icon Header Fillchar (M_udir, sizeof (m  _udir), 0);  Stream.read (M_udir, sizeof (M_udir));  Get icon Entries SetLength (m_udirentry, M_udir.idcount);  Stream.read (m_udirentry[0], sizeof (icondirentry) * m_udir.idcount);  Initialize Arrays and Monochrome palette//setlength (M_orderkey, M_udir.idcount);  SetLength (M_udibdata, M_udir.idcount);  SetLength (M_dibdata, M_udir.idcount);  SetLength (Apaland, 8);  Fillchar (Apaland[0], SizeOf (Apaland), 0);  APALAND[4]: = $FF;  APALAND[5]: = $FF;  APALAND[6]: = $FF;  Get images Nmaxindex: =-1;  NMAXW: = 0; For nimg: = 0 to M_udir.idcount-1 do BEGIN if (M_udirentry[nimg].bwidth > Nmaxw) or ((M_udirentry[nimg].bwidt      h = nmaxw) and (m_udirentry[nimg].bcolorcount = 0) THEN BEGIN NMAXW: = M_udirentry[nimg].bwidth;    Nmaxindex: = nimg;  End  End If Nmaxindex >-1 THEN BEGIN/Move to begin of image data stream.position: =M_udirentry[nmaxindex].dwimageoffset;    Load bitmapinfoheader stream.read (uBIH, SizeOf (uBIH)); Load XOR palette [?]      (<= 8 BPP) if Ubih.bibitcount <= 8 then BEGIN SetLength (Apalxor, 4 * TRUNC (Power (2, Ubih.bibitcount)));    Stream.read (Apalxor[0], Length (Apalxor));    End    Inititalize XOR DIB Fillchar (M_udibdata, SizeOf (M_udibdata), 0);    M_uDIBData.XORDIB.Create (Ubih.biwidth, Ubih.biheight Div 2, dibbppcts (Ubih.bibitcount));    If Ubih.bibitcount <= 8 then M_uDIBData.XORDIB.SetPalette (APALXOR);    Inititalize and DIB m_uDIBData.ANDDIB.Create (Ubih.biwidth, Ubih.biheight Div 2, bpp_01);    M_uDIBData.ANDDIB.SetPalette (Apaland);    Read DIB bits M_uDIBData.XORDIB.m_lpBits: = GetMemory (m_uDIBData.XORDIB.Size);    M_uDIBData.ANDDIB.m_lpBits: = GetMemory (m_uDIBData.ANDDIB.Size);    Stream.read (m_udibdata.xordib.m_lpbits^, m_uDIBData.XORDIB.Size);    Stream.read (m_udibdata.anddib.m_lpbits^, m_uDIBData.ANDDIB.Size); M_orderkey: = InTtohex (Ubih.biwidth, 3) + Inttohex (ubih.biheight Div 2, 3) + Inttohex (Ubih.bibitcount, 2);  End Changed (self); end;

Dibitem is the image data of an icon in the icons file, the code is as follows:

{Dibitem}procedure dibitem.clone (var todib:dibitem); var apal:tbytes;begin if M_hdib <> 0 THEN BEGIN TODIB.C    Reate (M_ubih.biwidth, M_ubih.biheight, Dibbppcts (M_ubih.bibitcount));      If m_lpbits <> nil then begin todib.m_lpbits: = GetMemory (Size);    CopyMemory (Todib.m_lpbits, M_lpbits, Size);    End else todib.m_lpbits: = nil;        if (M_ubih.bibitcount <= 8) THEN begin SetLength (Apal, 4 * TRUNC (Power (2, M_ubih.bibitcount))-1);        Getpalette (Apal);    Todib.setpalette (Apal);  End  End;end;function dibitem.create (Newwidth, Newheight:integer;  newbpp:dibbppcts): Boolean;var bi_001:bitmapinfo_001;  bi_004:bitmapinfo_004;  bi_008:bitmapinfo_008;  Bi_rgb:bitmapinfo_rgb;begin free ();  Define DIB header m_ubih.bisize: = SizeOf (M_ubih);  M_ubih.biplanes: = 1;  M_ubih.bibitcount: = Integer (NEWBPP);  M_ubih.biwidth: = Newwidth;  M_ubih.biheight: = Newheight; M_ubih.bisizeimage: = 4 * ((M_ubih.biwidth * m_ubih.bibitcount +) Div 32) * m_ubih.biheight;    Case NEWBPP of Bpp_01:BI_001.bmiHeader: = M_ubih;    Bpp_04:BI_004.bmiHeader: = M_ubih;  Bpp_08:BI_008.bmiHeader: = M_ubih;  else Bi_rgb.bmiheader: = M_ubih end;  Create DIB and select into a DC m_hdc: = CreateCompatibleDC (0); If M_HDC <> 0 THEN begin case NEWBPP of Bpp_01:m_hdib: = CreateDIBSection (m_hDC, Pbitmapinfo (@BI_001) ^, DIB      _rgb_colors, m_lpbits, 0, 0);      Bpp_04:m_hdib: = CreateDIBSection (m_hDC, Pbitmapinfo (@BI_004) ^, dib_rgb_colors, m_lpbits, 0, 0);    Bpp_08:m_hdib: = CreateDIBSection (m_hDC, Pbitmapinfo (@BI_008) ^, dib_rgb_colors, m_lpbits, 0, 0);    else M_hdib: = CreateDIBSection (m_hDC, Pbitmapinfo (@BI_RGB) ^, dib_rgb_colors, m_lpbits, 0, 0);    End  If M_hdib <> 0 then M_holddib: = SelectObject (M_HDC, m_hdib) Else free;  End Result: = M_hdib <> 0;end;procedure dibitem.free;begin if m_hdc <> 0 THEN BEGIN if M_hdib <> 0 Then Begin SelectObject (M_HDC, M_holddib);    DeleteObject (M_HDIB);    End  DeleteDC (M_HDC);  End    If m_lpbits <> nil then begin Freememory (m_lpbits);  M_lpbits: = nil;  End  Fillchar (M_ubih, SizeOf (M_ubih), 0);  M_HDC: = 0;  M_hdib: = 0; M_holddib: = 0;end;function dibitem.getbpp:dibbppcts;begin Result: = Dibbppcts (m_ubih.bibitcount); end;function Dibitem.getbytesperscanline:integer;begin Result: = ((M_ubih.biwidth * m_ubih.bibitcount +) div.) * 4;end;function Dibitem.getheight:integer;begin Result: = M_ubih.biheight;end;procedure Dibitem.getpalette (var palette:tbytes); Begin if M_hdib <> 0 then getdibcolortable (m_hdc, 0, Trunc (Power (2, M_ubih.bibitcount)), Palette[low (Palette)]);  End;function dibitem.getsize:integer;begin Result: = M_ubih.bisizeimage;end;function dibitem.getwidth:integer;begin Result: = M_ubih.biwidth;end;procedure Dibitem.setpalette (palette:tbytes); Begin Setdibcolortable (M_hDC, 0, (High) ( Palette)-Low (Palette) + 1) Div 4, Palette[low (Palette)]) end;function DibiteM.stretch (DC:HDC; x, Y, W, H, Xsrc, Ysrc, WSRC, Hsrc:integer;  rop:cardinal): Integer;var b001:bitmapinfo_001;  b004:bitmapinfo_004;  b008:bitmapinfo_008;  Brgb:bitmapinfo_rgb;  Ilen:integer;  Loldmode:integer;begin Result: = 0;  If M_hdib = 0 then Exit;  Loldmode: = Setstretchbltmode (DC, Coloroncolor);  Ilen: = Trunc (Power (2, M_ubih.bibitcount));        Case Dibbppcts (m_ubih.bibitcount) of bpp_01:begin b001.bmiheader: = M_ubih;        Getdibcolortable (M_HDC, 0, Ilen, b001.bmicolors[0]);      StretchDIBits (DC, X, Y, W, H, Xsrc, Ysrc, WSRC, HSRC, M_lpbits, Pbitmapinfo (@b001) ^, dib_rgb_colors, ROP);    End        Bpp_04:begin B004.bmiheader: = M_ubih;        Getdibcolortable (M_HDC, 0, Ilen, b004.bmicolors[0]);      StretchDIBits (DC, X, Y, W, H, Xsrc, Ysrc, WSRC, HSRC, M_lpbits, Pbitmapinfo (@b004) ^, dib_rgb_colors, ROP);    End        Bpp_08:begin B008.bmiheader: = M_ubih; Getdibcolortable (M_HDC, 0, Ilen, B008.bmicoLors[0]);      StretchDIBits (DC, X, Y, W, H, Xsrc, Ysrc, WSRC, HSRC, M_lpbits, Pbitmapinfo (@b008) ^, dib_rgb_colors, ROP);    End      ELSE begin Brgb.bmiheader: = M_ubih;    StretchDIBits (DC, X, Y, W, H, Xsrc, Ysrc, WSRC, HSRC, M_lpbits, Pbitmapinfo (@brgb) ^, dib_rgb_colors, ROP);  End  End  Setstretchbltmode (DC, Loldmode); Result: = 1;end;function dibitem.stretch32 (DC:HDC; Bufferbits:pointer;  Bytesperrow, X, Y, W, H, Xsrc, Ysrc, WSRC, Hsrc:integer): Integer;var I, I2, J, J2:integer;  Stretch:boolean;  Factorx, factory:double;  Abytesperscanline:integer;  Alphasource, imagedata:ppixelline;begin Result: = 0;  if (M_hdib = 0) or (m_lpbits = nil) then Exit;  Stretch: = (W <> wSrc) or (H <> hsrc);  If Stretch then Factorx: = W/wsrc Else Factorx: = 1;  If Stretch then FactorY: = H/hsrc Else FactorY: = 1;  Alphasource: = m_lpbits;  Abytesperscanline: = Bytesperscanline; Pbyte (ImageData): = Pbyte (Integer (bufferbits) + Bytesperrow * (H- 1));  Bufferbits: = ImageData; If M_ubih.bibitcount = and begin for J: = 1 to H does begin for I: = 0 to W-1 does begin if Stretch then        I2: = trunc (I/factorx) Else i2: = i;            if (alphasource[i2].rgbreserved <> 0) THEN BEGIN if (alphasource[i2].rgbreserved = 255) THEN BEGIN          Imagedata[i]: = Alphasource[i2]; End else with Imagedata[i] do begin rgbred: = ($7f + alphasource[i2].rgbred * ALPHASOURCE[I2].RGBR              Eserved + rgbred * (not alphasource[i2].rgbreserved)) Div $FF; Rgbgreen: = ($7f + alphasource[i2].rgbgreen * alphasource[i2].rgbreserved + rgbgreen * (not ALPHASOURCE[I2]              . rgbreserved)) Div $FF; Rgbblue: = ($7f + alphasource[i2].rgbblue * alphasource[i2].rgbreserved + rgbblue * (not Alphasource[i2].rgb              Reserved)) Div $FF;            Rgbreserved: = Not (($7f + (not rgbreserved) * (not alphasource[i2].rgbreserved)) div $FF); EnD      End      End      {Move Pointers}      Pbyte (ImageData): = Pbyte (Integer (bufferbits)-Bytesperrow * j);      If Stretch then J2: = Trunc (j/factory) Else J2: = j;    Pbyte (alphasource): = Pbyte (m_lpbits) + abytesperscanline * J2;  End END; Result: = 1;end;

Display of Icon:

The Tyxdicon in this example inherits from Ticon, which is itself a graphic, so you can overload the draw implementation display directly.

Type Tyxdicon = Class (Ticon) private m_udir:icondir; Icon file header M_udirentry:array of Icondirentry; Icon image Headers m_orderkey:string;    Image format key apalxor:tbytes;    Apaland:tbytes;    Nmaxw:byte;    Nmaxindex:integer;    Ubih:bitmapinfoheader;    BUFFERDC:HDC;    Oldbufferbitmap, Bufferbitmap:hbitmap;    LASTW, Lasth:integer;  Fusebuffer:boolean; protected m_udibdata:dibdata; Icon data (DIBs) function Getempty:boolean;    Override function Getheight:integer;    Override function Getwidth:integer;    Override Procedure Draw (Acanvas:tcanvas; const rect:trect);    Override function Getsupportspartialtransparency:boolean;  Override Public constructor Create;    Override destructor Destroy;    Override Procedure Assign (source:tpersistent);    Override Procedure Loadfromstream (Stream:tstream);    Override Procedure Savetostream (Stream:tstream);    Override Property Usebuffer:boolean Read Fusebuffer write FUsEbuffer; End
Procedure Tyxdicon.draw (Acanvas:tcanvas; const rect:trect); var bitmapinfo:tbitmapinfo;  Bufferbits, Buf:pointer;  Alphasource, Imagedata:ppixelline;  W, H:integer;  Bytesperrow:integer;  I, j:integer;begin W: = Rect.right-rect.left;  H: = Rect.bottom-rect.top;  Bitmapinfo: = Getbitmapinfoheader (W, H);  BUFFERDC: = CreateCompatibleDC (0);  if (BUFFERDC = 0) then Exit;  Bytesperrow: = ((((BitmapInfo.bmiHeader.biBitCount * W) + () and not) Div 8;  Bufferbitmap: = CreateDIBSection (BUFFERDC, Pbitmapinfo (@BitmapInfo) ^, dib_rgb_colors, bufferbits, 0, 0);  Oldbufferbitmap: = SelectObject (BUFFERDC, Bufferbitmap);  BitBlt (BUFFERDC, 0, 0, W, H, Acanvas.handle, Rect.left, Rect.top, srccopy); If M_uDIBData.XORDIB.BPP = Bpp_32 then BEGIN M_uDIBData.XORDIB.Stretch32 (BUFFERDC, Bufferbits, Bytesperrow, Rect.left,  Rect.top, W, H, 0, 0, m_uDIBData.XORDIB.Width, m_uDIBData.XORDIB.Height); End ELSE begin//Draw Mask layer M_uDIBData.ANDDIB.Stretch (BUFFERDC, Rect.left, rect.tOP, W, H, 0, 0, m_uDIBData.XORDIB.Width, M_uDIBData.XORDIB.Height, srccopy);    Save Transparent Area information Buf: = GetMemory (bytesperrow*h);    CopyMemory (Buf, Bufferbits, bytesperrow*h); Draw the actual image M_uDIBData.XORDIB.Stretch (BUFFERDC, Rect.left, Rect.top, W, H, 0, 0, M_uDIBData.XORDIB.Width, M_udibdata. Xordib.    Height, srccopy);    Apply Mask pbyte (ImageData): = Pbyte (bufferbits);    Alphasource: = Buf; for J: = 1 to H does begin for I: = 0 to W-1 does begin if (Alphasource[i].rgbblue = 0) and (ALPHASOURCE[I].RGBG        Reen = 0) and (alphasource[i].rgbred = 0) THEN BEGIN imagedata[i].rgbreserved: = $FF;      End else imagedata[i].rgbreserved: = 0;      End      {Move Pointers} Inc (Pbyte (Alphasource), bytesperrow);    Inc (Pbyte (ImageData), bytesperrow);    End  Freememory (BUF);  End Tyxdcanvas (Acanvas).  Requiredstate ([cshandlevalid]);  BitBlt (Acanvas.handle, Rect.left, Rect.top, W, H, BUFFERDC, 0, 0, srccopy); SelectObject (BUFFERDC, OldbufferbitMAP);  DeleteObject (BUFFERBITMAP);  DeleteDC (BUFFERDC); Bufferbitmap: = 0;end;

The main areas of special handling in the display are the transparent channel icons that distinguish whether they are 32-bit. With no transparent channels, the mask layer is used for transparent processing.

Http://www.cnblogs.com/yangyxd/articles/3984901.html

Icon File parsing

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.