[batch] Wert in Textdatei berechnen

Registriert
Juni 2010
Beiträge
181
Ich "entwickle" meine Digitalkamera-Fotos aus den RAW-Dateien am PC selbst.
Dazu habe ich mir schon eine Batch-Datei geschrieben, die das macht.
Mir geht es jetzt noch um das Fein-Tuning.

Mit einem Exif-Bearbeitungsprogramm kann ich Werte auslesen usw.
Die Sache ist nun folgende:

In einer Textdatei "mm.txt" steht dann eine einzige Zeile, z.B.:
Focal Length : 33.2

Das ist der Wert der beim Knipsen verwendeten Brennweite.
Aber mit der neueren digitalen Werte-Skala. Darunter kann ich mir
ziemlich schlecht etwas vorstellen. Deshalb will ich das wieder
auf alte Analog-Werte umstellen.

Dazu muss man bloß den vorhandenen Wert mit 5,556 multi-
plizieren. - Bloß, wie mache ich das?

Auf eine Stelle nach dem Komma sollte der neue Wert auch
nach Möglichkeit gerundet werden. Das Wunschergebnis
sähe in mit der Zeile von oben so aus:

Focal Length : 184.5

Wie genau bekomme ich das denn hin?

Es kann auch in einer anderen Datei stehen, z.B. "mm2.txt".
Das wäre nicht das Problem. Nur das berechnen. Wie stelle
ich das denn an? Und wie schreibe ich es dann wieder zurück?
 
Code:
setlocal enabledelayedexpansion
set tmpf=%temp%\temp.txt

findstr "Focal Length" datei.txt > "%tmpf%"
for /f "delims= ;tokens=*" %%a in ('%tmpf%') do (
  set /A analog=%%d * 5.556
  echo !analog! > mm2.txt
)
Vollkommen ungetestet, sitz auch grad nicht vor einem Windows (also nur aus dem Kopf zusammengeschrieben). Aber so Pi mal Fensterbank ist der Weg (wenn auch umständlich).
 
In der "temp.txt" steht genau das gleiche drin wie in "mm.txt".

Das Ziel war bestimmt, da den Wert reinzuschreiben.

So kommt auf jeden Fall:
";token=*"" kann syntaktisch an dieser Stelle nicht verwendet werden.

Ausserdem fehlt da noch das Runden.

Mir sagen übrigens die meisten der Befehle fast gar nichts. Noch nie gehört.
 
An deiner Stelle würde ich den Taschenrechner nehmen. set /A kann keine Kommazahlen berechnen und das Auseinandernehmen der Zahlen, multiplizieren und das Komma neu zu setzen (was auch nicht immer richtig funktionieren würde), ist ein klein wenig umständlich. Mit der Powershell würde dies einfacher gehen:
Code:
$flen = (Select-String -Path .\mm.txt -Pattern "Focal Length").toString().split( " " )[3]
$flen = [System.Convert]::ToDecimal( $flen )
$alen = $flen * 5.556
echo $alen > mm2.txt
 
Sieht recht hilfreich aus. Ich werde aber eine ganze Weile brauchen,
um das zu überprüfen.

Auf den Einfall mit dem Taschenrechner bin auch schon gekommen.
Das war mir dann aber doch zu blöd. - Wozu hat man schließlich mal
ein wenig programmiert?

Den Aufwand mit dem auseinander nehmen und wieder zusammen
setzen würde ich evtl. sogar auf mich nehmen, da es ja eine einmalige
Sache ist.

Powershell klingt natürlich besser. Das Ding wurde gewiss nicht umsonst
eingeführt (und ist bei jedem Windows mit dabei). - Dafür gibt's aber
meiner Meinung keine richtige Anleitung. (Sonst hätte ich's mir schon
einfach mal so angeschaut.) Da scheint so ein bißchen Geheimnis-
krämerei drum gemacht zu werden. - Anyway!

Ich seh's schon vor mir: Ich bin wieder der Verrückte, der versucht,
'ne Powershell über 'ne Batch-Datei zu öffnen. - Und das wird wieder
nicht gehen, weil man damit viel zu viele böse und schlimme Sachen
anstellen kann.

