preload image

I need to preload an image (jpeg) so its there when the user hits the button to show it and would like to know the basic procedure for doing this.

During a slideshow the user can hit *info to bring up a message dialog with some stats about the current slide. On the dialog is a button to show a “close-up”
This loads a canvas with the close-up detail image. Of course there is a delay while it loads, so I’m thinking I should load the current detail image when the user hits *info so its ready.
I dont see anything in the docs about preloading so I’m guessing it gets downloaded to /temp and then read from there? Or something like that?

Thanks

This would be tricky to pull off a benefit (in time) - if you are loading the image from the server, the image needs to download and be drawn to the canvas.
If you are loading the image from TMP, then you still need to initially download the image and still draw it onto the canvas.
Basically, use roUrlTransfer to download the file to TMP for your preview, and then when you are setting up the canvas, use the file://tmp:/ for the location of the image to use.

Hey thanks for answering. Its only a couple to a few seconds, but i notice once its been loaded it loads right away the second time. Maybe I’m confused about temp and how fast it is, and actually need to get it into memory and am confusing that with temp.
Perhaps I need a way to force it to load but not show itself ( an invisible canvas?)

thanks

Part of the speed problem you are seeing is the fact that you are using roImageCanvas. If you use roScreen instead, you can quickly download and draw images without much of the delay that you are currently encountering.

  • Joel

Thanks Joel, I’ll see if that works for me.

Edit - Ok I’ve looked at the docs, so which roscreen is supposed to replace the canvas? I need to display a picture and some text. There seems to be no “roscreen” rather a bunch of specialized ro-X-screens.

Thanks.

I think i wasnt clear in my first post. I’ve read about the roScreen and it seems most of the discussion and prodding from moderators is that the canvas is slow in a 60fps sense, the roscreen is for games which need to be fast. What i need is to download a 300k image, so if it doesn’t start until the user hits the button, it doesn’t matter how fast my one screen draws, its still going to be waiting for the download, especially if the internet is slow at that time/location.
This is what I’m trying to work around , not a slow animation problem.

Thanks

You can render your image into an roBitmap, and then use DrawObject to draw that bitmap on the roScreen. The DrawObject will be very fast.

–Mark

You could use roUrlTransfer.GetToFileAsync to download the image to tmp:, then load it from there. Issue the GetToFileAsync with a known tmp path when the user presses *, and point your image canvas layer to that known path. You can also try setting RequireAllImagesToDraw(False) to prevent the canvas from re-drawing portions of the screen that aren’t updating and/or visible.

BTW, I agree that roImageCanvas is the better screen to use for your application.

“TheEndless” wrote:
You could use roUrlTransfer.GetToFileAsync to download the image to tmp:, then load it from there. Issue the GetToFileAsync with a known tmp path when the user presses *, and point your image canvas layer to that known path.

Thank you theEndless. I’m going to try that.

Function  GetURL_Image()
  
    http = CreateObject("roUrlTransfer")
    http.SetPort(CreateObject("roMessagePort"))
    http.SetUrl("http://www.xxx.com/roku/detail/art/big/midtown.jpg")
    http.AsyncGetToFile("tmp:/detail.jpg")
   
End Function

Will calling this get the file into tmp:/ ?
AsyncGetToFile appears in exactly one function in the entire SDK, and it doesnt seem analogous to what i want.
I have to start somewhere, everyone here seems to already know how to do this. Is there a command to have the debugger show the tmp:/ directory so i can see if it got in there?
Currently have this line in the canvas where i want it to end up, of course its not working yet.

url = { url:"tmp:/detail.jpg"  TargetRect:{x:60,y:60,w:1160,h:610}}

Thanks

“everyone here seems to already know how to do this.” - everyone in this thread has tried to do it, or done it. It isn’t as common a thing to do as say, creating a poster selection screen.

For your image url, it needs to be url:“file://tmp:/filename.jpg”
ie “file://pkg:/images/splashsd.jpg” - but tmp instead of pkg
What you would probably do is use your AsyncGetToFile so your channel continues to run and do it’s regular work while the file downloads. And wait for the “download successful” event to know as soon as it’s done downloading the file, and then draw it to your canvas or roscreen. If you try to draw the image before it has finished downloading then I don’t think it will draw as the file will not have been closed. An important point is to set the RequireAllImages to draw to False as suggested above.
If you have a bunch of images, it might make more sense to start the download to tmp as soon as the slideshow section is selected - set it to download them 5 at a time, asynchronously, wait for the transfer succeeded event for one, and ask the user to wait if it’s not finished in time with a dialog/busy box display.

