Inhaltsverzeichnis
http://herbaer.de/xmlns/20060826/imgshow
imgshow_ht.xslt
- Die Bildergeschichte im XHTML-Formatimgshow.js
- Die Navigationimgshow.css
- Die Darstellung im BrowserJede Software muß nicht nur für Computer, sondern auch für Menschen verständlich geschrieben werden. Den menschenverständlichen Teil erfüllt diese Datei, die sie gerade lesen. Ich schreibe ihn im DocBook-XML-Format. Docbook ist nicht zuletzt deshalb meine Wahl, weil es gut dokumentiert ist.
Wie jedes andere Dateiformat braucht es Software, die mit dem Format umgehen kann.
Ich benutze die hervorragenden Docbook-Stylesheets von Norman Walsh
und den XSLT-Verarbeiter xsltproc,
um aus der DocBook-Datei eine XHTML-Datei zu erzeugen.
Außer der XHTML-Darstellung will ich später einmal auch eine druckbare Datei (z.B. PDF)
erzeugen. In der XHTML-Datei sollen die Namen von Verzeichnissen aktive Verweise sein,
aber nicht in der PDF-Darstellung.
Daher verwende ich in der DocBook-Datei filename
-Elemente
statt ulink
-Elemente.
Für die XHTML-Darstellung erstelle ich eine Anpasungsdatei mit einer Vorlage für
filename
-Elemente,
die das a
-Element in die XHTML-Ausgabe einfügt.
Die Anpassungsdatei muß aber den Pfad zu den eingebundenen Original-Stylesheets enthalten.
Die Datei docbook_ht.xsltpat
enthält daher den Platzhalter $DOCBOOK_XSLTDIR
,
den der Befehls sed durch den richtigen Dateipfad ersetzt.
Das bash-Skript docbook_ht zeigt,
wie xsltproc und die Stylesheets angewendet werden.
Die erzeugte XHTML-Datei enthält Verweise auf Bilddateien im Verzeichnis
images
.
Deshalb habe ich dieses Verzeichnis aus dem Stylesheet-Verzeichnis hierher kopiert.
Die Bilder sind im "Kasten", in diesem Falle als Bilddateien im Verzeichnis
orig
gespeichert.
Das Dateisystem des ursprünglichen Datenträgers (Speicherkarte) unterscheidet nicht zwischen
Groß- und Kleinschreibung in Dateinamen. Je nachdem, auf welchem System ich die Dateien kopiere,
sind die Dateinamen mit Großbuchstaben oder mit Kleinbuchstaben gebildet.
Das Perl-Programm fntolower.perl sorgt dafür,
dass die Dateinamen Kleinbuchstaben statt Großbuchstaben enthalten.
Die Bilddateien liegen im RAW-Format vor.
Ich konvertiere sie mit dem Programm dcraw zunächst in das PPM-Format
mit 16 Bit Farbtiefe.
Dieses Bildformat können andere Programme weiterverarbeiten.
Um die Bilder leicht überschauen zu können, brauche ich ein Format,
das schnell geladen werden kann.
Der Befehl convert aus dem Paket ImageMagick
erzeugt geeignete JPEG-Dateien.
Das Bash-Skript convraw erledigt die Arbeit.
Die PPM-Dateien werden in das Verzeichnis ppm
geschrieben,
die JPEG-Datei zur Bildauswahl in das Verzeichnis preview
.
Das Programm kann durch Zuweisungen an Variablen im Dateikopf angepaßt werden:
g_size=480x480 | Die beiden Zahlen geben die maximale Breite und Höhe des möglicherweise gedrehten JPEG-Bildes an. Das Bild wird nicht verzerrt, Breite und Höhe werden in demselben Verhältnis gestaucht oder gestreckt. |
g_qual=70 | Diese Einstellung im Bereich von 1 bis 100 bestimmt den Grad der JPEG-Kompression. Größere Werte bedeuten eine geringere Kompression und eine bessere Bildqualität. |
g_prfraw="orig/p" |
Die Original-Bilddateien liegen im Verzeichnis
orig ,
und deren Namen beginnen mit p .
|
g_sfxraw=".orf" |
Die Namen der Original-Bilddateien enden auf .orf .
Das Programm verarbeitet alle Dateien,
deren Dateipfad zu dem Muster $g_prfraw*$g_sfxraw paßt.
|
g_prfppm="ppm/p" |
Die erzeugten PPM-Bilddateien liegen im Verzeichnis
ppm ,
und deren Namen beginnen mit p .
Das Verzeichnis ppm
wird erzeugt, wenn es noch nicht existiert.
Das Präfix $g_prfraw der Quell-Bilddateien
wird durch $g_prfppm ersetzt.
|
g_sfxppm=".ppm" |
Die Namen der erzeugten PPM-Bilddateien enden auf .ppm .
Das Suffix $g_sfxraw der Quell-Bilddateien
wird durch $g_sfxppm ersetzt.
|
g_prfjpgl="preview/" |
Abhängig von der eingestellten Drehung (Querformat oder Hochformat)
können verschiedene Präfixe für die erzeugten JPEG-Dateien verwendet werden.
Diese Variable enthält das Dateipräfix für das Querformat
(Endbuchstabe l wie landscape ).
Die JPEG-Bilddateien für das Querformat liegen im Verzeichnis
preview , das erzeugt wird,
wenn es noch nicht existiert.
Das Präfix $g_prfraw der Quell-Bilddateien
wird durch $g_prfjpgl ersetzt.
|
g_prfjpgp="preview/" |
Diese Variable enthält das Dateipräfix für das Hochformat
(Endbuchstabe p wie portrait ).
Die JPEG-Bilddateien für das Hochformat liegen im Verzeichnis
preview , das erzeugt wird,
wenn es noch nicht existiert. Hier ist es dasselbe Verzeichnis
wie für die JPEG-Dateien im Querformat.
Das Präfix $g_prfraw der Quell-Bilddateien
wird durch $g_prfjpgp ersetzt.
|
g_sfxjpgl=l.jpg |
Ähnlich wie das Präfix hängt auch das Suffix der erzeugten JPEG-Dateien
von der eingestellten Drehung (Querformat oder Hochformat) ab.
Diese Variable enthält das Suffix für die JPEG-Dateien im Querformat
An der Endung .jpg erkennt das Programm convert
das Dateiformat der Zieldatei (JPEG).
Das Suffix $g_sfxraw der Quell-Bilddateien
wird durch $g_sfxjpgl ersetzt.
|
g_sfxjpgp=p.jpg |
Das Suffix für die JPEG-Dateien im Hochformat.
An der Endung .jpg erkennt das Programm convert
das Dateiformat der Zieldatei (JPEG).
Das Suffix $g_sfxraw der Quell-Bilddateien
wird durch $g_sfxjpgp ersetzt.
|
g_rotl="" | "Querformat" bedeutet hier keine Drehung. Dieser Wert wird als Option an convert übergeben, wenn Querformat eingestellt ist. |
g_rotp=270 | "Hochformat" bedeutet hier eine Drehung um 270 Grad im Uhrzeigersinn. Dieser Wert wird als Option an convert übergeben, wenn Hochformat eingestellt ist. |
g_curform=portrait |
Der Wert portrait stellt das Hochformat ein,
der Wert landscape das Querformat.
|
Die üblichen Befehlszeilen-Option --help
und --version
zeigen kurze Informationen an und beenden das Skript, ebenso alle anderen Optionen.
Das Verzeichnis preview
enthält nun Bilddateien,
die ich bequem mit dem Bildbetrachter Eye of Gnome
betrachten kann.
Jetzt gehe ich den Kern der Sache an und schreibe die "Geschichte" zu den Bildern,
die Datei story.xml.
Ich verwende XML-Auszeichnungen, die im Vergleich zur letzten Bildershow etwas erweitert sind.
Die Ausrichtung eines Bildes wird jetzt nicht mehr an der Kennung des Bildes erkannt,
sondern am Attribut format
.
Ich verwende den Namensraum http://herbaer.de/xmlns/20061228/imgshow
.
Alle Dateien, die zur fertigen Präsentation gehören, liegen im Verzeichnis
story.
Nun muß ich die Bilddateien für die Präsentation erzeugen. Zu jedem Bild erzeuge ich eine JPEG-Bilddatei im Verzeichnis images für die Normalansicht, eine JPEG-Bilddatei im Verzeichnis smallimg zur Anzeige auf kleinen Bildschirmen (z.B. von Notebooks) und eine JPEG-Bilddatei im Verzeichnis thumbs zur Vorschau. Die Verzeichnis-Pfade zu den Original-Bilddateien und den zu erstellenden Dateien, die Bildgrößen der zu erstellenden Dateien und weitere Parameter (Qualität der JPEG-Kompression) stehen in der XML-Datei makeimg.rc
Die verwendete XML-Syntax des Namensraums http://herbaer.de/xmlns/20060818/rc
ist allgemein für eine baumartige Struktur von Konfigurationseinstellungen gedacht.
Die Datei rc.rng (s. Anhang)
beschreibt den Namensraum.
Zwei Stylesheets können die Konfigurationseinstellungen im Web-Browser darstellen:
rc_ht.xslt erzeugt eine baumartige, hierarchische Darstellung. Verschachtelte div-Elemente werden durch CSS-Regeln eingerückt. Auf dieses Stylesheet verweist die Verarbeitungsanweisung in der Datei makeimg.rc.
rc_ht_c.xslt erzeugt eine "flache" Tabelle von Schlüssel/Wert-Paaren. Die hierarchische Struktur steckt in den Namen der Schlüssel. Die einzelnen Namen der Einträge von der Wurzel bis zum Wert werden mit zwei Doppelpunkten als Trenner aneinandergehängt. Diese XHTML-Darstellung zeigt die Datei makeimg.rc.c.xhtml.
Das Stylesheet rc_dkb.xslt stellt die Konfigurationseinstellungen im DocBook-Format dar. Das Ergebnis ist steht im Anhang.
Ein Dateiformat für Konfigurationseinstellungen nützt nichts ohne ein Programm,
das die Einstellungen lesen kann. Ich benutze Perl, daher habe ich dazu das Perl-Modul
Herbaer::ConfigReader erstellt.
Ich lege im Include-Pfad des Perl-Interpreters
einen Link an, so daß die Datei
unter dem relativen Pfad Herbaer/ConfgReader.pm
gefunden wird.
Das Perl-Modul Herbaer::ConfigReader hat zwei Schnittstellen:
Dem Anwender (d.h. dem importierenden Programm) bietet es die Routine
read_config_filename
.
Sie erwartet den Namen der Konfigurations-XML-Datei (hier makeimg.rc
) als Parameter
und liefert als Ergebnis einen Hash mit den gelesenen Einstellungen.
Die Attribute n
der Vorfahren eines Eintrags
(Element v
wie "value") bilden die Kette der Hash-Schlüssel zu dem Wert.
Die Funktion read_config_filename
wird automatisch exportiert.
Auf der anderen Seite benutzt das Modul einen SAX-Parser, um die XML-Datei zu lesen. Es ist selbst ein SAX-Handler und implementiert die SAX-Handler-Methoden
start_document
end_document
start_element
end_element
characters
Das Perl-Skript makeimg.pl erzeugt die Verzeichnisse
mit den Bild-Dateien für die fertige Präsentation. Die Hauptarbeit erledigt auch hier ein SAX-Handler,
nämlich HB_MakeImages
.
Für jede Bilddatei, die erzeugt wird, führt es den Befehl convert aus.
convert ist eine Kommandozeilen-Schnittstelle
zur Programmbibliothek GraphicMagick.
Der Konstruktor (new
) des SAX-Handlers liest die Konfigurationseinstellungen.
Der Pfad der Konfigurationsdatei (hier makeimg.rc)
steht in der Umgebungsvariablen HB_MAKEIMG_RC
.
Wenn diese Umgebungsvariable nicht definiert ist, liest er die Datei makeimg.rc
im aktuellen Verzeichnis.
Zu jedem Bildtyp trägt er in den Hash der Einstellungen zwei weitere Einträge ein:
"command
" entspricht dem auszuführenden Befehl mit den richtigen Argumenten.
Für den Platzhalter "##kennung##
" ist nur die Kennung des Bildes einzusetzen,
die aus der "Geschichte" (Datei story.xml) gelesen wird.
Der Hash-Eintrag "target
" entspricht dem Dateipfad der erzeugten Bilddatei.
Auch er enthält den Platzhalter "##kennung##
", für den die Kennung des Bildes
eingesetzt wird. Vor dem convert-Befehl muß das Verzeichnis der zu erzeugenden
Datei existieren. Dazu ist der Eintrag "target
" nützlich.
Immer, wenn in der Geschichte ein jpg-Element vorkommt, erzeugt die SAX-Handler-Methode
start_element
für jedes Bildformat (normal, klein, Vorschau)
zunächst das Zielvereichnis, falls erforderlich, und dann die Bilddatei im Zielverzeichnis.
Das Perl-Modul Herbaer::Utils,
ursprünglich geschrieben zur Datensicherung,
enthält einige Hilfsfunktionen. Hier erzeugt die Funktion makedir
aus diesem Modul bei Bedarf das Zielverzeichnis.
Alles weitere kann der Webbrowser verarbeiten (oder sollte es können).
Die Bildergeschichte (Datei story.xml)
verweist auf das Stylesheet imgshow_ht.xslt
,
das eine Darstellung als XHTML-Dokument erzeugt.
Die Vorlage für das Wurzelelement (is:document
)
zeigt die Struktur im Großen.
Sie bindet die CSS-Datei
imgshow.css
und die JavaScript-Datei
imgshow.js
ein
und definiert im Kopf einen JavaScript-load-Handler, der ausgeführt wird,
sobald die XHTML-Darstellung fertig erzeugt ist.
Der Rumpf des erzeugten XHTML-Dokuments beginnt mit der Hauptüberschrift
(h1
).
Es folgt ein Inhaltsverzeichnis.
Das Inhaltsverzeichnis besteht aus einer Liste aller Abschnitts-Titel
(is:section
/is:title
)
Jeder Listeneintrag ist ein Verweis auf eine "javascript:"-URL. Die JavaScript-Funktion,
auf die verwiesen wird, zeigt den ausgewählten Abschnitt an.
Nach den Abschnitts-Titeln folgt eine Tabelle mit Auswahl-Elementen
(select
),
in dem der Anwender die gewünschte Bildgröße (normal oder klein)
und die Anzeigedauer der Bilder beim automatischen Bildlauf
auswählen kann.
Jeder Abschnitt (is:section
)
wird zu einem div
-Element.
Verweise auf Bilder (is:jpg
)
werden zu a
-Elementen,
die ebenfalls auf eine "javascript:"-URL verweisen.
Die angesprochene JavaScript-Funktion zeigt den am Anfang eingefügten
Blindabschnitt mit dem ausgewählten Bild an.
Am Ende eines Abschnitts (is:section
)
werden alle Bilder, auf die im Abschnitt verwiesen wird,
als Vorschau-Bilder angezeigt.
Diese Bilder sind Verweise auf dieselbe "javascript:"-URL,
auf die auch der entsprechende Text verweist.
Am Ende des Dokument-Inhalts wird ein Abschnitt eingefügt,
der Schaltflächen zur Steuerung der Anzeige, ein "Blind"-Bild und einen
Blindtext enthält. Dieser Abschnitt wird angezeigt,
wenn der Anwender ein Bild auswählt. Das ausgewählte Bild
wird dann anstelle des Blind-Bildes eingesetzt, und der Inhalt des Attributs
is:jpg
/@alt
an die Stelle des Blindtextes.
Anschließend fügt die Vorlage den transformierten Inhalt des Wurzelelements
der Bildergeschichte ein.
Sobald die XHTML-Darstellung erzeugt ist, startet der "Load"-Handler. Er zeigt den ersten Abschnitt an und legt dann die Funktionen an, die auf die Wahl der Navigations-Schaltflächen in dem erzeugten "Einzelbild-Abschnitt" reagieren. Werfen wir einen Blick auf die Darstellung: Unter dem Titel wird links das Verzeichnis aller Abschnitte (Inhaltsverzeichnis) dargestellt, rechts der ausgewählte Abschnitt oder der Einzelbild-Abschnitt. Ein Mausklick auf einen Eintrag im Inhaltsverzeichnis zeigt den ausgewählten Abschnitt rechts an. Ein Mausklick auf einen Verweis auf ein Bild oder auf ein Vorschau-Bild im rechten Teil zeigt den Einzelbild-Abschnitt an. Oben im Einzelbild-Abschnitt befinden sich sechs Schaltflächen. Sie schalten einen automatischen Bildlauf vor oder zurück ein, wechseln zum vorigen oder zum nächsten Bild des Abschnitts, halten den Bildlauf an oder wechseln zurück zum "Geschichten-Abschnitt".
Bei der Erklärung der JavaScript-Datei
imgshow.js
will ich dem funktionalen Ablauf folgen.
Ein Klick auf einen Eintrag im Inhaltsverzeichnis
ruft die Funktion show_div
auf.
Diese nimmt die ID des anzuzeigenden Abschnitts als Parameter.
Die Funktion update_button
, hier ohne Parameter aufgerufen,
bewirkt, daß alle Schaltflächen des Einzelbild-Abschnitts
in ihrer Anfangs-Ansicht dargestellt werden:
keine Schaltfläche ist hervorgehoben.
Der bisher rechts sichtbare Abschnitt (globale Variable visible_div_
)
wird verborgen, der neue Abschnitt angezeigt.
Der neue Abschnitt kann entweder der Einzelbild-Abschnitt
oder ein "Geschichten-Abschnitt" sein.
"Geschichten-Abschnitte" sind durch den Attributwert
class
= "section" gekennzeichnet.
Wenn der neu angezeigte Abschnitt ein "Geschichten-Abschnitt" ist,
wird er in der globalen Variablen section_book_
gespeichert.
Dadurch kann ein Klick auf eine Schaltfläche im Einzelbild-Abschnitt
wieder den zuletzt angezeigten "Geschichten-Abschnitt" anzeigen.
Die Funktion update_button
hat
die zuletzt gewählte Schaltfläche als Parameter
oder wird ohne Parameter aufgerufen.
Sie stellt die zuletzt ausgewählte Schaltfläche
(Variable last_button_
) wieder normal dar,
hebt die neu ausgewählte Schaltfläche hervor.
Der automatische Bildlauf ist programmiertechnisch ein Timeout,
d.h. eine Funktion, die nach Ablauf einer Zeitspanne aufgerufen wird
und sich am Ende selbst zeitverzögert aufruft, wenn der Timeout nicht gelöscht ist.
Die globale Variable interout_
enthält die Kennzahl des Timeout.
In einer früheren Version war der Bildlauf ein Timer, also eine Funktion,
die in regelmäßigen Zeitabständen aufgerufen wird.
Ich habe die Implementierung geändert, weil ich mittels Timeout
einfacher eine Änderung des Zeitintervalls verarbeiten kann.
update_button
beendet den Bildlauf.
Ein Mausklick auf einen Verweis auf ein Bild oder auf ein Vorschau-Bild
ruft die Funktion show_img
auf.
Sie nimmt als Parameter die Kennung des anzuzeigenden Bildes.
Die Funktion update_img
setzt das neu ausgewählte Bild
in den Einzelbild-Abschnitt ein,
show_div
zeigt dann den Einzelbild-Abschnitt an.
Die Funktion update_img
wird an allen Stellen aufgerufen,
die ein anderes Bild im Einzelbild-Abschnitt auswählen.
Sie nimmt die Kennung des Bildes als Parameter.
Anhand der Kennung findet sie das Vorschau-Bild-Element
und liest den Pfad zur Bilddatei des Vorschau-Bildes
aus dem Attribut src
.
Den Pfad zur Bilddatei der Normalansicht bestimmt sie,
indem sie das Unterverzeichnis "thumbs
"
durch das Unterverzeichnis ersetzt,
das der ausgewählten Bildgröße (Attribut value
entspricht.
Den Pfad der Normalansicht-Bilddatei und den Inhalt des Attributs
alt
des Vorschau-Bild-Elements
setzt sie in die entsprechenden Stellen des Einzelbild-Abschnitts ein.
Die Funktion add_button_handlers
definiert,
was bei der Auswahl der Schaltflächen im Einzelbild-Abschnitt geschieht.
Sie definiert die Hilfsfunktionen nextImgId
und prevImgId
.
Diese Funktionen gehen vom Vorschau-Bild-Element zum aktuell angezeigten Einzelbild
(globale Variable thumb_
) aus
und ermitteln die Kennung des nächsten bzw. des vorigen Bildes
in der Bildvorschau am Ende des "Geschichten-Abschnitts".
Wenn das aktuelle Bild das letzte bzw. das erste Bild ist,
dann liefern diese Funktionen die Kennung des Bildes am anderen Ende der Reihe.
Die Hilfsfunktionen run_forward
und run_back
sind die Timeout-Funktionen für den automatischen Bildvorlauf bzw. Bildrücklauf.
Die Event-Behandler für die Schaltflächen sind mit den bisherigen Funktionen einfach.
Alle Schaltflächen-Funktionen rufen zunächst die Funktion update_button
auf
und beenden damit den automatischen Bildlauf.
"Text" (button.book
) zeigt den Abschnitt an,
der in der Variablen section_book_
gespeichert ist.
"Bild" (button.image
) macht nichts weiter.
"vor" (button.forestep
) kombiniert die Funktionen
update_img
und nextImgId
,
um das nächste Bild anzuzeigen.
"zurück" (button.backstep
) zeigt das vorhergehende Bild an.
"Vorlauf" ruft run_forward
auf.
"Rücklauf" ruft run_back
auf.
Dieser Abschnitt beschreibt die Datei
imgshow.css
.
Die div
-Elemente teilen sich in vier Klassen
(Attribut class
) auf:
Die ersten beiden Klassen sind der Titel (h1.title
)
und die "Navigationsleiste" (div.navig
) auf der linken Fensterseite.
Der Titel wird in einer Zeile ohne Zeilenwechsel ausgegeben.
Die "Geschichten-Abschnitte" (div.section
)
auf der rechten Fensterseite
entsprechen einem section
-Element
der "Bildergeschichte".
Der "Einzelbild-Abschnitt" gehört als Ausnahme auch zu den "Geschichten-Abschnitten".
Der Einzelbild-Abschnitt folgt nach den gewöhnlichen Geschichten-Abschnitten,
damit er diese überdeckt. So wird am einfachsten verhindert, daß
Außenabstände des Titels die "Knöpfe" überdecken.
Die letzte Klasse bildet die "Knopfleiste" (div.buttons
)
innerhalb des Einzelbild-Abschnitts. Der Innenabstand sorgt für einen
ausreichenden Abstand vom Titel.
Die Schaltflächen im Einzelbild-Abschnitt sind p
-Elemente
(p.button
für "unberührte" Schaltflächen,
p.selected_button
für den zuletzt "gedrückten Knopf").
Der Text der "Knöpfe" wird in doppelte eckige Klammern eingefaßt.
Die Knöpfe werden durch einen "Innenabstand" auf Abstand gehalten.
Der Mauszeiger ändert über einem Knopf seine Form (pointer
),
um anzuzeigen, dass ein Mausklick etwas auslöst.
Die Navigationsleiste ist eine Liste (ul
)
mit einem linken Außenabstand.
Die Listeneinträge (li
)
werden nicht als "list-item
",
sondern als "block
" angezeigt,
also ohne den eingefügten Listeneintrags-Markierer.
Die Eingabefelder werden durch den linken Innenabstand
(Selektor td + td
) von ihrer Bezeichnung
(dem vorangehenden td
-Element) abgesetzt.
Das "Einzelbild" ist ein "float
"-Element, wird also vom Text umflossen.
Allerdings sind die Texte im Einzelbild-Abschnitt
(die Attribute jpg
/@alt
der Bildergeschichte)
so kurz, daß das Umfließen nicht voll zur Geltung kommt.
Die maximale Breite des Bildes im Verhältnis zum enthaltenden
div
-Element wird begrenzt.
Das Perl-Programm, das die Bilddateien für die XHTML-Darstellung erzeugt, muß flexibler gestaltet werden. Es müssen andere Verzeichnisse einzustellen sein. Viel Dokumentation ist zu ergänzen.
Es gibt viele Dinge, die noch zu tun sind.
Die "javascript-URL" gefallen mir nicht. Ich sollte sie durch EventListener ersetzen, die durch das W3C-DOM beschrieben werden.
Die "Bildergeschichte" sollte auch in einer druckfähigen PDF-Version dargestellt werden. Das erfordert detaillierte Einstellungen zu Bildformaten. Die Bildformate zur PDF-Darstellung werden nicht nur das Seitenverhältnis 3:4 haben, sondern auch andere einfache ganzzahlige Seitenverhältnisse sowie das "DIN"-Seitenverhältnis oder das Seitenverhältnis im "Goldenen Schnitt".
Kann Software automatisch erkennen, welche Bildseite "oben" ist, das beste Seitenverhältnis und den besten Bildausschnitt finden, das dargestellte Objekt vom Hintergrund trennen, Beleuchtungsunterschiede korrigieren, durchschnittliche Helligkeiten verschiedener Bilder anpassen, eine geeignete Hintergrundfarbe in die Bilder einsetzen und eine geeignete Hintergrundfarbe für den Hintergrund der Darstellung bestimmen? Und dann noch Bilder gruppieren, die dasselbe Objekt zeigen?
Was machbar ist und was Zukunftsmusik bleibt, wird sich zeigen. Entwicklung braucht Visionen.
<?xml version = "1.0" encoding = "utf-8"?><!-- -*- coding: utf-8 -*- --> <xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns = "http://www.w3.org/1999/xhtml" > <!-- docbook_ht.xsltpat DocBook-Datei als XHTML Anpassungsdatei für die Stylesheets von Norman Walsh Vorlage: $DOCBOOK_XSLTDIR ist durch das Stylesheet-Verzeichnis zu ersetzen 2006-12-31 (C) Herbert Schiemann, mailto:info@herbaer.de unterliegt der GPL Version 2 oder neuer --> <xsl:import href = "file://$DOCBOOK_XSLTDIR/xhtml/docbook.xsl" /> <xsl:template match="filename [@class='directory']"> <a href="{.}"> <xsl:apply-templates/> </a> </xsl:template> </xsl:stylesheet>
#!/bin/bash # -*- coding:utf-8 -*- # docbook_ht XSLTPROC=/usr/bin/xsltproc ; SED=/bin/sed ; RM=/bin/rm ; # Verzeichnis der DocBook-Stylesheets DOCBOOK_XSLTDIR= ; for d in \ /usr/share/xml/docbook/stylesheet/nwalsh \ /usr/share/xml/docbook/stylesheet/docbook-xsl-ns ; do if [[ -d $d ]]; then DOCBOOK_XSLTDIR=$d; break; fi; done; show_version () { cat << .VERSION ; docbook_ht 20061230 erzeugt die XHTML-Darstellung der Beschreibung zu Bilderpräsentation 2006-12-30, Herbert Schiemann, mailto:info@herbaer.de GPL Version 2 oder neuer .VERSION } show_help () { cat << .HELP ; docbook_ht --version docbook_ht --help Alle Einstellungen erfolgen durch Variablen im Kopf der Datei. .HELP } # Argumente verarbeiten if [[ "$#" != "0" ]]; then case "$1" in --version ) show_version ; exit 0 ; ;; --help ) show_version ; show_help ; exit 0; ;; * ) echo "ungültige Option $1" ; show_help ; exit 1; ;; esac ; fi; tempfiles= ; # Aus den RELAX NG-Dateien, die die verwendeten XML-Namensräume beschreiben, # erzeuge ich zunächst DocBook-Dateien, die in das Ergebnis eingebunden werden for file in *.rng ; do base=${file%.rng} ; $XSLTPROC --output $base.ns.dbk rng_dbk.xslt $base.rng ; tempfiles="$tempfiles $base.ns.dbk" ; done; # Von rc - XML-Dateien abhängige Dateien for file in *.rc ; do base=${file%.rc} ; # DocBook-Dateien $XSLTPROC \ --output $base.rc.dbk \ --stringparam rootelem appendix \ --stringparam rootelemid appendix.$base.rc.dbk \ rc_dbk.xslt $base.rc \ ; tempfiles="$tempfiles $base.rc.dbk" ; # XHTML-Dateien $XSLTPROC --output $base.rc.c.xhtml rc_ht_c.xslt $base.rc ; done; # erzeugt aus der Datei imgshow.dbk die Datei imgshow.xhtml if [[ -r imgshow.dbk && -r docbook_ht.xsltpat ]] ; then $SED -e s:\\\$DOCBOOK_XSLTDIR:$DOCBOOK_XSLTDIR: docbook_ht.xsltpat > docbook_ht.xslt ; tempfiles="$tempfiles docbook_ht.xslt" ; $XSLTPROC --xinclude --output imgshow.xhtml \ docbook_ht.xslt imgshow.dbk ; fi ; # DocBook-Includes werden nicht mehr benötigt [ -n "$tempfiles" ] && $RM $tempfiles ;
#! /usr/bin/perl -w # -*- fundamental -*- # ersetzt Großbuchstaben in Dateinamen durch Kleinbuchstaben =pod Wandelt alle Großbuchstaben in Dateinamen eines bestimmten Musters in Kleinbuchstaben =cut my $dir = "orig"; # verarbeitetes Verzeichnis my $pattern = '(?:P|p)[a-zA-Z]*[0-9]+\.(?:ORF|orf)'; # Dateimuster my $verbose = 0; # Umfang der Ausgabe my $recursive = 0; # Unterverzeichnise verarbeiten? my $re_pattern = qr($pattern); process_arg(); -d $dir or do { print "$dir ist kein Verzeichnis\n" if $verbose; exit 1; }; process_dir ($dir); # ein Verzeichnis verarbeiten sub process_dir { my $curdir = shift; # Verzeichnisname my $fn; # Dateiname my $fn_lc; # der Dateiname in Kleinbuchstaben my $filepath; # Dateipfad my $filepath_lc; # der Dateipfad mit Dateinamen in Kleinbuchstaben $curdir =~ s/\/*$//; # abschließende Schrägstriche entfernen opendir (DIR, $curdir) or do { print "Kann Verzeichnis $curdir nicht öffnen: $!\n" if $verbose; return; }; print "Verzeichnis $curdir\n" if $verbose > 1; while ($fn = readdir (DIR)) { next if $fn eq '..' || $fn eq '.'; $filepath = "$curdir/$fn"; -l $filepath and next; # symbolische Links nicht verarbeiten if ($recursive && -d $filepath) { process_dir ($filepath); next; } if ($fn =~ $re_pattern and -f $filepath) { $fn_lc = lc ($fn); next if $fn_lc eq $fn; $filepath_lc = "$curdir/$fn_lc"; -f $filepath_lc and do { print "Datei $filepath_lc existiert bereits.\n" if $verbose; next; }; rename ($filepath, $filepath_lc) or do { print "Kann $filepath nicht in $filepath_lc umbenennen: $!\n" if $verbose; next; }; print "$filepath umbenannt in $filepath_lc\n" if $verbose; } } closedir (DIR); }; # Argumente verarbeiten sub process_arg { my $last = ''; # das vorige Argument my $arg; # das aktuelle Argument while (@ARGV) { $arg = shift @ARGV; $arg eq '--verbose' and do { ++$verbose; next; }; $arg eq '--recursive' and do { $recursive = 1; next; }; $arg eq '--help' and do { version(); help(); exit; }; $arg eq '--version' and do { version (); exit; }; $last eq '--pattern' and do { $pattern = $arg; next; }; $last eq '--dir' and do { $dir = $arg; next; }; $arg =~ /^(--[a-z]+)$/ and do { $last = $1; next; }; print "Unbekanntes Argument $arg\n" if $verbose; exit 1; } } # gibt eine Versionsinformation aus sub version { print <<'VERSION'; fntolower 20061226 Herbert Schiemann, 2006-12-26, mailto:info@herbaer.de VERSION } # zeigt eine kurze Hilfe an sub help { print <<'HELP'; fntolower [--pattern <muster>] [--dir <verzeichnis>] [--recursive] Ersetzt in den Namen gewöhnlicher Dateien im Verzeichnis <verzeichnis>, die zu dem Muster <muster> passen, Großbuchstaben durch Kleinbuchstaben. HELP }
#!/bin/bash # convraw # Konvertiert RAW-Bilddateien in PPM und JPEG # 2006-12-27, Herbert Schiemann <h.schiemann@herbaer.de> # GPL Version 2 oder neuer export PATH="/bin" ; DCRAW="/usr/bin/dcraw -c -6 -w" ; CONVERT="/usr/bin/convert"; g_size=480x480 ; # Ziel-Bildgröße (Maximalwerte in Pixeln) g_qual=70 ; # Kompressionsfaktor ("Qualität") g_prfraw="orig/p" ; # Präfix zur RAW-Datei g_sfxraw=".orf" ; # Suffix zur RAW-Datei g_prfppm="ppm/p" ; # Präfix zur PPM-Datei g_sfxppm=".ppm" ; # Suffix zur PPM-Datei g_prfjpgl="preview/" ; # Präfix zur JPEG-Datei Querformat g_prfjpgp="preview/" ; # Präfix zur JPEG-Datei Hochformat g_sfxjpgl=l.jpg ; # Suffix zur Ausgabedatei Querformat g_sfxjpgp=p.jpg ; # Suffix zur Ausgabedatei Hochformat g_rotl="" ; # Rotation für Querformat: keine g_rotp=270 ; # Rotation für Hochformat: links drehen g_curform=portrait ; # eingestellte Ausrichtung, landscape oder portrait g_verbose=1 ; # Meldungen zum Ablauf # stellt sicher, daß das Verzeichnis existiert # check_dir <prefix> check_dir () { local dir=${1%/*} ; [[ "$1" == "$dir" || -d "$dir" ]] || mkdir $dir ; } show_version () { cat << .VERSION ; convraw 20061230 Konvertiert Bilddateien im RAW-Format in PPM und JPEG-Dateien 2006-12-30, Herbert Schiemann, mailto:info@herbaer.de GPL Version 2 oder neuer .VERSION } show_help () { cat << .HELP ; convraw --version convraw --help Alle Einstellungen erfolgen durch Variablen im Kopf der Datei. .HELP } # process_raw <raw-Dateipfad> process_raw () { local raw=$1 ; local base=${fn#$g_prfraw}; base=${base%$g_sfxraw} ; local ppm=$g_prfppm$base$g_sfxppm ; (( g_verbose )) && echo "$DCRAW $raw > $ppm"; [ -e $ppm ] || $DCRAW $raw > $ppm ; if [[ $g_curform == landscape ]]; then local jpg=$g_prfjpgl$base$g_sfxjpgl ; local jpg_x=$g_prfjpgp$base$g_sfxjpgp ; local rot=$rotl ; elif [[ $g_curform == portrait ]]; then local jpg=$g_prfjpgp$base$g_sfxjpgp ; local jpg_x=$g_prfjpgl$base$g_sfxjpgl ; local rot=$rotp ; fi; (( g_verbose )) && echo "$CONVERT $ppm $rot -resize $g_size -quality $g_qual $jpg"; [ -e $jpg ] || $CONVERT $ppm $rot -resize $g_size -quality $g_qual $jpg ; } # Argumente verarbeiten if [[ "$#" != "0" ]]; then case "$1" in --version ) show_version ; exit 0 ; ;; --help ) show_version ; show_help ; exit 0; ;; * ) echo "ungültige Option $1" ; show_help ; exit 1; ;; esac ; fi; shopt -s nullglob ; # "Null-Globbing" zulassen # Verzeichnisse bei Bedarf erzeugen check_dir $g_prfppm ; check_dir $g_prfjpgl ; check_dir $g_prfjpgp ; for fn in $g_prfraw*$g_sfxraw ; do process_raw $fn; done ;
<?xml version="1.0" encoding="utf-8"?> <?xml-stylesheet href = "imgshow_ht.xslt" type = "text/xsl"?> <document xmlns="http://herbaer.de/xmlns/20061228/imgshow"> <title>Kleider, die die Welt Ende 2006 nicht braucht</title> <section> <title>Miniröcke und Sommer</title> <p> Miniröcke, freie Bäuche (Entschuldigung - ich meine die Körperstelle, wo beim Mann der Bauch ist), Sommer ... Hier der <jpg src="b046827" format="quer" alt="Gruppe in Miniröcken">erste Aufzug</jpg> von links und von <jpg src="b046828" format="quer" alt="Gruppe von rechts">rechts</jpg>. </p> <p> <jpg src="b046829" format="hoch" alt="Edit">Edit</jpg>, hier von <jpg src="b046830" format="hoch" alt="Edit von nahem">nahem</jpg>, trägt ein <jpg src="b046831" format="quer" alt="Edits kariertes Top">kariertes Top</jpg>, einen olivfarbenen <jpg src="b046832" format="quer" alt="Edits olivfarbener Jeans-Minirock">Jeans-Minirock</jpg> und matschfeste <jpg src="b046839" format="quer" alt="Edits silberne Schnür-Stiefelchen">silberne Schnür-Stiefelchen</jpg>, <jpg src="b046833" format="hoch" alt="Dorothee geblümt">Dorothee</jpg> (<jpg src="b046834" format="hoch" alt="Dorothee von nahem">Nahaufnahme</jpg>) einen <jpg src="b046835" format="quer" alt="Dorothees glänzender Minirock">Minirock</jpg> mit Blumenmuster auf metallisch glänzendem Grund, dazu ein rot-blau geblümtes <jpg src="b046836" format="hoch" alt="rot-blau geblümtes Neckholder-Top">Neckholder-Top</jpg> und "höherstellende" fliederfarbene <jpg src="b046840" format="quer" alt="Dorothees fliederfarbene Riemchen-Sandalen">Riemchen-Sandalen</jpg>. Aber in den Sandalen fühlt sie sich nicht richtig wohl. </p> <p> <jpg src="b046837" format="hoch" alt="Josephine im ultrakurzen Jeans-Minirock">Josephine</jpg> trägt ein kurzes, weißes <jpg src="b046838" format="hoch" alt="Josephines weißes Strick-Top">Strick-Top</jpg> mit Schulterträgern zum ultrakurzen, engen Jeans-Minirock. </p> </section> <section> <title>Sportlich</title> <p> Im <jpg src="b046841" format="quer" alt="Miniröcke und sportliche Tops">nächsten</jpg> <jpg src="b046842" format="quer" alt="Miniröcke und sportliche Tops">Aufzug</jpg> erscheint <jpg src="b046843" format="hoch" alt="Edit im schwarzen Minirock und schwarzen Top">Edit</jpg> bis auf die silbernen Stiefelchen ganz in <jpg src="b046844" format="hoch" alt="Edit im schwarzen Minirock und schwarzen Top">Schwarz</jpg> im <jpg src="b046845" format="quer" alt="Edits schwarzer Minirock">Minirock</jpg> mit weißen Seitenstreifen, die hier allerdings nicht gut zu sehen sind, und im sportlichen, eng anliegenden <jpg src="b046846" format="hoch" alt="Edits schwarzes, eng anliegendes Sport-Top">Top</jpg>. <jpg src="b046847" format="hoch" alt="Dorothee im Muster-Minirock und Blumentop">Dorothee</jpg> <jpg src="b046848" format="hoch" alt="Dorothee im Muster-Minirock und Blumentop">trägt</jpg> einen <jpg src="b046849" format="quer" alt="Dorothees Minirock mit Spiral-Muster">Minirock</jpg> im Spiral-Muster in Lila und Grün auf Blau im Stil der 60er Jahre, dazu ein eng anliegendes, geblümtes <jpg src="b046850" format="hoch" alt="Dorothees enges Blumen-Top">Top</jpg>. Und weil sie so süß aussieht, gleich noch ein Bild von <jpg src="b046857" format="hoch" alt="Dorothee im Muster-Minirock und Blumentop">vorn</jpg>. <jpg src="b046851" format="hoch" alt="Josephine weiß-geblümt im kurzen Rock und Träger-Top">Josephine</jpg> fühlt sich sichtlich <jpg src="b046852" format="hoch" alt="Josephine weiß-geblümt im kurzen Rock und Träger-Top von nahem">wohler</jpg> im glänzenden, cremefarbenen, kurzen <jpg src="b046853" format="quer" alt="Josephines glänzender, cremefarbener, kurzer Rock mit Blümchenmuster">Rock</jpg> mit Blümchenmuster und dem weißen <jpg src="b046854" format="hoch" alt="Josephines weißes Spaghettiträger-Top mit Blumenmuster">Top</jpg> mit den bunten Blumen. </p> <p> Edit hat einen <jpg src="b046856" format="hoch" alt="Edit ganz in Schwarz">schwarzen Hut</jpg> aufgesetzt. Bei der <jpg src="b046855" format="hoch" alt="Edit ganz in Schwarz mit Hut ohne Blitzlicht">ersten Aufnahme</jpg> vergaß ich das Blitzlicht. Die unscharfe, lang belichtete Aufnahme wirkt vielleicht gerade deshalb wie im Cabaret. </p> <p> Als professionelle Models mogeln die drei gelegentlich, wenn Ihnen ein Teil zu weit ist, indem sie hinten mit Sicherheitsnadeln oder Wäscheklammern den Stoff raffen. Aber dieser Aufzug steht allen dreien richtig gut. <jpg src="b046858" format="hoch" alt="Edit und Dorothee von hinten">Hier</jpg> sind <jpg src="b046859" format="hoch" alt="Edit von hinten">Edit</jpg> und <jpg src="b046860" format="hoch" alt="Dorothee von hinten">Dorothee</jpg> von <jpg src="b046861" format="quer" alt="Edit und Dorothee von hinten, näher betrachtet">hinten</jpg> zu sehen. </p> </section> <section> <title>Noch mehr Sommer</title> <p> <jpg src="b046862" format="quer" alt="Gruppe in Minröcken und Sommertops">Miniröcke</jpg> müssen wohl <jpg src="b046863" format="quer" alt="Gruppe in Minröcken und Sommertops">total out</jpg> sein. <jpg src="b046866" format="hoch" alt="Edit im Zipfeltop und geblümten, orangefrabenen Minirock">Edit</jpg> trägt flache <jpg src="b046864" format="quer" alt="Edits flache, weiße Schuhe">weiße Schuhe</jpg>, die ihr offenbar etwas weit sind, <jpg src="b046868" format="hoch" alt="Dorothee in Shorts in Rock-Optik">Dorothee</jpg> <jpg src="b046865" format="quer" alt="Dorothees goldglänzende Sandalen mit hohem Absatz">goldglänzende Sandalen</jpg> mit hohem Absatz. Im Eifer des Fotoshootings hat sie doch glatt vergessen, die Riemchen zu schließen? </p> <p> Edit sieht in ihrem orangefarbenen, geblümten, kurzen <jpg src="b046867" format="hoch" alt="Edit im Zipfeltop und geblümten, orangefrabenen Minirock">Rock</jpg> und dem Zipfeltop süß aus, auch <jpg src="b046869" format="hoch" alt="Dorothee im weißen Top und Shorts mit großen Karos">Dorothee</jpg> im weißen Träger-Top und den Shorts mit dem angedeuteten großen Karos. </p> <p> <jpg src="b046870" format="hoch" alt="Josephine im rot-weiß karierten Minirock und weißen Träger-Shirt">Josephine</jpg> ist der rot-weiß karierte Minirock etwas eng. Josephine hat immer Schwierigkeiten mit engen Röcken, aber das weiße <jpg src="b046871" format="hoch" alt="Josephine im rot-weiß karierten Minirock und weißen Träger-Shirt">Träger-Shirt</jpg> steht ihr sehr gut. </p> </section> <section> <title>Und noch mehr Minis</title> <p> Im <jpg src="b046872" format="quer" alt="T-Shirt und Minirock">vierten Aufzug</jpg> wollten die Models <jpg src="b046873" format="quer" alt="T-Shirt und Minirock">Minirock</jpg> und ein farblich passenendes <jpg src="b046874" format="quer" alt="T-Shirt und Minirock">T-Shirt</jpg> kombinieren. <jpg src="b046875" format="hoch" alt="Edit im kurzen blauen Rock und T-Shirt">Edit</jpg> trägt <jpg src="b046876" format="hoch" alt="Edit im kurzen blauen Rock und T-Shirt">Blau</jpg>, <jpg src="b046877" format="hoch" alt="Dorothee im kurzen oliven Rock und Neckholder-Top">Dorothee</jpg> einen olivfarbenen, kurzen Rock und ein <jpg src="b046879" format="hoch" alt="Dorothee im kurzen oliven Rock und Neckholder-Top">Neckholder-Top</jpg>. Sie benutzt zwei Bücher, damit sie in den flachen, <jpg src="b046878" format="quer" alt="Dorothees flache, grüne Sandalen">grünen Sandalen</jpg> stehen kann. Hat Dorothee nicht den Rock von Edit ausgeliehen? <jpg src="b046880" format="hoch" alt="Josephine im glänzenden, grünen, kurzen Rock und weißen T-Shirt">Josephine</jpg> trägt zum glänzenden, grünen Rock ein weißen <jpg src="b046881" format="hoch" alt="Josephine im grünen, kurzen Rock und weißen T-Shirt mit transparenten Streifen">T-Shirt</jpg> mit transparenten Streifen. </p> <p> Die <jpg src="b296882" format="hoch" alt="Puppe aus dem Müll">Kleine</jpg> schaut interessiert zu. Sie lag in einem Müllcontainer. Da mußte ich sie einfach retten. Im Bild sieht es so aus, als ob ihr ein Arm fehlte. Aber sie ist zum Glück ganz gesund und nicht behindert. Wer weiß eine liebe Puppen-Mutti, die mit ihr spielen möchte? </p> </section> <section> <title>Fertig zum Baden</title> <p> <jpg src="c256920" format="quer" alt="Edit, Dorothee und Josephine in Badeanzügen">Hier</jpg> sind die drei Models <jpg src="c256921" format="quer" alt="Edit, Dorothee und Josephine in Badeanzügen">bereit</jpg> zum <jpg src="c256922" format="quer" alt="Edit, Dorothee und Josephine in Badeanzügen">Baden</jpg>. <jpg src="c256923" format="hoch" alt="Edit im schwarzen Badeanzug">Edit</jpg> trägt einen schlichten, schwarzen <jpg src="c256931" format="hoch" alt="Edit im schwarzen Badeanzug">Badeanzug</jpg>, <jpg src="c256924" format="hoch" alt="Dorothee im rot-blau geblümten, rückenfreien Badeanzug">Dorothee</jpg> einen rot-blau geblümten, rückenfreien <jpg src="c256932" format="hoch" alt="Dorothees rot-blau geblümter, rückenfreier Badeanzug">Badeanzug</jpg>, <jpg src="c256925" format="hoch" alt="Josephine im schwarzen Schwimmanzug mit Wickel-Strandrock">Josephine</jpg> einen schwarzen <jpg src="c256933" format="hoch" alt="Josephine im schwarzen Schwimmanzug mit Wickel-Strandrock">Schwimmanzug</jpg> mit einem blau-bunten <jpg src="c256934" format="quer" alt="Josephines blau-bunter Wickel-Strandrock">Wickel-Strandrock</jpg>. Hier zeigt Josephine ihren <jpg src="c256935" format="hoch" alt="Josephines schwarzer Schwimmanzug">Schwimmanzug</jpg> ohne das Röckchen. Die <jpg src="c256936" format="quer" alt="Edit, Dorothee und Josephine in Badeanzügen">drei</jpg> zeigen noch einmal ihre <jpg src="c256937" format="quer" alt="Edits, Dorothees und Josephines Badeanzüge">Badeanzüge</jpg>, bevor sie sich <jpg src="c256938" format="quer" alt="Edit, Dorothee und Josephine in Badeanzügen von hinten">umdrehen</jpg> und ihre <jpg src="c256939" format="quer" alt="Edits, Dorothees und Josephines Badeanzüge von hinten">Rücken</jpg> zeigen. <jpg src="c256940" format="hoch" alt="Edits schwarzer Badeanzug von hinten">Edit</jpg>, <jpg src="c256941" format="hoch" alt="Dorothees bunter, rückenfreier Badeanzug von hinten">Dorothee</jpg> und <jpg src="c256942" format="hoch" alt="Josephines schwarzer Schwimmanzug von hinten">Josephine</jpg> sind in ihren Badeanzügen auch von hinten schön anzusehen. Josephine freut sich besonders über die rutschfesten <jpg src="c256928" format="quer" alt="Josephines rutschfeste Turnschuhe">Turnschuhe</jpg>, in denen sie mit Hilfe von <jpg src="c256929" format="quer" alt="Josephines linker Turnschuh">zwei Brettchen</jpg> sicher <jpg src="c256930" format="quer" alt="Josephines rechter Turnschuh">stehen</jpg> kann. Die Turnschuhe lagen im Dezember in einem Mülleimer auf dem Westenhellweg, Josephines Schwimmanzug und der Wickel-Strandrock lagen am 3. Dezember nach einem Flohmarkt im Müllcontainer. Da müssen auch <jpg src="c256926" format="quer" alt="Josephines schwarze Schuhe">Josephine</jpg> und <jpg src="c256927" format="quer" alt="Dorothees schwarze Schuhe">Dorothee</jpg> ihre Schuhe zeigen. Dorothee kann in vielen Schuhen ohne helfende Keile oder Brettchen stehen, wenn der Absatz nur hoch genug ist. Aber diese Schuhe brauchen einen höheren Absatz. </p> </section> <section> <title>Tanzkleider zur Silvesterparty</title> <p> Zum <jpg src="c266943" format="quer" alt="Edit, Dorothee und Josephine in Tanzkleidern">Jahreswechsel</jpg> wollten die <jpg src="c266944" format="quer" alt="Edit, Dorothee und Josephine in Tanzkleidern">drei</jpg> mir zur Freude <jpg src="c266945" format="quer" alt="Edit, Dorothee und Josephine in Tanzkleidern">Tanzkleider</jpg> tragen. Aber woher nehmen? <jpg src="c266946" format="hoch" alt="Edit im hellblauen Tanzkleid und weißen Anorak">Edit</jpg>, die schlankeste der drei, trägt ein hellblaues <jpg src="c266947" format="hoch" alt="Edit im hellblauen Tanzkleid und weißen Anorak">Tanzkleid</jpg>, das ich am 10. Dezember in Bremen gekauft habe. Das Kleid ist für eine Dame, die Konfektionsgröße 34 bequem tragen kann. Edit, deren Oberweite eher Konfektionsgröße 38 entspricht, kann den Reißverschluß nicht schließen, und will deshalb den weißen <jpg src="c266958" format="hoch" alt="Edits weißer Anorak">Anorak</jpg> darüber nicht ausziehen. Ist das Kleid nicht ein Outfit für eine schlanke, junge Dame zum Rosenmontag? Die braunen <jpg src="c266948" format="quer" alt="Edits braune Stiefeletten">Stiefeletten</jpg>, die Edit zum Tanzkleid trägt, würden zum Rosenmontag passen. Der Anorak lag wie Josephine Schwimmanzug am 3. Dezember in einem Müllcontainer. Alle übrigen bisher gezeigten Teile kommen aus dem Müll nach dem großen Flohmarkt im September in Münster. </p> <p> <jpg src="c266949" format="hoch" alt="Dorothee im Tanzpartykleid mit schwarzem Pailletten-Oberteil und rosa Rüschenrock" >Dorothee</jpg> trägt ein <jpg src="c266950" format="hoch" alt="Dorothees Tanzpartykleid mit schwarzem Pailletten-Oberteil und rosa Rüschenrock" >Tanzpartykleid</jpg> mit einem schwarzen Pailletten-Oberteil und einem rosa Rüschenrock, ebenfalls am 10. Dezember in Bremen gekauft. An die Brustschalen habe ich ein Band angeheftet und im Nacken gebunden, denn das Kleid ist Dorothee etwas groß. Dazu trägt Dorothee diese schwarzen <jpg src="c266953" format="quer" alt="schwarze Schuhe für Dorothee">Schuhe</jpg>. <jpg src="c266951" format="hoch" alt="Josephine im alten rosa Tanzkleid">Josephine</jpg> trägt zum alten rosa <jpg src="c266952" format="hoch" alt="rosa Tanzkleid">Tanzkleid</jpg> von Beatrice diese <jpg src="c266954" format="quer" alt="schwarze Schuhe für Josephine">Schuhe</jpg>. </p> <p> Lebendige Damen könnten sich auf ein Sofa setzen und die Tüllwolken für ein Foto ausbreiten, oder sie könnten sich schwungvoll drehen. Bei den stehenden Puppen <jpg src="c266955" format="hoch" alt="Edit im hellblauen Tanzkleid aus der Dackelsicht">Edit</jpg>, <jpg src="c266956" format="hoch" alt="Dorothee im rosa Tanzpartykleid aus der Dackelsicht">Dorothee</jpg> und <jpg src="c266957" format="quer" alt="Josephine im rosa Tanzkleid aus der Dackelsicht">Josephine</jpg> bleibt mir nur die Dackelperspektive. Diese Tüllwolken muss ich einfach im Bild festhalten. </p> <p> Kurz vor dem Jahreswechsel fielen Edit noch die <jpg src="1016959" format="hoch" alt="Edit hält die Arm-Stulpen zum hellblauen Tanzkleid">Arm-Stulpen</jpg> zum Kleid ein, und <jpg src="1016960" format="hoch" alt="Josephine im alten rosa Tanzkleid mit Einkaufstüte">Josephine</jpg> ihr letzter <jpg src="1016961" format="hoch" alt="Josephine im alten rosa Tanzkleid mit Einkaufstüte">Kosmetik-Einkauf</jpg>. So tritt die <jpg src="1016962" format="quer" alt="Mit Tanzkleidern ins Neue Jahr 2007">Gruppe</jpg> ins <jpg src="1016963" format="quer" alt="Mit Tanzkleidern ins Neue Jahr 2007">neue Jahr 2007</jpg>. </p> </section> <section> <title>Das Wort zum Ende</title> <p> Wenn Ihr Interesse oder auch kein Interesser mehr an irgendwelchen Klamotten habt oder Lust habt, irgendwie zu helfen, wendet Euch an mich: Herbert Schiemann <h.schiemann@@herbaer.de>. Ich brauche Hilfe jeder Art. Irgendjemand kann ganz sicher besser lockere Texte formulieren als ich. Ich zeige hier fast alle Bilder, die ich in zwei Foto-Sessions gemacht habe. Wer kann die besten Bilder für eine gute Präsentation auswählen? </p> </section> </document>
http://herbaer.de/xmlns/20060826/imgshow
Namespace | http://herbaer.de/xmlns/20060826/imgshow |
Wurzelelement | document |
document |
Das XML-Wurzelelement der Bilderpräsentation Enthält: title, section (*) Enthalten in: Wurzel |
title |
Der Titel des Dokuments (Fotopräsentation) oder Abschnitts Enthalten in: document, section |
section |
Ein Abschnitt der Bilderpräsentation. Enthält: title, p (*) Enthalten in: document |
p |
Ein Textabschnitt, der auf Bilder verweisen kann. Enthält: jpg (*) Enthalten in: section |
jpg |
Verweis auf ein Bild Enthält: @src, @alt Enthalten in: p |
@src |
Die Kennung eines Bildes. Aus der Kennung entnehmen verarbeitende Programme den Dateipfad der Bilddatei und Hinweise zum Bildformat und zu einer möglichen Drehung. Zur Zeit hat der letze Buchstabe eine spezielle Bedeutung: 'l' steht für ein Bild mit dem Seitenverhältnis 4:3 (Breitformat), das nicht gedreht werden braucht, 'p' steht für ein Bild mit dem Seitenverhältnis 3:4 (Hochformat), das aus der Original-Bilddatei durch eine Drehung um 270° im Uhrzeigersinn hervorgeht. Enthalten in: jpg |
@alt |
Ein kurzer Text, der das Bild beschreibt. Dieser Text sollte in der normalen Darstellung nicht angezeigt werden, kann aber als Hinweistext ("Tooltip") oder in der Statuszeile eines Web-Browser erscheinen. Enthalten in: jpg |
Die Datei imgshow.rng beschreibt den Namensraum formal:
<?xml version = "1.0" encoding = "utf-8"?><!-- -*- mode: nXML; coding: utf-8; -*- --> <?xml-stylesheet href="rng_ht.xslt" type="text/xsl"?> <!-- file: imgshow.rng Schema für eine Bilderpräsentation "http://herbaer.de/xmlns/20060818/imgshow" 2006-08-26 Herbert Schiemann <h.schiemann@herbaer.de> Bornstr. 107, D-44145 Dortmund, Germany GPL Version 2 Das Schema folgt den folgenden Richtlinien: - Jedes Attribut und jedes Element wird in einem <define>-Element spezifiziert - Jedes <define>-Element spezifiziert höchstens ein Attribut oder Element - Die Namen der Muster ("Pattern"), die ein Attribut spezifizieren, beginnen mit "att_". - Die Namen der Muster, die ein Element spezifizieren, beginnen mit "el_". - Die Dokumentation ist in den define-Elementen enthalten und benutzt DocBook-XML-artige Markierungen des Namensraums http://herbaer.de/xmlns/20051201/doc --> <grammar xmlns = "http://relaxng.org/ns/structure/1.0" xmlns:d = "http://herbaer.de/xmlns/20051201/doc" ns = "http://herbaer.de/xmlns/20060826/imgshow" > <d:title> Ein XML-Format für eine Bilderpräsentation </d:title> <start> <ref name = "el_document"/> </start> <define name = "el_document"> <d:para> Das XML-Wurzelelement der Bilderpräsentation </d:para> <element name = "document"> <interleave> <ref name = "el_title"/> <zeroOrMore> <ref name = "el_section"/> </zeroOrMore> </interleave> </element> </define> <define name = "el_title"> <d:para> Der Titel des Dokuments (Fotopräsentation) oder Abschnitts </d:para> <element name = "title"> <text/> </element> </define> <define name = "el_section"> <d:para> Ein Abschnitt der Bilderpräsentation. </d:para> <element name = "section"> <interleave> <ref name = "el_title"/> <zeroOrMore> <ref name = "el_p"/> </zeroOrMore> </interleave> </element> </define> <define name = "el_p"> <d:para> Ein Textabschnitt, der auf Bilder verweisen kann. </d:para> <element name = "p"> <interleave> <text/> <zeroOrMore> <ref name = "el_jpg"/> </zeroOrMore> </interleave> </element> </define> <define name = "el_jpg"> <d:para> Verweis auf ein Bild </d:para> <element name = "jpg"> <ref name = "att_src"/> <ref name = "att_alt"/> </element> </define> <define name = "att_src"> <d:para> Die Kennung eines Bildes. Aus der Kennung entnehmen verarbeitende Programme den Dateipfad der Bilddatei und Hinweise zum Bildformat und zu einer möglichen Drehung. Zur Zeit hat der letze Buchstabe eine spezielle Bedeutung: 'l' steht für ein Bild mit dem Seitenverhältnis 4:3 (Breitformat), das nicht gedreht werden braucht, 'p' steht für ein Bild mit dem Seitenverhältnis 3:4 (Hochformat), das aus der Original-Bilddatei durch eine Drehung um 270° im Uhrzeigersinn hervorgeht. </d:para> <attribute name = "src"/> </define> <define name = "att_alt"> <d:para> Ein kurzer Text, der das Bild beschreibt. Dieser Text sollte in der normalen Darstellung nicht angezeigt werden, kann aber als Hinweistext ("Tooltip") oder in der Statuszeile eines Web-Browser erscheinen. </d:para> <attribute name = "alt"/> </define> </grammar>
<?xml version = "1.0" encoding = "utf-8"?><!-- -*- XSL; coding: utf-8; -*- --> <!-- file: rng_ht.xslt Informationen aus einem RELAX NG-Schema im XHTML-Format darstellen date: 2005-12-02 (C) 2005 Herbert Schiemann, mailto:info@herbaer.de Bornstr. 107, D-44145 Dortmund, Germany Diese Datei wird unter der GPL verbreitet, s. Datei LICENSE. Jede Gewährleistung ist ausgeschlossen. Das RELAX NG - Schema soll den folgenden Richtlinien entsprechen: - Jedes Attribut und jedes Element wird in einem <define>-Element spezifiziert - Jedes <define>-Element spezifiziert höchstens ein Attribut oder Element - Die Namen der Muster ("Pattern"), die ein Attribut spezifizieren, beginnen mit "att_". - Die Namen der Muster, die ein Element spezifizieren, beginnen mit "el_". - Die Dokumentation ist in den define-Elementen enthalten und benutzt DocBook-XML-artige Markierungen des Namensraums http://herbaer.de/xmlns/20051201/doc --> <xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns:rng = "http://relaxng.org/ns/structure/1.0" xmlns:d = "http://herbaer.de/xmlns/20051201/doc" xmlns = "http://www.w3.org/1999/xhtml" version = "1.0" exclude-result-prefixes = "rng d" > <xsl:output method = "xml" encoding = "utf-8" indent = "yes" /> <!-- Wurzelelement --> <xsl:template match = "/rng:grammar"> <xsl:variable name = "title"> <xsl:choose> <xsl:when test = "d:title"> <xsl:value-of select = "d:title"/> </xsl:when> <xsl:when test = "@ns"> <xsl:text>XML-Namensraum </xsl:text> <xsl:value-of select = "@ns"/> </xsl:when> <xsl:when test = "rng:start/rng:ref/@name"> <xsl:text>XML-Element </xsl:text> <xsl:call-template name = "get_tagname"> <xsl:with-param name = "refname" select = "rng:start/rng:ref/@name"/> </xsl:call-template> </xsl:when> <xsl:otherwise> <xsl:text>RELAX NG grammar</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:variable> <html> <head> <style type = "text/css"> td {vertical-align: top; padding-left: 1em;} </style> <title><xsl:value-of select = "$title"/></title> </head> <body> <h1><xsl:value-of select = "$title"/></h1> <xsl:apply-templates select = "d:para"/> <table> <tbody> <xsl:apply-templates select = "@ns"/> <xsl:apply-templates select = "rng:start"/> <xsl:apply-templates select = "rng:define"/> </tbody> </table> </body> </html> </xsl:template> <d:para> Textabschnitt zur Grammatik (oberste Ebene) </d:para> <xsl:template match = "rng:grammar/d:para"> <p> <xsl:value-of select = "."/> </p> </xsl:template> <d:para> Textabschnitt zu einem Muster </d:para> <xsl:template match = "rng:define/d:para"> <xsl:value-of select = "."/> <br/> </xsl:template> <d:para> Der Namensraum </d:para> <xsl:template match = "rng:grammar/@ns"> <tr> <td>Namespace</td> <td> <xsl:value-of select = "."/> </td> </tr> </xsl:template> <d:para> Das spezifizierte Wurzelelement </d:para> <xsl:template match = "rng:start"> <xsl:variable name = "name" select = "rng:ref/@name [1]"/> <tr> <td>Wurzelelement</td> <td> <a href = "#tr.{$name}"> <xsl:call-template name = "get_tagname"> <xsl:with-param name = "refname" select = "$name"/> </xsl:call-template> </a> </td> </tr> </xsl:template> <d:para> Ein Eintrag zu einem Muster </d:para> <xsl:template match = "rng:define"> <xsl:variable name = "name" select = "@name"/> <tr id = "tr.{@name}"> <td> <xsl:call-template name = "get_tagname"> <xsl:with-param name = "refname" select = "$name"/> </xsl:call-template> </td> <td> <xsl:apply-templates select = "d:para"/> <xsl:if test = ".//rng:ref"> <em class = "legend">Enthält: </em> <xsl:apply-templates select = ".//rng:ref"/> <br/> </xsl:if> <xsl:if test = "//rng:ref [@name = $name]"> <em class = "legend">Enthalten in: </em> <xsl:apply-templates select = "//rng:ref [@name = $name]" mode = "container"/> </xsl:if> </td> </tr> </xsl:template> <d:section> <d:para> Ein Muster in der Liste der Muster, die in einem anderen Muster enthalten sind. Die in Klammern hinten angefügten Zeichen bedeuten: </d:para> <d:itemizedlist> <d:listitem> <d:para> *: das Element kann beliebig oft vorkommen </d:para> </d:listitem> <d:listitem> <d:para> +: das Element kann mehrfach vorkommen </d:para> </d:listitem> <d:listitem> <d:para> ?: das Element oder Attribut ist optional </d:para> </d:listitem> <d:listitem> <d:para> |: das Element oder Attribut ist in einer Auswahl enthalten </d:para> </d:listitem> </d:itemizedlist> </d:section> <xsl:template match = "rng:ref"> <xsl:if test = "position() > 1"> <xsl:text>, </xsl:text> </xsl:if> <a href = "#tr.{@name}"> <xsl:call-template name = "get_tagname"> <xsl:with-param name = "refname" select = "@name"/> </xsl:call-template> </a> <xsl:choose> <xsl:when test = "ancestor::rng:zeroOrMore"> <xsl:text> (*)</xsl:text> </xsl:when> <xsl:when test = "ancestor::rng:oneOrMore"> <xsl:text> (+)</xsl:text> </xsl:when> <xsl:when test = "ancestor::rng:optional"> <xsl:text> (?)</xsl:text> </xsl:when> <xsl:when test = "ancestor::rng:choice"> <xsl:text> (|)</xsl:text> </xsl:when> <xsl:otherwise/> </xsl:choose> </xsl:template> <d:para> Liste der Muster, die ein bestimmtes Muster enthalten </d:para> <xsl:template match = "rng:ref" mode = "container"> <xsl:if test = "position() > 1"> <xsl:text>, </xsl:text> </xsl:if> <xsl:choose> <xsl:when test = "ancestor::rng:start"> <xsl:text>Wurzel</xsl:text> </xsl:when> <xsl:otherwise> <xsl:for-each select = "ancestor::rng:define"> <a href = "#tr.{@name}"> <xsl:call-template name = "get_tagname"> <xsl:with-param name = "refname" select = "@name"/> </xsl:call-template> </a> </xsl:for-each> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- Hilfsvorlagen --> <!-- get_tagname --> <d:section> <d:para> Der Name des Elements oder Attributs, das in einem RNG-Muster (<d:sgmltag class="namespace">rng</d:sgmltag>:<d:sgmltag class="element">define</d:sgmltag>) spezifiziert wird. </d:para> <d:itemizedlist> <d:listitem> <d:para> wenn das Muster ein Element spezifiziert, der Name des Elements </d:para> </d:listitem> <d:listitem> <d:para> wenn das Muster ein Attribut spezifiziert, der Name des Attributs mit einem vorangstellten "@"-Zeichen </d:para> </d:listitem> <d:listitem> <d:para> andernfalls der Name des Musters (<d:sgmltag class="namespace">rng</d:sgmltag>:<d:sgmltag class="element" >define</d:sgmltag>/@<d:sgmltag class = "attribute">name</d:sgmltag>) in Klammern </d:para> </d:listitem> </d:itemizedlist> </d:section> <xsl:template name = "get_tagname"> <xsl:param name = "refname"/> <xsl:choose> <xsl:when test = "string-length ($refname) = 0"/> <xsl:when test = "/rng:grammar/rng:define [@name = $refname]//rng:element"> <xsl:value-of select = "/rng:grammar/rng:define [@name = $refname]//rng:element/@name"/> </xsl:when> <xsl:when test = "/rng:grammar/rng:define [@name = $refname]//rng:attribute"> <xsl:text>@</xsl:text> <xsl:value-of select = "/rng:grammar/rng:define [@name = $refname]//rng:attribute/@name"/> </xsl:when> <xsl:otherwise> <xsl:text>(</xsl:text> <xsl:value-of select = "$refname"/> <xsl:text>)</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:template> </xsl:stylesheet>
<?xml version = "1.0" encoding = "utf-8"?><!-- -*- coding:utf-8 -*- --> <!-- Ad hoc: XML-Markup zur Speicherung von Konfigurationseinstellungen 2006-12-28, Herbert Schiemann <h.schiemann@herbaer.de> GPL Version 2 oder neuer --> <?xml-stylesheet href = "rc_ht_c.xslt" type = "text/xsl"?> <rc xmlns = "http://herbaer.de/xmlns/20060818/rc"> <!-- d ist in jedem Element möglich, das direkt keinen Text enthält Das Element enthält beliebigen Inhalt zur Dokumentation. In dieser Datei sind drei verschiedene Dinge dokumentiert: XML-Kommentare dokumentieren die XML-Elemente, d-Elemente dokumentieren die "Schlüssel", die durch das verarbeitende Programm vorgegeben sind, a-Elemente dokumentieren die speziellen Einstellungen. --> <!-- Das erste d-Element auf der obersten Ebene dient als Titel --> <d>Bilddateien erzeugen: Einstellungen</d> <d> Einstellungen für das Perl-Programm generate_images.pl, das Web-geignete Bildformate erzeugt. </d> <!-- Das Element e enthält einen Eintrag. Es entspricht einer Zeile in einer konventionellen Konfigurationsdatei Das erforderliche Attribut n enthält einen Schlüssel, unter dem das Perl-Programm (oder ein Programm in einer anderen Programmiersprache) auf den Wert zugreifen kann. Es enhält das optionale Element v (Wert), das optionale Element t (Typ des Wertes) und normalerweise ein Element d zur Beschreibung --> <e n = "dir"> <d> Das Verzeichnis, das die Bildergeschichten enthält. In diesem Verzeichnis (oder bei einem entsprechenden Präfix in einem Unterverzeichnis) werden auch die Bilddateien angelegt. Der Default-Wert ist 'story' </d> <!-- Das Element v enthält einen Wert (Text) --> <v>story</v> </e> <e n = "filepattern"> <d> Regulärer Ausdruck, der die Dateinamen der Bildergeschichten beschreibt. Der Default-Wert ist '.xml$' </d> <v>.xml$</v> </e> <e n = "srcdir"> <d> Diese Verzeicnis enthält die Quell-Bilddateien, die das allgemeine Konvertierungsprogramm (ImageMagick oder GraphicMagick) verarbeiten kann, z.B. PPM-Dateien </d> <v>.</v> </e> <e n = "source_prf"> <d>Präfix für den Dateipfad der Bilddatei, aus der die JPEG-Dateien erzeugt werden</d> <v>ppm/p</v> </e> <e n = "source_sfx"> <d>Suffix für den Dateipfad der Bilddatei, aus der die JPEG-Dateien erzeugt werden</d> <v>.ppm</v> </e> <!-- Das Element g gruppiert Konfigurationseinstellungen. Es kann g- und e-Elemente enthalten. --> <g n = "imgtypes"> <d> Dieser Eintrag enthält Einstellungen zu verschiedenen Ergebnis-Bildtypen. Jeder Ergebnis-Bildtyp entspricht einem g-Element in diesem Eintrag. Die Namen (Attribut n) können beliebig gewählt werden. Der Eintrag zu jedem Bildtyp enthält wiederum g-Elemente, die den verschiedenen Bildformaten (hier "quer" für Querformat und "hoch" für "Hochformat") entsprechen. </d> <g n = "view"> <!-- Das Element a (Anmerkung) dient ebenso wie das Element d zur Dokumentation. Während d erklärt, was der Schlüssel bedeutet, was die möglichen Werte sind, was der Default-Wert ist, also das, was durch das verarbeitende Programm bestimmt ist, erklärt a den Wert, erläutert also die spezielle Einstellung. --> <a>Normalansicht</a> <g n = "quer"> <a>Querformat</a> <e n = "pfx"> <d>Präfix des Dateipfads der Ergebnis-Bilddatei</d> <v>images/</v> </e> <e n = "sfx"> <d>Suffix des Dateipfads der Ergebnis-Bilddatei</d> <v>.jpg</v> </e> <e n = "rotation"> <d> Drehung des Bildes, mögliche Werte 0 (keine Drehung), 90 (nach rechts gedreht), 180 (auf dem Kopf), 270 (nach links gedreht) </d> <v>0</v> </e> <e n = "size"> <d> Die Größe des transformierten Bildes im Format (breite)x(hoehe) Die Breite und die Höhe sind die Anzahl der Bildpunkte. Das Bild wird gestaucht oder gestreckt, wenn das Verhältnis nicht mit dem Seitenverhältnis des Originalbildes übereinstimmt. </d> <v>1440x1080</v> </e> <e n = "quality"> <d> Diese Zahl im Bereich von 1 bis 100 bestimmt die JPG-Kompression. Höhere Zahlen bedeuten ein bessere Bildqualität und entsprechend größere Bilddateien. Ohne Angabe gilt die Voreinstellung des Befehls convert. </d> </e> </g> <g n = "hoch"> <a>Hochformat</a> <e n = "pfx"> <v>images/</v> </e> <e n = "sfx"> <v>.jpg</v> </e> <e n = "rotation"> <v>270</v> </e> <e n = "size"> <v>810x1080</v> </e> </g> </g> <g n = "thumb"> <a>Vorschaubilder</a> <g n = "quer"> <a>Querformat</a> <e n = "pfx"> <v>thumbs/</v> </e> <e n = "sfx"> <v>.jpg</v> </e> <e n = "size"> <v>96x72</v> </e> </g> <g n = "hoch"> <a>Hochformat</a> <e n = "pfx"> <v>thumbs/</v> </e> <e n = "sfx"> <v>.jpg</v> </e> <e n = "rotation"> <v>270</v> </e> <e n = "size"> <v>72x96</v> </e> </g> </g> <g n = "smallimg"> <a>Kleine Bilder für Notebooks</a> <g n = "quer"> <a>Querformat</a> <e n = "pfx"> <v>smallimg/</v> </e> <e n = "sfx"> <v>.jpg</v> </e> <e n = "size"> <v>960x720</v> </e> </g> <g n = "hoch"> <a>Hochformat</a> <e n = "pfx"> <v>smallimg/</v> </e> <e n = "sfx"> <v>.jpg</v> </e> <e n = "rotation"> <v>270</v> </e> <e n = "size"> <v>540x720</v> </e> </g> </g> </g> </rc>
Namespace | http://herbaer.de/xmlns/20060818/rc |
Wurzelelement | rc |
@n |
Dieses Attribut identifiziert ein Element innerhalb seines Vaters Enthalten in: e, g |
d |
Beliebieger Inhalt zur Dokumentation der Schlüssel Enthalten in: e, g, rc |
a |
Beliebiger Inhalt zur Dokumentation der eingestellten Werte Enthalten in: e, g, rc |
v |
Der Wert eines Konfigurationsparameters Enthalten in: e |
e |
Ein Konfigurationsparameter mit Erläuterungen Enthält: @n, a (*), d (*), v Enthalten in: g, rc |
g |
Eine Gruppe von Konfigurationsparametern, die unter einem Schlüssel zusammengefaßt sind Enthält: @n, a (*), d (*), e (+), g (+) Enthalten in: g, rc |
rc |
Konfigurationseinstellungen, die als Baumstruktur von Schlüsseln mit Werten in den "Blättern" dargestellt werden. Enthält: a (*), d (*), e (+), g (+) Enthalten in: Wurzel |
Die Datei rc.rng beschreibt den Namensraum formal:
<?xml version = "1.0" encoding = "utf-8"?><!-- -*- mode: nXML; coding: utf-8; -*- --> <?xml-stylesheet href="rng_ht.xslt" type="text/xsl"?> <!-- file: rc.rng Schema für Konfigurationseinstellungen "http://herbaer.de/xmlns/20060818/rc" date: 2006-08-26 (C) 2006 Herbert Schiemann, mailto:info@herbaer.de Bornstr. 107, D-44145 Dortmund, Germany Diese Datei wird unter der GPL verbreitet, s. Datei LICENSE. Jede Gewährleistung ist ausgeschlossen. Das Schema folgt den folgenden Richtlinien: - Jedes Attribut und jedes Element wird in einem <define>-Element spezifiziert - Jedes <define>-Element spezifiziert höchstens ein Attribut oder Element - Die Namen der Muster ("Pattern"), die ein Attribut spezifizieren, beginnen mit "att_". - Die Namen der Muster, die ein Element spezifizieren, beginnen mit "el_". - Die Dokumentation ist in den define-Elementen enthalten und benutzt DocBook-XML-artige Markierungen des Namensraums http://herbaer.de/xmlns/20051201/doc --> <grammar xmlns = "http://relaxng.org/ns/structure/1.0" xmlns:d = "http://herbaer.de/xmlns/20051201/doc" ns = "http://herbaer.de/xmlns/20060818/rc" > <d:title> Ein XML-Format für Konfigurationseinstellungen </d:title> <start> <ref name = "el_rc"/> </start> <define name = "att_n"> <d:para> Dieses Attribut identifiziert ein Element innerhalb seines Vaters </d:para> <attribute name = "n"/> </define> <define name = "el_d"> <d:para> Beliebieger Inhalt zur Dokumentation der Schlüssel </d:para> <element name = "d"> <text/> </element> </define> <define name = "el_a"> <d:para> Beliebiger Inhalt zur Dokumentation der eingestellten Werte </d:para> <element name = "a"> <text/> </element> </define> <define name = "el_v"> <d:para> Der Wert eines Konfigurationsparameters </d:para> <element name = "v"> <text/> </element> </define> <define name = "el_e"> <d:para> Ein Konfigurationsparameter mit Erläuterungen </d:para> <element name = "e"> <ref name = "att_n"/> <interleave> <zeroOrMore> <ref name = "el_a"/> </zeroOrMore> <zeroOrMore> <ref name = "el_d"/> </zeroOrMore> <ref name = "el_v"/> </interleave> </element> </define> <define name = "el_g"> <d:para> Eine Gruppe von Konfigurationsparametern, die unter einem Schlüssel zusammengefaßt sind </d:para> <element name = "g"> <ref name = "att_n"/> <interleave> <zeroOrMore> <ref name = "el_a"/> </zeroOrMore> <zeroOrMore> <ref name = "el_d"/> </zeroOrMore> <oneOrMore> <choice> <ref name = "el_e"/> <ref name = "el_g"/> </choice> </oneOrMore> </interleave> </element> </define> <define name = "el_rc"> <d:para> Konfigurationseinstellungen, die als Baumstruktur von Schlüsseln mit Werten in den "Blättern" dargestellt werden. </d:para> <element name = "rc"> <interleave> <zeroOrMore> <ref name = "el_a"/> </zeroOrMore> <zeroOrMore> <ref name = "el_d"/> </zeroOrMore> <oneOrMore> <choice> <ref name = "el_e"/> <ref name = "el_g"/> </choice> </oneOrMore> </interleave> </element> </define> </grammar>
<?xml version = "1.0" encoding = "utf-8"?><!-- -*- coding: utf-8 -*- --> <xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns:rc = "http://herbaer.de/xmlns/20060818/rc" xmlns = "http://www.w3.org/1999/xhtml" exclude-result-prefixes="rc" > <!-- rc_ht.xslt rc-XML-Datei als XHTML 2006-08-26 (C) Herbert Schiemann, mailto:info@herbaer.de unterliegt der GPL Version 2 oder neuer --> <xsl:output method="xml" encoding="UTF-8" indent="yes"/> <xsl:template match = "rc:rc"> <xsl:variable name = "title"> <xsl:choose> <xsl:when test = "rc:d | rc:a"> <xsl:value-of select = "(rc:d | rc:a) [1]"/> </xsl:when> <xsl:otherwise> <xsl:text>Konfiguration</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:variable> <html> <head> <title><xsl:value-of select = "$title"/></title> <style type = "text/css"> div {margin-left: 5%;} td {padding-left: 1em; vertical-align: top;} td.name, td.value {font-family: monospace;} td.value {font-style: italic;} h2 {font-size: 100%; font-weight: bold; font-family: sans-serif;} div.c0 > h2 {font-size: 144%; } div.c1 > h2 {font-size: 120%; } </style> </head> <body> <h1><xsl:value-of select = "$title"/></h1> <xsl:apply-templates select = "rc:* [(local-name() != 'a' and local-name() != 'd') or position() > 1]"> <xsl:with-param name = "nestlevel" select = "0"/> </xsl:apply-templates> </body> </html> </xsl:template> <!-- aufeinanderfolgende Werte als Tabelle --> <xsl:template match = "rc:e"> <xsl:if test = "not (local-name (preceding-sibling::rc:* [1]) = 'e')"> <table> <tbody> <xsl:apply-templates select = "." mode = "tr"/> </tbody> </table> </xsl:if> </xsl:template> <!-- Wert als Tabelleneintrag --> <xsl:template match = "rc:e" mode = "tr"> <tr> <td class = "name"> <xsl:value-of select = "@n"/> </td> <td class = "value"><xsl:apply-templates select = "rc:v"/> </td> <td class = "doc"> <xsl:apply-templates select = "rc:a | rc:d"/> </td> </tr> <xsl:apply-templates select = "following-sibling::rc:* [1] [local-name() = 'e']" mode = "tr" /> </xsl:template> <!-- Dokumentation zu Werten --> <xsl:template match = "rc:e/rc:a | rc:e/rc:d" > <xsl:if test = "position() > 1"> <br/> </xsl:if> <span class = "{local-name(.)}"><xsl:value-of select = "."/></span> </xsl:template> <!-- Gruppen --> <xsl:template match = "rc:g"> <xsl:param name = "nestlevel" select = "0"/> <xsl:variable name = "shortdoc"> <xsl:value-of select = "rc:* [1][(local-name () = 'a' or local-name () = 'd') and string-length (.) < 50]"/> </xsl:variable> <div class = "c{$nestlevel}"> <h2> <xsl:value-of select = "@n"/> <xsl:if test = "string-length ($shortdoc) != 0"> <xsl:text> (</xsl:text> <xsl:value-of select = "$shortdoc"/> <xsl:text>)</xsl:text> </xsl:if> </h2> <xsl:apply-templates select = "rc:* [string-length ($shortdoc) = 0 or position () != 1]"> <xsl:with-param name = "nestlevel" select = "$nestlevel + 1"/> </xsl:apply-templates> </div> </xsl:template> <!-- Dokumentation zu Gruppen --> <xsl:template match = "rc:a | rc:d" > <p class = "{local-name(.)}"><xsl:value-of select = "."/></p> </xsl:template> </xsl:stylesheet>
<?xml version = "1.0" encoding = "utf-8"?><!-- -*- coding: utf-8 -*- --> <xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns:rc = "http://herbaer.de/xmlns/20060818/rc" xmlns = "http://www.w3.org/1999/xhtml" exclude-result-prefixes="rc" > <!-- rc_ht_c.xslt rc-XML-Datei als XHTML in Tabellenform 2006-08-26 (C) Herbert Schiemann, mailto:info@herbaer.de unterliegt der GPL Version 2 oder neuer --> <xsl:output method="xml" encoding="UTF-8" indent="yes"/> <xsl:template match = "rc:rc"> <xsl:variable name = "title"> <xsl:choose> <xsl:when test = "rc:d | rc:a"> <xsl:value-of select = "(rc:d | rc:a) [1]"/> </xsl:when> <xsl:otherwise> <xsl:text>Konfiguration></xsl:text> </xsl:otherwise> </xsl:choose> </xsl:variable> <html> <head> <title><xsl:value-of select = "$title"/></title> <style type = "text/css"> td {padding-top: 0.5em; padding-left: 1em; vertical-align: top; } td.name {font-family: monospace; line-height: 1.5; } span.value {font-family: nonospace; font-style: italic; line-height: 1.5; } </style> </head> <body> <h1><xsl:value-of select = "$title"/></h1> <xsl:apply-templates select = "rc:a | rc:d [position() > 1]"/> <xsl:if test = "(rc:e | rc:g) [1]"> <table> <tbody> <xsl:apply-templates select = "rc:e | rc:g"/> </tbody> </table> </xsl:if> </body> </html> </xsl:template> <!-- ein einzelner Wert --> <xsl:template match = "rc:e"> <xsl:param name = "prf" select = "''"/> <tr> <td class = "name"> <xsl:value-of select = "concat ($prf, @n)"/> </td> <td class = "value"> <span class = "value"><xsl:apply-templates select = "rc:v"/></span> <xsl:if test = "rc:a | rc:d"> <br/> <xsl:apply-templates select = "rc:a | rc:d"/> </xsl:if> </td> </tr> </xsl:template> <!-- Gruppen --> <xsl:template match = "rc:g"> <xsl:param name = "prf" select = "''"/> <tr> <td class = "name"> <xsl:value-of select = "concat ($prf, @n)"/> </td> <td class = "doc"> <xsl:apply-templates select = "rc:a | rc:d"/> </td> </tr> <xsl:apply-templates select = "rc:e | rc:g"> <xsl:with-param name = "prf" select = "concat ($prf, @n, '::')"/> </xsl:apply-templates> </xsl:template> <!-- Toplevel-Dokumentation --> <xsl:template match = "rc:rc/rc:a | rc:rc/rc:d" > <p class = "{local-name(.)}"><xsl:value-of select = "."/></p> </xsl:template> <!-- Dokumentation zu Gruppen und Werten --> <xsl:template match = "rc:a | rc:d" > <xsl:if test = "position() > 1"> <br/> </xsl:if> <span class = "{local-name(.)}"><xsl:value-of select = "."/></span> </xsl:template> </xsl:stylesheet>
<?xml version = "1.0" encoding = "utf-8"?><!-- -*- coding: utf-8 -*- --> <!-- rc_dbk.xslt rc-XML-Datei als DocBook-Tabelle 2006-09-20 (C) Herbert Schiemann, mailto:info@herbaer.de unterliegt der GPL Version 2 oder neuer --> <xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns:rc = "http://herbaer.de/xmlns/20060818/rc" xmlns = "http://docbook.org/ns/docbook" exclude-result-prefixes="rc" > <!-- der Name des erzeugten DocBook - Elements --> <xsl:param name = "rootelem" select = "'section'"/> <!-- die ID des erzeugten Elements --> <xsl:param name = "rootelemid"/> <xsl:output method="xml" encoding="UTF-8" indent="yes"/> <xsl:template match = "rc:rc"> <xsl:variable name = "title"> <xsl:choose> <xsl:when test = "rc:d | rc:a"> <xsl:value-of select = "(rc:d | rc:a) [1]"/> </xsl:when> <xsl:otherwise> <xsl:text>Konfiguration></xsl:text> </xsl:otherwise> </xsl:choose> </xsl:variable> <xsl:element name = "{$rootelem}"> <xsl:if test = "string-length ($rootelemid) > 0"> <xsl:attribute name = "id"> <xsl:value-of select = "$rootelemid"/> </xsl:attribute> </xsl:if> <title><xsl:value-of select = "$title"/></title> <xsl:apply-templates select = "rc:a | rc:d [position() > 1]" mode = "para"/> <xsl:if test = "(rc:e | rc:g) [1]"> <informaltable colsep = "0" frame = "none" rowsep = "0"> <tgroup cols = "2"> <tbody valign = "top"> <xsl:apply-templates select = "rc:e | rc:g"/> </tbody> </tgroup> </informaltable> </xsl:if> </xsl:element> <xsl:comment> Local Variables: mode: nXML coding: utf-8 End: </xsl:comment> </xsl:template> <!-- ein einzelner Eintrag --> <xsl:template match = "rc:e"> <xsl:param name = "prf" select = "''"/> <row> <entry><literal><xsl:value-of select = "concat ($prf, @n)"/></literal></entry> <entry> <xsl:choose> <xsl:when test = "rc:a | rc:d"> <para><xsl:apply-templates select = "rc:v"/></para> <xsl:apply-templates select = "rc:a | rc:d"/> </xsl:when> <xsl:otherwise> <xsl:apply-templates select = "rc:v"/> </xsl:otherwise> </xsl:choose> </entry> </row> </xsl:template> <!-- Gruppen --> <xsl:template match = "rc:g"> <xsl:param name = "prf" select = "''"/> <row> <entry><literal><xsl:value-of select = "concat ($prf, @n)"/></literal></entry> <entry> <xsl:apply-templates select = "rc:a | rc:d"/> </entry> </row> <xsl:apply-templates select = "rc:e | rc:g"> <xsl:with-param name = "prf" select = "concat ($prf, @n, '::')"/> </xsl:apply-templates> </xsl:template> <!-- Dokumentation zu Gruppen und Werten --> <xsl:template match = "rc:a | rc:d"> <para><xsl:value-of select = "."/></para> </xsl:template> <!-- ein Wert --> <xsl:template match = "rc:v"> <replaceable><xsl:value-of select = "."/></replaceable> </xsl:template> </xsl:stylesheet>
#! /usr/bin/perl -w # Herbaer/ConfigReader.pm # liest eine Konfigurationsdatei im XML-Format "http://herbaer.de/20060818/rc" package Herbaer::ConfigReader; use strict; use warnings; use XML::SAX::ParserFactory ; use Fcntl ; # wg O_RDONLY BEGIN { use Exporter (); our $VERSION = 0.1 ; our @ISA = qw(Exporter); our @EXPORT = qw(&read_config_filename); our @EXPORT_OK = qw(&read_config_filename); our %EXPORT_TAGS = (); } =pod Diese Klasse ist ein SAX-Handler. Datenmodell configdata die gelesenen Konfigurationsdaten stack Stack der "Hashes" im Laufe der Verarbeitung der XML-Datei curhash der aktuelle "Hash" im Laufe der XML-Verarbeitung curval der aktuelle "Wert" readval 1, wenn ein Wert gelesen wird, sonst 0 =cut sub new { my $class = shift; $class = ref($class) || $class; my $self = {}; $self -> {'configdata'} = {}; return bless ($self, $class); } # new sub get_configdata { my $self = shift; return $self -> {'configdata'}; } # get_configdata # SAX Handler sub start_document { my $self = shift; $self -> {'stack'} = []; $self -> {'curhash'} = $self -> {'configdata'}; $self -> {'curval'} = 0; $self -> {'readval'} = 0; } # start_document sub end_document { my $self = shift; delete $self -> {'stack'}; delete $self -> {'curhash'}; delete $self -> {'curval'}; delete $self -> {'readval'}; } # end_document sub start_element { my ($self, $el) = @_; my $ln = $el -> {'LocalName'}; # Anfang einer neuen Gruppe if ($ln eq 'g') { my $stack = $self -> {'stack'}; my $curhash = $self -> {'curhash'}; my $newhash = {}; $curhash -> {$el -> {'Attributes'} -> {'{}n'} -> {'Value'}} = $newhash; push @$stack, $curhash; $self -> {'curhash'} = $newhash; } # Anfang eines Wertes elsif ($ln eq 'e') { $self -> {'curval'} = \$self -> {'curhash'} -> {$el -> {'Attributes'} -> {'{}n'} -> {'Value'}}; } # ein Wert elsif ($ln eq 'v') { $self -> {'readval'} = 1; } } # start_element sub end_element { my ($self, $el) = @_; my $ln = $el -> {'LocalName'}; # Ende einer Gruppe if ($ln eq 'g') { my $stack = $self -> {'stack'}; $self -> {'curhash'} = pop @$stack; } # Ende eines Wertes elsif ($ln eq 'v') { $self -> {'readval'} = 0; } } # end_element sub characters { my ($self, $txt) = @_; if ($self -> {'readval'}) { my $curval = $self -> {'curval'}; $$curval .= $txt -> {'Data'}; } } # characters =pod liest eine Konfigurationsdatei im XML-Format und liefert die Daten als Hash-Referenz fn_xmlinput Dateipfad der XML-Datei (Konfigurationseinstellungen) =cut sub read_config_filename { my $fn_xml = shift; my $fh; # Dateihandle der XML-Eingabe sysopen ($fh, $fn_xml, O_RDONLY) or do { print "Kann Datei $fn_xml nicht öffnen: $!\n"; return; }; my $handler = new Herbaer::ConfigReader; my $parser = XML::SAX::ParserFactory -> parser (Handler => $handler); $parser -> parse_file ($fh); close ($fh); return $handler -> get_configdata (); } 1;
dir |
Das Verzeichnis, das die Bildergeschichten enthält. In diesem Verzeichnis (oder bei einem entsprechenden Präfix in einem Unterverzeichnis) werden auch die Bilddateien angelegt. Der Default-Wert ist 'story' |
filepattern |
Regulärer Ausdruck, der die Dateinamen der Bildergeschichten beschreibt. Der Default-Wert ist '.xml$' |
srcdir |
Diese Verzeicnis enthält die Quell-Bilddateien, die das allgemeine Konvertierungsprogramm (ImageMagick oder GraphicMagick) verarbeiten kann, z.B. PPM-Dateien |
source_prf |
Präfix für den Dateipfad der Bilddatei, aus der die JPEG-Dateien erzeugt werden |
source_sfx |
Suffix für den Dateipfad der Bilddatei, aus der die JPEG-Dateien erzeugt werden |
imgtypes | Dieser Eintrag enthält Einstellungen zu verschiedenen Ergebnis-Bildtypen. Jeder Ergebnis-Bildtyp entspricht einem g-Element in diesem Eintrag. Die Namen (Attribut n) können beliebig gewählt werden. Der Eintrag zu jedem Bildtyp enthält wiederum g-Elemente, die den verschiedenen Bildformaten (hier "quer" für Querformat und "hoch" für "Hochformat") entsprechen. |
imgtypes::view | Normalansicht |
imgtypes::view::quer | Querformat |
imgtypes::view::quer::pfx |
Präfix des Dateipfads der Ergebnis-Bilddatei |
imgtypes::view::quer::sfx |
Suffix des Dateipfads der Ergebnis-Bilddatei |
imgtypes::view::quer::rotation |
Drehung des Bildes, mögliche Werte 0 (keine Drehung), 90 (nach rechts gedreht), 180 (auf dem Kopf), 270 (nach links gedreht) |
imgtypes::view::quer::size |
Die Größe des transformierten Bildes im Format (breite)x(hoehe) Die Breite und die Höhe sind die Anzahl der Bildpunkte. Das Bild wird gestaucht oder gestreckt, wenn das Verhältnis nicht mit dem Seitenverhältnis des Originalbildes übereinstimmt. |
imgtypes::view::quer::quality | Diese Zahl im Bereich von 1 bis 100 bestimmt die JPG-Kompression. Höhere Zahlen bedeuten ein bessere Bildqualität und entsprechend größere Bilddateien. Ohne Angabe gilt die Voreinstellung des Befehls convert. |
imgtypes::view::hoch | Hochformat |
imgtypes::view::hoch::pfx | images/ |
imgtypes::view::hoch::sfx | .jpg |
imgtypes::view::hoch::rotation | 270 |
imgtypes::view::hoch::size | 810x1080 |
imgtypes::thumb | Vorschaubilder |
imgtypes::thumb::quer | Querformat |
imgtypes::thumb::quer::pfx | thumbs/ |
imgtypes::thumb::quer::sfx | .jpg |
imgtypes::thumb::quer::size | 96x72 |
imgtypes::thumb::hoch | Hochformat |
imgtypes::thumb::hoch::pfx | thumbs/ |
imgtypes::thumb::hoch::sfx | .jpg |
imgtypes::thumb::hoch::rotation | 270 |
imgtypes::thumb::hoch::size | 72x96 |
imgtypes::smallimg | Kleine Bilder für Notebooks |
imgtypes::smallimg::quer | Querformat |
imgtypes::smallimg::quer::pfx | smallimg/ |
imgtypes::smallimg::quer::sfx | .jpg |
imgtypes::smallimg::quer::size | 960x720 |
imgtypes::smallimg::hoch | Hochformat |
imgtypes::smallimg::hoch::pfx | smallimg/ |
imgtypes::smallimg::hoch::sfx | .jpg |
imgtypes::smallimg::hoch::rotation | 270 |
imgtypes::smallimg::hoch::size | 540x720 |
#! /usr/bin/perl -w # erzeugt Bilddateien im gewünschten Webformat package HB_MakeImages; use Herbaer::ConfigReader; use Herbaer::Utils; # wg. makedir use POSIX; =pod Ein SAX-Handler, der alle jpg-Elemente aus einer XML-Datei filtert und die erforderlichen Bilddateien erzeugt. =cut my $CONVERT="/usr/bin/convert" ; # Befehl zur Bildkonvertierung sub new { my $class = shift; $class = ref($class) || $class; # Referenz auf Hash mit Voreinstellungen, # die Einstellungen aus der Konfigurationsdatei überschreiben my $pre = shift; my $self = read_config_filename ($pre -> {'rcxml'} || 'makeimg.rc'); my $key; # überschreibende Einstellungen: Schlüssel my $value; # überschreibende Einstellungen: Wert while ( ($key, $value) = each %$pre ) { $self -> {$key} = $value; } # Default-Werte defined ($args -> {'dir'}) or $args -> {'dir'} = "story/" ; defined ($args -> {'filepattern'}) or $args -> {'filepattern'} = qr (\.xml$); my $img = '##kennung##'; # Platzhalter für die Kennung des Bildes my $srcdir = $self -> {'srcdir'} || ""; # Basis - Präfix $srcdir =~ s/([^\/])$/$1\//; # Schrägstrich an Verzeichnisnamen anhängen # der vollständige Dateipfad der Original-Bilddatei my $src = $srcdir . $self -> {'source_prf'} . $img . $self -> {'source_sfx'}; my $dir = $args -> {'dir'}; $dir =~ s/([^\/])$/$1\//; # Schrägstrich an Verzeichnisnamen anhängen my $keytype; # Hash-Schlüssel: Bildtyp my $hashtype; # Hash der Einträge zm Bildtyp my $keymode; # Hash-Schlüssel zu Modus my $hashmode; # Hash der Einträge zu einem Modus my $target; # Ziel-Datei my $cmd; # der Befehl my $val; # ein Hash-Wert while ( ($keytype, $hashtype) = each %{$self -> {'imgtypes'}} ) { while ( ($keymode, $hashmode) = each %$hashtype ) { # pfx # sfx # rotation # size # quality $target = $dir . $hashmode -> {'pfx'} . $img . $hashmode -> {'sfx'}; $cmd = "$CONVERT $src"; $val = $hashmode -> {'rotation'} and $cmd .= " -rotate " . $val; $val = $hashmode -> {'size'} and $cmd .= " -resize " . $val; defined ($val = $hashmode -> {'quality'}) and $cmd .= " -quality " . $val; $cmd .= ' ' . $target; $hashmode -> {'command'} = $cmd; $hashmode -> {'target'} = $target; } } return bless ($self, $class); } # new # erzeugt die Bilddateien sub makeImageFiles { my $self = shift; my $dir = $self -> {'dir'} or do { # Verzeichnis print "HB_MakeImages::makeImageFiles: Verzeichnis nicht definiert\n"; return 0; }; my $dh; # Verzeichnis-Handle my $fn; # Dateiname my $fh; # Datei-Handle my $regex = $self -> {'filepattern'}; print "HB_MakeImages::makeImageFiles\n" if $self -> {'verbose'}; opendir ($dh, $dir) or do { print "Kann Verzeichnis \"$dir\" nicht öffnen: $!\n"; return 0; }; my $parser = XML::SAX::ParserFactory -> parser (Handler => $self); my $num_files = 0; # Anzahl der verarbeiteten "Bildergeschichten" while ($fn = readdir ($dh)) { next if $fn eq '..' or $fn eq '.'; $fn =~ $regex or next; $fn = "$dir/$fn"; -f $fn or next; print "HB_MakeImages::makeImageFiles $fn\n" if $self -> {'verbose'}; sysopen ($fh, $fn, O_RDONLY) or do { print "Kann Datei $fn nicht öffnen: $!\n"; last; }; $parser -> parse_file ($fh); close ($fh); ++$num_files; } closedir ($dh); print "HB_MakeImages::makeImageFiles $num_files Dateien\n" if $self -> {'verbose'}; $num_files; } # SAX-Handler-Methode sub start_element { my ($self, $el) = @_; my $ln = $el -> {'LocalName'}; return if $ln ne 'jpg'; # Kennung des Bildes $el -> {'Attributes'} -> {'{}src'} -> {'Value'} =~ /^([a-z0-9]*)$/; my $img = $1; $el -> {'Attributes'} -> {'{}format'} -> {'Value'} =~ /^([a-z0-9]*)$/; my $mode = $1; # Kennung der Ausrichtung des Bildes my $key; # Hash-Schlüssel my $hash; # Parameter-Hash des Ziel-Bildes my $target; # Pfad der Ziel-Datei my $cmd; # Befehl zur Konvertierung der Bilder while ( ($key, $hash) = each %{$self -> {'imgtypes'}} ) { $hash = $hash -> {$mode}; $target = $hash -> {'target'}; $target =~ s/##kennung##/$img/ge; next if -e $target; # existierende Datei nicht überschreiben $target =~ s/\/[^\/]*$// and makedir ($target); $cmd = $hash -> {'command'}; $cmd =~ s/##kennung##/$img/ge; system ($cmd); print "$cmd\n"; } } # start_element 1; package main; use XML::SAX::ParserFactory ; use Fcntl ; # wg O_RDONLY sub version { print <<'VERSION' ; makeimg.pl 2007-01-02, Herbert Schiemann <h.schiemann@herbaer.de> VERSION } sub help { print <<'HELP'; makeimg.pl [--dir <dir>] [--srcdir <srcdir>] [--filepattern <filepattern>] [--verbose] <dir> Verzeichnis der "Bildergeschichten" (XML-Dateien). Default "story" <srcdir> Verzeichnis der Quell-Bilddateien, aus denen die JPEG-Dateien erzeugt werden. Default: das Arbeitsverzeichnis <filepattern> Muster (ReEx) der Dateinamen der "Bildergeschichten", Default '\.xml$' HELP } # Kommandozeilen-Argumente verarbeiten # args Referenz auf einen Hash, in den die Argumente eingetragen werden sub process_args { my $args = shift; # Hash-Referenz my $arg ; # das aktuelle Argument my $last = ''; # das zuvor verarbeitete Argument while (@ARGV) { $arg = shift @ARGV; if ($arg eq "--version") { version (); exit (0); } if ($arg eq "--help") { version (); help (); exit (0); } if ($last eq "--dir" or $last eq "--srcdir") { $last =~ s/^--//; $arg =~ /\.\./ and next; # .. ausschließen $arg =~ /^([-a-zA-Z0-9._\/]+)$/ or next; $args -> {$last} = $1; $last = ''; next; } if ($last eq "--filepattern") { $last = ''; $arg =~ /^(.*)$/ ; $args -> {'filepattern'} = qr ($1); next; } if ($arg eq "--verbose") { ++ $arg -> {'verbose'}; $last = ''; next; } if ( $arg =~ /^(--[a-z]*)$/ ) { $last = $arg; next; } print "ungültiges Argument $arg\n"; last; } } # Hash der Kommandozeilen-Argumente my $args = {}; process_args ($args); my $makeimages = new HB_MakeImages ($args); $makeimages -> makeImageFiles (); # makeImageFiles ("/home/herbaer/imgshow_20061230/story/story.xml");
# Utils.pm # Hilfsfunktionen package Herbaer::Utils; BEGIN { use Exporter; our @ISA = qw (Exporter); our @EXPORT = qw (makedir removedir emptydir copyFile readCfgFile); } use Digest::file "digest_file_hex" ; use File::Copy; use Fcntl; =for private Hilfsfunktion: erstellt ein Verzeichnis Parameter: Pfad des Verzeichnisses mit abschließendem "/" oder Dateipfad Ergebnis: Anzahl der neu angelegten Verzeichnisse =cut sub makedir { my $dir = shift; my $cur = ""; my $res = 0; $dir =~ s/^(\/?[^\/]*)//; for (; $cur .= $1; ) { -d $cur or do { -e $cur and die "$cur existiert und ist kein Verzeichnis\n"; mkdir ($cur) or die "Kann Verzeichnis $cur nicht anlegen: $!\n"; ++$res; }; $dir =~ s/^(\/[^\/]*)// or last; } $res; } =for private Hilfsfunktion: löscht eine Datei oder ein Verzeichnis mit allen Unterverzeichnissen Parameter: Pfad der Datei oder des Verzeichnisses =cut sub removedir { my $dir = shift; emptydir ($dir); rmdir ($dir); } =for private Hilfsfunktion: entfernt alle Dateien aus einem Verzeichnis Parameter: Pfad der Datei oder des Verzeichnisses =cut sub emptydir { my $dir = shift; -d $dir or return; my $dh; # Verzeichnis-Handle my $file; # Dateiname opendir ($dh, $dir) or die "Kann Verzeichnis $dir nicht öffnen: $!\n"; while ($file = readdir ($dh)) { $file =~ /^([^\/]+)$/ and $file = $1; # im T-Modus erforderlich $file =~ /^\.\.?$/ and next; $file = "$dir/$file"; -d $file and emptydir ($file); unlink ($file); } closedir ($dh); } =for private Hilfsfunktion: kopiert eine Datei Parameter: from, to from: Quell-Datei to: Ziel-Pfad, Verzeichnis wird ggf. erstellt Ergebnis: Anzahl der neu angelegten Verzeichniss und Datei(en) =cut sub copyFile { my ($from, $to) = @_; my $ddir = $to; $ddir =~ s/\/[^\/]*$//; # Basis-Dateinamen vom letzten / an entfernen $ddir and $res += makedir ($ddir); # sicherstellen, daß Zielverzeichnis existiert copy ($from, $to); # Datei kopieren } =for private Hilfsfunktion: liest eine Konfigurationsdatei Parameter: cfgfile Pfad der Konfigurationsdatei data Referenz auf Hash mit den Konfigurationseinstellungen =cut sub readCfgFile { my ($cfgfile, $data) = @_; -f $cfgfile && -r $cfgfile or return 0; defined ($data) or return 0; my $fh; # Dateihandle der Konfigurationsdatei sysopen ($fh, $cfgfile, O_RDONLY) or return; my $line; # Zeile der Konfigurations-Datei my $key; # Schlüssel while (defined ($line = <$fh>)) { $line =~ s/^\s*//; # führende Leerzeichen entfernen $line or next; # Leere Zeile überspringen $line =~ /^#/ and next; # Kommentarzeilen überspringen $line =~ s/^(\w+)\s*=\s*// and do { $key = $1; $line =~ s/\s*$//; $line =~ /^([-0-9a-zA-Z_.\/]+)$/ and $line = $1; # wg. unsauberer Eingabe ("tainted") $data -> {$key} = $line; }; } close ($fh); } # readCfgFile 1;
imgshow_ht.xslt
- Die Bildergeschichte im XHTML-Format<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" xmlns:is = "http://herbaer.de/xmlns/20061228/imgshow" xmlns = "http://www.w3.org/1999/xhtml" version = "1.0" > <xsl:template match = "/"> <xsl:apply-templates select = "is:document"/> </xsl:template> <!-- Verweis auf JPG-Bild im Text --> <xsl:template match = "is:jpg"> <a class="inlimgref" href="javascript:show_img('{generate-id(.)}')"><xsl:value-of select = "."/></a> </xsl:template> <!-- Dokument --> <xsl:template match = "is:document"> <html xml:lang = "de"> <head> <style type="text/css"> @import url(imgshow.css); </style> <script src="imgshow.js"/> <script> <xsl:text> onload = function () { show_div('div.</xsl:text> <xsl:value-of select = "generate-id(is:section)"/> <xsl:text>'); add_button_handlers (); }; </xsl:text> </script> <title><xsl:value-of select="is:title"/></title> </head> <body> <xsl:apply-templates select = "is:title"/> <xsl:call-template name = "inhalt"/> <xsl:apply-templates select = "is:section"/> <div id="div.image" class = "section center"> <div class="buttons"> <p class="button" id="button.back" >Rücklauf</p> <p class="button" id="button.backstep">zurück</p> <p class="button" id="button.image" >Bild</p> <p class="button" id="button.book" >Text</p> <p class="button" id="button.forestep">vor</p> <p class="button" id="button.forward" >Vorlauf</p> </div> <p> <img class="float" src="src" alt="alt"/> <span id="span.imagetext">Text</span> </p> </div> </body> </html> </xsl:template> <!-- Titel --> <xsl:template match = "is:document/is:title"> <h1 class = "title"><xsl:apply-templates/></h1> </xsl:template> <!-- Inhaltsübersicht --> <xsl:template name = "inhalt"> <div class="navig"> <ul> <xsl:for-each select = "//is:section"> <li><a href="javascript:show_div('div.{generate-id(.)}')" ><xsl:value-of select = "is:title"/></a></li> </xsl:for-each> </ul> <p> <table> <tbody> <tr> <td>Bildgröße</td> <td> <select id="select.imagesize"> <option value="images/" selected="selected">normal</option> <option value="smallimg/">klein</option> </select> </td> </tr> <tr> <td>Anzeigedauer bei Bildlauf</td> <td> <select id="select.duration"> <option value="2000">2 sec</option> <option value="3000">3 sec</option> <option value="4000">4 sec</option> <option value="5000" selected="selected">5 sec</option> <option value="6000">6 sec</option> <option value="7000">7 sec</option> <option value="8000">8 sec</option> <option value="9000">9 sec</option> <option value="10000">10 sec</option> <option value="15000">15 sec</option> </select> </td> </tr> </tbody> </table> </p> </div> </xsl:template> <!-- Abschnitt --> <xsl:template match = "is:section"> <div id = "div.{generate-id(.)}" class = "section"> <xsl:apply-templates select = "*"/> <p> <xsl:apply-templates select = "descendant::is:jpg" mode = "thumb"/> </p> </div> </xsl:template> <!-- Abschnitts-Überschrift --> <xsl:template match = "is:section/is:title"> <h2> <xsl:apply-templates/> </h2> </xsl:template> <!-- Unter-Abschnitt --> <xsl:template match = "is:p"> <p> <xsl:apply-templates/> </p> </xsl:template> <xsl:template match = "is:jpg" mode = "thumb"> <xsl:variable name = "id" select = "generate-id(.)"/> <a class="img" href="javascript:show_img('{$id}')"> <xsl:choose> <!-- Querformat --> <xsl:when test="@format = 'quer'"> <img id="img.{$id}" src="thumbs/{@src}.jpg" type="image/jpeg" width="96" height="72" alt="{@alt}"/> </xsl:when> <xsl:otherwise> <img id="img.{$id}" src="thumbs/{@src}.jpg" type="image/jpeg" width="72" height="96" alt="{@alt}"/> </xsl:otherwise> </xsl:choose> </a> </xsl:template> </xsl:stylesheet>
imgshow.js
- Die Navigation// index.js -*- coding: UTF-8 -*- // Scripts zur Anzeige eines "Bilder-Heftchens" // Herbert, 2006-12-29 var visible_div_; // die sichtbare "section" var section_book_; // der aktive "Buch"-Abschnitt var thumb_; // das aktive Vorschau img-Element var timeout_; // der laufende Timer var last_button_; // der zuletzt gewählte Knopf im Einzelbild-Fenster, nur in update_button_ benutzt // markiert den neuen Knopf als zuletzt "gedrückt" function update_button (button_) { if (last_button_) last_button_.setAttribute ("class", "button"); if (button_) { button_.setAttribute ("class", "selected_button"); last_button_ = button_; } else last_button_ = null; if (timeout_) { window.clearTimeout (timeout_); timeout_ = null; } }; // zeigt einen Abschnitt an function show_div (id_) { update_button (); if (visible_div_) { visible_div_.style.visibility = "hidden"; } visible_div_ = document.getElementById (id_); if (visible_div_) { visible_div_.style.visibility = "visible"; if (visible_div_.getAttribute ("class") == "section") { section_book_ = visible_div_; } } } // stellt ein neues Bild für den "Bild-Abschnitt" ein function update_img (id) { var image_div_ = document.getElementById ("div.image"); // der "Bild"-Abschnitt var img_ = image_div_.getElementsByTagName ("img") [0]; // das img-Element var span_ = img_.parentNode.getElementsByTagName ("span") [0]; // Der Text zum Bild thumb_ = document.getElementById("img." + id); // das Vorschau-img-Element var prf_img_ = document.getElementById ("select.imagesize").value || "images/" ; var imgfile_ = thumb_.getAttribute("src"); // Dateipfad des Vorschau-Bildes imgfile_ = imgfile_.replace (/^thumbs\//, prf_img_); // die Quelldatei des Bildes img_.setAttribute ("src", imgfile_); var text_ = document.createTextNode (thumb_.getAttribute ("alt")); // Text zum Bild span_.replaceChild (text_, span_.firstChild); } // aktualisiert den Einzelbild-Abschnitt und zeigt ihn an function show_img (id) { update_img (id); show_div ("div.image"); } function add_button_handlers () { var select_duration_ = document.getElementById ("select.duration"); // die Id des nächsten Vorschau-Bildes function nextImgId () { var next_ = thumb_.parentNode; // das umschlieÃende a-Element var parent_ = next_.parentNode; var img_; // Vorschau-img-Element while (true) { next_ = next_.nextSibling; if (next_ == null) next_ = parent_.firstChild; if (next_.nodeName == "a") { img_ = next_.getElementsByTagName ("img"); if (img_) img_ = img_ [0]; if (img_) img_ = img_.getAttribute ("id"); if (img_) img_ = img_.replace (/^img\./, ""); if (img_) return img_; } } }; // die Id des vorigen Vorschau-Bildes function prevImgId () { var next_ = thumb_.parentNode; // das umschlieÃende a-Element var parent_ = next_.parentNode; var img_; // Vorschau-img-Element while (true) { next_ = next_.previousSibling; if (next_ == null) next_ = parent_.lastChild; if (next_.nodeName == "a") { img_ = next_.getElementsByTagName ("img"); if (img_) img_ = img_ [0]; if (img_) img_ = img_.getAttribute ("id"); if (img_) img_ = img_.replace (/^img\./, ""); if (img_) return img_; } } }; // Vorlauf function run_forward () { update_img (nextImgId ()); timeout_ = window.setTimeout (run_forward, select_duration_.value); }; // Rücklauf function run_back () { update_img (prevImgId ()); timeout_ = window.setTimeout (run_back, select_duration_.value); }; document.getElementById ("button.book").addEventListener ( "click", function (event) { update_button (event.currentTarget); show_div (section_book_.getAttribute ("id")); }, true ); // Bildlauf anhalten document.getElementById ("button.image") .addEventListener ( "click", function (event) { update_button (event.currentTarget); }, true ); // das nächste Bild document.getElementById ("button.forestep").addEventListener ( "click", function (event) { update_button (event.currentTarget); update_img (nextImgId ()); }, true ); // das vorige Bild document.getElementById ("button.backstep").addEventListener ( "click", function (event) { update_button (event.currentTarget); update_img (prevImgId ()); }, true ); // Vorlauf document.getElementById ("button.forward").addEventListener ( "click", function (event) { update_button (event.currentTarget); run_forward (); }, true ); // Rücklauf document.getElementById ("button.back").addEventListener ( "click", function (event) { update_button (event.currentTarget); run_back (); }, true ); } // add_button_handlers
imgshow.css
- Die Darstellung im Browser/* Überschrift */ h1.title { position : absolute; top : 0px; left : 0px; padding-left : 10px; overflow : hidden; white-space : nowrap; } /* Liste der Abschnitte auf der linken Seite */ div.navig { position : absolute; top : 50px; left : 0px; width : 30%; padding-left : 10px; } ul { margin: 1em 0 0 0; padding: 0; } li {display : block;} td + td { padding-left: 1em; } /* Ein Abschnitt der Bildergeschichte */ div.section { visibility : hidden; position : absolute; top : 50px; left : 33%; width : 66%; } /* Vorschaubilder am Ende eines Abschnitts */ a.img {padding-right: 1em; border-top: 1cm;} /* Schaltflächen oben im Bild-Abschnitte */ div.buttons { padding-top: 1em; } p.button { display : inline; color : blue; cursor : pointer; padding-left : 2em; padding-right : 2em; } p.button:before { content: "[["; } p.button:after { content: "]]"; } p.selected_button { display : inline; color : green; cursor : pointer; padding-left : 2em; padding-right : 2em; } p.selected_button:before { content: "[["; } p.selected_button:after { content: "]]"; } img.float { max-width : 56%; float : left; padding-right : 1em; padding-bottom : 1em; }