Streaming directly from WebResponse content to SketchMorph

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

Streaming directly from WebResponse content to SketchMorph

CdAB63
Hello,

Is it possible to stream an image (png) directly from WebResponse to a
SketchMorph ? I'd like to avoid the burden of saving image in temporary
file to load it into a SketchMorph.

Tried something like:

...

response contentStream binary.
sm := SketchMorph fromStream: resp contentStream.

It fails. Don't know image type.

An alternative would be creating a socket interface so I stream image to
socket and read from the socket... but it would be verbose... would
involve forking... would be kind of a dirty job.

[ response streamTo: sock size: response contentLength progress: nil ]
fork. (...)

sm := SketchMorph fromStream: sock. (...)


If some of you can give me a light in this subject... :)

Best regards,

CdAB




signature.asc (267 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Streaming directly from WebResponse content to SketchMorph

Bert Freudenberg

On 17.10.2012, at 16:05, Casimiro de Almeida Barreto <[hidden email]> wrote:

> Hello,
>
> Is it possible to stream an image (png) directly from WebResponse to a
> SketchMorph ? I'd like to avoid the burden of saving image in temporary
> file to load it into a SketchMorph.
>
> Tried something like:
>
> ...
>
> response contentStream binary.
> sm := SketchMorph fromStream: resp contentStream.
>
> It fails. Don't know image type.
>
> An alternative would be creating a socket interface so I stream image to
> socket and read from the socket... but it would be verbose... would
> involve forking... would be kind of a dirty job.
>
> [ response streamTo: sock size: response contentLength progress: nil ]
> fork. (...)
>
> sm := SketchMorph fromStream: sock. (...)
>
>
> If some of you can give me a light in this subject... :)


You just need to decode the PNG data into a form, then you can use it in a morph. E.g.:

(PNGReadWriter formFromStream: (HTTPClient httpGet: 'http://squeak.org/img/squeaklogosmallerpng')) asMorph openInHand

- Bert -



Reply | Threaded
Open this post in threaded view
|

Re: Streaming directly from WebResponse content to SketchMorph

CdAB63
On 17-10-2012 20:42, Bert Freudenberg wrote:
> (PNGReadWriter formFromStream: (HTTPClient httpGet: 'http://squeak.org/img/squeaklogosmallerpng')) asMorph openInHand
Not so easy... site requires authentication (hence the idea of using
WebClient...)

| wc url resp ucode passw sm |

Transcript clear.

url := 'http://127.0.0.1:8088/(... lots of path elements ...)/image.png'.

ucode := 'xxx'.
passw := 'yyy'.

   
resp := (WebClient) new
                acceptCookies: true;
                username: ucode;
                password: passw;
                httpGet: url.
           
resp contentStream binary.

(PNGReadWriter formFromStream: resp contentStream) asMorph openInHand

It fails with "Image format not recognized.

What happens is that in the test there's something like:

understandsImageFormat
   
    #(137 80 78 71 13 10 26 10) do: [ :byte |
        stream next = byte ifFalse: [^ false]].
    ^ true

and while byte is Character stream returns SmallInteger. So, yeah, first
element of list is 137 and first byte of stream is 137 but comparsion
fails. If forced (byte asInteger) it will fail later on decoding.

Interesting enough is that when it reads from a file stream it works
(provided content binary).




