Convert hexadecimal string to Blob and display PNG image with AngularJS - javascript

I got a web page (I/m using angularjs 1.4.8) and I'm trying to show an image which comes from my GET url request.
Here is the page code (I got a grid and I/m displaying previews if they are applicable):
<div ng-show="message.message == null && message.is_image != null">
<a href="#" ng-click="downloadFile(message.id_message)">
<img data-ng-src="data:image/{{message.image_resolution}};base64,{{message.image_preview}}"/>
</a>
</div>
So, I got cassandra DB with this blob field and my Json looks like:
created_date:"2017-03-31 22:05:42.284Z"
id_message:"e6e2a5cb-ec25-472f-a59b-3f16a3a8afa9"
id_user_link:"47ed65bf-5520-4901-88c8-01980ffbcd4d"
id_user_sent:"3495c2de-c93c-4323-8e48-1fcecbfde625"
image_length:174443
image_name:"5.png"
image_preview:"0x89504e470d0a1a0a0000000d49484452000007800000039a080600000079a04f28000038714944415478daecd9496e55570045d13bfff124d442c654016320c4d4219832046308a132087199c26ba4f1fed65ad29ec0e99e71ec97635392244992244992244992b4f90d23489224499
...
... some other 90 lines of symbols
...
00000108401d8006c0096244906600000000008c2006c0036004b922403300000000004610036001b802549920118000000008230001b800dc09224c9000c000000004118800dc00660499264000600000080200cc0066003b024493200030000004010066003b001589224198001000000200803b001d8002c49920cc000000000108401d8006c0096244906600000000008c2006c0036004b92a4ff95fe0ffc7d46dd1b63a2b10000000049454e44ae426082"
image_resolution:"png"
is_image:1
message:null
But I have no images in my web page (only icon of broken link to image):
I researched
Angularjs showing image blob
Display blob image in html with angularjs
AngularJS - Show byte array content as image
but this won't help.I tried some varieties of this code:
page:
<img data-ng-src="data:image/{{message.image_resolution}};base64,{{b64encoded(message.image_preview)}}"/>
js:
$scope.b64encoded = function(image_preview){
//btoa(String.fromCharCode.apply(null, response.data[0].ClassImage.data));
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|file|ftp|blob):|data:image_preview\//);
return btoa(String.fromCharCode.apply(null, image_preview));
}
RESOLVED
Finally, that was not the issue about AngularJS or blob - that was a Java issue:
byte[] previewSizeByte = baos.toByteArray(); and I stored this one as blob, so, now I got a text field and my Java code looks like (I decided to use BufferedImage for preview):
String base64String = imgToBase64String(preview, fileFormat);
and
private String imgToBase64String(BufferedImage preview, String fileFormat) {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
ImageIO.write(preview, fileFormat, Base64.getEncoder().wrap(os));
return os.toString(StandardCharsets.ISO_8859_1.name());
} catch (final IOException ioe) {
throw new UncheckedIOException(ioe);
}
}
I really appreciate stackoverflow members for their comments and answers, they were extremely helpful

It appears that the CassandraDB is sending the image data as a hexadecimal string. It would be more efficient to send it as a base64 string and it would be easier to use.
Here is a function to convert a hexadecimal string to an image/png Blob and display the image:
angular.module("myApp",[]).controller("myVm", function($scope) {
var vm = $scope;
var testHex =
["0x89504e470d0a1a0a0000000d494844520000003c00000028040300000050",
"9584cc0000001b504c5445000000ffffff1f1f1f7f7f7f3f3f3f9f9f9f5f",
"5f5fdfdfdfbfbfbf2cb790f6000000097048597300000ec400000ec40195",
"2b0e1b000000b749444154388ded90cf0a83300cc63faaf5394a5defc56c",
"ee2a0c760e2a3b0b6e3ec7c0175f5aff1e77da657ea40dcd2ff90a010efd",
"9772a2f3f6ea4b830e121915b1a04e859999066a4b1801562dec544c3d36",
"cc723506ac9791809538f564af54055c33f8861d76d0cacfd30efc9450c3",
"b0e20189e28847aac5397458b7e2175d4cde4ed37252cff7d83ce367c849",
"b56014ecf638fa28bf62cd49b7c3e9a384f86764269cbde5bf665b969230",
"31adb25feffdd02ff50109f91bbd7897f34a0000000049454e44ae426082"]
.join('');
vm.hex = testHex;
vm.imgUrl = URL.createObjectURL(toPngBlob(testHex));
function toPngBlob(str){
var hexStr = str.slice(2);
var buf = new ArrayBuffer(hexStr.length/2);
var byteBuf = new Uint8Array(buf);
for (let i=0; i<hexStr.length; i+=2) {
byteBuf[i/2] = parseInt(hexStr.slice(i,i+2),16);
}
var blob = new Blob([byteBuf], {type: "image/png"});
return blob;
};
});
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="myApp" ng-controller="myVm">
<h1>Convert hex string to PNG Blob</h1>
{{hex}}<br>
{{imgUrl}}<br>
<img ng-src="{{imgUrl}}">
</body>

