"Bildbearbeitung" mit Oracle Application Express
"Bildbearbeitung" mit Oracle Application Express

Der Umgang mit Bilddateien ist für die meisten Web-Anwendungen völlig normal. Vor einigen Monaten wurde in diesem Forum bereits dargestellt, wie man Bilder mit Oracle Application Express hochladen und später bspw. in einem Bericht anzeigen kann. Vielfach werden neben diesem einfachen Up- und Download weitergehende Fähigkeiten benötigt ...

  • Größenänderung bzw. Skalierung
  • Umwandeln in Graustufen
  • Drehen, Spiegeln
  • ...

Die Oracle-Datenbank bietet diese und einige andere Basis-Funktionalitäten zum Bearbeiten von Bildern mit InterMedia direkt in der Datenbank an. Eine praktische Anwendung ist die automatische Erstellung von Thumbnails (kleine Vorschauen) für Bilder. In diesem Tipp erfahren Sie, wie Sie diese Funktionen für Ihre eigenen Anwendungen nutzen können.

Erstellen Sie zunächst eine Tabelle, welche die Bilder aufnehmen soll. Beim "einfachen" Speichern und Anzeigen von Bildern wurde bisher der Datentyp BLOB (Binary Large Object) verwendet. Ein BLOB nimmt jede Form von Binärdaten auf - über den Inhalt weiss die Datenbank nichts. Speziell für Bilder steht jedoch ein eigener Datentyp zur Verfügung: OrdImage  Dieser wird im Folgenden verwendet. Beachten Sie, dass die Tabelle eine zusätzliche Spalte vom Typ OrdImage enthält - sie ist für den automatisch generierten Thumbnail vorgesehen.

create table bilder_tab(
  id        number(10),
  bild      OrdImage,
thumbnail OrdImage,
  dateiname varchar2(4000)
)

create sequence seq_bilder_tab start with 1 increment by 1

Legen Sie als nächstes ein (ganz einfaches) Formular zum Hochladen der Bilder an.  Erstellen Sie das Element zum Hochladen einer Datei und die Schaltfläche Go am besten einzeln.

Formular mit Dateiauswahl
Abb.1: Formular mit Dateiauswahl

Wenn Sie nun eine Datei auswählen und die Schaltfläche Go klicken, speichert Application Express das Bild automatisch in die Tabelle WWV_FLOW_FILES. Dort steht es als Datentyp BLOB bereit. Sie benötigen daher nun einen PL/SQL-Prozeß, welcher das Bild aus der Tabelle WWV_FLOW_FILES entnimmt und als OrdImage in Ihre eigene Tabelle BILDER_TAB speichert. Im gleichen Atemzug werden wir dann auch den Thumbnail erstellen.

declare
v_bild ordImage := null;
v_thumbnail ordImage := null;

v_id BILDER_TAB.ID%TYPE;
begin
for bild in (
select blob_content, filename from wwv_flow_files
where name = :P1_BILD
) loop

-- Bild und Thumbnail initialisieren, Tabellenzeile erzeugen und
-- initialisierte Variablen zurückgeben.
insert into bilder_tab (id, bild, thumbnail, dateiname)
values (seq_bilder_tab.nextval, ordimage.init(), ordimage.init(), bild.filename)
returning id, bild, thumbnail into v_id, v_bild, v_thumbnail;

-- Bilddaten in das initialisierte ORDIMAGE übertragen
dbms_lob.copy(
v_bild.source.localData,
bild.blob_content,
dbms_lob.getlength(bild.blob_content)
);

-- Metadaten berechnen
v_bild.setProperties();
v_bild.setLocal();

-- Thumbnail (kleines Vorschau-Bild) als ORDIMAGE erzeugen
v_bild.processCopy('maxScale=100 100', v_thumbnail);

-- Bilddaten in die Tabelle "zurückschreiben"
update bilder_tab set
bild = v_bild,
thumbnail = v_thumbnail
where id = v_id;
end loop;
end;

