Benutzer-Werkzeuge

Webseiten-Werkzeuge


prog:oracle_multimedia_12c

Multimedia in der Oracle Datenbank 12c / 18c - Bildbearbeitung in PL/SQL

Start: 05.2017

12c, Basis Funktion aber schon ab Oracle 8i seit 1998 verfügbar

18c

Oracle Multimedia is deprecated in Oracle Database Release 18c, and may be desupported in a future release. Oracle recommends that you stop using deprecated features as soon as possible.

https://docs.oracle.com/en/database/oracle/oracle-database/18/imurg/index.html

Ziel: Mit der Oracle Multimedia Option Bilder in der Datenbank bearbeiten und in APEX darstellen

Mit Oracle Multimedia 12c (seit 8i / 11g noch unter dem Namen Oracle interMedia vertrieben) steht dem Apex Entwickler ein reichhaltiges Werkzeug für das Metadaten Handling von Bild und Ton Daten in der Oracle Datenbank zur Verfügung.

Mit der Oracle Multimedia 12c lassen sich die Metadaten und Attribute von Multimedia Daten lesen und setzen und viele Eigenschaften von Bild Dateien, wie Größe, Rotation, Schärfe, Kontrast etc., direkt in der Datenbank bearbeiten.

Bestimmte Eigenschaften wie die Farbe eines Bildes lassen sich aus den binären Daten des Bildes ermitteln und werden damit auch suchbar.

Mit diesem umfangreichen Set an Hilfsmitteln lassen sich mit PL/SQL auch komplexere Aufgabenstellung in Oracle Apex relativ einfach integrieren.

Übersicht über die Elemente in der Datenbank:

 Oracle Multimedia in der Datenbank

Die Verarbeitung der Daten wird über Datenbank Objekt Typen durchgeführt:

  • Bild Daten ⇒ ORDImage
  • Audio Daten ⇒ ORDAudio
  • Heterogene Daten ⇒ ORDDoc
  • Video Daten ⇒ ORDVideo

Die Speicherung in einer Datenbank Tabelle kann ebenfalls mit diesem Typen durchgeführt werden.

Vorteil der Speicherung als Objekt Type:

  • Daten und Eigenschaften über ein Objekt ansprechbar
  • Schlankes Datenmodel

Nachteil der Speicherung als Objekt Type:

  • Laderoutienen etwas komplexer
  • Gefahr von Bugs
  • Daten müssen für andere Tools immer extrahiert werden

Übersicht über möglichen Feature (11g) ⇒ http://www.oracle.com/technetwork/database/database-technologies/multimedia/overview/multimedia11gr2-featover-128418.pdf


Installation

Siehe https://docs.oracle.com/database/121/IMURG/ap_instl_upgrd.htm

Benötigt die JAVAVM, XDB, XML Option

Legt folgende User an:

  • ORDSYS
  • ORDPLUGINS ( hier können eigene Erweiterungen abgelegt werden)
  • SI_INFORMTN_SCHEMA
  • ORDDATA
  • MDSYS - Oracle Multimedia Locatorset

Prüfen ob die Option auch korrekt installiert wurde:

SYS>EXECUTE sys.validate_ordim;
 
PL/SQL PROCEDURE successfully completed.
 
 
SYS>SELECT version, STATUS FROM dba_registry WHERE comp_id='ORDIM';
 
VERSION                                            STATUS
------------------------------------------------- --------
12.1.0.2.0                                         VALID

Eine Beispiel Anwendung

Für ein Bautagebuch sollen auch die anfallenden Bilddaten gespeichert werden.

Einen User anlegen

Als SYS:

-- create the user
CREATE USER conbook IDENTIFIED BY conbook DEFAULT tablespace USERS TEMPORARY tablespace TEMP;
ALTER USER conbook quota unlimited ON USERS;
 
