A faster way to open an .CR2 file in C# - c#

I have a function that works great when opening JPG and PNG files, but locks my computer up when opening a CR2 file. The CRS files are coming from my Canon EOS Rebel T6 Camera and they are big, see:
but I feel like it should not lock my computer up and it should not move this slow.
here is my code :
public async Task OpenFile()
{
OriginalImage = null;
await SetProcessBarInformation(0, "Openning Image file");
OpenFileDialog _openFileDialog = new OpenFileDialog();
if (_openFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
await SetProcessBarInformation(20, "Openning Image file");
FileName = System.IO.Path.GetFileName(_openFileDialog.FileName);
BitmapImage tempOriginalImage = await GetPicture(_openFileDialog.FileName);
Height = (int)tempOriginalImage.Height;
Width = (int)tempOriginalImage.Width;
await SetProcessBarInformation(80, "Openning Image file");
await Task.Run(() =>
{
OriginalImage = tempOriginalImage;
});
}
catch (Exception ex)
{
ErrorMessage = ex.Message;
}
}
protected async Task<BitmapImage> GetPicture(string tempImage)
{
BitmapImage timage = null;
await Task.Run(() =>
{
timage = new BitmapImage(new Uri(tempImage));
timage.Freeze();
});
return timage;
}

Related

Image does not display in gallery after download

I am developing a Xamarin app which retrives info from DB, take/choose photo and upload them to remote server, display this images from the remote server and the user can delete them by tap on and press a button and download the images from the remote server to the local device.
Everything works without problem, but when I download the image and after I go to the gallery for check it, the image does not appear, whereas I can see it and open in the file explorer. When I reboot the phone, the image appear in the gallery.
Below my current button download method:
private void button_download_image_Clicked(object sender, EventArgs e)
{
Uri image_url_format = new Uri(image_url);
WebClient webClient = new WebClient();
try
{
byte[] bytes_image = webClient.DownloadData(image_url_format);
Stream image_stream = new MemoryStream(bytes_image);
string dest_folder = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).ToString();
string file_name = System.IO.Path.GetFileName(image_url_format.LocalPath);
string dest_path = System.IO.Path.Combine(dest_folder, file_name);
using (var fileStream = new FileStream(dest_path, FileMode.Create, FileAccess.Write))
{
image_stream.CopyTo(fileStream);
}
}
catch (Exception ex)
{
DisplayAlert("Error", ex.ToString(), "OK");
}
DisplayAlert("Alert", "Download completed!", "OK");
}
I tried in another device, but I got the same behavior.
Probably there is a sort of thing which does not refresh the gallery.
Any idea how to force the gallery to refresh or something similar?
You need to refresh your gallery after inserting or deleting any pictures in storage.
You can try this.
var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(dest_path)));
Xamarin.Forms.Forms.Context.SendBroadcast(mediaScanIntent);
Add these lines below your code.
Make it like
private void button_download_image_Clicked(object sender, EventArgs e)
{
Uri image_url_format = new Uri(image_url);
WebClient webClient = new WebClient();
try
{
byte[] bytes_image = webClient.DownloadData(image_url_format);
Stream image_stream = new MemoryStream(bytes_image);
string dest_folder = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDownloads).ToString();
string file_name = System.IO.Path.GetFileName(image_url_format.LocalPath);
string dest_path = System.IO.Path.Combine(dest_folder, file_name);
using (var fileStream = new FileStream(dest_path, FileMode.Create, FileAccess.Write))
{
image_stream.CopyTo(fileStream);
}
var mediaScanIntent = new Intent(Intent.ActionMediaScannerScanFile);
mediaScanIntent.SetData(Android.Net.Uri.FromFile(new Java.IO.File(dest_path)));
//for old xamarin forms version
Xamarin.Forms.Forms.Context.SendBroadcast(mediaScanIntent);
//for new xamarin forms version
//Android.App.Application.SendBroadcast(mediaScanIntent);
}
catch (Exception ex)
{
DisplayAlert("Error", ex.ToString(), "OK");
return;
}
DisplayAlert("Alert", "Download completed!", "OK");
}
You need to just refresh the file you have downloaded. It's helpful.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
File f = new File("file://"+ Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES));
Uri contentUri = Uri.fromFile(f);
mediaScanIntent.setData(contentUri);
this.sendBroadcast(mediaScanIntent);
}else{
sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED, Uri.parse("file://" + Environment.getExternalStorageDirectory())));
}
Make sure required permission given on both platforms.
Use in your class:
bool success = await DependencyService.Get<IPhotoLibrary>().SavePhotoAsync(data, folder, filename);
Common Interface
public interface IPhotoLibrary
{
Task<bool> SavePhotoAsync(byte[] data, string folder, string filename);
}
In Android service
public async Task<bool> SavePhotoAsync(byte[] data, string folder, string filename)
{
try
{
File picturesDirectory = Environment.GetExternalStoragePublicDirectory(Environment.DirectoryPictures);
File folderDirectory = picturesDirectory;
if (!string.IsNullOrEmpty(folder))
{
folderDirectory = new File(picturesDirectory, folder);
folderDirectory.Mkdirs();
}
using (File bitmapFile = new File(folderDirectory, filename))
{
bitmapFile.CreateNewFile();
using (FileOutputStream outputStream = new FileOutputStream(bitmapFile))
{
await outputStream.WriteAsync(data);
}
// Make sure it shows up in the Photos gallery promptly.
MediaScannerConnection.ScanFile(MainActivity.Instance,
new string[] { bitmapFile.Path },
new string[] { "image/png", "image/jpeg" }, null);
}
}
catch (System.Exception ex)
{
return false;
}
return true;
}
In iOS service:
public Task<bool> SavePhotoAsync(byte[] data, string folder, string filename)
{
NSData nsData = NSData.FromArray(data);
UIImage image = new UIImage(nsData);
TaskCompletionSource<bool> taskCompletionSource = new TaskCompletionSource<bool>();
image.SaveToPhotosAlbum((UIImage img, NSError error) =>
{
taskCompletionSource.SetResult(error == null);
});
return taskCompletionSource.Task;
}
also you can refer this one just to save an image and to reflect it in media, no need to use skiasharp for that. https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/bitmaps/saving
Hope this may resolve your issue.
Refer to Blu's answer,
I changed this Xamarin.Forms.Forms.Context.SendBroadcast(mediaScanIntent); to Android.App.Application.Context.SendBroadcast(mediaScanIntent); and all works.

