Titanium ByteArray to image Blob - character-encoding

I have a list of images encoded as ByteArrays from an API to be displayed in a TableView
Here is one of the ByteArrays
i'm not managing to display an image with it,
nor saving a file or making a buffer or a stream buffer, those are some examples
var blobStream = Ti.Stream.createStream({ source: array, mode: Ti.Stream.MODE_READ });
or
var buff = Ti.createBuffer({value:array, length:array.length, type:Ti.Codec.CHARSET_UTF8});
and giving the array either to
Titanium.Utils.base64decode( array );
Titanium.Utils.base64encode( array );
crashes badly with "wrong type passed to function"
How can I make a blob out of a ByteArray and set it to an Imageview?

You can use this snippet to convert byte array in base64 string.
Decode the string with var imageBlob = Ti.Utils.base64decode(string);
and than set it in var image = Ti.UI.createImageView({ image:imageBlob });

Related

`web_sys::Url::create_object_url_with_blob(&blob)` not formatting binary data correctly

I have the following code:
let bytes: Vec<u8> = load_file_as_bytes("mydoc.docx"); // This gets a byte vec representation of the file mydoc.docx
let uint8arr = unsafe { js_sys::Uint8Array::view(&bytes) };
let js_value = wasm_bindgen::JsValue::from(uint8arr);
let blob = Blob::new_with_u8_array_sequence_and_options(
&js_value,
web_sys::BlobPropertyBag::new().type_("application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
).unwrap();
let download_url = web_sys::Url::create_object_url_with_blob(&blob).unwrap();
When I follow the link, the file that gets downloaded is a bunch of bytes written inside a Word document.
These bytes are meant to represent the word document itself and not written to it as plaintext.
This is being compiled to Wasm and run in the browser.
I get the correct representation if I represent the bytes as Base64-encoded text and make an <a> element with an href to the string.
let base64_string = base64::encode(&file.bytes);
let download_url = format!("data:{};base64,{}",file.mime_type,base64_string);
// ... set href = &download_url inside dom
But this is horribly slow for files more than a couple KB and gets slower as more files get added.
What is the correct Rust -> JS conversion to use the create_object_url_with_blob() so that it works as expected?
It looks like the correct way to do this is to push your Uint8Array to a js_sys::Array first,
and because js_sys::Array implements JsCast you can use it directly inside the blob.
I assume this comes from some sort of internal representation of JavaScript types inside js_sys, and the behavior of the code in the question likely defaults to treating an array of bytes as text.
Working code:
let uint8arr = js_sys::Uint8Array::new(&unsafe { js_sys::Uint8Array::view(&bytes) }.into());
let array = js_sys::Array::new();
array.push(&uint8arr.buffer());
let blob = Blob::new_with_u8_array_sequence_and_options(
&array,
web_sys::BlobPropertyBag::new().type_("application/vnd.openxmlformats-officedocument.wordprocessingml.document"),
).unwrap();
let download_url = web_sys::Url::create_object_url_with_blob(&blob).unwrap();
This results in the bytes actually being used as the Word Document as opposed to written to an empty word doc.

encoding an image to base64 string

am trying to upload image from photo gallery in dart using the library image_picker.. which is working fine ..
and then am trying to convert the selected image to bas64 string like this:
imageSelectorGallery() async {
_image = await ImagePicker.pickImage(
source: ImageSource.gallery,
// maxHeight: 50.0,
// maxWidth: 50.0,
);
List<int> imageBytes = _image.readAsBytesSync();
print(imageBytes);
String base64Image = base64Encode(imageBytes);
print('string is');
print(base64Image);
print("You selected gallery image : " + _image.path);
setState(() {});
}
but this keeps returning a not correct string .. for example:
_9j_4QG1RXhpZgAATU0AKgAAAAgABwEQAAIAAAAaAAAAYgEAAAQAAAABAAADwAEBAAQAAAABAAAFAAEyAAIAAAAUAAAAfAESAAMAAAABAAEAAIdpAAQAAAABAAAAlwEPAAIAAAAHAAAAkAAAAABBbmRyb2lkIFNESyBidWlsdCBmb3IgeDg2ADIwMTg6MTA6MTcgMTE6Mjc6NTMAR29vZ2xlAAAQgp0ABQAAAAEAAAFdgpoABQAAAAEAAAFlkpIAAgAAAAQ0NzQAkpEAAgAAAAQ0NzQAkpAAAgAAAAQ0NzQAkgoABQAAAAEAAAFtkgkAAwAAAAEAAAAAiCcAAwAAAAEAZAAAkAQAAgAAABQAAAF1kAMAAgAAABQAAAGJoAMABAAAAAEAAAUApAMAAwAAAAEAAAAAoAIABAAAAAEAAAPAkgIABQAAAAEAAAGdkgEACgAAAAEAAAGlkAAABwAAAAQwMjIwAAAAAAAAARgAAABkAJiWgDuaygAAABOIAAAD6DIwMTg6MTA6MTcgMTE6Mjc6NTMAMjAxODoxMDoxNyAxMToyNzo1MwAAAAEpAAAAZAAAGfMAAAPo_-AAEEpGSUYAAQEAAAEAAQAA_9sAQwACAQEBAQECAQEBAgICAgIEAwICAgIFBAQDBAYFBgYGBQYGBgcJCAYHCQcGBggLCAkKCgoKCgYICwwLCgwJCgoK_9sAQwECAgICAgIFAwMFCgcGBwoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoK_8AAEQgFAAPAAwEiAAIRAQMRAf_EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC__EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYq
and this cannot be converted to image ..
where is the problem and how to solve it?
You've only copied the first 1024 characters of the encoded string into the question. Maybe the print command truncated it. Also, the online tool seems to prefer (require?) the URL safe version, so as Günter says, use base64UrlEncode.
To confirm that the string you are using is roughly the right length, add 33%. That is, a 2k image would convert to a string roughly 2667 characters long.

how to store byte array in neo4j database

I am unable to create a node in neo4j database to store byte array through java code. Please can anybody help?
String q = "create(userImage:UserImage{imageBytess:'"+imageBytes+"'})";
This stores as String. I am not getting how to do for bytes
Have you try this :
// Given
byte[] byteArray = "hello, world".getBytes();
// When
StatementResult result = session.run("CREATE (a {value:{value}}) RETURN a.value", parameters( "value", byteArray ) );

Convert string to base64 byte array in swift and java give different value

Incase of android everything is working perfectly. I want to implement same feature in iOS too but getting different values. Please check the description with images below.
In Java/Android Case:
I tried to convert the string to base64 byte array in java like
byte[] data1 = Base64.decode(balance, Base64.DEFAULT);
Output:
In Swift3/iOS Case:
I tried to convert the string to base64 byte array in swift like
let data:Data = Data(base64Encoded: balance, options: NSData.Base64DecodingOptions(rawValue: 0))!
let data1:Array = (data.bytes)
Output:
Finally solved:
This is due to signed and unsigned integer, meaning unsigned vs signed (so 0 to 255 and -127 to 128). Here, we need to convert the UInt8 array to Int8 array and therefore the problem will be solved.
let intArray = data1.map { Int8(bitPattern: $0) }
In no case should you try to compare data on 2 systems the way you just did. That goes for all types but specially for raw data.
Raw data are NOT presentable without additional context which means any system that does present them may choose how to present them (raw data may represent some text in UTF8 or some ASCII, maybe jpeg image or png or raw RGB pixel data, it might be an audio sample or whatever). In your case one system is showing them as a list of signed 8bit integers while the other uses 8bit unsigned integers for the same thing. Another system might for instance show you a hex string which would look completely different.
As #Larme already mentioned these look the same as it is safe to assume that one system uses signed and the other unsigned values. So to convert from signed (Android) to unsigned (iOS) you need to convert negative values as unsigned = 256+signet so for instance -55 => 256 + (-55) = 201.
If you really need to compare data in your case it is the best to save them into some file as raw data. Then transfer that file to another system and compare native raw data to those in file to check there is really a difference.
EDIT (from comment):
Printing raw data as a string is a problem but there are a few ways. The thing is that many bytes are not printable as strings, may be whitespaces or some reserved codes but mostly the problem is that value of 0 means the end of string in most cases which may exist in the middle of your byte sequence.
So you already have 2 ways of printing byte by byte which is showing Int8 or Uint8 corresponding values. As described in comment converting directly to string may not work as easy as
let string = String(data: data, encoding: .utf8) // Will return nil for strange strings
One way of converting data to string may be to convert each byte into a corresponding character. Check this code:
let characterSequence = data.map { UnicodeScalar($0) } // Create an array of characters from bytes
let stringArray = characterSequence.map { String($0) } // Create an array of strings from array of characters
let myString = stringArray.reduce("", { $0 + $1 }) // Convert an array of strings to a single string
let myString2 = data.reduce("", { $0 + String(UnicodeScalar($1)) }) // Same thing in a single line
Then to test it I used:
let data = Data(bytes: Array(0...255)) // Generates with byte values of 0, 1, 2... up to 255
let myString2 = data.reduce("", { $0 + String(UnicodeScalar($1)) })
print(myString2)
The printing result is:
!"#$%&'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþ
Then another popular way is using a hex string. It can be displayed as:
let hexString = data.reduce("", { $0 + String(format: "%02hhx",$1) })
print(hexString)
And with the same data as before the result is:
000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff
I hope this is enough but in general you could do pretty much anything with array of bytes and show them. For instance you could create an image treating bytes as RGB 8-bit per component if it would make sense. It might sound silly but if you are looking for some patterns it might be quite a witty solution.

getPixel32 is inaccurate

function encodeBmp(s:String){
s = Base64.Encode(s);
var width:Number = Math.ceil(Math.sqrt(s.length/4));
var bmp:BitmapData = new BitmapData(width,width,true,0x00000000);
var pos:Number=0; //track position in string
for(var x:Number=0;x<width;x++){
for(var y:Number=0;y<width;y++){
var col="0x";
for(var i:Number=0;i<4;i++){
col+=getHex(s.charAt(pos));
pos++;
}
bmp.setPixel32(x,y,col);
trace(col + " > 0x" + bmp.getPixel32(x,y).toString(16));
}
}
return bmp.clone();
}
Basically, the trace statement returns this:
0x56326868 > 0x56326868
0x64434270 > 0x64424270
0x63794230 > 0x63794331
...
Why is the result of getPixel32 different from that of the set value, and how can I resolve this?
EDIT: getPixel is accurate, but doesn't have the extra bit that get/setPixel32 does... I would prefer to have more data per pixel.
You're Base64 encoding a String to store it in a BitmapData. I hope you didn't know that, or are ashamed.
Anyway, here is what I see happening:
First, if you type col as a String, you'll get a compile error on setPixel32, because it's expecting a uint.
Now, we can ignore all the looping and hex strings to get some simple code to reproduce the problem.
var bitmapData:BitmapData = new BitmapData(1, 1);
bitmapData.setPixel32(0, 0, 1682129520);
trace(bitmapData.getPixel32(0, 0));
By using an int literal, we can see that it's not a problem with type coercion, but something inside of BitmapData. This makes sense, since BitmapData is intended to store graphics data, so storing the graphics in a way that is graphically similar but not exact is fine.
You're probably seeing the side-effects of pre-multiplied alpha in Flash. This would also explain why you don't see any problems with getPixel and setPixel.
You can read more about it here: http://www.quasimondo.com/archives/000665.php
So how do you fix the problem? Use the correct data type. A ByteArray is designed to store binary data.

Resources