Related

Blob as source docx/pptx/xlsm/etc as iframe

I am having a problem identical to this enter link description here (unanswered) question. Is it possible to create an iframe of docx/pptx/xlsm/etc with a blob? For reference, here's some code
AngularJS snippet to have docx iframes
get_file_data().then(function(response){ //assume get_file_data works
memtype = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
var blob = new Blob([response.data], {type: memtype});
var blob_url = $window.URL.createObjectUrl(blob);
var office_url = "http://view.officeapps.live.com/op/embed.aspx?src=";
var url = office_url + blob_url;
$scope.content = $sce.trustAsResourceUrl(url);
And then in my html file:
<iframe ng-src = "{{content}}"> </frame>
It doesn't work likely because blob_url has blob:// as a prefix, how can I fix this to make it work? Or is this something that can't be done? For some reason, this approach works for pdf files

ASP.NET MVC how can I convert my byte[] of a signature, using the signaturepad library, into a jpeg that keeps the signature's image?

I have been capturing user signatures using signature pad (https://github.com/szimek/signature_pad/). I need to be able to convert these signatures into a jpeg that retains the image of the signature. I can't get it to work with out the images just being a big black box. I think it has something to do with how the images are rendered.
I used this tutorial to create the signatures (https://www.thewebflash.com/using-signature-pad-with-asp-net-mvc/). I need the signature in a picture format so I can put it on my form. I'm guessing something is going wrong because javascript is needed to render the byte[] correctly, so I'm not converting the raw byte[] to a jpeg correctly in the controller (last part).
Here is my code:
Class:
public class Signature
{
public int ID { get; set; }
[UIHint("SignaturePad")]
public byte[] MySignature { get; set; }
}
public class SignatureDbContext : DbContext
{
public DbSet<Signature> SignatureDatabase { get; set; }
}
UIHint attribute in order to specify that the following SignaturePad.cshtml templates should be used to display the model property in a view.
Views\Shared\DisplayTemplates\SignaturePad.cshtml :
#model byte[]
<div class="signature-pad">
<canvas class="panel panel-default"></canvas>
<button type="button" class="btn btn-default btn-sm btn-clear- canvas">Clear</button>
#Html.HiddenFor(model => model, new { #disabled = "disabled" })
and Views\Shared\EditorTemplates\SignaturePad.cshtml :
#model byte[]
<div class="signature-pad">
<canvas class="panel panel-default"></canvas>
<button type="button" class="btn btn-default btn-sm btn-clear-canvas">Clear</button>
#Html.HiddenFor(model => model, ViewData["htmlAttributes"])
In my css Content\Site.css I have this :
.signature-pad > canvas {
display: block;
width: 300px;
height: 150px;
margin-bottom: 5px;
}
In the scripts folder I have a javascript script to help render the image on the view.
SignaturePadInit.js :
var signaturePadWrappers = document.querySelectorAll('.signature-pad');
[].forEach.call(signaturePadWrappers, function (wrapper) {
var canvas = wrapper.querySelector('canvas');
var clearButton = wrapper.querySelector('.btn-clear-canvas');
var hiddenInput = wrapper.querySelector('input[type="hidden"]');
var signaturePad = new SignaturePad(canvas);
// Read base64 string from hidden input
var base64str = hiddenInput.value;
if (base64str) {
// Draws signature image from data URL
signaturePad.fromDataURL('data:image/png;base64,' + base64str);
}
if (hiddenInput.disabled) {
signaturePad.off();
clearButton.classList.add('hidden');
} else {
signaturePad.onEnd = function () {
// Returns signature image as data URL and set it to hidden input
base64str = signaturePad.toDataURL().split(',')[1];
hiddenInput.value = base64str;
};
clearButton.addEventListener('click', function () {
// Clear the canvas and hidden input
signaturePad.clear();
hiddenInput.value = '';
});
}
});
When I want to see the signature in a view I include this at the buttom or else the signature appears as an empty white box:
#section Scripts {
<script src="~/Scripts/signature_pad.min.js"></script>
<script src="~/Scripts/SignaturePadInit.js"></script>
}
The signature_pad.min.js comes default with the signaturepad library through nuget. I didn't touch it and I don't think it needs to be discussed. I haven't included it because it is extremely long.
Here is my code for converting the byte[] to a jpeg. It converts the byte[] to a jpeg and adds it to a pdf but I have excluded everything but the part that converts to a jpeg. even saving the image locally yeilds a file that is a black block with no signature :
public ActionResult GeneratePDFforSignature(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Signature signature = db.SignatureDatabase.Find(id);
Image x = (Bitmap)((new ImageConverter()).ConvertFrom(signature.MySignature));
System.Drawing.Image img = x;
img.Save(Server.MapPath("~/Content/test.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg);
//return View();
return RedirectToAction("Index");
}
I really dont know what to do next to fix this and get the signatures as a jpeg with an actual image in it. I guess I'll keep messing with the SignaturePadInit.js for now. If anyone needs me to post more information to fix this please let me know in the comments.
Just a stab here, but have you tried to see if rendering to 24bit png will work allowing for areas that have no image/ signature be transparent?
I only think this because I had similar issues where there were encoded pixels for transparency that I wasn't thinking about and it had the same issue. (Would have commented but the system won't let me )

mxGraph shows grid, but does not show images

I'm using the mxGraph to develop a drawable area in a web page.
This is a legacy code and I'm trying to understand it, because the area is not showing any images besides a grid.
Here is my javascript code to show a simple diagram
//define a window to show the image and put a grid as background
container.style.background = 'url("js/src/images/grid.gif")';
//some other definitions here
var model = new mxGraphModel();
var graph = new mxGraph(container, model);
var id = _GET("id");
mxUtils.post("../Diagram",
"action=get&id="+id,
function(req)
{
var node = req.getDocumentElement();
var dec = new mxCodec(node.ownerDocument);
dec.decode(node, graph.getModel());
},
function(error){
console.log("Error in the design area");
console.log(error);
});
The ../Diagram is a servlet Java that you can see below:
try {
BufferedReader buffRead = new BufferedReader(new FileReader("/home/glassfish/mySite/Repository/"+getId()+"/"+getName()+".txt"));
String line = "";
while (true) {
if (line != null) {
file = line;
} else {
break;
}
line = buffRead.readLine();
}
buffRead.close();
} catch(Exception e) {
System.out.println("File not found");
}
return file;
The returned XML (file) is like below:
<root>
<mxCell id="0"/>
<mxCell id="1" parent="0"/>
<mxCell id="2" parent="1" style="shape=ellipse;fillColor=#33CCFF" value="Objective" vertex="1">
<mxGeometry as="geometry" height="40" width="100" x="262" y="90"/>
</mxCell>
</root>
However, the result in the screen is always the grid only
When I debug the line dec.decode(node, graph.getModel()); to see the node value I got a XML Object that contains the info returned by Java.
In Chrome I don't receive any message in the console, but when I test it in Firefox I receive an warning saying that I have a "XML parsing error in the file graph.properties", but this file is not a XML (actually, I don't know what is this file). I'm also pasting the file here
graph.properties
alreadyConnected=Nodes already connected
containsValidationErrors=Contains validation errors
updatingDocument=Updating Document. Please wait...
updatingSelection=Updating Selection. Please wait...
collapse-expand=Collapse/Expand
doubleClickOrientation=Doubleclick to change orientation
close=Close
error=Error
done=Done
cancel=Cancel
ok=OK
UPDATE
I still have not solved the problem, but I got a new evidence.
When I debug the dec.decode(node, graph.getModel()); line, I have two properties for the dec variable. A XMLDocument and also a empty array. I think that the problem could be in the encoding part, but I not found any tip in the page about mxCodec.
I finally found a solution to the problem.
The error was in the Javascript part, but I don't know why the console did not show any problem. Anyway, replace the original success function for the code below solves the problem.
function(req)
{
var doc = req.getDocumentElement();
var codec = new mxCodec(doc);
var elt = doc.firstChild;
var cells = [];
while (elt != null)
{
cells.push(codec.decode(elt));
elt = elt.nextSibling;
}
graph.addCells(cells);
}

How to access image file from HTML or Javascript for Windows Phone

I have a requirement in wp8, where the picture selected by the user needs to be shown in the browser. To browse and select the photo, I am using photo chooser task.
I am able to get the physical location of the selected image, but on passing the same to JavaScript from c# its not displaying the image.
On googling came across the following link How to access isolated storage file from HTML or Javascript for Windows Phone and PhoneGap Application But it did not solve my issue.
For reference, the location of the image I am using was:
C:\Data\Users\DefApps\AppData{FA586990-6E21-0130-BF9E-3C075409010C}\Local\sample_photo_00.jpg
This is my Javascript code:
function myPicture(data) {
document.getElementById("capturedImage").src = data.imageUri;
alert("data.imageUri " + document.getElementById("capturedImage").src );
var width = data.imageWidth;
var height = data.imageHeight;
alert("image width" + width );
alert("image height" + height );
}
And this is my C# code:
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
string[] picList = Directory.GetFiles(localFolder.Path, "*.jpg");
foreach (string DeleteFile in picList) {
File.Delete(DeleteFile);
}
StorageFile storageFile = await localFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
using (Stream outputStream = await storageFile.OpenStreamForWriteAsync())
{
await file.CopyToAsync(outputStream);
}
send (storageFile.Path);
Now send function should add MyHTML in picture.
You can call JavaScript function from C# by WebBrowser.InvokeScript and send image in args parameter. But args is string(s), so you will have to encode your image to string using some algorithm... Base64 for example:
string ImageToBase64String(Image image)
{
using (MemoryStream stream = new MemoryStream())
{
image.Save(stream, image.RawFormat);
return Convert.ToBase64String(stream.ToArray());
}
}
You will get some long string like this iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==
On other side - in the JavaScript function you calling you will get that Base64 string and use it like this as src attribute of img element:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" />
More info about data uri scheme.
UPDATE: The easer solution. I think you can send your image path, width and height:
ImageProperties properties = await storageFile.Properties.GetImagePropertiesAsync();
webBrowser.InvokeScript("myPicture", storageFile.Path, (string)properties.Width, (string)properties.Height);
function myPicture(src, width, height) {
document.getElementById("capturedImage").src = src;
alert("data.imageUri " + document.getElementById("capturedImage").src );
alert("image width" + width );
alert("image height" + height );
}

JavaScript sending base64 image string to servlet

my html code for selecting image and by clicking browserbutton,
<input id="image_file" type="file" class="frmitm" onChange="fileSelected();">
here for selcted code preview showing,
<img id="preview" width="50px" height="50px" border="1" />
here javascript code for selected image & preview showing on page but when i alert or storing in the key its not getting full of string.
function selectedImage(){
var oFile = document.getElementById('image_file').files[0];
var oImage = document.getElementById('preview');
var oReader = new FileReader();
oReader.onload = function(e){
oImage.src = e.target.result;
var resultStr = oImage.src;
var result = resultStr.split(",");
$('#ImageKey').val(result[1]);
};
oReader.readAsDataURL(oFile);
}
here alert($('#ImageKey').val()) i got only half string only like,
/9j/4AAQSkZJRgABAgEAYABgAAD/7gAOQWRvYmUAZAAAAAAB/+ESC.....etc,
how to get full length of string value.or any other way to convert image to base64 string..
if i saved server response base64 string in var tempImgStr = response.ImgStr;("/9j/4AAQSkZJRgABAgEAYABgAAD/7gAOQWRvYmUAZAAAAAAB/+ESC..etc")
then alert(tempImgStr), i will get half of string value only.
any suggestions please..

Categories