Menu

image gadget memory allocation

2021-01-15
2021-02-09
  • John Duchek

    John Duchek - 2021-01-15

    I am writing a program that displays 20 (320x240)images in a window using 20 imagegadgets. I then try to replace those images with new ones, and I seem to crash after displaying 240 images. I think that is a memory problem. Is there a way to display an image on the button and then clear that memory and display a second image? I am doing that, but I think I am filling memory up and that causes the crash... I have been playing with freegadget and free_image, but it still crashes. Any help appreciated,
    Thanks,
    John

     
  • stabud

    stabud - 2021-01-15

    Hi John!

    Provide code + images, then maybe we will find a solution or errors.

     
  • John Duchek

    John Duchek - 2021-01-18

    The object of the program is to look through hundreds or thousands of images 20 at a time, and when one finds an interesting one, to rename it.
    I am using hundreds of images so they would be hard to provide. (output from a game(wild animal) camera that has been taking pictures for months. That being said, any jpgs larger than 320x240 in the directory should be sorted, loaded, shrunk to 320x240 and displayed. As the code is shown the last 4 characters in the file name have to be ".JPG" to be recognized. That can be changed by changing the fend variable to ".jpg" if desired.
    It is made to display 20 images (5x4) on a screen and the monitor has to be 1900x1080 or larger. Once displayed, you can click on any picture and change its filename. It crashes at about 250 images (usually page 12 or so.) The freegadget stuff I commented out but it doesn't work anyway. And maybe I am wrong about it being a memory problem. That is my best guess. Here is the code:

    include "dir.bi"

    include once "window9.bi"

    /'provides constants to use for the attrib_mask parameter
    changes filename on disk 9/2020
    Its working for jpgs
    added free_gadget but it doesn't seem to do anything
    '/
    declare sub shell_sort()
    declare sub free_gadget()
    dim shared as integer sort1,sort2,sort3,sort4,sort5,sort6

    declare sub list_files(ByRef filespec As String, ByVal attrib As Integer)
    declare sub load_images()
    Dim shared As integer hwnd,event,BS_PUSHLIKE,BS_AUTOCHECKBOX,ES_WANTRETURN
    dim shared as integer total, attrib,indx,total_even
    dim shared as string files(2500),fname,fend
    dim shared as integer size_x,size_y

    Dim shared As integer i,col,image_num,l,k,row
    size_x=320:size_y=240

    '----- start
    fend=".JPG"
    indx=0
    hwnd=OpenWindow("Images",1700,200,1700,1020)

    list_files "*"+fend, attrib
    shell_sort()
    load_images()
    Do

    event=WaitEvent()
    If event=EventClose Then End

    Select Case event

    case EventGadget
    select case EventNumber
    case 1 to 20
    l=len(files(EventNumber+indx20))
    fname=left(files(EventNumber+indx
    20),l-4)
    fname=InputBox("Change Filename","Enter New Name (no ending)",fname,ES_WANTRETURN)
    Name(files(EventNumber+indx20),fname+fend)
    files(EventNumber+indx
    20)=fname+fend

    case 21
    if indx>0 then indx=indx-1
    image_num=indx*20
    'free_gadget()
    load_images()
    
    
    case 22
    indx=indx+1
    if indx<(total_even/20) then image_num=indx*20
    'free_gadget()
    load_images()
    
    case 23
    'fname=Getgadgettext(23)
    

    'indx=EventNumber

    End Select

    End Select
    Loop
    '----- end

    Sub list_files (ByRef filespec As String, ByVal attrib As Integer)
    Dim As String filename = Dir(filespec, attrib)
    Do While Len(filename) > 0
    total=total+1
    files(total)=filename
    filename = Dir()
    Loop

    ' print total
    total_even=int((total+19)/20)*20
    for i=total+1 to total_even
    files(i)="zzz"
    next
    for i=1 to total_even
    print files(i),
    next
    End Sub
    '-------------------
    sub load_images()
    print indx,image_num
    k=0:row=0:col=0
    for col=0 to 3
    for row=0 to 4

    k=k+1
    image_num=image_num+1

    Var HIMAGE=Load_image(files(image_num))
    HIMAGE=Resize_image( HIMAGE,size_x,size_y)

    ButtonImageGadget(k,0+size_xrow,0+size_ycol,size_x,size_y,HIMAGE, BS_PUSHLIKE Or BS_AUTOCHECKBOX)
    Free_Image(HIMAGE)

    next:next
    buttongadget(21,1600,200,90,50,"Last 20")
    buttongadget(22,1600,250,90,50,"Next 20")
    TextGadget(23,1620,300,90,50,"page "+str(indx+1))

    end sub

    sub shell_sort()

    sort1 = total_even 'number of items to be sorted
    sort2 = sort1

    Lsort1:
    sort2 = INT(sort2 / 2)
    IF sort2 = 0 THEN goto endit
    sort3 = 1: sort4 = sort1 - sort2

    Lsort2:
    sort5 = sort3

    Lsort3:
    sort6 = sort5 + sort2
    IF files(sort5) <= files(sort6) THEN GOTO Lsort4 'item to be sorted
    SWAP files(sort5), files(sort6) 'item to be sorted
    sort5 = sort5 - sort2
    IF sort5 < 1 THEN GOTO Lsort4
    GOTO Lsort3

    Lsort4:
    sort3 = sort3 + 1
    IF sort3 > sort4 THEN GOTO Lsort1
    GOTO Lsort2
    endit:
    end sub
    /'

    sub free_gadget()
    for i=1 to 20
    'Free_Image(HIMAGE)
    freegadget(i)
    next
    end sub
    '/

     
  • stabud

    stabud - 2021-01-18

    Your error seems to occur due to the fact that you do not free memory after resize_image.

    The principle should be as follows:

    dim imgFullSize as Hbitmap
    dim imgScaled as Hbitmap
    dim as Long imgWidth , imgHeight
    
    imgFullSize = Load_image(file)
    imgScaled = Resize_image(imgFullSize ,imgWidth , imgHeight)
    Free_Image(imgFullSize) 
    

    Advice:

    1) No need to create 20 gadgets every time (ButtonImageGadget). Use SetImageGadget to change the image in it.

    2) Create an array for images at the beginning of the program, for example:

    dim shared as Hbitmap images(1 to 20)

    3) create gadgets (ButtonImageGadget) at the beginning of the program c ID from 1 to 20 :

        k = 0
    
        for col = 0 to 3
            for row = 0 to 4
    
                k=k+1
    
                ButtonImageGadget(k,0+size_xrow,0+size_ycol,size_x,size_y,, BS_PUSHLIKE Or BS_AUTOCHECKBOX)
    
            next
        next
    

    4) in the load_images () procedure load images like this:

    for i as Long = 1 to 20
    
        dim imgFullSize as Hbitmap
        dim as Long imgWidth = 320 , imgHeight = 240 
    
        if images(i) <> 0 then Free_Image(images(i)) ' first we free the image in the array cell
    
        imgFullSize = Load_image(file) ' load image
        images(i) = Resize_image(imgFullSize ,imgWidth , imgHeight) ' cut and save the image to an array cell
        Free_Image(imgFullSize) ' free memory full image 
    
        setimagegadget(i , images(i)) ' display the image in ButtonImageGadget 
    
    Next
    
     
  • John Duchek

    John Duchek - 2021-02-02

    Hi Stabud,
    Thank you for your information. It has taken me a while to work through this, but I have it working now, and understand how it works more thoroughly. I really appreciate the help!
    John

     
  • John Duchek

    John Duchek - 2021-02-08

    Hi Stabud,
    I pretty much have it all working properly with your suggestions. thank you. I have one question. When I run this program, I get an error message in the terminal for each jpg loaded. I think I asked this question on the freebasic forums and did not get an answer that I was able to implement. Hopefully I didn't ask it of you before. I would hate to repeat myself. Here is the error message I get, and it doesn't seem to affect anything, but I would like to know how to get rid of it.

    (320x240-JPG_image_renamer2:15597): GLib-GObject-CRITICAL **: 18:34:19.314: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
    HUNT1054.JPG

    This shows up once for each file loaded. It appears that it is referring to the imgScaled rather than the imgFullSize
    I do not understand the error message, nor do I know how to get rid of it. Any help or suggestions as to what it means would be appreciated.
    Thanks,
    John

     
  • stabud

    stabud - 2021-02-08

    Hi! I have no such mistakes. The most simple code attach where this error appears.

     
  • John Duchek

    John Duchek - 2021-02-08

    I can give you two examples. I think the first is from the window9 documentation.

    Include "window9.bi"

    Var hbitmap=Load_image("IMG_0001.JPG")
    hbitmap=Resize_image( hbitmap,800,600)
    OpenWindow("",1600,10,800,600)
    ImageGadget(1,10,10,100,100,hbitmap)

    'Free_Image(hbitmap)
    'ImageGadget(2,110,10,800,600,hbitmap)

    Do
    var ev=WaitEvent()
    If ev=EventClose Then End
    Loop

    The above gives this error:

    (one_image:6978): GdkPixbuf-CRITICAL **: 07:31:01.778: gdk_pixbuf_scale_simple: assertion 'GDK_IS_PIXBUF (src)' failed

    This code below:---------------------------------------------------------------------------------------------------

    include "dir.bi"

    include once "window9.bi"

    Dim shared As integer hwnd
    dim shared as string fend
    dim shared as long size_x,size_y,index
    dim shared imgFullSize as Hbitmap
    dim shared imgScaled as Hbitmap
    size_x=320:size_y=240

    fend=".JPG"
    index=0
    hwnd=OpenWindow("Images",1700,200,800,600)
    ButtonImageGadget(2,size_x,size_y,size_x,size_y,imgScaled)
    free_image(imgFullSize)
    free_image(imgScaled)
    imgFullSize = Load_image("HUNT1030.JPG")' load image
    Do
    var ev=WaitEvent()
    If ev=EventClose Then End
    Loop

    imgScaled = Resize_image(imgFullSize ,size_x, size_y)
    
    setimagegadget(2 ,imgScaled) ' display the image i
    
    Gives the error twice:
    (error_test:7036): GLib-GObject-CRITICAL **: 07:32:05.818: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
    

    (error_test:7036): GLib-GObject-CRITICAL **: 07:32:05.818: g_object_unref: assertion 'G_IS_OBJECT (object)' failed

    In both cases the code runs ok.
    John

     
  • stabud

    stabud - 2021-02-08

    Do you call the FREE_IMAGE function and then use the image functions? The FREE_IMAGE function is called when the image is no longer needed. Basically: after calling FREE_IMAGE, the image no longer exists and any access to this image causes an error, even if it is displayed in the gadget.

     
  • John Duchek

    John Duchek - 2021-02-08

    No , that was leftover from when I chopped unnecessary lines out to shorten the example. In my program I free up the image and then add a new one to the button. In the first example I get the error without freeing up anything.
    I did run into this (Basically: after calling FREE_IMAGE, the image no longer exists and any access to this image causes an error, even if it is displayed in the gadget.) in my program. On the last page of my images if there were buttons that should have been blank, they displayed the old image from the page before, one that had been freed. I had to grab a blank image and then load the blank image to cover over the old image so that unused buttons were grey rather than displaying an old image from the page before.

     
  • stabud

    stabud - 2021-02-08

    Try checking what the BITMAP is before sending it to the RESIZE_IMAGE function:

    Var bitmap=Load_image("image.jpg")
    if bitmap then
    messbox("success" , "success")
    Resize_image(.....)
    else
    messbox("error" , "error")
    endif

    I can't find the error from here. Unambiguously, an invalid BITMAP is received in the RESIZE_IMAGE function or other functions. Find this place in the code where the error takes off. Most likely you made a mistake with the file load line in Load_image

     
  • John Duchek

    John Duchek - 2021-02-09

    This test code ran without an error shown in the terminal, and gave the success message. Thanks for your help. I will keep looking.
    John

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.