signature.asc (267 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Streaming directly from WebResponse content to SketchMorph

Bob Arning-2
The problem with this approach is that the contentStream is a SocketStream which has some issues:

- does not undersatnd #reset. This is used after matching the first bytes to ensure starting at the beginning when building the image.
- has wobbly #atEnd. The png reader keeps getting data until the end of the stream, but the SocketStream won't answer true to #atEnd until the socket is closed.

The following will work, but I'm not certain if WebClient might give you the response before all needed data has arrived, in which case it will not work. ;-)

    | url resp ucode passw myData myStream |

    Transcript clear.

    url := 'http://127.0.0.1/~bob/images/addInitialAction_button.png'.

    ucode := 'xxx'.
    passw := 'yyy'.

      
    resp := (WebClient) new
                    acceptCookies: true;
                    username: ucode;
                    password: passw;
                    httpGet: url.
              
    resp contentStream binary.
    myData _ resp contentStream nextAllInBuffer.
    myStream _ ReadStream on: myData.
    (PNGReadWriter on: myStream) nextImage asMorph openInHand

Cheers,
Bob

On 10/17/12 8:38 PM, Casimiro de Almeida Barreto wrote:
On 17-10-2012 20:42, Bert Freudenberg wrote:
(PNGReadWriter formFromStream: (HTTPClient httpGet: 'http://squeak.org/img/squeaklogosmallerpng')) asMorph openInHand
Not so easy... site requires authentication (hence the idea of using
WebClient...)

| wc url resp ucode passw sm |

Transcript clear.

url := 'http://127.0.0.1:8088/(... lots of path elements ...)/image.png'.

ucode := 'xxx'.
passw := 'yyy'.

   
resp := (WebClient) new
                acceptCookies: true;
                username: ucode;
                password: passw;
                httpGet: url.
           
resp contentStream binary.

(PNGReadWriter formFromStream: resp contentStream) asMorph openInHand

It fails with "Image format not recognized.

What happens is that in the test there's something like:

understandsImageFormat
   
    #(137 80 78 71 13 10 26 10) do: [ :byte |
        stream next = byte ifFalse: [^ false]].
    ^ true

and while byte is Character stream returns SmallInteger. So, yeah, first
element of list is 137 and first byte of stream is 137 but comparsion
fails. If forced (byte asInteger) it will fail later on decoding.

Interesting enough is that when it reads from a file stream it works
(provided content binary).




    



Reply | Threaded
Open this post in threaded view
|

Re: Streaming directly from WebResponse content to SketchMorph

Andreas.Raab
In reply to this post by CdAB63
Casimiro de Almeida Barreto wrote
On 17-10-2012 20:42, Bert Freudenberg wrote:
> (PNGReadWriter formFromStream: (HTTPClient httpGet: 'http://squeak.org/img/squeaklogosmallerpng')) asMorph openInHand
Not so easy... site requires authentication (hence the idea of using
WebClient...)

| wc url resp ucode passw sm |

Transcript clear.

url := 'http://127.0.0.1:8088/(... lots of path elements ...)/image.png'.

ucode := 'xxx'.
passw := 'yyy'.

   
resp := (WebClient) new
                acceptCookies: true;
                username: ucode;
                password: passw;
                httpGet: url.
           
resp contentStream binary.

(PNGReadWriter formFromStream: resp contentStream) asMorph openInHand

It fails with "Image format not recognized.

What happens is that in the test there's something like:

understandsImageFormat
   
    #(137 80 78 71 13 10 26 10) do: [ :byte |
        stream next = byte ifFalse: [^ false]].
    ^ true

and while byte is Character stream returns SmallInteger. So, yeah, first
element of list is 137 and first byte of stream is 137 but comparsion
fails. If forced (byte asInteger) it will fail later on decoding.

Interesting enough is that when it reads from a file stream it works
(provided content binary).
Yes, but the reason is different. The ImageReadWriters assume seekable streams, and PNGReadWriter itself tries to do a "stream reset" which fails on SocketStream. That's why it refuses to read the data directly from the (socket) stream. Which means the following should work fine:

url := 'http://www.fnordware.com/superpng/pnggrad8rgb.png'.  
resp := (WebClient) new httpGet: url.
resp isSuccess ifFalse:[self error: resp content].
stream := RWBinaryOrTextStream with: resp content.
(PNGReadWriter formFromStream: stream) asMorph openInHand

Cheers,
  - Andreas
Reply | Threaded
Open this post in threaded view
|

Re: Streaming directly from WebResponse content to SketchMorph

Göran Krampe
Hi!

I pretty recently did some work for Citilabs reviving my "streaming
reception in SocketStream/Kom" in order to deal with very large file
uploads. That adds a "chunk wise" method to SocketStream so that one can
"read a bit at a time" and do things with it.

Now I notice that 4.3 has evolved a bit so merging that in might be a
bit of work.

regards, Göran

PS. But I presume you weren't really asking to *stream* into SketchMorph
- but simply avoid going to a temp file.

Reply | Threaded
Open this post in threaded view
|

Re: Streaming directly from WebResponse content to SketchMorph

