Modern way to load a picture from the web?

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

Modern way to load a picture from the web?

Hannes Hirzel
Hello

What is a good modern way in Squeak to load a picture from the web?

I am looking for an equivalent of

| pngPicURL aStream |

pngPicURL := 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.

aStream := HTTPSocket httpGet: pngPicURL.

(ImageReadWriter formFromStream: aStream) asMorph openInHand

And answer or just comments are welcome.

Thank you.

Kind regards

Hannes

Reply | Threaded
Open this post in threaded view
|

Re: Modern way to load a picture from the web?

marcel.taeumel
What about ...

Form fromBinaryStream: (WebClient httpGet: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png') contentStream.

... I think we should add a #fromUrl: besides Form class >> #fromFileNamed: and there distinguish between file paths and HTTP urls etc:

Form fromUrl: 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.

Best,
Marcel

Am 21.03.2019 11:51:58 schrieb H. Hirzel <[hidden email]>:

Hello

What is a good modern way in Squeak to load a picture from the web?

I am looking for an equivalent of

| pngPicURL aStream |

pngPicURL := 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.

aStream := HTTPSocket httpGet: pngPicURL.

(ImageReadWriter formFromStream: aStream) asMorph openInHand

And answer or just comments are welcome.

Thank you.

Kind regards

Hannes



Reply | Threaded
Open this post in threaded view
|

Re: Modern way to load a picture from the web?

Hannes Hirzel
Thanks for answering, Marcel

On 3/21/19, Marcel Taeumel <[hidden email]> wrote:
> What about ...
>
> Form fromBinaryStream: (WebClient httpGet:
> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png')
> contentStream.

Unfortunately a debugger window comes up [1]


> ... I think we should add a #fromUrl: besides Form class >> #fromFileNamed:
> and there distinguish between file paths and HTTP urls etc:
>
> Form fromUrl:
> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.

Yes, that would be fine to create a new convenience method

     Form fromUrl:

after we have figured out the solution.

-- Hannes

[1]
SecureSocketStream(Object)>>doesNotUnderstand: #reset
        Receiver: SecureSocketStream[inbuf:4kb/outbuf:4kb]
        Arguments and temporary variables:
                aMessage: reset
                exception: MessageNotUnderstood: SecureSocketStream>>reset
                resumeValue: nil
        Receiver's instance variables:
                recentlyRead: 0
                socket: a Socket[destroyed]
                inBuffer: #[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0...etc...
                outBuffer: #[71 69 84 32 47 119 105 107 105 112 101 100 105 97 47
99 111 109 10...etc...
                inNextToWrite: 1
                outNextToWrite: 1
                lastRead: 0
                timeout: 45
                autoFlush: true
                bufferSize: 4096
                binary: true
                shouldSignal: true
                ssl: nil
                sendBuf: #[23 3 3 0 232 61 247 6 24 144 238 146 249 51 100 82 127
29 104 195 17...etc...
                readBuf: #[203 4 102 97 151 46 237 173 196 165 168 136 21 56 21 225
6 113 183 1...etc...
                decoded: a ReadStream
                certIssues: 0

[] in ImageReadWriter class>>formFromStream:
        Receiver: ImageReadWriter
        Arguments and temporary variables:
<<error during printing>
        Receiver's instance variables:
                superclass: Object
                methodDict: a MethodDictionary(#atEnd->(ImageReadWriter>>#atEnd "a
CompiledMethod...etc...
                format: 65537
                instanceVariables: #('stream')
                organization: ('accessing' nextImage nextPutImage:)
('stream access' atEnd close...etc...
                subclasses: {PCXReadWriter . XBMReadWriter . JPEGReadWriter .
JPEGReadWriter2 ....etc...
                name: #ImageReadWriter
                classPool: a Dictionary(#ImageNotStoredSignal->nil
#MagicNumberErrorSignal->nil...etc...
                sharedPools: nil
                environment: nil
                category: #'Graphics-Files'

Reply | Threaded
Open this post in threaded view
|

Re: Modern way to load a picture from the web?

Hannes Hirzel
It works if I replace

    #contentStream

with

   content asByteArray readStream

Form fromBinaryStream: (WebClient httpGet:
'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png')
content asByteArray readStream.

On 3/21/19, H. Hirzel <[hidden email]> wrote:

> Thanks for answering, Marcel
>
> On 3/21/19, Marcel Taeumel <[hidden email]> wrote:
>> What about ...
>>
>> Form fromBinaryStream: (WebClient httpGet:
>> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png')
>> contentStream.
>
> Unfortunately a debugger window comes up [1]
>
>
>> ... I think we should add a #fromUrl: besides Form class >>
>> #fromFileNamed:
>> and there distinguish between file paths and HTTP urls etc:
>>
>> Form fromUrl:
>> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.
>
> Yes, that would be fine to create a new convenience method
>
>      Form fromUrl:
>
> after we have figured out the solution.
>
> -- Hannes
>
> [1]
> SecureSocketStream(Object)>>doesNotUnderstand: #reset
> Receiver: SecureSocketStream[inbuf:4kb/outbuf:4kb]
> Arguments and temporary variables:
> aMessage: reset
> exception: MessageNotUnderstood: SecureSocketStream>>reset
> resumeValue: nil
> Receiver's instance variables:
> recentlyRead: 0
> socket: a Socket[destroyed]
> inBuffer: #[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
> 0 0 0 0 0 0...etc...
> outBuffer: #[71 69 84 32 47 119 105 107 105 112 101 100 105 97 47
> 99 111 109 10...etc...
> inNextToWrite: 1
> outNextToWrite: 1
> lastRead: 0
> timeout: 45
> autoFlush: true
> bufferSize: 4096
> binary: true
> shouldSignal: true
> ssl: nil
> sendBuf: #[23 3 3 0 232 61 247 6 24 144 238 146 249 51 100 82 127
> 29 104 195 17...etc...
> readBuf: #[203 4 102 97 151 46 237 173 196 165 168 136 21 56 21 225
> 6 113 183 1...etc...
> decoded: a ReadStream
> certIssues: 0
>
> [] in ImageReadWriter class>>formFromStream:
> Receiver: ImageReadWriter
> Arguments and temporary variables:
> <<error during printing>
> Receiver's instance variables:
> superclass: Object
> methodDict: a MethodDictionary(#atEnd->(ImageReadWriter>>#atEnd "a
> CompiledMethod...etc...
> format: 65537
> instanceVariables: #('stream')
> organization: ('accessing' nextImage nextPutImage:)
> ('stream access' atEnd close...etc...
> subclasses: {PCXReadWriter . XBMReadWriter . JPEGReadWriter .
> JPEGReadWriter2 ....etc...
> name: #ImageReadWriter
> classPool: a Dictionary(#ImageNotStoredSignal->nil
> #MagicNumberErrorSignal->nil...etc...
> sharedPools: nil
> environment: nil
> category: #'Graphics-Files'
>

Reply | Threaded
Open this post in threaded view
|

Re: Modern way to load a picture from the web?

marcel.taeumel
Huh? WebResponse >> #contentStream has been there since 2012.

Best,
Marcel

Am 21.03.2019 20:37:40 schrieb H. Hirzel <[hidden email]>:

It works if I replace

#contentStream

with

content asByteArray readStream

Form fromBinaryStream: (WebClient httpGet:
'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png')
content asByteArray readStream.

On 3/21/19, H. Hirzel wrote:
> Thanks for answering, Marcel
>
> On 3/21/19, Marcel Taeumel wrote:
>> What about ...
>>
>> Form fromBinaryStream: (WebClient httpGet:
>> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png')
>> contentStream.
>
> Unfortunately a debugger window comes up [1]
>
>
>> ... I think we should add a #fromUrl: besides Form class >>
>> #fromFileNamed:
>> and there distinguish between file paths and HTTP urls etc:
>>
>> Form fromUrl:
>> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.
>
> Yes, that would be fine to create a new convenience method
>
> Form fromUrl:
>
> after we have figured out the solution.
>
> -- Hannes
>
> [1]
> SecureSocketStream(Object)>>doesNotUnderstand: #reset
> Receiver: SecureSocketStream[inbuf:4kb/outbuf:4kb]
> Arguments and temporary variables:
> aMessage: reset
> exception: MessageNotUnderstood: SecureSocketStream>>reset
> resumeValue: nil
> Receiver's instance variables:
> recentlyRead: 0
> socket: a Socket[destroyed]
> inBuffer: #[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
> 0 0 0 0 0 0...etc...
> outBuffer: #[71 69 84 32 47 119 105 107 105 112 101 100 105 97 47
> 99 111 109 10...etc...
> inNextToWrite: 1
> outNextToWrite: 1
> lastRead: 0
> timeout: 45
> autoFlush: true
> bufferSize: 4096
> binary: true
> shouldSignal: true
> ssl: nil
> sendBuf: #[23 3 3 0 232 61 247 6 24 144 238 146 249 51 100 82 127
> 29 104 195 17...etc...
> readBuf: #[203 4 102 97 151 46 237 173 196 165 168 136 21 56 21 225
> 6 113 183 1...etc...
> decoded: a ReadStream
> certIssues: 0
>
> [] in ImageReadWriter class>>formFromStream:
> Receiver: ImageReadWriter
> Arguments and temporary variables:
>
> Receiver's instance variables:
> superclass: Object
> methodDict: a MethodDictionary(#atEnd->(ImageReadWriter>>#atEnd "a
> CompiledMethod...etc...
> format: 65537
> instanceVariables: #('stream')
> organization: ('accessing' nextImage nextPutImage:)
> ('stream access' atEnd close...etc...
> subclasses: {PCXReadWriter . XBMReadWriter . JPEGReadWriter .
> JPEGReadWriter2 ....etc...
> name: #ImageReadWriter
> classPool: a Dictionary(#ImageNotStoredSignal->nil
> #MagicNumberErrorSignal->nil...etc...
> sharedPools: nil
> environment: nil
> category: #'Graphics-Files'
>



Reply | Threaded
Open this post in threaded view
|

Re: Modern way to load a picture from the web?

Hannes Hirzel
Yes, WebResponse >> #contentStream is there but if I use it I get an
error message, see my earlier mail in this thread where I include the
details.

It seems that the stream is asked for #reset and that does not go well
with the stream WebResponse uses.

SecureSocketStream(Object)>>doesNotUnderstand: #reset

So getting the whole content first and then to ask for a new stream is
a workaround.
It is a solution but maybe not the solution.

More investigation needed....

HH


On 3/22/19, Marcel Taeumel <[hidden email]> wrote:

> Huh? WebResponse >> #contentStream has been there since 2012.
>
> Best,
> Marcel
> Am 21.03.2019 20:37:40 schrieb H. Hirzel <[hidden email]>:
> It works if I replace
>
> #contentStream
>
> with
>
> content asByteArray readStream
>
> Form fromBinaryStream: (WebClient httpGet:
> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png')
> content asByteArray readStream.
>
> On 3/21/19, H. Hirzel wrote:
>> Thanks for answering, Marcel
>>
>> On 3/21/19, Marcel Taeumel wrote:
>>> What about ...
>>>
>>> Form fromBinaryStream: (WebClient httpGet:
>>> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png')
>>> contentStream.
>>
>> Unfortunately a debugger window comes up [1]
>>
>>
>>> ... I think we should add a #fromUrl: besides Form class >>
>>> #fromFileNamed:
>>> and there distinguish between file paths and HTTP urls etc:
>>>
>>> Form fromUrl:
>>> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.
>>
>> Yes, that would be fine to create a new convenience method
>>
>> Form fromUrl:
>>
>> after we have figured out the solution.
>>
>> -- Hannes
>>
>> [1]
>> SecureSocketStream(Object)>>doesNotUnderstand: #reset
>> Receiver: SecureSocketStream[inbuf:4kb/outbuf:4kb]
>> Arguments and temporary variables:
>> aMessage: reset
>> exception: MessageNotUnderstood: SecureSocketStream>>reset
>> resumeValue: nil
>> Receiver's instance variables:
>> recentlyRead: 0
>> socket: a Socket[destroyed]
>> inBuffer: #[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
>> 0 0 0 0 0 0...etc...
>> outBuffer: #[71 69 84 32 47 119 105 107 105 112 101 100 105 97 47
>> 99 111 109 10...etc...
>> inNextToWrite: 1
>> outNextToWrite: 1
>> lastRead: 0
>> timeout: 45
>> autoFlush: true
>> bufferSize: 4096
>> binary: true
>> shouldSignal: true
>> ssl: nil
>> sendBuf: #[23 3 3 0 232 61 247 6 24 144 238 146 249 51 100 82 127
>> 29 104 195 17...etc...
>> readBuf: #[203 4 102 97 151 46 237 173 196 165 168 136 21 56 21 225
>> 6 113 183 1...etc...
>> decoded: a ReadStream
>> certIssues: 0
>>
>> [] in ImageReadWriter class>>formFromStream:
>> Receiver: ImageReadWriter
>> Arguments and temporary variables:
>>
>> Receiver's instance variables:
>> superclass: Object
>> methodDict: a MethodDictionary(#atEnd->(ImageReadWriter>>#atEnd "a
>> CompiledMethod...etc...
>> format: 65537
>> instanceVariables: #('stream')
>> organization: ('accessing' nextImage nextPutImage:)
>> ('stream access' atEnd close...etc...
>> subclasses: {PCXReadWriter . XBMReadWriter . JPEGReadWriter .
>> JPEGReadWriter2 ....etc...
>> name: #ImageReadWriter
>> classPool: a Dictionary(#ImageNotStoredSignal->nil
>> #MagicNumberErrorSignal->nil...etc...
>> sharedPools: nil
>> environment: nil
>> category: #'Graphics-Files'
>>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Modern way to load a picture from the web?

Tobias Pape

> On 22.03.2019, at 09:35, H. Hirzel <[hidden email]> wrote:
>
> Yes, WebResponse >> #contentStream is there but if I use it I get an
> error message, see my earlier mail in this thread where I include the
> details.
>
> It seems that the stream is asked for #reset and that does not go well
> with the stream WebResponse uses.
>
> SecureSocketStream(Object)>>doesNotUnderstand: #reset
>
> So getting the whole content first and then to ask for a new stream is
> a workaround.
> It is a solution but maybe not the solution.
>
> More investigation needed....

No. The WebResponse stream is a non-resettable stream, it comes effectively from the network, so you can't meaningfully #reset it :)
I can think of several ways to counter that, but not today :D

Best regards
        -Tobias


>
> HH
>
>
> On 3/22/19, Marcel Taeumel <[hidden email]> wrote:
>> Huh? WebResponse >> #contentStream has been there since 2012.
>>
>> Best,
>> Marcel
>> Am 21.03.2019 20:37:40 schrieb H. Hirzel <[hidden email]>:
>> It works if I replace
>>
>> #contentStream
>>
>> with
>>
>> content asByteArray readStream
>>
>> Form fromBinaryStream: (WebClient httpGet:
>> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png')
>> content asByteArray readStream.
>>
>> On 3/21/19, H. Hirzel wrote:
>>> Thanks for answering, Marcel
>>>
>>> On 3/21/19, Marcel Taeumel wrote:
>>>> What about ...
>>>>
>>>> Form fromBinaryStream: (WebClient httpGet:
>>>> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png')
>>>> contentStream.
>>>
>>> Unfortunately a debugger window comes up [1]
>>>
>>>
>>>> ... I think we should add a #fromUrl: besides Form class >>
>>>> #fromFileNamed:
>>>> and there distinguish between file paths and HTTP urls etc:
>>>>
>>>> Form fromUrl:
>>>> 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.
>>>
>>> Yes, that would be fine to create a new convenience method
>>>
>>> Form fromUrl:
>>>
>>> after we have figured out the solution.
>>>
>>> -- Hannes
>>>
>>> [1]
>>> SecureSocketStream(Object)>>doesNotUnderstand: #reset
>>> Receiver: SecureSocketStream[inbuf:4kb/outbuf:4kb]
>>> Arguments and temporary variables:
>>> aMessage: reset
>>> exception: MessageNotUnderstood: SecureSocketStream>>reset
>>> resumeValue: nil
>>> Receiver's instance variables:
>>> recentlyRead: 0
>>> socket: a Socket[destroyed]
>>> inBuffer: #[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
>>> 0 0 0 0 0 0...etc...
>>> outBuffer: #[71 69 84 32 47 119 105 107 105 112 101 100 105 97 47
>>> 99 111 109 10...etc...
>>> inNextToWrite: 1
>>> outNextToWrite: 1
>>> lastRead: 0
>>> timeout: 45
>>> autoFlush: true
>>> bufferSize: 4096
>>> binary: true
>>> shouldSignal: true
>>> ssl: nil
>>> sendBuf: #[23 3 3 0 232 61 247 6 24 144 238 146 249 51 100 82 127
>>> 29 104 195 17...etc...
>>> readBuf: #[203 4 102 97 151 46 237 173 196 165 168 136 21 56 21 225
>>> 6 113 183 1...etc...
>>> decoded: a ReadStream
>>> certIssues: 0
>>>
>>> [] in ImageReadWriter class>>formFromStream:
>>> Receiver: ImageReadWriter
>>> Arguments and temporary variables:
>>>
>>> Receiver's instance variables:
>>> superclass: Object
>>> methodDict: a MethodDictionary(#atEnd->(ImageReadWriter>>#atEnd "a
>>> CompiledMethod...etc...
>>> format: 65537
>>> instanceVariables: #('stream')
>>> organization: ('accessing' nextImage nextPutImage:)
>>> ('stream access' atEnd close...etc...
>>> subclasses: {PCXReadWriter . XBMReadWriter . JPEGReadWriter .
>>> JPEGReadWriter2 ....etc...
>>> name: #ImageReadWriter
>>> classPool: a Dictionary(#ImageNotStoredSignal->nil
>>> #MagicNumberErrorSignal->nil...etc...
>>> sharedPools: nil
>>> environment: nil
>>> category: #'Graphics-Files'
>>>
>>
>>
>



Reply | Threaded
Open this post in threaded view
|

Re: Modern way to load a picture from the web?

Hannes Hirzel
Hello Tobias

On 3/22/19, Tobias Pape <[hidden email]> wrote:

>
>> On 22.03.2019, at 09:35, H. Hirzel <[hidden email]> wrote:
>>
>> Yes, WebResponse >> #contentStream is there but if I use it I get an
>> error message, see my earlier mail in this thread where I include the
>> details.
>>
>> It seems that the stream is asked for #reset and that does not go well
>> with the stream WebResponse uses.
>>
>> SecureSocketStream(Object)>>doesNotUnderstand: #reset
>>
>> So getting the whole content first and then to ask for a new stream is
>> a workaround.
>> It is a solution but maybe not the solution.
>>
>> More investigation needed....
>
> No. The WebResponse stream is a non-resettable stream, it comes effectively
> from the network, so you can't meaningfully #reset it :)

Sure, I am aware that WebResponse is a non-resettable stream.

To reset the SecureSocketStream stream would mean that I have to get
the content again from the web. This is not be what is wanted most of
the time.

So somewhere we need to
- get the content of the WebResponse object
- convert it to an in-memory stream.


    content asByteArray readStream.


theUrl := 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.

 Form fromBinaryStream: (WebClient httpGet: theUrl) content
asByteArray readStream.

> I can think of several ways to counter that, but not today :D
Yes, I am interested in this, even in 3 .. 300 days time :-)

in the meantime I use the following patch in my application (method
name and class suggested by Marcel) -- a useful solution..

NEW method
    Form class>>fromUrl: anUrlString

similar to

    Form fromFileNamed: fileName


Yours and Marcel's feedback was helpful for me to get at this point.

...................................................................................................................................

'From Squeak5.2 of 13 December 2018 [latest update: #18221] on 22
March 2019 at 11:37:44 am'!

!Form class methodsFor: '*Add-Ons-BaseImage52patches' stamp: 'hjh
3/22/2019 11:37'!
fromUrl: anUrlString
"It is advisable to call this in a separate process"

self fromBinaryStream: (WebClient httpGet: anUrlString) content
asByteArray readStream.
! !

...................................................................................................................................

An issue I had is that depending on the URL this may lock up the
image, so it is advisable to put the call to #fromUrl: into another
process.


Regards

Hannes

Reply | Threaded
Open this post in threaded view
|

Re: Modern way to load a picture from the web?

Levente Uzonyi
On Fri, 22 Mar 2019, H. Hirzel wrote:

> Hello Tobias
>
> On 3/22/19, Tobias Pape <[hidden email]> wrote:
>>
>>> On 22.03.2019, at 09:35, H. Hirzel <[hidden email]> wrote:
>>>
>>> Yes, WebResponse >> #contentStream is there but if I use it I get an
>>> error message, see my earlier mail in this thread where I include the
>>> details.
>>>
>>> It seems that the stream is asked for #reset and that does not go well
>>> with the stream WebResponse uses.
>>>
>>> SecureSocketStream(Object)>>doesNotUnderstand: #reset
>>>
>>> So getting the whole content first and then to ask for a new stream is
>>> a workaround.
>>> It is a solution but maybe not the solution.
>>>
>>> More investigation needed....
>>
>> No. The WebResponse stream is a non-resettable stream, it comes effectively
>> from the network, so you can't meaningfully #reset it :)
>
> Sure, I am aware that WebResponse is a non-resettable stream.
>
> To reset the SecureSocketStream stream would mean that I have to get
> the content again from the web. This is not be what is wanted most of
> the time.

Or you could just pick the right converter based on the mime type of the
response. #reset is sent by ImageReadWriter, because it uses trial and
error to find the right converter for the image.

Levente

>
> So somewhere we need to
> - get the content of the WebResponse object
> - convert it to an in-memory stream.
>
>
>    content asByteArray readStream.
>
>
> theUrl := 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.
>
> Form fromBinaryStream: (WebClient httpGet: theUrl) content
> asByteArray readStream.
>
>> I can think of several ways to counter that, but not today :D
> Yes, I am interested in this, even in 3 .. 300 days time :-)
>
> in the meantime I use the following patch in my application (method
> name and class suggested by Marcel) -- a useful solution..
>
> NEW method
>    Form class>>fromUrl: anUrlString
>
> similar to
>
>    Form fromFileNamed: fileName
>
>
> Yours and Marcel's feedback was helpful for me to get at this point.
>
> ...................................................................................................................................
>
> 'From Squeak5.2 of 13 December 2018 [latest update: #18221] on 22
> March 2019 at 11:37:44 am'!
>
> !Form class methodsFor: '*Add-Ons-BaseImage52patches' stamp: 'hjh
> 3/22/2019 11:37'!
> fromUrl: anUrlString
> "It is advisable to call this in a separate process"
>
> self fromBinaryStream: (WebClient httpGet: anUrlString) content
> asByteArray readStream.
> ! !
>
> ...................................................................................................................................
>
> An issue I had is that depending on the URL this may lock up the
> image, so it is advisable to put the call to #fromUrl: into another
> process.
>
>
> Regards
>
> Hannes

Reply | Threaded
Open this post in threaded view
|

Re: Modern way to load a picture from the web?

Tim Johnson-2
In reply to this post by Hannes Hirzel
Hi Hannes,

I have implemented this in various ways in my InternetArchive client library—a work in (slow) progress over the last 3+ years.  Note I did not realize a similar library had been written for Sophie ten years ago.  This one was based on the Python client library which uses the current InternetArchive API.

I finally made it public in its current state here: 


Some examples for how to use it live in the IAExample* classes.  

The following will display the famous Byte cover and restore the display after a click:

(IAItem named: 'byte-magazine-1981-08' ) displayItemTileJpeg

Anyway, you can find my code in the 'displaying graphics' instance method category of IADownload.   Also note that you may be interested in seeing Form class>>#openImageInWindow:

Here is how I implemented some JPEG download & display in Squeak 5.2.  These methods are taken from the IADownload and perhaps IAItem classes.

getResponse
"returns a WebResponse object"
^ response := WebClient httpGet: self url.

downloadJpegIntoForm
| s contents jww imageExtent form | 
s := ByteArray new writeStream.
s binary.
self getResponse.
response streamTo: s size: response contentLength progress: nil.
response close.
contents := s contents.
(JPEGReadWriter2 understandsImageFormat: (contents readStream))
ifFalse: [^ self error: 'cannot read jpeg'].
jww := JPEGReadWriter2 new.
imageExtent := jww imageExtent: contents.
form := Form extent: imageExtent depth: 32.
jww uncompress: contents into: form doDithering: false.
^ form

displayJpeg
| form | 
form := self downloadJpegIntoForm.
Display restoreAfter: [ form displayOn: Display ].


displayJpegInMorph
| form morph | 
form := self downloadJpegIntoForm.
morph := BorderedMorph newBounds: (form bounds). 
Display restoreAfter: [ form displayOn: Display ].


displayJpegInWindow
| form morph window | 
self flag: #seeFormClassSideForUtilityMethod.
form := self downloadJpegIntoForm.
morph := form asMorph.

window := SystemWindow labelled: 'image'.
window 
" addMorphCentered: (form asMorph);"
addMorph: (form asMorph) frame: (0.0@0.0 corner: 1.0@1.0) .
" addMorph: (form asMorph) fullFrame: (SystemWindow menuBoxFrame) ."
window 
openInWorldExtent: (form extent scaleBy: 1.2 @ 1.2).



Let me know if I can help further.  I believe there is also code in there for displaying downloaded GIFs and animated GIFs but I could be wrong.

Best,
Tim






On Mar 21, 2019, at 3:51 AM, H. Hirzel <[hidden email]> wrote:

Hello

What is a good modern way in Squeak to load a picture from the web?

I am looking for an equivalent of

| pngPicURL aStream |

pngPicURL := 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.

aStream := HTTPSocket httpGet: pngPicURL.

(ImageReadWriter formFromStream: aStream) asMorph openInHand

And answer or just comments are welcome.

Thank you.

Kind regards

Hannes





Reply | Threaded
Open this post in threaded view
|

Re: Modern way to load a picture from the web?

Tim Johnson-2
Self-reply:

I just noticed the #displayJpegInMorph method below is garbage and can be ignored.

Also, I believe there is a higher-level abstraction above JPEGReadWriter2.  If I recall correctly, this higher level abstraction is connected to the Services architecture and can display many different formats of image files from disk.  I didn't dig into it much and could be mistaken, but with further research it could prove useful.

Thanks again,
Tim J



On Apr 2, 2019, at 8:15 AM, Tim Johnson <[hidden email]> wrote:

Hi Hannes,

I have implemented this in various ways in my InternetArchive client library—a work in (slow) progress over the last 3+ years.  Note I did not realize a similar library had been written for Sophie ten years ago.  This one was based on the Python client library which uses the current InternetArchive API.

I finally made it public in its current state here: 


Some examples for how to use it live in the IAExample* classes.  

The following will display the famous Byte cover and restore the display after a click:

(IAItem named: 'byte-magazine-1981-08' ) displayItemTileJpeg

Anyway, you can find my code in the 'displaying graphics' instance method category of IADownload.   Also note that you may be interested in seeing Form class>>#openImageInWindow:

Here is how I implemented some JPEG download & display in Squeak 5.2.  These methods are taken from the IADownload and perhaps IAItem classes.

getResponse
"returns a WebResponse object"
^ response := WebClient httpGet: self url.

downloadJpegIntoForm
| s contents jww imageExtent form | 
s := ByteArray new writeStream.
s binary.
self getResponse.
response streamTo: s size: response contentLength progress: nil.
response close.
contents := s contents.
(JPEGReadWriter2 understandsImageFormat: (contents readStream))
ifFalse: [^ self error: 'cannot read jpeg'].
jww := JPEGReadWriter2 new.
imageExtent := jww imageExtent: contents.
form := Form extent: imageExtent depth: 32.
jww uncompress: contents into: form doDithering: false.
^ form

displayJpeg
| form | 
form := self downloadJpegIntoForm.
Display restoreAfter: [ form displayOn: Display ].


displayJpegInMorph
| form morph | 
form := self downloadJpegIntoForm.
morph := BorderedMorph newBounds: (form bounds). 
Display restoreAfter: [ form displayOn: Display ].


displayJpegInWindow
| form morph window | 
self flag: #seeFormClassSideForUtilityMethod.
form := self downloadJpegIntoForm.
morph := form asMorph.

window := SystemWindow labelled: 'image'.
window 
" addMorphCentered: (form asMorph);"
addMorph: (form asMorph) frame: (0.0@0.0 corner: 1.0@1.0) .
" addMorph: (form asMorph) fullFrame: (SystemWindow menuBoxFrame) ."
window 
openInWorldExtent: (form extent scaleBy: 1.2 @ 1.2).



Let me know if I can help further.  I believe there is also code in there for displaying downloaded GIFs and animated GIFs but I could be wrong.

Best,
Tim






On Mar 21, 2019, at 3:51 AM, H. Hirzel <[hidden email]> wrote:

Hello

What is a good modern way in Squeak to load a picture from the web?

I am looking for an equivalent of

| pngPicURL aStream |

pngPicURL := 'https://upload.wikimedia.org/wikipedia/commons/thumb/1/11/Squeak-x11.png/617px-Squeak-x11.png'.

aStream := HTTPSocket httpGet: pngPicURL.

(ImageReadWriter formFromStream: aStream) asMorph openInHand

And answer or just comments are welcome.

Thank you.

Kind regards

Hannes