Xamarin.Forms Document Scanner - xamarin.forms

I scan the document with camera and write in to stream. Now is the hardest part, i need to write code for Cropping & Perspective Correction on the document taken. There is a nuget packages and libraries but they are expensive. I want to try to make my own code but don't know from where to start.
This is my code :
var file = await Plugin.Media.CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions() {
Directory = "Sample",
Name = "test.jpg",
SaveToAlbum = false,
});
if (file == null)
return;
Stream stream = file.GetStream();
var localPath = string.Empty;
localPath = Task.Run(() => DependencyService.Get<Shared.ISharedFunction>().SaveFileToDisk(stream, "picture.jpg")).Result;
ImageDoc = ImageSource.FromStream(() => stream);
Picture.Name = localPath;
ImagesNew.Add(Picture);
This is my code i'm using media library to take photo(document) , and saving in stream. Now for the stream i need to convert in pdf(it may be more then one image). I need Cropping & Perspective Correction on the image.

Related

How to TakeSnapshot while streaming rtsp in a Xamarin form

I'm using libvlcsharp to stream camera, it working normally, but I can't take snapshot while stream is playing.
Here is my code :
private void TakeScreenShot()
{
var folderPath = myServices.GetAppImageFolder();
var file = folderPath + "//abc.jpg";
var file1 = Path.Combine(folderPath, "aabbc.jpg");
MediaPlayer.TakeSnapshot(0,file,0,0);
MediaPlayer.TakeSnapshot(0, file1, 0, 0);
bool doesExist = File.Exists(file);
bool doesExist1 = File.Exists(file1);
}
I can't find image, I tried use MediaPlayer.SetVideoCallback(Lock,null,null) too, but it crash before stream start play.
TakeSnapshot return true but:
in Android, I can't find image in folder, doesExist = false.
in iOS, doesExist = true , but I can't find folder contain image.
My folder path is Environment.SpecialFolder.ApplicationData.

Generate QR code image stream or bytes for Xamarin Forms