How do I adjust the video quality from the camera in xamarin

I want to upload a video into server from my app, now I can upload small size video's, but in the case of larger size the video uploading is not done.How can I do this.
I found a reason that the 2 minutes video has the size 300 mb, so how can I reduce the size of the video with out losing the quality
Please somebody help me..
Here is my code for video taking
private async void TakeVideo_Clicked(object sender, EventArgs e)
{
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakeVideoSupported)
{
await DisplayAlert("No Camera", ":( No camera avaialble.", "OK");
return;
}
var _file = await CrossMedia.Current.TakeVideoAsync(new Plugin.Media.Abstractions.StoreVideoOptions
{
Name = "gtsvideo.mp4",
Directory = "GTSVideos",
});
if (_file == null)
{
return;
}
else
{
_path = _file.Path;
using (var _streamReader = new StreamReader(_file.GetStream()))
{
var _array = default(byte[]);
using (MemoryStream _memoryStream = new MemoryStream())
{
_streamReader.BaseStream.CopyTo(_memoryStream);
_array = _memoryStream.ToArray();
if (await DisplayAlert(App._confirmation, "It may take few Minutes..,Do you want to save the video?", "Yes", "Cancel"))
{
FileUploadAsync(_array, false);
activity_Indicator.IsVisible = true;
activity_Indicator.IsRunning = true;
}
else
{
return;
}
}
}
}
}
public async void FileUploadAsync(byte[] fileUpload, bool IsImage)
{
APIResponse _response = await App.DataManager.UpdateFilesAsync(_task.ID, fileUpload, IsImage);
if (IsImage == false)
{
await System.Threading.Tasks.Task.Delay(5000);
}
if (_response != null)
{
activity_Indicator.IsRunning = false;
if (IsImage)
{
DependencyService.Get<IAlertPlayer>().AlertMessege("Image upload successfully");
}
else
{
DependencyService.Get<IAlertPlayer>().AlertMessege("Video upload successfully");
}
}
else
{
DisplayAlertMessage();
}
}
UploadVideo
public async Task<APIResponse> UpdateFilesAsync(int id, byte[] file, bool IsImage)
{
Url _url = new Url(BaseURL).AppendPathSegment("tasks/UploadFiles");
_url.QueryParams["ID"] = id;
return await Service.POSTFILE<APIResponse>(_url, file, IsImage);
}
public async Task<T> POSTFILE<T>(Url url, byte[] uploadFile, bool IsImage)
{
try
{
using (MultipartFormDataContent _content = new MultipartFormDataContent())
{
ByteArrayContent _filecontent = new ByteArrayContent(uploadFile);
if (IsImage)
{
_filecontent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = Guid.NewGuid().ToString() + ".png"
};
}
else
{
_filecontent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
FileName = Guid.NewGuid().ToString() + ".mp4"
};
}
_content.Add(_filecontent);
using (HttpResponseMessage _response = await Client.PostAsync(url, _content))
{
string _result = await _response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(_result);
}
}
}
catch (Exception ex)
{
}
return default(T);
}
Simple answer: Unless you implement some fancy lossless compression code yourself, you don't. You get what the operating system of your phone gives you.