Naja, irgendwie werde ich das schon noch rauskriegen. Gibt ja mittler-
weile sogar ein paar Tools für die Powershell. (Hab' mich dann wohl
doch schon irgendwann dran versucht, und bin nicht weit gekommen.)

Immer diese Abkürzungen, die mich dann annerven:
"findstr" finde ich ja noch ok, steht gewiß für "find string"
aber "delims" ... steht für ?? "delete ims"?
und "$flen" setzt sich zusammen aus "$f" für "Floating-Wert"?
und "len" dann für "length"?

So im Schlaf macht man das nicht einfach mal so. (Wenn man's sonst
nicht braucht.)

(Oder steht "$flen" für "focal length"? und "$alen" dann für was?)

Naja, wird schon werden.

Ich hab's mir gerade noch mal angeschaut. Den Code-Schnipsel von
Dir. Da fehlt wieder das runden! (auf eine Stelle nach dem Komma)
Ich hoffe mal, dass ich auch so darüber stolpern werden, wenn ich
mir die Powershell etwas genauer anschaue. (Hoffentlich diesmal
etwas glückvoller.)
 
Code:
$flen = (Select-String -Path .\mm.txt -Pattern "Focal Length").toString().split( " " )[3]
$flen = [System.Convert]::ToDecimal( $flen )
$alen = [System.Math]::Round( $flen * 5.556, 1 )
echo $alen > mm2.txt
$flen für Focal Length und $alen für Analog. delims steht für delimiters (Trennzeichen).

Ich hab von der Powershell auch keine Ahnung. Da fällt mir aber gerade wieder ein, dass man dort auch .NET Klassen verwenden kann. Glaub ich muss mich damit mal näher auseinandersetzen. :)

Falls du es per Batch machen willst, kannst du ja da weiter machen, wo ich aufgehört hab. Wenn du aber wenig Ahnung davon hast, kannst du es im Prinzip gleich lassen, außer du willst dich damit wirklich beschäftigen.
Code:
@echo off

setlocal enabledelayedexpansion

set mul_g=5
set mul_k=556
set mul_l=0

set strlen_value=%mul_k%
set exit_anchor=begin
goto :strlen
set mul_l=%strlen_length%
:begin

for /F "tokens=1-4" %%a in ('findstr "Focal Length" mm.txt') do (
	set val=%%d
	
	for /F "tokens=1-2 delims=." %%i in ("!val!") do (
		set val_g=%%i
		set val_k=%%j
	)
	
	echo value length = !val_l!
	
	echo %mul_g%
	echo %mul_k%
	echo %mul_l%
	echo.
	echo !val_g!
	echo !val_k!
	echo !val_l!
	
	set mul=%mul_g%%mul_k%
	set val=!val_g!!val_k!
	
	echo !mul!
	echo !val!
)

goto :EOF

:strlen
set #=%strlen_value%
set strlen_length=0
:strlen_loop
if defined # (set #=%#:~1%&set /A strlen_length += 1&goto strlen_loop)
goto %exit_anchor%

:EOF
Wie gesagt, über set /A kannst du keine Kommazahlen zusammenrechnen. Also nehm ich oben über mul_* die Zahl vor und nach dem Komma auseinander. Unten bei der Definition von mul hatte ich vor, einfach die Berechnung ohne Komma durchzuführen, dann die Anzahl der Kommastellen hochzuzählen, das Komma erneut zu setzen und mit dem Ergebnis leben. Dort müsstest du dann wieder den Kommateil herausnehmen und hast dann vorn den Ganzzahlanteil und die Stellen hinter dem Komma. Das kannst du ja dann einfach über echo %vorderteil%.%hinterteil% > datei.txt in eine Datei schreiben. Die Frage ist nur, ob die Berechnung mit so großen Zahlen durchgeführt werden kann.

Zum Runden sei gesagt: 0,5 aufaddieren, 10^Stellenanzahl multiplizieren, den ganzzahligen Teil nehmen, durch 10^Stellenanzahl dividieren und dann hast du deinen gerundeten Wert. Wüsste aber gerade nicht, wie man das elegant machen könnte.
 