GRANT CONNECT, resource TO conbook;
 
 
-- create the info Archive DIRECTORY
CREATE OR REPLACE directory IMG_ARCHIVE AS 'C:\entwicklung\work\OracleMultiMedia\99-Images';
GRANT READ,WRITE ON directory IMG_ARCHIVE TO conbook;

Darauf achten das der Oracle User unter dem die 12c DB läuft, in meinen Fall der User ORARUN, auch die entsprechenden Rechte auf das Verzeichnis besitzt!

Im Dateisystem unter „C:\entwicklung\work\OracleMultiMedia\99-Images“ liegen in meinen Testfall nun 13 Bilder, 1.jpg bis 13.jpg. Diese werden später über das Directory Objekt in die Datenbank geladen.

Tabelle für die Bilddaten

Für das Speichern der Bilddaten wird der Datentyp ORDSYS.ORDIMAGE eingesetzt.

ORDSYS.ORDIMAGE hat die folgenden „Felder“:

  -------------------
  -- TYPE ATTRIBUTES
  -------------------
  source              ORDSource,
  height              INTEGER,
  width               INTEGER,
  contentLength       INTEGER,
  fileFormat          VARCHAR2(4000),
  contentFormat       VARCHAR2(4000),
  compressionFormat   VARCHAR2(4000),
  mimeType            VARCHAR2(4000),

Als User conbook

CREATE TABLE CONBOOK.CON_IMAGES
(
  ID       NUMBER(13),
  name     VARCHAR2(256)                        NOT NULL,
  remarks  VARCHAR2(4000),
  img      ORDSYS.ORDIMAGE,
  preview  ORDSYS.ORDIMAGE
)
LOB(img.source.localData)     STORE AS SECUREFILE
LOB(preview.source.localData) STORE AS SECUREFILE
;
 
 
ALTER TABLE CONBOOK.CON_IMAGES ADD (
  CONSTRAINT CON_IMAGES_PK
  PRIMARY KEY
  (ID)
  ENABLE VALIDATE);

Daten in die Tabelle laden

Einfache Laderoutine:

  CREATE OR REPLACE PROCEDURE loadConImg (p_id NUMBER , p_name varchar2 , p_remark varchar2)
 AS
   v_img_orig ORDSYS.ORDImage;
   v_img_preview ORDSYS.ORDImage;
   v_ctx RAW(64) := NULL;
  BEGIN
    -- save metadata and return a referenz on the img object
    INSERT INTO CON_IMAGES (ID, NAME, REMARKS,img,preview) 
      VALUES (p_id,p_name,p_remark,ORDImage(),ORDSYS.ORDImage.init())
      RETURNING img INTO v_img_orig;
 
 
    -- read the image data to the temporary object
  	v_img_orig.importFrom(v_ctx,'file','IMG_ARCHIVE',p_name);
 
    -- insert the temporary object into the image tabee    
    UPDATE CON_IMAGES SET img=v_img_orig WHERE id=p_id;
    commit;
 
     --create trumbnail image
    SELECT img.IMG,img.PREVIEW
        INTO v_img_orig,v_img_preview
        FROM CON_IMAGES img
    WHERE img.id=p_id
         FOR UPDATE;
 
    BEGIN
        -- create the preview image
        v_img_orig.processCopy('fileFormat=JFIF CompressionQuality=MAXINTEGRITY  maxScale=126 126',v_img_preview);
        -- only copy
        --v_img_orig.copy(v_img_preview);        
    EXCEPTION
        WHEN ORDSYS.ORDImageExceptions.NULL_DESTINATION THEN
            DBMS_OUTPUT.PUT_LINE('The destination is null');
        WHEN ORDSYS.ORDImageExceptions.DATA_NOT_LOCAL THEN
            DBMS_OUTPUT.PUT_LINE('Data is not local');
        WHEN ORDSYS.ORDImageExceptions.NULL_LOCAL_DATA THEN
            DBMS_OUTPUT.PUT_LINE('dest.source.localData attribute is null');
        WHEN others THEN
             DBMS_OUTPUT.PUT_LINE('Find this SQL ERROR:: '|| SQLCODE || ' - '||SQLERRM);    
    END;
 
    UPDATE CON_IMAGES SET preview=v_img_preview WHERE id=p_id;
    commit;
 
  END;
