fc2ブログ

EXIF の評価と大量の写真の保存について

*この記事はEXIFをWindowsのコマンドラインで書き換えるという内容と写真の保存方法について述べています。

カメラで撮影すると写真が出来上がるのは当たり前だが、最近ではフィルムカメラというものはほぼ絶滅しており、
写真といえば、デジタルデータの場合が殆どとなっている。
このデジタルデータには、色の情報以外にも、撮影に関する情報が色々と入っており、
どのような状況で撮影されたのか、後から判るようになっている。
この情報には何タイプか種類があるが、その中に、EXIF(JEITA(電子情報技術産業協会)によるEXIFの定義)というものがある。

このEXIFデータには、色々な情報が入っている。
例えば、撮影したときの焦点距離とか光の情報(絞り、シャッタースピード)とか、諸々である。
これらは、カメラのほうで撮影したときに、画像データにカメラが埋め込んでくれる。
というか勝手に埋め込んでくれる。
たとえば携帯電話(スマートフォン)のカメラだとGPSを搭載していることもあって、
どの場所で撮影されたか、という情報を埋め込んだりしてくれる(これはこれで自宅等の位置情報が
外部に公開されてしまう可能性があって問題となったが)。

このEXIFデータだが、デジタルデータではあるが、暗号化等はかかっていない。
そのため、読み方さえわかれば、中に何が書かれているか判る。

カメラが埋め込む情報だが、カメラメーカー独自の情報というわけではなく、
広く一般的になっている情報であり、CANONのカメラのEXIFだから、
NIKONのソフトウェアでは読み込めないという事は殆どない。

殆どと書いたのは、EXIFの情報の種類にはものすごく色々な情報があり、
先程述べた焦点距離とか絞りとかシャッタースピードといった一般的なものは、
カメラメーカーごとの違いはないが、やはりカメラメーカー独自の情報というのも
埋め込んでいることがあり(というか、CANONやNIKONは独自の情報を
埋め込んでくれる)、独自情報は、解析方法を知らない場合は読み解くことはできない。

このように一部、メーカー独自の情報も含まれているEXIFデータだが、
パソコンでも読み取ることはできる。Windowsだと、写真データのあるフォルダで、
EXPLORERの表示する列を選ぶときにEXIFの情報の何を表示するかを選択することも
できる。これは、WindowsというOSがEXIFデータの読み方を知っているからに
他ならない。

このEXIFデータだが、読み取り方法について述べてきたが、読み取りだけでなく、書き込み
もできる。さきほど暗号化されていないと書いたが、後から改変することも出来るわけである。
それはデジタルデータの宿命で、複製も簡単だし、改変もデジタルのビットを
書き換えるだけである。
とはいえ、作法を知らないと、書き換えたデータはチグハグなものになる。
写真は望遠なのに焦点距離が短いとか、絞りとシャッタースピードは改変したら明らかにおかしいデータとなる。
なので、書き換えはほとんど行われないのだが、特例的に書き換える頻度の高い項目がある。
それは、

評価

である。☆を1個から5個までで評価するわけだ(☆無しを含めれば6段階)。
つまり、写真を撮ったあとの自己評価を、EXIFとして埋め込むことができる。
埋め込んでおくと、写真データをパソコンにコピーしたあとも、評価は残る。
またWindowsだと、評価順にファイルを並び替えることができる。つまり評価の高い写真だけを
コピーしたりもできる。

