locked
How to set a image from a file in C++

    Question

  • I am researching Windows 8 new features about image. I have already downloaded a sample named "Images Sample", but this sample is writting by C#.

    What I want to do is selecting a picture from file and istead the existing pic. Now I use FileOpenPicker to pick a file. I saw in the C# sample, they use BitmapImage to set image's source, but it doesn't work in C++. Here is the code in C# sample:

    {
    ....
    	    FileOpenPicker open = new FileOpenPicker();
                open.SuggestedStartLocation = PickerLocationId.PicturesLibrary;
                open.ViewMode = PickerViewMode.Thumbnail;
    
                // Filter to include a sample subset of file types
                open.FileTypeFilter.Clear();
                open.FileTypeFilter.Add(".bmp");
                open.FileTypeFilter.Add(".png");
                open.FileTypeFilter.Add(".jpeg");
                open.FileTypeFilter.Add(".jpg");
    
                // Open a stream for the selected file
                StorageFile file = await open.PickSingleFileAsync();  
                IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
    	    //Here! In C++ mode the StorageFile not have OpenAsync() method, so I cant create a IRandomAccessStream variety for 	  // bitmapImage->SetSource()
                // Set the image source to the selected bitmap
                BitmapImage bitmapImage = new BitmapImage();
                bitmapImage.DecodePixelHeight = decodePixelHeight;
                bitmapImage.DecodePixelWidth = decodePixelWidth;
    
                bitmapImage.SetSource(fileStream);
                Scenario2Image.Source = bitmapImage;
    }

    Here's my code:

    {
    	
    	FileOpenPicker ^ openPicker =ref new FileOpenPicker();
    	
    	openPicker->ViewMode = PickerViewMode::Thumbnail;
    	openPicker->SuggestedStartLocation = PickerLocationId::Desktop;
    	openPicker->FileTypeFilter->Append(".jpg");
    	openPicker->FileTypeFilter->Append(".jpeg");
    	openPicker->FileTypeFilter->Append(".png");
    
    	auto pickOperation = openPicker->PickSingleFileAsync();
    	
    	
    	Image^ result = Imageshow;// Imageshow is my Image Control's x:Name
    	
    
    	pickOperation->Completed = ref new AsyncOperationCompletedHandler<StorageFile^>([result](IAsyncOperation<StorageFile^> ^operation)
    	{
    
    		auto file = operation->GetResults();
    		
    
    		if(file)
    		{
    			Imageshow->Source = file->Path;// How to set the Imageshow's source?
    
    		}
    	});
    	pickOperation->Start();
    	
    }

    So how should I do to set Scenario2Image->Source from file?

    Thanks!


    • Edited by Dino Tech Thursday, February 09, 2012 11:33 AM
    Thursday, February 09, 2012 11:27 AM

