Wrote this for getting the content of image from the given URL. It accepts a URL and returns an array of shape number_of_channels image_height image_width. Each "row" represents a pixel, and each element is within the range of 0 to 1.

• What are some issues with my implementation?
• Is there a better way to turn the data from HttpCommand.Get into image?
• Is there a better way to handle different image format?
• How to make it more portable?

∇ r←GetImg url ;ns
'ns'⎕NS'url'
:With ns

valueOf←{⊃(,¯1↑⍉⍵)/⍨(⊂⍺)≡¨,1↑⍉⍵}
split←{⍵⊆⍨~⍺=⍵}

tmp_path←(⊢2 ⎕NQ # 'GetEnvironment',⊂)'tmp'

res←HttpCommand.Get url

tmp_ft←(tmp_path,'\tmp.',fmt)(⎕NCREATE⍠('Unique' 1))0
tmp_name←⊃⎕NINFO tmp_ft
res.Data ⎕NREPLACE tmp_ft 0
⎕NUNTIE tmp_ft
'bm'⎕WC'Bitmap'('File'tmp_name)
⎕NDELETE tmp_name
:EndWith
r←255÷⍨256(⊥⍣¯1)ns.bm.CBits
∇


1. Your use of :With is a clever way to avoid having to localise names, but you should be aware of the peculiarities of :With to avoid frustration in the future. Even inside the :With block, you can access r and in this case also url, but if the argument was an object, you would have to mention it explicitly, so you're doing the right thing here. Since you can access r, you can move the last line inside the block:

r←255÷⍨256(⊥⍣¯1)bm.CBits

2. You do not need the ns local, as you can give :With an anonymous namespace:

:With ⎕NS'url'

3. Since you're only using HttpCommand once, you can create an anonymous instance of it, which is then used (and discarded) immediately:

res←(⎕SE.SALT.New'HttpCommand'('Get' url)).Run

4. valueOf can be simplified a lot:

valueOf←{(⊢/⍵)⊃⍨(⊣/⍵)⍳⊂⍺}

5. I strongly recommend a strict naming convention. I'd personally name functions with initial Capital and variables with initial minuscule: ValueOf and Split

6. Split could use ≠ instead of inverting ~ the equality =. You could also consider using a train:

Split←≠⊆⊢

7. There's an I-beam to get a proper temporary directory, which will allow your function to work even if there's no tmp environment variable:

tmp_path←739⌶0

8. I personally try to avoid parentheses, especially to govern order of execution, so I'd write the tmp_ft line as:

tmp_ft←0 ⎕NCREATE⍠'Unique' 1⍨tmp_path,'\tmp.',fmt

9. The final expression that computes the result is the only real bug you have. You're using ⊥⍣¯1 to automatically determine how many base-256 "digits" to use. However, if your image has no red (or no red and no green) signal at all, you will end up with only two "digits", and the format will be all wrong. E.g. if the image was entirely cyan ($$\\color{#0FF}{⬤}\$$ #00FFFF), all the the pixels would be encoded as 65535, which would become 255 255 instead of 255 255 255. You must therefore specify the full radix:

r←255÷⍨bm.CBits⊤⍨3⍴256

Here is your function with all my suggested changes:

 r←GetImg url
:With ⎕NS'url'
ValueOf←{(⊢/⍵)⊃⍨(⊣/⍵)⍳⊂⍺}
Split←≠⊆⊢

tmp_path←739⌶0

res←(⎕SE.SALT.New'HttpCommand'('Get'url)).Run

tmp_ft←0 ⎕NCREATE⍠'Unique' 1⍨tmp_path,'\tmp.',fmt
tmp_name←⊃⎕NINFO tmp_ft
res.Data ⎕NREPLACE tmp_ft 0
⎕NUNTIE tmp_ft
'bm'⎕WC'Bitmap'('File'tmp_name)
⎕NDELETE tmp_name
r←255÷⍨bm.CBits⊤⍨3⍴256
:EndWith

• Thank you. One thing I want to ask is that, for the last point (9th), I did it that way to handle images with transparency, which will have an additional alpha channel in the front. After reading your answer, I used this which seems to be working: r←255÷⍨bm.CBits⊤⍨256⍴⍨3+24≤2⍟⌈/,bm.CBits But is there a better way to do that? Aug 27 at 3:02
• @leo3065 I'm frankly surprised that this works, and I'll take it up with the colleague that deals with this, but he's on holiday until Wednesday.