Achten Sie im Code auf das Kommando processCopy(). Es enthält als ersten Parameter den Befehl maxScale=100 100. Dies bedeutet, dass das hochgeladene Bild auf eine Größe von maximal 100 Pixeln (Länge oder Breite) herunterskaliert wird. Das Ergebnis wird als Kopie (copy) in die Variable v_thumbnail gespeichert. Weiter unten werden noch einige andere Befehle für das processCopy()-Kommando vorgestellt. 

Laden SIe anschließend ein paar Bilder hoch. Nehmen Sie ruhig große Bilder mit hoher Auflösung - die Erstellung des Thumbnail ist insbesondere für solche Bilder von Vorteil. Als nächstes erzeugen Sie einen Bericht zur Darstellung der hochgeladenen Bilder. Stellen Sie aus der Tabelle BILDER_TAB zunächst nur die Spalten ID und DATEINAME dar. Fügen Sie dem Bericht schließlich noch eine leere Spalte hinzu - An dieser Stelle soll später der Thumbnail dargestellt werden. Das SQL für den Bericht lautet daher:

select id, dateiname, 0 as thumbnail from bilder_tab

Bericht zur Darstellung der hochgeladenen Bilder - erster Schritt
Abb.2: Bericht zur Darstellung der hochgeladenen Bilder - erster Schritt

Zum Anzeigen des Thumbnails benötigen Sie wiederum einen PL/SQL-Prozeß. Legen Sie daher einen Anwendungsprozeß an. Navigieren Sie dazu zu den Gemeinsamen Komponenten und dort zu den Anwendungsprozessen. Legen Sie einen Bedarfsgesteuerten Prozeß an und nennen Sie ihn Thumbnail darstellen.

Neuen Applikationsprozeß anlegen
Abb.3: Neuen Applikationsprozeß anlegen

Hinterlegen Sie den folgenden PL/SQL-Code für den Prozeß:

declare
v_bilddaten blob;
v_mimetype varchar2(100);
v_groesse number;
begin
-- Bild anhand der ID selektieren - die ID wird im
-- Applikationselement :F111_BILD_ID übergeben
select
al.thumbnail.getMimetype(),
al.thumbnail.getContent(),
al.thumbnail.getContentLength()
into v_mimetype, v_bilddaten, v_groesse
from bilder_tab al where id = :F111_BILD_ID;

-- Mimetype des Bildes für den Browser setzen
owa_util.mime_header(nvl(v_mimetype,'application/octet'),false);
-- Größe des Bildes (in Byte setzen)
htp.p('Content-length:'|| v_groesse);
htp.p('Content-Disposition: inline');
owa_util.http_header_close;
-- Daten an den Browser senden - dieser stellt das Bild dann dar
wpg_docload.download_file(v_bilddaten);
end;

Achten Sie im Code auf das SELECT-Kommando. Es ruft den Mime-Typ und die Größe des Bildes direkt aus dem OrdImage-Datentypen ab. Das Bild selbst wird anhand der ID selektiert. Der Prozeß verwendet dabei das Application Express-Element F111_BILD_ID. Da dies noch nicht existiert, legen Sie es nun an. Navigieren Sie dazu zu den Gemeinsamen Komponenten und von dort zu den Anwendungselementen. Anwendungselemente sind nicht an eine Seite gebunden, funktionieren aber ansonsten wie die Seitenelemente. Legen Sie also mit Erstellen ein neues Anwendungselement an - außer dem Namen brauchen Sie nichts anzugeben.

Neues Anwendungselement anlegen
Abb.4: Neues Anwendungselement anlegen

Nachdem der PL/SQL-Prozeß zum Darstellen des Thumbnails angelegt wurde, können Sie den Thumbnail nun in Ihren Bericht aufnehmen. Navigieren Sie dazu wieder zu Ihrem Bericht, von dort zu den Berichtsattributen und dann zur Spalte THUMBNAIL. Geben Sie als HTML-Ausdruck ein:

