version 1.3. Changes include: Support for products without front facing

camera, flash setting now available, half-pressing the camera key now
reactivates auto-focus in case manual focus has been made, persistent
settings using IsolatedStorageSettings.
This commit is contained in:
Mikko Piipponen 2013-06-20 15:21:42 +03:00
Родитель e7e6c9f77a
Коммит 25cb5299eb
9 изменённых файлов: 250 добавлений и 60 удалений

Просмотреть файл

@ -232,6 +232,8 @@ namespace CameraExplorer
NotifyPropertyChanged("SelectedOption");
NotifyPropertyChanged("OverlaySource");
}
Save();
}
}
}
@ -301,6 +303,61 @@ namespace CameraExplorer
/// </summary>
/// <param name="option">Option to set</param>
protected abstract void SetOption(ArrayParameterOption option);
/// <summary>
/// Set saved value if exists, otherwise set to default.
/// </summary>
public override void SetSavedOrDefault()
{
System.Diagnostics.Debug.WriteLine("Setting saved or default value to setting " + Name);
if (!Load())
{
SetDefault();
}
}
/// <summary>
/// Save parameter to application settings.
/// </summary>
public override void Save()
{
if (SelectedOption == null || SelectedOption.Value == null) return;
if (DataContext.Settings.Contains(ParameterSettingName))
{
if ((string)DataContext.Settings[ParameterSettingName] != SelectedOption.Name)
{
DataContext.Settings[ParameterSettingName] = SelectedOption.Name;
}
}
else
{
DataContext.Settings.Add(ParameterSettingName, SelectedOption.Name);
}
}
/// <summary>
/// Load parameter from application settings.
/// </summary>
/// <returns>true if setting was loaded successfully, otherwise false.</returns>
public override bool Load()
{
bool ret = false;
if (DataContext.Settings.Contains(ParameterSettingName))
{
string name = DataContext.Settings[ParameterSettingName].ToString();
for (int i = 0; i < Options.Count; i++)
{
if (Options[i].Name.Equals(name))
{
ret = true;
SelectedOption = Options[i];
}
}
}
return ret;
}
}
/// <summary>
@ -591,9 +648,9 @@ namespace CameraExplorer
foreach (dynamic i in supportedValues)
{
FlashMode fm = (FlashMode)i;
FlashState fm = (FlashState)i;
ArrayParameterOption option = new ArrayParameterOption(fm, fm.EnumerationToParameterName<FlashMode>(), "Assets/Icons/overlay.flashmode." + fm.ToString().ToLower() + ".png");
ArrayParameterOption option = new ArrayParameterOption(fm, fm.EnumerationToParameterName<FlashState>(), "Assets/Icons/overlay.flashmode." + fm.ToString().ToLower() + ".png");
Options.Add(option);
@ -610,7 +667,7 @@ namespace CameraExplorer
/// <param name="option">Option to set as current value</param>
protected override void SetOption(ArrayParameterOption option)
{
Device.SetProperty(PropertyId, (FlashMode)option.Value);
Device.SetProperty(PropertyId, (FlashState)option.Value);
}
/// <summary>
@ -622,7 +679,7 @@ namespace CameraExplorer
foreach (ArrayParameterOption i in Options)
{
if (i.Value == FlashMode.Auto)
if (i.Value == FlashState.Auto)
{
SelectedOption = i;
found = true;
@ -737,7 +794,7 @@ namespace CameraExplorer
{
WhiteBalancePreset wbp = (WhiteBalancePreset)i;
option = new ArrayParameterOption(wbp, wbp.EnumerationToParameterName<WhiteBalancePreset>(), "Assets/Icons/overlay.whitebalancepreset." + wbp.ToString().ToLower() + ".png");
option = new ArrayParameterOption(wbp, wbp.EnumerationToParameterName<WhiteBalancePreset>());
Options.Add(option);

Просмотреть файл

@ -10,6 +10,7 @@ using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.IO.IsolatedStorage;
using Windows.Phone.Media.Capture;
namespace CameraExplorer
@ -23,6 +24,7 @@ namespace CameraExplorer
public event PropertyChangedEventHandler PropertyChanged;
private static DataContext _singleton;
private static IsolatedStorageSettings _settings = IsolatedStorageSettings.ApplicationSettings;
private PhotoCaptureDevice _device = null;
private ObservableCollection<Parameter> _parameters = new ObservableCollection<Parameter>();
@ -58,7 +60,6 @@ namespace CameraExplorer
{
_parameters = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Parameters"));
@ -95,7 +96,7 @@ namespace CameraExplorer
try
{
parameter.Refresh();
parameter.SetDefault();
parameter.SetSavedOrDefault();
newParameters.Add(parameter);
}
@ -132,6 +133,17 @@ namespace CameraExplorer
}
}
/// <summary>
/// Settings accessors.
/// </summary>
public static IsolatedStorageSettings Settings
{
get
{
return _settings;
}
}
/// <summary>
/// Memory stream to hold the image data captured in MainPage but consumed in PreviewPage.
/// </summary>

Просмотреть файл

@ -58,16 +58,5 @@
</ComboBox>
</Grid>
</Grid>
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar>
<shell:ApplicationBarIconButton x:Name="sensorButton" Text="sensor"
IconUri="Assets/Icons/appbar.sensor.png" Click="sensorButton_Click" IsEnabled="False"/>
<shell:ApplicationBarIconButton x:Name="captureButton" Text="capture"
IconUri="Assets/Icons/appbar.feature.camera.rest.png" Click="captureButton_Click" IsEnabled="False"/>
<shell:ApplicationBarIconButton x:Name="settingsButton" Text="settings"
IconUri="Assets/Icons/appbar.feature.settings.rest.png" Click="settingsButton_Click" IsEnabled="False"/>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
</phone:PhoneApplicationPage>

Просмотреть файл

@ -41,20 +41,26 @@ namespace CameraExplorer
private SolidColorBrush _notFocusedBrush = new SolidColorBrush(Colors.Red);
private SolidColorBrush _focusedBrush = new SolidColorBrush(Colors.Green);
private ApplicationBarIconButton _sensorButton = null;
private ApplicationBarIconButton _captureButton = null;
private ApplicationBarIconButton _settingsButton = null;
public MainPage()
{
InitializeComponent();
ApplicationBarMenuItem menuItem = new ApplicationBarMenuItem();
menuItem.Text = "about";
menuItem.IsEnabled = false;
ApplicationBar.MenuItems.Add(menuItem);
menuItem.Click += new EventHandler(aboutMenuItem_Click);
VideoCanvas.Tap += new EventHandler<GestureEventArgs>(videoCanvas_Tap);
DataContext = _dataContext;
_progressIndicator.IsIndeterminate = true;
CreateAppBar();
ApplicationBarMenuItem menuItem = new ApplicationBarMenuItem();
menuItem.Text = "about";
menuItem.IsEnabled = false;
ApplicationBar.MenuItems.Add(menuItem);
menuItem.Click += new EventHandler(aboutMenuItem_Click);
}
/// <summary>
@ -97,7 +103,6 @@ namespace CameraExplorer
/// </summary>
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
// release camera as soon as no longer needed in order to avoid green bitmap bug
// fix for https://projects.developer.nokia.com/cameraexplorer/ticket/6
if ((_dataContext.Device != null) && e.Uri.ToString().Contains("PreviewPage.xaml"))
@ -247,7 +252,6 @@ namespace CameraExplorer
// Get tap coordinates as a foundation point
Windows.Foundation.Point tapPoint = new Windows.Foundation.Point(uiTapPoint.X, uiTapPoint.Y);
double xRatio = VideoCanvas.ActualHeight / _dataContext.Device.PreviewResolution.Width;
double yRatio = VideoCanvas.ActualWidth / _dataContext.Device.PreviewResolution.Height;
@ -319,20 +323,14 @@ namespace CameraExplorer
private async Task InitializeCamera(CameraSensorLocation sensorLocation)
{
Windows.Foundation.Size initialResolution = new Windows.Foundation.Size(640, 480);
Windows.Foundation.Size previewResolution = new Windows.Foundation.Size(640, 480);
Windows.Foundation.Size captureResolution = new Windows.Foundation.Size(640, 480);
PhotoCaptureDevice d = await PhotoCaptureDevice.OpenAsync(sensorLocation, initialResolution);
await d.SetPreviewResolutionAsync(previewResolution);
await d.SetCaptureResolutionAsync(captureResolution);
d.SetProperty(KnownCameraGeneralProperties.EncodeWithOrientation,
d.SensorLocation == CameraSensorLocation.Back ?
d.SensorRotationInDegrees : - d.SensorRotationInDegrees);
_dataContext.Device = d;
}
/// <summary>
@ -378,10 +376,11 @@ namespace CameraExplorer
_capturing = false;
// defer navigation, we're releasign the camera device there so following .Device calls must still work
// at least until the next cleanup, they're clearly not needed since the .Device is released
// Defer navigation as it will release the camera device and the
// following Device calls must still work.
goToPreview = true;
}
_manuallyFocused = false;
if (PhotoCaptureDevice.IsFocusRegionSupported(_dataContext.Device.SensorLocation))
{
@ -397,14 +396,16 @@ namespace CameraExplorer
}
/// <summary>
/// Half-pressing the shutter key initiates autofocus unless tapped to focus.
/// Half-pressing the shutter key initiates autofocus.
/// </summary>
private async void ShutterKeyHalfPressed(object sender, EventArgs e)
{
if (!_manuallyFocused)
if (_manuallyFocused)
{
await AutoFocus();
_manuallyFocused = false;
}
FocusIndicator.SetValue(Canvas.VisibilityProperty, Visibility.Collapsed);
await AutoFocus();
}
/// <summary>
@ -414,5 +415,36 @@ namespace CameraExplorer
{
await Capture();
}
/// <summary>
/// Creates an application bar based on the amount of sensors.
/// </summary>
private void CreateAppBar()
{
ApplicationBar appBar = new ApplicationBar();
if (PhotoCaptureDevice.AvailableSensorLocations.Count > 1)
{
_sensorButton = new ApplicationBarIconButton(new Uri("Assets/Icons/appbar.sensor.png", UriKind.Relative));
_sensorButton.Click += new EventHandler(sensorButton_Click);
_sensorButton.Text = "sensor";
_sensorButton.IsEnabled = false;
appBar.Buttons.Add(_sensorButton);
}
_captureButton = new ApplicationBarIconButton(new Uri("Assets/Icons/appbar.feature.camera.rest.png", UriKind.Relative));
_captureButton.Click += new EventHandler(captureButton_Click);
_captureButton.Text = "capture";
_captureButton.IsEnabled = false;
appBar.Buttons.Add(_captureButton);
_settingsButton = new ApplicationBarIconButton(new Uri("Assets/Icons/appbar.feature.settings.rest.png", UriKind.Relative));
_settingsButton.Click += new EventHandler(settingsButton_Click);
_settingsButton.Text = "settings";
_settingsButton.IsEnabled = false;
appBar.Buttons.Add(_settingsButton);
ApplicationBar = appBar;
}
}
}

