You are not logged in.
IMPORTANT: Read this topic to the very last post, because updates are posted below!
Many users were asking me to add a support for reading date and time from RAW images. Unfortunately, there is no open-source libraries for Delphi to read these formats (and extract date and time values), and it was too big of a task to write such a library my-self, in my free time. But with the recent release of ReNamer it is finally possible! There are free tools on the Internet that allow reading the date and time from RAW images. Now, ReNamer can re-use their output from within PascalScript rule.
I will give an example of usage for those who needs it:
1) Download a tool called Exiv2 from http://www.exiv2.org/ and unpack it into ReNamer's folder. It is a command-line tool, it will let you extract date and time from RAW images, here is an example:
> exiv2.exe CRW_9367.CRW
Filename : CRW_9367.CRW
Filesize : 5637808 Bytes
Camera make : Canon
Camera model : Canon EOS 10D
Image timestamp : 2004:03:19 16:13:00
Image number : 193-9367
Exposure time : 1/1024 s
...........................
2) Get your hands on the latest version of ReNamer, and add a PascalScript rule with this code:
const
EXIV = 'exiv2.exe';
TIME_STAMP_LINE = 5;
var
Date, Command, Output: string;
Lines: TStringsArray;
function ExtractDate(const Text: string): string;
var
I: Integer;
Started: Boolean;
begin
Started := False;
for I:=1 to Length(Text) do
if (Text[i] >= '0') and (Text[i] <= '9') then
begin
Result := Result + Text[i];
Started := True;
end
else if (Text[i] = ':') and Started then
Result := Result + '-'
else if (Text[i] = ' ') and Started then
Result := Result + ' ';
end;
begin
Command := '"'+EXIV+'" "'+FilePath+'"';
ExecConsoleApp(Command, Output);
Lines := WideSplitString(Output, #13#10);
if (WideArrayLength(Lines) >= TIME_STAMP_LINE) then
FileName := ExtractDate(Lines[TIME_STAMP_LINE-1]) +
WideExtractFileExt(FileName);
end.
3) Drag over your RAW images to ReNamer, Preview, and Rename
P.S. New name for a sample file "CRW_9367.CRW" will be "2004-03-19 16-13-00.CRW", and you can twick it further from here... good luck!
P.P.S. That was done with Exiv2 v0.10 downloaded on 12 of September 2006 and ReNamer v4.15, minor modifications might be required as both of these tools update.
Offline
Here it is the revised code. I've made some changes and customized the return string with constants. Give it a try:
const
EXIV = 'exiv2.exe';
DATETIMESTRING = 'Image timestamp';
SEPARATORDATE = '-';
SEPARATORTIME = '.';
SEPARATORDATETIME = '_';
var
Command, Output: string;
Lines: TStringsArray;
function ExtractDate(const Lines: TStringsArray; FilePath: String): string;
var I, Start : Integer;
DateAndTime : TStringsArray;
begin
for I := 0 to WideArrayLength(Lines) - 1 do
begin
if (WideCopy(Lines[i], 1, WideLength(DATETIMESTRING)) = DATETIMESTRING) then
begin
Start := WidePos(': ', Lines[i]) + 2;
DateAndTime := WideSplitString(WideCopy(Lines[i], Start, 19), ':');
Result := DateAndTime[0] + SEPARATORDATE
+ DateAndTime[1] + SEPARATORDATE
+ DateAndTime[2] + SEPARATORTIME
+ DateAndTime[3] + SEPARATORTIME
+ DateAndTime[4];
DateAndTime := WideSplitString(Result, ' ');
Result := DateAndTime[0] + SEPARATORDATETIME + DateAndTime[1] + WideExtractFileExt(FileName);
exit;
end
end;
Result := Filename;
end;
begin
Command := '"'+EXIV+'" "'+FilePath+'"';
ExecConsoleApp(Command, Output);
Lines := WideSplitString(Output, #13#10);
FileName := ExtractDate(Lines, FilePath);
end.
This could only be possible with this utility. Now I can rename almost 2000 NEF files in a snap. Thank you Denis!
Carlos
Last edited by madeinlisboa (2006-11-08 13:53)
Offline
Carlos,
As I said in my original post: "minor modifications might be required as both of these tools update". That's what probably happened. The Exiv2 tool got updated, and image timestamp line from the output has been moved from line 5 to line 9 (according to what I see from your modifications). I don't think there was any need for major modifications, you could have just changed TIME_STAMP_LINE constant to 9, and it should've worked
Unfortunately I don't have RAW files anymore, to perform the tests and support my guess...
Offline
It didn't change to line 9. I was getting warnings in the output and that shifted the date several rows down, but it doesn't mean it will happen with everybody. I only increased the number to make sure enough data was retrieved from the file. The other small patches were included only to make the new filename more customized and to find the exact place of the date and time, thus making the script flexible for future versions.
Cheers
Carlos
Offline
It probably would've been better to detect the "Image timestamp" line (like you did), without binding it to some particular line number (like I did). So good job! Did it work for you after all?
Offline
May be I should have renamed the constant. It is there only to make sure enough lines are retrieved from the output. Perhaps it is better to delete it though. The string verification is enough.
It is working like a charm, thanks to your wonderful utility
ps: I changed the code. it's simpler and it works!
Last edited by madeinlisboa (2006-11-08 13:46)
Offline
I found few RAW images, and decided to improve this script! It is optimized and has a better error handling, and now you can also define the output format for the datetime using DATETIMEFORMAT constant!
Note: you will need the latest dev version, with few new pascalscript functions: ReNamerBeta.zip
const
EXIV = 'exiv2.exe';
DATETIMESTRING = 'Image timestamp';
DATETIMEFORMAT = 'yyyy-mm-dd hh.nn.ss';
function TryExtractDate(const Output: WideString; var DateTime: TDateTime): Boolean;
var
Lines: TStringsArray;
I, Start, Position: Integer;
DateAndTime: String;
Parts: TStringsArray;
Date, Time: TDateTime;
Year, Month, Day, Hour, Min, Sec: Integer;
begin
Result := False;
Lines := WideSplitString(Output, #13#10);
for I := 0 to WideArrayLength(Lines)-1 do
begin
Position := WideTextPos(DATETIMESTRING, Lines[i]);
if Position > 0 then
begin
Position := Position + WideLength(DATETIMESTRING);
DateAndTime := WideCopy(Lines[i], Position, WideLength(Lines[i]));
DateAndTime := WideTrim(WideReplaceStr(DateAndTime, ':', ' '));
Parts := WideSplitString(DateAndTime, ' ');
if WideArrayLength(Parts) = 6 then
begin
Year := StrToIntDef(Parts[0], -1);
Month := StrToIntDef(Parts[1], -1);
Day := StrToIntDef(Parts[2], -1);
Hour := StrToIntDef(Parts[3], -1);
Min := StrToIntDef(Parts[4], -1);
Sec := StrToIntDef(Parts[5], -1);
if (Year>0) and (Month>0) and (Day>0) and
(Hour>=0) and (Min>=0) and (Sec>=0) then
if TryEncodeDate(Year, Month, Day, Date) then
if TryEncodeTime(Hour, Min, Sec, 0, Time) then
begin
DateTime := Date + Time;
Result := True;
end;
end;
end
end;
end;
var
Command, Output: string;
DateTime: TDateTime;
begin
Command := '"'+EXIV+'" "'+FilePath+'"';
ExecConsoleApp(Command, Output);
if TryExtractDate(Output, DateTime) then
FileName := FormatDateTime(DATETIMEFORMAT, DateTime);
end.
Offline
Revival of this topic....
Actually the script gives the error: Unknow function WideArrayLength();
Should i replace this for length()?
Tiago
Offline
Yes, good man!
You need to replace WideArrayLength() with Length().
Offline
Yes, good man!
You need to replace WideArrayLength() with Length().
Thanks
Another quick question, in the line:
DATETIMEFORMAT = 'yyyy-mm-dd hh.nn.ss';
There some way that he can read the format defined in settings?
Offline