B4J Question File chooser for image pick

microbox

Active Member
Licensed User
Longtime User
I'm trying to construct code that will use file chooser to open an image file (jpg) in preparation to save it to Mysql database as blob file. The code I'm experimenting is a copy and paste from different thread.
B4X:
Sub btnfd_MouseClicked (EventData As MouseEvent)
    Dim f As String = fc.ShowOpen(MainForm)
    If f <> "" Then
        TextArea1.Text = File.ReadString(f, "")
    End If
  
    For Each row() As Object In result.Rows
    Dim out As OutputStream = File.OpenInput("C:\AB4JProjects","caption.jpg")
    Dim In As InputStream
    Dim Buffer() As Byte
    Buffer = row(0) ' gives error here, says that can not convert a string to byte array
    In.InitializeFromBytesArray(Buffer, 0, Buffer.Length)
    File.Copy2(In, out)
    out.Close
End Sub

1. I don't really understand, how result.rows be used here?
2. How can I replace File.OpenInput("C:\AB4JProjects","caption.png") after I select using File chooser?

I appreciate any input and thanks for time.
 

microbox

Active Member
Licensed User
Longtime User
Can anyone share a code to save an image to a table using RDC2? This will serve as my starting point and understand how it works.

Thank you in advance.
 
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
hi, i may help you.

What do you want to do first? Save the image to the DB?

