Jpeg圖片屬性讀取EXIF

來源:互聯網
上載者:User

jpeg圖片屬性讀取

測試環境  Delphi XE

主要功能代碼擷取自其他作者

單元檔案

unit utJpegInfo;interfaceuses  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  Dialogs, StdCtrls;type  TfrmJpegInfo = class(TForm)    btnOpenJpeg: TButton;    mmoJpegInfo: TMemo;    procedure btnOpenJpegClick(Sender: TObject);  private    { Private declarations }    fsImage : TFileStream;    i64RefPos : int64;    //讀取Jpeg資訊    procedure ReadJpegInfo(const JpegFileName : string);    //讀取byte值    function GetByte: byte;    //讀取Word值    function GetWord: word;    //讀取DWord值    function GetDWord: DWord;    //擷取指定長度的字串    function GetString(intBufferSize: integer): string;    //標籤名稱    function GetTagName(wrdTag: Word): string;    //讀取Jpeg的標籤資訊    procedure pReadIFD;  public    { Public declarations }  end;var  frmJpegInfo: TfrmJpegInfo;implementation{$R *.dfm}function TfrmJpegInfo.GetByte : byte;begin  fsImage.Read(result, 1);end;function TfrmJpegInfo.GetWord : word;begin  result := GetByte OR (GetByte SHL 8);end;function TfrmJpegInfo.GetDWord : DWord;begin  result := GetWord OR (GetWord SHL 16);end;function TfrmJpegInfo.GetString(intBufferSize : integer) : string;var  strResult : string;  i : integer;begin  result := '';  for i := 1 to intBufferSize do    result := result + chr(GetByte);end;function TfrmJpegInfo.GetTagName(wrdTag : Word) : string;begin  Case wrdTag of   $001: result :='InteroperabilityIndex';   $002: result :='InteroperabilityVersion';   $0FE: result :='NewSubfileType';   $0FF: result :='SubfileType';   $100: result :='ImageWidth';   $101: result :='ImageLength';   $102: result :='BitsPerSample';   $103: result :='Compression';   $106: result :='PhotometricInterpretation';   $10A: result :='FillOrder';   $10D: result :='DocumentName';   $10E: result :='ImageDescription';   $10F: result :='Make';   $110: result :='Model';   $111: result :='StripOffsets';   $112: result :='Orientation';   $115: result :='SamplesPerPixel';   $116: result :='RowsPerStrip';   $117: result :='StripByteCounts';   $11A: result :='XResolution';   $11B: result :='YResolution';   $11C: result :='PlanarConfiguration';   $128: result :='ResolutionUnit';   $12D: result :='TransferFunction';   $131: result :='Software';   $132: result :='DateTime';   $13B: result :='Artist';   $13D: result :='Predictor';   $13E: result :='WhitePoint';   $13F: result :='PrimaryChromaticities';   $142: result :='TileWidth';   $143: result :='TileLength';   $144: result :='TileOffsets';   $145: result :='TileByteCounts';   $14A: result :='SubIFDs';   $15B: result :='JPEGTables';   $156: result :='TransferRange';   $200: result :='JPEGProc';   $201: result :='JPEGInterchangeFormat';   $202: result :='JPEGInterchangeFormatLength';   $211: result :='YCbCrCoefficients';   $212: result :='YCbCrSubSampling';   $213: result :='YCbCrPositioning';   $214: result :='ReferenceBlackWhite';   $1001: result :='Related Image Width';   $1002: result :='Related Image Height';   $828D: result :='CFARepeatPatternDim';   $828E: result :='CFAPattern';   $828F: result :='BatteryLevel';   $8298: result :='Copyright';   $829A: result :='ExposureTime';   $829D: result :='FNumber';   $83BB: result :='IPTC/NAA';   $8769: result :='ExifOffset';   $8773: result :='InterColorProfile';   $8822: result :='ExposureProgram';   $8824: result :='SpectralSensitivity';   $8825: result :='GPSInfo';   $8827: result :='ISOSpeedRatings';   $8828: result :='OECF';   $8829: result :='Interlace';   $882A: result :='TimeZoneOffset';   $882B: result :='SelfTimerMode';   $9000: result :='ExifVersion';   $9003: result :='DateTimeOriginal';   $9004: result :='DateTimeDigitized';   $9101: result :='ComponentsConfiguration';   $9102: result :='CompressedBitsPerPixel';   $9201: result :='ShutterSpeedValue';   $9202: result :='ApertureValue';   $9203: result :='BrightnessValue';   $9204: result :='ExposureBiasValue';   $9205: result :='MaxApertureValue';   $9206: result :='SubjectDistance';   $9207: result :='MeteringMode';   $9208: result :='LightSource';   $9209: result :='Flash';   $920A: result :='FocalLength';   $920B: result :='FlashEnergy';   $920C: result :='SpatialFrequencyResponse';   $920D: result :='Noise';   $9211: result :='ImageNumber';   $9212: result :='SecurityClassification';   $9213: result :='ImageHistory';   $9214: result :='SubjectLocation';   $9215: result :='ExposureIndex';   $9216: result :='TIFF/EPStandardID';   $927C: result :='MakerNote';   $9286: result :='UserComment';   $9290: result :='SubSecTime';   $9291: result :='SubSecTimeOriginal';   $9292: result :='SubSecTimeDigitized';   $A000: result :='FlashPixVersion';   $A001: result :='ColorSpace';   $A002: result :='ExifImageWidth';   $A003: result :='ExifImageLength';   $A005: result :='InteroperabilityOffset';   $A20B: result :='FlashEnergy';   $A20C: result :='SpatialFrequencyResponse';   $A20E: result :='FocalPlaneXResolution';   $A20F: result :='FocalPlaneYResolution';   $A210: result :='FocalPlaneResolutionUnit';   $A214: result :='SubjectLocation';   $A215: result :='ExposureIndex';   $A217: result :='SensingMethod';   $A300: result :='FileSource';   $A301: result :='SceneType';  else    Result := 'Unknown Tag Type';  end;end;procedure TfrmJpegInfo.pReadIFD;var  wrdNumberOfEntries : Word; //number of directory entries  wrdTag             : Word; //tag number  wrdDataType        : Word; //type or kind of data in entry  dwdComponents      : DWord; //number of components in entry  dwdData            : DWord; //data or offset to data  wrdNextIFD         : Word; //offset to next IFD  intLoop            : integer; //loop control  intDataLoop        : integer; //loop control  intTotalDataLength : integer; //total length of directory entry value  strData            : string; //string directory entry  bytData            : byte; //byte directory entry  lngData            : longint; //long directory entry  i64HoldPos         : int64; //hold position within filebegin  //read number of entries  wrdNumberOfEntries := GetWord;  mmoJpegInfo.lines.Add('Number of Entries:' + IntToStr(wrdNumberOfEntries));  //read individual entries  for intLoop := 1 to wrdNumberOfEntries do  begin    //read tag number and interpret    wrdTag := GetWord;    strData := 'Tag: ' + GetTagName(wrdTag);    //read tag type (kind of data) and interpret    wrdDataType := GetWord;    case wrdDataType of      1 : strData := strData + ':(unsigned byte)'; //1 byte      2 : strData := strData + ':(ascii strings)'; //1 byte      3 : strData := strData + ':(unsigned short)'; //2 bytes      4 : strData := strData + ':(unsigned long)'; //4 bytes      5 : strData := strData + ':(unsigned rational)'; //8 bytes      6 : strData := strData + ':(signed byte)'; //1 byte      7 : strData := strData + ':(undefined)'; //1 byte      8 : strData := strData + ':(signed short)'; //2 bytes      9 : strData := strData + ':(signed long)'; //4 bytes      10 : strData := strData + ':(signed rational)'; //8 bytes      11 : strData := strData + ':(single float)'; //4 bytes      12 : strData := strData + ':(double float)'; //8 bytes    else      mmoJpegInfo.lines.Add('Unknown Data Type');    end; {case wrdDataType of}    mmoJpegInfo.lines.Add(strData);    //read number of components    dwdComponents := GetDWord;    //lstINFO.Items.Add('Number of Components:' + IntToStr(dwdComponents));    //read data value or offset to data value    {first check the total data length (bytes/component * # of components     gives the total data length - if > 4 bytes then dwdData is the offset     to the data, if < 4 bytes then dwdData is the value itself}    Case wrdDataType of      1 : intTotalDataLength := dwdComponents; //1 byte      2 : intTotalDataLength := dwdComponents; //1 byte      3 : intTotalDataLength := dwdComponents * 2; //2 bytes      4 : intTotalDataLength := dwdComponents * 4; //4 bytes      5 : intTotalDataLength := dwdComponents * 8; //8 bytes      6 : intTotalDataLength := dwdComponents; //1 byte      7 : intTotalDataLength := dwdComponents; //1 byte      8 : intTotalDataLength := dwdComponents * 2; //2 bytes      9 : intTotalDataLength := dwdComponents * 4; //4 bytes      10 : intTotalDataLength := dwdComponents * 8; //8 bytes      11 : intTotalDataLength := dwdComponents * 4; //4 bytes      12 : intTotalDataLength := dwdComponents * 8; //8 bytes    else      IntTotalDataLength := 0;    end;    //read the data value    dwdData := GetDWord;    //set the hold position    i64HoldPos := fsImage.Position;    //now set data or read offset    if intTotalDataLength > 4 then      begin //read offset value        //seek to offset value        fsImage.Seek(dwdData+i64RefPos,soFromBeginning);        //read specific data type (unsigned byte)        if wrdDataType = 1 then //unsigned byte          begin            bytData := GetByte;            mmoJpegInfo.lines.Add('Value=' + IntToStr(bytData));          end; {wrdDataType=1}        //read specific data type (string)        if wrdDataType = 2 then //ascii string          begin            strData := '';            for intDataLoop := 1 to dwdComponents do              strData := strData + chr(GetByte);            mmoJpegInfo.lines.Add('Value=' + strData);          end; {wrdDataType=2}        //read specific data type (unsigned short)        if wrdDataType = 3 then          begin            for intDataLoop := 1 to dwdComponents do              strData := strData + chr(GetByte);            mmoJpegInfo.lines.Add('Value=' + strData);          end; {wrdDataType=3}        //read specific data type (unsigned long)        if wrdDataType = 4 then          begin            lngData := GetDWord;            mmoJpegInfo.lines.Add('Value:=' + IntToStr(lngData));          end; {wrdDataType=4}        //read specific data type (unsigned rational)        if wrdDataType = 5 then          begin            strData := IntToStr(GetDWord) + '/' + IntToStr(GetDWord);            mmoJpegInfo.lines.Add('Value:=' + strData);          end; {wrdDataType=5}      end {intTotalDataLength > 4}    else      begin //read value intTotalDataLength < 4        mmoJpegInfo.lines.Add('Value=' + IntToStr(dwdData));      end; //read value intTotalDataLength < 4    //return to former data position    fsImage.Seek(i64HoldPos,soFromBeginning);  end; {for intLoop}  //finally, read the offset to the next IFD  wrdNextIFD := GetWord;end;procedure TfrmJpegInfo.ReadJpegInfo(const JpegFileName : string);var  wrdImage  : word; //word read from image file  dwdImage  : dword; //double word read from image file  bytImage  : byte; //byte read from image file  strImage  : string; //string read from image filebegin  {open the file}  fsImage := TFileStream.Create(JpegFileName,fmOpenRead);  {show file path on caption}  Caption := JpegFileName;  {look for start-of-image marker FF D8 as first two bytes}  if GetByte = $FF then  begin    if GetByte = $D8 then      mmoJpegInfo.lines.Add('Start-Of-Image Marker Found: Valid Image')    else    begin //exit if invalid image      mmoJpegInfo.lines.Add('Start-Of-Image Marker NOT Found: Invalid Image');      exit;    end; //check for soi marker  end;  {look for exif marker}  while bytImage <> $D9 do  //$D9=eof byte  begin    fsImage.Read(bytImage,1);  //read one byte    //if exif marker found (starts by $FFE1}    if bytImage = $FF then      if GetByte = $E1 then      begin        mmoJpegInfo.lines.Add('EXIF Marker Found');        //now read image information        {read exif data size}        wrdImage := GetWord;        mmoJpegInfo.lines.Add('Exif Data Size=' + Inttostr(wrdImage));        {read actual exif header}        strImage := GetString(4);        if strImage <> 'Exif' then          exit        else          mmoJpegInfo.lines.Add('Header: ' + strImage);        //read two null bytes after exif header        GetWord;        //set reference position for future offsets        i64RefPos := fsImage.Position;        //the next 8 bytes are the TIFF header        //2 bytes to determine byte order        //2 bytes (002A or 2A00)        //4 bytes offset to first image file directory        {now read byte order, II is intel (little endian),         MM is motorola (big endian)}        wrdImage := GetWord;        Case wrdImage of          $4949 : mmoJpegInfo.lines.Add('Encoding: Little Endian');          $4D4D : mmoJpegInfo.lines.Add('Encoding: Big Endian');        else          mmoJpegInfo.lines.Add('Unknown Encoding');        end;        {read the next two bytes - always $02AA or $2A00}        wrdImage := GetWord;        {read the end of the tiff header - 4 bytes         contain offset to first IFD}        dwdImage := GetDWord;        mmoJpegInfo.lines.Add('Offset to 1st IFD:' + IntToStr(dwdImage));        {seek to first IFD, subtract 8 bytes for         TIFF header}        fsImage.Seek(dwdImage-8,soFromCurrent);        {read the first image file directory}        pReadIFD;      end; //if exif marker found  end; {look for exif marker - while bytSOI <> $D9 do}  {close the file}  fsImage.Free;end; {read information from the jpeg file}procedure TfrmJpegInfo.btnOpenJpegClick(Sender: TObject);begin  mmoJpegInfo.Clear;  with TOpenDialog.Create(self) do  begin    Options := [ofHideReadOnly, ofFileMustExist];    Filter := '*.jpeg|*.jpg';    if Execute then    begin      ReadJpegInfo(FileName);    end;    free;  end;end;end.

表單檔案

object frmJpegInfo: TfrmJpegInfo  Left = 0  Top = 0  Caption = 'frmJpegInfo'  ClientHeight = 564  ClientWidth = 366  Color = clBtnFace  Font.Charset = DEFAULT_CHARSET  Font.Color = clWindowText  Font.Height = -12  Font.Name = 'Tahoma'  Font.Style = []  OldCreateOrder = False  PixelsPerInch = 106  TextHeight = 14  object btnOpenJpeg: TButton    Left = 16    Top = 16    Width = 75    Height = 25    Caption = #25171#24320'Jpeg'    TabOrder = 0    OnClick = btnOpenJpegClick  end  object mmoJpegInfo: TMemo    Left = 0    Top = 47    Width = 366    Height = 517    Align = alBottom    ScrollBars = ssVertical    TabOrder = 1  endend

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.