• 读取Exif信息需要对JPEG和Exif格式有简单的了解


    读取Exif信息需要对JPEG和Exif格式有简单的了解

    JEGP格式请查看云风的文章http://blog.csdn.net/glock18/archive/2004/09/05/95268.aspx

    Exif格式请查看猛禽的文章http://dev.csdn.net/article/27/27594.shtm

    下面给出了一个读取Exif信息的类:

    const
      JPEG_BEGIN = $FFD8;
      JPEG_APP1  = $FFE1;
      JPEG_END   = $FFD9;
      JPEG_EXIF  = (Byte('E') shl 24)+(Byte('x') shl 16)+(Byte('i') shl 8)+Byte('f');
      BYTE_ODR_I = (Byte('I') shl 8) + Byte('I');
      BYTE_ODR_M = (Byte('M') shl 8) + Byte('M');

    type
      U32  = DWORD;
      U16  = WORD;
      S32  = Integer;
      U8   = Byte;
               
      PIFDEntry   = ^YIFDEntry;
      YIFDEntry   = record
        u16tag    : U16;
        u16type   : U16;
        u32count  : U32;
        u32value  : U32;
        u32rsize  : U32; //数据真实大小---bytes
        u32maddr  : PChar; //数据在内存中的地址
        sDescript : string;
      end;

      YIFDTagInfo = record
        Tag       : U16;
        Mean      : string;
      end;

      YExifReader = class(TComponent)
      private
        FStream   : TFileStream;
        FTagInfo  : Array of YIFDTagInfo;
        FEntrys   : Array of YIFDEntry;
        FExifBuf  : PChar;//存放所有Exif value的内存
        FBufused  : U32;//
        FInfCount : S32;
        procedure GetEntryData( var ie: YIFDEntry; TiffHdrPos: U32 );
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        function ReadExif( JpgFileName: string ): string;
        function ExifInf( i: S32 ):string;
        property ExifInfoCount: S32 read FInfCount;
      end;


    implementation

    uses Winsock;

    const
      EXIF_ATTR_DEF_FILE = 'ExifInf.Ini';
      CLRF               = #13#10;

    //计算一个Entry数据的真实大小
    procedure GetEntrySize( var ie: YIFDEntry );
    begin
      case ie.u16type of
        1,2,7 : ie.u32rsize := 1;
        3     : ie.u32rsize := 2;
        4,9   : ie.u32rsize := 4;
        5,10  : ie.u32rsize := 8;
      else
        ie.u32rsize := 1;
      end;
      ie.u32rsize := ie.u32rsize * ie.u32count;
    end;

    //获得一个Entry的含义
    procedure GetEntryDescript( var ie: YIFDEntry; const iti: Array of YIFDTagInfo);
    var
      i : U16;
      b : BOOL;
    begin
      b := False;
      for i:=0 to Length(iti)-1 do
      begin
        if ie.u16tag = iti[i].Tag then
        begin
          ie.sDescript := iti[i].Mean;
          b := True; break;
        end;
      end;

      if not b then
         ie.sDescript := format( 'Unknow Tag: %.4x', [ie.u16tag] );
    end;

    constructor YExifReader.Create(AOwner: TComponent);
    var
      s : string;
      i,j : S32;
      lst : TStringList;
    begin
      inherited Create(AOwner);
      FStream := nil;
      FExifBuf := AllocMem( 1024 * 100 );//先分配100KB内存备用...足够存放所有信息了

      s := ExtractFilePath( ParamStr(0) );
      if s[Length(s)] <> '/' then
         s := s + '/';

      lst := TStringList.Create;
      lst.LoadFromFile( s + EXIF_ATTR_DEF_FILE );

      for i:=0 to lst.Count-1 do
      begin
        s := lst.Strings[i];
        if s[1] <> ';' then
        begin
          SetLength( FTagInfo, Length(FTagInfo)+1 );
          j := Pos( ' ', s );
          FTagInfo[Length(FTagInfo)-1].Tag := StrToInt( Copy(s,1,j-1) );
          FTagInfo[Length(FTagInfo)-1].Mean := Copy( s, j+1, Length(s)-j );
        end;
      end;
    end;

    destructor YExifReader.Destroy;
    begin
      if FStream <> nil then
         FStream.Free;
      FreeMem( FExifBuf );
      inherited Destroy;
    end;

    procedure YExifReader.GetEntryData( var ie: YIFDEntry; TiffHdrPos: U32 );
    begin
      ie.u32maddr := FExifBuf + FBufUsed;

      if ie.u32count <= 4 then
      begin
        Move( ie.u32value, ie.u32maddr^, ie.u32rsize );
        Inc( FBufUsed, ie.u32rsize );
        Exit;
      end;

      FStream.Position := TiffHdrPos + ie.u32value;
      FStream.Read( ie.u32maddr^, ie.u32rsize );
      Inc( FBufUsed, ie.u32rsize );
    end;

    function YExifReader.ReadExif( JpgFileName: string ): string;
    var
      i, w, TiffHeaderPos, IFD_0_EntryCount, IFD_1_EntryCount : U16;
      dw : U32;
    begin
      FStream := TFileStream.Create( JpgFileName, fmOpenRead );
      FBufUsed := 0;
      FInfCount := 0;

      //JEPG file header
      FStream.Read( w, sizeof(w) );
      if JPEG_BEGIN <> ntohs(w) then
      begin
        result := 'Not A Jpeg Image.' + CLRF;
        FreeAndNil( FStream );
        Exit;
      end;

      //search segment 'app1' ---Exif attribute information
      FStream.Read( w, sizeof(w) );
      w := ntohs(w);
      while JPEG_APP1 <> w do
      begin
        FStream.Read( w, sizeof(w) );
        FStream.Seek( ntohs(w)-sizeof(w), soFromCurrent );
        FStream.Read( w, sizeof(w) );
        w := ntohs(w);
        if JPEG_END = w then
        begin
          result := result + 'No Exif info.' + CLRF;
          FreeAndNil( FStream );
          Exit;
        end;
      end;

      result := result + 'Segment APP1 found.' + CLRF;
      FStream.Read( w, sizeof(w) );
      w := ntohs(w);
      result := result + 'Segment APP1 length: ' + format('%.4x',[w]) + CLRF;

      //search Exif sign ---'Exif'
      FStream.Read( dw, sizeof(dw) );
      dw := ntohl( dw );
      if JPEG_EXIF <> dw then
      begin
        result := result + 'No Exif in this segment.' + CLRF;
        FreeAndNil( FStream );
        Exit;
      end;

      result := result + 'Exif sign found...' + CLRF;
      FStream.Read( w, sizeof(w) ); //two zero

      //TIFF Header
      TiffHeaderPos := FStream.Position;
      FStream.Read( w, sizeof(w) );
      if BYTE_ODR_I = w then
      begin
        result := result + 'TIFF Header byte order is Intel.' +CLRF;
      end else
      begin //如果是Motolora格式的就不处理了~~~~~~`
        result := result + 'TIFF Header byte order is Motolora.' +CLRF;
        FreeAndNil( FStream );
        Exit;
      end;

      FStream.Read( w, sizeof(w) );//TIFF文件格式的标志,总是为0x002A
      FStream.Read( dw, sizeof(dw) );//第一个IFD的起始位置,其偏移量的计算起点是TIFF Header的起点
      FStream.Seek( dw-8, soFromCurrent );//8==size of Image File Header
      FStream.Read( w, sizeof(w) );//IFD.0 Entry Count
      result := result + 'TIFF IFD0 Entry count: ' + format('%.4x',[w]) +CLRF;

      IFD_0_EntryCount := w;
      SetLength( FEntrys, IFD_0_EntryCount );

      //read ifd entry
      for i:=0 to IFD_0_EntryCount-1 do
      begin
        FStream.Read( FEntrys[i].u16tag, sizeof(u16) );
        FStream.Read( FEntrys[i].u16type, sizeof(u16) );
        FStream.Read( FEntrys[i].u32count, sizeof(u32) );
        FStream.Read( FEntrys[i].u32value, sizeof(u32) );
        GetEntrySize( FEntrys[i] );
      end;

      //read ifd value
      for i:=0 to IFD_0_EntryCount-1 do
      begin
        GetEntryDescript( FEntrys[i], FTagInfo );
        GetEntryData( FEntrys[i], TiffHeaderPos );
      end;

      //Offset of Exif IFD = The last TIFF IFDEntry value + TIFF header offset
      FStream.Position := TiffHeaderPos + FEntrys[IFD_0_EntryCount-1].u32value;

      FStream.Read( w, sizeof(w) );//IFD.1 Entry Count
      result := result + 'TIFF IFD1 Entry count: ' + format('%.4x',[w]) +CLRF;

      IFD_1_EntryCount := w;
      SetLength( FEntrys, IFD_0_EntryCount + IFD_1_EntryCount );

      for i:=IFD_0_EntryCount to Length(FEntrys)-1 do
      begin
        FStream.Read( FEntrys[i].u16tag, sizeof(u16) );
        FStream.Read( FEntrys[i].u16type, sizeof(u16) );
        FStream.Read( FEntrys[i].u32count, sizeof(u32) );
        FStream.Read( FEntrys[i].u32value, sizeof(u32) );
        GetEntrySize( FEntrys[i] );
      end;

      for i:=IFD_0_EntryCount to Length(FEntrys)-1 do
      begin
        GetEntryDescript( FEntrys[i], FTagInfo );
        GetEntryData( FEntrys[i], TiffHeaderPos );
      end;

      FInfCount := Length(FEntrys);

      FreeAndNil( FStream );
    end;

    function YExifReader.ExifInf( i: S32 ):string;
    var
      s : string;
      p : PChar;
    begin
      if i >= Length(FEntrys) then
      begin
        result := '';
        Exit;
      end;

      result := FEntrys[i].sDescript + '   ';
      s := '';
      if (FEntrys[i].u16type = 2) or //Ascii or ExifVersion or FlashPixVersion
         (FEntrys[i].u16tag = $9000) or (FEntrys[i].u16tag = $A000) then
      begin
        SetLength( s, FEntrys[i].u32rsize );
        Move( FEntrys[i].u32maddr^, s[1], FEntrys[i].u32rsize );
      end else
      begin
        if (FEntrys[i].u16tag = $927C) or (FEntrys[i].u16tag = $9286) then
        begin //MakerNote or UserComment
          s := 'Not Read.';
          result := result + s;
          Exit;
        end;
        p := AllocMem( FEntrys[i].u32rsize * 2 + 1 );
        BinToHex( FEntrys[i].u32maddr, p, FEntrys[i].u32rsize );
        s := p;
        FreeMem( p );
      end;
      result := result + s;
    end;

    end.

    ;*********************************************************************
    ;
    ;               TIFF Rev. 6.0 Attribute Information
    ;
    ;********************************************************************* 
    ;
    ;
    ;   A. Tags relating to image data structure
    ;
    256 100 Image width                       -
    257 101 Image height                      -
    258 102 Number of bits per component      -
    259 103 Compression                       -
    262 106 Pixel composition                 -
    274 112 Orientation of image              -
    277 115 Number of components              -
    284 11C Image data arrangement            -
    530 212 Subsampling ratio of Y to C       -
    531 213 Y and C positioning               -
    282 11A Image resolution in width direct  -
    283 11B Image resolution in height direct -
    296 128 Unit of X and Y resolution        -
    ;
    ;   B. Tags relating to recording offset
    ;
    273 111 Image data location               -
    278 116 Number of rows per strip          -
    279 117 Bytes per compressed strip        -
    513 201 Offset to JPEG SOI                -
    514 202 Bytes of JPEG data                -
    ;
    ;   C. Tags relating to image data characteristics
    ;
    301 12D Transfer function                 -
    318 13E White point chromaticity          -
    319 13F Chromaticities of primaries       -
    529 211 Color space transformation matrix -
    532 214 Pair of black and white reference -
    ;
    ;   D. Other tags
    ;
    306 132 File change date and time         -
    270 10E Image Description                 -
    271 10F Image input equipment maker       -
    272 110 Image input equipment model       -
    305 131 Software used                     -
    315 13B Person who created the image      -
    3432 8298 Copyright holder                  -
    ;
    ;
    ;*********************************************************************
    ;
    ;               Exif IFD Attribute Information v2.1
    ;
    ;*********************************************************************
    ;
    ;    A. Tags Relating to Version
    ;
    36864 9000 Exif version                     -
    40960 A000 Supported FlashPix version       -
    ;
    ;    B. Tag Relating to Image Data Characteristics
    ;
    40961 A001 Color space information          -
    ;
    ;    C. Tags Relating to Image Configuration
    ;
    37121 9101 Meaning of each component        -
    37122 9102 Image compression mode           -
    40962 A002 Valid image width                -
    40963 A003 Valid image height               -
    ;
    ;    D. Tags Relating to User Information
    ;
    37500 927C Manufacturer notes               -
    37510 9286 User comments                    -
    ;
    ;    E. Tag Relating to Related File Information
    ;
    40964 A004 Related audio file               -
    ;
    ;    F. Tags Relating to Date and Time
    ;
    36867 9003 Date and time of original data   -
    36868 9004 Date and time of digital data    -
    37520 9290 DateTime subseconds              -
    37521 9291 DateTimeOriginal subseconds      -
    37522 9292 DateTimeDigitized subseconds     -
    ;
    ;    G. Tags Relating to Picture- Taking Conditions
    ;
    33434 829A Exposure time                    -
    33437 829D F number                         -
    34850 8822 Exposure program                 -
    34852 8824 Spectral sensitivity             -
    34855 8827 ISO speed rating                 -
    34856 8828 Optoelectric conversion factor   -
    37377 9201 Shutter speed                    -
    37378 9202 Aperture                         -
    37379 9203 Brightness                       -
    37380 9204 Exposure bias                    -
    37381 9205 Maximum lens aperture            -
    37382 9206 Subject distance                 -
    37383 9207 Metering mode                    -
    37384 9208 Light source                     -
    37385 9209 Flash                            -
    37386 920A Lens focal length                -
    41483 A20B Flash energy                     -
    41484 A20C Spatial frequency response       -
    41486 A20E Focal plane X resolution         -
    41487 A20F Focal plane Y resolution         -
    41488 A210 Focal plane resolution unit      -
    41492 A214 Subject location                 -
    41493 A215 Exposure index ExposureIndex     -
    41495 A217 Sensing method                   -
    41728 A300 File source                      -
    41729 A301 Scene type                       -
    41730 A302 CFA pattern                      -
    ;
    ;    H. Tags Relating to Date and Time
    ;
    40965 A005 Pointer of Interoperability IFD  -
    ;
    34665 8769 Exif IFD Pointer                 -
    34853 8825 GPS Info IFD Pointer             -
    40965 A005 Interoperability IFD Pointer     -
    ; END

  • 相关阅读:
    CSS选择器
    CSS选择器详解(二)通用选择器和高级选择器
    CSS选择器详解(一)常用选择器
    30个最常用css选择器解析
    常用CSS缩写语法总结
    XHTML 代码规范
    命名空间(xmlns属性)
    HTML 5 <meta> 标签
    HTML <!DOCTYPE> 标签
    Mybatis-generator 逆向工程
  • 原文地址:https://www.cnblogs.com/xianyin05/p/3071360.html
Copyright © 2020-2023  润新知