/

Damit das Image Objekt auch verwendet werden kann, muss es zuvor initialisiert werden.

Das kann ohne weitere Eigenschaften „leer“ erfolgen mit ORDSYS.ORDImage.init() für das am Anfang noch leere Preview Image oder mit folgenden Konstruktor ORDImage('file','IMG_ARCHIVE',p_name) um eine BFile Referenz auf das Bild im DB Direktory laden zu können oder mit eben als BLOB direkt in die Datenbank laden mit v_img_orig.importFrom(v_ctx,'file','IMG_ARCHIVE',p_name);.

Beispiel für das Laden mit der obigen Routine über SQL*Plus:

DELETE CON_IMAGES;
 
commit;
 
SET serveroutput ON
 
BEGIN
    FOR i IN 1 .. 13
    loop
      loadConImg ( p_id     => i
                 , p_name   => to_char(i)||'.JPG'
                 , p_remark => 'This is image '||to_char(i));
    END loop;
END;
/ 
 
SELECT * FROM CON_IMAGES;

Objekt Eigenschaften von ORDSYS.ORDImage ausgeben

Die wichtigsten Metadaten eines Bildes werden in dem Objekt ORDSYS.ORDImage als Attribute gespeichert.

Ausgeben mit:

SET serveroutput ON
 
DECLARE
 v_image ORDSYS.ORDImage;
BEGIN
 SELECT img 
    INTO v_image
   FROM CON_IMAGES img
  WHERE id  = 1; 
 
 DBMS_OUTPUT.PUT_LINE('image width        = ' || v_image.getWidth());
 DBMS_OUTPUT.PUT_LINE('image height       = ' || v_image.getHeight());
 DBMS_OUTPUT.PUT_LINE('image size         = ' || v_image.getContentLength());
 DBMS_OUTPUT.PUT_LINE('image file type    = ' || v_image.getFileFormat());
 DBMS_OUTPUT.PUT_LINE('image type         = ' || v_image.getContentFormat());
 DBMS_OUTPUT.PUT_LINE('image compression  = ' || v_image.getCompressionFormat());
 DBMS_OUTPUT.PUT_LINE('image mime type    = ' || v_image.getMimeType());
 
END;
/

Bzw. in SQL ausgeben:

SELECT   i.id
       , i.img.getHeight() height
       , i.img.getWidth() width
       , i.img.getMimetype() mimetype
       , i.img.getFileFormat() fileformat
       , i.img.getContentLength() LENGTH
FROM CON_IMAGES i ORDER BY i.id
/

EXIF Daten aus dem Bildern auslesen

Beispiel:

SET serveroutput ON
 
DECLARE 
  v_image     ORDSYS.ORDImage; 
  v_metadata  XMLSequenceType; 
BEGIN 
 
  SELECT img 
    INTO v_image
   FROM CON_IMAGES img
  WHERE id  = 1; 
 
  v_metadata := v_image.getMetadata('ALL'); 
 
  -- print the namespace of each metadata document
  FOR i IN 1..v_metadata.count LOOP
    DBMS_OUTPUT.PUT_LINE('namespace: ' || v_metadata(i).getNamespace() );
     DBMS_OUTPUT.PUT_LINE('-----------------------');
    DBMS_OUTPUT.PUT_LINE('CLOB Value: ' || v_metadata(i).getCLOBVal());    
  END LOOP; 
 
 
  EXCEPTION 
  WHEN ORDSYS.ORDImageExceptions.NULL_LOCAL_DATA THEN 
    DBMS_OUTPUT.PUT_LINE('source local data is null'); 
  WHEN ORDSYS.ORDImageExceptions.NULL_SOURCE THEN 
    DBMS_OUTPUT.PUT_LINE('source is null'); 
  WHEN OTHERS THEN
    RAISE;
