I'm writing a cross-platform (iOS and Android) app in C# using Xamarin on Visual Studio Community 2022. I have implemented a camera preview on the app using the code found at this website :
https://www.c-sharpcorner.com/article/creating-a-custom-camera-view-basic-concept-create-half-screen-camera-in-xamari/
The code on the website is for iOS, but there is a link at the bottom to download a folder which contains the code for Android as well. My app now displays a camera preview, but there is no way to take a picture with this. I therefore want to create a button which takes a picture without having to open the camera app. I'd also like the resulting photo to not be saved in the photos of the phone. I have looked but have found no way of doing exactly what I want, and therefore I don't know where to get started. If the answer could give as many details as possible about how to do this for both platforms it would be appreciated. Also, would the resulting photo be of the type FileResult? I have previously worked with the mediapicker in Xamarin which returns the type FileResult, but have come to realize that there are limitations within the mediapicker and I therefore can't work with it.
Thanks a lot :)
You can try MediaPicker to capture picture.And get the filepath in photo.FullPath.
You can refer to the link below to get more details:
https://learn.microsoft.com/en-us/xamarin/essentials/media-picker?tabs=ios
edit:
private void cameraView_MediaCaptured(object sender, Xamarin.CommunityToolkit.UI.Views.MediaCapturedEventArgs e)
{
byte[] image = e.ImageData;
DependencyService.Get<ISaveService>().wirteFile("pic.jpg", image);
}
public interface ISaveService
{
void SaveFile(string fileName, byte[] data);
}
Android:
[assembly: Xamarin.Forms.Dependency(typeof(SaveService))]
namespace cameraviewDemo.Droid
{
public class SaveService: ISaveService
{
void ISaveService.SaveFile(string fileName, byte[] data)
{
string picPath = Path.Combine(Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, Android.OS.Environment.DirectoryPictures);
string filePath = Path.Combine(picPath, fileName);
File.WriteAllBytes(filePath, data);
}
}
}
iOS:
[assembly: Xamarin.Forms.Dependency(typeof(SaveService))]
namespace cameraviewDemo.iOS
{
class SaveService: ISaveService
{
void ISaveService.SaveFile(string fileName, byte[] data)
{
var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var filename = Path.Combine(documents, fileName);
File.WriteAllBytes(filename, data);
}
}
}
Related
I have build a winform application which connects a technical drawing application (CAD - SolidEdge) and an ERP-system. This is working fine but I can't get the right thumbnails in the bomstructure.
When I click on a file in Windows (Windows 10) I see a nice preview image. How can I extract this image to my application?
I had found a similar question and solution (Extract thumbnail for any file in Windows) but this is won't work anymore (because of Windows 10 updates I guess).
Also this one (C# get thumbnail from file via windows api) doesn't work and gives: Example wrong thumbnail and Example wrong thumbnail.
Have you guys any idea how to solve this? Thanks!!
There are different types of thumbnails that can be retrieved from Windows.
Picture
Song Album Art
Document Icon
Folder
File Group
Single Item
Microsoft has a nice sample project called FileThumbnails that lets you play with each type. This project was updated for Windows10 and VS 2019 in March 2020. Although it's a universal windows project instead of winforms.
After playing with the different modes I found the one you are after for Solid Edge files is #6.
internal class FileExtensions
{
public static readonly string[] SEfiles = new string[] { ".dft", ".par", ".asm" };
}
FileOpenPicker openPicker = new FileOpenPicker();
foreach (string extension in FileExtensions.SEfiles)
{
openPicker.FileTypeFilter.Add(extension);
}
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
const ThumbnailMode thumbnailMode = ThumbnailMode.SingleItem;
bool fastThumbnail = FastThumbnailCheckBox.IsChecked.Value;
ThumbnailOptions thumbnailOptions = ThumbnailOptions.UseCurrentScale;
if (fastThumbnail)
{
thumbnailOptions |= ThumbnailOptions.ReturnOnlyIfCached;
}
using (StorageItemThumbnail thumbnail = await file.GetScaledImageAsThumbnailAsync(thumbnailMode, size, thumbnailOptions))
{
if (thumbnail != null)
{
MainPage.DisplayResult(ThumbnailImage, OutputTextBlock, thumbnailMode.ToString(), size, file, thumbnail, false);
}
else
{
rootPage.NotifyUser(Errors.NoThumbnail, NotifyType.StatusMessage);
}
}
}
public static void DisplayResult(Image image, TextBlock textBlock, string thumbnailModeName, uint size, IStorageItem item, StorageItemThumbnail thumbnail, bool isGroup)
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(thumbnail);
image.Source = bitmapImage;
textBlock.Text = String.Format("ThumbnailMode.{0}\n"
+ "{1} used: {2}\n"
+ "Requested size: {3}\n"
+ "Returned size: {4}x{5}",
thumbnailModeName,
isGroup ? "Group" : item.IsOfType(StorageItemTypes.File) ? "File" : "Folder",
item.Name,
size,
thumbnail.OriginalWidth,
thumbnail.OriginalHeight);
}
Result Example:
I have a desktop application that I have made on Unity and I want to take a screenshot of my current view in the application using a C# script attached to the main camera. Please help.
I have browsed other code snippets that I found on this platform and nothing seemed to help.
You can use CaptureScreenshot.
public class ScreenCapture : MonoBehaviour
{
//here you can set the folder you want to use,
//IMPORTANT - use "#" before the string, because this is a verbatim string
//IMPORTANT - the folder must exists
string pathToYourFile = #"C:\Screenshots\";
//this is the name of the file
string fileName = "filename";
//this is the file type
string fileType = ".png";
private int CurrentScreenshot { get => PlayerPrefs.GetInt("ScreenShot"); set => PlayerPrefs.SetInt("ScreenShot", value); }
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
UnityEngine.ScreenCapture.CaptureScreenshot(pathToYourFile + fileName + CurrentScreenshot + fileType);
CurrentScreenshot++;
}
}
}
A few notes.
I used a verbatim string to define your folder
The folder where you store the screenshot must exist (if you want to create it in the script you can follow this answer)
AFTER COMMENT REQUEST - 1: If you do not set the folder the file will be saved in the default directory of the application (that changes based on the system - you can check it from Application.dataPath)
AFTER COMMENT REQUEST - 2: If you use the same path and filename the file will be overriden, so I added a way to let you save multiple screenshots, also in different sessions using PlayerPrefs.
You can use CaptureScreenshot method as answered above but it might be confusing for you if you are new to unity. It stores your captures image in a filepath which you should pass to CaptureScreenshot method as parameter for example
public class ScreenShotManager : MonoBehaviour {
const string FilePath = #"C:\Users\UserName\Desktop\ScreenShots";
public void CaptureScreenShot() {
ScreenCapture.CaptureScreenshot(FilePath);
}
void Update(){
if(Input.GetKeyDown(Keycode.C))
CaptureScreenShot();
}
this code shows that if you press 'c' key on keyboard it would be captured what main camera is rendering at that moment and stored in that file path
Specs
Unity editor version: 2018.2.8f1
Firebase Unity SDK version: 5.5.0
Additional SDKs: SimpleFirebaseUnity
Developing on: Mac
Export Platform: Android
Issue
I'm having troubles setting up a system to download pictures from storage. I'm not an expert in databases, but I wanted to give it try, just to learn how it is done.
I found Firebase very useful to store metadata on the real-time database and easy to approach even for an entry level programmer like me.
The problem is that I'm trying to download a .png file from a folder in storage, but I can't manage to find if the file is actually downloaded or if it's just lost in the process. I don't get any errors in the console, but when I open the folder in which the files should be, it's empty.
Code
private SimpleFirebaseUnity.Firebase firebaseDatabase;
private FirebaseQueue firebaseQueue;
private FirebaseStorage firebaseStorage;
private StorageReference m_storage_ref;
// Setup refernece to database and storage
void SetupReferences()
{
// Get a reference to the database service, using SimpleFirebase plugin
firebaseDatabase = SimpleFirebaseUnity.Firebase.CreateNew(FIREBASE_LINK, FIREBASE_SECRET);
// Get a reference to the storage service, using the default Firebase App
firebaseStorage = FirebaseStorage.DefaultInstance;
// Create a storage reference from our storage service
m_storage_ref = firebaseStorage.GetReferenceFromUrl(STORAGE_LINK);
// Create a queue, using SimpleFirebase
firebaseQueue = new FirebaseQueue(true, 3, 1f);
}
// ...
IEnumerator DownloadImage(string address, string fileName)
{
var local_path = Application.persistentDataPath + THUMBNAILS_PATH;
var content_ref = m_storage_ref.Child(THUMBNAILS_PATH + fileName + ".png");
content_ref.GetFileAsync(local_path).ContinueWith(task => {
if (!task.IsFaulted && !task.IsCanceled)
{
Debug.Log("File downloaded.");
}
});
yield return null;
}
There can be many reason for why this is not working for you including:
security rules are not setup properly
paths to files are not correct
you are testing it on wrong platform (Firebase is not working well in the editor)
your device is blocking the connection
etc...
In order to get error messages you need to log them:
IEnumerator DownloadImage(string address, string fileName)
{
var local_path = Application.persistentDataPath + THUMBNAILS_PATH;
var content_ref = m_storage_ref.Child(THUMBNAILS_PATH + fileName + ".png");
content_ref.GetFileAsync(local_path).ContinueWith(task => {
if (!task.IsFaulted && !task.IsCanceled)
{
Debug.Log("File downloaded.");
}
else
{
Debug.Log(task.Exception.ToString());
}
});
yield return null;
}
Keep in mind testing it in the editor may not work.
I am using the Plugin.Media (jamesmontemagno/MediaPlugin) plugin for Xamarin and I am having an issue with accepting a picture. When I take the second picture (the first picture works fine) and I click to accept the image the whole app crashes with no output as to the error. I have tried trapping the error but cannot find where it is occurring. I have as suggested removing the min SDK from Android manifest, but the crash still happens.
I have tried looking through the output in visual studio but it is always different. I am assuming the code works as it takes the image and gives me data back, to be clear, it only happens when trying to accept the second image.
private string GetTimestamp(DateTime value)
{
string timestamp = value.ToString("yyyyMMddHHmmssfff");
string filename = timestamp + ".jpg";
return filename;
}
public Command CaptureImage => new Command(TakePicture);
private async void TakePicture()
{
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
//Some message
return;
}
var file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "FoodSnap",
Name = GetTimestamp(DateTime.Now) //Gets a unique file name,
PhotoSize = Plugin.Media.Abstractions.PhotoSize.Custom,
CustomPhotoSize = 50
});
if (file == null)
return;
FilePath = file.Path;
}
I am completely stumped as to why this is happening. I am also having trouble refreshing my ViewModel when data changes in the page I am using to take the image. I can't help wondering if this has something to do with it.
I solved the problem by testing each line of code. Once I removed PhotoSize = Plugin.Media.Abstractions.PhotoSize.Custom I could take as many pictures as I need. I did use the Github information for the plugin.
I would be interested to know what I did wrong to cause the error. I would suggest that I have misunderstood the tutorial on Github.
I am new in Windows Phone application. In my application, when uploading files it is required to add file size limit not exceeding 50kb.
Code:
public sealed class OpenFileDialog
{
public string Filter { get; set; }
internal static object ShowDialog()
{
throw new NotImplementedException();
}
public static object DialogResult { get; set; }
public static string FileName { get; set; }
}
if (OpenFileDialog.ShowDialog() == System.Windows.Controls.DialogResult.OK)
{
FileStream fs = File.OpenRead(OpenFileDialog.FileName);
if (fs.Length > 51200)
{
MessageBox.Show("Image size must not exceed 50kb.");
return;
}
System.Windows.Controls.Image myImage = new System.Windows.Controls.Image();
myImage.Source = bmp;
}
but it show error,
Error:
namespace dialogresult doesn't exist in the namespace system.windows.controls(missing a assembly reference)
Anybody help me to solve this error?
You're attempting to use an enumeration that is part of the System.Windows.Forms namespace, and no such open file dialog exists in the Windows Phone 8 library. Without knowing more about your file access scenario, I will point out that your options would include:
Application Isolated Storage
Known Folders (WP 8.1 only including music, videos, photos, and SD card storage)
I'll point you to this general guide to accessing files programmatically which may take you to where you need to be specifically, but I should point out that since the most commonly accessible files on a phone device are rarely 50kb or less in size, we likely need more information about your use case.