decode image data from a HTTP string response. (Elm 0.18) - image

I'd like to fetch an image from a remote server and load it into the following data structure:
type alias Pixel = { r : Int, g : Int, b: Int, a: Float }
type alias ImageData = { pixels : Array Pixel, width: Int }
In the project for some reasons I'm still using Elm 0.18, and elm-lang/http only let's you handle strings as responses from http requests.
init : ( Model, Cmd Msg )
init =
( {}
, Http.send
(\response ->
case response of
Ok data ->
let
_ =
Debug.log "ok" data
in
NoOp
Err error ->
let
_ =
Debug.log "error" error
in
NoOp
)
(Http.getString "https://upload.wikimedia.org/wikipedia/commons/thumb/f/fb/Creamer_MET_186969.jpg/2px-Creamer_MET_186969.jpg")
)
This logs:
ok: "����\0C\0\n\r\t\n\n\r\r��\0\v\0\0\"\0��\0\0\0\0\0\0\0\0\0\0\0\t\n\v��\0�\0\0\0}\0!1AQa\"q2���#B��R��$3br�\t\n%&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz���������������������������������������������������������������������������\0\0\0?\0�9�(�.t�/���=~���"
But how to convert it into the above data structure? Also, does it matter if the image is a jpg, png, gif?
What I'm looking for is the implementation of a function imageDataFromString : String -> Maybe ImageData
note: I'd prefer a non-port solution even if performance will be lower, the images I'm trying to process are not large.

Related

How do I retrieve a string from a PWSTR after a Win32 function succeeds?

I would like to get my username in an std::String using the windows-rs crate.
use bindings::Windows::Win32::{
System::WindowsProgramming::GetUserNameW,
Foundation::PWSTR,
};
fn main() {
let mut pcbbuffer: u32 = 255;
let mut helper: u16 = 0;
let lpbuffer = PWSTR(&mut helper);
println!("lpbuffer: {:?}\npcbbuffer: {:?}", lpbuffer, pcbbuffer);
unsafe {
let success = GetUserNameW(lpbuffer, &mut pcbbuffer);
println!("GetUserNameW succeeded: {:?}\nlpbuffer: {:?}\npcbbuffer: {:?}", success.as_bool(), lpbuffer, pcbbuffer);
}
}
produces the output:
lpbuffer: PWSTR(0xca20f5f76e)
pcbbuffer: 255
GetUserNameW succeeded: true
lpbuffer: PWSTR(0x7200650073)
pcbbuffer: 5
The username is "user" that's 4 + 1 terminating character = 5 which is good. I also see the GetUserNameW function succeeded and the pointer to the string changed.
What are the next steps?
The code as posted works by coincidence alone. It sports a spectacular buffer overflow, hardly what you'd want to see in Rust code. Specifically, you're taking the address of a single u16 value, and pass it into an API, telling it that the pointed-to memory were 255 elements in size.
That needs to be solved: You will have to allocate a buffer large enough to hold the API's output first.
Converting a UTF-16 encoded string to a Rust String with its native encoding can be done using several different ways, such as String::from_utf16_lossy().
The following code roughly sketches out the approach:
fn main() {
let mut cb_buffer = 257_u32;
// Create a buffer of the required size
let mut buffer = Vec::<u16>::with_capacity(cb_buffer as usize);
// Construct a `PWSTR` by taking the address to the first element in the buffer
let lp_buffer = PWSTR(buffer.as_mut_ptr());
let result = unsafe { GetUserNameW(lp_buffer, &mut cb_buffer) };
// If the API returned success, and more than 0 characters were written
if result.as_bool() && cb_buffer > 0 {
// Construct a slice over the valid data
let buffer = unsafe { slice::from_raw_parts(lp_buffer.0, cb_buffer as usize - 1) };
// And convert from UTF-16 to Rust's native encoding
let user_name = String::from_utf16_lossy(buffer);
println!("User name: {}", user_name);
}
}

Decoding an image from binary in rust

I am playing with the youtube api and I would like to download the thumbnails and process them. I've managed to download them in binary doing a simple http request and I can save them as a .jepec file. What I would like to do is not having to save the image as a file and parse the binary directly into an image all in memory to avoid leaving files behind.
Any idea on hat do I need to do to accompish this?
Here is my code:
#[tokio::main(flavor = "current_thread")]
async fn main() {
let res = reqwest::get("https://i.ytimg.com/vi/dQw4w9WgXcQ/hqdefault.jpg")
.await
.unwrap();
let bytes: Bytes = res.bytes().await.unwrap();
let _ = fs::write("img.jpeg", bin.clone()); // this saves the image correctly
let img = ????::from(bytes); // help here
}
You can use the jpeg_decoder crate:
use jpeg_decoder::Decoder;
let mut decoder = Decoder::new(&*bytes);
let pixels = decoder.decode().expect("jpeg decoding failed");
let info = decoder.info().unwrap(); // image metadata
If you call decode() from an async function, you should do so in a blocking task using tokio::spawn_blocking, as decode() is not itself async.

Calling a DLL from Go - what am I doing wrong?