I am struggling big time with generating QR barcodes as a byte[] or Stream (something that I can use on a XAML image source)
ZXING.NET
I've tried with Zxing.Net but I find the documentation is not great.
In fact, when installing in the xamarin forms class library I am able to compile, but as soon as I add some code to write barcodes I get a compilation error saying that
Can not resolve reference: `zxing`, referenced by `MyXamarinFormsClassLibrary`. Please add a NuGet package or assembly reference for `zxing`, or remove the reference to `Sasw.AforoPass`. 0
Something funky is going on with that library.
And I'm doing a simple example such as:
var options = new QrCodeEncodingOptions
{
DisableECI = true,
CharacterSet = "UTF-8",
Width = 250,
Height = 250
};
var writer = new BarcodeWriter<Image>();
writer.Format = BarcodeFormat.QR_CODE;
writer.Options = options;
var result = writer.Write("foo");
MyImage.Source = result.Source;
QRCoder
It's another nuget library. I've successfully used for dotnet core applications, but it does not seem to be compatible with Xamarin Forms (or Mono, or whatever). It says that the platform is not supported. Probably because it uses System.Drawing.Common?
ZXing.Net.Mobile.Forms
I've used this other library which underneath it uses ZXing.Net. What I don't like is that I don't know if there's any way to generate qr codes without relying on Xaml or the ZXingBarcodeImageView.
I managed to generate QR Codes that way as a workaround, but I hit another wall. See https://github.com/Redth/ZXing.Net.Mobile/issues/908 in which I describe the problems I have to embed the ZXingBarcodeImageView in a carousel inside a popup.
So basically I wanted to go back to the roots, and simply have a working example with the latest version of ZXing.Net (or an alternative, if it exists) that I am able to use in Xamarin Forms.
Most of the examples I find talk about BarcodeWriter but there is no such a class anymore. There is a generic one BarcodeWriter<TUnknownType>and a BarcodeWriterGeneric but as I said, I could not compile anything using Zxing.Net library and with through ZXing.Net.Mobile the images I generate are always empty.
Any help or "modern" code sample (ideally with an alternative) would be much appreciated
UPDATE 1
In other words, I'm looking to have in Xamarin Forms something similar to this code that I had using QrCoder library.
public class QrCodeService
: IQrCodeService
{
public Stream GetQrCode(Guid id, string mimeType = "image/jpeg")
{
if (mimeType is null)
{
throw new ArgumentNullException(nameof(mimeType));
}
var qrGenerator = new QRCodeGenerator();
var qrCodeData = qrGenerator.CreateQrCode(id.ToString(), QRCodeGenerator.ECCLevel.Q);
var qrCode = new QRCode(qrCodeData);
var qrCodeImage = qrCode.GetGraphic(20);
var myImageCodecInfo = GetEncoderInfo(mimeType);
var myEncoder = Encoder.Quality;
var myEncoderParameters = new EncoderParameters(1);
var myEncoderParameter = new EncoderParameter(myEncoder, 50L);
myEncoderParameters.Param[0] = myEncoderParameter;
var stream = new MemoryStream();
qrCodeImage.Save(stream, myImageCodecInfo, myEncoderParameters);
stream.Position = 0;
return stream;
}
private static ImageCodecInfo GetEncoderInfo(string mimeType)
{
var encoders = ImageCodecInfo.GetImageEncoders();
foreach (var encoder in encoders)
{
if (encoder.MimeType == mimeType)
{
return encoder;
}
}
throw new KeyNotFoundException($"Encoder for {mimeType} not found");
}
}
The solution uses QrCoder library and it works fine for Xamarin Forms as follows.
private byte[] GetQrImageAsBytes()
{
var randomText = Guid.NewGuid().ToString();
var qrGenerator = new QRCodeGenerator();
var qrCodeData = qrGenerator.CreateQrCode(randomText, QRCodeGenerator.ECCLevel.L);
var qRCode = new PngByteQRCode(qrCodeData);
var qrCodeBytes = qRCode.GetGraphic(20);
return qrCodeBytes;
}
Here a working sample with this implementation
QrCoder library can do this, but instead of using as in the main page of the project:
QRCodeGenerator qrGenerator = new QRCodeGenerator();
QRCodeData qrCodeData = qrGenerator.CreateQrCode("The text which should be encoded.", QRCodeGenerator.ECCLevel.Q);
QRCode qrCode = new QRCode(qrCodeData); // This point onwards is problematic
Bitmap qrCodeImage = qrCode.GetGraphic(20); // This will throw not supported exception
Switch the last 2 lines to:
var qrCode = new PngByteQRCode(qrCodeData);
byte[] imageByteArray = qrCode.GetGraphic(20);
You'll get byte array instead, but you can convert it into Stream or whatever you like afterwards.

How to write/modify/add some text in a file stored in azure file storage?