if that is so, you mysql (if you are using this DB, needs a BLOB column

the code for that is:

With my example you need stringutils library, but i believe it is not necessary, it helps me tho.
B4X:
private Sub ImageToBlob(dir As String, f As String) As String
        Dim InputStream1 As InputStream
        InputStream1 = File.OpenInput(dir,f)
       
        Dim su As StringUtils
       
        Dim OutputStream1 As OutputStream
        OutputStream1.InitializeToBytesArray(1000)
        File.Copy2(InputStream1, OutputStream1)
        Dim Buffer() As Byte 'declares an empty array
        Buffer = OutputStream1.ToBytesArray
        Return su.EncodeBase64(Buffer)
End Sub
 
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
And the counterside:

'use it like this

B4X:
'use it like this
dim byStr as string = sql1.execquerysingleresult("SELECT image FROM table1 WHERE id = 1") '(or your prefered DB read method)

    Dim im As Image
    im.Initialize2(blobToIO(byStr))

public Sub blobToIO(bySt As String) As InputStream
    Dim su As StringUtils
    Dim by() As Byte = su.DecodeBase64(bySt)
  
    Dim InputStream1 As InputStream
    InputStream1.InitializeFromBytesArray(by, 0, by.Length)
'    InputStream1.Close  
    Return InputStream1
End Sub
 
Upvote 0

microbox

Active Member
Licensed User
Longtime User
Hi Enrique, Can you verify if I am on the right track, I'm using the following code for saving image to mysql
B4X:
    Dim len As Int
    Dim filename As String
    fc.Title="Select Photo"
    fc.InitialDirectory = "C:\Users\MicroboxMac\Pictures\Saved Pictures"
    fc.SetExtensionFilter("Image",Array As String("*.jpg","*.png","*.bmp"))
    len = fc.InitialDirectory.Length
  
    Dim f As String = fc.ShowOpen(MainForm)
    If f <> "" Then
    filename = f.SubString(len+1)
    Log(filename & " > " & f)
    Dim bmp As Image
    bmp.Initialize("C:\Users\MicroboxMac\Pictures\Saved Pictures",filename)
    ImageToBytes(bmp)
    '------------------------------------------------------------------------
    Dim cmd As DBCommand
    cmd.Initialize
    'Defined as sql.insert in the RDC file config.properties located in the files folder
     cmd.Name = "insert"
    'Set the parameter defined as sql.insert=INSERT INTO notes (description, content) VALUES(?, ?)
    cmd.Parameters = Array As Object("Test3", ImageToBytes(bmp))
    'Trigger the command. The result is handled by JobDone.
    reqManager.ExecuteCommand(cmd, "insert")
  
    Log("Insert table Triggered")
    End If

And this what looks like in phpMyAdmin
screen1.png


When I click a button in B4J to query the content of my table

screen2.png

Now I'm trying to read and display the image from table with id = 2
B4X:
Sub btnOpen_MouseClicked (EventData As MouseEvent)
    Dim byStr As String
  
    Dim cmd As DBCommand
       cmd.Initialize
    'Defined as sql.select2 in the RDC file config.properties located in the files folder
       cmd.Name = "select1"
    'Trigger the query. The result is handled by JobDone.
    reqManager.ExecuteQuery(cmd, 0, "select1")
    'Dlg.ToastMessage(DlgMsgWait, DlgMsgWaitDuration)
    Log("Select1 Table Query triggered")
    Dim im As Image
    im.Initialize2(blobToIO(byStr))

   ImageView1.SetImage(im)
End Sub

but I'm getting a blank on ImageView1 probably due to byStr is empty.

Thank you so much for the time.
 
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Technically you can save an image with ImageToBytes as Erel suggested, but i tested it once and for some reason my DB did not stored it correctly, that is why i created my version with ImageToBlob.

change your first code for this:
B4X:
    Dim fc As FileChooser
    fc.Initialize
    fc.Title="Select Photo"
    fc.InitialDirectory = "C:\Users\MicroboxMac\Pictures\Saved Pictures"
    fc.SetExtensionFilter("Image",Array As String("*.jpg","*.png","*.bmp"))
   
    Dim f As String = fc.ShowOpen(MainForm)
    If f <> "" Then
        Dim BlobedImage As String = ImageToBlob(f)
        '------------------------------------------------------------------------
        Dim cmd As DBCommand
        cmd.Initialize
        'Defined as sql.insert in the RDC file config.properties located in the files folder
        cmd.Name = "insert"
        'Set the parameter defined as sql.insert=INSERT INTO notes (description, content) VALUES(?, ?)
        cmd.Parameters = Array As Object("Test3", BlobedImage)
        'Trigger the command. The result is handled by JobDone.
'        reqManager.ExecuteCommand(cmd, "insert")
        Log("Insert table Triggered")
    End If

private Sub ImageToBlob(FileChooserResult As String) As String
    Dim InputStream1 As InputStream
   
    Dim directory As String =FileChooserResult.SubString2(0,FileChooserResult.LastIndexOf("\"))
    Dim FileName As String = FileChooserResult.SubString(FileChooserResult.LastIndexOf("\") + 1)
    InputStream1 = File.OpenInput(directory,FileName)
       
    Dim su As StringUtils
       
    Dim OutputStream1 As OutputStream
    OutputStream1.InitializeToBytesArray(1000)
    File.Copy2(InputStream1, OutputStream1)
    Dim Buffer() As Byte 'declares an empty array
    Buffer = OutputStream1.ToBytesArray
    Return su.EncodeBase64(Buffer)
End Sub

i modified my code a bit so you can pass the whole string that Filechooser gives to you.
 
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Then to retrieve you will do it like this:

B4X:
sub btnOpen_MouseClicked (EventData As MouseEvent)
    Dim byStr As String
    Dim cmd As DBCommand
       cmd.Initialize
    'Defined as sql.select2 in the RDC file config.properties located in the files folder
       cmd.Name = "select1"
    'Trigger the query. The result is handled by JobDone.
    reqManager.ExecuteQuery(cmd, 0, "select1")

    Wait For(j) JobDone(j As HttpJob)
    If j.Success Then
        req.HandleJobAsync(j, "req")
        Wait For (req) req_Result(res As DBResult)

         dim r() as row = res.rows.get(0)

         Dim im As Image
         im.Initialize2(blobToIO(r(1)) 'The column index of your query. 

         ImageView1.SetImage(im)
     end if
End Sub

public Sub blobToIO(bySt As String) As InputStream
    Dim su As StringUtils
    Dim by() As Byte = su.DecodeBase64(bySt)
    Dim InputStream1 As InputStream
    InputStream1.InitializeFromBytesArray(by, 0, by.Length)
'    InputStream1.Close  
    Return InputStream1
End Sub
 
Upvote 0

microbox

Active Member
Licensed User
Longtime User
@enrique, sorry to bother again but I have an error when compiling
B4X:
B4J version: 4.70
Parsing code.    Error
Error parsing program.
Error description: Duplicate sub: blobtoio
Occurred on line: 181 (Main)
public Sub BlobToIO(bySt As String) As InputStream
This is my whole code
B4X:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private btnfile As Button
    Private TextField1 As TextField
    Private fc As FileChooser
    Private btnsave As Button

    Private reqManager As DBRequestManager
    'Define the result from a query. The columns and Rows to be used further, like listing in a tableview
    Type DBResult (Tag As Object, Columns As Map, Rows As List)
    'The database commands are defined in the RDC config.properties file
    Type DBCommand (Name As String, Parameters() As Object)
 
    Private btnOpen As Button
    Private ImageView1 As ImageView
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    fc.Initialize
    reqManager.Initialize(Me, "http://localhost:17178/rdc")
    MainForm = Form1
    MainForm.RootPane.LoadLayout("Layout1") 'Load the layout file.
    MainForm.Show
 
End Sub

Sub btnfile_MouseClicked (EventData As MouseEvent)
'------------------------------------------------------------------------------
Dim fc As FileChooser
    fc.Initialize
    fc.Title="Select Photo"
    fc.InitialDirectory = "C:\Users\MicroboxMac\Pictures\Saved Pictures"
    fc.SetExtensionFilter("Image",Array As String("*.jpg","*.png","*.bmp"))

    Dim f As String = fc.ShowOpen(MainForm)
    If f <> "" Then
        Dim BlobedImage As String = ImageToBlob(f)
        '------------------------------------------------------------------------
        Dim cmd As DBCommand
        cmd.Initialize
        'Defined as sql.insert in the RDC file config.properties located in the files folder
        cmd.Name = "insert"
        'Set the parameter defined as sql.insert=INSERT INTO notes (description, content) VALUES(?, ?)
        cmd.Parameters = Array As Object("Test1", BlobedImage)
        'Trigger the command. The result is handled by JobDone.
        reqManager.ExecuteCommand(cmd, "insert")
        Log("Insert table Triggered")
    End If

'-------------------------------------------------------------------------------------------
End Sub

private Sub ImageToBlob(FileChooserResult As String) As String
    Dim InputStream1 As InputStream

    Dim directory As String =FileChooserResult.SubString2(0,FileChooserResult.LastIndexOf("\"))
    Dim FileName As String = FileChooserResult.SubString(FileChooserResult.LastIndexOf("\") + 1)
    InputStream1 = File.OpenInput(directory,FileName)
    
    Dim su As StringUtils
    
    Dim OutputStream1 As OutputStream
    OutputStream1.InitializeToBytesArray(1000)
    File.Copy2(InputStream1, OutputStream1)
    Dim Buffer() As Byte 'declares an empty array
    Buffer = OutputStream1.ToBytesArray
    Return su.EncodeBase64(Buffer)
End Sub


Public Sub ImageToBytes(Image As Image) As Byte()
   Dim out As OutputStream
   out.InitializeToBytesArray(0)
   Image.WriteToStream(out)
   out.Close
   Log("Done!")

   Return out.ToBytesArray
End Sub

'
public Sub blobToIO(bySt As String) As InputStream
    Dim su As StringUtils
    Dim by() As Byte = su.DecodeBase64(bySt)

    Dim InputStream1 As InputStream
    InputStream1.InitializeFromBytesArray(by, 0, by.Length)
    InputStream1.Close
    Return InputStream1
End Sub

Sub btnsave_MouseClicked (EventData As MouseEvent)
    Dim cmd As DBCommand
       cmd.Initialize
    'Defined as sql.select2 in the RDC file config.properties located in the files folder
       cmd.Name = "select"
    'Trigger the query. The result is handled by JobDone.
       reqManager.ExecuteQuery(cmd, 0, "select")
    'Dlg.ToastMessage(DlgMsgWait, DlgMsgWaitDuration)
    Log("Select Table Query triggered")
End Sub

Sub JobDone(Job As HttpJob)
   If Job.Success = False Then
     Log("Error: " & Job.ErrorMessage)
   Else
     If Job.JobName = "DBRequest" Then
       reqManager.HandleJobAsync(Job, "ReqManager")
     End If
   End If
   Job.Release
End Sub

Sub ReqManager_Result(result As DBResult)
   'reqManager.PrintTable(result)
   reqManager.PrintTable(result)
   Log("Done here")
   'reqManager.PrintTable(result)
End Sub


Sub btnOpen_MouseClicked (EventData As MouseEvent)
    Dim byStr As String
    Dim cmd As DBCommand
       cmd.Initialize
    'Defined as sql.select2 in the RDC file config.properties located in the files folder
       cmd.Name = "select1"
    'Trigger the query. The result is handled by JobDone.
    reqManager.ExecuteQuery(cmd, 0, "select1")

    Wait For(j) JobDone(j As HttpJob)
    If j.Success Then
        req.HandleJobAsync(j, "req")
        Wait For (req) req_Result(res As DBResult)

         Dim r() As row = res.rows.get(0)

         Dim im As Image
         im.Initialize2(blobToIO(r(1)) 'The column index of your query.

         ImageView1.SetImage(im)
     End If
End Sub

public Sub BlobToIO(bySt As String) As InputStream
    Dim su As StringUtils
    Dim by() As Byte = su.DecodeBase64(bySt)
    Dim InputStream1 As InputStream
    InputStream1.InitializeFromBytesArray(by, 0, by.Length)
'    InputStream1.Close
    Return InputStream1
End Sub
When commenting the 2nd BlobToIO function gives this error message
B4X:
B4J version: 4.70
Parsing code.    Error
Error parsing program.
Error description: Invalid number of parentheses.
Occurred on line: 145 (Main)
         im.Initialize2(blobToIO(r(1)) 'The column index of your query
 
Last edited:
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Hi microbox

Just add another parentesis at the end of this line

B4X:
im.Initialize2(blobToIO(r(1))) 'like thi
 
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
you are using B4J 5.0, my example was for 5.50

to convert it to B4J 5.0 (your version)
Delete this code:
B4X:
    Wait For(j) JobDone(j As HttpJob)
    If j.Success Then
        req.HandleJobAsync(j, "req")
        Wait For (req) req_Result(res As DBResult)

         Dim r() As row = res.rows.get(0)

         Dim im As Image
         im.Initialize2(blobToIO(r(1)) 'The column index of your query.

         ImageView1.SetImage(im)
     End If

add this new code sub

B4X:
'Delte the jobDone you already have!
sub jobDone(j as httpJob)
  If j.Success Then
        req.HandleJobAsync(j, "req")
        Wait For (req) req_Result(res As DBResult)

         Dim r() As row = res.rows.get(0)

         Dim im As Image
         im.Initialize2(blobToIO(r(1)) 'The column index of your query.

         ImageView1.SetImage(im)
     End If
end sub
 
Upvote 0

microbox

Active Member
Licensed User
Longtime User
I will upgrade later when I get the idea how this works but for now I will use this version.
Kindly check the attached file...
BTW I want to mention that this code "reqManager.ExecuteQuery(cmd, 0, "select1")" where select1 looks like this in my config properties.
B4X:
 sql.select1=select image FROM myfie WHERE id = 3
But it points only to id = 3, can you suggest how to make this dynamic?
 

Attachments

  • BlobTest.zip
    58.3 KB · Views: 258
Upvote 0

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
Microbox

attached is your project without errors, i get rid of the features of 5.50,

For this to work, you have to change:
B4X:
sql.select1=select image FROM myfie WHERE id = ?

now you can pass the parameter to choose any of the Ids, in the code is in here:

B4X:
Sub btnOpen_MouseClicked (EventData As MouseEvent)
    Dim cmd As DBCommand
       cmd.Initialize
    'Defined as sql.select2 in the RDC file config.properties located in the files folder
       cmd.Name = "select1"
      Dim id As Int = 2
      cmd.Parameters = Array As Object(id)
    'Trigger the query. The result is handled by JobDone.
    reqManager.ExecuteQuery(cmd, 0, "select1")
End Sub

i hope it works as you intend.
 

Attachments

  • BlobTest.zip
    58.1 KB · Views: 245
Upvote 0

microbox

Active Member
Licensed User
Longtime User
Hi Enrique, I'm sorry but I still getting error when I click the Open button(loading image from table).
 

Attachments

  • s3.png
    s3.png
    410 KB · Views: 228
Upvote 0

microbox

Active Member
Licensed User
Longtime User
I upgrade my B4J to 5.51. No error on compiling when using the project file you gave, but when I click the Open Button gives me the same error.

I tried to use the code posted on #13 for the updated version and when compiling gives me the following.
B4X:
B4J version: 5.51
Parsing code.    Error
Error parsing program.
Error description: Unknown type: row
Are you missing a library reference?
Occurred on line: 143 (Main)
         Dim r() As row = res.rows.get(0)
 
Upvote 0
Top