I'm currently trying to download an image, save it to a folder within the LocalStorage container, and then use it as tile. However, everytime I try to do so, the tile is just blank. All there is the name of the app and a title.
I'm unable to test if this occurs because the image isn't saved correctly or because the URI is incorrect.
var localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
var channelFolder = await localFolder.CreateFolderAsync(_currentChannel.Name, CreationCollisionOption.OpenIfExists);
var thumbnail = RandomAccessStreamReference.CreateFromUri(new Uri(_currentChannel.Logo));
var remoteFile = await StorageFile.CreateStreamedFileFromUriAsync("profilePicture.jpeg", new Uri(_currentChannel.Logo), thumbnail);
await remoteFile.CopyAsync(channelFolder, "profilePicture.jpeg", NameCollisionOption.ReplaceExisting);
string tileXmlString = "<tile>"
+ "<visual>"
+ "<binding template='TileSquareText04'>"
+ "<image id='1' src='ms-appdata:///local/" +_currentChannel.Name + "/profilePicture.jpeg'>" + "</image>"
+ "<text id='1'>" + "Latest Image" + "</text>"
+ "</binding>"
+ "</visual>"
+ "</tile>";
Windows.Data.Xml.Dom.XmlDocument tileDOM = new Windows.Data.Xml.Dom.XmlDocument();
tileDOM.LoadXml(tileXmlString);
TileNotification tile = new TileNotification(tileDOM);
TileUpdateManager.CreateTileUpdaterForApplication().Update(tile);
_currentChannel.Logo is a string with a url to a jpeg image.
I end up with a transparent tile every time.
After the code runs, you should be able to see if the image is in your \AppData\Microsoft\Packages\\Local folder. If not, then there's a problem downloading it. If it's there, make sure it's both 200KB or less and 1024px or smaller in both dimensions. Those are the limits for tile images which, if exceeded, will cause the image to not appear. In that case you'll need to resample the image.
You should also test your tile updating code separately with a known small image, e.g. something in the package using an ms-appx URI or a remote image with an http URI. If those don't work either, then your updating code is suspect. Check for any errors or exceptions from that section of your code.
Related
I use the following code to scale and crop all images in a folder.
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(file);
string fileExtension = Path.GetExtension(file);
string filePath = Path.GetDirectoryName(file);
string newFileName = string.Empty;
long fileSize = new FileInfo(file).Length;
if (fileSize > fileSizeLimit)
{
string tempFile = System.IO.Path.GetTempFileName();
File.Copy(file, tempFile, true);
Bitmap sourceImage = (Bitmap)System.Drawing.Image.FromFile(tempFile);
System.Drawing.Image imgPhoto = ScaleCrop(sourceImage, sourceImage.Width / 4, sourceImage.Height / 4, AnchorPosition.Top);
Bitmap bitImage = new Bitmap(imgPhoto);
File.Delete(file);
newFileName = filePath + "\\" + fileNameWithoutExtension + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + "_" + CoilWarehouseProcessed + fileExtension;
bitImage.Save(newFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
imgPhoto.Dispose();
bitImage.Dispose();
}
If I run the application locally (in debug mode in VS2010) and point it to a network drive then all images are processed every time.
If I run it from a our local webserver the problem is that the app may process no images, it may process 5, it may process 1, it never does all of the images in a given folder, only ever some of them... then it hangs in the clients browser.
There are no events to view via the event log... the application does not crash or error in anyway... the fact that it will process an image proves it's not a permissions issue.
Any ideas why this is happening?
EDIT: Thanks to wazdev, but I ended up testing a less intrusive (and also don't like dependencies relying on 3rd party software) solution, and it all seems good so far... Basically I changed it so that when it copies the stream to produce a new image 'System.Drawing.Image imgPhoto = ...' to use a using statement to ensure that the 'temp' image is disposed of. I also moved the delete of the original (uncropped / unscaled image) file to be the last operation (In tests it has worked fine, only time will tell once more users come online and concurrency is tested):
string tempFile = System.IO.Path.GetTempFileName();
File.Copy(file, tempFile, true);
Bitmap sourceImage = (Bitmap)System.Drawing.Image.FromFile(tempFile);
System.Drawing.Image imgPhoto = ScaleCrop(sourceImage, sourceImage.Width / 4, sourceImage.Height / 4, AnchorPosition.Top);
Bitmap bitImage;
using (var bmpTemp = new Bitmap(imgPhoto))
{
bitImage = new Bitmap(bmpTemp);
}
newFileName = filePath + "\\" + fileNameWithoutExtension + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + "_" + CoilWarehouseProcessed + fileExtension;
bitImage.Save(newFileName, System.Drawing.Imaging.ImageFormat.Jpeg);
imgPhoto.Dispose();
bitImage.Dispose();
File.Delete(file);
EDIT2: It's been live now for a few days and i've tested it every day and it is working well.. Here's all that I did;
Basically inside the ScaleCrop() call there was a GC.Collect and a Wait For Pending Finalisers() call. I removed the wait for pending call and moved the GC.Collect() to after the File.Delete().
I've seen this behaviour in the past when RAM was exhausted resulting in paging to disk. I've found a great deal of success in utilising the ImageResizing.net libraries:
http://imageresizing.net/
I updated my code to use this library and have never looked back.
HTH
(I have no affiliation with imageresizing.net - I'm just a very happy user)
I have downloaded an image with the following code:
bool pageExists = false;
// Check if webpage exists
HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://image.tmdb.org/t/p/w780" + imagePath);
request.Method = WebRequestMethods.Http.Head;
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
pageExists = response.StatusCode == HttpStatusCode.OK;
}
// Download image
if (pageExists)
{
string localFilename = #"C:\Users\Giri\Desktop\giri" + id + ".jpg";
using (WebClient client = new WebClient())
{
client.DownloadFile("http://image.tmdb.org/t/p/w780" + imagePath, localFilename);
}
}
For now, I have just been saving this image on my Desktop.
My question is how do I go about storing this image in my WPF application programmatically within a resources folder or a folder I have generated myself? The images should persist in that the next time the application is run, the added images should remain.
Is there an accepted place I should be storing my images?
Thanks for your help.
Please use AppDomain.CurrentDomain.BaseDirectory. Which will give you the directory of your executable. Even in deployed code this should give you the right value. But other values like Environment.CurrentDirectory can give different value based on from where you are calling it etc.
See this question Best way to get application folder path
I am trying to save an image in an azure worker roles' file system.
This is my code :
BlobStream inputImage = inputBlob.OpenRead();
Stream inputStream = inputImage;
string inputPath = "F:\\approot\\input\\" + imageId; //Image id is 582
inputStream.Position = 0;
//save image to physicall file
var img = Image.FromStream(inputStream);
string imagePath = pInputPath + "\\" + pImageId + ".png";
img.Save(imagePath, ImageFormat.Png);
var xml = "";
This problem came all of the sudden, my application was working but suddenly it started crashing at this point.
I'm guessing that the issue is with the f drive. You'll find that, occasionally, e: and f: may change upon restart. Since you claimed that things were working, and then suddenly started crashing, I'm thinking that, if you rdp into your role instance, you'll find that approot is now on e: instead of f:.
There should be an environment variable, RoleRoot, that you can use for determining what drive your approot is on:
Environment.GetEnvironmentVariable("RoleRoot");
I have been attempting to use a saved image in IsolatedStorage within the new ShareMediaTask in Windows Phone 8. I am having issues getting an image path from IsolatedStorage. I have successfully used the ShareMediaTask from the result of CameraCaptureTask as exampled in http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207027(v=vs.105).aspx but I am unsure of how to get the path from IsolatedStorage in wp8.
I was attempting to retrieved an image path using something of the following:
//Combine the directory and file name
filePath = Path.Combine(IsolatedStoragePath, fileName);
Uri uri = new Uri(#"isostore:" + filePath, UriKind.Absolute);
_shareTask = new ShareMediaTask();
//_shareTask.FilePath = #"isostore:" + filePath;
_shareTask.FilePath = uri.ToString();
_shareTask.Show();
Not sure if I'm headed in the right direction or not with this, any advice, assistance, or references would be greatly appreciated! The only similiar link I've found uses xna which I must avoid for this application http://social.msdn.microsoft.com/Forums/en-US/wpdevelop/thread/56c91aa1-26ea-41f7-b5ac-035537419faf/ .
I think the best you can do is to save the photo do MediaLibrary, share it and the delete it immediately after sharing.
your idea i working But after save image we are not able delete image because WP OS not give permission to delete other app item
var mediaLibrary = new Microsoft.Xna.Framework.Media.MediaLibrary();
var location = mediaLibrary.SavePicture(tempJpeg + ".jpg", e.Result);
string Path = location.GetPath();
ShareMediaTask SMT = new ShareMediaTask();
SMT.FilePath = Path;
SMT.Show();
The App.xaml.cs page of my app contains the following method.
public static void SendLiveTileUpdate(Record rr)
{
string imageUristring = "ms-appdata:///local/" + rr.Id.ToString() + ".jpg";
XmlDocument wideTileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileWideImageAndText01);
XmlNodeList wideTileTextAttrib = wideTileXml.GetElementsByTagName("text");
wideTileTextAttrib[0].InnerText = rr.Name;
XmlNodeList wideTileImageAttrib = wideTileXml.GetElementsByTagName("image");
//((XmlElement)wideTileImageAttrib[0]).SetAttribute("src", "ms-appdata:///local/" + rr.Id.ToString() + ".jpg");
((XmlElement)wideTileImageAttrib[0]).SetAttribute("src", imageUristring);
((XmlElement)wideTileImageAttrib[0]).SetAttribute("alt", "Image");
//Wide tile Layout done
XmlDocument sqTileXml = TileUpdateManager.GetTemplateContent(TileTemplateType.TileSquareImage);
XmlNodeList sqTileImageAttrib = sqTileXml.GetElementsByTagName("image");
((XmlElement)sqTileImageAttrib[0]).SetAttribute("src", imageUristring);
((XmlElement)sqTileImageAttrib[0]).SetAttribute("alt", "Image");
IXmlNode node = wideTileXml.ImportNode(sqTileXml.GetElementsByTagName("binding").Item(0), true);
wideTileXml.GetElementsByTagName("visual").Item(0).AppendChild(node);
//Square tile set and added to wide tile xml
TileNotification tileNot = new TileNotification(wideTileXml);
tileNot.ExpirationTime = DateTime.Now.AddDays(5);
updater.Update(tileNot);
}
On the page there is also the global variable updater, which is used on page initialization to call EnableNotificationQueue(true) (then later to update the queue as shown).
The problem is that when this code is run it doesn't work. I have deduced that it is something to do with the images because when the image assignments are excluded the live tile updates with the value of rr.Id.ToString(), but included the tile is never updated. this images referenced by imageUristring are present in the apps local storage (and the name corresponds with the Id of the method parameter), yet it still does not work. The images in question are under 200KB, and are 1920x1080. (I think that they will be scaled to fit the tile?)
What am I doing wrong? How could I get the tile to update with the image stored in the local storage?
Your images must be <= 1024x1024. From http://msdn.microsoft.com/en-us/library/windows/apps/Hh781198.aspx:
Tile images must have dimensions less than or equal to 1024x1024
pixels, have a file size of less than or equal to 200 KB, and be of
type .png, .jpg, .jpeg, or .gif.