Frank Shearar-3
On 18 October 2012 11:41, Göran Krampe <[hidden email]> wrote:
> Hi!
>
> I pretty recently did some work for Citilabs reviving my "streaming
> reception in SocketStream/Kom" in order to deal with very large file
> uploads. That adds a "chunk wise" method to SocketStream so that one can
> "read a bit at a time" and do things with it.

Sounds like a reason to use Xtreams...

frank

> Now I notice that 4.3 has evolved a bit so merging that in might be a bit of
> work.
>
> regards, Göran
>
> PS. But I presume you weren't really asking to *stream* into SketchMorph -
> but simply avoid going to a temp file.
>

Reply | Threaded
Open this post in threaded view
|

Re: Streaming directly from WebResponse content to SketchMorph

Colin Putney-3
On Thu, Oct 18, 2012 at 5:01 AM, Frank Shearar <[hidden email]> wrote:
> On 18 October 2012 11:41, Göran Krampe <[hidden email]> wrote:
>> Hi!
>>
>> I pretty recently did some work for Citilabs reviving my "streaming
>> reception in SocketStream/Kom" in order to deal with very large file
>> uploads. That adds a "chunk wise" method to SocketStream so that one can
>> "read a bit at a time" and do things with it.
>
> Sounds like a reason to use Xtreams...

Yes, this sort of thing is where Xtreams shines. The Altitude http
client examines the Content-Length header, then returns a limited
stream, so that you can read the response content until the end of the
stream and close it when you're done, without blocking on a socket
read or closing the socket. Xtreams also has a buffering stream so
that clients like PNGReadWriter can skip around, even when the
underlying data source doesn't support that.

Colin

Reply | Threaded
Open this post in threaded view
|

Proposals for Squeak 4.5 (was Re: [squeak-dev] Re: Streaming directly from WebResponse content to SketchMorph)

Edgar De Cleene



On 10/18/12 6:38 PM, "Colin Putney" <[hidden email]> wrote:

>> Sounds like a reason to use Xtreams...
>
> Yes, this sort of thing is where Xtreams shines. The Altitude http
> client examines the Content-Length header, then returns a limited
> stream, so that you can read the response content until the end of the
> stream and close it when you're done, without blocking on a socket
> read or closing the socket. Xtreams also has a buffering stream so
> that clients like PNGReadWriter can skip around, even when the
> underlying data source doesn't support that.
>
> Colin

I wish Xtreams become first citizen in Squeak 4.5.

By the way, great job of Frank in

http://wiki.squeak.org/squeak/6188

Edgar




Reply | Threaded
Open this post in threaded view
|

Re: Streaming directly from WebResponse content to SketchMorph

CdAB63
In reply to this post by Bob Arning-2
First, thanks for everybody. Using RWBinaryOrTextStream worked OK.

But I've had other problems with streams...

For instance, using streams other than the ones related to reading from hard disk in conjunction of XMLDOMParser also provide strange results (for instance an empty instance of XMLDOMParser without any errors)...

Like:

url:='http://127.0.0.1:8088/spec.xml'.
resp := (WebClient new)
            username: ucode;
            password: passw;
            acceptCookies: true;
            httpGet: url.

str := RWBinaryOrTextStream with: resp content.

xmlDocument := XMLDOMParser parseDocumentFrom: str.

returns an empty XMLDOMParser (all variables, etc, nil).

url:='http://127.0.0.1:8088/spec.xml'.
resp := (WebClient new)
            username: 'admin';
            password: 'c26354br';
            acceptCookies: true;
            httpGet: url.

xmlDocument := XMLDOMParser parseDocumentFrom: resp contentStream.

enters an infinite loop while waiting for next token...

But when I stream document to a file and then...

newStr := FileStream fileNamed: '/tmp/spec.xml'.

xmlDocument := XMLDOMParser parseDocumentFrom: newStr.


It works just fine...



signature.asc (267 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Streaming directly from WebResponse content to SketchMorph

CdAB63
In reply to this post by Bob Arning-2
O, BTW, returns XMLDocument... not XMLDOMParser (obviously)...

CdAB




signature.asc (267 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Streaming directly from WebResponse content to SketchMorph

Bob Arning-2
In reply to this post by CdAB63

On 10/19/12 1:29 PM, Casimiro de Almeida Barreto wrote:

str := RWBinaryOrTextStream with: resp content.

Use

    str := ReadStream on: resp content.

instead.

Cheers,
Bob