Ich hab's hinbekommen! und zwar mit der Powershell. Vorher hab ich's noch kurz als Batch versucht, aber da bin ich an den % und ! gescheitert. (Weil ich nicht so richtig weiß bzw. herausgefunden habe, was was bedeutet.) Jetzt fehlt zwar immer noch das Runden, aber so der gewaltige Beinbruch ist das nun nicht mehr. (Es geht ja nur um ein paar Fotos. Der Vollständigkeit halber könnte man das aber schon noch richtig machen.)

Die Powershell lässt sich tatsächlich mit dem Befehl "powershell" aus einer Batch-Datei heraus aufrufen. Stellt man dem Powershell-Skript ein ./ voran, wird es direkt ausgeführt. Ungefähr so:

powershell ./core.ps1

Dazu muss aber vorher die Ausführung von unsignierten Skripten in der Powershell vorher mit "Set-ExecutionPolicy RemoteSigned" erlaubt werden. (Warum das da RemoteSigned heißt und nicht RemoveSigned weiss wohl auch keiner.)

Hier nun der Powershell-Code: (Der wohl um einiges kürzer aussähe, hätte ich anstatt focuslengtdigital fld und anstatt focuslengthanalog fla verwendet.)

Code:
$focuslengthdigital = (Select-String -Path .\mm1.txt -Pattern "Focal Length").ToString().split( " " )[22]
echo $focuslengthdigital
$focuslengthdigital = [System.Convert]::ToDecimal( $focuslengthdigital )
$fla = $focuslengthdigital / 10 * 5.556
echo $fla
if ( $fla -gt 100 )
{
$fla = [System.Convert]::ToString( $fla )
$fla = $fla[0] + $fla[1] + $fla[2] + "." + $fla[4]
$fla = "Focal Length                    : " + $fla
echo $fla > mm2.txt
}
else
{
$fla = [System.Convert]::ToString( $fla )
$fla = $fla[0] + $fla[1] + "." + $fla[3]
$fla = "Focal Length                    : " + $fla
echo $fla > mm2.txt
}

Ich hab einfach mal focuslengthanalog durch fla ersetzt. Der Lesbarkeit halber. Die ersten beiden echo's können noch raus und statt der 3 beim split habe ich eine 22 verwendet, weil das an der Forensoftware lag, die die anderen Leerzeichen entfernt hatte. Interessant ist eigentlich nur, dass noch ein / 10 verwendet werden muss, weil es sich anscheinend verrechnet.

Ich hab noch nicht mal eine Ahnung, was man in der Powershell anstatt von REM verwenden kann oder eben wie man da rundet. (round funktioniert jedenfalls nicht) Falls da noch jemand noch irgendwas weiss, kann er es ja mal hier noch zum besten geben.

Was mich noch wundert ist, dass mein Windows 7 nur eine Powershell in der Version 1 hat. Eigentlich müsste es Version 2 sein. Weiss da noch jemand, warum das so ist? Muss man die erst extra noch downloaden? War die nicht beim letzten Service-Pack mit dabei?
Ergänzung ()

Naja, wider Erwarten war's das noch nicht. Als nächstes habe ich natürlich versucht, das mit mehreren Fotos zu machen und prompt ging es da nicht mehr.

Wenn "Focal Length" mehrmals in mm1.txt vorkommt, wird $focuslengthdigital nicht mehr richtig ausgelesen. Eine Lösung dafür habe ich erstmal noch nicht. Ob da der [-AllMatches]-Parameter irgendwie hilft, ist noch offen. "Focal Length" steht bei mehreren Fotos jedenfalls in mehreren Zeilen, z.B. in der 2., 4. und 6. In der 1., 3. und 5. befindet sich der jeweilige Foto-Name.
 
Zu der Powershell-Version:
führ mal get-host aus. Kann mir kaum vorstellen, dass da 1.0 rauskommt. Der Start-Pfad ist auf jeden Fall nicht die Version!

Zu deinem Problem:
Das verstehe ich gerade nicht so ganz. :D Generell kannst du dir bei mehreren Treffern über einen Array-Index die jeweilge Zeile verschaffen.
In Verbindung mit ner Schleife sollte das dann klappen.
 