で、この評価の与え方だが、やり方が何種類かある。
まず、カメラ本体で設定する方法だ。これはカメラで写真を表示させ、そこで操作して一枚ずつ評価を入力する方法だ。
ただ、この方式だと、小さいカメラのディスプレイで写真を評価しなければならない。
が、3インチ前後の小さいディスプレイでは微妙なピントの切れとか空気間までは把握できないので、この
方式は非現実的である。
では、どうするか、というとメモリカードをパソコンに接続し、☆を設定するのが、王道である。
が、☆評価を設定できる画像ソフトはそうそうない。
IrfanViewer等は、☆評価を入力できない。
もちろんWindowsのペイントでも☆評価は入力できない。
CANONの場合は、純正ソフトでDPPというデジタル現像用のソフトがあるが、これは☆評価を入力できる。
が、おそい。
☆評価を設定することはすぐできるが、写真を保存し直すようで、非常に時間がかかる。
という感じで決定版がない。
最初に書いたが、EXPLORERでは☆評価を設定できる。
が、これも書き込みには若干時間がかかる。
大量に写真を撮る人はわかるとおもうが、1日に数千枚撮るなんてことはよくある。
そりゃ秒間5コマとか7コマとかでカシャカシャ撮って32GBとか64GBのメモリカードを使っていればそうなる。。。
なので評価を設定するときというのは大抵大量の写真を相手にしている場合で、
速度
というのは
非常に重要である。
ちなみにPowerShellで頑張ってやると、☆評価を書き換えることが可能ではある、が、
Powershellで書き換えると、EXIF情報のほとんど、とくにメーカー独自の情報は、消えてしまう。
それはMicrosoftが、EXIFの細かいところをほとんど把握できていない、と思われる。
写真データのEXIF情報というのは、ここまで読めばわかるが、写真データを書き込みしなおすついでに
書き換えるという形式で更新することが殆どだ。
この、PowerShellで☆を書き換える事ができるといえば、たいへんに便利そうではあるが、
貴重なEXIF情報のうち、マイクロソフトが知らない情報は書き戻してくれないので、
大半のEXIF情報は失われてしまう。なので、使えない。
EXIFを綺麗にする、ということであればまだ使えるが、趣味の写真のデータ整理であれば、やはり
EXIF情報が消えるのは許されないことだろう。。。

で、ここで出てくるのは、exiftool.exe  

https://exiftool.org/である。使い方説明


PhilHarveyという人が作成したソフトウェアであるが、
これが非常に優秀なソフトで、メーカー製情報もふくめてほぼ100%のEXIF情報を失うことなく、
☆評価を更新する事ができる。

URLはいちいち記載しないが、Googleなどで exiftool.exe Phil Harvey で検索すれば間違いなく発見できる。
ちなみにPerl形式とWindows EXE 形式が選択できるが、通常使用で且つパソコンが普通にWindowsであれば
EXE形式を使えばよい。

ちなみに使い方のページは日本語ではないが、Chromeを使えば、右クリックで即日本語化され、かなり精度の高い翻訳が
すぐに手に入るのでお勧めだ。

でEXIFTOOLの使い方だが、batファイルなどを用意しておく。
例えば

Exiftool.exe -charset UTF8 -o newfilename.jpg -Rating=5 original-filename.jpg

等とすると、original-filename.jpg を読み込み、評価を☆5(Rating=5の部分)で書き換えてくれ、
尚且つそれ以外のEXIF情報は綺麗にもとのままとなる。
またIrfanView.exeであれば、
オプション→その他の外部ツールで、
上記のbatファイル名がphotolevel.bat だったとすると、
下記のように設定すると、呼び出せばすぐに☆5で評価してくれる。

C:/windows/system32/cmd.exe "/c c:/photo/tool/photolevel.bat "%1""

ちなみに写真というのは撮り出すと本当に溜まってしまう。
とくに通常では撮れないもの、例えばイベントとかにカメラを持ち出すようになったりして、
連写機能を使うようになると本当に一日に3,000枚とか撮影してしまう。
そうなるとまともに撮れているのはそのうち何枚?という話になる。
具体的にはピントが合っていなかったり、被写体が遠くてゴマ粒みたいなのに興奮してシャッターを押し続けて
メモリカードの肥やしを増やしていたりするわけで、
そういった写真を全て永久保存なんてするのはコストがかかって仕方がないわけです。

そうなると、コストをかけてバックアップを撮って残す写真と、そうではない、ディスクに余裕があれば
おいといてあげてもいいよ、的な二軍的扱いの写真とにわけていくしかないのです。
この選別行為が、先に挙げた、1日3,000枚とかになると大変な重労働で、
重労働となるとにんげんは面倒くさくなってやらなくなります。
面倒くさがる、というのは人間は皆持っている弱点なので対策が必要なわけで、
出来るだけ写真を簡単に評価できるように環境を作る必要があります。
で、いまのところ、写真を一度にできるだけたくさん処理しようとすると、
iPadとかだと転送に時間がかかります。
なのでどうしてもパソコンでやるのが早くなるわけです。
パソコンで写真を評価してその評価で写真を仕分けてバックアップがとれているNAS、
バックアップのないNAS、パソコンの内蔵ディスク、といった具合に差別化して保存、
というのがいまのところベストかと思われるわけです。

