Oracle Resize eines Images in Java und Rückgabe des Image als BLOB an die Oracle Datebank

hkoelzer

Mitglied
Hey,

ich habe mal wieder ein Problem beim Zusammenspiel Oracle Datenbank und einer embedded Java Klasse.
Ich möchte eine Image (als blob) aus der Datenbank an die Java Klasse übergeben, dort erfolgt dann ein resizen des Bildes auf die gewünschte Höhe und Breite und dann soll das Image wieder als blob zurück an die die aufrufenden Funktion übergeben werden.

Für das Resizen des Bildes habe ich bei www.codejava.net auch ein Beispiel gefunden, welches ein lokal liegendes Bild resized und wieder auf lokal ablegt.

Das Funktioniert lokal auch sehr gut. Mein Katzenbeispiel - Jpg wird auf 50% der Originalgröße (1024 x 811 WxH) also auf 512 x 405 verkleinert.
Dabei verringert sich natürlich auch die Dateigröße - in dem Fall von 192 KB auf 39 KB.

Mein angepasstes Programm (siehe Anhang HKRCALL.java) nimmt auch den aus der Datenbank übergebenen BLOB, ermittelt die Größe des Originalbildes,
berechnet 50 % der Breite udn Höhe und gibt dann letztendlich auch wieder ein blob zurück. Dieser wird dann wieder in einer Tabelle abgelegt.
Ich habe mal ein paar Ausgaben in mein Java Programm gebaut und lasse mir diese per dbms-Output mal während der Ausführung der PL/SQL Prozedur (welche dann wiederum die Java Klasse aufruft) ausgeben (s.u.)

Leider ist dieser blob nur 3955 Byte groß.

Wenn ich mir das zurückgegebene Bild von der Datebank mal herunterlade, ist das durchaus Jpeg und die Bildinformationen zeigen auch die Masse 512 x 405 an.
Leider ist das Bild schwarz.

Kann sich das vielleicht mal jemand anschauen, wo mein Fehler liegen könnte (ImageOutputStream ?)
Ich bin gerade am verzweifeln :-(




resizeJpegCall: Groesse des uebergebenen Blob: 194334
Original scaledWidth = 1024
Original scaledHeight = 811
50 % scaledWidth = 512
50 % scaledHeight = 405
resizeJpeg: BufferedImage outputImage
resizeJpeg: Graphics2D g2d = outputImage.createGraphics()
resizeJpeg: g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null)
resizeJpeg: g2d.dispose()
ImageIO.write(outputImage, JPG, ios)
Image resized successfully.
Image resized successfully.
Groesse des Return Blob: 3955
 

Anhänge

  • HKRCALL.java
    6 KB · Aufrufe: 15

Oneixee5

Top Contributor
Mit ORDImage/ORD_IMAGE kann man die Bilder als Teil des Prozesses zum Hochladen des Bildes in die Datenbank skalieren. Oder man kann die Bilder kurz nach dem Hochladen als Teil eines Hintergrundprozesses (DBMS_SCHEDULER) skalieren. ORDImage benötigt Java. Die Oracle Express Edition [XE] unterstützt kein Java. Daher ist ORDImage für XE-Datenbanken nicht verfügbar.

SQL:
CREATE OR REPLACE FUNCTION fixed_img(p_blob       BLOB,

                                     in_width     NUMBER,

                                     in_height    NUMBER)

   RETURN BLOB

IS

   vimagedata    BLOB;

   vsizedimage   BLOB;

BEGIN

   vimagedata := p_blob;

   DBMS_LOB.createtemporary(vsizedimage, FALSE, DBMS_LOB.call);

   ordsys.ordimage.processcopy(vimagedata,

                               'fixedScale=' || in_width || ' ' || in_height,

                               vsizedimage);

   RETURN vsizedimage;

END;

Ergänzung: https://www.doag.org/formes/pubfile...-Czarski-Bildbearbeitung-in-der-Datenbank.pdf
 
Zuletzt bearbeitet:

hkoelzer