You’ll need to set a port to receive events from the transfer object -
UT=CreateObject(“roUrlTransfer”)
port=CreateObject(“roMessagePort”)
UT.SetPort(port)
UT.SetUrl(“http://server.com/file.wav”)
UT.AsyncGetToFile(“tmp:/file.wav”)

In your message loop,
if msg(type)=“rourlevent”
If msg.getint()=1 'completed download

End If
End If

http://sdkdocs.roku.com/display/sdkdoc/roUrlEvent

I’m sure someone can clean this code up, but you get the idea? By using the roUrlevent to test when the file has downloaded, there shouldn’t be a reason to check the actual directory for the file. Tmp works like a cache system - the oldest files get pushed out to make room for new files (as I understand it)
If you want to check all the files though and file operations, check out the ifFileSystem interface - http://sdkdocs.roku.com/display/sdkdoc/ifFileSystem
You will not be able to determine how much room is left in local fle systems - so space free for tmp will be useless. And you can’t write to external file systems so that info is also rather useless.

Thank You destruk, I really appreciate your (and everyones) efforts and time. I dont know how anyone could get a channel built without this board.
I will apply what you’ve said and I’m sure I’ll have another question.
I think its a good point about the file being called before its downloaded into temp which is certainly a possibility - I’m wondering if that could make this process cause more problems than its worth? - Do i need some repeating request in the loop in case that happens? Obviously, not being ready for the load image command would make it just sit there with the loading… screen which would be worse than what i have now. I thought about downloading multiple images but unless it can go on in the background and not impair the slideshow I’m probably second guessing the user enough with this scheme.

Thanks

The wait loop for the message port will already be looping to check for received messages. The builtin roku screensaver component downloads the first image and buffers the next four. When the user presses forward on the remote, or the time to change the image arrives it downloads the next image past the one that has been buffered. (I’m not saying this is the best way - just an example of what it does as default behavior). If you prefer to enable blocking in your code while the image downloads, you can use a GetToFile request instead of ASyncGetToFile - with result=http.GetToFile(“tmp:/detail.jpg”) – if the delay is the big issue, use a higher compression format for the image, or toss up a busy notice while it downloads with or without a progress bar (progress bars are on the developer blog) or text percentage. It might also be considered to have two slideshows - one for the main images and one for the closeup images.

Thanks for explaining the loop thing. I really am at the nitpicking stage, but every little thing makes it seem slicker for the user. I have a “loading..” graphic on the canvas which gets covered by the image so it appears like feedback there. The time to show the image is 3-4 seconds from the button press so its not horrible but if I can cut it in half or eliminate it i want to. I think im at my limit compression-wise but I will revisit that - the TV screen kills detail any way.
Once the image is loaded, like if you procede a few slides and then come back - pressing the button appears to do nothing, but only for about 1.5 seconds - and then shows the complete canvas with image - it doesn’t go through the showing blank canvas immediately/then image process. I like that way better and the only way to do that is to get the image into RAM first.
Really like the second slideshow idea though, can they run concurrently and use some function to switch between them? I may get to that, but I cant see far enough ahead on how to do that right now, plus it seems like syncing the two slideshows might be an issue.

Thanks again.

OK I got it working! Thank you to theEndless, destruk and RokuMarkn, without you I’d still be seeing that annoying “loading..” graphic on the canvas.
It works as imagined, there is a 1 second-ish wait after hitting the close-up button and then the canvas shows complete with image. Much better. I did have to use the actual filename instead of a generic one when saving to tmp:/ because of the cache not overwriting the file. Now only two last questions:

  1. Do i need to worry about filling up tmp:/ and having that cause a crash? (please say no)

  2. The only side-effect is that when the main image displays, the closeup image starts downloading, and if you hit the info button right away during those few seconds, the info dialog wont show until (I presume) the closeup image has downloaded. Am I misunderstanding the function of the Async command? I’m guessing this is not a big problem in practice but again, I’m at the nitpicking stage.

Thanks All.