In my application I have a data entry view which I'd also like to give the user the option to store a photograph. Currently, using the tutorial at http://msdn.microsoft.com/en-US/library/windowsphone/develop/hh394006(v=vs.105).aspx, I've got a button which lets me take the photo, and can display it back properly at the bottom of the view.
However, I'd like this photo to be saved as part of the record. I thought it would be simple to save the location of the file as a string(I can access this by using PhotoResultObject.OriginalFileName), then display the photo again by using a URI like in my code here. This is inside the cameraCaptureTask_Completed method, e is a PhotoResult object.
string imageLoc = e.OriginalFileName;
Uri imageUri = new Uri(imageLoc, UriKind.RelativeOrAbsolute);
StreamResourceInfo resourceInfo = Application.GetResourceStream(imageUri);
BitmapImage bmp = new BitmapImage();
bmp.SetSource(resourceInfo.Stream);
myImage.Source = bmp;
However, this gives me an Argument exception, or various other exceptions when I move things around. I'm pretty new to c# so I'm really certain what's going on.
I reckon it's something to do with trying to access the photo straight from the phone memory, but I haven't found any other clear ways to store photos which will stay accessible inside the app.
Any tips on where I'm going wrong or how to accomplish my aim would be appreciated greatly!
Related
I'm writing a WinForms application. I created a Google Doc template file that contains placeholders like {{name}} for various text elements. I can successfully make a copy of this document and use the BatchUpdateDocumentRequest to modify them just fine.
However, I also have an embedded image in the document. I can obtain the objectId for this image just fine. I either want to replace this image with another or remove it from my template and then append my new image to the end of the document. In both cases, the InsertInlineImage or ReplaceImage classes require a URI of the image to insert or replace with. This is where I have an issue.
The image itself has been captured from a control on the WinForms. Its actually a chart. I've saved the image in PNG format since I know that is one of the formats supported by Google drive/docs. I figured in order to use it in the batch update, I would need to upload it first, so I did and got its file id and webcontentlink back in the response.
I'm not locked into any particular way of doing this. I originally tried creating an HTML file, uploading but then it would strip the image from it, so became useless, so I switched gears to using a Google Doc as my template and just try to replace elements in it instead. This went well until I got to the image.
Essentially no matter what I try to specify as the URI, it says the file in not in a supported format.
As far as I can tell, Google expects the URI to actually end in .png or be a real link versus a download URL you'd get from Google Drive.
Here is an example of the code I'm using to attempt to replace the image. The strImageObjectId is the objectId of the Embedded Object image in the template document copy that I want to replace. The Uri is what Google needs to pull the new image from. I'm happy to pull it from my local computer or Google Drive if only I could get it to accept it somehow.
BatchUpdateDocumentRequest batchUpdateRequest = new BatchUpdateDocumentRequest {
Requests = new List<Google.Apis.Docs.v1.Data.Request>()
};
request = new Google.Apis.Docs.v1.Data.Request {
ReplaceImage = new ReplaceImageRequest() {
ImageObjectId = strImageObjectId,
Uri = strChartWebContentLink
}
};
batchUpdateRequest.Requests.Add(request);
DocumentsResource.BatchUpdateRequest updateRequest =
sDocsService.Documents.BatchUpdate(batchUpdateRequest, strCopyFileId);
BatchUpdateDocumentResponse updateResponse = updateRequest.Execute();
I'm happy to use whatever method will get me to a point where I an end up with a Google Doc on Google Drive that was based on a template in which I can replace various text elements, but most importantly add/replace an image.
Thanks so much for the advice.
I got to the point were I believe I was specifying the URI correctly, but then I started getting an access forbidden error instead.
I didn't have time to hunt this one down, so I went back to creating an HTML template with my image, uploading as a Google Doc, exporting to PDF, and then uploading as a PDF. This ended up working because originally I was using a BMP as the file format and that is not supported by Google Docs, so I changed to a PNG instead and it worked just fine.
I think Google Docs needs to add the ability to add an image using a MemoryStream or some other programmatic base64 resource instead of purely being based on URIs and running into temporary upload or permission issues.
Hey I'm doing the same thing with you,
and I got this, by modify the download link format.
from this:
https://docs.google.com/uc?export=download&id={{YOUR GDRIVE IMAGE
ID}
to this
https://docs.google.com/uc?export=view&id={{YOUR GDRIVE IMAGE ID}
e.g :
uri: "https://docs.google.com/uc?export=view&id=1cjgyHqtYSgS0CBT4x-9eQIHRzOIfGgv-"
but the image should be set for public privilege
I want to let a user load an image from their gallery:
var imageIntent = new Intent();
imageIntent.SetType("image/*");
imageIntent.SetAction(Intent.ActionGetContent);
StartActivityForResult(Intent.CreateChooser(imageIntent, "Select photo"), REQUESTCODE);
This works fine: I can use the image in that activity. But I want to store the URI in the database so the image is associated with the object. I use:
_recipeImage.SetImageURI(data.Data);
model.ImageUrl = data.Data.ToString();
_recipeImage is just an image view I'm using to see if I actually got the image correctly for now.
When I save my model to the database I get a string that looks something like:
content://com.android.providers.downloads.documents/document/22
When the user opens this item later the image should load so I parse the string to a Uri. I try and set the image URI as I did before, but no image gets shown.
var uri = Android.Net.Uri.Parse(imageUrl);
imageView.SetImageURI(uri);
Is there a better/working way to do this?
I think you want to load image directly use URL, it's easier to use some third-party lib, for example Picasso.
Since it's a java lib, you can use Binding Library to use it in Xamarin.
After adding this lib into your project, you can simply code like this:
Picasso.With(this).Load(imageUrl).Into(imageView);
I have a Windows Store app written in C# that works with photos. I want to show the last photo the user selected in the app in the medium size live tile (150 x 150). I am using the code below to do it. When I run the app I don't get any errors, but I don't see the selected photo in the live tile either. I know that I am doing at least some things right. I say this because if the user hasn't selected a photo yet, then I show a test image and I do see that image in the tile. But the test image comes from the app package using the ms-appx protocol, not from the app storage area.
I found a few SO posts on the subject but they are all for Windows Phone. I looked at the KnownFolders list for Windows Store app files, but nothing seemed to map to the SharedContent folder required for files meant for live tile use in Windows Phone. What is wrong with my code?
Note, the vvm.ActiveVideomark.GetThumbnail() call simply retrieves a bitmap as a WriteableBitmap object. As you can see in the code, I am resizing the image to the size required by the Medium live tile (150 x 150). ToJpegFileAsync() is an extension method that encodes a WriteableBitmap object to jpeg bytes and then writes those bytes to a file using the given file name. Both of these calls are well-tested and are not the source of the problem as far as I know.
TileUpdateManager.CreateTileUpdaterForApplication().Clear();
TileUpdateManager.CreateTileUpdaterForApplication().EnableNotificationQueue(true);
var tileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquare150x150Image);
var tileImage = tileXml.GetElementsByTagName("image")[0] as XmlElement;
// Got a current photo?
if (vvm.ActiveVideomark == null)
// No, just show the regular logo image.
tileImage.SetAttribute("src", "ms-appx:///Assets/Logo.scale-100.png");
else
{
// Resize it to the correct size.
WriteableBitmap wbm = await vvm.ActiveVideomark.GetThumbnail();
WriteableBitmap wbm2 = wbm.Resize(150, 150, WriteableBitmapExtensions.Interpolation.Bilinear);
// Write it to a file so we can pass it to the Live Tile.
string jpegFilename = "LiveTile1.jpg";
StorageFile jpegFile = await wbm2.ToJpegFileAsync(jpegFilename);
// Yes, show the selected image.
tileImage.SetAttribute("src", jpegFile.Path);
}
The src attribute must contain a URI with ms-appx:///, ms-appdata:///local, or http[s]:// schemes. The StorageFile.Path property, as you're using with jpegFile.Path, is a local filesystem pathmame like c:\users\Robert\AppData... which won't be valid. So create your tile images in local app data, and then use ms-appdata:///local/ to refer to them in tile payloads.
I'm trying to make a Windows Phone 7 app that will save some images off the web, I have no idea where I can or if I can save images from the web to the phone.
What can I do to save images?
You can download them using WebClient or WebRequest to get the raw bytes.
You can then save to isolated storage fairly easily - but I don't believe you can save in any location seen by the Picture hub, if that's what you were aiming for. (I can't see anything in the Microsoft.Phone.Tasks namespace which would be relevant. There are tasks to capture the camera of choose a photo, but not to save one.)
EDIT: Ooh, I've just found a way. You can use the MediaLibrary class and its SavePicture method... although that's in XNA, so I'd at least have concerns about it working from a Silverlight app. I know some bits of the XNA API do work from Silverlight, and some don't. Worth experimenting with.
On the phone, you can use HttbWebRequest (recommended to avoid UI impact) or WebClient per the project I posted here.
WebClient, HttpWebRequest and the UI Thread on Windows Phone 7
You can then take your stream and pass it into something of this form to write it to isolated storage.
private void PicToIsoStore(Stream pic) {
using (var isoStore = IsolatedStorageFile.GetUserStoreForApplication()) {
var bi = new BitmapImage();
bi.SetSource(pic);
var wb = new WriteableBitmap(bi);
using (var isoFileStream = isoStore.CreateFile("somepic.jpg")) {
var width = wb.PixelWidth;
var height = wb.PixelHeight;
Extensions.SaveJpeg(wb, isoFileStream, width, height, 0, 100);
}
}
}
Jon is correct you can also use MediaLibrary.SavePicture. Be aware that this would put the pics mixed in with the users photos in the Picture Hub.
This is as straight forward as
private void PicToMediaLibary(Stream pic) {
MediaLibrary lib = new MediaLibrary();
lib.SavePicture("blah", pic);
}
Storing it in isolated storage is basically your apps private file system.
Greetings all,
Thanks for reading and sharing any insights. I've created a new simple Windows Phone 7 application. I have two Image objects on the form I would like to update with various .png files. I have included the .png files into my project, and I believe I am building proper URi resources pointing to these files.
Uri myImage1URi = new Uri( strImage1, UriKind.RelativeOrAbsolute );
Uri myImage2URi = new Uri( strImage2, UriKind.RelativeOrAbsolute );
System.Windows.Media.Imaging.BitmapImage bi1 = new System.Windows.Media.Imaging.BitmapImage(myImage1URi);
System.Windows.Media.Imaging.BitmapImage bi2 = new System.Windows.Media.Imaging.BitmapImage(myImage2URi);
image1.Source = bi1;
image1.Stretch = Stretch.Fill;
image2.Source = bi2;
image2.Stretch = Stretch.Fill;
This alone is not accomplishing what I want (to update the images to the two from the URi's).
I know there is something a bit off going on (IE: I am doing something dumb) in that all of the BitmapImage class descriptions mention that I have to do a .BeginInit() before I work with the BitmapImage object, and a .EndInit() call afterwards. These method calls don't work for me, so I know something is amiss....
Or maybe I am competely off base and I simply need a way to tell my main window to repaint itself? That thought has occurred to me as well.
Thanks again.
The following will load an image that is in the appropriate path and is set as having a build action content.
myImg.Source = new BitmapImage(new Uri("/images/filename.png", UriKind.Relative));
It assumes XAML on the page like:
<Image x:Name="myImg" />
This seems very similar to what you're doing. Simplify what you're doing ot get it working.
Does it work with just using one image?
Is the path in strImageN a valid path?
Do the image files have their build action set to Content?