Просмотреть файл

@ -64,6 +64,24 @@ namespace CameraExplorer
}
}
/// <summary>
/// Name of the parameter in application settings.
/// </summary>
public string ParameterSettingName
{
get
{
if (Device.SensorLocation == CameraSensorLocation.Back)
{
return "Back " + Name;
}
else
{
return "Front " + Name;
}
}
}
/// <summary>
/// Path to the overlay icon source used in viewfinder.
/// </summary>
@ -136,5 +154,21 @@ namespace CameraExplorer
/// Set parameter default value.
/// </summary>
public abstract void SetDefault();
/// <summary>
/// Set parameter to saved or default value.
/// </summary>
public abstract void SetSavedOrDefault();
/// <summary>
/// Save parameter to application settings.
/// </summary>
public abstract void Save();
/// <summary>
/// Load parameter to application settings.
/// </summary>
/// <returns>true if setting was loaded successfully, otherwise false.</returns>
public abstract bool Load();
}
}

Просмотреть файл

@ -9,7 +9,6 @@
using Microsoft.Phone.Controls;
using Microsoft.Xna.Framework.Media;
using System;
using System.IO.IsolatedStorage;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
@ -32,16 +31,15 @@ namespace CameraExplorer
}
/// <summary>
/// When navigating to this page, if camera has not been initialized (for example returning from
/// tombstoning), application will navigate directly back to the main page. Otherwise the
/// DataContext.ImageStream will be set as the source for the Image control in XAML.
/// When navigating to this page, DataContext.ImageStream will be set as the source
/// for the Image control in XAML. If ImageStream is null, application will navigate
/// directly back to the main page.
/// </summary>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (_dataContext.ImageStream != null)
{
_bitmap.SetSource(_dataContext.ImageStream);
image.Source = _bitmap;
}
else
@ -65,18 +63,6 @@ namespace CameraExplorer
MediaLibrary library = new MediaLibrary();
library.SavePictureToCameraRoll("CameraExplorer_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".jpg", _dataContext.ImageStream);
// There should be no temporary file left behind
using (var isolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
var files = isolatedStorage.GetFileNames("CameraExplorer_*.jpg");
foreach (string file in files)
{
isolatedStorage.DeleteFile(file);
//System.Diagnostics.Debug.WriteLine("Temp file deleted: " + file);
}
}
}
catch (Exception ex)
{

Просмотреть файл

@ -32,6 +32,6 @@ using System.Resources;
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.2.0.0")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyVersion("1.3.0.0")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: NeutralResourcesLanguageAttribute("en-US")]

Просмотреть файл

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Deployment xmlns="http://schemas.microsoft.com/windowsphone/2012/deployment" AppPlatformVersion="8.0">
<DefaultLanguage xmlns="" code="en-US" />
<App xmlns="" ProductID="{94f53777-5783-47b2-9bcb-ce46ccb0f219}" Title="Camera Explorer" RuntimeType="Silverlight" Version="1.2.0.0" Genre="apps.normal" Author="Nokia" Description="" Publisher="Nokia" PublisherID="{cc336b25-5e51-419a-8c64-3c4a7a4383f4}">
<App xmlns="" ProductID="{94f53777-5783-47b2-9bcb-ce46ccb0f219}" Title="Camera Explorer" RuntimeType="Silverlight" Version="1.3.0.0" Genre="apps.normal" Author="Nokia" Description="" Publisher="Nokia" PublisherID="{cc336b25-5e51-419a-8c64-3c4a7a4383f4}">
<IconPath IsRelative="true" IsResource="false">Assets\ApplicationIcon.png</IconPath>
<Capabilities>
<Capability Name="ID_CAP_NETWORKING" />
@ -39,9 +39,7 @@
</PrimaryToken>
</Tokens>
<Extensions>
<Extension ExtensionName="Camera_Capture_App"
ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5631}"
TaskID="_default" />
<Extension ExtensionName="Camera_Capture_App" ConsumerID="{5B04B775-356B-4AA0-AAF8-6491FFEA5631}" TaskID="_default" />
</Extensions>
<ScreenResolutions>
<ScreenResolution Name="ID_RESOLUTION_WVGA" />
@ -50,7 +48,6 @@
</ScreenResolutions>
<Requirements>
<Requirement Name="ID_REQ_REARCAMERA" />
<Requirement Name="ID_REQ_FRONTCAMERA" />
</Requirements>
</App>
</Deployment>