My goal is to modify a .txt file in azure file storage using WindowsAzure.Storage API. I would like to know if there is any method to add some text in the file.
Is it easier to use the System.IO API?
I've already tried the cloudFileStream.Write() but it didn't work.
Thank you
The sample on https://github.com/Azure/azure-storage-net/blob/master/Test/WindowsRuntime/File/FileStreamTests.cs shows you how to do this.
public async Task FileOpenWriteTestAsync()
{
byte[] buffer = GetRandomBuffer(2 * 1024);
CloudFileShare share = GetRandomShareReference();
try
{
await share.CreateAsync();
CloudFile file = share.GetRootDirectoryReference().GetFileReference("file1");
using (CloudFileStream fileStream = await file.OpenWriteAsync(2048))
{
Stream fileStreamForWrite = fileStream;
await fileStreamForWrite.WriteAsync(buffer, 0, 2048);
await fileStreamForWrite.FlushAsync();
byte[] testBuffer = new byte[2048];
MemoryStream dstStream = new MemoryStream(testBuffer);
await file.DownloadRangeToStreamAsync(dstStream, null, null);
MemoryStream memStream = new MemoryStream(buffer);
TestHelper.AssertStreamsAreEqual(memStream, dstStream);
}
}
finally
{
share.DeleteIfExistsAsync().Wait();
}
}
If you want to add some text(append to the existing data) to the file on azure file storage, there is no direct method. You need to download it and then upload with the text you want to append.
string accountName = "xxx";
string key = "xxx";
var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, key), true);
var share = storageAccount.CreateCloudFileClient().GetShareReference("testfolder");
CloudFile file1 = share.GetRootDirectoryReference().GetFileReference("a.txt");
//if you want to append some text from local file
var stream1 = File.OpenRead("your file path in local, like d:\hello.txt");
string from_local_file = (new StreamReader(stream1)).ReadToEnd();
//if you just want to add some text from string, directly use the string
//string from_local_file ="the text I want to append to azure file";
//download the content of the azure file
string from_azure_file = file1.DownloadText();
//this does the trick like appending text to azure file, not overwrite
file1.UploadText(from_azure_file + from_local_file);
If you want to directly upload text to file stored on azure file storage, you should use one of the following methods: UploadText() / UploadFromFile() / UploadFromStream().
Note that this will overwrite the existing data in the azure file.
If you want to update the context of azure file, you can use WriteRange() method. But it has some limitations, if you're interesting about it, I can provide you some code.

Progressive Upload and Encryption with CryptoJS

