unit umain; {$WARN UNIT_PLATFORM OFF} interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids, ieview, ImageEnView, FileCtrl, StdCtrls, ImageEnIO, ComCtrls, ExtCtrls, hyieutils, hyiedefs, math, iexBitmaps, iesettings, iexLayers, iexRulers; type TMainForm = class(TForm) StringGrid1: TStringGrid; Panel2: TPanel; ImageEnView1: TImageEnView; ProgressBar1: TProgressBar; DriveComboBox1: TDriveComboBox; DirectoryListBox1: TDirectoryListBox; FileListBox1: TFileListBox; btnSaveChanges: TButton; OpenDialog1: TOpenDialog; SaveDialog1: TSaveDialog; btnViewMakerNote: TButton; lblMethod: TLabel; cmbMethod: TComboBox; procedure FormCreate(Sender: TObject); procedure FileListBox1Change(Sender: TObject); procedure ImageEnView1Progress(Sender: TObject; per: Integer); procedure btnSaveChangesClick(Sender: TObject); procedure btnViewMakerNoteClick(Sender: TObject); procedure cmbMethodChange(Sender: TObject); private { Private declarations } procedure UpdateDisplay; // Use standard TImageEnIO.Params properties procedure ReadParameters_Method1; procedure WriteParameters_Method1; // Use helper methods in iexMetaHelpers procedure ReadParameters_Method2; procedure WriteParameters_Method2; public { Public declarations } end; var MainForm: TMainForm; implementation uses umakernote, iexMetaHelpers; {$R *.DFM} {$R WindowsTheme.res} const // Items of cmbMethod _ieStandardImageEnProperties = 0; _ieHelperMethods = 1; procedure DecimalToFract(value: double; AllowedDecimals: integer; var num, den: integer); var d, i: integer; ex: boolean; begin d := trunc(Power(10, AllowedDecimals)); num := trunc(value * d); den := d; repeat ex := true; for i := 10 downto 2 do if ((num mod i) = 0) and ((den mod i) = 0) then begin num := num div i; den := den div i; ex := false; end; until ex; end; function DecimalToFractStr(value: double): string; var num, den: integer; begin DecimalToFract(value, 6, num, den); result := inttostr(num) + '/' + inttostr(den); end; procedure TMainForm.FormCreate(Sender: TObject); begin IEAutoLoadIOPlugins; FileListBox1.Mask := EXIF_COMPATIBLE_EXTENSIONS; cmbMethod.ItemIndex := _ieStandardImageEnProperties; end; procedure TMainForm.FileListBox1Change(Sender: TObject); begin UpdateDisplay; end; // File selection has changed. Load EXIF data procedure TMainForm.UpdateDisplay; begin if IsKnownFormat(FileListBox1.FileName) then begin // load only parameters ImageEnView1.IO.ParamsFromFile(FileListBox1.FileName); if assigned(ImageEnView1.IO.Params.EXIF_Bitmap) and not ImageEnView1.IO.Params.EXIF_Bitmap.IsEmpty then begin // there is a thumbnail, display it ImageEnView1.IEBitmap.Assign( ImageEnView1.IO.Params.EXIF_Bitmap ); ImageEnView1.Update; end else begin // we need only a thumbnail (fast load) ImageEnView1.IO.Params.GetThumbnail:=true; ImageEnView1.io.LoadFromFile(FileListBox1.FileName); end; ProgressBar1.Position := 0; case cmbMethod.ItemIndex of _ieStandardImageEnProperties : ReadParameters_Method1; _ieHelperMethods : ReadParameters_Method2; end; end else begin ImageEnView1.Blank; StringGrid1.ClearGridFields; end; end; // Loading progress procedure TMainForm.ImageEnView1Progress(Sender: TObject; per: Integer); begin ProgressBar1.Position := per; end; // Save changes procedure TMainForm.btnSaveChangesClick(Sender: TObject); begin case cmbMethod.ItemIndex of _ieStandardImageEnProperties : WriteParameters_Method1; _ieHelperMethods : WriteParameters_Method2; end; // Save to file case ImageEnView1.IO.Params.FileType of ioJPEG : ImageEnView1.IO.InjectJpegEXIF(FileListBox1.FileName); ioTIFF : ImageEnView1.IO.InjectTIFFEXIF(FileListBox1.FileName); end; ProgressBar1.Position := 0; end; procedure TMainForm.ReadParameters_Method1; const EXIF_Prop_Count = 62; var I: Integer; begin // initialize properties grid StringGrid1.RowCount := StringGrid1.FixedRows + EXIF_Prop_Count; StringGrid1.Cells[0, 0] := 'Property'; StringGrid1.Cells[1, 0] := 'Value'; with ImageEnView1.IO.Params do begin StringGrid1.Cells[0, 1] := 'Image Description'; StringGrid1.Cells[1, 1] := EXIF_ImageDescription; StringGrid1.Cells[0, 2] := 'Make'; StringGrid1.Cells[1, 2] := EXIF_Make; StringGrid1.Cells[0, 3] := 'Model'; StringGrid1.Cells[1, 3] := EXIF_Model; StringGrid1.Cells[0, 4] := 'Orientation'; StringGrid1.Cells[1, 4] := IntToStr(EXIF_Orientation); StringGrid1.Cells[0, 5] := 'X Resolution'; StringGrid1.Cells[1, 5] := floattostr(EXIF_XResolution); StringGrid1.Cells[0, 6] := 'Y Resolution'; StringGrid1.Cells[1, 6] := FloatToStr(EXIF_YResolution); StringGrid1.Cells[0, 7] := 'Software'; StringGrid1.Cells[1, 7] := EXIF_Software; StringGrid1.Cells[0, 8] := 'Date/Time'; StringGrid1.Cells[1, 8] := EXIF_DateTime; StringGrid1.Cells[0, 9] := 'Copyright'; StringGrid1.Cells[1, 9] := EXIF_Copyright; StringGrid1.Cells[0, 10] := 'Exposure Time'; StringGrid1.Cells[1, 10] := DecimalToFractStr(EXIF_ExposureTime) + ' sec'; StringGrid1.Cells[0, 11] := 'F-Number'; StringGrid1.Cells[1, 11] := FloatToStr(EXIF_FNumber); StringGrid1.Cells[0, 12] := 'Exposure Program'; StringGrid1.Cells[1, 12] := IntToStr(EXIF_ExposureProgram); StringGrid1.Cells[0, 13] := 'Exif Version'; StringGrid1.Cells[1, 13] := EXIF_ExifVersion; StringGrid1.Cells[0, 14] := 'Date/Time Original'; StringGrid1.Cells[1, 14] := EXIF_DateTimeOriginal; StringGrid1.Cells[0, 15] := 'Date/Time Digitized'; StringGrid1.Cells[1, 15] := EXIF_DateTimeDigitized; StringGrid1.Cells[0, 16] := 'Compressed Bits Per Pixel'; StringGrid1.Cells[1, 16] := FloatToStr(EXIF_CompressedBitsPerPixel); StringGrid1.Cells[0, 17] := 'Shutter Speed Value'; StringGrid1.Cells[1, 17] := FloatToStr(EXIF_ShutterSpeedValue); StringGrid1.Cells[0, 18] := 'Aperture Value'; StringGrid1.Cells[1, 18] := FloatToStr(EXIF_ApertureValue); StringGrid1.Cells[0, 19] := 'Brightness Value'; StringGrid1.Cells[1, 19] := FloatToStr(EXIF_BrightnessValue); StringGrid1.Cells[0, 20] := 'Exposure Bias Value'; StringGrid1.Cells[1, 20] := FloatToStr(EXIF_ExposureBiasValue); StringGrid1.Cells[0, 21] := 'Max Aperture Value'; StringGrid1.Cells[1, 21] := FloatToStr(EXIF_MaxApertureValue); StringGrid1.Cells[0, 22] := 'Subject Distance'; StringGrid1.Cells[1, 22] := FloatToStr(EXIF_SubjectDistance); StringGrid1.Cells[0, 23] := 'Metering Mode'; StringGrid1.Cells[1, 23] := IntToStr(EXIF_MeteringMode); StringGrid1.Cells[0, 24] := 'Light Source'; StringGrid1.Cells[1, 24] := IntToStr(EXIF_LightSource); StringGrid1.Cells[0, 25] := 'Flash'; StringGrid1.Cells[1, 25] := IntToStr(EXIF_Flash); StringGrid1.Cells[0, 26] := 'Focal Length'; StringGrid1.Cells[1, 26] := FloatToStr(EXIF_FocalLength); StringGrid1.Cells[0, 27] := 'Subsec Time'; StringGrid1.Cells[1, 27] := EXIF_SubsecTime; StringGrid1.Cells[0, 28] := 'Subsec Time Original'; StringGrid1.Cells[1, 28] := EXIF_SubsecTimeOriginal; StringGrid1.Cells[0, 29] := 'Subsec Time Digitized'; StringGrid1.Cells[1, 29] := EXIF_SubsecTimeDigitized; StringGrid1.Cells[0, 30] := 'FlashPix Version'; StringGrid1.Cells[1, 30] := EXIF_FlashPixVersion; StringGrid1.Cells[0, 31] := 'Color Space'; StringGrid1.Cells[1, 31] := IntToStr(EXIF_ColorSpace); StringGrid1.Cells[0, 32] := 'Exif Image Width'; StringGrid1.Cells[1, 32] := IntToStr(EXIF_ExifImageWidth); StringGrid1.Cells[0, 33] := 'Exif Image Height'; StringGrid1.Cells[1, 33] := IntToStr(EXIF_ExifImageHeight); StringGrid1.Cells[0, 34] := 'Related Sound File'; StringGrid1.Cells[1, 34] := EXIF_RelatedSoundFile; StringGrid1.Cells[0, 35] := 'FocalPlane X Resolution'; StringGrid1.Cells[1, 35] := FloatToStr(EXIF_FocalPlaneXResolution); StringGrid1.Cells[0, 36] := 'FocalPlane Y Resolution'; StringGrid1.Cells[1, 36] := FloatToStr(EXIF_FocalPlaneYResolution); StringGrid1.Cells[0, 37] := 'FocalPlane Resolution Unit'; StringGrid1.Cells[1, 37] := IntToStr(EXIF_FocalPlaneResolutionUnit); StringGrid1.Cells[0, 38] := 'Exposure Index'; StringGrid1.Cells[1, 38] := FloatToStr(EXIF_ExposureIndex); StringGrid1.Cells[0, 39] := 'Sensing Method'; StringGrid1.Cells[1, 39] := IntToStr(EXIF_SensingMethod); StringGrid1.Cells[0, 40] := 'File Source'; StringGrid1.Cells[1, 40] := IntToStr(EXIF_FileSource); StringGrid1.Cells[0, 41] := 'Scene Type'; StringGrid1.Cells[1, 41] := IntToStr(EXIF_SceneType); StringGrid1.Cells[0, 42] := 'User Comment'; StringGrid1.Cells[1, 42] := EXIF_UserComment; StringGrid1.Cells[0, 43] := 'Camera Owner Name'; StringGrid1.Cells[1, 43] := EXIF_CameraOwnerName; StringGrid1.Cells[0, 44] := 'Body Serial Number'; StringGrid1.Cells[1, 44] := EXIF_BodySerialNumber; StringGrid1.Cells[0, 45] := 'Lens Make'; StringGrid1.Cells[1, 45] := EXIF_LensMake; StringGrid1.Cells[0, 46] := 'Lens Model'; StringGrid1.Cells[1, 46] := EXIF_LensModel; StringGrid1.Cells[0, 47] := 'Lens Serial Number'; StringGrid1.Cells[1, 47] := EXIF_LensSerialNumber; StringGrid1.Cells[0, 48] := 'Gamma'; StringGrid1.Cells[1, 48] := FloatToStr( EXIF_Gamma ); StringGrid1.Cells[0, 49] := 'Subject Area'; StringGrid1.Cells[1, 49] := IntToStr( EXIF_SubjectArea[ 0 ]); for I := 1 to 3 do StringGrid1.Cells[1, 49] := StringGrid1.Cells[1, 49] + ', ' + IntToStr( EXIF_SubjectArea[ I ]); StringGrid1.Cells[0, 50] := 'Subject Location X'; StringGrid1.Cells[1, 50] := IntToStr( EXIF_SubjectLocationX ); StringGrid1.Cells[0, 51] := 'Subject Location Y'; StringGrid1.Cells[1, 51] := IntToStr( EXIF_SubjectLocationY ); StringGrid1.Cells[0, 52] := 'XP Title'; StringGrid1.Cells[1, 52] := WideCharToString(PWideChar(EXIF_XPTitle)); StringGrid1.Cells[0, 53] := 'XP Comment'; StringGrid1.Cells[1, 53] := WideCharToString(PWideChar(EXIF_XPComment)); StringGrid1.Cells[0, 54] := 'XP Author'; StringGrid1.Cells[1, 54] := WideCharToString(PWideChar(EXIF_XPAuthor)); StringGrid1.Cells[0, 55] := 'XP Keywords'; StringGrid1.Cells[1, 55] := WideCharToString(PWideChar(EXIF_XPKeywords)); StringGrid1.Cells[0, 56] := 'XP Subject'; StringGrid1.Cells[1, 56] := WideCharToString(PWideChar(EXIF_XPSubject)); StringGrid1.Cells[0, 57] := 'GPS Version ID'; StringGrid1.Cells[1, 57] := EXIF_GPSVersionID; StringGrid1.Cells[0, 58] := 'GPS Datestamp'; StringGrid1.Cells[1, 58] := EXIF_GPSDateStamp; StringGrid1.Cells[0, 59] := 'GPS Altitude'; StringGrid1.Cells[1, 59] := FloatToStr(EXIF_GPSAltitude); StringGrid1.Cells[0, 60] := 'GPS Latitude'; StringGrid1.Cells[1, 60] := Format('%f° %f'' %f'''' %s', [EXIF_GPSLatitudeDegrees, EXIF_GPSLatitudeMinutes, EXIF_GPSLatitudeSeconds, EXIF_GPSLatitudeRef]); StringGrid1.Cells[0, 61] := 'GPS Longitude'; StringGrid1.Cells[1, 61] := Format('%f° %f'' %f'''' %s', [EXIF_GPSLongitudeDegrees, EXIF_GPSLongitudeMinutes, EXIF_GPSLongitudeSeconds, EXIF_GPSLongitudeRef]); // if there is no exif data then clear invalid values if EXIF_HasEXIFData = False then for I := 1 to StringGrid1.RowCount - 1 do StringGrid1.Cells[1, I] := ''; end; end; // Only partially implemented... procedure TMainForm.WriteParameters_Method1; begin with ImageEnView1.IO.Params do begin // Set flag that file contains EXIF information EXIF_HasEXIFData := True; EXIF_ImageDescription := StringGrid1.Cells[1, 1]; EXIF_Make := StringGrid1.Cells[1, 2]; EXIF_Model := StringGrid1.Cells[1, 3]; EXIF_Orientation := StrToIntDef(StringGrid1.Cells[1, 4], 0); EXIF_XResolution := StrToIntDef(StringGrid1.Cells[1, 5], 0); EXIF_YResolution := StrToIntDef(StringGrid1.Cells[1, 6], 0); EXIF_Software := StringGrid1.Cells[1, 7]; EXIF_DateTime := StringGrid1.Cells[1, 8]; EXIF_Copyright := StringGrid1.Cells[1, 9]; // StringGrid1.Cells[1,10] := DecimalToFractStr(EXIF_ExposureTime)+' sec'; EXIF_FNumber := StrToFloat(StringGrid1.Cells[1, 11]); EXIF_ExposureProgram := StrToIntDef(StringGrid1.Cells[1, 12], 0); EXIF_ExifVersion := StringGrid1.Cells[1, 13]; EXIF_DateTimeOriginal := StringGrid1.Cells[1, 14]; EXIF_DateTimeDigitized := StringGrid1.Cells[1, 15]; // StringGrid1.Cells[1,16] := FloatToStr(EXIF_CompressedBitsPerPixel); // StringGrid1.Cells[1,17] := FloatToStr(EXIF_ShutterSpeedValue); // StringGrid1.Cells[1,18] := FloatToStr(EXIF_ApertureValue); // StringGrid1.Cells[1,19] := FloatToStr(EXIF_BrightnessValue); // StringGrid1.Cells[1,20] := FloatToStr(EXIF_ExposureBiasValue); // StringGrid1.Cells[1,21] := FloatToStr(EXIF_MaxApertureValue); // StringGrid1.Cells[1,22] := FloatToStr(EXIF_SubjectDistance); // StringGrid1.Cells[1,23] := IntToStr(EXIF_MeteringMode); // StringGrid1.Cells[1,24] := IntToStr(EXIF_LightSource); // StringGrid1.Cells[1,25] := IntToStr(EXIF_Flash); // StringGrid1.Cells[1,26] := FloatToStr(EXIF_FocalLength); // StringGrid1.Cells[1,27] := EXIF_SubsecTime; // StringGrid1.Cells[1,28] := EXIF_SubsecTimeOriginal; // StringGrid1.Cells[1,29] := EXIF_SubsecTimeDigitized; // StringGrid1.Cells[1,30] := EXIF_FlashPixVersion; // StringGrid1.Cells[1,31] := IntToStr(EXIF_ColorSpace); EXIF_ExifImageWidth := StrToIntDef(StringGrid1.Cells[1, 32], 0); EXIF_ExifImageHeight := StrToIntDef(StringGrid1.Cells[1, 33], 0); EXIF_RelatedSoundFile := StringGrid1.Cells[1, 34]; // StringGrid1.Cells[1,35] := FloatToStr(EXIF_FocalPlaneXResolution); // StringGrid1.Cells[1,36] := FloatToStr(EXIF_FocalPlaneYResolution); // StringGrid1.Cells[1,37] := IntToStr(EXIF_FocalPlaneResolutionUnit); // StringGrid1.Cells[1,38] := FloatToStr(EXIF_ExposureIndex); // StringGrid1.Cells[1,39] := IntToStr(EXIF_SensingMethod); // StringGrid1.Cells[1,40] := IntToStr(EXIF_FileSource); // StringGrid1.Cells[1,41] := IntToStr(EXIF_SceneType); EXIF_CameraOwnerName := StringGrid1.Cells[1, 43]; EXIF_BodySerialNumber := StringGrid1.Cells[1, 44]; EXIF_LensMake := StringGrid1.Cells[1, 45]; EXIF_LensModel := StringGrid1.Cells[1, 46]; EXIF_LensSerialNumber := StringGrid1.Cells[1, 47]; // EXIF_Gamma := FloatToStr( StringGrid1.Cells[1, 48] ); // EXIF_SubjectArea := StringGrid1.Cells[0, 49]; EXIF_SubjectLocationX := StrToIntDef( StringGrid1.Cells[1, 50], -1 ); EXIF_SubjectLocationY := StrToIntDef( StringGrid1.Cells[1, 51], -1 ); EXIF_XPTitle := StringGrid1.Cells[1, 52]; EXIF_XPComment := StringGrid1.Cells[1, 53]; EXIF_XPAuthor := StringGrid1.Cells[1, 54]; EXIF_XPKeywords := StringGrid1.Cells[1, 55]; EXIF_XPSubject := StringGrid1.Cells[1, 56]; end; end; procedure TMainForm.ReadParameters_Method2; begin StringGrid1.ReadGridFromEXIF(ImageEnView1.IO.Params); end; procedure TMainForm.WriteParameters_Method2; begin StringGrid1.WriteGridToEXIF(ImageEnView1.IO.Params); end; // Read maker notes procedure TMainForm.btnViewMakerNoteClick(Sender: TObject); begin fMakerNote.ShowModal; end; procedure TMainForm.cmbMethodChange(Sender: TObject); begin UpdateDisplay; end; end.