@ moo-moo--moogle:
Für Auskommentierung kannst du in Powershell "#" benutzen.
Was etwas weh tut (aber natürlich nur Kosmetik ist), ist, dass du übliche CMD-Befehle und Powershell-Befehle mischt (z.B. echo anstatt Write-Host).
Auch die Umleitung mit dem ">" macht man in Powershell mit dem Befehl "Out-File".
....das aber nur am Rande :)


Wie real_general richtig schrieb, würde ich es auch in einer Schleife machen ...
 
Code:
> alias | findstr echo
Alias           echo                            Write-Output



> get-help echo

NAME
    Write-Output

ÜBERSICHT
    Sendet die angegebenen Objekte an den nächsten Befehl in der Pipeline. Wenn
     es sich um den letzten Befehl in der Pipeline handelt, werden die Objekte
    in der Konsole angezeigt.


SYNTAX
    Write-Output [-InputObject] <PSObject[]> [<CommonParameters>]


BESCHREIBUNG
    Mit dem Cmdlet "Write-Output" wird das angegebene Objekt über die Pipeline
    an den nächsten Befehl gesendet. Wenn es sich um den letzten Befehl in der
    Pipeline handelt, wird das Objekt in der Konsole angezeigt.

    Write-Output sendet Objekte über die primäre Pipeline, die auch als "Ausgab
    estream" oder "Erfolgspipeline" bezeichnet wird. Um Fehlerobjekte über die
    Fehlerpipeline zu senden, verwenden Sie Write-Error.

    Dieses Cmdlet wird in der Regel in Skripts verwendet, um Zeichenfolgen und
    andere Objekte in der Konsole anzuzeigen. Da standardmäßig jedoch die Objek
    te am Ende einer Pipeline angezeigt werden, ist es im Allgemeinen nicht erf
    orderlich, das Cmdlet zu verwenden. Beispielsweise sind "get-process | writ
    e-output" und "get-process" äquivalent.


VERWANDTE LINKS
    Online version: http://go.microsoft.com/fwlink/?LinkID=113427 (möglicherwei
    se auf Englisch)
    Write-Debug
    Write-Verbose
    Write-Error
    Write-Progress
    Write-Host
    Write-Warning
    Tee-Object

HINWEISE
    Zum Aufrufen der Beispiele geben Sie Folgendes ein: "get-help Write-Output
    -examples".
    Weitere Informationen erhalten Sie mit folgendem Befehl: "get-help Write-Ou
    tput -detailed".
    Technische Informationen erhalten Sie mit folgendem Befehl: "get-help Write
    -Output -full".
:)
 
@Yuuri
schon klar, dass es aliases gibt. Aber wenn ich Powershell programmiere, nutze ich auch dessen "Namenskonzepte", alleine der Übersicht und der Sauberkeit halber.
Wenn du deine Ausgabe z.B. pipen willst nimmst du Write-Output. Wenn du dagegen direkt etwas auf der Konsole ausgeben willst nimmst du Write-Host (das ist ein Unterschied den du mit "echo" nicht erkennen würdest), das ist sauber und widerspruchsfrei :)

Ist vlt. eine Phylosophiefrage, aber für mich gehört das zur sauberen Programmierung dazu.



.... sollte aber keine Kritik sein, ist mir nur auf die schnelle aufgefallen :)

Grüße
 
@real_general: get-host sagt mir "Version : 2.0" - "Der Start-Pfad ist auf jeden Fall nicht die Version!" Aha! Warum sollte man das auch umbenennen? "1.0" sieht ja viel lustiger aus. "In Verbindung mit ner Schleife sollte das dann klappen." - Wenn man denn eine hinbekommt. So in Powershell meine ich. Hat sich ja einiges am Syntax geändert über die Jahre. (so generell)

@estre: "Für Auskommentierung kannst du in Powershell "#" benutzen." Das ist mir auch irgendwann wieder eingefallen. Ich mische CMD-Befehle und Powershell-Befehle? Wohl am ehesten weil ich es nicht besser weiss. Unter anderem deswegen gebe ich hier auch meinen finalen Code preis: damit vielleicht jemand noch den ein oder anderen Verbesserungsvorschlag macht. Funktionieren tut es ja. Ist halt nur eine Formsache (und eine Frage der Eleganz). (Im Endeffekt werde ich aber wohl das benutzen, was mir leichter fällt.) (Das sollte man nicht machen, aber da es hier "um nichts geht", ist das wohl gerade noch verzeihlich.)