ちなみにNASというのはファイルサーバ専用機でさいきんはI・Oデータなどのコンピュータ周辺機器メーカーさん
から安価(といっても2~4万くらいしますが)なものが出ています。
ディスクのミラーリングと言う機能を備えたものもあります。これは企業などでも採用されていますが、
1枚の写真を2つのディスクに常に書き込む機能をもっており、万が一ディスクが壊れても、もう一枚のディスク
が生き残る事でデータをまもるというものです。言い方を変えると、RAID1等とも呼ばれています。
もちろんディスク2枚で1枚分の容量しか確保できないので、容量の観点で見ると割高ですが、壊れてもデータが
失われる可能性はものすごく低いので安心です。

写真の保存先だが、NAsというのは基本的には自宅においておく事を意味しており、大災害で家などで
被害にあわないともかぎらない、という懸念はあるわけです。
となると、自宅以外に置いておくしかない。
でもどこに?
例えば親戚のウチ?
でも新しい写真を撮ったらどうするの?その度に親戚の家にいってNASに接続して
写真をバックアップするの?
それは面倒くさすぎるし、相手の家の人にも了承をとらないといけない。
そもそも近所だと災害対策にもならない。
ちなみに親戚でもネットワークでコピーするという手法もとれないわけではない。
ただ、ネットワーク的な知識がないと、セキュリティ上非常にまずいことが起きてしまう。
ようは全世界から書き込み可能なフォルダを作成してしまい、海外から攻撃を受けるなんてことになる。
まぁそこまでいかなくても、写真を遠隔地の親戚の家にあるNASに書き込む、という場合にエラーが起きてしまった、
となるといちいち見に行くのも大変。とはいえバックアップはとっておかないと心配。。。

で、ここで出てくるのがクラウド保存という考え方。
クラウドというのは、ようは企業が用意したコンピュータ群だけど、インターネットのアドレスさえ判っていれば、そのサーバが実際にどの地にあろうが
扱える、という考え方。
簡単にいえば、スマホのゲームでは、大抵はサーバがあり、サーバに接続して戦いを進めたりする。このとき、
サーバが東京にあるのか大阪にあるのか、九州か沖縄か北海道か、といったことを気にすることはないと思う。
この感じがクラウドである。
で、クラウド上に個人の写真を保管する方法が、2つある。
1つは、そういうサービスを利用する形態だ。
例えばAmazonとかGoogleはスマホなどにソフトを入れておくとそのソフト経由でクラウドに写真を保存できたりする。
でさらに無料で無制限で使い放題だったりする。
が、ここには落とし穴がある。
タダほど高いものはないというアレだ。
はっきりとは書いていないが、機械学習の学習データなどに自分の写真が使われたりすると思われる。
たぶん、クラウドのサービスで写真を保存すると写真に名前をつけたり、タグをつけたり、SNSへの投稿に使ったりすると
おもうが、このタグやファイル名といった文字情報と具体的な写真の画像データをもとにAIに知識として
吸収させたりできると思われる(本当にやっているかどうかは知らない)。
でもたぶんこういうサービスは規約的にそういう逃げ道が用意してあるものだ。最近は個人情報保護という観点もあるから、
顔の映った写真をそのまま利用しているということはないと思うが、どちらにせよサービスの提供者にもメリットがあるはずで、
おそらくは、写真のデータとそれに付随する文字列情報をAIの知識のネタとして使われると思う。
まぁだからといって利用者にはデメリットとなることは殆どないのだが。

で、クラウドを利用する方法として考えられるもう一つの方法が、
ファイルサーバを自分で作ったりするプリミティブな利用法
である。ややこしい言い方をしたが、ようは、クラウド上でディスクだけ確保し、そこに実際にファイルをコピーしたりするのは、
自分でやってしまおうというものだ。
これだとクラウド業者に盗み見られる頻度はかなり少なくなると思う。
暗号化して暗号化のキーは俺しか知らない、という状態も作るおうと思えば作れる。

が、

