ようやく最終型(の一つ前)を提示します。
まずは単一ファイルをOpenDialogで選択して処理するプログラム。フォームから、

このようにTButtonx1,TLabelx1,TCheckboxx3,TOpenDialogを配置。適宜Nameを変更して、Unit1.hは、
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <FMX.Controls.hpp>
#include <FMX.Forms.hpp>
#include <FMX.Controls.Presentation.hpp>
#include <FMX.Dialogs.hpp>
#include <FMX.Memo.hpp>
#include <FMX.Memo.Types.hpp>
#include <FMX.ScrollBox.hpp>
#include <FMX.StdCtrls.hpp>
#include <FMX.Types.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TOpenDialog *OpenDialog1;
TButton *Open;
TMemo *Memo1;
TLabel *Label1;
TCheckBox *NoDumpTables;
TCheckBox *FixDateTime;
TCheckBox *SnifGPSInfo;
void __fastcall OpenClick(TObject *Sender);
private: // ユーザー宣言
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif続いて、Unit1.cppは、
//---------------------------------------------------------------------------
#include <fmx.h>
#pragma hdrstop
#include "exif.h"
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.fmx"
extern AnsiString getdatetime(void *array);
AnsiString datetime;
void PRINTF(char **ms, const char *fmt, ...) {
AnsiString output;
char buf[4096];
char *p = NULL;
int len, cnt;
va_list args;
va_start(args, fmt);
cnt = vsnprintf(buf, sizeof(buf)-1, fmt, args);
if (!ms) {
output.sprintf("%s\n", buf);
//Form1->Memo1->Lines->Add(output);
if( !(Form1->NoDumpTables->IsChecked) ){
Form1->Memo1->Lines->Text += output;
Form1->Memo1->Lines->Text += L"\n";
}
return;
}
else if (*ms) {
len = (int)(strlen(*ms) + cnt + 1);
p = (char*)malloc(len);
strcpy(p, *ms);
strcat(p, buf);
free(*ms);
} else {
len = cnt + 1;
p = (char*)malloc(len);
strcpy(p, buf);
}
*ms = p;
va_end(args);
}
int sample_removeGPSData(const char *srcJpgFileName,const char *outJpgFileName)
{
int sts, result;
void **ifdTableArray = createIfdTableArray(srcJpgFileName, &result);
if (!ifdTableArray) {
printf("createIfdTableArray: ret=%d\n", result);
return result;
}
// remove GPS IFD and 1st IFD if exist
removeIfdTableFromIfdTableArray(ifdTableArray, IFD_GPS);
removeIfdTableFromIfdTableArray(ifdTableArray, IFD_1ST);
sts = updateExifSegmentInJPEGFile(srcJpgFileName, outJpgFileName, ifdTableArray);
if (sts < 0) {
printf("updateExifSegmentInJPEGFile: ret=%d\n", sts);
}
freeIfdTableArray(ifdTableArray);
return sts;
}
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
bool SetFileCreationTime(String filePath, TDateTime dt) {
// Convert SYSTEMTIME to FILETIME
SYSTEMTIME newTime;
DateTimeToSystemTime(dt,newTime);
FILETIME ft;
if (!SystemTimeToFileTime(&newTime, &ft)) {
return false;
}
// Open file with write attributes permission
HANDLE hFile = CreateFileW(
filePath.w_str(),
FILE_WRITE_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hFile == INVALID_HANDLE_VALUE) {
return false;
}
// Set creation time (leave last access and write times unchanged)
BOOL result = SetFileTime(hFile, &ft, NULL, NULL);
CloseHandle(hFile);
return (result != 0);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OpenClick(TObject *Sender)
{
String prefix = "nogps_";
String fullpath;
String filename;
String filepath;
String newname;
if( OpenDialog1->Execute()){
fullpath = OpenDialog1->FileName;
//Memo1->Lines->Add("fullpath " + fullpath);
void **ifdArray;
TagNodeInfo *tag;
int i, result;
ifdArray = createIfdTableArray(AnsiString(fullpath).c_str(),&result);
for( i = 0 ; ifdArray[i] != NULL ; i++ ){
dumpIfdTable(ifdArray[i]);
}
//mpIfdTable(ifdArray[0]);
if( FixDateTime->IsChecked ){
//Form1->Memo1->Lines->Add("datetime is " + datetime);
TDateTime dt;
TFormatSettings fs;
fs = TFormatSettings::Create(); // Initialize with defaults
//fs.DateSeparator = ':';
fs.ShortDateFormat = "yyyy:mm:dd";
dt = StrToDateTime(datetime,fs);
if( !SetFileCreationTime(fullpath, dt) )
ShowMessage("file creation date set failed");
}
if( SnifGPSInfo->IsChecked ){
filename = ExtractFileName(fullpath);
//Memo1->Lines->Add("Extracted filename " + filename);
filepath = ExtractFilePath(fullpath);
//Memo1->Lines->Add("Extracted filepath " + filepath);
newname = filepath + prefix + filename;
//Memo1->Lines->Add("newname is " + newname);
// AnsiString(fname).c_str()
sample_removeGPSData(AnsiString(fullpath).c_str(), AnsiString(newname).c_str());
if( FixDateTime->IsChecked ){// should again set file creation time for output
//Form1->Memo1->Lines->Add("datetime is " + datetime);
TDateTime dt;
TFormatSettings fs;
fs = TFormatSettings::Create(); // Initialize with defaults
//fs.DateSeparator = ':';
fs.ShortDateFormat = "yyyy:mm:dd";
dt = StrToDateTime(datetime,fs);
if( !SetFileCreationTime(newname, dt) )
ShowMessage("file creation date set failed");
}
//Memo1->Lines->Add("datetime " + datetime);
}
}
}
//---------------------------------------------------------------------------起動すると、

となるので、作成日時をExif内部の撮影日時にセットするならば、FixDateTimeにチェック(デフォルト)、Exif内部のGPS情報を切るのであれば、SnifGPSInfoにチェック(これまたデフォルト)、Exifテーブルを表示しないのであれば、NoDumpTablesにチェック(デフォルト)で“Open”します。ファイルを選択すると、ファイル処理して、Exif情報をいじる場合は、
IMG_3197.JPEG
がオリジナルのファイル名だとすると、頭にprefix=nogps_を付けた新しいファイルを書き出します。
nogps_IMG_3197.JPEG
つまりこんな感じで、

これを以前に紹介したexif-check.orgへ投げると、

GPS情報が削除されているのがわかります。exiv2を別プロセスで起動して対処する以前のやり方よりexiv2のパスの指定とかのトラブルが少ないだけ具合はよろしいですね。Drag and Drop(ファイルと一階層のフォルダーを含む)対応は別記事で、


コメント