How to set image.Source via async stream in an UWP application? - xaml

I want to set image.Source via async stream in an UWP application. Otherwise the image will flicker when switch to other image source.
My code is as below. And the log shows it works. Certainly I put 2 image files in the corresponding path before I test the demo code.
But in fact I did not see any picture shown, why?
Log:
111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\2.jpg
22222222222
33333333333333
4444444444444
The thread 0x6d38 has exited with code 0 (0x0).
The thread 0x6a34 has exited with code 0 (0x0).
111111111111 image file path = C:\Users\tomxu\AppData\Local\Packages\a0ca0192-f41a-43ca-a3eb-f128a29b00c6_1qkk468v8nmy0\LocalState\1.jpg
22222222222
33333333333333
4444444444444
Code:
private async void setImageSource(string imageFilePath)
{
StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);
Debug.WriteLine("111111111111 image file path = " + imageFilePath);
Stream fileStream = await sFile.OpenStreamForReadAsync();
Debug.WriteLine("22222222222");
InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream();
Debug.WriteLine("33333333333333");
await fileStream.CopyToAsync(ras.AsStreamForRead());
Debug.WriteLine("4444444444444");
BitmapImage bi = new BitmapImage();
bi.SetSource(ras);
image1.Source = bi;
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
string fullFolder = ApplicationData.Current.LocalFolder.Path;
if (count % 2 == 1)
{
setImageSource(fullFolder + #"\1.jpg");
//image1.Source = new BitmapImage(new Uri(#"ms-appx:///Assets/1.jpg"));
}
else
{
setImageSource(fullFolder + #"\2.jpg");
//image1.Source = new BitmapImage(new Uri(#"ms-appx:///Assets/2.jpg"));
}
count++;
}

Here is an example of how I convert a base64 image string to a BitmapImage..
var ims = new InMemoryRandomAccessStream();
var bytes = Convert.FromBase64String(base64String);
var dataWriter = new DataWriter(ims);
dataWriter.WriteBytes(bytes);
await dataWriter.StoreAsync();
ims.Seek(0);
var img = new BitmapImage();
img.SetSource(ims);
ims.Dispose();
return img;
Try some of the things I'm doing there. Like I notice your code is not setting the seek of the InMemoryReadAccessStream

For your question, I have something to clarify with you.
Your pictures are always in the application data folder. If you want to show it at runtime by programming, the easy way is using the ms-appdata URI scheme to refer to files that come from the app's local, roaming, and temporary data folders. Then, you could use this URL to initialize the BitmapImage object. With this way, you don't need to manually manipulate the file stream.
private void setImageSource(int i)
{
BitmapImage bi = new BitmapImage(new Uri("ms-appdata:///local/"+i+".png"));
image1.Source = bi;
}
private int count = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
if (count % 2 == 1)
{
setImageSource(1);
}
else
{
setImageSource(2);
}
count++;
}
If you say you have to manipulate the file stream to initialize the BitmaImage, then please add some break points to debug your code. If you add break points to check the InMemoryRandomAccessStream after call CopyToAsync method, you will see that its size is 0. It meant that the file stream has not been wrote to it. To solve this issue, you need to set a buffer size for it. Note: you used ras.AsStreamForRead() method, it's incorrect. You're writing stream to it, so you need to call ras.AsStreamForWrite().
The code looks like the following:
private async void setImageSource(string imageFilePath)
{
StorageFile sFile = await StorageFile.GetFileFromPathAsync(imageFilePath);
using (Stream fileStream = await sFile.OpenStreamForReadAsync())
{
using (InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream())
{
await fileStream.CopyToAsync(ras.AsStreamForWrite((int)fileStream.Length));
ras.Seek(0);
BitmapImage bi = new BitmapImage();
bi.SetSource(ras);
img.Source = bi;
}
}
}
private int count = 0;
private void Button_Click(object sender, RoutedEventArgs e)
{
string fullFolder = ApplicationData.Current.LocalFolder.Path;
if (count % 2 == 1)
{
setImageSource(fullFolder + #"\1.jpg");
}
else
{
setImageSource(fullFolder + #"\2.jpg");
}
count++;
}
In addition, like #visc said, you need to call ras.Seek(0) method to reset the stream to beginning, else the image will not show there.

Related

UWP hangs when loading Rich Text document as embedded resource

I'm trying to include some rich text with my app, but the app hangs when trying to load the text.
// Here is the initiating call:
await aboutDialog.ShowAsync();
// This code hangs on the second line
private async void Page_Loaded(object sender, RoutedEventArgs e)
{
var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("XamlSandbox.cities.rtf");
myRichEditBox.Document.LoadFromStream(Windows.UI.Text.TextSetOptions.FormatRtf, stream.AsRandomAccessStream());
}
// This code works OK
private async void Page_Loaded(object sender, RoutedEventArgs e)
{
var picker = new Windows.Storage.Pickers.FileOpenPicker();
var file = await picker.PickSingleFileAsync();
var fileStream = await file.OpenAsync(FileAccessMode.Read);
myRichEditBox.Document.LoadFromStream(Windows.UI.Text.TextSetOptions.FormatRtf, fileStream);
}
I've tried loading the embedded resource into a memory stream and using that, but that hangs too. Any ideas?
Here is how to properly load the embedded resource in UWP:
var rtfUri = new Uri("ms-appx:///cities.rtf");
var file = await StorageFile.GetFileFromApplicationUriAsync(rtfUri);
var stream = file.OpenAsync(FileAccessMode.Read);
myRichEditBox.Document.LoadFromStream(Windows.UI.Text.TextSetOptions.FormatRtf, stream.GetResults());

how to send a pdf file through http-post

I need to send a PDF file through HTTP POST.
I'm sending it using a third party (nSoftware) dll.
But my question is, how to receive it at the server end and save it.
I tried it with HTTPlistener, but unable to do.
Can some one help me on this..
Thanks,
Maddy
I tried below..
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
listener = new HttpListener();
listener.Prefixes.Add("http://localhost:122/");
listener.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
listener.Start();
this.listenThread1 = new Thread(new ParameterizedThreadStart(startlistener));
listenThread1.Start();
}
private void startlistener(object s)
{
while (true)
{
ProcessRequest();
}
}
private void ProcessRequest()
{
var result = listener.BeginGetContext(ListenerCallback, listener);
result.AsyncWaitHandle.WaitOne();
}
private void ListenerCallback(IAsyncResult result)
{
var context = listener.EndGetContext(result);
Thread.Sleep(1000);
var data_text = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding).ReadToEnd();
var cleaned_data = System.Web.HttpUtility.UrlDecode(data_text);
byte[] bytes = new byte[1024 * 1024];
int size = 1024 * 1024;
context.Request.InputStream.Read(bytes, 0, size);
using (FileStream fsNew = new FileStream("E:\\temp\\test.pdf", FileMode.Create, FileAccess.Write))
{
fsNew.Write(bytes, 0, bytes.Length);
}
context.Response.StatusCode = 200;
context.Response.StatusDescription = "OK";
MessageBox.Show(cleaned_data);
context.Response.Close();
}
With this I'm able to save create a PDF but it's not opening, and also the data is something more than the actual in the original PDF (I think some headers of http).
I hope this makes sense...
Thanks,
Madhu