The process cannot access the file because it is being used by another process

I am running a program where a file gets uploaded to a folder in IIS,and then is processed to extract some values from it. I use a WCF service to perform the process, and BackgroundUploader to upload the file to IIS. However, after the upload process is complete, I get the error "The process cannot access the file x because it is being used by another process." Based on similar questions asked here, I gathered that the file concerned needs to be in a using statement. I tried to modify my code to the following, but it didn't work, and I am not sure if it is even right.
namespace App17
{
public sealed partial class MainPage : Page, IDisposable
{
private CancellationTokenSource cts;
public void Dispose()
{
if (cts != null)
{
cts.Dispose();
cts = null;
}
GC.SuppressFinalize(this);
}
public MainPage()
{
this.InitializeComponent();
cts = new CancellationTokenSource();
}
public async void Button_Click(object sender, RoutedEventArgs e)
{
try
{
Uri uri = new Uri(serverAddressField.Text.Trim());
FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add("*");
StorageFile file = await picker.PickSingleFileAsync();
using (var stream = await file.OpenAsync(FileAccessMode.Read))
{
GlobalClass.filecontent = file.Name;
GlobalClass.filepath = file.Path;
BackgroundUploader uploader = new BackgroundUploader();
uploader.SetRequestHeader("Filename", file.Name);
UploadOperation upload = uploader.CreateUpload(uri, file);
await HandleUploadAsync(upload, true);
stream.Dispose();
}
}
catch (Exception ex)
{
string message = ex.ToString();
var dialog = new MessageDialog(message);
await dialog.ShowAsync();
Log(message);
}
}
private void CancelAll(object sender, RoutedEventArgs e)
{
Log("Canceling all active uploads");
cts.Cancel();
cts.Dispose();
cts = new CancellationTokenSource();
}
private async Task HandleUploadAsync(UploadOperation upload, bool start)
{
try
{
Progress<UploadOperation> progressCallback = new Progress<UploadOperation>(UploadProgress);
if (start)
{
await upload.StartAsync().AsTask(cts.Token, progressCallback);
}
else
{
// The upload was already running when the application started, re-attach the progress handler.
await upload.AttachAsync().AsTask(cts.Token, progressCallback);
}
ResponseInformation response = upload.GetResponseInformation();
Log(String.Format("Completed: {0}, Status Code: {1}", upload.Guid, response.StatusCode));
cts.Dispose();
}
catch (TaskCanceledException)
{
Log("Upload cancelled.");
}
catch (Exception ex)
{
string message = ex.ToString();
var dialog = new MessageDialog(message);
await dialog.ShowAsync();
Log(message);
}
}
private void Log(string message)
{
outputField.Text += message + "\r\n";
}
private async void LogStatus(string message)
{
var dialog = new MessageDialog(message);
await dialog.ShowAsync();
Log(message);
}
private void UploadProgress(UploadOperation upload)
{
BackgroundUploadProgress currentProgress = upload.Progress;
MarshalLog(String.Format(CultureInfo.CurrentCulture, "Progress: {0}, Status: {1}", upload.Guid,
currentProgress.Status));
double percentSent = 100;
if (currentProgress.TotalBytesToSend > 0)
{
percentSent = currentProgress.BytesSent * 100 / currentProgress.TotalBytesToSend;
}
MarshalLog(String.Format(CultureInfo.CurrentCulture,
" - Sent bytes: {0} of {1} ({2}%), Received bytes: {3} of {4}", currentProgress.BytesSent,
currentProgress.TotalBytesToSend, percentSent, currentProgress.BytesReceived, currentProgress.TotalBytesToReceive));
if (currentProgress.HasRestarted)
{
MarshalLog(" - Upload restarted");
}
if (currentProgress.HasResponseChanged)
{
MarshalLog(" - Response updated; Header count: " + upload.GetResponseInformation().Headers.Count);
}
}
private void MarshalLog(string value)
{
var ignore = this.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
Log(value);
});
}
}
}
After this is done, the file name is sent to a WCF service which will access and process the uploaded file to extract certain values. It is at this point I receive the error. I would truly appreciate some help.
public async void Extract_Button_Click(object sender, RoutedEventArgs e)
{
ServiceReference1.Service1Client MyService = new ServiceReference1.Service1Client();
string filename = GlobalClass.filecontent;
string filepath = #"C:\Users\R\Documents\Visual Studio 2015\Projects\WCF\WCF\Uploads\"+ filename;
bool x = await MyService.ReadECGAsync(filename, filepath);
}
EDIT: Code before I added the using block
try
{
Uri uri = new Uri(serverAddressField.Text.Trim());
FileOpenPicker picker = new FileOpenPicker();
picker.FileTypeFilter.Add("*");
StorageFile file = await picker.PickSingleFileAsync();
GlobalClass.filecontent = file.Name;
GlobalClass.filepath = file.Path;
BackgroundUploader uploader = new BackgroundUploader();
uploader.SetRequestHeader("Filename", file.Name);
UploadOperation upload = uploader.CreateUpload(uri, file);
await HandleUploadAsync(upload, true);
}
When you work with stream writers you actually create a process, which you can close it from task manager. And after stream.Dispose() put stream.Close().
This should solve your problem.
You should also close the stream that writes the file to disk (look at your implementation of CreateUpload).
i got such error in DotNet Core 2 using this code:
await file.CopyToAsync(new FileStream(fullFileName, FileMode.Create));
counter++;
and this is how I managed to get rid of message (The process cannot access the file x because it is being used by another process):
using (FileStream DestinationStream = new FileStream(fullFileName, FileMode.Create))
{
await file.CopyToAsync(DestinationStream);
counter++;
}

