Anzeigen von Bildern in posgres

Hallo,

es geht um Anzeigen von Bildern.

Ich habe einen Datensatz von BIldern in einer Shape-Datei konvertiert (mittels qgis bekommt man die Koordinaten der BildmIttelpunkten).
Diese shape Datei wurde in einer Datenbank als Table gespeichert (mittels pgAdmin4). Die Spalten der Tabelle sind: gid, name, lat, lng, image location path, und geom.
Meine Frage ist: können wir eine Verlinkung zu den orginalen Bildern erstellen?. In pgAdmin befindet sich ein Tool: “view all geometries in this column”, kann man dies als Verlinkung zu den Bildern?

Grüße
Ahmed

Du musst den Pfad zum Bild nehmen, dein Anzeigeclient muss darauf Zugriff haben. Anzeigen kannst du das in QGIS indem du HTML-Maptips verwendest und dort den Pfad als Quelle eines IMG-Elements verwendest. Hat bei mir leider irgendwie noch nie funktioniert, ist aber so beschrieben.
Wenn du das direkt aus der Datenbank haben willst, kannst du ein bytea-Feld mit den Imagedaten befüllen. Diese kannst du dann z.B. base64-encoded in einem WMS-GetFeatureInfo im HTML darstellen. Ich mach so z.B. Bildvorschauen in oben genannten Formularen. Das PGAdmin-Tool zeigt vermutlich nur die Vektorgeometrie, also das geom-Feld, hier wahrscheinlich ein Punkt.
Gruß Uwe

Danke! hab diese Bildanzeige in qgis verwendet und zwar über ein CONCATINATION Command durchgeführt. Klar hier muss man den Pfad zu den Bildern eingeben. HTML Maptips hab ich noch nicht getestet.
Mein Ziel ist eigentlich direkt aus der Datenbank die Bilder zu zeigen. Daher finde ich deinen Vorschlag “ein bytea-Feld” eine Lösung sein könnte. Aber leider hab ich keine Erfahrung damit. Hast du schon dafür ein Tutorial, Link, usw.? in der Datenbank (wo die Bilder als shape Datei gespeichrt wurden) gibt es ja dieses Feld geom, das zu dem je PUnkt gehört.
Gruß
Ahmed

Die Bilder sind nicht als shape gespeichert, sondern nur deren Position. Dazu der Pfad zur Datei. Was im Feld geom ist, kannst du mit

select st_astext(geom) from tabelle

anschauen. Das ist zwar ein Binärfeld, enthält aber nur die Geometrie in WKB.

Ein Tutorial oder so hab ich nicht. Ich nutze dafür ein Pythonscript, dass mir das Bild verkleinert und samt allen anderen Informationen, die ich haben will, in die Datenbank schreibt. Dafür nutze ich die Bilbliothek PIL, die das zur Verfügung stellt (siehe Code unten). Im Skript werden verkleinerte Bilder erzeugt, wenn du ganze Bilder speichern willst musst du das entsprechend anpassen.
Für die base64-codierte Ausgabe nutze ich die Postgres-Funktionen (encode(t1.thumbnail, ‘base64’::text) AS thumbnail,) in einem View, der vom Geoserver als Layer eingebunden wird. Damit wird wird ein String erzeugt, der im HTML als Bild interpretiert werden kann.
Das funktioniert in etwa so (aus dem GetFeatureInfo-HTML):

Die ${}-Ausdrücke sind die Variablen im HTML, die die Daten enthalten. Wie das konkret aussieht, hängt von deinem Layer und der Template/Script-Engine ab, hier ist es das, was der Geoserver verwendet.

Grüße
Uwe

#! /usr/bin/env python

import os
from io import BytesIO
import datetime
import psycopg2 as p
from PIL import Image

db = p.connect(database='db', host='server', port=5432, user='me',
                password='pwd')

def make_thumb(path, sizex=200, sizey=200):
    stream  = BytesIO()
    size = sizex, sizey
    try:
        img = Image.open(path)
        thumb = img.copy()
    except:
        print path
        exit
    thumb.thumbnail(size, Image.ANTIALIAS)
    thumb.save(stream, 'PNG')
    return stream.getvalue()