Mitglied
Mit ORDImage/ORD_IMAGE kann man die Bilder als Teil des Prozesses zum Hochladen des Bildes in die Datenbank skalieren. Oder man kann die Bilder kurz nach dem Hochladen als Teil eines Hintergrundprozesses (DBMS_SCHEDULER) skalieren. ORDImage benötigt Java. Die Oracle Express Edition [XE] unterstützt kein Java. Daher ist ORDImage für XE-Datenbanken nicht verfügbar.

SQL:
CREATE OR REPLACE FUNCTION fixed_img(p_blob       BLOB,

                                     in_width     NUMBER,

                                     in_height    NUMBER)

   RETURN BLOB

IS

   vimagedata    BLOB;

   vsizedimage   BLOB;

BEGIN

   vimagedata := p_blob;

   DBMS_LOB.createtemporary(vsizedimage, FALSE, DBMS_LOB.call);

   ordsys.ordimage.processcopy(vimagedata,

                               'fixedScale=' || in_width || ' ' || in_height,

                               vsizedimage);

   RETURN vsizedimage;

END;

Ergänzung: https://www.doag.org/formes/pubfile...-Czarski-Bildbearbeitung-in-der-Datenbank.pdf
Danke, aber leider ist ordimage von Oralce abgekündigt worden und steht in neueren Datenbankversionen nicht mehr zu Verfügung.
Das ist der Grund, warum ich mich überhaupt mit der Bildbearbeitung in Java beschäftige.
Wir verwenden derzeit ordimage und müssen es ersetzen.
 

Oneixee5

Top Contributor
In der API steht:
OutputStream setBinaryStream(long pos) - pos - the position in the BLOB value at which to start writing; the first position is 1
Also müsstest du ändern:
Java:
OutputStream os = retBlob.setBinaryStream(1L);
 

Oneixee5

Top Contributor
Und das hier: float percent_float = (float) 0.50; tut mir richtig weh! -> float scaleFactor = .5F; Eigentlich ist das aber eine Konstante und gehört als solche deklariert.
 

hkoelzer

Mitglied
Hey,

erstmal danke für deine Rückmeldung.

Leider führte die Umstellung auf
OutputStream os = retBlob.setBinaryStream(1L);
zu keinem anderen Ergebnis.


Das float percent_float = (float) 0.50; habe ich nur temporär eingebaut für den Test.
Normalerweise soll die Breite und Höhe des Bildes beim Aufruf Java Klasse mitgegeben werden.

Hättest du sonst noch eine Idee, warum nicht das korrekte Bild zurückgegeben wird?
 

Oneixee5

Top Contributor
Ich denke du solltest beim Schreiben der Daten: oracle.sql.BLOB statt java.sql.Blob verwenden:

Java:
outstream = ((BLOB) retBlob).getBinaryOutputStream();
ios = ImageIO.createImageOutputStream(outstream);
 

Oneixee5

Top Contributor
Ich habe das Deprecated gesehen. Ausprobieren hätte ja nicht geschadet. Java verwenden wir eigentlich nicht in der Ora, weil es zu umständlich ist. Unser Stand ist die 12 und wir werden, auf Grund rechtlicher Vorgaben, niemals in die Cloud wechseln. Die DB's müssen immer in unseren Rechenzentren und unter unserer Kontrolle bleiben. Oracle versucht das so schwer wie nur irgend möglich zu machen. So wird es wohl noch dauern, bis wir nach 19+ migrieren oder gar den Hersteller wechseln. Ich werde es nächste Woche aber mal ausprobieren, vorher bin ich nicht in der Arbeit. Mit JDBC bin ich auch etwas aus der Übung seit es JPA gibt. Wenn jetzt Oracle Multimedia desupported ist, kann man zu APEX Media Extension (AME) https://www.apexmediaextension.com/index.html wechseln.
 

hkoelzer

Mitglied
Hey,

AME wäre die Alternative. Ist allerdings kostenpflichtig, außerdem mann muss seine(n) eigenen Server aufbauen (wenn man seine Bilder nicht über den Äther an deren Server schicken möchte) .

