exiv2を使ってJPEGファイル内部のExif情報を除去

外部プログラムとして起動する試み

以前の記事(割と初期)でC++ Builder CEで使えるPopenを開発紹介しました。

これを使うことも可能ですが、純粋にCreateProcessを使う方法を取りました。Popenではcmd.exeを通すことによりcode pageの影響を受けることになり、日本語を含むフルパスで文字化けによるエラーがでることがわかったからです。いきなりバルクで試してもいいのですが、まずは単一ファイルでトライしてみましょう。動いているプログラムのソースコード等を紹介します。まずフォームから、

Drag and Dropに前述の仕組みを使う関係で珍しくFMXです。上図のように、TLabelを2個、TButtonを1個、TOpenDialogを1個使います。配置は適当でいいのですが、Label1は幅を長く取るのが吉です。続いて、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.StdCtrls.hpp>
#include <FMX.Types.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published:	// IDE で管理されるコンポーネント
	TOpenDialog *OpenDialog1;
	TButton *Go;
	TLabel *Label1;
	TLabel *Label2;
	void __fastcall GoClick(TObject *Sender);
private:	// ユーザー宣言
public:		// ユーザー宣言
	__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

さらにUnit1.cpp

//---------------------------------------------------------------------------

#include <fmx.h>
#pragma hdrstop
#include <windows.h>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.fmx"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}

bool CreateProcess(String cmdline)
{
        STARTUPINFOW si;
    PROCESS_INFORMATION pi;
    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    si.dwFlags = STARTF_USESHOWWINDOW;
	si.wShowWindow = SW_HIDE;
    // 実行ファイルと引数(1つの文字列にまとめる)
	//wchar_t cmdLine[] = L"notepad.exe C:\\Temp\\test.txt";

    if (CreateProcessW(
        NULL,       // 実行ファイル名(NULLなら cmdLine から取得)
		cmdline.w_str(),    // コマンドライン
        NULL,       // プロセスセキュリティ属性
        NULL,       // スレッドセキュリティ属性
        FALSE,      // ハンドル継承
        0,          // 作成フラグ
        NULL,       // 環境変数
        NULL,       // カレントディレクトリ
        &si,        // STARTUPINFO
        &pi         // PROCESS_INFORMATION
    )) {
        // プロセス終了を待つ場合
        //WaitForSingleObject(pi.hProcess, INFINITE);

        // ハンドルを閉じる
        CloseHandle(pi.hProcess);
		CloseHandle(pi.hThread);
		return true;
    } else {
		ShowMessage(L"CreateProcess に失敗しました。");
		return false;
    }

}

void ProcessFile(String fname)
{
	String comm = "c:\\program files\\python311\\exiv2.exe";
	comm += " -k -d e ";
	comm += "\"" + fname + "\"";

	Form1->Label1->Text = comm;

	if( CreateProcess(comm) )
		Form1->Label2->Text = "success";
	else
		Form1->Label2->Text = "failed";

}
//---------------------------------------------------------------------------
void __fastcall TForm1::GoClick(TObject *Sender)
{
	if( OpenDialog1->Execute())
		ProcessFile(OpenDialog1->FileName);

}
//---------------------------------------------------------------------------

Build and Runすると、

“Go”ボタンをクリックすると、

こんなファイル選択ダイアログが出ます。アイコン表示してるので画像を選択しやすいですね。で、IMG_0503.JPGを選ぶと、

となり、successですからExif情報が削除できているはずです。ファイルを選択して、プロパティーで確認すると、

ごっそり削除されています。これでおけですね。他にExifToolというのもあります。こちらはPerlで書かれたものだというので敬遠したんですが、C++から呼び出せるかも

というのでこちらの方が柔軟に使えるかもしれませんね。ま、これいじるくらいなら、自前でExifデータの中からGPS関連のデータだけ削除すればいいんですが、そのうち実現するかもしれません。webサイトならありますね。

Exiv2使ってExif情報まるごと削除すると予想外の副作用が出るんですけど、それは別記事で。

コメント