Creating Image Array from a File

Got a LiveCode personal license? Are you a beginner, hobbyist or educator that's new to LiveCode? This forum is the place to go for help getting started. Welcome!

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller

Post Reply
JeffO2013
Posts: 17
Joined: Thu Jun 27, 2013 7:41 pm

Creating Image Array from a File

Post by JeffO2013 » Sat Jun 29, 2013 6:10 am

Hi,

I'm trying to create an array of images from a file and then call a random image from the array and have it display in an image area. To do this I have a button with the following code

Code: Select all

global distractorArray
global distractorNumber

on mouseUp
   local tFolder
   
    answer folder ""
    put it into tFolder
    -- asks the user to pick a folder (with images) and then put it into a variable for manipulation
    
    doForEachFile tFolder
    -- now we pull out the images using this function
    
    if there is a folder tFolder then 
       put tFolder into field "Field"
    end if
    -- puts the folder path into a field to make sure the program actually recieved a folder
    
end mouseUp

on doForEachFile tFolder                                                  

   set defaultFolder to tFolder
   -- set defaultFolder to tFolder so we can begin pulling files from the folder
   
   put 1 into distractorNumber
   -- this will be used to assign the files a location within the array
   -- Also will be used later to help pick a random from 1 to however many files
   
   repeat for each line tFile in tFolder     
      -- goes through every file in the folder and performs the tasks within the repeat loop
      
      createArray (tFile)
      -- where the array is acutally made
      
      add 1 to distractorNumber            
      -- distractorNumber increases by 1 everytime this is repeated to for location assignment within the array
      
   end repeat
end doForEachFile

on createArray tFile
   if there is a file tFile then
      -- checks that there is a file 
      
      put tFile into distractorArray[distractorNumber]                                    
      --put individual images into the array, at location distractorNumber (should increase by one everytime the script is run)
      
   end if                                                                                                                
end createArray
this is from a tutorial on arrays I think from on of the earlier versions of livedcode, but I'm not sure which one.

the image field in on the next card and the code for it is as follows:

Code: Select all

global distractorArray
global distractorNumber

global distractorDisplay

on openCard
   getRandom
   set the filename of img "Image" to distractorArray[distractorDisplay}
end openCard

on getRandom
   put random(distractorNumber) into distractorDisplay
end getRandom
Unfortunately, there is no image displayed in the image area when I go to the next card.

Also, the comments are for the code above them.

Thanks for your help,
Jeff

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4172
Joined: Sun Jan 07, 2007 9:12 pm

Re: Creating Image Array from a File

Post by bn » Sat Jun 29, 2013 10:08 am

Hi Jeff,

I modified your script 1 a bit and commented it. My comments end with -- BN.

the main problem was you were not getting "the files" to get the content of the folder. I added a filter to only get files with a suffix of "jpg" or "png", otherwise you would get all kinds of files in that folder, on MacOS also invisible files, that are not images.
I changed the file path to the images to a complete path to the images. And I reset the default folder to the initial setting, this can at times lead to problems in Livecode if the default folder is not what your app expects.
I changed your increment "global distractorNumber" to a different location in the loop since in the last round it added 1 too many.

have a look

Code: Select all

global distractorArray
global distractorNumber

on mouseUp
   local tFolder
   
   answer folder ""
   put it into tFolder
   
   if it is empty then exit mouseUp -- user cancelled -- BN
   -- asks the user to pick a folder (with images) and then put it into a variable for manipulation
   
   -- reset the the globals just a precaution might not be what you want, depends -- BN 
   put "" into distractorNumber
   put "" into distractorArray
   -- end reset globals
   
   
   put the defaultFolder into tOldDefault -- so we can restore the defaultFolder later -- BN
   set defaultFolder to tFolder -- moved setting the defaultFolder here, setting defaultFolder is persistent -- BN
   -- set defaultFolder to tFolder so we can begin pulling files from the folder
   
   doForEachFile tFolder
   -- now we pull out the images using this function
   
   set the defaultFolder to tOldDefault -- restore the old default folder, it is nice and we dont need it to be at the image folder since the array now has absolute filePaths -- BN
   
   if there is a folder tFolder then 
      put tFolder into field "Field"
   end if
   -- puts the folder path into a field to make sure the program actually recieved a folder
   