I'm trying to convert a program from Python (2.7, 32-bit) to Go (1.12.5, 32bit), and failing miserably with an access violation. The program calls a function in a 32-bit dll (ehlapi32.dll).
The following clips of the Python code appear to work perfectly (I'm not affirming that they are correct!):
class ehlapi32:
hllDll = "C:\Program Files (x86)\IBM\Personal Communications\EHLAPI32.dll"
hllDll = ctypes.WinDLL(hllDll)
hllApiProto = ctypes.WINFUNCTYPE(ctypes.c_int,ctypes.c_void_p,ctypes.c_void_p,
ctypes.c_void_p,ctypes.c_void_p)
hllApiParams = (1, "p1", 0), (1, "p2", 0), (1, "p3",0), (1, "p4",0),
hllApi = hllApiProto (("HLLAPI", hllDll), hllApiParams)
pFunConnect = ctypes.c_int(1)
...
def connect(self):
shlSession = self.session + b'\0\0\0'
pText = ctypes.c_char_p (shlSession)
pLength = ctypes.c_int (len(shlSession))
pReturn = ctypes.c_int (13)
ehlapi32.hllApi (ctypes.byref (ehlapi32.pFunConnect), pText,
ctypes.byref (pLength), ctypes.byref (pReturn))
Now here's what I'm trying as the Go equivalent. This fails:
// ElFunc: EHLLAPI Functions
type ElFunc uint32
const (
eConnect ElFunc = 1 // Connect to a terminal
)
...
// Session: a 3270 session handle
type Session struct {
SessId string
SysId string
Entry string
Result []string
Headers int
Footers int
Rows int
Cols int
Scroll int
Proc *syscall.LazyProc
}
...
func (s Session) Connect() uint32 {
// Load EHLLAPI DLL
dll := syscall.NewLazyDLL(dllName)
s.Proc = dll.NewProc(dllProc)
// Connect to session
rc := s.ecall(eConnect, s.SessId, 1, 0)
if rc == 0 {
defer s.Disconnect()
}
...
// ecall: provides simplified EHLLAPI DLL calls
func (s Session) ecall(fun ElFunc, buffer string, count uint32, ps uint32) uint32 {
rc := ps
_, _, _ = s.Proc.Call(
uintptr(unsafe.Pointer(uintptr(uint32(fun)))),
uintptr(unsafe.Pointer(&buffer)),
uintptr(unsafe.Pointer(uintptr(count))),
uintptr(unsafe.Pointer(uintptr(rc))),
)
return rc
}
The failure looks like an access violation at s.Proc.Call in ecall().
I realise that syscall is deprecated; I have also tried with golang.org/x/sys/windows, without success. I have no constraints as to which I use.
I'll confess I'm way out of my depth here.

How to get slice of concrete type (not pointers) in go protobuff

For protofile:
syntax = "proto3";
package messagepb;
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
option (gogoproto.marshaler_all) = true;
option (gogoproto.sizer_all) = true;
option (gogoproto.unmarshaler_all) = true;
option (gogoproto.goproto_getters_all) = false;
service KV {
// Put puts the given key into the store.
// A put request increases the revision of the store,
// and generates one event in the event history.
rpc Put(PutRequest) returns (PutResponse) {}
}
message PutRequest {
bytes key = 1;
bytes value = 2;
}
message ResponseHeader {
repeated PutRequest l = 3;
}
I get the following proto struct:
type ResponseHeader struct {
L []*PutRequest `protobuf:"bytes,3,rep,name=l" json:"l,omitempty"`
}
But how do I get following protostruct:
type ResponseHeader struct {
L []PutRequest `protobuf:"bytes,3,rep,name=l" json:"l,omitempty"`
}
That is I want having data locality (and thus slices of contig data, not pointers to spread out stuff)
I needed to use: [(gogoproto.nullable) = false]
as in:
repeated PutRequest l = 3 [(gogoproto.nullable) = false];
And got:
L []PutRequest `protobuf:"bytes,3,rep,name=l" json:"l"`

Two sequential HTTP requests

Sorry for newbie's question (and for my english) :)
I tries to write the following function:
the function downloads a content from URL1 (it's received as argument)
the function parses this content and extract URL2
the function downloads a content from URL2
the content from URL2 is a result of this function
if an error was occured, this function should return Nothing
I know how to execute the HTTP requests. I have a function to parse the request from URL1. But I don't know how:
to execute new request with extracted URL2
to ignore second request if URL2 isn't extracted (or error in URL1 is occured)
I principle you want something like this:
import Maybe
import Http
type Url = String
getContentFromUrl : Maybe Url -> Maybe String
getContentFromUrl url = --your implementation
extractUrlFromContent : Maybe String -> Maybe Url
extractUrlFromContent content = --your implementation
content = getContentFromUrl (Just "http://example.com")
|> extractUrlFromContent
|> getContentFromUrl
Sending an Http means talking to the outside world, which involves Signals in Elm. So the final result from URL2 will come packed in a Signal. As long as you're ok with that, you can use maybe to return the content of in a Maybe in a Signal. For example:
import Maybe
import Http
-- helper functions
isSuccess : Http.Response a -> Bool
isSuccess response = case response of
Http.Success _ -> True
_ -> False
responseToMaybe : Http.Response a -> Maybe.Maybe a
responseToMaybe response = case response of
Http.Success a -> Just a
_ -> Nothing
parseContentAndExtractUrl : String -> String
parseContentAndExtractUrl = identity -- this still requires your implementation
-- URL1
startUrl : String
startUrl = "www.example.com" -- replace this with your URL1
result1 : Signal (Http.Response String)
result1 = Http.sendGet <| constant startUrl
-- URL2
secondUrl : Signal String
secondUrl = result1
|> keepIf isSuccess (Http.Success "")
|> lift (\(Http.Success s) -> s)
|> lift parseContentAndExtractUrl
result2 : Signal (Maybe String)
result2 = secondUrl
|> Http.sendGet
|> lift responseToMaybe
Note that there are plans to make all of this easier to work with: https://groups.google.com/d/topic/elm-discuss/BI0D2b-9Fig/discussion

Resources