Load a picturebox from a WIA ImageFile? - c#

I've taken over a poorly designed project from a co-worker and am looking to load a picture box directly from the WIA command that just completed to take a picture from an attached USB camera.
The current implementation waits until the file has been written to disk, then displays it from there probably
re-reading the file from disk.
Item item = d.ExecuteCommand(WIA.CommandID.wiaCommandTakePicture);
WIA.ImageFile imagefile = item.Transfer(FormatID.wiaFormatJPEG) as WIA.ImageFile;
I tried casting an Image to the given picture box without success
picBox.Image = (Image)imageFile;

WIA.ImageFile is a COM object wrapper, not a System.Drawing.Image.
You'll have to mess with WIA.ImageFile Save method with temporary files or try in-memory solution as shown here:
http://www.pcreview.co.uk/forums/wia-imagefile-system-drawing-image-t2321026.html
var imageBytes = (byte[])image.FileData.get_BinaryData();
var ms = new MemoryStream(imageBytes);
var img = Image.FromStream(ms);

Related

Deleting image displayed in Windows Phone Image Control

I have the following code to display image in an Image control.
var stream = isolatedStorage.OpenFile(imageName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(stream);
imageControl.Source = bitmapImage;
I also want to give the user option to delete the image. I have the following code for it.
myImage.Source = null;
isolatedStorage.DeleteFile(imageName);
But this results in IsolatedStorageException with the message 'Unable to delete the file'.
I can't use stream source property of the bitmap or use Cache option, since Windows phone doesn't support them.
Any other workaround?
May be you need to close the fileStream before deleting the file.
Try
stream.Close()
or something like this before deleting the file
OR
If your isolatedStorage variable is of type IsolatedStorageFile then you can directly use
isolatedStorage.DeleteFile("yourfilename.ext");

C# / WinRT: How to save image to file

I'm an iOS developer learning Windows Store App development with no previous Microsoft technology experience.
I need to save an image to a file. I figured this would be easy, but I've been at it for a day and I've got nothing to show for it. Either this is extremely difficult in Windows, or I'm missing something due to ignorance of the platform / APIs.
The source of the image I need to save is Windows.UI.Xaml.Media.Imaging.RenderTargetBitmap. RenderTargetBitmap can return an image as either a source for Windows.UI.Xaml.Controls.Image or as a IBuffer.
I can verify that RenderTargetBitmap is rendering the image correctly. However, I have not been able to save the image to a file. I'd hoped that Image would have a Save() method, but it doesn't. So I figured I'd need to use the IBuffer somehow. I got close, I was able to save the buffer to disk, but it was unencoded, so I couldn't open it in anything.
So, next, I tried converting the buffer to a stream, encoding that into PNG with BitmapEncoder. That worked, but that left me with my PNG data in a IRandomAccessStream. I have no idea how to save a IRandomAccessStream to a file.
I tried 5-10 different convoluted approaches, such as going through type conversion hell to attempt to turn a IRandomAccessStream into an IBuffer so I could use .WriteAsync() on a file stream. I tried using a DataWriter on a file stream fed by a DataReader on my IRandomAccessStream but I ran into a type mismatch problem. Etc, etc.
So, how can I save my file? Here's what I got so far:
private async void saveButton_Click(object sender, RoutedEventArgs e)
{
//Create a new temporary image for saving
//Image tempImage = new Image();
//Create a render object
RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap();
//Render the app's display buffer
await renderTargetBitmap.RenderAsync(null);
//Set the temp image to the contents of the app's display buffer
//tempImage.Source = renderTargetBitmap;
//Create a new file picker, set the default name, and extenstion
FileSavePicker savePicker = new FileSavePicker();
savePicker.SuggestedFileName = "New LightTable.png";
savePicker.FileTypeChoices.Add("Image", new List<string>(){".png"});
//Get the file the user selected
StorageFile saveFile = await savePicker.PickSaveFileAsync();
//Only move on if the user actually selected a file
if (saveFile != null)
{
//Get a buffer of the pixels captured from the screen
Windows.Storage.Streams.IBuffer buffer = await renderTargetBitmap.GetPixelsAsync();
//Get a stream of the data in the buffer
System.IO.Stream stream = buffer.AsStream();
//Convert the stream into a IRandomAccessStream because I don't know what I'm doing.
Windows.Storage.Streams.IRandomAccessStream raStream = stream.AsRandomAccessStream();
//Attempt to encode the stream into a PNG
BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, raStream);
//Get a stream for the file the user selected
Windows.Storage.Streams.IRandomAccessStream fileStream = await saveFile.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
//FIND SOME WAY TO SAVE raStream TO fileStream
//Something like:
// await fileStream.WriteAsync(raStream.AsStreamForRead());
}
}
Either I'm just missing the very end: how to write my raStream to a file, or my approach is totally off.
I appreciate the help. Keep in mind I've only been developing with Microsoft tech for a week now. I have no .NET, Silverlight, or other MS tech experience. Saving an encoded image from a UIImage control on iOS is a single method call, so the shear complexity of the solution I'm circling makes me think I'm missing something really easy that I just don't know about.
You need to set the pixel data into the StorageFile stream. See http://basquang.wordpress.com/2013/09/26/windows-store-8-1-save-visual-element-to-bitmap-image-file/ for an example.

