Send and verify images via WebRTC - javascript

I need to send image data over WebRTC to another peer. My first thought was to use the base64 representation from the image. I get this data URI with the help of a Canvas. Works like a charm. But now I want to check if the data was not altered before sending.
The problem is, that the Canvas re-encodes the image and what's worth Firefox and Chrome encode the imageData differently. So I can't get matching SHA hashes.
Any ideas on how to solve this issue. Maybe a new approach to the whole problem? (WebRTC is mandatory though). Thanks!

Here is what I did... Basically I'm working with ArrayBuffers and Blobs now. I have a Blob of the image in question. Then I use FileReader.readAsArrayBuffer(blob) and and UInt8Array as a view on that data. Then I concatinate the bytes and compute a MD5 hash with https://github.com/satazor/SparkMD5. Concatination takes quite a while, so I only take every tenth byte in consideration. Which is supposedly quite a big security issue. So any tips on improving this process are very appreciated. As long as I or someone else comes up with a better idea, I will keep this the answer.

Related

How to compare two base64 strings in Javascript and ignore some differences

I'm getting one base64 string from API response and other one I'm converted image (which is in test data file) to base64 using cypress readfile method.
When I'm using below command the assertion is failing because there is tracking number difference which will be always new with every call.
And I'm getting 2 different base64.
//This base64 is from API response
var base64FromAPI =
res.body.completedShipments[0].completedPackages[0].documents[0].image;
//Image is picked from Test Data file and converts to base64
cy.readFile(`cypress/e2e/Testdata/Canada Post 02StoreId.pdf`, "base64").should(
"eq",
base64FromAPI
);
Because there is tracking number on the label(image) which will be generated from API response is always different.
Is there any other way to compare base64 strings and to ignore some % of difference while comparing in cypress or javascript.
Or is there any other way to do this.
Thanks in advance.
Essentially you can't do this at the base64 level. The differences in a raw bitstream like base64 are totally meaningless. The differences can only become apparent through rendering that image. Actually, what you need to do is pretty complex! I'm assuming it's not possible or a good idea in your use case to change away from having the server add the text to the image, to for example, using DOM to overlay it instead.
If that's the case, the only thing you could do is utilise visual regression testing. With this, you can set a threshold on which a % similarity is defined.
Since the base64 comes from the API. This would probably mean also having test code that injects an img tag with the base64 as the source, so you can allow the visual snapshot to take place.
This works at the level of image analysis rather than on the actual bitstream. Internally it will render and compare the images.
Another way I can think of, though this is quite complex and I wouldn't pursue it unless the above did not work is to:
Use image manipulation libraries to load the base64 into an actual rendered image in memory.
Try to cut away/crop the superimposed text using image manipulation libraries in order to reliably remove areas of difference.
Base 64 that.
Compare that to a known stable base64 of the "rest" of the image.

Is there a way to append to an object URL or otherwise create a stream as a URL?

There was an interesting discussion over here on StackOverflow, and in some ways this question is a followup. I've also asked a similar question in the past, but I feel this is more generally a question about object URLs.
There have been a number of times where I would like to implement a streaming version of a ".src" for image or video elements in JS, perhaps from a stream of bytes. Unfortunately, I only see two main options that are more controllable by JS:
Create a Blob and then use URL.createObjectURL(). Unfortunately, this seems to be static - but perhaps there is a way to mutate the contents?
Create a MediaSource. However, this only works for video and is much pickier than just using a video element, which is really the level of support I need.
Any thoughts on how I can create some type of streaming object URL? And/or if not, does anybody know why JS hasn't implemented this type of streaming long, long ago?
There have been a number of times where I would like to implement a streaming version of a ".src" for image or video elements in JS, perhaps from a stream of bytes.
Use a Service Worker to respond with a Response with a ReadableStream as the body.
but I feel this is more generally a question about object URLs.
Object URLs really only represent immutable Blobs. The MediaStream object URL is a special case, not really applicable here, and a deprecated API as srcObject exists for media elements these days.
Create a Blob and then use URL.createObjectURL(). Unfortunately, this seems to be static - but perhaps there is a way to mutate the contents?
No, Blobs are immutable.
Create a MediaSource. However, this only works for video...
... or audio.

Reading JPEG file to retrieve orientation information

I've been researching ways to retrieve orientation information from a JPEG file in pure JavaScript.
An excellent way to get this information is outlined in this SO answer. Essentially one reads the entire file using readAsArrayBuffer and then processes it for the required information.
However, is it really necessary to read the whole file to retrieve EXIF information? Is there an optimization whereby one can read a subset of bytes when doing this?
For instance, this SO answer seems to suggest the first 20 bytes are good enough for the job. However, the former answer's writer himself asserts that he removed the slice statement because sometimes the tag came in after the limit (he had originally set it to 64KB, i.e. reader.readAsArrayBuffer(file.slice(0, 64 * 1024));)
So what's a rule of thumb one can use when programming this sort of a thing? Or does one not exist at all? I want to write code where performance doesn't get heavily affected by the size (in bytes) of file uploaded by a user. That is my goal.
Note: I've tried Googling this information as well, however haven't found anything meaningful.
Till a more seasoned expert chimes in, I've settled for reader.readAsArrayBuffer(file.slice(0, 128 * 1024));.