end mouseUp

on doForEachFile tFolder                         
   
   put tFolder & "/" into tPathToFolder  -- store the path to the folder, append slash to tFolder for path building -- BN
   
   put the files into tAllFiles -- get a list of all files in the default folder -- BN
   
   -- check to make shure the list contains only images of type PNG, JPG -- BN
   put "png,jpg" into tSuffixes
   
   repeat for each line aFile in tAllFiles
      if char - 3 to - 1 of aFile is among the items of tSuffixes then put aFile & cr after tCollect
   end repeat
   delete last char of tCollect -- a trailing return
   
   if tCollect = empty then 
      answer "there are no suitable image files in the folder"
      exit doForEachFile
   end if
   put tCollect into tAllFiles
   -- end check for valid image types -- BN
   
   
   put 0 into distractorNumber -- changed to 0 -- BN
   -- this will be used to assign the files a location within the array
   -- Also will be used later to help pick a random from 1 to however many files
   
   repeat for each line tFile in tAllFiles  
      -- goes through every file in the folder and performs the tasks within the repeat loop
      
      
      -- createArray (tFile) -- you use function notation on a command -- BN
      
      add 1 to distractorNumber      -- moved this up otherwise we were getting on too many -- BN
      -- distractorNumber increases by 1 everytime this is repeated to for location assignment within the array
      
      createArray tFile, tPathToFolder -- changed to command notation and passed the folder path on top of the list of files --BN
      -- where the array is acutally made
      
   end repeat
end doForEachFile

on createArray tFile, tPathToFolder
   if there is a file tFile then
      -- checks that there is a file 
      
      put (tPathToFolder & tFile) into distractorArray[distractorNumber]  -- it now checks for the complete path and stores the complete path in array -- BN     
      --put individual images into the array, at location distractorNumber (should increase by one everytime the script is run)
      
   end if                                                        
end createArray
it works for me in a small test stack when I put your second script into the stack script. I go from card to card and it shows me a random image. (you might want to give your objects unique names, like for distractor images image "distractor" on each card)

Kind regards
Bernd

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7393
Joined: Sat Apr 08, 2006 8:31 pm
Contact:

Re: Creating Image Array from a File

Post by jacque » Sat Jun 29, 2013 8:29 pm

Bernd writes good scripts. :)

But I wonder if you really need an array. If you will be adding more info to each entry later then it's a good choice. But if all you need is a list of files, the script could be simpler if you just leave it as a text list of file paths. Then when you need to get a random image, you can do it in one line of code: set the filename of img "image" to any line of <variable>

You won't need to check for the folder's existence because "answer folder" only allows users to select folders (not files,) and also because if the user selected it, you know it exists.

If you only need a list of files, here's a shorter way. I like using "filter" to remove unwanted lines from lists, but Bern's way works just as well.

Code: Select all

global gFileList

on mouseUp
  local tFolder
  
  answer folder ""
  if it = "" then exit mouseUp -- user cancelled
  put it into tFolder
  -- asks the user to pick a folder (with images) and then put it into a variable for manipulation
  put the defaultfolder into tOldDefault
  set the defaultfolder to tFolder
  put the files into tFileList
  set the defaultfolder to tOldDefault -- restore original default
  -- remove non-image files from the list, you can add other extensions:
  repeat for each item i in ".png,.jpg"
    put tFileList into temp
    filter temp with ("*"&i)
    put temp after gFileList -- add to global
  end repeat
  if gFileList = "" then -- no images
    answer "No images found in this folder."
  end if
end mouseUp
For the openCard handler:

Code: Select all

global gFileList

on openCard
  set the filename of img "Image" to any line of gFileList
end openCard
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

JeffO2013
Posts: 17
Joined: Thu Jun 27, 2013 7:41 pm

Re: Creating Image Array from a File

Post by JeffO2013 » Sun Jun 30, 2013 2:10 am

Thank you both for your help!

I'm brand new to programming so I'm trying to learn as I go.

I have a question, though: which one of these would be better for dealing with folders with a large amount of files? I need something that's going to be able to select a random picture and put it into the image as quickly as possible since people will be timed on a task related to the picture.

I'm thinking Jacque's might be the way to go, but would appreciate feedback.