Save InkManager images to byte array

I'm new to win8 app programming but has been assigned to write a windows store app to capture customers' signature and save it to SQL Server. After some research I found a great tutorial
http://www.codeproject.com/Articles/416878/Metro-Paint which shows how to draw and save the image locally. My question is how do I use the InkManager class in the tutorial to save the image to byte arrays so that I can save the image to SQLServer? Thanks!
private async void btnSaveWritingAsImage_Click(object sender, RoutedEventArgs e)
{
if (MyInkManager.GetStrokes().Count > 0)
{
try
{
Windows.Storage.Pickers.FileSavePicker SavePicker = new Windows.Storage.Pickers.FileSavePicker();
SavePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.Desktop;
SavePicker.DefaultFileExtension = ".png";
SavePicker.FileTypeChoices.Add("PNG", new string[] { ".png" });
SavePicker.FileTypeChoices.Add("JPG", new string[] { ".jpg" });
StorageFile filesave = await SavePicker.PickSaveFileAsync();
IOutputStream ab = await filesave.OpenAsync(FileAccessMode.ReadWrite);
if (ab != null)
await MyInkManager.SaveAsync(ab);
}
catch (Exception)
{
var MsgDlg = new MessageDialog("Only handwriting can be saved as image.", "Error while saving");
MsgDlg.ShowAsync();
}
}
else
{
var MsgDlg = new MessageDialog("Only handwriting can be saved as image.", "Error while saving");
await MsgDlg.ShowAsync();
}
}
add: (IBuffer.ToArray() is defined in WindowsRuntimeBufferExtensions)
using System.Runtime.InteropServices.WindowsRuntime;
then just do:
var buffer = await FileIO.ReadBufferAsync(image);//replace ab instead of image
var bytes = buffer.ToArray();

Sharing video and photo in metro apps through share charm