END; 
/

Am einfachsten wird das am Anfang beim Laden gelesen und dann gleich in einer eigenen CLOB / XML Spalte gespeichert um später weiter verarbeitet werden zu können.



APEX 5.1 Integration

Ein Bild darstellen

In Apex 5 kann sehr einfach ein Bild auf ein auf einer Seite über ein Page Item vom Typ „Display Image“ dargestellt werden.

Dazu muss aber das Bild in einer BLOB Spalte vorliegen!

In unseren Fall liegt das Bild aber in einem Objekt vom Typ ORDSYS.ORDImage, d.h. wir müssen einfach nur den BLOB in dem Objekt auslesen.

Als „Based on wählen wir „Blob Column returned by SQL Statement“ .

SQL:

SELECT img.preview.source.localData     
        FROM CON_IMAGES img
    WHERE img.id=1

 Display Image with a page Item


Bilder in einem Bericht darstellen

Leider geht es nicht so einfach mit einen „Interactive Report“, wird einfach nur die BLOB Spalte im Bericht referenziert wird nur ein „[unsupported data type]“ angezeigt.

Wird nun die Image Spalte auf den Typ „Display Image“ gesetzt, brauchen wir einen View auf unsere Daten um die BLOB Spalte im Objekt in der Apex Maske auswählen zu können, Apex muss das selber erkennen, wir können die Spalte nicht mit „img.source.localData“ einfach selber angeben.

SQL für die BLOB View:

CREATE OR REPLACE VIEW CONBOOK.V_CON_IMAGES_BLOB
AS 
SELECT   ID
      , NAME
      , img.img.getMimetype() mimetype      
      , REMARKS
      , img.img.source.localData IMG
      , img.PREVIEW.source.localData AS PREVIEW
        FROM CON_IMAGES img;

 Type "Display Image" to show image in interactive report

Fehler „ORA-06502: PL/SQL: numeric or value error: character to number conversion error“

In der eigentlichen Berichtsabfrage darf nicht der BLOB des Bildes, sondern die Größe des Bildes muss referenziert werden.

SELECT  img.preview.getContentLength()  AS preview_image
      , ID
      , NAME
      , REMARKS 
 FROM CON_IMAGES img ORDER BY ID

Und schon funktioniert es!

Siehe auch ⇒ http://www.oralytics.com/2016/09/how-to-display-blob-image-in-apex-report.html


Bild bearbeiten

Über die Methode http://docs.oracle.com/database/121/AIVUG/ch_imgref.htm#AIVUG80485 process() kann das Bild Objekt direkt in der Datenbank bearbeitet werden.

Dazu wird in APEX einfach diese Funktion als Source für ein Image Display Item aufgerufen und dabei das entsprechende Kommando übergeben.

In der folgenden Routine wird die Watermark Funktion verwandt um im Fehlerfall den SQL Fehler direkt in das Bild zu schreiben.

Achtung! Hier ist noch ein böser Bug! der Temporäre Speicher wird nicht freigeben wenn die Watermark Funktion verwendet wird!

Beispiel Code um ein Bild zu verarbeiten:

CREATE OR REPLACE FUNCTION imgConverter(p_img_id NUMBER,p_command varchar2 DEFAULT 'maxScale 400 400')
RETURN BLOB
IS
   v_img_orig ORDSYS.ORDImage;
   v_img_work ORDSYS.ORDImage;
   v_img_blob_error BLOB;
   v_img_blob BLOB;
 
   v_command varchar2(4000):=p_command;
 
 
   --- Error handling
   v_watermark_prop ORDSYS.ORD_STR_LIST;   
   v_message varchar2(32000);
   v_error BOOLEAN:=TRUE;
   v_logging varchar2(2000);
 