この2つ目の方法は好き勝手に自分で仕様を決める事ができる反面デメリットとして出てくるのが、
料金
になる。Amazonのs3ストレージは現時点でかなり価格の安いオブジェクトストレージだと思うが、
これでも1GB0.25USDかかる。200GBで月3,000円だ。これは年間3万6千円となる。
さきほどpc周辺機器メーカー製のNASがディスクミラー機能付きで売っているといったが、
値段的には、2TBでも4万くらいである。
だからクラウドでの保存は利用期間が1年を超えると当然、NASより割高になってしまうわけだ。
NASを5年使ったとすると、NASは機器購入に4万だが、
クラウドで写真を保存する第二の方法だと、5年で15万を超えてしまうのだ。
(Amazonの場合はGlacier グレイシャー)という更に安価なストレージもあるが、
こちらは写真をクラウドから撮り出すのに、非常に時間がかかってしまう。というか遅い。
何時間もかかることがあるし、早くダウンロードできるオプションもあるが、有料であるし、
使えばものすごく費用がかかることがあり、個人単位でおいそれとは手が出しにくい。

というわけで、写真を大量に撮る人は、写真整理方法としてpc上で選別し、☆評価をつけて分け、
☆評価の高いファイルだけを集めてNASなどで管理するのがよろしいと思うあれ、
そのときに☆評価を更新する際は、オリジナルのEXIFを壊さないように元データを保存しておくか、
またはEXIFTOOLのようなメーカー固有のEXIF情報でさえ理解して書き戻してくれるツールが必要、
という話でした。

関連リンク

EXIFTOOLのコマンドラインヘルプです https://exiftool.org/exiftool_pod.html

EXIFTOOLの「評価」に関する情報 https://exiftool.org/TagNames/XMP.html#Rating

EXIFTOOL でコマンドラインを考えるときに必要なGROUPタグの指定に関する情報 https://exiftool.org/#groups

EXIFTOOLに関するフォーラムのサイト https://exiftool.org/forum/index.php?topic=3567.0

EXIFTOOLのタグ情報 https://exiftool.org/TagNames/EXIF.html

EXIFTOOLのGPSに関する情報 https://exiftool.org/TagNames/GPS.html

JEITA(電子情報技術産業協会)によるEXIFの定義 https://www.jeita.or.jp/cgi-bin/standard/search.cgi?id=46



ちなみにウチの写真整理方法は下記の通り。

写真を撮ってくる

写真をパソコンの内蔵ディスクへ移動

良い写真に★5個を付ける

★5の写真だけをNASへコピー

NASはRAID1:ミラーリングディスクで保護

パソコンの内蔵ディスクはいつか壊れますので、大事な写真だけNASへコピーしておきます

写真を閲覧するときは、IrfanViewを使用し、外部toolには上記記事で書いているようにbatを指定します。

batの中身はこんなのです


rem setlocal enabledelayedexpansion
echo %1
rem pause
C:\photo\tool\CheckPath.exe %1 M 0
if NOT %ERRORLEVEL% == 0 EXIT
C:\photo\tool\exiftool.exe -charset UTF8 -o %%dSEL\%%f.%%e -Rating=5 %1
rem if NOT %ERRORLEVEL% == 0 EXIT
C:\photo\tool\CopyChDr.exe %1 M SEL
echo %ERRORLEVEL%
if NOT %ERRORLEVEL% == 0 PAUSE

%1にはファイル名がフルパスで渡されてきます。で、CheckPath.exeというのは自作ツールで、Mドライブ(NASドライブ)の同名フォルダ(内蔵ディスクの写真保存フォルダがC:\photo\hoge であれば、M:\photo\hoge )

にファイルが存在しないかチェックします。ファイルがあれば処理は中断

つぎに、EXIFTOOLで評価を★5に書き換えます。このとき、-o %%dSEL\%%f.%%eという記述を
することでサブフォルダSELに評価済み写真のデータが作成されます(オリジナルは書き換えない)。

つぎに、CopyChDr.exeで写真をコピーします。このとき、ドライブをMドライブにします(C:\photo\hoge\SEL というフォルダ
から、 M:\photo\hoge\SEL にコピーする)。このCopyChDr.exeも自作ツールとなります。



自作ツールについて

とりあえずソースを載せておきます。