Loading Images in some directories via BitmapImage results in E_NETWORK_ERROR

I am new to Windows 8 development and Microsoft's technologies. I've done a lot of iOS development, but I've never touched Visual Studio, C#, etc before, so I am learning a lot (frameworks, IDEs, language) all at once. Forgive me if this is something simple, but I can't find an answer anywhere.
Note: I'm using Visual Studio Express 2013, C#, and Windows 8.1
For learning purposes I'm just trying to create an app that loads images, displays them on the screen, and allows the user to rotate, move, resize, and arrange them. I've got this working, except for one major bug that I can't figure out: When I load images from some directories everything works fine, when I load images from other directories I get E_NETWORK_ERROR and BitmapImage.ImageFailed. I can see no reason for this. I can actually take an image and put it in a directory and it will load, copy the same image to another directory, and it wont load.
Here's the code:
private async void addImageButton_Click(object sender, RoutedEventArgs e)
{
Windows.Storage.Pickers.FileOpenPicker filePicker = new Windows.Storage.Pickers.FileOpenPicker();
filePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
filePicker.FileTypeFilter.Add(".jpg");
filePicker.FileTypeFilter.Add(".png");
filePicker.FileTypeFilter.Add(".bmp");
filePicker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
Windows.Storage.StorageFile imageFile = await filePicker.PickSingleFileAsync();
if (imageFile != null)
{
System.Diagnostics.Debug.WriteLine(imageFile.Path);
Windows.UI.Xaml.Media.Imaging.BitmapImage bitmap = new Windows.UI.Xaml.Media.Imaging.BitmapImage(new Uri(imageFile.Path));
System.Diagnostics.Debug.WriteLine(bitmap.UriSource);
bitmap.CreateOptions = Windows.UI.Xaml.Media.Imaging.BitmapCreateOptions.None;
Image img = new Image();
img.Source = bitmap;
this.theCanvas.Children.Add(img);
}
}
This seems to work great with image files from some directories, and doesn't work at all with others. For example: in my Pictures library I have a "Camera Roll" directory that the Windows 8 camera app saves to, and I also have my Steam screenshots directory. If I try to open images in my Steam screenshots directory it works fine; however, if I try to load images in the Camera Roll directory it fails with E_NETWORK_ERROR. If I copy images from the Camera Roll directory to the Steam Screenshots directory I can open them.
Can anyone point out what's wrong? I'm starting to think this isn't a code problem so much as a security / capabilities / declarations type thing. Is there something I need to declare or request to get unfettered access to the filesystem? Do I need to form my URI differently or something?
EDIT: Here is some output from the debug statements showing the paths and URIs:
Loaded fine:
C:\Program Files (x86)\Steam\userdata\24321739\760\remote\72850\screenshots\2013-12-04_00001.jpg
file:///C:/Program Files (x86)/Steam/userdata/24321739/760/remote/72850/screenshots/2013-12-04_00001.jpg
Resulted in E_NETWORK_ERROR
C:\Users\Adam\Pictures\Camera Roll\WIN_20131023_194718.JPG
file:///C:/Users/Adam/Pictures/Camera Roll/WIN_20131023_194718.JPG
Weird issue, but I think that you should modify your code a bit as this answer here suggests. Instead of using the file path, try to create an image via loading a stream.
Just to be sure, does your app have the permission for accessing files in the user libraries?
I fixed this, but I'm not 100% sure I understand how/why the solution I arrived at resolved my problem.
I fixed the problem by switching to using a Windows.Storage.Streams.IRandomAccessStream to read the file into the BitmapImage Source:
private async void addImageButton_Click(object sender, RoutedEventArgs e)
{
Windows.Storage.Pickers.FileOpenPicker filePicker = new Windows.Storage.Pickers.FileOpenPicker();
filePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
filePicker.FileTypeFilter.Add(".jpg");
filePicker.FileTypeFilter.Add(".png");
filePicker.FileTypeFilter.Add(".bmp");
filePicker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
Windows.Storage.StorageFile imageFile = await filePicker.PickSingleFileAsync();
if (imageFile != null)
{
Windows.UI.Xaml.Media.Imaging.BitmapImage bitmap = new Windows.UI.Xaml.Media.Imaging.BitmapImage();
Windows.Storage.Streams.IRandomAccessStream stream = await imageFile.OpenAsync(Windows.Storage.FileAccessMode.Read);
Image newImage = new Image();
bitmap.SetSource(stream);
newImage.Source = bitmap;
newImage.Height = 250;
newImage.Stretch = Stretch.UniformToFill;
newImage.ManipulationMode = ManipulationModes.All;
newImage.ManipulationDelta += TestImage_ManipulationDelta;
this.theCanvas.Children.Add(newImage);
}
}
This resolved the issue and I can now load image files from any arbitrary location. However, I'm not 100% why this resolved the problem. I think it has something to do with async. I think that the way I was doing it before would somehow result in the BitmapImage or Image not containing the actual image data at display time. What I think this solution did was make the display code wait until we'd actually taken time to load the image. Even though this is solved, if a