Read Barcode in an WP8.1 app with ZXing

Im currently writing my first app for WP8.1. The app just need to scan a barcode.
public async void ScanBarcodeAsync(Windows.Storage.StorageFile Afile)
{
WriteableBitmap bitmap;
BitmapDecoder decoder;
using (IRandomAccessStream str = await Afile.OpenReadAsync())
{
decoder = await BitmapDecoder.CreateAsync(str);
bitmap = new WriteableBitmap(Convert.ToInt32(decoder.PixelWidth),
Convert.ToInt32(decoder.PixelHeight));
await bitmap.SetSourceAsync(str);
}
ZXing.BarcodeReader reader = new BarcodeReader();
/*reader.Options.PossibleFormats = new ZXing.BarcodeFormat[]
{
ZXing.BarcodeFormat.CODE_128,
ZXing.BarcodeFormat.CODE_39
};*/
reader.Options.TryHarder = true;
reader.AutoRotate = true;
var results = reader.Decode(bitmap);
if (results != null)
{
edtBarcode.Text = results.Text;
}
else
{
edtBarcode.Text = "Error";
}
}
The file for this method is created this way
async void StartCapture()
{
var cameraID = await GetCameraID(Windows.Devices.Enumeration.Panel.Back);
MediaCaptureInitializationSettings settings = new MediaCaptureInitializationSettings();
settings.PhotoCaptureSource = Windows.Media.Capture.PhotoCaptureSource.VideoPreview;
settings.StreamingCaptureMode = Windows.Media.Capture.StreamingCaptureMode.Video;
settings.AudioDeviceId = string.Empty;
settings.VideoDeviceId = cameraID.Id;
captureManager = new MediaCapture(); //Define MediaCapture object
await captureManager.InitializeAsync(settings); //Initialize MediaCapture and
var focusSettings = new FocusSettings();
focusSettings.AutoFocusRange = AutoFocusRange.Macro;
focusSettings.Mode = FocusMode.Auto;
focusSettings.WaitForFocus = true;
focusSettings.DisableDriverFallback = false;
captureManager.VideoDeviceController.FocusControl.Configure(focusSettings);
captureManager.SetPreviewRotation(VideoRotation.Clockwise90Degrees);
capturePreview.Source = captureManager; //Start preiving on CaptureElement
await captureManager.StartPreviewAsync(); //Start camera capturing
}
async private void Capture_Photo_Click(object sender, RoutedEventArgs e)
{
//Create JPEG image Encoding format for storing image in JPEG type
ImageEncodingProperties imgFormat = ImageEncodingProperties.CreateJpeg();
// create storage file in local app storage
if (ImageIndex > 0)
{
StorageFile delFile = await ApplicationData.Current.LocalFolder.GetFileAsync("Photo" + Convert.ToString(ImageIndex - 1) + ".jpg");
await delFile.DeleteAsync();
}
file = await ApplicationData.Current.LocalFolder.CreateFileAsync("Photo" + Convert.ToString(ImageIndex++) + ".jpg", CreationCollisionOption.ReplaceExisting);
// take photo and store it on file location.
await captureManager.CapturePhotoToStorageFileAsync(imgFormat, file);
//// create storage file in Picture Library
//StorageFile file = await KnownFolders.PicturesLibrary.CreateFileAsync("Photo.jpg",CreationCollisionOption.GenerateUniqueName);
// Get photo as a BitmapImage using storage file path.
bmpImage = new BitmapImage();
bmpImage.CreateOptions = BitmapCreateOptions.None;
bmpImage.UriSource = new Uri(file.Path);
ImageTaken = true;
Frame.Navigate(typeof(MainPage));
Frame.Navigate(typeof(MainPage));
}
I dont get an error running this code. But the result from ZXing is always null. The ScanBarcodeAsync-Function is directly run after taking the picture. The image the app takes is not sharp. Can this cause the problem?
Im happy to get any suggestions to solve my problem.