So, nun aber mal wieder zurück zum eigentlichen Problem. Ich hab' mich mal dazu entschlossen, alles ganz ausführlich darzustellen. Vielleicht hilft's ja irgendwem. Für diese eine Sache ist das (für mich) wohl noch verkraftbar. Auch wenn der Aufwand wirklich recht hoch ist.

Also, um mal am Anfang anzufangen: an Programmen habe ich exiftool v8.84, PowerGUI v3.2.0, SilkyPix v5.0.10.2 und (XnView 1.98.8 mit) nConvert 6.05 benutzt. (exiftool zum Schreiben der EXIF-Werte, PowerGUI um in PowerShell einfacher programmieren zu können, SilkyPix zum Entwickeln der Fotos und nConvert zum Nachschärfen.)

Eine etwas umfangreichere Dokumentation der PowerShell-Befehle mit der Bezeichnung "Windows PowerShell Language Specification Version 2.0" habe ich gleich ziemlich am Anfang hier gefunden: http://www.microsoft.com/en-us/download/details.aspx?id=9706

Die Arbeitspfade sahen bei mir wie folgt aus: C:\AMD mit den Unterverzeichnissen C:\AMD\developed und C:\AMD\sharpened

Die erste "batch.bat" sah wie folgt aus:
Code:
"C:\Program Files (x86)\XnView\nconvert" -opthuff -q 97 -subsampling 2 -efocus -soften 52 -org_depth -dct 2 -out jpeg -o C:\AMD\sharpened\%%.jpg -D C:\AMD\developed\*.*
"C:\Program Files (x86)\XnView\exiftool" C:\AMD\sharpened\*.jpg -Software= -ModifyDate= -CreateDate= -overwrite_original
Da erfolgt also schon das Nachschärfen (mit -efocus) sowie die Modifikation einiger EXIF-Werte, besser gesagt deren Löschung. Am Rande sei erwähnt, dass die Huffmann-Tabelle immer optimiert werden sollte (um den Farbraum besser zu treffen) und das "enhance focus" zwar schön nachschärft, das aus meiner Sicht aber etwas übertreibt, sodass ich später zu einer anderen Methode wechselte.

Mein erster Versuch, die Brennweite auszulesen sah wie folgt aus:
Code:
exiftool *.jpg -n -FocalLength > mm.txt

Inhalt und Ziel sahen dann in verkürzter Form so aus:
Focal Length : 33.2
*5.556
Focal Length : 184.4

Das klappte mit der
core.ps1 v1.0
Code:
$focuslengthdigital = (Select-String -Path .\mm1.txt -Pattern "Focal Length").ToString().split( " " )[22]
echo $focuslengthdigital
$focuslengthdigital = [System.Convert]::ToDecimal( $focuslengthdigital )
$focuslengthanalog = $focuslengthdigital / 10 * 5.556
echo $focuslengthanalog
if ( $focuslengthanalog -gt 100 )
{
$focuslengthanalog = [System.Convert]::ToString( $focuslengthanalog )
$focuslengthanalog = $focuslengthanalog[0] + $focuslengthanalog[1] + $focuslengthanalog[2] + "." + $focuslengthanalog[4]
$focuslengthanalog = "Focal Length                    : " + $focuslengthanalog
echo $focuslengthanalog > mm2.txt
}
else
{
$focuslengthanalog = [System.Convert]::ToString( $focuslengthanalog )
$focuslengthanalog = $focuslengthanalog[0] + $focuslengthanalog[1] + "." + $focuslengthanalog[3]
$focuslengthanalog = "Focal Length                    : " + $focuslengthanalog
echo $focuslengthanalog > mm2.txt
}
ganz gut:
mm1.txt
Focal Length : 23.1
mm2.txt
Focal Length : 128.3