The goal here is to upload a file, encrypt it at the client side, and send the file and its attributes via AJAX to myphpscript.php. To allow larger files, I want to upload in slices using the FileReader slice method and progressively encrypt the slices using the methods described on the CryptoJS site (https://code.google.com/p/crypto-js/). My code below runs, but only ends up storing a a small portion of the intended entire encrypted file. Can I progressively upload and encrypt in the way I am describing?
<script type="text/javascript" src="js/jquery-1.11.0.min.js"></script>
<script src="js/aes.js"></script>
<script>
function readBlob(opt_startByte, opt_stopByte) {
var files = document.getElementById('fileinput').files;
if (!files.length) {
alert('Please select a file!');
return;
}
var file = files[0];
var start = parseInt(opt_startByte) || 0;
var stop = parseInt(opt_stopByte) || file.size - 1;
var reader = new FileReader();
// If we use onloadend, we need to check the readyState.
reader.onloadend = function(evt) {
if (evt.target.readyState == FileReader.DONE) { // DONE == 2
window.bits.push(aesEncryptor.process(evt.target.result));
}
};
var blob = file.slice(start, stop + 1);
reader.readAsBinaryString(blob);
}
function handling(evt) {
// INITIALIZE PROGRESSIVE ENCRYPTION
var key = CryptoJS.enc.Hex.parse(document.getElementById('pass').value);
var iv = CryptoJS.lib.WordArray.random(128 / 8);
window.bits = [];
window.aesEncryptor = CryptoJS.algo.AES.createEncryptor(key, {iv: iv});
// LOOP THROUGH BYTES AND PROGRESSIVELY ENCRYPT
var startByte = 0;
var endByte = 0;
while(startByte < document.querySelector('input[type=file]').files[0].size - 1){
endByte = startByte + 1000000;
readBlob(startByte, endByte);
startByte = endByte;
}
// FINALIZE ENCRYPTION AND UPLOAD
var encrypted = aesEncryptor.finalize();
encrypted = encodeURIComponent(encrypted);
var filename = document.getElementById('fileinput').value;
var file_type = document.getElementById('fileinput').files[0].type;
var url = 'data=' + encrypted + '&filename=' + filename + '&filetype=' + file_type;
$.ajax({
url: 'myphpscript.php',
type: 'POST',
data: url
}).success(function(data){
// Display encrypted data
document.getElementById('status').innerHTML = 'Upload Complete.';
});
alert(encrypted);
}
</script>
So your problem is the line var encrypted = aesEncryptor.finalize();
This is not the encrypted file, but the final 'chunk' produced by the CryptoJS.AES finalizer.
you need to append that to the end of the window.bits buffer to yield the fully encrypted file.
Also, you shouldn't be using window.bits.push, you should keep hold of a reference to each chunk like this (psuedocode):
var prog;
//then in the loop, if chunk is null assign to chunk or else concat:
loop:
if(!prog)
prog = cipher.process()
else
prog.concat(cipher.process())
//then finalize
prog.concat(cipher.finalize())
//now you're free to do whatever with the encrypted file:
var ciphertext = prog.toString()
One important thing to keep in mind is that the chunks may arrive to the encryptor out of order so you either have to keep track of the order that chunks went into aesEncryptor.process so that you can decrypt in the proper order later or queue the chunks and encrypt them in the proper order to begin with.

DOS based printing through ASP.NET

Well my situation is like this:
I am generating a report as a text file at the server which needs to be printed using DOS mode on a dot matrix printer. I want to avoid Windows printing because it would be too slow. Is there a way in ASP.NET through which I can carry out DOS based printing as it is best suited for Dot matrix printers. I have scoured the net but could not come across any solution or pointers. Does any body have any pointers/solutions which they might have implemented or stumbled across.
This application is a Web based application.
Thanx.
If I understand you right, one option is to execute a batch file that would do the actual printing from ASP.NET. From here: (Obviously, you can omit some of the code writing the output to the page)
// Get the full file path
string strFilePath = “c:\\temp\\test.bat”;
// Create the ProcessInfo object
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo("cmd.exe");
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardError = true;
psi.WorkingDirectory = “c:\\temp\\“;
// Start the process
System.Diagnostics.Process proc = System.Diagnostics.Process.Start(psi);
// Open the batch file for reading
System.IO.StreamReader strm = System.IO.File.OpenText(strFilePath);
// Attach the output for reading
System.IO.StreamReader sOut = proc.StandardOutput;
// Attach the in for writing
System.IO.StreamWriter sIn = proc.StandardInput;
// Write each line of the batch file to standard input
while(strm.Peek() != -1)
{
sIn.WriteLine(strm.ReadLine());
}
strm.Close();
// Exit CMD.EXE
string stEchoFmt = "# {0} run successfully. Exiting";
sIn.WriteLine(String.Format(stEchoFmt, strFilePath));
sIn.WriteLine("EXIT");
// Close the process
proc.Close();
// Read the sOut to a string.
string results = sOut.ReadToEnd().Trim();
// Close the io Streams;
sIn.Close();
sOut.Close();
// Write out the results.
string fmtStdOut = "<font face=courier size=0>{0}</font>";
this.Response.Write(String.Format(fmtStdOut,results.Replace(System.Environment.NewLine, "<br>")));
The answer from BobbyShaftoe is correct. Here's a pedantic version of it:
public static void CreateProcess(string strFilePath)
{
// Create the ProcessInfo object
var psi = new ProcessStartInfo("cmd.exe")
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
RedirectStandardError = true,
WorkingDirectory = "c:\\temp\\"
};
// Start the process
using (var proc = Process.Start(psi))
{
// Attach the in for writing
var sIn = proc.StandardInput;
using (var strm = File.OpenText(strFilePath))
{
// Write each line of the batch file to standard input
while (strm.Peek() != -1)
{
sIn.WriteLine(strm.ReadLine());
}
}
// Exit CMD.EXE
sIn.WriteLine(String.Format("# {0} run successfully. Exiting", strFilePath));
sIn.WriteLine("EXIT");
// Read the sOut to a string.
var results = proc.StandardOutput.ReadToEnd().Trim();
// Write out the results.
string fmtStdOut = "<font face=courier size=0>{0}</font>";
this.Response.Write(String.Format(fmtStdOut,results.Replace(System.Environment.NewLine, "<br>")));
}
}

Resources