Screenshot Feature on Windows Store App

I am making an app for the windows store, and one section, 'Create' allows the user to drag images onto a background to create their own little scene (the app is aimed at kids). I'm adding a screenshot button so the user can save their work once they are done, and I have all the coding done, error free, but once I run it and press the screenshot button the app fails. Any advice or help is appreciated.
I get this message originating from the button once it fails:
An exception of type 'System.UnauthorizedAccessException'
occurred in mscorlib.dll but was not handled in user code
async void btnScreenshot_Click(object sender, RoutedEventArgs e)
{
var bitmap = await SaveScreenshotAsync(controlsGrid);
}
async Task<RenderTargetBitmap> SaveScreenshotAsync(FrameworkElement uielement)
{
var file = await PickSaveImageAsync();
return await SaveToFileAsync(uielement, file);
}
async Task<StorageFile> PickSaveImageAsync()
{
var filePicker = new FileSavePicker();
filePicker.FileTypeChoices.Add("Bitmap", new List<string>() { ".bmp" });
filePicker.FileTypeChoices.Add("JPEG format", new List<string>() { ".jpg" });
filePicker.FileTypeChoices.Add("Compuserve format", new List<string>() { ".gif" });
filePicker.FileTypeChoices.Add("Portable Network Graphics", new List<string>() { ".png" });
filePicker.FileTypeChoices.Add("Tagged Image File Format", new List<string>() { ".tif" });
filePicker.DefaultFileExtension = ".jpg";
filePicker.SuggestedFileName = "screenshot";
filePicker.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
filePicker.SettingsIdentifier = "picture picker";
filePicker.CommitButtonText = "Save picture";
return await filePicker.PickSaveFileAsync();
}
async Task<RenderTargetBitmap> SaveToFileAsync(FrameworkElement uielement, StorageFile file)
{
if (file != null)
{
CachedFileManager.DeferUpdates(file);
Guid encoderId = GetBitmapEncoder(file.FileType);
try
{
using (var stream = await file.OpenAsync(FileAccessMode.ReadWrite))
{
return await CaptureToStreamAsync(uielement, stream, encoderId);
}
}
catch (Exception ex)
{
DisplayMessage(ex.Message);
}
var status = await CachedFileManager.CompleteUpdatesAsync(file);
}
return null;
}
Guid GetBitmapEncoder(string fileType)
{
Guid encoderId = BitmapEncoder.JpegEncoderId;
switch (fileType)
{
case ".bmp":
encoderId = BitmapEncoder.BmpEncoderId;
break;
case ".gif":
encoderId = BitmapEncoder.GifEncoderId;
break;
case ".png":
encoderId = BitmapEncoder.PngEncoderId;
break;
case ".tif":
encoderId = BitmapEncoder.TiffEncoderId;
break;
}
return encoderId;
}
async Task<RenderTargetBitmap> CaptureToStreamAsync(FrameworkElement uielement, IRandomAccessStream stream, Guid encoderId)
{
try
{
var renderTargetBitmap = new RenderTargetBitmap();
await renderTargetBitmap.RenderAsync(uielement);
var pixels = await renderTargetBitmap.GetPixelsAsync();
var logicalDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
var encoder = await BitmapEncoder.CreateAsync(encoderId, stream);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Ignore,
(uint)renderTargetBitmap.PixelWidth,
(uint)renderTargetBitmap.PixelHeight,
logicalDpi,
logicalDpi,
pixels.ToArray());
await encoder.FlushAsync();
return renderTargetBitmap;
}
catch (Exception ex)
{
DisplayMessage(ex.Message);
}
return null;
}
async void DisplayMessage(string error)
{
var dialog = new MessageDialog(error);
await dialog.ShowAsync();
}

Categories