Seite 1 von 2

Bild aus dem Speicher in DB speichern und wieder laden

Verfasst: 24.12.2020 00:59
von The_Dark_Zim-.-
Moin,

ich würde gerne ein Bild, dass zuvor mit loadImage() geladen wurde, als blob in einer sqlite DB hinterlegen und später wieder laden.
Dabei will ich aber nicht den Umweg über eine Datei gehen, sprich das Bild direkt aus dem Speicher nehmen und später einfach aus der DB laden weiter nutzen. Geht das so ohne weiteres?
Ich hatte mir catchimage angesehen, aber wenn ich das richtig sehe, muss das Bild als "Datei" im Speicher sein.

Pseudocode, der so nicht funktioniert:
img = loadImage(#pb_any, "Bild.jpg")
SetDatabaseBlob(0,0,@img, imgsize)
...

GetDatabaseBlob(0,0,*img, blobsize)
img = catchimage(#pb_any, *img, blobsize)
...

Leider geht es so halt nicht. Einzige Möglichkeit, die ich momentan sehe, ist das Bild temporär zu speichern und die Datei als Blob zu speichern und diese dann zu laden.

Mit freundlichen Grüßen
Zim

Re: Bild aus dem Speicher in DB speichern und wieder laden

Verfasst: 24.12.2020 01:45
von STARGÅTE
Guck dir mal EncodeImage() an.
Es gibt dir einen Speicherpuffer des "gespeicherten" Bilds zurück.

Re: Bild aus dem Speicher in DB speichern und wieder laden

Verfasst: 28.12.2020 01:38
von kpeters58
Etwa so?

Code: Alles auswählen

 Procedure LoadImageGadgetFromDB(DatabaseHandle, SQLExpr.s, ImageGadget, ColIndex)
  Protected tmpimage, bytecount, *membuffer
  
  If DatabaseQuery(DatabaseHandle, SQLExpr)
    If NextDatabaseRow(DatabaseHandle)
      bytecount = DatabaseColumnSize(DatabaseHandle, ColIndex) 
      If bytecount > 0
        *membuffer = AllocateMemory(bytecount)
        If *membuffer
          GetDatabaseBlob(DatabaseHandle, ColIndex, *membuffer, bytecount)
          tmpimage = CatchImage(#PB_Any, *membuffer, bytecount)
          SetGadgetState(ImageGadget, ImageID(tmpimage))
          FreeMemory(*membuffer)
          FreeImage(tmpimage)
        Else ; allocation error
          FinishDatabaseQuery(DatabaseHandle)
          ProcedureReturn #False
        EndIf  
      Else ; no data in column
        FinishDatabaseQuery(DatabaseHandle)
        ProcedureReturn #False
      EndIf  
    Else ; no record found
      FinishDatabaseQuery(DatabaseHandle)
      ProcedureReturn #False
    EndIf  
    FinishDatabaseQuery(DatabaseHandle)
    ProcedureReturn #True
  Else ; query failed
    ProcedureReturn #False
  EndIf
EndProcedure

Re: Bild aus dem Speicher in DB speichern und wieder laden

Verfasst: 28.12.2020 08:49
von Pelagio
Guten Morgen,

ich weiß nicht aber man sollte sich mal die Hilfe genau anschauen, besonders 'SetDatabaseBlob' einschließlich 'DatabaseUpdate'
; SQLite, MySQL und ODBC verwenden den gleichen Syntax, um Blobs einzufügen. Diese werden mit dem '?' Zeichen angegeben.
;
; Die Datenbank sollte geöffnet sein und eine Tabelle PHOTOS mit 3 Feldern (BLOB, VARCHAR(255), BLOB) haben.
;
SetDatabaseBlob(0, 0, ?Picture, PictureLength)
SetDatabaseBlob(0, 1, ?SmallPicture, SmallPictureLength)
DatabaseUpdate(0, "INSERT INTO PHOTOS (picture, name, small_picture) values (?, 'my description', ?);")

Re: Bild aus dem Speicher in DB speichern und wieder laden

Verfasst: 28.12.2020 14:51
von The_Dark_Zim-.-
Hey,

danke für eure Antworten. Daten in die DB und wieder heraus zu bekommen ist nicht das Problem. Die Funktion CatchImage scheint jedoch quasi eine Datei zu erwarten. Wenn jedoch den Speicherbereich eines Bildes verwendet, funktioniert es nicht. Vermutlich muss ich wohl die Datei einlesen und dann mit CatchImage arbeiten, sowohl beim ersten Laden, als auch beim Speichern und wieder laden.

Re: Bild aus dem Speicher in DB speichern und wieder laden

Verfasst: 28.12.2020 15:28
von HeX0R
...oder Du liest die Antwort von STARGÅTE nochmal.

Re: Bild aus dem Speicher in DB speichern und wieder laden

Verfasst: 28.12.2020 16:18
von The_Dark_Zim-.-
Bei EncodeImage() habe ich das "Problem", dass ich jedes mal entscheiden muss, welcher Dateityp bzw. Bildtyp gewählt werden soll.
Vllt. zum besseren Verständnis, was ich überhaupt mache bzw. vor habe: User legt Datensatz an, dabei hat er auch die Möglichkeit ein Bild zu hinterlegen. Dieses muss er entspechend auswählen, file requestor dingen. Dabei hatte ich bisher das Bild direkt per LoadImage laden wollen und in ein ImageGadget gesetzt. Außerdem noch den Dateinamen gemerkt.

Hier ist es jetzt einfacher, für mich, statt direkt über LoadImage die Datei in einen *Buffer zu lesen und dann den Buffer sowohl für das ImageGadget ( CatchImage) als auch für die DB zu verwenden. Dateityp interessiert mich dann nicht mehr :)

Re: Bild aus dem Speicher in DB speichern und wieder laden

Verfasst: 28.12.2020 22:08
von STARGÅTE
Wenn du das Bild (wobei das Format ja egal ist) einfach von einer Datei in einen Buffer laden willst, nimmst du einfach ReadFile ließt die Gesamte Datei in einen Memory (ReadData) und später kannst du dann diesen Speicher mit CatchImage() laden.

Und ja, das Bild in dann "codiert" (als "Datei") in der Datenbank, das rohe Bild kannst du da auch speichern, aber dann musst du halt das Format definieren. Das ginge dann z.B. indem du DrawingBuffer() nutzt, aber das geht glaube ich zuweit.

Wenn du bereits ein Image hast, dann halt EncodeImage, und da du musst das Format festlegen.

Re: Bild aus dem Speicher in DB speichern und wieder laden

Verfasst: 30.12.2020 18:59
von kpeters58
EncodeImage functioniert auch ohne Angabe des Formats (siehe unten). ImagePlugin ist in der Hilfe als optional ausgewiesen.

Ich nehme mal an, daß EncodeImage das Format des vorliegenden Images erkennt und als Default verwendet.
Format scheint also nur erforderlich zu sein, wenn das vorliegende Format geändert werden soll (von .PNG zu .JPG oder so...)

Code: Alles auswählen

Procedure SaveLoadedImageToDB(DatabaseHandle, SqlExpr.s, Image)  
  Protected *membuffer, result
  
  If IsImage(Image)
    *membuffer = EncodeImage(Image)
    SetDatabaseBlob(DatabaseHandle, 0, *membuffer, MemorySize(*membuffer))
    result = DatabaseUpdate(DatabaseHandle, SQLExpr) ; sqlexpr = either an insert or update, must use parameter substitution
    FreeMemory(*membuffer)    
    ProcedureReturn result
  Else
    ProcedureReturn #False
  EndIf  
EndProcedure

Re: Bild aus dem Speicher in DB speichern und wieder laden

Verfasst: 30.12.2020 21:27
von STARGÅTE
kpeters58 hat geschrieben:EncodeImage functioniert auch ohne Angabe des Formats (siehe unten). ImagePlugin ist in der Hilfe als optional ausgewiesen.

Ich nehme mal an, daß EncodeImage das Format des vorliegenden Images erkennt und als Default verwendet.
Format scheint also nur erforderlich zu sein, wenn das vorliegende Format geändert werden soll (von .PNG zu .JPG oder so...)
Nein so ist es nicht.
Wird das ImagePlugin weggelassen, wird das Image im BMP-Format gespeichert.
Ferner kann EncodeImage kein Format "erkennen". Ein Image liegt in Pure Basic im rohen Pixel-Format vor (siehe DrawingBufferPixelFormat()). Wird ein JPG oder PNG in PureBasic eingeladen, ist das Format (also der Kompressionsalgorithmus) "weg". Du musst also in jedem Fall entscheiden wie dein Bild kodiert werden soll (verlustbehaftet in JPG, mit Alpha-Kanal in PNG, usw.).