Wir müssen demnächst migrieren, daher jetzt meine Bemühungen, das mit Java hinzubekommen (auch wenn ich bis dato nichts mit Java am Hut hatte ;-)

Die Konvertierung von einem GIF, BMP zu JPG habe ich auch hinbekommen.
Auch die Kompremierung von JPEG Files klappt - da schicke ich auch BLOB hin und her.

Nur das Resizen sträubt sich und ich weiß nicht warum.

Wenn ich das ganze lokal mache, mir den blob per odbc connect aus der Tabelle hole und dann resize, hat sowohl der blob (in der Java Umgebung) die richtig Größe und das rausgeschriebene Bild ist dann auch resized.

Echt zum Verzweifeln!!!
 

Oneixee5

Top Contributor
Ich finde das "kostenpflichtig" Argument in Bezug zur Oracle-DB lustig. Ich weiß nicht wie viele Millionen Euro die DB's an Kosten verursachen - aber in irgend einem Lizenz-Paket wird das schon mit drin sein. Man muss einfach mal mit den zuständigen Leuten reden. Ich kenne mich nicht so genau aus, habe mal so nebenbei gehört die Lizenzen gehen wohl pro Core + Ausstattung an Software + Support-Level, so würde ich schätzungsweise nur bei einer vollständig genutzten ExaData auf ca. 640000 € im Jahr kommen + 350000 € für die Hardware + Infrastruktur und das Ganze mal 2 für das Backup-Rechenzentrum. Natürlich wird das alles noch verhandelt aber trotzdem fällt da AME garantiert nicht ins Gewicht.
 

hkoelzer

Mitglied
Hey,

natürlich hast du bezüglich der Kosten der Datenbank vollkommen recht. Dagegen sind die 2000 EUR ein Klacks.
Allerdings sind wir nicht die Betreiber der Datenbank, so das die Installation zusätzlicher Software etc. immer ein Graus sind.

Außerdem wollten wir das mal ausprobieren und grundsätzlich geht es ja auch mit Java.
Ich habe das Problem ein wenig eingrenzen können.
Es liegt nicht an der Rückgabe des blob, sondern der eigentliche Kopiervorgang beim drawimage.

g2d.drawImage(inputImage, 0, 0, scaledWidth, scaledHeight, null);

Das scheint beim eingebetteten Java innerhalb der Datenbank nicht zu funktionieren. Es liegt aber nicht grundsätzlich an Graphics2D

Wenn ich statt des Kopiervorgangs des Originalimages in das neue Image einfach mal ein Gesicht male,
so wird das korrekt in den blob zurückgebeben - und das Bild landet in meiner Datenbanktabelle (s.u.)

// Fill background with white
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, scaledWidth, scaledHeight);

// Draw a smiley face
g2d.setColor(Color.YELLOW);
g2d.fillOval(10, 10, 180, 180);
g2d.setColor(Color.BLACK);
g2d.fillOval(40, 40, 40, 40);
g2d.fillOval(120, 40, 40, 40);
g2d.fillRect(50, 150, 100, 10);

1621356665832.png
 

hkoelzer

Mitglied
So,

jetzt klappt es.

Ich habe umgestellt und benutze jetzt Image:

Image resultingImage = inputImage.getScaledInstance(scaledWidth, scaledHeight, Image.SCALE_DEFAULT);
BufferedImage outputImage = new BufferedImage(scaledWidth, scaledHeight, BufferedImage.TYPE_INT_RGB);
outputImage.getGraphics().drawImage(resultingImage, 0, 0, null);
ImageIO.write(outputImage, "jpg", os);
 

deoran

Neues Mitglied
Moin,

nach vielem hin und her habe ich es heute mit deiner Hilfe ebenso zum laufen gebracht.
ein paar kleinere Sachen hatte ich noch angepasst, sodass es nun die Funktion erhalten hat, die sie von Anfang an haben sollte.

Den fertigen Code hab ich im Anhang und sollte nun ohne Probleme laufen (jedenfalls bei mir)
 

Anhänge

  • converter.java
    6,2 KB · Aufrufe: 3