Das Problem war, dass das bei mehreren jpg-Dateien nicht mehr funktionierte:
mm1.txt
======== I-P1000849.jpg
Focal Length : 70.9
======== I-P1000850.jpg
Focal Length : 112.2
======== I-P1000851.jpg
Focal Length : 550
======== I-P1000860.jpg
Focal Length : 3.1
4 image files read
warf
mm2.txt
Focal Length : 0,.0
aus. Warum, habe ich nie so richtig herausgefunden.

Als nächstes ergab sich dann, dass
Code:
exiftool *.jpg -n -FocalLength <= mm1.txt
nicht funktionierte. Man muss wohl ziemlich naiv sein, um zu glauben, dass das funktionieren könnte, aber es hätte ja auch klappen können. Nun, "in die andere Richtung" kann exiftool nur mit CSV-Dateien was anfangen. Die Befehle dafür brachte ich für Testzwecke in einer "crucible.bat" unter:
Code:
exiftool *.jpg -n -csv -FocalLength > mm1.csv
exiftool *.jpg -n -csv=mm2.csv -overwrite_original

Dann modifizierte ich core.ps1 v1.0 geringfügig, indem ich mm1.txt durch mm1.csv usw. ersetzte. core.ps1 v2.0 lieferte mir dann folgende Ergebnisse:

mm1.csv
SourceFile,FocalLength
"I-P1000849_02.05.2012,09'20.jpg",62.3
"I-P1000850_02.05.2012,09'20.jpg",33.2
"I-P1000851_02.05.2012,10'33.jpg",50

mm2.csv
Focal Length : .

Die vom PowerShell-Skript ausgelesenen Werte sahen wohl so aus:
mm1.csv:2:"I-P1000849_02.05.2012,09'20.jpg",62.3
mm1.csv:3:"I-P1000850_02.05.2012,09'20.jpg",33.2
mm1.csv:4:"I-P1000851_02.05.2012,10'33.jpg",50

Lange Rede, kurzer Sinn: an dieser Stelle verwarf ich dann die ganze Auslese-Methode und fing fast noch einmal neu von vorn an. Mit Select-String verhaspelte sich PowerShell immer wieder. (Jedenfalls fand ich keine Lösung dafür.)

core.ps1 v3.0
Code:
$i = 0