Thanks again,

Jeff

bn
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 4172
Joined: Sun Jan 07, 2007 9:12 pm

Re: Creating Image Array from a File

Post by bn » Sun Jun 30, 2013 10:42 am

@Jacque, thank you for the kind words. From you I take that as an honour.

Jeff,

there are two parts to your question.
The first one is regarding loading the global variable gFileList. Jacque and I used different ways to gather the information. Actually I tried to leave your original script in its structure as it was.
Both approaches are reasonable. Jacque's has the advantage that it is more straightforward and easier to read and maintain.
Arrays come into play if you want to access larger numbers of files. Lets say more than 1000.

But beware, Jacque left some surprises in her script for you to find out about.

Hint: throw a folder with a mix of png and jpg images at the handler
Hint2: suppose your images are not located in the default folder of your stack then you will not get at your images

(she probably was in a hurry because in her kitchen turkeys get away around thanksgiving
http://forums.runrev.com/phpBB2/viewtop ... und#p64452
and her birthday is thursday,
http://forums.runrev.com/phpBB2/viewtop ... 681#p79683
on top she can timetravel, the livecode use-list has lots of well documented incidents, but those are different stories)

Part two of your question is timing. This depends on the size of the images. Loading an image of 640 by 480 takes about 50 to 60 milliseconds. If your timing requirements (I suppose you are doing psychological research) are very high you could change the script that loads images.
You could load an image on preopenCard and then in the opencard handler you would put a send in time message to a handler that starts your timer. Preopencard is send before the card is visible, openCard is when the card appears.
If you tell us more about your requirements we could work something out.

The way it is now you will have to take care of the opening sequence of your stack/application.
Your first card will get an opencard on start up but at that time the global might not be filled yet. This is not a big problem and there are solutions for this but that depends a bit on the layout of your stack. Also if you should add a substack and the substack does not trapp the opencard message then your mainstack will also get the openCard message.

Kind regards
Bernd

JeffO2013
Posts: 17
Joined: Thu Jun 27, 2013 7:41 pm

Re: Creating Image Array from a File

Post by JeffO2013 » Mon Jul 01, 2013 12:28 am

Hi Bernd,

Your're correct about the research.

The way it's set up, the program would only have to handle max 200 files in a folder (for now) and they will all be the same size and format (as I'll have to create them myself and will have the luxury of ensuring this). But, if I continue with this project I may at some point in time have upwards of 1000 images of different sizes, in which case I will probably revisit this code and either convert to using an array and also have the program format the picture sizes for me so they are consistent.

As far as the timing, there will actually be 400 milliseconds between each trial during which I hope to have the program perform all of the tasks that you described in the preOpenCard section. Additionally, I will not have the timer start until the individual is actually able to respond (the program will accept user input). But, they time clearances will be in the order of milliseconds.

jacque
VIP Livecode Opensource Backer
VIP Livecode Opensource Backer
Posts: 7393
Joined: Sat Apr 08, 2006 8:31 pm
Contact:

Re: Creating Image Array from a File

Post by jacque » Mon Jul 01, 2013 5:35 pm

Bernd's right as usual. I'll post a correction for posterity. This time I actually ran the script instead of writing it without testing.

Code: Select all

global gFileList

on mouseUp
  local tFolder
  answer folder ""
  if it = "" then exit mouseUp -- user cancelled
  put "" into gFileList
  put it into tFolder
  -- asks the user to pick a folder (with images) and then put it into a variable for manipulation
  put the defaultfolder into tOldDefault
  set the defaultfolder to tFolder
  put the files into tFileList
  set the defaultfolder to tOldDefault -- restore original default
  -- remove non-image files from the list, you can add other extensions:
  repeat for each item i in ".png,.jpg"
    put tFileList into temp
    filter temp with ("*"&i)
    repeat for each line l in temp
      put tFolder & slash & l & cr after gFileList -- add to global
    end repeat
  end repeat
  if gFileList = "" then -- no images
    answer "No images found in this folder."
  end if
end mouseUp
I wrote these corrections a week from today when I had more time.
Jacqueline Landman Gay | jacque at hyperactivesw dot com
HyperActive Software | http://www.hyperactivesw.com

Post Reply