Nativescript Mapbox screen capture - javascript

My app offers a button to take a screenshot of the current page, which includes a Mapbox map (handled by the nativescript-mapbox plugin). Everything works fine on iOS but on Android, the map is not rendering.
I was pointed from the mapbox team to this example, which addresses their issue with the "regular" Android Graphics Canvas, providing a solution using the Mapbox Snapshot API: https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java#L52
As I am not a Java developer (I barely can handle the {NS} part :) ), I don't know how to convert the code to my pure Javascript {NS} code.
This is what I have now:
var v = view;
var bmp = android.graphics.Bitmap.createBitmap(v.getMeasuredWidth(), v.getMeasuredHeight()+50, android.graphics.Bitmap.Config.ARGB_8888);
v.android.draw(new android.graphics.Canvas(bmp));
var source = new imageSource.ImageSource();
source.setNativeSource(bmp);
//saves image into Documents folder
var folder = fs.knownFolders.documents().path;
var fileName = "Test.png"
var path = fs.path.join(folder, fileName);
var saved = source.saveToFile(path, "png");
Any ideas on how to convert/use their code to capture my entire view, including the map?

Related

How to get custom ttf font working with jsPDF.output()

I've added the jsPDF library to my Titanium project to generate PDFs client side, which has been working great. But now I want to localize the app for Arabic countries, which means that I have the add a custom font. This works perfectly if you use doc.save('file.pdf'), but it doesn't seem to work correctly for doc.output(). I have to use output because I'm using jsPDF outside of a browser.
To make the library work in Titanium I've had to strip all of the references to window, because it's not running in a browser or webview.
I've tried writing the file from different sources, but nothing seems to yield any results.
My current implementation:
doc = new jsPDF();
var f = Ti.Filesystem.getFile(Ti.Filesystem.resourcesDirectory, 'fonts/markazi-text.regular.ttf');
var contents = f.read();
var base64font = Ti.Utils.base64encode(contents).toString();
doc.addFileToVFS("MarkaziText-Regular", base64font);
doc.addFont('MarkaziText-Regular', 'markazi-text', 'normal');
doc.setFontSize(20);
doc.setFont('markazi-text', 'normal');
doc.text('The quick brown fox jumps over the lazy dog', 20, 20);
var tempFile = Ti.Filesystem.getFile(Ti.Filesystem.getTempDirectory(), 'report.pdf');
if (tempFile.exists()) {
tempFile.deleteFile();
}
tempFile.write(doc.output());
I've also tried to write the file from a blob:
var reader = new FileReader();
reader.onloadend = function () {
tempFile.write(reader.result);
};
reader.readAsText(getBlob(buildDocument()));
But the pdf is empty if I use this. I've also tried the library in a webview within a titanium application, which does work but I don't really want to go that road. It would require too many changes to the code.
Expected:
Actual:
I've finally resolved it by creating a local HTML file. In this HTML file I've loaded jsPDF and my own JavaScript to generate a PDF file. I've loaded this HTML file in a WebView.
I'm generating all the data needed for the PDF in an Alloy controller. I'm sending this data to my WebView JavaScript by firing an app event and catching it in the WebView.
After the PDF is created I trigger an app event in the WebView that contains the base64 data of the jsPDF doc:
Ti.App.fireEvent('app:pdfdone', {
output: doc.output('dataurlstring').replace("data:application/pdf;filename=generated.pdf;base64,", "")
});
I finally save this as a file in the Alloy controller:
var f = Ti.Filesystem.getFile(Ti.Filesystem.getTempDirectory(), 'doc.pdf');
f.write(Ti.Utils.base64decode(e.output));

Extracting EXIF data (specifically dateTime and GPSLatitude and GPSLongitude) with JavaScript