Ähnliche Java Themen
  Titel Forum Antworten Datum
Robert Zenz Aufteilen von Up/Downvotes eines Benutzers in drei Gruppen. Datenbankprogrammierung 0
damike84 Hibernate: persistieren eines Graphen Datenbankprogrammierung 2
G Laufzeit eines Algorithmus mittels Big Theta bestimmen Datenbankprogrammierung 5
G ID zuweisung eines TerminKalenders (mehrere Kalender) Datenbankprogrammierung 8
D Hibernate: Zustand eines Objekts erkennen? Datenbankprogrammierung 0
S HSQLDB Verbieten eines update auf eine bestimmte reihe Datenbankprogrammierung 4
J Datenbankeintag eines Warenkorbes funktioniert nicht Datenbankprogrammierung 4
H MySQL Werte eines Datensatzes in einen anderen kopieren Datenbankprogrammierung 2
M [Hibernate]Abgleich eines lokalen Objekts mit dem Zustand aus der Datenbank. Datenbankprogrammierung 3
N Problem bei Erstellung eines Index Datenbankprogrammierung 12
G PostgreSQL Postgre: Passwort eines Benutzers ändern Datenbankprogrammierung 3
D Anzeige wärend des Ausführens eines Statements Datenbankprogrammierung 13
N executeUpdate "innerhalb" eines Resultsets Datenbankprogrammierung 14
S Select eines bestimmten Datensatzes Datenbankprogrammierung 4
J Kopieren eines Datensatzes Datenbankprogrammierung 4
R Effiziente Java-Methode zum finden eines freien PK Datenbankprogrammierung 7
M Zugriff auf eine Access-Datenbank innerhalb eines jar-Files Datenbankprogrammierung 7
brainray Bei MySQL alle Datenbanken eines Servers abfragen Datenbankprogrammierung 3
1 User die Rechte eines Datenbankerstellers zuweisen? Datenbankprogrammierung 3
X SQL Abfrage für Ähnlichkeit eines Strings Datenbankprogrammierung 2
B SQL Abfrage. Nur den ersten eines Blocks Datenbankprogrammierung 2
M Passwort eines Technischen Users hinterlegen Datenbankprogrammierung 6
A JPA: Zweite Instanz eines Entitätsobjekts Datenbankprogrammierung 3
M Konvertierung eines Ojects to String Datenbankprogrammierung 3
T Datenbanknamen eines Datenbankservers auslesen Datenbankprogrammierung 9
J Größe eines ResultSets Datenbankprogrammierung 12
G Problem beim Schreiben eines Dateipfads in MySQL-DB Datenbankprogrammierung 9
G Löschen eines Eintrages verbunden mit JList Datenbankprogrammierung 5
F Filtern innerhalb eines Resultset Datenbankprogrammierung 12
W Anzahl der Spalten eines ResultSets bestimmen Datenbankprogrammierung 5
F die DN eines LDAP verzeichnisses abfragen Datenbankprogrammierung 2
B Laden eines JDBC Treiber. Datenbankprogrammierung 7
N Struktur eines Datenbankinterface? Datenbankprogrammierung 7
P Wirkliche Zeilenanzahl eines ResultSets ermitteln Datenbankprogrammierung 22
K frage zum ausführen eines INSERT statements Datenbankprogrammierung 16
K errechnen eines mittelwertes vom jdbc rSet Datenbankprogrammierung 4
M Abfrage trennt Ergbnis eines Atrributes nach den Leerzeichen Datenbankprogrammierung 4
F Abfrage eines DB Feldes aus einer mySQL Datenbank Datenbankprogrammierung 2
K Datenbank eines Forums nutzen Datenbankprogrammierung 11
J Alle Spalten und Zeilen eines ResultSets ausgeben ? Datenbankprogrammierung 2
B Zeilenzahl eines ResultSet ermitteln Datenbankprogrammierung 5
H Java Class zum komprimieren von Jpeg-Images zum Einbinden in Oracle DB - Bild als blob (in und out) Datenbankprogrammierung 23

Ähnliche Java Themen

Neue Themen


Oben