From 4cc89285082250d7a7d38fc78dbe9d7229192da3 Mon Sep 17 00:00:00 2001 From: wp_xxyyzz Date: Sat, 29 Dec 2018 13:15:37 +0000 Subject: [PATCH] fpexif: Fix crash when writing big-endian file with thumbnail (see https://forum.lazarus.freepascal.org/index.php/topic,43714). Add button for changing EXIF date/time to MetadataViewer. git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@6776 8e941d3f-bd1b-0410-a28a-d453659cc2b4 --- .../metadata_viewer/MetadataViewer.lpi | 9 +-- .../examples/metadata_viewer/mdvmain.lfm | 67 ++++++++++++++++-- .../examples/metadata_viewer/mdvmain.pas | 49 ++++++++++++- components/fpexif/fpeexifreadwrite.pas | 7 +- components/fpexif/fpetags.pas | 6 +- .../fpexif/tests/multiread/MultiRead_Laz.lpi | 9 +-- .../fpexif/tests/multiread/MultiRead_Laz.res | Bin 138696 -> 139092 bytes .../fpexif/tests/multiread/common/mrtmain.lfm | 2 +- .../fpexif/tests/multiread/common/mrtmain.pas | 1 + .../pictures/originals/images_origin.txt | 9 +++ .../tests/readwrite/ReadWriteTest_Laz.res | Bin 1422 -> 1820 bytes 11 files changed, 135 insertions(+), 24 deletions(-) create mode 100644 components/fpexif/tests/pictures/originals/images_origin.txt diff --git a/components/fpexif/examples/metadata_viewer/MetadataViewer.lpi b/components/fpexif/examples/metadata_viewer/MetadataViewer.lpi index ec6c2b461..a657bf228 100644 --- a/components/fpexif/examples/metadata_viewer/MetadataViewer.lpi +++ b/components/fpexif/examples/metadata_viewer/MetadataViewer.lpi @@ -1,7 +1,7 @@ - + @@ -18,9 +18,10 @@ - - - + + + + diff --git a/components/fpexif/examples/metadata_viewer/mdvmain.lfm b/components/fpexif/examples/metadata_viewer/mdvmain.lfm index 4860f3c71..ab20f8940 100644 --- a/components/fpexif/examples/metadata_viewer/mdvmain.lfm +++ b/components/fpexif/examples/metadata_viewer/mdvmain.lfm @@ -8,7 +8,7 @@ object MainForm: TMainForm ClientWidth = 926 OnCreate = FormCreate OnDestroy = FormDestroy - LCLVersion = '1.9.0.0' + LCLVersion = '2.1.0.0' object ShellPanel: TPanel Left = 0 Height = 691 @@ -112,7 +112,7 @@ object MainForm: TMainForm end object PageControl1: TPageControl Left = 0 - Height = 573 + Height = 539 Top = 23 Width = 647 ActivePage = PgMetadata @@ -122,11 +122,11 @@ object MainForm: TMainForm OnChange = PageControl1Change object PgMetadata: TTabSheet Caption = 'Meta data' - ClientHeight = 545 + ClientHeight = 511 ClientWidth = 639 object TagListView: TListView Left = 0 - Height = 525 + Height = 491 Top = 0 Width = 639 Align = alClient @@ -158,7 +158,7 @@ object MainForm: TMainForm object Panel1: TPanel Left = 0 Height = 20 - Top = 525 + Top = 491 Width = 639 Align = alBottom AutoSize = True @@ -201,7 +201,7 @@ object MainForm: TMainForm object Messages: TMemo Left = 4 Height = 90 - Top = 596 + Top = 567 Width = 639 Align = alBottom BorderSpacing.Left = 4 @@ -212,11 +212,64 @@ object MainForm: TMainForm Cursor = crVSplit Left = 0 Height = 5 - Top = 686 + Top = 562 Width = 647 Align = alBottom ResizeAnchor = akBottom end + object DateTimePanel: TPanel + Left = 0 + Height = 34 + Top = 657 + Width = 647 + Align = alBottom + AutoSize = True + BevelOuter = bvNone + ClientHeight = 34 + ClientWidth = 647 + TabOrder = 4 + object LblChangeDate: TLabel + AnchorSideLeft.Control = DateTimePanel + AnchorSideTop.Control = EdChangeDate + AnchorSideTop.Side = asrCenter + Left = 4 + Height = 15 + Top = 10 + Width = 135 + BorderSpacing.Left = 4 + Caption = 'Change EXIF date/time to' + ParentColor = False + end + object EdChangeDate: TEdit + AnchorSideLeft.Control = LblChangeDate + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = DateTimePanel + AnchorSideTop.Side = asrCenter + Left = 144 + Height = 23 + Top = 6 + Width = 152 + BorderSpacing.Left = 5 + BorderSpacing.Bottom = 4 + TabOrder = 0 + end + object BtnChangeDate: TButton + AnchorSideLeft.Control = EdChangeDate + AnchorSideLeft.Side = asrBottom + AnchorSideTop.Control = EdChangeDate + AnchorSideTop.Side = asrCenter + Left = 304 + Height = 25 + Top = 5 + Width = 66 + AutoSize = True + BorderSpacing.Left = 8 + BorderSpacing.Bottom = 4 + Caption = 'Execute' + OnClick = BtnChangeDateClick + TabOrder = 1 + end + end end object StatusBar1: TStatusBar Left = 0 diff --git a/components/fpexif/examples/metadata_viewer/mdvmain.pas b/components/fpexif/examples/metadata_viewer/mdvmain.pas index 3c8d6dd9e..6fad1ce0b 100644 --- a/components/fpexif/examples/metadata_viewer/mdvmain.pas +++ b/components/fpexif/examples/metadata_viewer/mdvmain.pas @@ -14,14 +14,18 @@ type { TMainForm } TMainForm = class(TForm) + BtnChangeDate: TButton; CbDecodeMakerNotes: TCheckBox; + EdChangeDate: TEdit; FilenameInfo: TLabel; Image: TImage; + LblChangeDate: TLabel; Messages: TMemo; PageControl1: TPageControl; Panel1: TPanel; Panel2: TPanel; Panel3: TPanel; + DateTimePanel: TPanel; PreviewImage: TImage; ImageList: TImageList; Splitter3: TSplitter; @@ -34,6 +38,7 @@ type ShellTreeView: TShellTreeView; Splitter1: TSplitter; Splitter2: TSplitter; + procedure BtnChangeDateClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure PageControl1Change(Sender: TObject); @@ -66,7 +71,7 @@ implementation {$R *.lfm} uses - IniFiles, Math, StrUtils, + IniFiles, Math, StrUtils, DateUtils, fpeGlobal, fpeTags, fpeExifData, fpeIptcData; @@ -88,6 +93,37 @@ begin //ShellListView.Parent.DoubleBuffered := true; end; +procedure TMainForm.BtnChangeDateClick(Sender: TObject); +var + lTag: TTag; + dt: TDateTime; + fn: String; +begin + if (FImgInfo = nil) or (FImgInfo.ExifData = nil) then + exit; + + if not TryStrToDateTime(EdChangeDate.Text, dt) then begin + MessageDlg('No valid date/time. Use your locale settings.', mtError, [mbOK], 0); + exit; + end; + + lTag := FImgInfo.ExifData.TagByName['DateTimeOriginal']; + if lTag <> nil then + TDateTimeTag(lTag).AsDateTime := dt; + + lTag := FImgInfo.ExifData.TagByName['DateTimeDigitized']; + if lTag <> nil then + TDateTimeTag(lTag).AsDateTime := dt; + + lTag := FImgInfo.ExifData.TagByName['DateTime']; + if lTag <> nil then + TDateTimeTag(lTag).AsDateTime := dt; + + fn := FImgInfo.FileName; + fn := ChangeFileExt(fn, '') + '_modified' + ExtractFileExt(fn); + FImgInfo.SaveToFile(fn); +end; + procedure TMainForm.FormDestroy(Sender: TObject); begin try @@ -136,7 +172,16 @@ begin item.SubItems.Add(lTag.Description); item.SubItems.Add(lTag.AsString); end; - end; + + lTag := FImgInfo.ExifData.TagByName['DateTimeOriginal']; + if lTag <> nil then + EdChangeDate.Text := DateTimeToStr(TDateTimeTag(lTag).AsDateTime) + else + EdChangeDate.Text := ''; + DateTimePanel.Show; + end else + DateTimePanel.Hide; + if FImgInfo.HasIptc then begin for i := 0 to FImgInfo.IptcData.TagCount-1 do begin lTag := FImgInfo.IptcData.TagByIndex[i]; diff --git a/components/fpexif/fpeexifreadwrite.pas b/components/fpexif/fpeexifreadwrite.pas index a476fc03a..f6f916e02 100644 --- a/components/fpexif/fpeexifreadwrite.pas +++ b/components/fpexif/fpeexifreadwrite.pas @@ -853,10 +853,9 @@ begin Continue; // Offset to the thumbnail image - if tag.TagID = FULLTAG_THUMBSTARTOFFSET then begin - dw := FixEndian32(thumbStartOffset); - tag.AsInteger := dw; - end else + if tag.TagID = FULLTAG_THUMBSTARTOFFSET then + tag.AsInteger := DWord(thumbStartOffset) + else // Some tags will link to subdirectories. The offset to the start of // a subdirectory must be specified in the DataValue field of the // written ifd record. Since it is not clear at this moment where the diff --git a/components/fpexif/fpetags.pas b/components/fpexif/fpetags.pas index 1dd33f9f5..98b374678 100644 --- a/components/fpexif/fpetags.pas +++ b/components/fpexif/fpetags.pas @@ -1059,7 +1059,8 @@ begin else raise EFpExif.CreateFmt('Value %d out of range for tag "%s"', [AValue, FName]); ttUInt16: - if not WithRangeCheck or ((AValue >= 0) and (AValue <= 65535)) then begin + if not WithRangeCheck or ((AValue >= 0) and (AValue <= 65535)) then + begin if BigEndian then w := NtoBE(PWord(@AValue)^) else @@ -1069,7 +1070,8 @@ begin raise EFpExif.CreateFmt('Value %d out of range for tag "%s"', [AValue, FName]); ttUInt32, ttIFD: - if not WithRangeCheck or (AValue >= 0) then begin + if not WithRangeCheck or (AValue >= 0) then + begin if BigEndian then dw := NtoBE(PDWord(@AValue)^) else diff --git a/components/fpexif/tests/multiread/MultiRead_Laz.lpi b/components/fpexif/tests/multiread/MultiRead_Laz.lpi index ee0d89d17..290d0eb4f 100644 --- a/components/fpexif/tests/multiread/MultiRead_Laz.lpi +++ b/components/fpexif/tests/multiread/MultiRead_Laz.lpi @@ -1,7 +1,7 @@ - + @@ -18,9 +18,10 @@ - - - + + + + diff --git a/components/fpexif/tests/multiread/MultiRead_Laz.res b/components/fpexif/tests/multiread/MultiRead_Laz.res index e994dfa65a96d79259e5ee4940a4dbaf7a725d38..4133fe048bfc96eac220bd2dbc2c6057417f565b 100644 GIT binary patch delta 429 zcmX@Ho8!tpjtL4(ci1K>{bzS9DDX?nO`WX4XtOz!QHn)g!6vadx6Ifov7jI)GdZy& zGe1wEA~z?m*a|E@Igwdr@;oNqdWfp>%)FHR^5Wpsl9J54^kRrgTcwPWk^(Dz{o>?| z)ZD~kz1+;?qWt3gv=Y7K{9OHDUr&7_0|Qh2a8%7ocD!5)3JNwU1(}ZJiAAY)ZizX? zsW$p>K1kX|A7XJmn$2LnP^Y6wk>DspGaQbBxGX0>FFhc!Bm?NY2%!7YAnrpF1qvcN m63rnXIhgyAf)^+Z5-m>6P0FdXYo5T`K7o~S`vg`d3kd*tu#x