<img 
src="f?p=&APP_ID.:&APP_PAGE_ID.:&SESSION.:APPLICATION_PROCESS=Thumbnail darstellen:::F111_BILD_ID:#ID#"
>

Beachten Sie, dass die HTML-Attribute width oder height hier nicht verwendet werden. Bestätigen Sie die Änderungen und schauen Sie sich das Ergebnis an. Das in diesem Beispiel hochgeladene Bild hat eine Auflösung von 1500 mal 1200 Pixeln. Der hier dargestellte Thumbnail wurde bereits in der Datenbank berechnet - somit mussten zur Darstellung nur wenige Bytes heruntergeladen werden.

Darstellung der hochgeladenen Bilder mit Thumbnail

Abb.5: Darstellung der hochgeladenen Bilder mit Thumbnail

Nun geht es daran, die Anwendung ein wenig zu erweitern. Schön wäre es, wenn man die Auflösung des Bildes direkt im Bericht sehen könnte. Dies ist kein Problem. OrdImage bietet auch dazu passende Methoden an. Ändern Sie das SQL des Berichts wie folgt um:

select 
a.id,
a.dateiname,
0 as thumbnail,
a.bild.getWidth() || ' x ' || a.bild.getHeight() as AUFL
from bilder_tab a

Das Ergebnis sieht dann wie folgt aus:

Darstellung der hochgeladenen Bilder mit Thumbnails und Auflösung

Abb.6: Darstellung der hochgeladenen Bilder mit Thumbnails und Auflösung

Zum "Bearbeiten" des Bildes verwenden Sie (wie schon bei der Erzeugung des Thumbnails) das Kommando process() bzw. processCopy(). Während processCopy() des bearbeitete Bild als Kopie in eine weitere Variable vom Typ OrdImage speichert, verändert process() das Bild "in-Place". Als nächstes hinterlegen Sie einen Prozeß, der das Bild in Graustufen umrechnet und direkt einen neuen Thumbnail generiert. 

Erzeugen Sie dazu einen neuen Seitenprozeß - er soll beim Laden der Seite  vor Header ausgeführt werden:

Neuer Anwendungsprozeß zum Umwandeln in Graustufen

Abb.7: Neuer Prozess für die Umwandlung des Bildes in Graustufen

Der PL/SQL-Code ist wie folgt:

declare
v_bild ordimage;
v_thumbnail ordimage;

begin
-- Bild anhand der ID selektieren - die ID wird im
-- Applikationselement :F111_BILD_ID übergeben

-- WICHTIG: SELECT .. FOR UPDATE !
select a.bild, a.thumbnail
into v_bild, v_thumbnail
from bilder_tab a where id = :F111_BILD_ID
for update;

-- Umrechnen des Bildes in Graustufen
v_bild.process('contentFormat=8BITGRAY');

-- Thumbnail neu berechnen
v_bild.processCopy('maxScale=100 100', v_thumbnail);

-- Bilddaten in die Tabelle "zurückschreiben"
update bilder_tab set
bild = v_bild,
thumbnail = v_thumbnail
where id = :F111_BILD_ID;
end;

Wichtig ist, dass Sie das Bild im PL/SQL-Code FOR UPDATE selektieren - Während der Bildbearbeitung muss die Tabellenzeile gesperrt sein. Wenn Sie den PL/SQL-Code hinterlegt haben, versehen Sie den Prozeß mit einer Bedingung (Abbildung 8). Der Prozeß darf nur ausgeführt werden, wenn die Umgebungsvariable REQUEST den Wert GRAUSTUFEN enthält.

Bedingung für die Umwandlung in Graustufen: REQUEST=GRAUSTUFEN

Abb.7: Neuer Prozess für die Umwandlung des Bildes in Graustufen

Navigieren Sie nun wieder zum Bericht und fügen Sie diesem eine neue Spalte hinzu.

