Save PDF to file - c#

I am working on a Windows Store app for Windows 8.1, and I can't find anything that addresses what I need to do. I am trying to save an image of a pdf page to my local app data storage. I have the following:
private async void GetFirstPage()
{
// Retrieve file from FutureAccessList
StorageFile file = await Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.GetFileAsync(token);
// Truncate last 4 chars; ex: '.pdf'
FileName = file.Name.Substring(0, file.Name.Length - 4);
// Get access to pdf functionality from file
PdfDocument doc = await PdfDocument.LoadFromFileAsync(file);
// Get a copy of the first page
PdfPage page = doc.GetPage(0);
// Below could be used to tweak render options for optimizations later
//PdfPageRenderOptions options = new PdfPageRenderOptions();
// Render the first page to the BitmapImage
InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
await page.RenderToStreamAsync(stream);
// Common code
Cover.SetSource(stream);
// Convert the active BitmapImage Cover to a storage file to be stored locally
// ???
}
The variable, Cover, is a BitmapImage that is bound in XAML to display the image to the user. I want to save this image to my local app data so that I don't have to re-render it through the PDF library every time my app opens! The problem is I can't save anything in a Windows Store app from a stream unless it is text to my knowledge, (no filestream or fileoutputstreams for me), and Cover's URI source is null, since it was sourced from a stream, making it difficult to get my BitmapImage, Cover, to a StorageFile for proper Windows Store saving.
Everything works for me currently, I'm just upset about re-rendering the pdf page to my bitmapimage from scratch every time my app opens. Thanks in advance for any input!

You need to save the image from the PdfPage directly rather than from the BitmapImage since you can't get the data out of the BitmapImage. The PdfPage.RenderToStreamAsync already encodes the stream as a bitmap so you don't need to do any manipulation beyond sending it to the file. This is essentially the same as what you are doing to save to the InMemoryRandomAccessStream, except to a file based stream:
//We need a StorageFile to save into.
StorageFile saveFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("safedPdf.png",CreationCollisionOption.GenerateUniqueName);
using (var saveStream = await saveFile.OpenAsync(FileAccessMode.ReadWrite))
{
await page.RenderToStreamAsync(saveStream);
}

Related

Can you get a video thumbnail using MediaToolkit without reading/writing to disk?

I have a video file that's already loaded in memory (an IFormFile that's converted to a byte[]).
I've been trying to figure out how to take that video and get a thumbnail image from it, without having to read/write to disk.
I found use cases for MediaToolkit and FFmpeg here, and Movie Thumbnailer here, but from what I can find, those require the video already be saved to disk and have write access to output the thumbnail to a file.
Is there any way I can take either an IFormFile or byte[] and do something similar to what MediaToolkit is doing while being able to keep the result in memory?
I know a lot of folks are saying byte[] isn't the way to go. In that case, I'm more than happy to convert from IFormFile to a Stream, but I still need a way to do that and keep it in memory.
please try this with Windows.Media.Editing should work, not fully tested..
int frameHeight; // you can set the height
int frameWidth; // ...
TimeSpan getFrameInTime = new TimeSpan(0, 0, 1);
//Using Windows.Media.Editing get your ImageStream
var yourClip = await MediaClip.CreateFromFileAsync(someFile);
var composition = new MediaComposition();
// add the section of the video as needed
composition.Clips.Add(yourClip);
// Answer - now that your have your imageStream, get the thumbnail
var yourImageStream = await composition.GetThumbnailAsync(
getFrameInTime,
Convert.ToInt32(frameWidth),
Convert.ToInt32(frameHeight),
VideoFramePrecision.NearestFrame);
//now create your thumbnail bitmap
var yourThumbnailBitmap = new WriteableBitmap(
Convert.ToInt32(frameWidth),
Convert.ToInt32(frameHeight)
);
yourThumbnailBitmap.SetSource(yourImageStream);

Loading image from picture library to image source

I am capturing an image . Project places the image in picture library that is C:\...\Pictures\PreviewFrame.jpg.
I have an image tag
<Image Name="ClinicImage"></Image>
Now i want to load that PreviewFrame.jpg in this tag.
I tried this
ClinicImage.Source=new BitmapImage(new Uri(path));
where
path is a string variable containing image path.
But it is not getting loaded. How should i do it?
Thanks in advance.
There is some retrictions about what the universal applications can access.
You need first to be sure that the picture library capability is properly added in your application manifest.
Then, you can open the image using GetFileFromPathAsync() and provide the stream to the BitmapSource using SetSourceAsync()
var file = await StorageFile.GetFileFromPathAsync("c:\\users\\me\\images\\a.png");
var stream = await file.OpenReadAsync();
var imageSource = new BitmapImage();
await imageSource.SetSourceAsync(stream);
Make sure your slashes are set correctly. If I remember correctly, you need to work with double backslash instead of single.

