Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Problem with net image displayed (carousel)

edited May 25 in Questions Posts: 2,348

All,
Trying to set up a carousel in which images are downloaded from a site on the net. The images are displayed free downloading to a table and iterating through the table in the draw() function.
I have tried to build an image in setup by downloading images within setContext() and sprite them onto the image, then Sprite the resultant image in the draw() function. But the images don't seem to be pasted into the target image.

Are images downloaded in this way only displayable direct to screen and not to other memory locations?

Comments

  • dave1707dave1707 Mod
    Posts: 9,415

    @Bri_G Msybe this is close enough for you to modify. Tap screen to read and display the next image.

    viewer.mode=FULLSCREEN
    
    function setup()
        tab={
            "http://www.freeimageslive.com/galleries/home/playroom/pics/objects00016g.jpg",
            "http://www.freeimageslive.com/galleries/transtech/auto/pics/03250046.jpg",
            "http://www.freeimageslive.com/galleries/transtech/auto/pics/car00708.jpg",
            }
        z=0
        getNext=false
    end
    
    function draw()
        background(40,40,50)
        if getNext then
            getNext=false
            z=z+1
            if z<=#tab then
                http.request(tab[z],gotImage,noImage)
            end
        end
        if img~=nil then
            sprite(img,WIDTH/2,HEIGHT/2)
        end
    end
    
    function noImage()
        print("Error:  ",tab[z])
        getNext=true
    end
    
    function gotImage(image1,status,header)
        print("Success:  ",tab[z])
        img=image1 
    end
    
    function touched(t)
        if t.state==BEGAN then
            getNext=true
        end
    end
    
  • Posts: 2,348
    @dave1707 - missed the point there. What I suspect is you are constantly streaming to the screen there via the http.request, possibly to a buffer. That's what happens in the Carousel from the other thread.

    I am trying to download the images onto a defined blank image using setContext() within setup. That way I can play around with the image. I suspect the http protocol will only allow streaming of the image and an array of several images merely holds a pointer to the image for streaming.
  • dave1707dave1707 Mod
    Posts: 9,415

    @Bri_G I’m displaying the image from img. I only do a http request when you tap the screen. The images could be moved into a table and viewed from there so you could rotate thru them.

  • Posts: 2,348

    @dave1707 - attached a listing of your code slightly adapted. Run it then switch the in context commenting to other copy and re-run.

    Moving the code to the subroutine works, so I have a way forward. Thanks.


    viewer.mode=FULLSCREEN function setup() -- tab = {"http://www.freeimageslive.com/galleries/home/playroom/pics/objects00016g.jpg"} z=#tab http.request(tab[z],gotImage,noImage) pic = image(400,400) setContext(pic) spriteMode(CENTER) sprite(img,200,200,400,400) setContext() end function draw() background(40,40,50) sprite(pic,WIDTH/2,HEIGHT/2) end function addImageToTable( theImage, status, head ) print(i,status,head) table.insert(imageTable, theImage) end function noImage() print("Error: ",tab[z]) getNext=true end function gotImage(image1,status,header) print("Success: ",tab[z]) img=image1 --[[ setContext(pic) spriteMode(CENTER) sprite(img,200,200,400,400) setContext() ]] end function touched(t) if t.state==BEGAN then getNext=true end end
  • edited May 25 Posts: 193
    @Bri_G Are you perhaps misunderstanding how the http request works? The key thing here is that it's always asynchronous, so the code following `http.request` will always execute before either of the callbacks are actually executed.

    The callbacks themselves will be executed outside of any `setup()` or `draw()` call. As Lua is inherently single-threaded the entire `setup()` call in which the request is made will run in its entirety before any of the callbacks are executed by the Codea runtime.

    @Simeon Is this right or am I talking crap?
  • edited May 25 Posts: 2,348
    @dave1707 @steppers - you may be right, I wondered if it was down to timing as downloads over the net vary wildly. However downloading 1 image in setup and writing to a blank image I should have thought was fine. How do you explain the difference in location of the setContext() loop?
  • dave1707dave1707 Mod
    Posts: 9,415

    @Bri_G With the setcontext in setup, it’s being executed before the http.request is finished. So img isn’t loaded yet giving you nil. With it in gotImage, then http.request is done and the gotImage function is called.

  • Posts: 2,348

    @dave1707 - aha, so it is down to timing. Thanks, I’m sure I have encountered this before but it’s not something I use on a regular basis - hence having to ask for support. Thanks again.

  • dave1707dave1707 Mod
    Posts: 9,415

    @Bri_G Just a quick refresher. The http.request will download whatever you request. When the download is done and successful, it calls the gotImage function or whatever name you have for the first callback. If the request fails, then the noImage function is called or whatever function name you have for the second callback. So you can download multiple items one after the other by setting a variable in the gotImage callback to start then next request.

  • Posts: 193
    @Bri_G Yes, timing entirely. The callbacks are only called when the request/download completes or fails. In the case of a large file this could mean 'draw()' is called and a frame rendered multiple times before any callback is even executed. Even for a small file the callback won't be executed until execution returns to the runtime (setup() or draw() returning)
  • Posts: 2,348

    Hi All,

    Have attached a project with a 3D cube carousel using the image downloads from the net mentioned in this thread and others. It’s not finished, I struggled to reload a new set of images with the routine I have put in. Also I left a routine to display the downloaded images in to check whilst developing. Any ideas would be appreciated.

  • dave1707dave1707 Mod
    edited May 28 Posts: 9,415

    @Bri_G Try this. Slide the Boolean parameter for next set of images.

    Updated version below
    
  • Posts: 2,348
    @dave1707 - thanks for that, very neat and tidy as usual. Always something to learn when you post.

    One thing, I originally used 'load' in my parameter.action but it turned orange when I tried to use it as a variable. Looks like it may be a reserved word but you've used it as a function.
  • dave1707dave1707 Mod
    Posts: 9,415

    @Bri_G There’s a volume:load(), so maybe that’s why.

  • dave1707dave1707 Mod
    Posts: 9,415

    @Bri_G Here’s an updated version. The changes are
    1. I create the cube only once.
    2. When all six new images are received, I update the cubes material.map with the new images.

    viewer.mode=STANDARD
    
    function setup()
        wTab={}
        assert(OrbitViewer, "Please include Cameras as a dependency")
        scene = craft.scene()
        scene.ambientColor=color(255)
        v=scene.camera:add(OrbitViewer, vec3(0,0,0), 40, 0, 200)    
        v.rx,v.ry=30,30
        createCube()
        parameter.boolean("New_images",new)
        new()
    end
    
    function draw()
        update(DeltaTime)
        scene:draw()
    end
    
    function update(dt)
        scene:update(dt)
    end
    
    function new()
        New_images=false
        getImages()
    end
    
    function createCube()
        createWall(vec3(-5,0,0),vec3(.1,10,10))
        createWall(vec3(5,0,0),vec3(.1,10,10))    
        createWall(vec3(0,-5,0),vec3(10,.1,10))    
        createWall(vec3(0,0,5),vec3(10,10,.1))    
        createWall(vec3(0,0,-5),vec3(10,10,.1))
        createWall(vec3(0,5,0),vec3(10,.1,10))
    end
    
    function createWall(pos,mod)
        local temp=scene:entity()
        temp.position=pos
        temp.model = craft.model.cube(mod)
        temp.material = craft.material(asset.builtin.Materials.Standard)
        temp.material.map = readImage(asset.builtin.SpaceCute.Health_Heart)
        table.insert(wTab,temp)
    end
    
    function getImages()
        images={}
        for i=1,6 do
            http.request( 'https://picsum.photos/200/200',addImageToTable)
        end
    end
    
    function addImageToTable( theImage, status, head )
        table.insert(images,theImage)
        if #images==6 then
            for z=1,6 do
                wTab[z].material.map=images[z]
            end
        end
    end
    
  • Posts: 2,348

    @dave1707 - great, it’s getting really compact and tidy now. I never think about using a craft cube made up of Craft walls but the code looks so neat and tidy. Need to go back and add to a few other projects. Thanks for this. I’m busy trying to add a default cube from local assets (Dropbox) so that it is present until you use the Boolean slider.

Sign In or Register to comment.