Get-Content mm1.csv | ForEach-Object { $_ 

$i = $i + 1

if ( $i -eq 1 ){
$newfile = $_
}

if ( $i -gt 1 ){
$Name = $_.SubString(0,34)
$fld = $_.SubString(34)
$fla = $fld / 10 * 555.55 
$fla = [System.Math]::Round( $fla )
$fla = $fla / 10
$res = $Name + $fla
$newfile = $newfile + "
" + $res
}
}
echo $newfile > mm2.csv
war da ein großer Schritt nach vorne. Jetzt hatte ich sogar herausgefunden, wie das mit dem Runden ging. Diese mysteriöse "/ 10" vor der "* 555.55" verwende ich auch immer, weil PowerShell sonst $fld nicht als Zahl begreift usw. Ausserdem verrechnet es sich sonst manchmal (um eine Zehner-Potenz), wie bereits erwähnt. Das habe ich unfreiwillig noch etwas genauer untersucht und herausgefunden, dass das überhaupt nicht konsistent ist. Es hängt sogar vom Wert ab, ob es sich (um eine Zehner-Potenz) verrechnet oder nicht. (Vielleicht lag's aber auch nur daran, wie einige Werte ausgelesen werden. Die "50" (für FocalLength) in der 3. Zeile (von mm1.csv) endet ja nicht auf ".0") Wenn ich mich recht entsinne, war aber "33.2" so ein Wert bei dem die gleiche Operation zu einem anderen Wert (bzgl. Zehner-Potenz) führen konnte als bei "62.3" aus der 1. Zeile.
Das degradiert aus meiner Sicht PowerShell schon mal gewaltig. Für ernsthafte Anwendungen ist es damit fast hinfällig. Verlassen kann man sich darauf jedenfalls nicht, was es so als Ergebnisse bringt. Mag sein, dass das nur in nicht alltäglichen Konstellationen (für erfahrerene Programmierer) vorkommt, daran gearbeitet werden, sollte aber trotzdem. Wozu hat man denn X CPU-Kerne, wenn die dann nur Müll ausrechnen?

mm1.csv sah dann wie folgt aus:
SourceFile,FocalLength
"I-P1000849_02.05.2012,09'20.jpg",62.3
"I-P1000850_02.05.2012,09'20.jpg",33.2
"I-P1000851_02.05.2012,10'33.jpg",50

und mm2.csv so:
SourceFile,FocalLength
"I-P1000849_02.05.2012,09'20.jpg",346.1
"I-P1000850_02.05.2012,09'20.jpg",184.4
"I-P1000851_02.05.2012,10'33.jpg",277.8

Es hat also im Grunde genommen, gemacht, was es sollte. So hatte ich mir das vorgestellt.
Das Dumme war nur, dass mir exiftool da einen Strich durch die Rechnung machte. Nur weil eine Datei auf ".csv" endet und ihr Inhalt optisch mit der einer CSV-Datei vergleichbar ist, heisst das noch lange nicht, dass da auch das richtige Format (aus programmtechnischer Sicht) vorliegt.

"C:\Program Files (x86)\XnView\exiftool" *.jpg -n -csv=mm2.csv -overwrite_original

führte also zu
Invalid tag name ' ?S o u r c e F i l e ' in mm2.csv
No SourceFile 'I-P1000849_02.05.2012,09'20.jpg' in imported CSV database
(canonical path: 'C:\AMD\sharpened\I-P1000849_02.05.2012,09'20.jpg')
No SourceFile 'I-P1000850_02.05.2012,09'20.jpg' in imported CSV database
(canonical path: 'C:\AMD\sharpened\I-P1000850_02.05.2012,09'20.jpg')
No SourceFile 'I-P1000851_02.05.2012,10'33.jpg' in imported CSV database
(canonical path: 'C:\AMD\sharpened\I-P1000851_02.05.2012,10'33.jpg')

Dieses "?" vor'm "S" in "SourceFile" konnte nicht verarbeitet werden. Also musste ich dann wirklich auf das CSV-Format umsteigen. Glücklicherweise gelang mir das und hier ist nun die finale Version meines kleinen EXIF-Wert-Umrechnungsprogramms:

core.ps1 v4.0
Code:
$oldfile = Import-Csv mm1.csv
$newfile = $oldfile

$i=0
$q=0

foreach ($line in $oldfile){
$q=$q+1
}

if ( $q -gt 1 ) {
foreach ($line in $oldfile){

$newdata = $oldfile[$i]."FocalLength"
$newdata = $newdata / 180 * 10000
$newdata = [System.Math]::Round( $newdata )
if ( $newdata -gt 999 )
{
$newdata = [System.Convert]::ToString( $newdata )
$newdata = $newdata[0] + $newdata[1] + $newdata[2] + "." + $newdata[3]
}
else
{
$newdata = [System.Convert]::ToString( $newdata )
$newdata = $newdata[0] + $newdata[1] + "." + $newdata[2]
}
$newfile[$i]."FocalLength" = $newdata
$i=$i+1
}
}

if ( $q -eq 1 )  {

$newdata = $oldfile."FocalLength"
$newdata = $newdata / 180 * 10000
$newdata = [System.Math]::Round( $newdata )
if ( $newdata -gt 999 )
{
$newdata = [System.Convert]::ToString( $newdata )
$newdata = $newdata[0] + $newdata[1] + $newdata[2] + "." + $newdata[3]
}
else
{
$newdata = [System.Convert]::ToString( $newdata )
$newdata = $newdata[0] + $newdata[1] + "." + $newdata[2]
}
$newfile."FocalLength" = $newdata
}

$newfile | Export-Csv mm2.csv -NoTypeInformation

Die Inhalte der CSV-Dateien sehen da wie folgt aus:

mm1.csv
SourceFile,FocalLength
"I-P1000849_02.05.2012,09'20.jpg",62.3
"I-P1000850_02.05.2012,09'20.jpg",33.2
"I-P1000851_02.05.2012,10'33.jpg",50

mm2.csv
"SourceFile","FocalLength"
"I-P1000849_02.05.2012,09'20.jpg","346.1"
"I-P1000850_02.05.2012,09'20.jpg","184.4"
"I-P1000851_02.05.2012,10'33.jpg","277.8"

Glücklicherweise kann exiftool aber auch etwas mit dem etwas abweichenden Format der mm2.csv anfangen. (Die "mm" im Dateinamen stehen übrigens für Millimeter.) Um alles in einem Rutsch zu machen hab' ich mir dann eine "develop!.bat" geschrieben bzw. die "batch.bat" vom Anfang umbenannt und erweitert und die Verzeichnisse etwas geändert.

develop!.bat
Code:
@echo off
"C:\Program Files (x86)\XnView\nconvert" -opthuff -q 97 -subsampling 2 -eedge 51 -org_depth -dct 2 -out jpeg -o C:\AMD\development\%%.jpg -D C:\AMD\development\temp\*.*
cd development
"C:\Program Files (x86)\XnView\exiftool" *.jpg -Software= -ModifyDate= -CreateDate= -FileSource= -FlashpixVersion= -overwrite_original
"C:\Program Files (x86)\XnView\exiftool" *.jpg -n -csv -FocalLength > mm1.csv
powershell ./core.ps1
"C:\Program Files (x86)\XnView\exiftool" *.jpg -n -csv=mm2.csv -overwrite_original
copy *.jpg C:\AMD\
del *.jpg
cd ..

Das Ergebnis sieht dann wie folgt aus:
XnView-Eigenschaften/Meta-Daten
Name Wert

Kamerahersteller Panasonic
Kameramodell DMC-FZ45

Belichtungszeit 1/125
Blende 5.2
Belichtungsprogramm normal(2)
Filmempfindlichkeit(ISO) 320
EXIF-Version 02.30
Aufnahmedatum/-uhrzeit 2012:05:12 15:25:49
Belichtungskorrektur 0
Max. Blendenwert F2.8
Belichtungsmessung Mehrfeld(5)
Blitz Aus
Brennweite [mm] 600
Farbraum sRGB


Die Angaben/Werte reichen mir bzw. so gefällt mir das besser und da die Fotos sowieso mit nConvert aus einer Batch heraus weiterbearbeitet werden müssen, ist das ja nun mal kein Umstand.

So, was mir jetzt eigentlich noch fehlt, sind elegantere Lösungen. Es geht aber auch so. Nur, falls jemand einen Einfall hat. Diese Trennung der Werte für über 99.9 und unter 99.9 nehme ich vor, weil die unterschiedlich lang sind, und $q fängt die Fälle ab, in denen nur ein 1 Foto weiter zu bearbeiten ist, weil sonst irgendwas mit dem Array nicht klappt. Dann kann kein Index angelegt werden oder sowas. Die Zahlen sind so groß (und eher merkwürdig) gewählt worden, damit die Genauigkeit gegeben ist und damit auch Werte wie die "50" eine ".0" bekommen. (Die Dateinamen der ".jpg"-Dateinen habe ich inzwischen vereinfacht zu "I-P1000851_02.05.2012.jpg". Wenn die EXIF-Werte stimmen, gibt es keinen Grund dafür, die Dateinamen so nur unnötig lang zu machen.)

Alles in allem war's dann doch ein Heiden-Aufwand, aber so kommt man wenigstens nicht aus der Übung. Eigentlich fehlt mir jetzt nur noch, dass ich einfach die SD-Karte einstecken kann, nur noch einmal auf "develop!.bat" klicke und alles automatisch vonstatten geht. Nur leider spielt da SilkyPix nicht mit. Kommandozeilen-Parameter dafür habe ich noch nicht gesehen. (Vereinfachen würde es die Sache allemal.) Den ganzen Aufwand ist es übrigens Wert, die Bilder manuell am PC zu entwickeln. Zoomt man da rein, fällt nichts auseinander wie bei den mit der Automatik geknipsten Bildern. Vielleicht packen es die Kamera-Hersteller ja auch irgendwann, die Bildnachbearbeitung (bzw. Customisierung) in der Kamera besser zu machen. Oder eine ganz neue Technik findet sich.
 

Ähnliche Themen

Zurück
Oben