I have a program where a camera is set up to constantly take pictures (about every 10 seconds or so) and the picture is sent to a folder on my server and then another program refreshes that folder constantly so that I always just have the most recent picture in that particular folder.
An HTML document exists that also constantly refreshes, and references that picture location to get and display the newest image.
What I'm trying to do is extract the EXIF data (that I've verified exists when I save the image from the active webpage and look at it's properties). I want to display the DateCreated (I believe this is DateTime) and the Latitude and Longitude (I believe is GPSLatitude and GPSLongitude).
I came across this library, exif-js, which seems like the go-to for most people trying to do this same thing in JavaScript. My code looks the same as the code at the bottom of the README.md file, except I changed out my img id="...." and variable names, (see below). It seems like it should work, but it's not producing any data. My empty span element just stays empty.
Is there an issue with the short time span that the page has before refreshing?
Thanks for any help!
Here's what my code currently looks like (just trying to get the DateTime info). I have also tried the GPSLatitude and GPSLongitude tags.
<!-- Library to extract EXIF data -->
<script src="vendors/exif-js/exif-js"></script>
<script type="text/javascript">
window.onload=getExif;
function getExif()
{
var img1 = document.getElementById("img1");
EXIF.getData(img1, function() {
var time = EXIF.getTag(this, "DateTime");
var img1Time = document.getElementById("img1Time");
img1Time.innerHTML = `${time}`;
});
var img2 = document.getElementById("img2");
EXIF.getData(img2, function() {
var allMetaData = EXIF.getALLTags(this);
var allMetaDataSpan = document.getElementById("Img2Time");
allMetaDataSpan.innerHTML = JSON.stringify(allMetaData, null, "\t");
});
}
</script>
go into ur exif.js file and then go to line 930 and then change it to
EXIF.getData = function(img, callback) {
if ((self.Image && img instanceof self.Image
|| self.HTMLImageElement && img instanceof self.HTMLImageElement)
&& !img.complete)
return false;
I know this may be already solved but I'd like to offer an alternative solution, for the people stumbling upon this question.
I'm a developer of a new library exifr you might want to try. It's maintained, actively developed library with focus on performance and works in both nodejs and browser.
async function getExif() {
let output = await exifr.parse(imgBuffer)
console.log('latitude', output.latitude) // converted by the library
console.log('longitude', output.longitude) // converted by the library
console.log('GPSLatitude', output.GPSLatitude) // raw value
console.log('GPSLongitude', output.GPSLongitude) // raw value
console.log('GPSDateStamp', output.GPSDateStamp)
console.log('DateTimeOriginal', output.DateTimeOriginal)
console.log('DateTimeDigitized', output.DateTimeDigitized)
console.log('ModifyDate', output.ModifyDate)
}
You can also try out the library's playground and experiment with images and their output, or check out the repository and docs.

How can I modify a javascript event in a PDF file programmatically?

My PDF file has an event attached to a button. I need to be able to modify that event programmatically. I tried this way using iTextSharp, but it didn't change the javascript in the new file:
var pdfReader = new PdfReader(originalPdfDocumentPath);
pdfReader.RemoveUsageRights();
var pdfStamper = new PdfStamper(pdfReader, new FileStream(
newPdfDocumentPath, FileMode.Create, FileAccess.Write, FileShare.None),
'\0', true);
var originalXml = pdfReader.AcroFields.Xfa.DomDocument.InnerXml;
var newXml = originalXml.Replace(
"Table2.Row1.instanceManager.removeInstance(1)",
"Table2._Row1.removeInstance(this.parent.parent.index)");
// Unfortunately, this line does nothing.
pdfStamper.AcroFields.Xfa.DomDocument.InnerXml = newXml;
pdfStamper.Close();
pdfReader.Close();
Any help would be greatly appreciated.
I found that it works if, instead of changing the XML directly, I change the DomDocument and mark the XFA as changed. Below is the corrected code:
var pdfReader = new PdfReader(originalPdfDocumentPath);
pdfReader.RemoveUsageRights();
var pdfStamper = new PdfStamper(pdfReader, new FileStream(newPdfDocumentPath, FileMode.Create, FileAccess.Write, FileShare.None), '\0', true);
var originalXml = pdfReader.AcroFields.Xfa.DomDocument.InnerXml;
var newXml = originalXml.Replace("Table2.Row1.instanceManager.removeInstance(1)", "Table2._Row1.removeInstance(this.parent.parent.index)");
/* New Code */
var doc = new XmlDocument();
doc.LoadXml(newXml);
pdfStamper.AcroFields.Xfa.DomDocument = doc;
pdfStamper.AcroFields.Xfa.Changed = true;
/* End of New Code */
pdfStamper.Close();
pdfReader.Close();
I should note that, even though this code changes the javascript in the PDF file, it also disables the extended features in Adobe Acrobat Reader. You can find more information regarding this here:
http://developers.itextpdf.com/question/why-do-i-get-error-saying-use-extended-features-no-longer-available
"The problem is related to whether or not your document is Reader Enabled. Reader-enabling can only be done using Adobe software. It is a process that requires a digital signature using a private key from Adobe. When a valid signature is present, specific functionality (as defined in the usage rights when signing) is unlocked in Adobe Reader.
You change the content of such a PDF, hence you break the signature."

HTML5/ javascript barcode reader on mobile without manually switching resolution

I am trying to do barcode reading in HTML5/ Javascript on mobile so I can extract the barcode and post to a Ruby on Rails web service.
I am using this code for barcode reading: code by manuels which works fine (You can try out the barcode reader code here) if camera on mobile is set to a very low resolution, not at high resolution though. This method using HTML Media Capture is not ideal as user would have to switch to low resolution manually. I know one can set resolution using GetUserMedia but it's not compatible with many browser/ versions.
I am trying to resize the captured photo using a canvas, based on the canvas code here (not written by myself). The resize works as expect. I then combine the barcode reading code mentioned above in the resize function as below but the barcode reading part doesn't work.
... var interface = new Interface('./bardecode-worker.js');
interface.on_stdout = function(x) { document.getElementById('barcode').appendChild(document.createTextNode('result:
'+x)); }; ...
interface.addData(tempCanvas.toDataURL('image/jpeg'), '/barcode.jpg').then
(
function()
{
interface.run('/barcode.jpg').then
(
function() { console.log(arguments); }
);
}
)
This is manuels' original code below, and in the above code, I am trying to feed the resized image from the canvas into the interface.js instead of a FileReader:
document.getElementById('barcode_file').onchange = function(e) {
var file = e.target.files[0];
var reader = new FileReader();
document.getElementById('barcode').appendChild(document.createTextNode('running...'));
reader.onload = function(ev) {
interface.addData(ev.target.result, '/barcode.jpg').then(function() {
interface.run('/barcode.jpg').then(function() { console.log(arguments); });
})
};
reader.readAsBinaryString(file);
};
Sorry, I am quite new to javascript. Any suggestions? Or is there a better solution?
You might be interested in looking at this program which specializes in providing easier access to hardware on mobile phones.
http://bridgeit.mobi/
It installs a native app on the phone and then lets you open the app from your webpage and then passes back the scan or photo or other item.
They use a javascript library they wrote to open the app and then pass the information back to your webpage.
The library will also open the store page of the program if it is not installed the first time it a user tries to use it.

Using a local folder how to store google markers

var newIcon = new google.maps.MarkerImage('images/red-pushpin.png');
var newIcon = 'http://images/red-pushpin.png';
var newIcon = 'http://maps.google.com/mapfiles/ms/icons/red-pushpin.png';
var MarkerOption = {map:map, position:MarkerLatLng, title:name, icon:newIcon };
var Marker = new google.maps.Marker(MarkerOption);
I am using a VB WebBrowser Control to load an HTML page & access Google Maps via
javascript. It all works, except that I can only access the markers by line 3 above
but I want to use a local image folder (images) but javascrip cant 'see' it, yet
it is in the same directory as the HTML page.
What am I missing, please?
According to the MarkerOptions docs, the icon should be a URL.
So you will only be able to access an image within a url and local files embedded with file:/// tend to be ignored by browsers if the website is being served over http.
So only your 3 line is working.
If in case you want to access your icon image from the local drive, you can do it like this:
var newIcon= "http://mysite.com/images/red-pushpin.png"
In place of mysite replace it with the url that you get for your website when you run it

Categories