erbi_lucifer吧 关注:406贴子:3,325
  • 8回复贴,共1

【win32 ASM】File format parsing (part 4)

只看楼主收藏回复



一楼心然……


1楼2013-04-29 15:53回复

    (一)文件组成
    文件结构及文件头PCX图像由3个部分组成,即文件头、位图数据和一个多达256种色彩的调色板。
    pcx文件头的结构比较简单,为固定的128字节。
    (1)16字节的文件头
    (2)48字节的16色调色板
    (3)6字节的文件信息
    (4)58字节的“00”
    (5)图像数据


    本楼含有高级字体3楼2013-04-29 15:56
    回复

      (二)构建结构体
      根据文件结构我们可以构建下面的结构体,然后读取文件即可获取文件的信息。
      PcxFileHeader struct ; // pcx文件头
      flag BYTE ?;// 标记
      version BYTE ?;// 版本号
      encodeing BYTE ?;// 编码方式
      bitsPrePixel BYTE ?; // 平面像素位数
      xMin WORD ?;// 最小X
      yMin WORD ?;// 最小Y
      xMax WORD ?;// 最大X
      yMax WORD ?;// 最大Y
      hRes WORD ?;// 水平分辨率
      vRes WORD ?;// 垂直分辨率
      palette db 48 dup(?); // 16色调色板
      reserved BYTE ?;// 保留
      iplanes BYTE ?;// 平面数
      bytesPreLine WORD ?; // 每行字节数
      paletteType WORD ?; // 调色板类型。1:彩色或黑白,2:灰度
      filler db 58 dup(?);//全空直到文件结束
      PcxFileHeader ends


      本楼含有高级字体4楼2013-04-29 15:57
      回复

        (三)读取文件信息
        接下来以图标文件“1.pcx”(文件见附件)为例子读取它的结构信息。
        (1)图片“1.pcx”的文件头(16字节)结构:

        1. 字节1:数值是“0A”,故标记为‘A‘。
        2. 字节2:数值是“05”,故版本号为5。
        3. 字节3:数值是“01”,故编码方式为1。
        4. 字节4:数值是“08”,故平面像素位数为8。
        5. 字节5-6:数值是“00 00”,故最小X坐标为0
        6. 字节7-8:数值是“00 00”,故最小Y坐标为0
        7. 字节9-10:数值是“63 00”,故最大X坐标为99
        8. 字节11-12:数值是“DC 00”,故最大X坐标为220
        9. 字节13-14:数值是“B7 00”,故水平分辨率:183
        10. 字节15-16:数值是“B7 00”,故垂直分辨率:183


        本楼含有高级字体5楼2013-04-29 15:58
        回复

          PCX进行解码的关键因为在一个PCX文件中可以用到几种不同的记录方法,因此其中必须包含所用方法的标志。
          在对PCX进行解释时,单靠读取版本号是不够的,最可靠的标志是每像素的位数(文件头的第3个字节)和色彩平面数(文件头的第65个字节),这两个标志与图像色彩数的对应关系如下表所示。
          每像素的位数 色彩平面数 解释
          1 1 单色
          1 2 4色
          1 3 8色
          1 4 16色
          2 1 4色
          2 4 16色
          4 1 16色
          8 1 256色
          8 3 16.7兆色
          (4)58字节的填充数据,都是“00”。


          7楼2013-04-29 15:59
          回复

            读取的128字节文件头:


            8楼2013-04-29 16:00
            回复

              START:
              ;获取参数
              invoke GetCommandLine
              mov CommandLine,eax
              ;提取参数
              invoke PathGetArgs,CommandLine
              mov LpArg,eax mov esi,eax
              lodsb ;[esi]-->al
              cmp al,0
              je noArgs
              cmp al,34 ;双引号
              jne @F
              invoke PathUnquoteSpaces,LpArg ;去双引号
              mov LpArg,eax
              @@:
              invoke CreateFile,LpArg, GENERIC_READ,FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL
              .if eax!=INVALID_HANDLE_VALUE
              mov hFile, eax
              invoke ReadFile,hFile,addr pcx, sizeof pcx, addr dwRead, NULL
              .if dwRead!= sizeof pcx
              jmp endexit
              .else
              invoke ShowPcxHead,pcx
              invoke ShowFileType,pcx
              .endif
              .else
              jmp openerror
              .endif
              invoke CloseHandle, hFile
              jmp endexit
              noArgs:
              invoke StdOut,addr lpMsg
              jmp endexit
              openerror:
              invoke StdOut,addr lpMsg_fileerr
              jmp endexit
              endexit:
              ;暂停显示,回车键关闭
              invoke StdIn,addr buffer,sizeof buffer
              invoke ExitProcess,0


              10楼2013-04-29 16:01
              回复

                ShowPcxHead proc mypcx:PcxFileHeader
                invoke wsprintf,addr info,CTXT(13,10,"====================PCX信息头====================",13,10)
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("标记:%X",13,10), mypcx.flag
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("版本号:%d",13,10), mypcx.version
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("编码方式:%d",13,10), mypcx.encodeing
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("平面像素位数:%d",13,10), mypcx.bitsPrePixel
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("最小X:%d",13,10), mypcx.xMin
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("最小Y:%d",13,10), mypcx.yMin
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("最大X:%d",13,10), mypcx.xMax
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("最大Y:%d",13,10), mypcx.yMax
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("水平分辨率:%d",13,10), mypcx.hRes
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("垂直分辨率:%d",13,10), mypcx.vRes
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("保留:%d",13,10), mypcx.reserved
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("平面数:%d",13,10), mypcx.iplanes
                invoke StdOut,addr info
                invoke wsprintf,addr info,CTXT("每行字节数:%d",13,10), mypcx.bytesPreLine
                invoke StdOut,addr info
                .if pcx.paletteType==1
                invoke wsprintf,addr info,CTXT("调色板类型:彩色或黑白",13,10)
                .else
                invoke wsprintf,addr info,CTXT("调色板类型:灰度",13,10)
                .endif
                invoke StdOut,addr info
                ret
                ShowPcxHead endp


                11楼2013-04-29 16:02
                回复

                  ShowFileType proc mypcx:PcxFileHeader
                  cmp pcx.bitsPrePixel,1
                  jne bp2
                  cmp pcx.iplanes,1
                  jne bp1goon1
                  invoke wsprintf,addr info,CTXT("单色PCX文件",13,10)
                  invoke StdOut,addr info
                  ret
                  bp1goon1:
                  cmp pcx.iplanes,2
                  jne bp1goon2
                  invoke wsprintf,addr info,CTXT("4色PCX文件",13,10)
                  invoke StdOut,addr info
                  ret
                  bp1goon2:
                  cmp pcx.iplanes,3
                  jne noside
                  invoke wsprintf,addr info,CTXT("8色PCX文件",13,10)
                  invoke StdOut,addr info
                  ret
                  bp2:
                  cmp pcx.bitsPrePixel,2
                  jne bp3
                  cmp pcx.iplanes,1
                  jne bp2goon1
                  invoke wsprintf,addr info,CTXT("4色PCX文件",13,10)
                  invoke StdOut,addr info
                  ret
                  bp2goon1:
                  cmp pcx.iplanes,4
                  jne noside
                  invoke wsprintf,addr info,CTXT("16色PCX文件",13,10)
                  invoke StdOut,addr info
                  ret
                  bp3:
                  cmp pcx.bitsPrePixel,4
                  jne bp4
                  cmp pcx.iplanes,1
                  jne noside
                  invoke wsprintf,addr info,CTXT("16色PCX文件",13,10)
                  invoke StdOut,addr info
                  ret
                  bp4:
                  cmp pcx.bitsPrePixel,8
                  jne noside
                  cmp pcx.iplanes,1
                  jne bp4goon1
                  invoke wsprintf,addr info,CTXT("256色PCX文件",13,10)
                  invoke StdOut,addr info
                  ret
                  bp4goon1:
                  cmp pcx.iplanes,3
                  jne noside
                  invoke wsprintf,addr info,CTXT("16.7兆色PCX文件",13,10)
                  invoke StdOut,addr info
                  ret
                  noside:
                  invoke wsprintf,addr info,CTXT("未知PCX文件",13,10)
                  invoke StdOut,addr info
                  ret
                  ShowFileType endp
                  end START


                  12楼2013-04-29 16:02
                  回复