BEGIN
    -- get the original image
    SELECT img.IMG
      INTO v_img_orig
      FROM CON_IMAGES img
    WHERE img.id=p_img_id;
 
    -- init the blob
     dbms_lob.createtemporary(v_img_blob     , TRUE, DBMS_LOB.SESSION);
     dbms_lob.createtemporary(v_img_blob_error, TRUE, DBMS_LOB.SESSION);
 
   BEGIN
 
        ORDSYS.ORDImage.processCopy( 
             imageblob  => v_img_orig.source.localData
            ,command    => v_command
            ,dest       => v_img_blob);
 
        v_error:=FALSE;
 
    EXCEPTION
        WHEN ORDSYS.ORDImageExceptions.NULL_DESTINATION THEN
            v_message:='The destination is null';
            v_error:=TRUE;
        WHEN ORDSYS.ORDImageExceptions.DATA_NOT_LOCAL THEN
            v_message:='Data is not local';
            v_error:=TRUE;
        WHEN ORDSYS.ORDImageExceptions.NULL_LOCAL_DATA THEN
            v_message:='dest.source.localData attribute is null';
            v_error:=TRUE;
        WHEN others THEN
            v_message:='Find this SQL ERROR:: '|| SQLCODE || ' - '||SQLERRM;    
            v_error:=TRUE;
    END;
 
     IF v_error THEN     
         -- print the error into the image as Watermark
         --'position=bottomright'
         v_watermark_prop := ordsys.ord_str_list(
                  'font_name=Arial',
                  'font_style=bold',
                  'font_size=20',
                  'text_color=red',
                  'position_x=10',
                  'position_y=20',
                  'transparency=1'
                );
 
 
        dbms_lob.createtemporary(v_img_blob_error, TRUE, DBMS_LOB.SESSION);       
 
        ORDSYS.ORDImage.applyWatermark(
                 imageBlob              => v_img_orig.source.localData   
                ,added_text           =>  substr(v_message,1,100)
                ,dest                  => v_img_blob_error    
                ,logging               => v_logging    
                ,watermark_properties => v_watermark_prop
            );
        v_img_work:=ORDSYS.ORDImage(v_img_blob_error);
        -----------------------------------------
        -- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1    
        -- dummy process to free memory
        -- BUG with applyWatermark !!
        -- if you call ORDSYS.ORDImage.processCopy the memory will be freed sucessfull
        -- strange behavior
        -- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
        -----------------------------------------
        ORDSYS.ORDImage.processCopy( 
             imageblob  => v_img_orig.source.localData
            ,command    => 'maxScale 200 200'
            ,dest       => v_img_blob);
     ELSE
        v_img_work:=ORDSYS.ORDImage(v_img_blob);
     END IF;   
 
 
 
     -- Free the temporary LOB
     --DBMS_LOB.CLOSE(v_img_blob);
     DBMS_LOB.FREETEMPORARY(v_img_blob_error);
     DBMS_LOB.FREETEMPORARY(v_img_blob);
 
 
 
     RETURN v_img_work.source.localData ; -- UTL_RAW.CAST_TO_RAW(v_logging); --
 
 
 
END imgConverter; 

Demnächst Mehr

Problem mit ORDImage.applyWatermark - data cartridge error IMG-00003: exhausted memory while processing image IMG-003: out of memory in (native) awt jpeg decode-

Da ich ja im obigen Code den BLOB nicht mehr so wirklich freigeben kann, laufen ich schnell nach ein paar Versuchen bei den obigen Oracle Fehler…. daher auch das etwas umständliche Kopieren der LOB's, leider hat das nicht wirklich geholfen, nach 8 Versuchen ist Schluss…. aber nur wenn die Methode ORDImage.applyWatermark betroffen ist!