What is the most efficient way in JavaScript to parse huge amounts of data from a file

What is the most efficient way in JavaScript to parse huge amounts of data from a file?
Currently I use JSON parse to serialize an uncompressed 250MB file, which is really slow. Is there a simple and fast way to read a lot of data in JavaScript from a file without looping through every character? The data stored in the file are only a few floating point arrays?
UPDATE:
The file contains a 3d mesh, 6 buffers (vert, uv etc). Also the buffers need to be presented as typed arrays. streaming is not a option because the file has to be fully loaded before the graphics engine can continue. Maybe a better question is how to transfer huge typed arrays from a file to javascript in the most efficient way.
I would recommend a SAX based parser for these kind of JavaScript or a stream parser.
DOM parsing would load the whole thing in memory and this is not the way to go by for large files like you mentioned.
For Javascript based SAX Parsing (in XML) you might refer to
https://code.google.com/p/jssaxparser/
and
for JSON you might write your own, the following link demonstrates how to write a basic SAX based parser in Javascript
http://ajaxian.com/archives/javascript-sax-based-parser
Have you tried encoding it to a binary and transferring it as a blob?
https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Sending_and_Receiving_Binary_Data
http://www.htmlgoodies.com/html5/tutorials/working-with-binary-files-using-the-javascript-filereader-.html#fbid=LLhCrL0KEb6
There isn't a really good way of doing that, because the whole file is going to be loaded into memory and we all know that all of them have big memory leaks. Can you not instead add some paging for viewing the contents of that file?
Check if there are any plugins that allow you to read the file as a stream, that will improve this greatly.
UPDATE
http://www.html5rocks.com/en/tutorials/file/dndfiles/
You might want to read about the new HTML5 API's to read local files. You will have the issue with downloading 250mb of data still tho.
I can think of 1 solution and 1 hack
SOLUTION:
Extending the split the data in chunks: it boils down to http protocol. REST parts on the notion that http has enough "language" for most client-server scenarios.
You can setup on the client a request header Content-len to establish how much data you need per request
Then on the backend have some options http://httpstatus.es
Reply a 413 if the server is simply unable to get that much data from the db
417 if the server is able to reply but not under the requested header (Content-len)
206 with the provided chunk, letting know the client "there is more from where that came from"
HACK:
Use Websocket and get the binary file. Then use the html5 FileAPI to load it into memory.
This is likely to fail though because its not the download causing the problem, but the parsing of an almost-endless JS object
You're out of luck on the browser. Not only do you have to download the file, but you'll have to parse the json regardless. Parse it on the server, break it into smaller chunks, store that data into the db, and query for what you need.

BMP decoding in JavaScript and drawing to Explorer Canvas

I need to download a BMP with JavaScript and render it to the screen, in Internet Explorer. First off, yes, I know this is insane, I'm not going to get into why, let's just accept for a moment that img src is not working because of security constraints, but an ajax request with the proper authentication in the post will pull back the image. This example bypasses all the security for the sake of simplicity and just proves we can render something.
The best idea I could come up with was to fetch the stream via ajax, decode the bitmap, and then render it with canvas. Internet Explorer obviously doesn't support canvas, but luckily Google provided a wrapper to SVG called excanvas that I can use for that.
My code (drawing code appears to work, bmp decoding not so much)
http://gist.github.com/614328
Future support for other images besides BMP is plausable, and because of how the canvas works it's easiest to draw pixels in RGBA. Texture2D is essentially the wrapper class for an RGBA byte array, plus the drawing code. ByteStream makes it a bit easier on the eyes dealing with the byte array, and BitmapDecoder contains the method to translate the BGR format to RGBA texture2d for drawing.
Is it possible the bytes are getting mis-translated along the way or is there something the matter with my decoding logic?
FYI, I got the file spec from wikipedia:
http://en.wikipedia.org/wiki/BMP_file_format#Bitmap_Information_.28DIB_header.29
Any idea what's going on in the decoding logic or drawing logic that's causing my BMP to draw incorrectly?
XMLHttpRequest (aka AJAX) was primarily designed for text content, so it's possible that binary data (especially null characters) aren't translated correctly. The first check would be to compare the size of retrieved data with the actual file size.
At least on Firefox, there seems to be a way to specifically retrieve binary data, as described here: Handling binary data.
Here's a much easier (and vastly more performant) approach: base64 encode the BMP data (you can do this either on the server or the client) and then embed it in the page using a data URI:
<script type="text/javascript">
function fetchBmp() {
$.get('http://localhost:3168/experimental/imgrender/beta.bmp', function (data) {
var base64Data = $.base64.encode(data); // *
$('#my-image').attr('src', 'data:image/bmp;base64,' + base64Data);
});
}
// * Lots of plugins for this, e.g. http://github.com/carlo/jquery-base64
</script>
<img id="my-image" />
All modern browsers support data URIs (including IE8 and up--for IE7 workarounds exist) as well as the BMP format.
As casablanca points out, there may be issues with loading binary data via Ajax, so you may have to google around for workarounds.
The fix was a combination of two things
a bit of VBScript to read the raw bytes of responseBody
decoding the byte data properly, each pixel is not padded as the wikipedia article suggests, it's actually each scanline that is padded to dword size.
Working code:
http://gist.github.com/616240

Categories

Resources