i am trying to take a picture and video from within the app and trying to share it through share charm but i am having a problem doing that. After i take the pic ,the share charm says it has trouble sharing the image. This is my code .Can anybody please let me know what i am doing wrong.
namespace Temp
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class Page1 : Page
{
private StorageFile _photo; // Photo file to share
private StorageFile _video; // Video file to share
private async void OnCapturePhoto(object sender, TappedRoutedEventArgs e)
{
var camera = new CameraCaptureUI();
var file = await camera.CaptureFileAsync(CameraCaptureUIMode.Photo);
if (file != null)
{
_photo = file;
DataTransferManager.ShowShareUI();
}
}
private async void OnCaptureVideo(object sender, TappedRoutedEventArgs e)
{
var camera = new CameraCaptureUI();
camera.VideoSettings.Format = CameraCaptureUIVideoFormat.Wmv;
var file = await camera.CaptureFileAsync(CameraCaptureUIMode.Video);
if (file != null)
{
_video = file;
DataTransferManager.ShowShareUI();
}
}
void OnDataRequested(DataTransferManager sender, DataRequestedEventArgs args)
{
var request = args.Request;
if (_photo != null)
{
request.Data.Properties.Description = "Component photo";
var reference = Windows.Storage.Streams.RandomAccessStreamReference.CreateFromFile(_photo);
request.Data.Properties.Thumbnail = reference;
request.Data.SetBitmap(reference);
_photo = null;
}
else if (_video != null)
{
request.Data.Properties.Description = "Component video";
List<StorageFile> items = new List<StorageFile>();
items.Add(_video);
request.Data.SetStorageItems(items);
_video = null;
}
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
DataTransferManager.GetForCurrentView().DataRequested += OnDataRequested;
}
}
In order for your app to share, you must set the Title of the DataPackagePropertySet and at least one of the "SetXXX" methods. If you do not, you'll see the following message when trying to share "There was a problem with the data from ."
So add request.Data.Properties.Title = "Title_of_photo_or_video"; in OnDataRequested event.

C# Web Cam with Remoting

My project is about Remoting and i want to add a webcam component to it. Here it goes: I have 3 project in my solution... Client, Server, Remote.dll. In Remote.dll is a common class which has methods works in server machine. When i call these methods from Client it executes in server side. So now my question is i put the code of Webcam in remote.dll and it has an event called "video_NewFrame" which it works everytime when webcam catch an image. But i cant reach to the images from my Client side because when code drops to this event it executes infinitely
and my timer in Client side doesnt work as well. I tried to assing image to my global variable but whenever code goes to client and comes to Remote.dll again my variable is null...
How can i reach simultaneously captured images from my client? here is my code:
(i use AForge framework for webcam)
private bool DeviceExist = true;
private FilterInfoCollection videoDevices;
private VideoCaptureDevice videoSource = null;
public bool WebCamStart(int DeviceIndex)
{
if (DeviceExist)
{
videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
//string myDevice = videoDevices[0].Name;
videoSource = new VideoCaptureDevice(videoDevices[0].MonikerString);
videoSource.NewFrame += new NewFrameEventHandler(video_NewFrame);
CloseVideoSource();
videoSource.DesiredFrameSize = new Size(640, 480);
//videoSource.DesiredFrameRate = 10;
videoSource.Start();
return true;
}
else return false;
}
public Bitmap lastImg;
private void video_NewFrame(object sender, NewFrameEventArgs eventArgs)
{
Bitmap img = (Bitmap)eventArgs.Frame.Clone();
//in executes infinitely when execution comes here and i cant reach from Cliend side...
}
public string getFPS()
{
return videoSource.FramesReceived.ToString();
}
public void CloseVideoSource()
{
if (!(videoSource == null))
if (videoSource.IsRunning)
{
videoSource.SignalToStop();
videoSource.Stop();
videoSource = null;
}
}
public string getCamList()
{
string result = "No Device Found";
try
{
videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
//comboBox1.Items.Clear();
if (videoDevices.Count == 0)
throw new ApplicationException();
DeviceExist = true;
foreach (FilterInfo device in videoDevices)
{
//comboBox1.Items.Add(device.Name);
result = device.Name;
return result;
}
//comboBox1.SelectedIndex = 0; //make dafault to first cam
}
catch (ApplicationException)
{
DeviceExist = false;
//comboBox1.Items.Add("No capture device on your system");
return "No capture device on your system";
}
return result;
}
// and my client side...
private void timerWebCam_Tick(object sender, EventArgs e)
{
//lblFPS.Text ="Device Running... " + remObj.getFPS() + " FPS";
pictureBox1.Image = remObj.lastImg;
}