Save image in windows phone 8.1 using FileSavePicker

I want to save an image using File Save Picker . I am using this link to save but it is only for text , how I modify it to save an image?
As you have provided the link then I assume that you managed to get StorageFile after Continuation (this is how it works at WP8.1 Runtime).
I also assume that you have a Stream with your image or you know how to obtain such a one. Basing on those two, you can save your image in png format to a file selected by picker for example like this:
public async Task SaveStreamAsync(IRandomAccessStream streamToSave, StorageFile destination)
{
BitmapDecoder bmpDecoder = await BitmapDecoder.CreateAsync(streamToSave);
PixelDataProvider pixelData = await bmpDecoder.GetPixelDataAsync(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, null, ExifOrientationMode.RespectExifOrientation, ColorManagementMode.DoNotColorManage);
using (var destFileStream = await destination.OpenAsync(FileAccessMode.ReadWrite))
{
BitmapEncoder bmpEncoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, destFileStream);
uint yourWidthAndOrHeight = 1024;
bmpEncoder.SetPixelData(BitmapPixelFormat.Rgba8, BitmapAlphaMode.Straight, yourWidthAndOrHeight, yourWidthAndOrHeight, 300, 300, pixelData.DetachPixelData());
await bmpEncoder.FlushAsync();
}
}
Also please remember to Dispose your streamToSave (and other resources) after finishing working with them.
If you take a look at BitmapEncoder and BitmapDecoder classes, then you will see more options including transformation and various properties.
(I've not tested the code above rough, but hopefully it will work fine)

Get stream from path wp8

I want to set an image choosen from picture library as background. So I take the originalname of the choosen photo in IsolatedStorageSetting. But later i do not manage to get the stream of the file from the path.. here the code:
bitmapimage.UriSource = new Uri(Settings.BackgroundPhotoUrl, UriKind.Absolute);
BackgroundImg.ImageSource = bitmapimage;
But this code does not work. No exception. Just the background is black.
So I have tried to save the Stream in IsolatedStorageSetting (I do not relly like this solution!!) but in this case I obtain an exception:
Operation denied
Here the code:
Settings.MyStream = e.ChosenPhoto
In the end, I have tried to save the image in isolated storage:
using (System.IO.IsolatedStorage.IsolatedStorageFile isf = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication())
{
isf.CopyFile(e.OriginalFileName, "background" + System.IO.Path.GetExtension(e.OriginalFileName), true);
}
But also in this case i obtain an operation denied exception
How can I solve the problem?? Thanx
It seems you are misunderstanding streams. A stream is a pointer to a position in a file you can read from or write to. If you are you are using a photo chooser then the result will give you a stream to the file. You need to read the bytes from that at stream and save then you your local storage. Then you can access the image from there.
In my Live Countdown app I use the WriteableBitmap class to save the Jpeg to a stream. Something along the lines of this:
var store =
System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication();
var newPath = "MyFileName.png";
if (store.FileExists(newPath)) store.DeleteFile(newPath);
var stream = store.CreateFile(newPath);
BitmapImage i = new BitmapImage();
i.SetSource(photoResult.ChosenPhoto);
WriteableBitmap imageToSave = new WriteableBitmap(i);
imageToSave.SaveJpeg(stream, 173, 173, 0, 100);
stream.Flush();
stream.Close();
That is kind of the flow. I had to take parts from different functions and put them together as the app allows the user to scale the app first. There is scaling the SaveJpeg method parameters as I am saving the image for a tile.

Best way to move date/textures from CLR to Runtime Component for directx when doing Win Store Apps

I have a Windows Store App, and A Runtime Component (Cpp/CX) that creates SurfaceImageSource (direct3d rendering).
The app shows a gridview of images. When a user click an image, i want to use it as a texture in my RT library. What are my options and what are best. Should i pass the path to the image to the RT Lib and load it somehow there or should i load it in CLR and pass over the data as a pointer?
Passing the filename might crash due to the security restrictions of Windows Store Apps. You can open a file only with a file picker or if you have been granted the explicit permission.
So when loading the file, you should save its content. E.g. to a byte array. Here is how the byte array can be generated from a StorageFile:
//file is the input StorageFile
var sourceStream = await file.OpenReadAsync();
//do anything else with the file, e.g. creating a BitmapImage
using(MemoryStream mem = new MemoryStream())
{
//Reset the file stream
sourceStream.Seek(0);
sourceStream.AsStreamForRead().CopyTo(mem);
var bytes = mem.ToArray();
}
Then you should pass the byte data to the DirectX library and load it to a texture. Alternatively you can use the BitmapDecoder class to convert the file to raw image data. The methods CreateAsync, GetPixelDataAsync and DetachPixelData might be of help.

Categories