ERROR:
ORA-29400: data cartridge error
IMG-00003: exhausted memory while processing image
IMG-003: out of memory in (native) awt jpeg decode
ORA-06512: at "ORDSYS.ORDIMERRORCODES", line 75
ORA-06512: at "ORDSYS.ORDIMERRORCODES", line 65
ORA-06512: at "ORDSYS.ORDIMG_PKG", line 471
ORA-06512: at "ORDSYS.ORDIMAGE", line 1623
ORA-06512: at "CONBOOK.IMGCONVERTER", line 67
ORA-06512: at line 1

Erste Lösungen:

Java Pool Size vergrößert

ALTER system SET java_pool_size=256M scope=memory sid='*';
 
-- kontrolle der aktuellen Verwendung mit:
 
SELECT * FROM v$javapool;

Dann funktioniert es etwas länger, Speicher läuft trotzdem voll …..

Laut Support Node ⇒ „ORDSYS.ORDImage Methods Fail Or Slow Down After Extended Processing; Consume Increasing Amounts Of Memory (Doc ID 267880.1)“ ist das Problem seit längeren evlt. bekannt, hier hilft wohl nur einen eigenen Bug dazu für 12c bei Oracle neu zu öffnen.

Ärgerlich …

Solution

Nach dem Aufruf von ORDSYS.ORDImage.applyWatermark nochmals eine gültige Operation mit ORDSYS.ORDImage.processCopy ausführen um den Stack der Session wieder richtig aufzuräumen.

Funktioniert, ist aber nicht sehr schön ….. 8-O


Bilder hochladen

Wie aber nun die Bilder über die Weboberfläche hochladen?

In APEX 5 wird intern die Tabelle APEX_APPLICATION_TEMP_FILES für das hochladen von Dateien verwendet.

Aus dieser Tabelle holen wir uns die Daten und schreiben die Daten in unsere Bild Tabelle.

Danach nicht vergessen das Bild in der APEX_APPLICATION_TEMP_FILES auch wieder zu löschen ( View auf wwv_flow_file_objects$)!

Um die Datei auszuwählen ein Page Item vom Typ „File Browse“ anlegen (in diesem Beispiel mit dem Namen P1_FILESELECTION )

Einen Submit Button auf der Page anlegen ( Action „Submit Page“)

Für die eigentliche Logik des Umkopieren der Daten dann ein Stück PL/SQL verwenden um die Daten in unsere Struktur einzulesen.

Der PL/SQL code für den „After Submit“ Process der Apex Seite:

DECLARE
  v_file_count pls_integer:=0;
 
  v_img_orig ORDSYS.ORDImage;
  v_img_preview ORDSYS.ORDImage;
 
  v_id CON_IMAGES.id%TYPE;
 
  v_message varchar2(4000):='Prozessing File Insert'||'<br/>';
 
