B4J Question Displayed ProgressBar doesn't update

DarkMann

Member
Licensed User
Longtime User
I've been working on this all afternoon and it is driving me slowly more insane than I already am!

My program is set up to import a load of JPEG files that you drag onto it. This all works fine. I select an album, drag the images from a Windows Explorer window into the mane panel and after a period of time they all appear as expected. If there are a lot of images or they are very large, then it takes quite some time and during this time I can't get any indication of progress.

I've added a ProgressBar and set up a timer to check the state of a progress variable and update the bar. I have tried to offload the hard work by using CallSubDelayed. This seems to improve responsiveness but the timer only fires right at the end. I only know this because all the log of the progress variable shows a progress of 1 and appears all at the same time, once for every call to the sub.

These two subs loop through the dropped images
B4X:
Sub ScrlMainView_DragDropped(e As DragEvent)
    If CurrentAlbum=-1 Then Return
    Dim Files() As String
    Dim FileList As String=e.GetDataObjectForId("text/uri-list")
    FileList=FileList.Replace("file:/","").Replace("/","\")
    Files=Regex.Split("\r\n",FileList)
    If Files.Length=0 Then Return
    ProgWorking.Progress=0
    TimerMain.Enabled=True
    Dim gap As Double = 1/Files.Length
    Dim count As Int=0
    For Each source As String In Files
        If source.Contains(".jpg")=True Then
            count=count+1
            CallSubDelayed3(Me,"InsertPicture",source,count*gap)
        End If
    Next
End Sub

Sub InsertPicture(Source As String, Position As Double)
    Dim imgname As String=File.GetName(Source)
    imgname=imgname.Replace(".jpg","")
    Dim imgwork As Image=Graphics.ResizeImage(Source,120)
    Dim imgaspect As Int=0
    If imgwork.Width>imgwork.Height Then imgaspect=1
    Dim blob() As Byte
    blob=Graphics.CreateSQLiteBlob(imgwork)
    SQLMain.ExecNonQuery2("INSERT INTO pictures (_album,source,title,thumb,aspect) VALUES (?,?,?,?,?)",Array As Object(CurrentAlbum,Source,imgname,blob,imgaspect))
    ProCount=Position
    FillPhotoPanel
End Sub

and this one in the Graphics Module does the sizing. This will be the one that takes a long time.

B4X:
Public Sub ResizeImage(Source As String, Size As Int) As Image
    Dim temp As Image
    temp.Initialize(File.GetFileParent(Source),File.GetName(Source))
    Dim wid As Int=temp.Width
    Dim hid As Int=temp.Height
    If wid>hid Then
        Dim swid As Int=Size
        Dim shid As Int=(Size/wid)*hid
    Else
        Dim shid As Int=Size
        Dim swid As Int=(Size/hid)*wid
    End If
    Dim temp2 As Image
    temp2.InitializeSample(File.GetFileParent(Source),File.GetName(Source),swid,shid)
    Return temp2

I've attached the project and any help would save my sanity.

I'm using JRLDialogs8 and jDragAndDrop so you may need these.

David
 

Attachments

  • PhotoSite.zip
    17.5 KB · Views: 290

DarkMann

Member
Licensed User
Longtime User
The purpose of Image.InitializeSample is to allow you to load downsampled large images, without loading the full image. Your code load each image twice. You should avoid loading the full image to make your program faster.

That is what I would like to do Erel, but I need to know the dimensions of the full-sized image first to get the aspect ratio right.

Is there any way to read the dimensions of the bitmap before it's opened?

If so, then in this case, the problem will be solved as the speed will increase dramatically. Having said that, I can see a scenario where I drag 1000 images to the window and then we are back needing to have some way of showing progress. What I don't understand is the way the timer doesn't fire. I get that it needs the message loop to be processed and may not be accurate, but I don't see why the message loop isn't being processed between each delayed call to the ResizeImage sub firing.

I've found in my searches an early response to a similar question where AGraham does it with his threading library, but I don't want to do something that complex for something seemingly so simple and honestly it seems like total overkill to do so. I've also looked at examples where it clearly does work, but I just can't see why it works there but not for this case.

Thanks,

David
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Use this code to load the image without breaking the ratio:
B4X:
Sub LoadImageSamplePreserveRatio(Dir As String, FileName As String, _
     Width As Double, Height As Double) As Image
   Dim jo As JavaObject
   Dim in As InputStream = File.OpenInput(Dir, FileName)
   jo.InitializeNewInstance("javafx.scene.image.Image", Array( _
     in ,Width, Height, True, True))
   in.Close
   Return jo
End Sub
 
Upvote 0

DarkMann

Member
Licensed User
Longtime User
Use this code to load the image without breaking the ratio:
B4X:
Sub LoadImageSamplePreserveRatio(Dir As String, FileName As String, _
     Width As Double, Height As Double) As Image
   Dim jo As JavaObject
   Dim in As InputStream = File.OpenInput(Dir, FileName)
   jo.InitializeNewInstance("javafx.scene.image.Image", Array( _
     in ,Width, Height, True, True))
   in.Close
   Return jo
End Sub
Thanks Erel, that's good enough for it to no longer be a problem. For the moment I'll find another way of indicating that the system will be busy for a few moments.

David
 
Upvote 0
Top