如何在windows运行时应用中拍照


本节将介绍如何使用照相设备进行拍照,并保存照片。

1. MediaCapture

winRT中使用MediaCapture类进型拍照和录制视频相关操作。具体该类的介绍参考https://msdn.microsoft.com/zh-cn/library/windows/apps/windows.media.capture.mediacapture.aspx。通过Mediacapture获取照相资源,由于照相资源在系统中是唯一的,所以我们必须在退出拍照页面和应用挂起时释放资源,否则在应用挂起时开启别的应用(如照相机)会出现资源被占用的情况而死机。具体流程如下:

1) 一般手机都有前置, 后置摄像头,具体使用哪个摄像头会根据应用的要求而不相同。所以首先,我们要根据需求来决定使用哪个摄像头. 如获取后置摄像头:

task<DeviceInformation^> PhotoCapturePage::GetCamera(Windows::Devices::Enumeration::Panel camera)
{
	return create_task(DeviceInformation::FindAllAsync(DeviceClass::VideoCapture))
		.then([camera](DeviceInformationCollection^ devices)->DeviceInformation^
	{
		DeviceInformation^ device = nullptr;
		for (unsigned int i = 0; i < devices->Size; i++)
		{
			device = devices->GetAt(i);
			if (device->EnclosureLocation != nullptr
				&& device->EnclosureLocation->Panel == camera)
				break;
		}
		return device;
	});
}

2)接下来我们获取照相资源,并初始化:

task<void> PhotoCapturePage::InitPreview(Windows::Devices::Enumeration::DeviceInformation^ device)
{

	MediaCaptureInitializationSettings^ settings = ref new MediaCaptureInitializationSettings();
	settings->StreamingCaptureMode = StreamingCaptureMode::Video;
	settings->PhotoCaptureSource = PhotoCaptureSource::Photo;
	settings->AudioDeviceId = "";
	settings->VideoDeviceId = device->Id;
	return create_task(mediaCaptureMgr->InitializeAsync(settings));
}
3)初始化之后,就可以开始预览:

</pre><pre name="code" class="cpp">concurrency::task<void> PhotoCapturePage::StartPreview()
{
	previewElement->Source = mediaCaptureMgr.Get();
	mediaCaptureMgr->SetPreviewRotation(VideoRotation::Clockwise90Degrees);
	return create_task(mediaCaptureMgr->StartPreviewAsync());
}
</pre>在预览时,我们需要将预览的内容呈现给用户,所以在xaml中定于CaptureElement用来显示预览内容:<p></p><p></p><pre name="code" class="cpp"><pre name="code" class="html"><CaptureElement x:Name="previewElement" Stretch="UniformToFill" Grid.RowSpan="3" Canvas.ZIndex="1"/>


 

那么我们何时申请照相资源,何时释放它呢?我们考虑进入一个页面依次触发的事件:OnNavigateTo->LoadState. 退出页面时:OnNavigateFrom->SaveState。所以我们可以在进入页面的事件中使用照相资源,在退出时释放。考虑到应用的挂起和恢复,挂起时触发事件OnNavigateFrom->SaveState, 恢复时OnResume.  在OnResume时也要重新申请资源。所以我们可以在LoadState事件中调用ScenarioInit():

void PhotoCapturePage::ScenarioInit()
{
	mediaCaptureMgr = ref new MediaCapture();
	isPreviewing = false;
	previewElement->Source = nullptr;

	GetCamera(Windows::Devices::Enumeration::Panel::Back)
		.then([this](DeviceInformation^ device)
	{
		return InitPreview(device);
	}).then([this]()
	{
		//return SetFocus();
	})	
		.then([this](void)
	{
		if (mediaCaptureMgr->VideoDeviceController->FocusControl->Supported)
		{
			mediaCaptureMgr->VideoDeviceController->FlashControl->Enabled = false;
			mediaCaptureMgr->VideoDeviceController->FlashControl->Auto = true;
		}
		return StartPreview();
	}).then([this]()
	{
		return SetFocus();
		//isPreviewing = true;
	}).then([this]()
	{
		isPreviewing = true;
	});
}
在SaveState,和Onresume事件中调用CleanMediaCapture():
concurrency::task<void> PhotoCapturePage::CleanMediaCapture()
{
	task<void> op([](){});
	if (mediaCaptureMgr.Get() != nullptr)
	{
		if (isPreviewing)
		{
			try
			{
				op = create_task(mediaCaptureMgr->StopPreviewAsync())
					.then([this](void)
				{
					if (previewElement != nullptr)
						previewElement->Source = nullptr;

				//	delete(mediaCaptureMgr.Get());
					mediaCaptureMgr = nullptr;
					isPreviewing = false;
				});
			}
			catch (Exception^ e)
			{

			}
		}
		else {
			//delete(mediaCaptureMgr.Get());
			mediaCaptureMgr = nullptr;
			isPreviewing = false;
		}
	}
	return op;
}

2. 拍照并保存
void PhotoCapturePage::CapturePhoto()
{
	ImageEncodingProperties^ format = ImageEncodingProperties::CreateJpeg();
	
	inputStream = ref new InMemoryRandomAccessStream();
	outputStream = ref new InMemoryRandomAccessStream();
	try
	{
		create_task(mediaCaptureMgr->CapturePhotoToStreamAsync(format, inputStream))
			.then([this]()
		{
			return BitmapDecoder::CreateAsync(inputStream);
		}).then([=](BitmapDecoder^ decoder)
		{
			return BitmapEncoder::CreateForTranscodingAsync(outputStream, decoder);  
		}).then([=](BitmapEncoder^ encoder)
		{
			encoder->BitmapTransform->Rotation = BitmapRotation::Clockwise90Degrees;
			return encoder->FlushAsync();
		}).then([=]()
		{
			// Save the image
			String^ fileName = CreateFileName();
			photoFolder = KnownFolders::PicturesLibrary;
			return photoFolder->CreateFileAsync(fileName, CreationCollisionOption::ReplaceExisting);
		}).then([=](StorageFile^ file)
		{
			photoStorageFile = file;
			// Store stream in file
			return photoStorageFile->OpenAsync(FileAccessMode::ReadWrite);
		}).then([=](IRandomAccessStream^ stream)
		{
			outputStream->Seek(0);
			stream->Seek(0);
			stream->Size = 0;
			return RandomAccessStream::CopyAndCloseAsync(outputStream, stream);
		}).then([=](long long result)
		{
			captureNum++;
			captureNumTB->Text = captureNum.ToString();
			vFileNames->Append(photoStorageFile->Name);
		});
	}
	catch (Exception^ e)
	{

	}

}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值