BitmapImage and Uri for local file (WinRT store app) - c#

I am attempting to display an image that lives on my c: drive. The code below shows how I handle two images: image 1 is local and image 2 is from the web.
Image 1 fails to display, image 2 works perfectly. Why does image 1 fail to display?
private void Button_Click(object sender, RoutedEventArgs e)
{
// Image 1 - lives on local disk
var uri = new Uri(#"C:\Users\Frank\Pictures\MindMap.jpg", UriKind.Relative);
BitmapImage img = new BitmapImage(uri);
testImage.Source = img;
// Image 2 - image lives on web
var uri2 = new Uri("http://www.mommyish.com/wp-content/uploads/2013/05/GwynethPaltrow.jpg");
BitmapImage img2 = new BitmapImage(uri2);
testImage2.Source = img2;
}

You can't do this. Because app have limited access to the device/computer. This can be understand from this - for accessing Pictures library photos you have to add the capability to your app explicitly. You can understand this - as for security reasons too.
Suppose it has been displayed correctly but after some days someone has deleted it. then what happen to your app. It will crash. Or you can say app become dependent on the device to work.
So it is better that you understand the domain of an app and resources and capabilities of an app that is can use.
So first add image to your YourAppFoder then access it.

Related

c# WPF URI syntax

I am just learning c# and have been struggling to work with URIs in WPF. I've googled around a fair bit but not having much luck.
Essentially I'm trying to have a BitmapImage object stored as a property in a Car object. I then want to display the BitmapImage in an Image control on a WPF form.
The app is a simple app (it's for a Uni assignment), so no database, etc.
I have two methods of doing this. The first is that I'm preloading Car data from a text file, including the filename of the JPG I want to load. I have included the JPG in a directory called Files which is off the main directory where my source code and class files are. I have set the JPG file to 'Content' and 'Always copy'. When I run a Debug, it copies the Files directory and the JPG to the debug\bin directory.
My code creates a BitmapImage by referring to the JPG using a URI as follows;
BitmapImage myImage = new BitmapImage (new Uri("Files/" + Car.Imagefilename, UriKind.Relative);
Car.Image = myImage;
ImageControl.Source = myImage;
If I step through this code in the debugger, it sometimes works and displays the image, but most of the time it doesn't.
My second method is when a user creates a new Car. This method always works. In this one, I use a file dialog box (dlg) to select the image and use an absolute path.
BitmapImage myImage = new BitmapImage (new Uri(dlg.Filename, UriKind.Absolute);
Car.Image = myImage;
ImageControl.Source = myImage;
So....I can't work out why the first method doesn't work. I think it's got something to do with the relative reference, but I can't work out how to syntax that properly to work. I've tried using "pack:,,,", I've tried adding "component", I've tried an '#' before the "pack". I can't seem to find something that explains this simply.
Apologies if this is straight forward but it's doing my head in! Appreciate any pointers.
If the image files are located in a "Files" folder of your Visual Studio project, you should set their Build Action to Resource (and Copy to Output Directory to Do not copy), and load them by a Resource File Pack URI:
var image = new BitmapImage(new Uri("pack://application:,,,/Files/" + Car.Imagefilename));
Car.Image = image;
ImageControl.Source = image;
There is no need to copy the files anywhere. Images are loaded directly from the assembly.
First try to load the image file using its absolute path. For example if the images are stored in c:\projects\yourproject\files, then try using something like
BitmapImage myImage = new BitmapImage (new Uri("c:/projects/yourproject/files/carname.jpg", UriKind.Absolute);
If it works, what you are facing is an path calculation issue.
At this point you may either calculate the Absolute with reference to your executable using AppDomain.CurrentDomain.BaseDirectory at runtime or use App.Config to store the path and reference it from there.
Cheers

C# - Set (hundreds of) StorageFiles as BitmapImages (Without Stream)

I'm trying to get all the photos from the device's pictures library and show then on the app using a <GridView/> with an <Image/> inside it's item template, but I didn't find a way to do that without issues.
I need to create BitmapImages from the StorageFiles that I get.
First I tried creating the BitmapImages and setting the UriSource as new Uris with the files paths, like this:
var picsLib = await KnownFolders.PicturesLibrary.GetFilesAsync(CommonFileQuery.OrderByDate);
var picsList = new List<BitmapImage>();
foreach (StorageFile pic in picsLib)
{
var imgSrc = new BitmapImage();
imgSrc.UriSource = new Uri(pic.Path, UriKind.Absolute);
picsList.Add(imgSrc);
}
PhotosView.ItemsSource = picsList;
But the images doesn't show up.
Right after, I tried using streams:
var imgSrc = new BitmapImage();
var picStream = await pic.OpenReadAsync();
imgSrc.SetSource(picStream);
picsList.Add(imgSrc);
Of course, I got System.OutOfMemoryException.
Next, I tried using thumbnails:
var imgSrc = new BitmapImage();
var picThumb = await pic.GetThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.PicturesView,
200, Windows.Storage.FileProperties.ThumbnailOptions.ResizeThumbnail);
imgSrc.SetSource(picThumb);
picsList.Add(imgSrc);
But I realized that it's just like the stream, OutOfMemory again. If I limit it to only get the thumbnails of 10 or 20 images, it works nice, but I really need to show all the photos.
XAML isn't the problem as it does the job fine when I limit the number of images to load.
The app is meant to be used by anyone who download it from the Windows Phone Store when finished, so the size of the images vary, as the pictures library of Windows Phone devices contains almost any photos stored on the user's phone, including photos from the device's camera, saved images, etc.
There is absolutely no way to ever guarantee that you won't run out of memory with any of the above approaches. And the reality is that unless you are resizing the images on the fly to a standard size, you will never really control how much memory you are using, even for just the visible images.
You MUST make the containing grid virtualized so that the byte array's are only allocated for the images that are actually visible to the user.
Yes, there will be some lag on most systems as you scroll as byte arrays are discarded and created, but that is the price you pay for being able to view them 'all'.
All of that being said, here is a blog to help get you started.

BitmapSource to point to local file

What's the best pattern to implement a local cache for a Metro Style App so that the images can be cached in the background while the app is being used on-line and to serve images when the App goes offline?
How do we set a BitmapSource to a local file upon discovering the lack of internet access? using new Uri(localpath, UriKind.Absolute) doesn't work.
Are the images already downloaded? If so, are they in the "Local" folder?
If so, you can build a BitmapImage from the path like this
var m_Image = new BitmapImage(new Uri("ms-appdata:///local/" + ImageFileName));
EDIT
If your file is stored in the package as a "never had access and can't download anything" standby, the Uri would be something like
var m_Image = new BitmapImage(new Uri("ms-appx:///Assets/" + FallBackImageFileName));

Does WriteableBitmap has new features in Silverlight 4?

and if someone could give me an example on how to use it, with a stream? (not sure how that works) I know how to create a BitmapImage from an URI now I need to convert this image to a WriteableBitmap, but I get a null exception error with something like this:
BitmapImage image = new BitmapImage(new Uri("http://www.example.com/example.png"));
WriteableBitmap newImage = new WriteableBitmap(image);
In short: Nope, there are no new features in Silverlight 4. The WriteableBitmapEx tries to compensate the missing functionality.
Regarding your real problem:
You should add a handler to the BitmapImage.ImageFailed event to see if there's an error when the image should be downloaded. And you you should create the WriteableBitmap in the ImageOpened event handler.
var image = new BitmapImage(new Uri("http://www.example.com/example.png"));
WriteableBitmap newImage = null;
image.ImageOpened += (s, e) => newImage = new WriteableBitmap(image);
Please also note that cross-domain references are permitted. See the MSDN page for details. You should put the image into the Web Project's ClientBin folder and use a relative path instead.
As an alternative you can also compile the image into the assembly as resource and load it from there. The WriteableBitmapEx has an extension method to make this task a bit easier. But keep in mind that this blows the assembly size up and the initial XAP loading time will increase.
// Load an image from the calling Assembly's resources only by passing the relative path
var writeableBmp = new WriteableBitmap(0, 0).FromResource("example.png");

convert bitmap to image c# [duplicate]

this is how my code look now:
System.Drawing.Image objImage = System.Drawing.Image.FromFile(Server.MapPath("aaa.jpg"));
int height = objImage.Height;
int width = objImage.Width;
System.Drawing.Bitmap bitmapimage = new System.Drawing.Bitmap(objImage, width, height);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmapimage);
System.Drawing.Image bitmap2 = (System.Drawing.Image)Bitmap.FromFile(Server.MapPath("sem.png"));
g.DrawImage(bitmap2, (objImage.Width - bitmap2.Width) / 2, (objImage.Height - bitmap2.Height) / 2);
MemoryStream stream = new MemoryStream();
bitmapimage.Save(stream, ImageFormat.Jpeg);
String saveImagePath = Server.MapPath("ImagesMerge/") + "aaa.jpg";
bitmapimage.Save(saveImagePath);
imgBig.ImageUrl = saveImagePath;
The problem I have now is that the image is not displayed in browser, I don't understand why .
like jmaglasang said, I would suggest to you to use an ashx file and if you don't need to keep the image, just send the image stream directly to the http without saving it on the disk
so you only need to do something like
<img src="Handler.ashx?action=merge&image1=blah.jpg&image2=bloh.jpg">
look at this code for an example of how to send an image made in memory that does not exist on the drive
Bitmap is a subclass of Image, so there no need to convert Bitmap to Image. It already is...
Probably because saveImagePath will be a local path (such as c:\somepath\aaa.jpg) that is not reachable from the browser. You probably want to set the ImageUrl = "ImagesMerge/aaa.jpg" instead.
You can also try:
imgBig.ImageUrl = ResolveUrl(saveImagePath);
EDIT:
If saveImagePath is under the WebApplication Directory, doing some modifications on the directory structure i.e. modifying files, deleting and creating can cause the application pool to recycle, and once it reaches the maximum recycle count the application pool will be stopped causing "Server unavailable" error.
I would suggests to add/save/modify images on a separate directory (not under the Apps Directory) then create a Handler(ASHX) that will read the images, just an advice though.
MapPath will give you a physycal address, not a virtual address which is what the browser needs to get to the image.
You might be forgetting to set the Response.Headers. Check out the following example that shows how to create bar chart images and then display it on the screen:
http://www.highoncoding.com/Articles/399_Creating_Bar_Chart_Using__NET_Graphics_API.aspx

Categories