I'm trying to send a frame from a video feed in open cv-python over websockets to react js frontend.
I can encode and send it fine, but when I try to decode it I get an error that reads that the string wasn't properly encoded.
backend code
#open url to view info
stream_url = urlopen(url)
#read information from url, convert array into bytarray
stream_feed = stream_url.read()
image = np.asarray(bytearray(stream_feed), dtype="uint8")
str_frame = str(b64encode(frame))
payload = json.dumps({
'image': str_frame
})
await remoteSocket.send(payload)
frontend code
const image = decodeURIComponent(atob(orgImg))
const img = new Image()
img.src = image
img.alt = 'frame'
the string to contain a b before before the single quotes, I thought that might be it so I trimmed it off and no luck. I've also tried it without decodeURICompoenet.
And I've tried it by adding data:image/jpeg;base64 to the start.
Related
I'm trying to write a program that dowloads OneNote pages to my pc, including files in the pages. I'm stuck on the downloading images from the pages. I make a GET request and get the binary data for the image just fine, when I save it and try to open it, I get a "it looks like we don't support this file format.
The code I'm using is
var u16 = btoa(unescape(encodeURIComponent(resp)));
var imgAsBlob = new Blob([u16], {type: 'application/octet-stream'});
var downloadLink = document.createElement("a");
downloadLink.download = "hello.png";
downloadLink.href = window.webkitURL.createObjectURL(imgAsBlob);
downloadLink.click();
resp is the responseText from the GET request with the binary data.
I've tried not using btoa and saving the resp directly on the blob. I've tried changing the blob type to image/png and I've tried escaping it using Uint16Array(resp.length) and equaling each byte to a byte from resp. I'm out of ideas and don't know what I'm doing wrong.
Im trying to POST a request with some header information and other parameters to my api and then have it return a PDF file.
I've got the API communication working fine however I've tried several methods of viewing the PDF and none really work 100%.
The method below was found on stackoverflow and returns response data in PDF format however when it's converted to a blob to view it becomes blank.
[API]
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
ReturnInformationITEM rtn = GetPDFData(); //Comes back as Base64
response.Content = new ByteArrayContent(System.Convert.FromBase64String(rtn.Data));
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return response;
[client]
var blob=new Blob([result], {type: 'application/pdf'});
var pom = document.getElementById("pdf" + $counter);
pom.setAttribute('href',window.URL.createObjectURL(blob));
pom.setAttribute('download',"Test.pdf");
pom.setAttribute('target','_blank');
'I did have a click event here but firefox ignores it so I have to pass the href back to the pom and manully click it'
If I alter the API to return base64 and have the client decode it before becoming a blob it will diaply the page but with an ugly blob URL and when saving in safari it doesnt recognise the 'download' attribute.
Does anyone know a method which can be used which will work cross browser and and allow for a filename to be prefilled? and if possible auto show the file upon returning the post data.
Thanks
Mark
JIRA Ticket created due to base64encode failure: https://jira.appcelerator.org/browse/TC-5876
My Current CFG:
Titanium SDK 5.1.2.GA
Testing on an iPhone iOS 9.1
I'm stuck in a problem in a project for a client that requires images took on device (using the camera) to be sent to a WebService and afterwards be seen on any device using the app (both Android and iOS devices).
Titanium provides a Ti.Blob object (event.media) after taking a picture (which is not JSON serializable) and I need somehow to send this to the server. The server responds always a JSON object, thus this Blob must be somehow JSON serializable.
I've tried many ways without success:
1 - Base64Encode the Blob
var base64blob = Ti.Utils.base64encode(event.media);
Doesn't work, it stucks the app and throws a ASL exceeded maximum size error. I imagine that the image is too large to be base64encoded.
2 - Read the Blob into a Buffer
var blobStream = Ti.Stream.createStream({ source: event.media, mode: Ti.Stream.MODE_READ });
var buffer = Ti.createBuffer({ length: event.media.length });
var bytes = blobStream.read(buffer);
It works but I have no idea how can I transform this buffer holding the image contents into something that the server can return in a JSON object and later be transformed into an Image Blob again.
The server can't manage Ti.Blob objects or Ti.Buffer objects because, first of all, they are Titanium objects and the server is C# based, and second due to Ti.Blob and Ti.Buffer aren't JSON serializable, thus the JSON return doesn't work.
What I need is basically described in the imaginary example below:
var imageBlob = event.media;
var JSONSerializableImg = imageBlob.toJSON();
sendImageToServer(JSONSerializableImg);
var imgFromServer = getImageFromServer();
var imageBlob = imgFromServer.toBlob();
var imgView = createImageView({
image: imageBlob
});
I hope someone can help me with any conversion method possible.
Thank's
OK,
This is what I think you have to do. Looking at the API, this is very doable.
1: You need to create an object Server side that will hold the BLOB.
public class BlobContainer
{
public string fileName{get;set;}
//... (Other properties)
public byte[] data {get;set;}
}
2: Convert the important information from the BLOB into a binary array and send to server.
var blobStream = Ti.Stream.createStream({ source: myBlob, mode: Ti.Stream.MODE_READ });
var newBuffer = Ti.createBuffer({ length: myBlob.length });
var bytes = blobStream.read(newBuffer);
3: Then send the byte data to the server through Ajax requests. Be mindful of how big your array is that you are sending. It might be advantageous to split the array up and combine it on the other side (Might not be necessary):
var dataObjects: [
{ id: 1, data: [BYTE_DATA_PART] },
{ id: 2, data: [BYTE_DATA_PART] }...
]
$.each(dataObjects, function(i,a) {
$.ajax({ url: "BLA", data: JSON.stringify(a), dataType: "json", type: "POST",
success: function() { //CONTINUE\\ },
error: function() {alert("ERROR BRO"})
});
});
4: Then server side get each request in your little blob container, store in a session object or cache object and once you have N out of N, piece it all together and store that sucker in the Database.
5: Retrieve the stuff in the reverse order. Just remember that it is stored as byte[] data. You may have to fuddle with it and store it as a string because of the way the TI buffer creates bytes and the way c# interprets bytes. Best thing is trial and error. Once you have all the pieces back on the client.
var newBuffer = Ti.Stream.read(data, 0, data.length);
var newBlob = newBuffer.toBlob();
To send and receive binary data to and from a server it's best to use Ti.Network.HTTPClient which can send and receive binary data.
There's a guide on uploading and downloading files here:
http://docs.appcelerator.com/platform/latest/#!/guide/File_Uploads_and_Downloads
JSON isn't designed to carry binary data, although base64encoded binary data should work. This is what Ti.Utils.base64encode() indeed is for. If you believe the "ASL exceeded maximum size error" you get shouldn't happen, please create a ticket on Appcelerator JIRA
I solved this issue by creating a separate method on server-side specially to upload photos. I followed the link below for server side:
PHP code
In Titanium I had to set XHR's header like this:
this.xhr.setRequestHeader("ContentType", "image/png");
this.xhr.setRequestHeader('enctype', 'multipart/form-data');
That's it!
Thank's for all the answers.
I've used the following method before (not in Titanium, but another web-based mobile app platform).
function convertToDataURLviaCanvas(url, callback, outputFormat){
var img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function(){
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
var dataURL;
canvas.height = this.height;
canvas.width = this.width;
ctx.drawImage(this, 0, 0);
dataURL = canvas.toDataURL(outputFormat);
callback(dataURL);
canvas = null;
};
img.src = url;
}
convertToDataURLviaCanvas('http://example.com/image.png', function(base64Img){
// Base64DataURL
});
I used this to send the base64 encoded image string as JSON to my backend server. Then re-encoded the image on the server. It worked for me, but the base64 encoded string is huge.
I have a Custom helpdesk application that I am trying to run in javascript.
the program has a peice of code that runs on the customer's computer and sends an image to a autobahn websocket server which acts as a proxy to a image viewer which can send clicks and keystrokes back over the websockets. this is all currently working in python correctly however, when i try it in javascript, I cannot get my image loaded no matter what I do and I can't figure out what i am doing wrong.
This is the part of my javascript that is broken:
function onMessage(evt) {
if(evt.data.indexOf('[00000]')>=0){
var ar = evt.data.split('[00000]');
if (ar[0] == "[IMAGE]"){
var imgdata = evt.data.split('[22222]');
context.width = imgdata[0];
context.height = imgdata[1];
console.log(context.width + " " + context.height)
try{
var img = new Image();
img.src = imgdata[2];
context.drawImage(img,0,0);
console.log("IMAGE");
}catch(e){
console.log(e)
}
}else if(ar[0] == "[RETCONN]"){
console.log("Accepted!");
}
}
}
Below is some code from the server to try and clarify what is going on with the javascript.
def onMessage(self, payload, isBinary):
if isBinary:
print("Binary message received: {0} bytes".format(len(payload)))
else:
msg = payload.decode('utf8')
com, data, arg = msg.split('[11111]')
if com == ("[IMAGE]"):
for name, conn in clients.items():
if name == data:
conn.sendMessage(('[IMAGE]'+'[00000]'+arg).encode('utf8'))
break
and this is how the image is put together from the customer side:
data = image.tostring()
data = base64.b64encode(data)
self.sendMessage(('[IMAGE]' + '[11111]' + rid + '[11111]' + str(w) + '[22222]' + str(h) + '[22222]' + data).encode('utf8'))
Anyone have any ideas how what i am doing wrong in my javascript?
EDIT: i am aware that img.src is in the wrong location. moving to the right spot does not fix the issue
If you want to use base64 encoded image as a source for the image object, it needs to be in format:
data:image/png;base64,<base64 encoded image>
You need to prepend data:image/png;base64, to your base64 string
img.src = "data:image/png;base64,"+imgdata[2];
You are also parsing your messages wrong.
imgdata[0] is supposed to be your width, but it also includes [IMAGE][00000].
You probably want ar[1].split('[22222]'); instead of evt.data.split('[22222]');.
To avoid complications with encoding, I would recommend you to use JSON to encode your WebSocket messages.
Edit:
You are getting a broken image because image.tostring() returns raw image data, but with data:image/png;base64, it's expected to be in PNG format.
To get base64 encoded PNG data use this:
import io
buffer = io.BytesIO()
image.save(buffer, "png")
data = base64.b64encode(buffer.getvalue())
I'm attempting to consume server-side code that is owned by another team and that I can't easily change. It is processing an image and returning it via Response.BinaryWrite:
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
var imageToReturn = ms.ToArray();
Response.ContentType = "image/jpg";
Response.BinaryWrite(imageToReturn);
However, when I attempt to do standard client-side processing of the result, like using Javascript's btoa() to convert it from a byte array to an ArrayBuffer, I get messages like "'btoa' failed: The string to be encoded contains characters outside of the Latin1 range".
I really just want to be able to display and work with this image - so any approach that would get it to appear in a canvas, or convert it to a data URL, etc., would help me out. Am I missing something?
If you just want to display the image, why don't you just src attribute of img tag to the url of the ASP.Net page, which is writing the JPG in the in the response.
If you want to display the image in canvas, you can do it in following way
myimage = new Image();
myimage.onload = function () {
var canvas = document.getElementById('canv');
var ctx = canvas.getContext('2d');
ctx.drawImage(myimage, x, y);
}
myimage.src = '<url to the asp.net page>';