Answers

  • Hi Dino,

    It looks like you accidentally removed the async handling when you added the stream handling.

    Any asynchronous function (by convention those ending in "Async") returns an "Operation" which doesn't do anything until it has been Start()ed and which will fire its Completed event when it has finished. This means that anything that has to happen after the call needs to go in the Completed handler like you did in the first snippet.

    So if you move the code to call OpenAsync the pickOperation's Completed handler and then move the code to deal with the stream to the StreamOperation's Completed handler and call StreamOperation->Start then it should work.

    C# does this for you with the await keyword, but that is not available in C++ in the Developer Preview. See Windows 8 Asynchronous Operations in C++ with PPL for a sample of how to do async operations the easy way in C++.

    --Rob

    • Marked as answer by Dino Tech Friday, February 10, 2012 5:34 AM
    Friday, February 10, 2012 3:51 AM
    Owner
  • void FilePickerCpp::MainPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) { FileOpenPicker ^ openPicker =ref new FileOpenPicker(); openPicker->ViewMode = PickerViewMode::Thumbnail; openPicker->SuggestedStartLocation = PickerLocationId::Desktop; openPicker->FileTypeFilter->Append(".jpg"); openPicker->FileTypeFilter->Append(".jpeg"); openPicker->FileTypeFilter->Append(".png"); auto pickOperation = openPicker->PickSingleFileAsync(); Image^ result = ImageFromFile;// Imageshow is my Image Control's x:Name pickOperation->Completed = ref new AsyncOperationCompletedHandler<StorageFile^>([this](IAsyncOperation<StorageFile^> ^operation) { StorageFile^ file = operation->GetResults(); if(file) { StreamRetrievalOperation^ StreamOperation = file->OpenAsync(FileAccessMode::Read); StreamOperation->Completed = ref new AsyncOperationCompletedHandler<IRandomAccessStream^>([this](IAsyncOperation<IRandomAccessStream^> ^operation) { IRandomAccessStream^ bitmapStream = operation->GetResults(); BitmapImage^ bitmapImage = ref new BitmapImage(); bitmapImage->SetSource(bitmapStream); ImageFromFile->Source = bitmapImage; }); StreamOperation->Start(); } }); pickOperation->Start(); }
    • Marked as answer by Dino Tech Friday, February 10, 2012 5:34 AM
    Friday, February 10, 2012 3:58 AM
    Owner

All replies

  • Hi Dino,

    You need to follow the same steps as in the C# example. Instead of using the file's Path (which your app likely doesn't have access to), open the StorageFile, extract the stream from it, and set it with BitmapImage::SetSource.

    --Rob

    Thursday, February 09, 2012 5:52 PM
    Owner
  • Thanks for your replying, Rob! I will try it .
    • Edited by Dino Tech Friday, February 10, 2012 12:57 AM
    Friday, February 10, 2012 12:56 AM
  • 	FileOpenPicker^ open = ref new FileOpenPicker();// Create a FileOpenPicker instance.
    	open->ViewMode = PickerViewMode::Thumbnail;
    	open->SuggestedStartLocation = PickerLocationId::Desktop;
    	open->FileTypeFilter->Append(".jpg");
    	open->FileTypeFilter->Append(".png");
    	open->FileTypeFilter->Append(".txt");
    	
    	//Instance a pickOperation and Start.
    	PickSingleFileOperation^ pickOperation = open->PickSingleFileAsync();
    	pickOperation->Start();
    
    	//Set a StorageFile 
    	StorageFile^ file = pickOperation->GetResults();
    
    	//Pick file to Stream
    	StreamRetrievalOperation^ StreamOperation = file->OpenAsync(FileAccessMode::Read);
    	IRandomAccessStream^ bitmapStream = StreamOperation->GetResults();
    	BitmapImage^  bitmapImage = ref new BitmapImage();
    	bitmapImage->SetSource(bitmapStream);
    
    	ImageFromFile->Source = bitmapImage;// Can't work.
    	

    I have improved the code as following. The project can run but I still can't replace the image from picking file.

    Friday, February 10, 2012 2:50 AM
  • Hi Dino,

    It looks like you accidentally removed the async handling when you added the stream handling.

    Any asynchronous function (by convention those ending in "Async") returns an "Operation" which doesn't do anything until it has been Start()ed and which will fire its Completed event when it has finished. This means that anything that has to happen after the call needs to go in the Completed handler like you did in the first snippet.

    So if you move the code to call OpenAsync the pickOperation's Completed handler and then move the code to deal with the stream to the StreamOperation's Completed handler and call StreamOperation->Start then it should work.

    C# does this for you with the await keyword, but that is not available in C++ in the Developer Preview. See Windows 8 Asynchronous Operations in C++ with PPL for a sample of how to do async operations the easy way in C++.

    --Rob

    • Marked as answer by Dino Tech Friday, February 10, 2012 5:34 AM
    Friday, February 10, 2012 3:51 AM
    Owner
  • void FilePickerCpp::MainPage::Button_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e) { FileOpenPicker ^ openPicker =ref new FileOpenPicker(); openPicker->ViewMode = PickerViewMode::Thumbnail; openPicker->SuggestedStartLocation = PickerLocationId::Desktop; openPicker->FileTypeFilter->Append(".jpg"); openPicker->FileTypeFilter->Append(".jpeg"); openPicker->FileTypeFilter->Append(".png"); auto pickOperation = openPicker->PickSingleFileAsync(); Image^ result = ImageFromFile;// Imageshow is my Image Control's x:Name pickOperation->Completed = ref new AsyncOperationCompletedHandler<StorageFile^>([this](IAsyncOperation<StorageFile^> ^operation) { StorageFile^ file = operation->GetResults(); if(file) { StreamRetrievalOperation^ StreamOperation = file->OpenAsync(FileAccessMode::Read); StreamOperation->Completed = ref new AsyncOperationCompletedHandler<IRandomAccessStream^>([this](IAsyncOperation<IRandomAccessStream^> ^operation) { IRandomAccessStream^ bitmapStream = operation->GetResults(); BitmapImage^ bitmapImage = ref new BitmapImage(); bitmapImage->SetSource(bitmapStream); ImageFromFile->Source = bitmapImage; }); StreamOperation->Start(); } }); pickOperation->Start(); }
    • Marked as answer by Dino Tech Friday, February 10, 2012 5:34 AM
    Friday, February 10, 2012 3:58 AM
    Owner
  • Thanks Rob, it works for me. I think i have to research about async operation.

    Friday, February 10, 2012 5:36 AM