BEGIN 
    IF :P1_FILESELECTION IS NOT NULL THEN
 
     v_message:= v_message||' Name of P1_FILESELECTION is '||:P1_FILESELECTION||'<br/>';
 
        SELECT COUNT(ID) INTO v_file_count
            FROM apex_application_temp_files
            WHERE name = :P1_FILESELECTION;
 
        IF v_file_count > 0  THEN
              FOR rec IN (SELECT
                    id,
                    application_id,
                    name,
                    filename,
                    mime_type,
                    created_on,
                    blob_content
                FROM apex_application_temp_files WHERE name = :P1_FILESELECTION ) loop
                   BEGIN
 
                    v_message:= v_message||' Read Image with filename '||rec.filename||'<br/>'; 
                       INSERT INTO CON_IMAGES (ID, NAME, REMARKS,img,preview) 
                        VALUES ( CON_IMAGES_SEQ.nextval
                                , rec.filename
                                , rec.filename ||' Mime type'||rec.mime_type||' Uploaded at'||to_char(rec.created_on,'dd.mm.yyyy hh24:mi')
                                , ORDSYS.ORDImage.init()
                                , ORDSYS.ORDImage.init() )
                        RETURNING id,img INTO v_id,v_img_orig;
 
                        v_img_orig:=ORDSYS.ORDImage(rec.blob_content);
 
                         UPDATE CON_IMAGES SET img=v_img_orig WHERE id=v_id;
                        commit;
 
                            --create trumbnail image
                        SELECT img.IMG,img.PREVIEW
                            INTO v_img_orig,v_img_preview
                            FROM CON_IMAGES img
                        WHERE img.id=v_id
                             FOR UPDATE;
 
 
                            -- create the preview image
                            v_img_orig.processCopy('fileFormat=JFIF CompressionQuality=MAXINTEGRITY  maxScale=126 126',v_img_preview);
                            -- only copy
                            --v_img_orig.copy(v_img_preview);        
 
 
                        UPDATE CON_IMAGES SET preview=v_img_preview WHERE id=v_id;
                        commit;
 
                         EXCEPTION
                            WHEN ORDSYS.ORDImageExceptions.NULL_DESTINATION THEN
                                v_message:=v_message||' The destination is null'||'<br/>';
                            WHEN ORDSYS.ORDImageExceptions.DATA_NOT_LOCAL THEN
                                 v_message:=v_message||' Data is not local'||'<br/>';
                            WHEN ORDSYS.ORDImageExceptions.NULL_LOCAL_DATA THEN
                                 v_message:=v_message||' dest.source.localData attribute is null'||'<br/>';
                            WHEN others THEN
                                  v_message:=v_message||' Find this SQL ERROR:: '|| SQLCODE || ' - '||SQLERRM;    
                        END;
 
                END loop; 
 
                -- clean the tempfile
                BEGIN
                    DELETE apex_application_temp_files  WHERE name = :P1_FILESELECTION;
                    commit;
                EXCEPTION    
                    WHEN others THEN
                       v_message:=v_message||' clean tempfile '|| SQLCODE || ' - '||SQLERRM||'<br/>';    
                 END;
        END IF;
    END IF; 
 
    apex_application.g_print_success_message := '<span style="color:yellow">'|| v_message || '</span>';
END;


Bilder vergleichen

Wir legen uns daher nun eine Tabelle mit ein paar Basis Bilder an um den Vergleichsalgorithmus zu testen.

DROP TABLE con_img_templates;
 
CREATE TABLE con_img_templates (
   ID            NUMBER(13)
  ,name          VARCHAR2(256) NOT NULL
  ,remarks       VARCHAR2(4000)
  ,img_template  ORDSYS.ORDIMAGE
  ,signature     ORDSYS.ORDImageSignature
)
LOB(img_template.source.localData)     STORE AS SECUREFILE
;
 
 
ALTER TABLE CONBOOK.con_img_templates ADD (
  CONSTRAINT con_img_templates_PK
  PRIMARY KEY
  (ID)
  ENABLE VALIDATE);
 
CREATE SEQUENCE CONBOOK.con_img_templates_SEQ;

In diese Tabelle laden wir nun ein blaues,rotes,gelbes Bild mit 100*100Pixel.

CREATE OR REPLACE PROCEDURE CONBOOK.loadTemplateImg (p_id NUMBER
                                       , p_name varchar2
                                       , p_remark varchar2)
 AS
 
   v_img_sig   ORDSYS.ORDImageSignature;
   v_img_orig ORDSYS.ORDImage;
   v_ctx RAW(4000) := NULL;
BEGIN
 
    -- save metadata and return a referenz on the img object
    INSERT INTO con_img_templates (ID, NAME, REMARKS,img_template,signature) 
      VALUES (p_id,p_name,p_remark,ORDImage('file','IMG_ARCHIVE',p_name),ORDImageSignature.init())
      RETURNING img_template,signature INTO v_img_orig,v_img_sig;
 
    -- read the image data to the temporary object
    v_img_orig.import(v_ctx);
    v_img_sig.generateSignature(v_img_orig);
 
    -- insert the temporary object into the image tabee    
    UPDATE con_img_templates SET img_template=v_img_orig,signature=v_img_sig WHERE id=p_id;
    commit;  
 
END;
/

Laden:

DELETE con_img_templates;
 
commit;
 
SET serveroutput ON
 
BEGIN
 
    loadTemplateImg ( p_id     => con_img_templates_SEQ.nextval
                 , p_name   => 'gruen.png'
                 , p_remark => 'This is image gruen');
 
    loadTemplateImg ( p_id     => con_img_templates_SEQ.nextval
                 , p_name   => 'weiss.png'
                 , p_remark => 'This is image weiss');          
 
    loadTemplateImg ( p_id     => con_img_templates_SEQ.nextval
                 , p_name   => 'blau.png'
                 , p_remark => 'This is image blau');                      
 
    loadTemplateImg ( p_id     => con_img_templates_SEQ.nextval
                 , p_name   => 'gelb.png'
                 , p_remark => 'This is image gelb');     
 
    loadTemplateImg ( p_id     => con_img_templates_SEQ.nextval
                 , p_name   => 'rot.png'
                 , p_remark => 'This is image rot');                                          
END;
/ 
 
SELECT * FROM con_img_templates;
commit;
ALTER TABLE con_images ADD (signature ORDSYS.ORDImageSignature);
UPDATE con_images SET signature=ORDImageSignature.init();

Vergleichen über den Score:

DECLARE
     v_i1_img       ORDSYS.ORDImage;
     v_i2_img       ORDSYS.ORDImage;
     v_i1_img_sig   ORDSYS.ORDImageSignature;
     v_i2_img_sig   ORDSYS.ORDImageSignature;
     v_score FLOAT;
     v_sim FLOAT;
     v_weight varchar2(256):='color="0.4",texture="0.10",shape="0.3", location="0.2"';
     v_name varchar2(255);
BEGIN
 
    -- read image
    SELECT img,signature,name INTO  v_i1_img , v_i1_img_sig ,v_name FROM CON_IMAGES WHERE id =6 FOR UPDATE;
 
     v_i1_img_sig.generateSignature(v_i1_img);
 
    FOR rec IN (SELECT img_template
                     ,signature
                     ,name FROM con_img_templates  FOR UPDATE)
    loop
         -- Compare two images for similarity based on image color:
         v_score:=ORDSYS.ORDImageSignature.evaluateScore(v_i1_img_sig, rec.signature,v_weight);
 
         v_sim:=ORDSYS.ORDImageSignature.ISSIMILAR(v_i1_img_sig, rec.signature, v_weight, 75);
 
         DBMS_OUTPUT.PUT_LINE('The score for compare '||rec.name||' with image ' ||v_name||' is ' || v_score);
         DBMS_OUTPUT.PUT_LINE('The sim score for simalar '||rec.name||' with image ' ||v_name|| 'is ' || v_sim);
         DBMS_OUTPUT.PUT_LINE('-----------------');
     END loop;
 
     commit;
 
END;
/

see ⇒ https://docs.oracle.com/cd/B14117_01/appdev.101/b10829/mm_imgref002.htm#sthref896

Um ein Bild zu suchen muss immer zuvor ein Beispiel Bild vorgegeben werden, mit diesem wird verglichen See ⇒ https://docs.oracle.com/cd/B14117_01/appdev.101/b10840/mm_cbr.htm#i605493



Quellen

Doku

Oracle Multimedia User's Guide 12c ⇒ http://docs.oracle.com/database/121/IMURG/toc.htm

Support
  • Information Center: Oracle Multimedia/Oracle interMedia (Doc ID 1546315.2)
Web
Audio
Diese Website verwendet Cookies. Durch die Nutzung der Website stimmen Sie dem Speichern von Cookies auf Ihrem Computer zu. Außerdem bestätigen Sie, dass Sie unsere Datenschutzbestimmungen gelesen und verstanden haben. Wenn Sie nicht einverstanden sind, verlassen Sie die Website.Weitere Information
prog/oracle_multimedia_12c.txt · Zuletzt geändert: 2019/01/13 10:06 von gpipperr