select 
a.id,
a.dateiname,
0 as thumbnail,
a.bild.getWidth() || ' x ' || a.bild.getHeight() as AUFL,
0 as GRAUSTUFEN
from bilder_tab a

In den Berichtsattributen hinterlegen Sie nun wiederum einen HTML-Ausdruck für die neue Spalte GRAUSTUFEN:

<a href="f?p=&APP_ID.:&APP_PAGE_ID.:&SESSION.:GRAUSTUFEN:::F111_BILD_ID:#ID#">Graustufen</a>

Das Ergebnis sollte wie folgt aussehen - Nachdem Sie auf Graustufen geklickt haben, wird das Bild entsprechend umgewandelt.

Umwandlung in Graustufen: Ergebnis

Abb.9: Umwandlung in Graustufen: Ergebnis

Zum Abschluß erfahren Sie, wie Sie das Bild in Originalform abrufen können. Dies funktioniert ähnlich zur Darstellung als Thumbnail. Nehmen Sie einfach den weiter oben bereits erstellten Anwendungsprozeß Thumbnail darstellen als Vorlage und erstellen Sie so einen neuen Anwendungsprozeß Bild darstellen.

Neuer Anwendungsprozeß: Bild darstellen

Abb.9: Umwandlung in Graustufen: Ergebnis

Der PL/SQL-Code ist (analog zu "Thumbnail darstellen") wie folgt. Im Grunde genommen wird im SELECT-Kommando die Spalte THUMBNAIL durch die Spalte BILD ersetzt.

declare
v_bilddaten blob;
v_mimetype varchar2(100);
v_groesse number;
begin
-- Bild anhand der ID selektieren - die ID wird im
-- Applikationselement :F111_BILD_ID übergeben
select
al.bild.getMimetype(),
al.bild.getContent(),
al.bild.getContentLength()
into v_mimetype, v_bilddaten, v_groesse
from bilder_tab al where id = :F111_BILD_ID;

-- Mimetype des Bildes für den Browser setzen
owa_util.mime_header(nvl(v_mimetype,'application/octet'),false);
-- Größe des Bildes (in Byte setzen)
htp.p('Content-length:'|| v_groesse);
htp.p('Content-Disposition: inline');
owa_util.http_header_close;
-- Daten an den Browser senden - dieser stellt das Bild dann dar
wpg_docload.download_file(v_bilddaten);
end;

Das Bild soll in einem separaten Browserfenster dargestellt werden, sobald auf den Namen geklickt wird. Gehen Sie nun wieder zum Bericht, zu den Berichtsattributen und von dort zu den Attributen der Spalte DATEINAME:

HTML-Ausdruck für die Berichtspalte DATEINAME

Abb.9: HTML-Ausdruck für die Berichtspalte DATEINAME

Das Ergebnis sieht dann in etwa so aus: Nach Klick auf den Dateinamen öffnet sich ein Fenster, welches das Bild vollständig anzeigt.

Bild komplett anzeigen

Abb.9: HTML-Ausdruck für die Berichtspalte DATEINAME

Neben den hier vorgestellten Kommandos kennen process() und processCopy() noch weitere Befehle ... Probieren Sie die folgenden Kommandos einfach mal aus:

  • contentFormat=8BITGRAY: Umwandlung in Graustufen
  • rotate [grad]: Dreht das Bild um [grad] Grad
  • mirror: Spiegelt das Bild 
  • gamma [wert größer als 1]: hellt das Bild auf
  • gamma [wert kleiner als 1]: dunkelt das Bild ab

Demnach können Sie mit dem Kommando ...

v_bild.process('rotate 90');

das Bild um 90° drehen. Die Oracle-Dokumentation enthält eine Übersicht über alle Bildbearbeitungs-Funktionen des process()-Kommandos. Daneben sind auch allgemeine Informationen zum Umgang mit Multimedia-Daten in der Dokumentation enthalten.

Zurück zur Community-Seite