Vertracktes Bash-Problem mit Argumenten
Hallo,
Zum Hintergrund des Problems siehe unten.
Kurz: ImageMagick draw rectangle Kommando dynamisch in ein convert
einbauen.
Ich habe zum Ueben mein Script mal drastisch reduziert auf folgendes
fehlerhafte Script:
--- snippety snip ---
#!/bin/bash
set -x
function rect
{
echo "-stroke black -strokewidth 3 -draw 'rectangle 1,2 5,6'"
}
convert -size 10x10 xc:transparent -fill transparent \
$(
rect
) \
out.png
--- snappety snap ---
Aber das geht ja schief, Der Parameter zu -draw wird in seine
Einzelteile zerlegt. Also habe ich mir mit folgender Kruecke beholfen:
--- snippety snip ---
#!/bin/bash
set -x
function rect
{
echo -e "-stroke\nblack\n-strokewidth\n3\n-draw\nrectangle 1,2 5,6"
}
IFS='
'
convert -size 10x10 xc:transparent -fill transparent \
$(
rect
) \
out.png
--- snappety snap ---
Aber das ist ziemlich mistig. Ab dem Setzen von IFS habe ich nur noch
Probleme am Hals, wenn ich noch weitere Dinge anstellen will. Aber ich
komme einfach nicht drauf wie ich das mit der bash eleganter loesen
koennte. Ich habe beinahe alle Kombinationen von Escapes und
Hochkommas ausprobiert, bisher ohne Erfolg.
Die Function rect berechnet im richtigen Script natuerlich die x und y
aus den verschiedenen EXIF-Daten der Kamera.
Hintergrund lang: ein Script um mit ImageMagick die AF-Sensoren wie
sie im EXIF stehen ueber ein Bild zu legen. In digikam ist das erst
ein Enhancement Request.
Hierzu wird der IM Befehl
-draw "rectangle $x0,$y0 $x1,$y1"
benutzt. Wichtig hierbei, das Argument zu -draw ist eines, nicht
mehrere einzelne. Nun aber hat so eine DSLR ja viele AF-Sensoren,
manche davon genutzt. D.h. ich habe eine Funktion mit dem Namen
"rect", deren Ausgabe in das IM convert-Kommando eingebaut werden soll
um mehrere Rechtecke zu zeichnen (wie z.B. im Canon DPP oder dem TFT
der Kamera selbst).
function rect
{
# after some mathematics
echo "-stroke $5 -strokewidth $6 -draw 'rectangle $x0,$y0 $x1,$y1'"
}
... exiftool Output parsen und in Variablen mit dem Namen der Tags
ablegen ...
convert ... \
-fill transparent \
$(
...
for i in "${AFPointsInFocus[@]}"
do
rect ${AFAreaXPositions[$i]
Hallo Roman, Am 19.10.2010 21:48, schrieb Roman Fietze:
Zum Hintergrund des Problems siehe unten.
Kurz: ImageMagick draw rectangle Kommando dynamisch in ein convert einbauen.
Ich habe zum Ueben mein Script mal drastisch reduziert auf folgendes fehlerhafte Script:
--- snippety snip --- #!/bin/bash set -x
function rect { echo "-stroke black -strokewidth 3 -draw 'rectangle 1,2 5,6'" }
convert -size 10x10 xc:transparent -fill transparent \ $( rect ) \ out.png --- snappety snap ---
[...]
Falls du dich zu sehr darauf versteifst und in deinem Skript nur noch Verschlimmbesserungen einbaust, dann solltest du besser nochmal zum Anfang zurück und eine etwas längere Pause einlegen. Oft ist die Lösung direkt vor der Nase. ;-) Ich würde im o.g. Code-Ausschnitt den Parameter für convert von der Funktion "rect" nicht mit echo ausgeben lassen, sondern in einer Variable wegspeichern. Hier ein Beispiel: --- ANFANG --- ANFANG --- ANFANG --- ANFANG --- ANFANG --- #!/bin/bash # initialisieren RECT_PARAMETER="" function rect() { # die übergebenen Parameter ($1,$2,$3,...) an diese Funktion # an dieser Stelle verarbeiten lassen # ... # Werte festlegen (ggfs. vorher von irgendwo auslesen) STROKE="black" STROKEWIDTH="3" X0="1" Y0="2" X1="5" Y1="6" # Parameter für convert zusammen bauen RECT_PARAMETER="-stroke ${STROKE} \ -strokewidth ${STROKEWIDTH} \ -draw 'rectangle ${X0},${Y0} ${X1},${Y1}'" } # .... hier weiteren code .... # Aufruf der Funktion "rect" ggfs. mit weiteren Parameter rect wert1 wert2 wert3 wert4 usw. # Die Variable RECT_PARAMETER im convert-Parameter einbetten convert -size 10x10 xc:transparent \ -fill transparent \ ${RECT_PARAMETER} \ out.png # .... hier weiteren code .... --- ENDE --- ENDE --- ENDE --- ENDE --- ENDE --- Das o.g. Beispiel kann man noch weiter ausführen. Jedoch würde das den Rahmen sprengen. Folgende Dokumentation kann dir beim Skripting helfen: # info bash HTH, -- Gruß Sebastian - openSUSE Member (Freespacer) Webseite/Blog: http://www.sebastian-siebert.de Wichtiger Hinweis zur openSUSE Mailing Liste: http://de.opensuse.org/OpenSUSE_Mailinglisten-Netiquette -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Hallo Sebastian, On Wednesday 20 October 2010 06:41:48 Sebastian Siebert wrote:
Oft ist die Lösung direkt vor der Nase. ;-)
Deshalb habe ich mir nun schon an mehreren Abenden ein gutes Glas Wein neben den Bildschirm gestellt als ich an dem Problem knabberte. Aber jetzt ist langsam gut. ;)
... sondern in einer Variable wegspeichern.
So weit war ich schon mal. In der Scheife habe ich mir eine Variable zusammengebastelt: cmd="convert ..." for i in ... do rect ... # setzt rect_return cmd="$cmd $rect_return" done $cmd Aber das ist unschoen. In einer richtigen Programmiersprache wuerden sich mir bei so was wie globalen Variablen die Nackenhaare aufstellen. Ich spielte auch mit dem Gedanken es doch mit echo zu machen und die Parameter durch \0 zu trennen, und unten in der Schleife nicht mit $(...) sondern mit dem Ansatz der cmd-Variablen zu machen. Ich war auch schon drauf und dran das jetzt mit Python, evt. gar PythonMagick, oder auch in C++ (Magick++) und boost (zum Parsen der exiftool-Ausgaben) oder auch libexi[fv] zu machen. Da waere ich jetzt vermutlich schon lange fertig.
Folgende Dokumentation kann dir beim Skripting helfen: # info bash
Habe ich schon rauf und runter, inklusive des Advanced Bash-Scripting Guide im TLDP. Roman -- Roman Fietze Telemotive AG Buero Muehlhausen Breitwiesen 73347 Muehlhausen Tel.: +49(0)7335/18493-45 http://www.telemotive.de -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Am 20.10.2010 07:28, schrieb Roman Fietze:
Hallo Sebastian,
On Wednesday 20 October 2010 06:41:48 Sebastian Siebert wrote:
Oft ist die Lösung direkt vor der Nase. ;-)
Deshalb habe ich mir nun schon an mehreren Abenden ein gutes Glas Wein neben den Bildschirm gestellt als ich an dem Problem knabberte. Aber jetzt ist langsam gut. ;)
... sondern in einer Variable wegspeichern.
So weit war ich schon mal. In der Scheife habe ich mir eine Variable zusammengebastelt:
cmd="convert ..." for i in ... do rect ... # setzt rect_return cmd="$cmd $rect_return" done
$cmd
Aber das ist unschoen. In einer richtigen Programmiersprache wuerden sich mir bei so was wie globalen Variablen die Nackenhaare aufstellen. Ich spielte auch mit dem Gedanken es doch mit echo zu machen und die Parameter durch \0 zu trennen, und unten in der Schleife nicht mit $(...) sondern mit dem Ansatz der cmd-Variablen zu machen.
Ich war auch schon drauf und dran das jetzt mit Python, evt. gar PythonMagick, oder auch in C++ (Magick++) und boost (zum Parsen der exiftool-Ausgaben) oder auch libexi[fv] zu machen. Da waere ich jetzt vermutlich schon lange fertig.
Folgende Dokumentation kann dir beim Skripting helfen: # info bash
Habe ich schon rauf und runter, inklusive des Advanced Bash-Scripting Guide im TLDP.
Roman
Hi, nein, nicht alles, nur den speziellen Teil in die Variable: function buildhstr() { hstr=... return $hstr } und dann convert ... `buildhstr` .... dann brauchst Du auch keine globalen Variablen... cu jth -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Hallo Joerg, On Wednesday 20 October 2010 07:36:29 Joerg Thuemmler wrote:
return $hstr
Eine Funktion in der Bash kann doch nur numerische Werte zurueckliefern, keine Strings und schon gar keine Arrays? Roman -- Roman Fietze Telemotive AG Buero Muehlhausen Breitwiesen 73347 Muehlhausen Tel.: +49(0)7335/18493-45 http://www.telemotive.de -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Am 20.10.2010 10:15, schrieb Roman Fietze:
Hallo Joerg,
On Wednesday 20 October 2010 07:36:29 Joerg Thuemmler wrote:
return $hstr
Eine Funktion in der Bash kann doch nur numerische Werte zurueckliefern, keine Strings und schon gar keine Arrays?
Roman
Hi, da hast Du wohl recht ;-( (zu viel php in letzter Zeit). Dafür sind doch aber die Variblen gemeinsam und Du kannst stattdessen function buildhstr() { hstr=... return } und dann convert ... $hstr .... nehmen. man bash: "Variables local to the function may be declared with the local builtin command. Ordinarily, variables and their values are shared between the function and its caller." cu jth -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Hallo, Am Die, 19 Okt 2010, Roman Fietze schrieb: [..]
#!/bin/bash set -x
function rect { echo "-stroke black -strokewidth 3 -draw 'rectangle 1,2 5,6'" } [..] Aber das geht ja schief, Der Parameter zu -draw wird in seine Einzelteile zerlegt. Also habe ich mir mit folgender Kruecke beholfen:
Nimm Array-Variablen.
function rect { # after some mathematics echo "-stroke $5 -strokewidth $6 -draw 'rectangle $x0,$y0 $x1,$y1'" }
==== make_rect() { # after some mathematics RECT=( "${RECT[@]}" -stroke "$5" -strokewidth "$6" \ -draw "rectangle $x0,$y0 $x1,$y1" ) } ====
... exiftool Output parsen und in Variablen mit dem Namen der Tags ablegen ...
convert ... \ -fill transparent \ $( ...
for i in "${AFPointsInFocus[@]}" do rect ${AFAreaXPositions[$i]
$afinfocuscolor 3 done ... # noch AFPointsSelected ) \ ...
====
RECT=()
for i in "${AFPointsInFocus[@]}"; do
make_rect ${AFAreaXPositions[$i]
Hallo, Nachtrag: Am Mit, 20 Okt 2010, David Haller schrieb:
BTW: in Perl kannst du Exiftool direkt verwenden (use Image::ExifTool) und hast dann direkt Zugriff auf alle Variablen, d.h. du musst nix parsen, sondern kannst dir direkt die Werte geben lassen.
In Perl hast du auch direkt ein Interface zu Image::Magick, d.h. du kannst sowas machen: 1a) Bild mit Image::ExifTool öffnen 1b) Bild mit Image::Magick öffnen 2a) EXIF Daten auslesen und nachbearbeiten/parsen (parsen nur, wenn ein Feld etwas zum parsen enthält, z.B. ein Datum, das du umformatieren oder umrechnen willst). 2b) deinen Krams ins Image::Magick Bild reinzeichnen 3) fertiges Bild abspeichern Wie du die "Schleife" legst (also um 2a und 2b oder eine um 2a und eine um 2b) kannst du wohl frei wählen. Dein Script übernimmt dann in dem Szenario die Rolle vom perlscript 'exiftool' und vom binary 'convert' ;) Ansonsten hätt' ich dir auch noch eine perl-Funktion, mit der du bequem externe Programme aufrufen kannst (inkl. Fehlerbehandlung). Ein Problem könnte evtl. allerdings die Dateigröße bzw. die Größe des Bilds im Speicher sein, tendenziell hast du das Problem mit 'convert' allerdings AFAIK auch in gleichem Maße. Achso: das Interface von Image::ExifTool ist eher eklig, das von Image::Magick entspricht IIRC mehr oder weniger den Optionen, die man von 'convert' und 'mogrify' her kennt. Welches Schweinderl hätten's gern? -dnh -- Never be afraid to try something new. Remember, amateurs built the ark; professionals built the Titanic. -- Anonymous -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
Hallo David, On Thursday 21 October 2010 03:01:13 David Haller wrote:
BTW: in Perl kannst du Exiftool direkt verwenden (use Image::ExifTool) und hast dann direkt Zugriff auf alle Variablen, d.h. du musst nix parsen, sondern kannst dir direkt die Werte geben lassen.
Ich sehe schon, ich werde mich was dieses Script anbelangt von der bash verabschieden. Exiftool selbst ist ja Perl, aber ich programmiere dann doch weit lieber in Python. Also werde ich mir die Muehe machen die Ausgabe von exiftool zu parsen, das ist in Python ebenfalls sehr einfach. Und in Python kann ich ImageMagick bei Bedarf auch direkt nutzen. Roman -- Roman Fietze Telemotive AG Buero Muehlhausen Breitwiesen 73347 Muehlhausen Tel.: +49(0)7335/18493-45 http://www.telemotive.de -- Um die Liste abzubestellen, schicken Sie eine Mail an: opensuse-de+unsubscribe@opensuse.org Um eine Liste aller verfuegbaren Kommandos zu bekommen, schicken Sie eine Mail an: opensuse-de+help@opensuse.org
participants (4)
-
David Haller
-
Joerg Thuemmler
-
Roman Fietze
-
Sebastian Siebert