checkpath.exe


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CheckPath
{
class Program
{
static void Main(string[] args)
{
//コピー元ファイル パス情報
//ドライブレター  例えばMとか
//規則 0:同じだとエラー
System.Environment.ExitCode = 9;
System.Windows.Forms.DialogResult ix;
if (args.Count()<2)
{
Console.WriteLine("ARGS COUNT;" + args.Count());
ix = MessageBox.Show("引数がたりません。\nArg1:CopyFileFullPath Arg2:DestDriveLetter Arg3:Rule{0:Arg1 = Arg is Error 1:Arg1 != Arg2 is Error");
}
else
{
if (args[2].Substring(0, 1).Equals("0"))
{
if (args[0].Substring(0, 1).ToUpper().Equals(args[1].Substring(0, 1).ToUpper()))
{
Console.WriteLine("ERROR same drive");
ix = MessageBox.Show("ドライブが同じなのでエラーです","ERROR",MessageBoxButtons.OK,MessageBoxIcon.Error);
}
else
{
Console.WriteLine("ok");
System.Environment.ExitCode = 0;
}
}
if (args[2].Substring(0, 1).Equals("1"))
{
if (args[0].Substring(0, 1).ToUpper().Equals(args[1].Substring(0, 1).ToUpper()))
{
Console.WriteLine("ok");
System.Environment.ExitCode = 0;
}
else
{
Console.WriteLine("ERROR other drive");
ix = MessageBox.Show("ドライブが指定されたものと異なりますのでエラーです", "ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);

}
}

}
}
}
}


copychdr.exe


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualBasic.FileIO;

namespace CopyChDr
{
class Program
{
static void Main(string[] args)
{
//仕様
//引数1:ファイル名
//引数2:ドライブ(コピー先)
//引数3:付与フォルダ名
//引数4:(オプション)フォルダ名の大本の文字列数(規定値:5) これは、m:\photo\20201231 というフォルダ構造を想定していて、photoのフォルダは
// 無視して、20201231 という位置のフォルダのタイムスタンプをオリジナルと合せる機能で使用
//
//動作 コピー元 引数1のフォルダ名¥付与フォルダ名¥引数1のファイル名
//    コピー先 引数2のドライブ名¥引数1のフォルダ名¥付与フォルダ名¥引数1のファイル名
Console.WriteLine("ARG COUNT" + args.Count().ToString());
int ExitCode = 9;
System.Environment.ExitCode = ExitCode;
for (int i = 0; i < args.Count(); i++)
{
Console.WriteLine("ARG:" + args[i]);
}
if (args.Count() < 3)
{
Console.WriteLine("InsufficientParameters\n" +
"arg1 original filename\n" +
"arg2 drive\n" +
"arg3 external-folder-name\n"+
"[arg4] basepathlength:default5 ex.M:\\photo\\20201231dir (photo is 5 chars )\n");

}else{
//ドライブレターチェック(同じならダメ)
if (args[0].Substring(0, 1).ToUpper().Equals(args[1].Substring(0, 1).ToUpper())){
Console.WriteLine("ERROR DriveLetter is Same!\n");
}else{
//ファイル名の組み立て
string DirName;
DirName = System.IO.Path.GetDirectoryName(args[0]);
Console.WriteLine("DirName:" + DirName);
string ExtName;
ExtName = System.IO.Path.GetExtension(args[0]);
string FileName;//拡張子含まれる
FileName = System.IO.Path.GetFileName(args[0]);
string OriginalFileName;
OriginalFileName = DirName + "\\" + FileName;
Console.WriteLine("OriginalFileName:" + OriginalFileName);
Console.WriteLine("SourceFileName:" + DirName + "\\" + args[2] + "\\" + FileName);
string DestDirName;
DestDirName = args[1] + DirName.Substring(1) + "\\" + args[2];
Console.WriteLine("DestFileName:" + DestDirName + "\\" + FileName);
int IgnoreFolderNameLength;
IgnoreFolderNameLength = 5;
if (args.Count() == 4)
{
IgnoreFolderNameLength = int.Parse(args[3]);
}
int SkipLength;
SkipLength = IgnoreFolderNameLength + 4;
//ファイルの存在チェック
DateTime CreateTime;
DateTime WriteTime;
DateTime LastAccessTime;
string SourceFileName;
SourceFileName = DirName + "\\" + args[2] + "\\" + FileName;
if (System.IO.File.Exists(SourceFileName))
{
Console.WriteLine("FileExists");
if (System.IO.File.Exists(DestDirName + "\\" + FileName))
{
Console.WriteLine("ERROR Destination File AlreadyExists!");

}
else
{
//コピー先のフォルダチェック→なければ作成
if (System.IO.Directory.Exists(DestDirName))
{
Console.WriteLine("Dest Dir Exists");
}
else
{//ないので作る
Console.WriteLine("Dest Dir Not Exists,Make Directory " + DestDirName);
System.IO.DirectoryInfo di = System.IO.Directory.CreateDirectory(DestDirName);
//作ったときはフォルダのタイムスタンプを移植する。
string SourceDirName;
SourceDirName = DirName;
CreateTime = System.IO.Directory.GetCreationTime(SourceDirName);
WriteTime = System.IO.Directory.GetLastWriteTime(SourceDirName);
LastAccessTime = System.IO.Directory.GetLastAccessTime(SourceDirName);
string DestDirBaseName;
DestDirBaseName = args[1] + DirName.Substring(1);
System.IO.Directory.SetCreationTime(DestDirBaseName, CreateTime);
System.IO.Directory.SetLastWriteTime(DestDirBaseName, WriteTime);
System.IO.Directory.SetLastAccessTime(DestDirBaseName, LastAccessTime);
SourceDirName = DirName + "\\" + args[2];
CreateTime = System.IO.Directory.GetCreationTime(SourceDirName);
WriteTime = System.IO.Directory.GetLastWriteTime(SourceDirName);
LastAccessTime = System.IO.Directory.GetLastAccessTime(SourceDirName);
DestDirBaseName = args[1] + DirName.Substring(1) + "\\" + args[2];
System.IO.Directory.SetCreationTime(DestDirBaseName, CreateTime);
System.IO.Directory.SetLastWriteTime(DestDirBaseName, WriteTime);
System.IO.Directory.SetLastAccessTime(DestDirBaseName, LastAccessTime);
//親ディレクトリのタイムスタンプをコピーする
string sourceRootDirectory;
sourceRootDirectory = SourceDirName.Substring(0, SourceDirName.IndexOf('\\', SkipLength));
string DestRootDirectory;
DestRootDirectory = DestDirBaseName.Substring(0, DestDirBaseName.IndexOf('\\', SkipLength));
Console.WriteLine("Dir Timestamp copy " + sourceRootDirectory + " --->>> " + DestRootDirectory);
CreateTime = System.IO.Directory.GetCreationTime(sourceRootDirectory);
WriteTime = System.IO.Directory.GetLastWriteTime(sourceRootDirectory);
LastAccessTime = System.IO.Directory.GetLastAccessTime(sourceRootDirectory);
System.IO.Directory.SetCreationTime(DestRootDirectory, CreateTime);
System.IO.Directory.SetLastWriteTime(DestRootDirectory, WriteTime);
System.IO.Directory.SetLastAccessTime(DestRootDirectory, LastAccessTime);


}
//コピー実行
string DestFileName;
DestFileName = DestDirName + "\\" + FileName;
CreateTime = System.IO.File.GetCreationTime(OriginalFileName);
WriteTime = System.IO.File.GetLastWriteTime(OriginalFileName);
LastAccessTime = System.IO.File.GetLastAccessTime(OriginalFileName);
Console.WriteLine("Copying File " + SourceFileName + " --->>> " + DestFileName);
FileSystem.CopyFile(SourceFileName, DestFileName, UIOption.AllDialogs, UICancelOption.DoNothing);
System.IO.File.SetCreationTime(DestFileName, CreateTime);
System.IO.File.SetLastWriteTime(DestFileName, WriteTime);
System.IO.File.SetLastAccessTime(DestFileName, LastAccessTime);
Console.WriteLine("Copy finished");
ExitCode = 0;

}
}
else
{
Console.WriteLine("ERROR File not found! :" + SourceFileName);
}
}
}
System.Environment.ExitCode = ExitCode;
}
}
}

スポンサーサイト



この記事のトラックバックURL

http://alphaiota.blog105.fc2.com/tb.php/540-d0212a83

コメント

コメントする

管理者にだけ表示を許可する

Template Designed by DW99