B4J Question Resize Image field to thumbnail size image field in SQL Server

mfstuart

Active Member
Licensed User
Longtime User
Hi all,

I have 2 varbinary(MAX) fields in a SQL Server table - Photo and Thumbnail.
The Photo field has a large image in it - a photo.
The Thumbnail field is a new field, and needs to be updated with the Photo field, but downsized with a scale of 50%, or whatever percentage displays the best when rendered in a grid.

I've searched the forum, but all examples are in B4A and the methods are different in B4J.

What's the best way to update the field in the table?

Regards,
Mark Stuart
 

mfstuart

Active Member
Licensed User
Longtime User
Hi Daestrum,
I did see that and tried it out, but I'm stuck on writing the image to SQL server using B4J.
I've only found B4A examples.
After resizing, the ImageView has to be parsed out into bytes to the buffer to be used in the UPDATE SET SQL statement.
Sorry, stuck.

Regards,
Mark Stuart
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Upvote 0

mfstuart

Active Member
Licensed User
Longtime User
Well, that exercise was disappointing, but thanx to Daestrum and LucaMs for pointing me to the links.
After building the scripts to read the image and write to the database, I've found out that B4J saves the image into the Bytes array as PNG, resulting in the Thumbnail field content to be anywhere from 5 to 13 times bigger than the original Photo image.
Not what I wanted. I was hoping to down-size the Photo into the Thumbnail.

Will have to rethink this process.

Regards,
Mark Stuart

Here's the scripts:
B4X:
Sub btnSave2DB_Click
    Dim bytes() As Byte = ImageToBytes(imgThumbnail.GetImage)
    DBConnect
    sql.ExecNonQuery2("UPDATE Pass SET Thumbnail=? WHERE ResID=" & ResID & " AND ResDetID=" & ResDetID & " AND Line=" & LineNo, Array As Object(bytes))
    DBDisconnect
End Sub

Sub ImageToBytes(Img As Image) As Byte()
    Dim out As OutputStream
    out.InitializeToBytesArray(0)
    Img.WriteToStream(out)       'Writes the image to the OutputStream as PNG image.
    out.Close
    Return out.ToBytesArray
End Sub

If I did this completely wrong, please advise.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Did you load the image into an imageview that has its size set to thumbnail size and then use snapshot and write the image out ?

You can make the imageview a set size and all your thumb nails will be the same size.
 
Upvote 0

mfstuart

Active Member
Licensed User
Longtime User
Hi Daestrum,
Yes I did.

The Thumbnail ImageView is set to half the size of the Photo ImageView.

First, I load a TableView with the Pass records, and on row select, grab the Primary Key field values, which are then used in the ReadPhoto Sub below to load the ImageViews.
B4X:
Sub tvPasses_SelectedRowChanged(Index As Int, Row() As Object)
    If Index > -1 Then
        ResID = Row(0)
        ResDetID = Row(1)
        LineNo = Row(2)
        ReadPhoto
    End If
End Sub

Here's the script that reads the record from the SQL db and populates the ImageViews:
B4X:
Sub ReadPhoto
    Dim strSQL As String = "SELECT Photo, DATALENGTH(Photo) as Size, Thumbnail FROM Pass WHERE ResID = ? AND ResDetID = ? AND Line = ?"
    Dim rs As ResultSet
   
    'reset the imageviews
    imgPhoto.SetImage(Null)
    imgThumbnail.SetImage(Null)
    ImgPreview.SetImage(Null)
   
    DBConnect
    If Connected Then
        rs = sql.ExecQuery2(strSQL,Array As String(ResID, ResDetID,LineNo))
        rs.NextRow
       
        Dim Buffer() As Byte
        Buffer = rs.GetBlob2(0)
       
        'load Photo image
        If Buffer <> Null Then
            Dim Inputstream1 As InputStream
            Inputstream1.InitializeFromBytesArray(Buffer,0,Buffer.Length)
           
            If Inputstream1.BytesAvailable > 0 Then
                Dim img As Image
                img.Initialize2(Inputstream1)
                Inputstream1.Close
                imgPhoto.SetImage(img)
                imgThumbnail.SetImage(img)        'as you suggested
                imgThumbnail.Snapshot             'as you suggested
            End If
        End If
       
        Dim PrevBuffer() As Byte
        PrevBuffer = rs.GetBlob2(2)
       
        'load Thumbnail to ImgPreview ImageView, to confirm what was saved to the db prior in the btnSave2DB_Click handler - see Post#5
        If PrevBuffer <> Null Then
            Dim in As InputStream
            in.InitializeFromBytesArray(PrevBuffer,0,PrevBuffer.Length)
            Dim PrevImg As Image
            PrevImg.Initialize2(in)
            in.Close
            ImgPreview.SetImage(PrevImg)
        End If
    End If
   
    DBDisconnect
End Sub

If there's something wrong in the scripts, please advise.

Regards,
Mark Stuart
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Sorry if I did not explain clearly (brain working faster than typing)

1, read the image from database and place into an image (Img)
2, use the image (Img) in an imageview which is the size of the thumbnail you want ( Imageview.SetImage(Img) )
3, call snapshot and WriteToStream on the (thumbnail) imageview ( Imageview.Snapshot.WriteToStream(out) )
4, convert the outputstream to byte array as you have ( bytes() = out.ToByteArray )
5, write bytes to the database for the thumbnail
 
Upvote 0

mfstuart

Active Member
Licensed User
Longtime User
Thanx Daestrum, I'll give that a go and report back.
It's quite a bit to grasp the concept of resizing an image and putting back into the database - a lot of steps really.

Regards,
Mark Stuart
 
Upvote 0
Top