if __name__ == '__main__':

    directory = '/irgend/ein/directory/mit/bildern/' 
    files = [os.path.join(directory, f) for f in os.listdir(directory)]
    i = 0
    
    for f in files:
        path, filename = os.path.split(f)
        prf = os.path.splitext(filename)[0].split('_')
        values = {'prjid': prf[0], 
                'locid': prf[1], 
                'recid': prf[2],
                'type': 'png',
                'shortname': prf[4],
                'longname': filename,
                'scheme': 'file://',
                'path': f,
                'thumb': p.Binary(make_thumb(f)),
                'src_id': 1
                }
        ins = '''
              insert into sep3.resources(prjid, locid, recid, type, longname, shortname, scheme, path, thumbnail, src_id)
                values (%(prjid)s, %(locid)s, %(recid)s, '%(type)s', '%(longname)s', '%(shortname)s', '%(scheme)s', '%(path)s', %(thumb)s, %(src_id)s);  
              '''
        cur1 = db.cursor()
        cur1.execute(ins%values)
        db.commit()
        print datetime.datetime.now().isoformat(), i, f
        i += 1

Hi,
danke für die Info.
Ja stimmt, die shap Datei enthält nur die Geometrie der MIttelhauptpunkten je Bild.

Für dein Skrip hab noch ein paar Fragen:

  • Zeile 9: hier definierst du die gezielten Datenbank, wo die verklinerten Bilder abzuspeichen sind, oder?
  • Zeile 27: muss man hier den Pfad zu den Input-Bildern eintragen?
  • Zeile 31 bis 44: meinst du hier, die Info, die man will von den Bildern?

und noch letzte Frage: kannst du bitte mir die HTML Verbindung mir den Bildern erklären? Sollte ich die BIlder erst in Geoserver publizieren?

Grüße
Ahmed

Hallo!

Zeile 9: Hier musst du deine Datenbankverbindung eintragen. Infos dazu gibt die Doku von psycopg2
Zeile 27: Hier steht dein Verzeichnis mit Bildern. Zeile 28 macht da eine Liste mit Pfaden draus.
Zeile 31-44: Hier wird die Liste abgearbeitet. Es werden einige Attribute gesetzt, die in ein Dict geschrieben und anschliessend an das Insert verfüttert werden. Das kannst/musst du an deine Bedürfnisse anpassen. Der wichtige Punkt ist hier die Zeile 42, die aus dem Bild aus der Liste ein Thumbnail macht. Hier solltest du auch das ganze Bild verarbeiten können, die Doku zu PIL sollte da weiterhelfen. Das resultierende Bild wird dann als Binärdaten in die Datenbank geschrieben.

Wie gesagt, ein Beispiel, du musst es sicher für dich anpassen.

Geoserver: Ich habe hier einen WMS mit Geoserver, der mir geologische Aufschlüsse mit Fotos als Webkarte bereitstellt. Man kann, vereinfacht beschrieben,auf einen Punkt in der dargestellten Karte klicken und bekommt eine Liste mit Vorschaubildern. Dies ist ein HTML-Dokument, das in einem kleinen Fenster dargestellt wird. Wenn man auf ein Vorschaubild klickt, öffnet sich ein neues Browserfenster mit der großen Ansicht des Bildes, dazu brauche ich den Pfad zum Bild. Ich wollte die volle Ansicht nicht in der Datenbank haben, da ich die Bilder auch in anderen Kontexten nutzen möchte. Selbstverständlich kann man dies auch in jedem anderen HTML-Dokument tun, dazu musst du die binären Daten in der Datenbank base64-encoded übergeben, sonst kann der HTML-Client nichts damit anfangen. Oder wie gesagt, du kannst den Pfad zum Bild als Quelle nutzen.
Im obigen Beispiel ist das href-Attribut der Link zum File, das src-Attribut im img-Tag sind die Binärdaten, sieht wie jede HTML-Templatesprache etwas wild aus…

Grüße Uwe

Hallo,

ich hab versucht, das Skript mit meinen Daten anzupassen. Erst hab nur drei Bilder in einem Ordner verwendet.
In der Zeile 27 hab den Pfad definiert. Nach dem Runing des Skriptes hab einen Fehler bekommen und zwar wie folgend:

line 35, in
‘locid’: prf[1],
IndexError: list index out of range

Leider konnte ich diesen Fehler nicht beheben. Daher bitte um weitere Hilfe

Gruß
Ahmed

Hallo!
Diese Zeile zerlegt den Filenamen (der einen best. Aufbau hat, da automatisiert erzeugt) und macht daraus eine Liste.

prf = os.path.splitext(filename)[0].split('_')

In der Zeile, in der der Fehler auftaucht, wird versucht, auf ein Element der Liste über seinen Index zuzugreifen, was bei dir scheitern muss, weil dein Filename nicht entsprechend aufgebaut ist und deine ‘Liste’ nur das Element [0] enthält.
Bei mir sind das verschiedene Schlüsselwerte, das hat aber für deine Daten keine Bedeutung. Diese Stelle und das insert, dass die Daten dann aufnimmt, musst du an deine Datenbanktabelle anpassen.

Hast du schon mal mit Python gearbeitet?

Grüße
Uwe