Changing Image Source Dynamically

I'm new to WPF and am having some trouble loading an image from a file that has been modified.
I have an image control called Image1, which I load in the following manner
string fileName = "C:\\Users\\..\\myImage.jpg"
BitmapImage tmp = new BitmapImage();
tmp.BeginInit();
tmp.UriSource = new Uri(#fileName, UriKind.Absolute);
tmp.CacheOption = BitmapCacheOption.OnLoad;
tmp.EndInit();
Image1.Source = tmp;
This works the first time, but then I run a function which overwrites myImage.jpg, at which point I call this code again, expecting Image1 to update. However, the GUI remains unchanged. Does it have something to do with the cacheoption? I need that so that I can overwrite the file.
First of all when we want a modified image file,then we have to save first the image
file by calling save method in that function where u r overwriting.
when saving also do something cleverly, like create copy of that original image file then modify that copied file,then save the file,so that when u access again that image file,u can get that modified file + original file.Because sometimes the original file will modified.

Saving a modified image to the original file using GDI+

I was loading a Bitmap Image from a File. When I tried to save the Image to another file I got the following error "A generic error occurred in GDI+". I believe this is because the file is locked by the image object.
Ok so tried calling the Image.Clone function. This still locks the file.
hmm. Next I try loading a Bitmap Image from a FileStream and load the image into memory so GDI+ doesn't lock the file. This works great except I need to generate thumbnails using Image.GetThumbnailImage method it throws an out of memory exception. Apparently I need to keep the stream open to stop this exception but if I keep the stream open then the file remains locked.
So no good with that method. In the end I created a copy of the file. So now I have 2 versions of the file. 1 I can lock and manipulate in my c# program. This other original file remains unlocked to which I can save modifications to. This has the bonus of allowing me to revert changes even after saving them because I'm manipulating the copy of the file which cant change.
Surely there is a better way of achieving this without having to have 2 versions of the image file. Any ideas?
Well if you're looking for other ways to do what you're asking, I reckon it should work to create a MemoryStream, and read out the FileStream to it, and load the Image from that stream...
var stream = new FileStream("original-image", FileMode.Open);
var bufr = new byte[stream.Length];
stream.Read(bufr, 0, (int)stream.Length);
stream.Dispose();
var memstream = new MemoryStream(bufr);
var image = Image.FromStream(memstream);
Or something prettier to that extent.
Whether or not that's the way you should go about solving that problem, I don't know. :)
I've had a similar problem and wound up fixing it like this.
I have since found an alternative method to clone the image without locking the file. Bob Powell has it all plus more GDI resources.
//open the file
Image i = Image.FromFile(path);
//create temporary
Image t=new Bitmap(i.Width,i.Height);
//get graphics
Graphics g=Graphics.FromImage(t);
//copy original
g.DrawImage(i,0,0);
//close original
i.Dispose();
//Can now save
t.Save(path)
I had a similar problem. But I knew, that I will save the image as a bitmap-file. So I did this:
public void SaveHeightmap(string path)
{
if (File.Exists(path))
{
Bitmap bitmap = new Bitmap(image); //create bitmap from image
image.Dispose(); //delete image, so the file
bitmap.Save(path); //save bitmap
image = (Image) bitmap; //recreate image from bitmap
}
else
//...
}
Sure, thats not the best way, but its working :-)

Categories

Resources