Просмотреть файл

@ -141,6 +141,8 @@ namespace CameraExplorer
Device.SetProperty(_propertyId, (T)value);
NotifyPropertyChanged("Value");
Save();
}
catch (Exception)
{
@ -149,6 +151,17 @@ namespace CameraExplorer
}
}
}
/// <summary>
/// Set saved value if exists, otherwise set to default.
/// </summary>
public override void SetSavedOrDefault()
{
if (!Load())
{
SetDefault();
}
}
}
/// <summary>
@ -168,6 +181,41 @@ namespace CameraExplorer
{
Value = (Int32)(Minimum + (Maximum - Minimum) / 2);
}
/// <summary>
/// Save parameter to application settings.
/// </summary>
public override void Save()
{
if (DataContext.Settings.Contains(ParameterSettingName))
{
if ((Int32)DataContext.Settings[ParameterSettingName] != Value)
{
DataContext.Settings[ParameterSettingName] = Value;
}
}
else
{
DataContext.Settings.Add(ParameterSettingName, Value);
}
}
/// <summary>
/// Load parameter from application settings.
/// </summary>
/// <returns>true if setting was loaded successfully, otherwise false.</returns>
public override bool Load()
{
bool ret = false;
if (DataContext.Settings.Contains(ParameterSettingName))
{
Int32 value = (Int32)DataContext.Settings[ParameterSettingName];
this.Value = value;
ret = true;
}
return ret;
}
}
/// <summary>
@ -187,5 +235,40 @@ namespace CameraExplorer
{
Value = (UInt32)(Minimum + (Maximum - Minimum) / 2);
}
/// <summary>
/// Save parameter to application settings.
/// </summary>
public override void Save()
{
if (DataContext.Settings.Contains(ParameterSettingName))
{
if ((UInt32)DataContext.Settings[ParameterSettingName] != Value)
{
DataContext.Settings[ParameterSettingName] = Value;
}
}
else
{
DataContext.Settings.Add(ParameterSettingName, Value);
}
}
/// <summary>
/// Load parameter from application settings.
/// </summary>
/// <returns>true if setting was loaded successfully, otherwise false.</returns>
public override bool Load()
{
bool ret = false;
if (DataContext.Settings.Contains(ParameterSettingName))
{
UInt32 value = (UInt32)DataContext.Settings[ParameterSettingName];
this.Value = value;
ret = true;
}
return ret;
}
}
}