Init RaspberryIO
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
namespace Unosquare.RaspberryIO.Camera
|
||||
{
|
||||
using Swan;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
/// <summary>
|
||||
/// A simple RGB color class to represent colors in RGB and YUV colorspaces.
|
||||
/// </summary>
|
||||
public class CameraColor
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CameraColor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="r">The red.</param>
|
||||
/// <param name="g">The green.</param>
|
||||
/// <param name="b">The blue.</param>
|
||||
public CameraColor(int r, int g, int b)
|
||||
: this(r, g, b, string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CameraColor"/> class.
|
||||
/// </summary>
|
||||
/// <param name="r">The red.</param>
|
||||
/// <param name="g">The green.</param>
|
||||
/// <param name="b">The blue.</param>
|
||||
/// <param name="name">The well-known color name.</param>
|
||||
public CameraColor(int r, int g, int b, string name)
|
||||
{
|
||||
RGB = new[] { Convert.ToByte(r.Clamp(0, 255)), Convert.ToByte(g.Clamp(0, 255)), Convert.ToByte(b.Clamp(0, 255)) };
|
||||
|
||||
var y = (R * .299000f) + (G * .587000f) + (B * .114000f);
|
||||
var u = (R * -.168736f) + (G * -.331264f) + (B * .500000f) + 128f;
|
||||
var v = (R * .500000f) + (G * -.418688f) + (B * -.081312f) + 128f;
|
||||
|
||||
YUV = new byte[] { (byte)y.Clamp(0, 255), (byte)u.Clamp(0, 255), (byte)v.Clamp(0, 255) };
|
||||
Name = name;
|
||||
}
|
||||
|
||||
#region Static Definitions
|
||||
|
||||
/// <summary>
|
||||
/// Gets the predefined white color.
|
||||
/// </summary>
|
||||
public static CameraColor White => new CameraColor(255, 255, 255, nameof(White));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the predefined red color.
|
||||
/// </summary>
|
||||
public static CameraColor Red => new CameraColor(255, 0, 0, nameof(Red));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the predefined green color.
|
||||
/// </summary>
|
||||
public static CameraColor Green => new CameraColor(0, 255, 0, nameof(Green));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the predefined blue color.
|
||||
/// </summary>
|
||||
public static CameraColor Blue => new CameraColor(0, 0, 255, nameof(Blue));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the predefined black color.
|
||||
/// </summary>
|
||||
public static CameraColor Black => new CameraColor(0, 0, 0, nameof(Black));
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Gets the well-known color name.
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the red byte.
|
||||
/// </summary>
|
||||
public byte R => RGB[0];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the green byte.
|
||||
/// </summary>
|
||||
public byte G => RGB[1];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the blue byte.
|
||||
/// </summary>
|
||||
public byte B => RGB[2];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the RGB byte array (3 bytes).
|
||||
/// </summary>
|
||||
public byte[] RGB { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the YUV byte array (3 bytes).
|
||||
/// </summary>
|
||||
public byte[] YUV { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hexadecimal representation of the RGB byte array.
|
||||
/// Preceded by 0x and all in lowercase
|
||||
/// </summary>
|
||||
/// <param name="reverse">if set to <c>true</c> [reverse].</param>
|
||||
/// <returns>A string</returns>
|
||||
public string ToRgbHex(bool reverse)
|
||||
{
|
||||
var data = RGB.ToArray();
|
||||
if (reverse) Array.Reverse(data);
|
||||
return ToHex(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hexadecimal representation of the YUV byte array.
|
||||
/// Preceded by 0x and all in lowercase
|
||||
/// </summary>
|
||||
/// <param name="reverse">if set to <c>true</c> [reverse].</param>
|
||||
/// <returns>A string</returns>
|
||||
public string ToYuvHex(bool reverse)
|
||||
{
|
||||
var data = YUV.ToArray();
|
||||
if (reverse) Array.Reverse(data);
|
||||
return ToHex(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hexadecimal representation of the data byte array
|
||||
/// </summary>
|
||||
/// <param name="data">The data.</param>
|
||||
/// <returns>A string</returns>
|
||||
private static string ToHex(byte[] data) => $"0x{BitConverter.ToString(data).Replace("-", string.Empty).ToLowerInvariant()}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
namespace Unosquare.RaspberryIO.Camera
|
||||
{
|
||||
using Swan.Abstractions;
|
||||
using System;
|
||||
using Swan.Components;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// The Raspberry Pi's camera controller wrapping raspistill and raspivid programs.
|
||||
/// This class is a singleton
|
||||
/// </summary>
|
||||
public class CameraController : SingletonBase<CameraController>
|
||||
{
|
||||
#region Private Declarations
|
||||
|
||||
private static readonly ManualResetEventSlim OperationDone = new ManualResetEventSlim(true);
|
||||
private static readonly object SyncRoot = new object();
|
||||
private static CancellationTokenSource _videoTokenSource = new CancellationTokenSource();
|
||||
private static Task<Task> _videoStreamTask;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the camera module is busy.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is busy; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsBusy => OperationDone.IsSet == false;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Image Capture Methods
|
||||
|
||||
/// <summary>
|
||||
/// Captures an image asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings.</param>
|
||||
/// <param name="ct">The ct.</param>
|
||||
/// <returns>The image bytes</returns>
|
||||
/// <exception cref="InvalidOperationException">Cannot use camera module because it is currently busy.</exception>
|
||||
public async Task<byte[]> CaptureImageAsync(CameraStillSettings settings, CancellationToken ct = default)
|
||||
{
|
||||
if (Instance.IsBusy)
|
||||
throw new InvalidOperationException("Cannot use camera module because it is currently busy.");
|
||||
|
||||
if (settings.CaptureTimeoutMilliseconds <= 0)
|
||||
throw new ArgumentException($"{nameof(settings.CaptureTimeoutMilliseconds)} needs to be greater than 0");
|
||||
|
||||
try
|
||||
{
|
||||
OperationDone.Reset();
|
||||
|
||||
var output = new MemoryStream();
|
||||
var exitCode = await ProcessRunner.RunProcessAsync(
|
||||
settings.CommandName,
|
||||
settings.CreateProcessArguments(),
|
||||
(data, proc) =>
|
||||
{
|
||||
output.Write(data, 0, data.Length);
|
||||
},
|
||||
null,
|
||||
true,
|
||||
ct);
|
||||
|
||||
return exitCode != 0 ? new byte[] { } : output.ToArray();
|
||||
}
|
||||
finally
|
||||
{
|
||||
OperationDone.Set();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Captures an image.
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings.</param>
|
||||
/// <returns>The image bytes</returns>
|
||||
public byte[] CaptureImage(CameraStillSettings settings)
|
||||
{
|
||||
return CaptureImageAsync(settings).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Captures a JPEG encoded image asynchronously at 90% quality.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <param name="ct">The ct.</param>
|
||||
/// <returns>The image bytes</returns>
|
||||
public Task<byte[]> CaptureImageJpegAsync(int width, int height, CancellationToken ct = default)
|
||||
{
|
||||
var settings = new CameraStillSettings
|
||||
{
|
||||
CaptureWidth = width,
|
||||
CaptureHeight = height,
|
||||
CaptureJpegQuality = 90,
|
||||
CaptureTimeoutMilliseconds = 300,
|
||||
};
|
||||
|
||||
return CaptureImageAsync(settings, ct);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Captures a JPEG encoded image at 90% quality.
|
||||
/// </summary>
|
||||
/// <param name="width">The width.</param>
|
||||
/// <param name="height">The height.</param>
|
||||
/// <returns>The image bytes</returns>
|
||||
public byte[] CaptureImageJpeg(int width, int height) => CaptureImageJpegAsync(width, height).GetAwaiter().GetResult();
|
||||
|
||||
#endregion
|
||||
|
||||
#region Video Capture Methods
|
||||
|
||||
/// <summary>
|
||||
/// Opens the video stream with a timeout of 0 (running indefinitely) at 1080p resolution, variable bitrate and 25 FPS.
|
||||
/// No preview is shown
|
||||
/// </summary>
|
||||
/// <param name="onDataCallback">The on data callback.</param>
|
||||
/// <param name="onExitCallback">The on exit callback.</param>
|
||||
public void OpenVideoStream(Action<byte[]> onDataCallback, Action onExitCallback = null)
|
||||
{
|
||||
var settings = new CameraVideoSettings
|
||||
{
|
||||
CaptureTimeoutMilliseconds = 0,
|
||||
CaptureDisplayPreview = false,
|
||||
CaptureWidth = 1920,
|
||||
CaptureHeight = 1080
|
||||
};
|
||||
|
||||
OpenVideoStream(settings, onDataCallback, onExitCallback);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens the video stream with the supplied settings. Capture Timeout Milliseconds has to be 0 or greater
|
||||
/// </summary>
|
||||
/// <param name="settings">The settings.</param>
|
||||
/// <param name="onDataCallback">The on data callback.</param>
|
||||
/// <param name="onExitCallback">The on exit callback.</param>
|
||||
/// <exception cref="InvalidOperationException">Cannot use camera module because it is currently busy.</exception>
|
||||
/// <exception cref="ArgumentException">CaptureTimeoutMilliseconds</exception>
|
||||
public void OpenVideoStream(CameraVideoSettings settings, Action<byte[]> onDataCallback, Action onExitCallback)
|
||||
{
|
||||
if (Instance.IsBusy)
|
||||
throw new InvalidOperationException("Cannot use camera module because it is currently busy.");
|
||||
|
||||
if (settings.CaptureTimeoutMilliseconds < 0)
|
||||
throw new ArgumentException($"{nameof(settings.CaptureTimeoutMilliseconds)} needs to be greater than or equal to 0");
|
||||
|
||||
try
|
||||
{
|
||||
OperationDone.Reset();
|
||||
_videoStreamTask = Task.Factory.StartNew(() => VideoWorkerDoWork(settings, onDataCallback, onExitCallback), _videoTokenSource.Token);
|
||||
}
|
||||
catch
|
||||
{
|
||||
OperationDone.Set();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Closes the video stream of a video stream is open.
|
||||
/// </summary>
|
||||
public void CloseVideoStream()
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
if (IsBusy == false)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_videoTokenSource.IsCancellationRequested == false)
|
||||
{
|
||||
_videoTokenSource.Cancel();
|
||||
_videoStreamTask.Wait();
|
||||
}
|
||||
|
||||
_videoTokenSource = new CancellationTokenSource();
|
||||
}
|
||||
|
||||
private static async Task VideoWorkerDoWork(
|
||||
CameraVideoSettings settings,
|
||||
Action<byte[]> onDataCallback,
|
||||
Action onExitCallback)
|
||||
{
|
||||
try
|
||||
{
|
||||
await ProcessRunner.RunProcessAsync(
|
||||
settings.CommandName,
|
||||
settings.CreateProcessArguments(),
|
||||
(data, proc) => onDataCallback?.Invoke(data),
|
||||
null,
|
||||
true,
|
||||
_videoTokenSource.Token);
|
||||
|
||||
onExitCallback?.Invoke();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// swallow
|
||||
}
|
||||
finally
|
||||
{
|
||||
Instance.CloseVideoStream();
|
||||
OperationDone.Set();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
namespace Unosquare.RaspberryIO.Camera
|
||||
{
|
||||
using Swan;
|
||||
using System.Globalization;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the Raspberry Pi camera's sensor ROI (Region of Interest)
|
||||
/// </summary>
|
||||
public struct CameraRect
|
||||
{
|
||||
/// <summary>
|
||||
/// The default ROI which is the entire area.
|
||||
/// </summary>
|
||||
public static readonly CameraRect Default = new CameraRect { X = 0M, Y = 0M, W = 1.0M, H = 1.0M };
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the x in relative coordinates. (0.0 to 1.0)
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The x.
|
||||
/// </value>
|
||||
public decimal X { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the y location in relative coordinates. (0.0 to 1.0)
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The y.
|
||||
/// </value>
|
||||
public decimal Y { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width in relative coordinates. (0.0 to 1.0)
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The w.
|
||||
/// </value>
|
||||
public decimal W { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height in relative coordinates. (0.0 to 1.0)
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The h.
|
||||
/// </value>
|
||||
public decimal H { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is equal to the default (The entire area).
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is default; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsDefault
|
||||
{
|
||||
get
|
||||
{
|
||||
Clamp();
|
||||
return X == Default.X && Y == Default.Y && W == Default.W && H == Default.H;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps the members of this ROI to their minimum and maximum values
|
||||
/// </summary>
|
||||
public void Clamp()
|
||||
{
|
||||
X = X.Clamp(0M, 1M);
|
||||
Y = Y.Clamp(0M, 1M);
|
||||
W = W.Clamp(0M, 1M - X);
|
||||
H = H.Clamp(0M, 1M - Y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="string" /> that represents this instance.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A <see cref="string" /> that represents this instance.
|
||||
/// </returns>
|
||||
public override string ToString() => $"{X.ToString(CultureInfo.InvariantCulture)},{Y.ToString(CultureInfo.InvariantCulture)},{W.ToString(CultureInfo.InvariantCulture)},{H.ToString(CultureInfo.InvariantCulture)}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,340 @@
|
||||
namespace Unosquare.RaspberryIO.Camera
|
||||
{
|
||||
using Swan;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// A base class to implement raspistill and raspivid wrappers
|
||||
/// Full documentation available at
|
||||
/// https://www.raspberrypi.org/documentation/raspbian/applications/camera.md
|
||||
/// </summary>
|
||||
public abstract class CameraSettingsBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The Invariant Culture shorthand
|
||||
/// </summary>
|
||||
protected static readonly CultureInfo Ci = CultureInfo.InvariantCulture;
|
||||
|
||||
#region Capture Settings
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the timeout milliseconds.
|
||||
/// Default value is 5000
|
||||
/// Recommended value is at least 300 in order to let the light collectors open
|
||||
/// </summary>
|
||||
public int CaptureTimeoutMilliseconds { get; set; } = 5000;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether or not to show a preview window on the screen
|
||||
/// </summary>
|
||||
public bool CaptureDisplayPreview { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether a preview window is shown in full screen mode if enabled
|
||||
/// </summary>
|
||||
public bool CaptureDisplayPreviewInFullScreen { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether video stabilization should be enabled.
|
||||
/// </summary>
|
||||
public bool CaptureVideoStabilizationEnabled { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the display preview opacity only if the display preview property is enabled.
|
||||
/// </summary>
|
||||
public byte CaptureDisplayPreviewOpacity { get; set; } = 255;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the capture sensor region of interest in relative coordinates.
|
||||
/// </summary>
|
||||
public CameraRect CaptureSensorRoi { get; set; } = CameraRect.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the capture shutter speed in microseconds.
|
||||
/// Default -1, Range 0 to 6000000 (equivalent to 6 seconds)
|
||||
/// </summary>
|
||||
public int CaptureShutterSpeedMicroseconds { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the exposure mode.
|
||||
/// </summary>
|
||||
public CameraExposureMode CaptureExposure { get; set; } = CameraExposureMode.Auto;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the picture EV compensation. Default is 0, Range is -10 to 10
|
||||
/// Camera exposure compensation is commonly stated in terms of EV units;
|
||||
/// 1 EV is equal to one exposure step (or stop), corresponding to a doubling of exposure.
|
||||
/// Exposure can be adjusted by changing either the lens f-number or the exposure time;
|
||||
/// which one is changed usually depends on the camera's exposure mode.
|
||||
/// </summary>
|
||||
public int CaptureExposureCompensation { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the capture metering mode.
|
||||
/// </summary>
|
||||
public CameraMeteringMode CaptureMeteringMode { get; set; } = CameraMeteringMode.Average;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the automatic white balance mode. By default it is set to Auto
|
||||
/// </summary>
|
||||
public CameraWhiteBalanceMode CaptureWhiteBalanceControl { get; set; } = CameraWhiteBalanceMode.Auto;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the capture white balance gain on the blue channel. Example: 1.25
|
||||
/// Only takes effect if White balance control is set to off.
|
||||
/// Default is 0
|
||||
/// </summary>
|
||||
public decimal CaptureWhiteBalanceGainBlue { get; set; } = 0M;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the capture white balance gain on the red channel. Example: 1.75
|
||||
/// Only takes effect if White balance control is set to off.
|
||||
/// Default is 0
|
||||
/// </summary>
|
||||
public decimal CaptureWhiteBalanceGainRed { get; set; } = 0M;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the dynamic range compensation.
|
||||
/// DRC changes the images by increasing the range of dark areas, and decreasing the brighter areas. This can improve the image in low light areas.
|
||||
/// </summary>
|
||||
public CameraDynamicRangeCompensation CaptureDynamicRangeCompensation { get; set; } =
|
||||
CameraDynamicRangeCompensation.Off;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Image Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the picture to take.
|
||||
/// Less than or equal to 0 in either width or height means maximum resolution available.
|
||||
/// </summary>
|
||||
public int CaptureWidth { get; set; } = 640;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the height of the picture to take.
|
||||
/// Less than or equal to 0 in either width or height means maximum resolution available.
|
||||
/// </summary>
|
||||
public int CaptureHeight { get; set; } = 480;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the picture sharpness. Default is 0, Range form -100 to 100
|
||||
/// </summary>
|
||||
public int ImageSharpness { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the picture contrast. Default is 0, Range form -100 to 100
|
||||
/// </summary>
|
||||
public int ImageContrast { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the picture brightness. Default is 50, Range form 0 to 100
|
||||
/// </summary>
|
||||
public int ImageBrightness { get; set; } = 50; // from 0 to 100
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the picture saturation. Default is 0, Range form -100 to 100
|
||||
/// </summary>
|
||||
public int ImageSaturation { get; set; } = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the picture ISO. Default is -1 Range is 100 to 800
|
||||
/// The higher the value, the more light the sensor absorbs
|
||||
/// </summary>
|
||||
public int ImageIso { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the image capture effect to be applied.
|
||||
/// </summary>
|
||||
public CameraImageEffect ImageEffect { get; set; } = CameraImageEffect.None;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the color effect U coordinates.
|
||||
/// Default is -1, Range is 0 to 255
|
||||
/// 128:128 should be effectively a monochrome image.
|
||||
/// </summary>
|
||||
public int ImageColorEffectU { get; set; } = -1; // 0 to 255
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the color effect V coordinates.
|
||||
/// Default is -1, Range is 0 to 255
|
||||
/// 128:128 should be effectively a monochrome image.
|
||||
/// </summary>
|
||||
public int ImageColorEffectV { get; set; } = -1; // 0 to 255
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the image rotation. Default is no rotation
|
||||
/// </summary>
|
||||
public CameraImageRotation ImageRotation { get; set; } = CameraImageRotation.None;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the image should be flipped horizontally.
|
||||
/// </summary>
|
||||
public bool ImageFlipHorizontally { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the image should be flipped vertically.
|
||||
/// </summary>
|
||||
public bool ImageFlipVertically { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the image annotations using a bitmask (or flags) notation.
|
||||
/// Apply a bitwise OR to the enumeration to include multiple annotations
|
||||
/// </summary>
|
||||
public CameraAnnotation ImageAnnotations { get; set; } = CameraAnnotation.None;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the image annotations text.
|
||||
/// Text may include date/time placeholders by using the '%' character, as used by strftime.
|
||||
/// Example: ABC %Y-%m-%d %X will output ABC 2015-10-28 20:09:33
|
||||
/// </summary>
|
||||
public string ImageAnnotationsText { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the font size of the text annotations
|
||||
/// Default is -1, range is 6 to 160
|
||||
/// </summary>
|
||||
public int ImageAnnotationFontSize { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the color of the text annotations.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The color of the image annotation font.
|
||||
/// </value>
|
||||
public CameraColor ImageAnnotationFontColor { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the background color for text annotations.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The image annotation background.
|
||||
/// </value>
|
||||
public CameraColor ImageAnnotationBackground { get; set; } = null;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Interface
|
||||
|
||||
/// <summary>
|
||||
/// Gets the command file executable.
|
||||
/// </summary>
|
||||
public abstract string CommandName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates the process arguments.
|
||||
/// </summary>
|
||||
/// <returns>The string that represents the process arguments</returns>
|
||||
public virtual string CreateProcessArguments()
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
sb.Append("-o -"); // output to standard output as opposed to a file.
|
||||
sb.Append($" -t {(CaptureTimeoutMilliseconds < 0 ? "0" : CaptureTimeoutMilliseconds.ToString(Ci))}");
|
||||
|
||||
// Basic Width and height
|
||||
if (CaptureWidth > 0 && CaptureHeight > 0)
|
||||
{
|
||||
sb.Append($" -w {CaptureWidth.ToString(Ci)}");
|
||||
sb.Append($" -h {CaptureHeight.ToString(Ci)}");
|
||||
}
|
||||
|
||||
// Display Preview
|
||||
if (CaptureDisplayPreview)
|
||||
{
|
||||
if (CaptureDisplayPreviewInFullScreen)
|
||||
sb.Append(" -f");
|
||||
|
||||
if (CaptureDisplayPreviewOpacity != byte.MaxValue)
|
||||
sb.Append($" -op {CaptureDisplayPreviewOpacity.ToString(Ci)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(" -n"); // no preview
|
||||
}
|
||||
|
||||
// Picture Settings
|
||||
if (ImageSharpness != 0)
|
||||
sb.Append($" -sh {ImageSharpness.Clamp(-100, 100).ToString(Ci)}");
|
||||
|
||||
if (ImageContrast != 0)
|
||||
sb.Append($" -co {ImageContrast.Clamp(-100, 100).ToString(Ci)}");
|
||||
|
||||
if (ImageBrightness != 50)
|
||||
sb.Append($" -br {ImageBrightness.Clamp(0, 100).ToString(Ci)}");
|
||||
|
||||
if (ImageSaturation != 0)
|
||||
sb.Append($" -sa {ImageSaturation.Clamp(-100, 100).ToString(Ci)}");
|
||||
|
||||
if (ImageIso >= 100)
|
||||
sb.Append($" -ISO {ImageIso.Clamp(100, 800).ToString(Ci)}");
|
||||
|
||||
if (CaptureVideoStabilizationEnabled)
|
||||
sb.Append(" -vs");
|
||||
|
||||
if (CaptureExposureCompensation != 0)
|
||||
sb.Append($" -ev {CaptureExposureCompensation.Clamp(-10, 10).ToString(Ci)}");
|
||||
|
||||
if (CaptureExposure != CameraExposureMode.Auto)
|
||||
sb.Append($" -ex {CaptureExposure.ToString().ToLowerInvariant()}");
|
||||
|
||||
if (CaptureWhiteBalanceControl != CameraWhiteBalanceMode.Auto)
|
||||
sb.Append($" -awb {CaptureWhiteBalanceControl.ToString().ToLowerInvariant()}");
|
||||
|
||||
if (ImageEffect != CameraImageEffect.None)
|
||||
sb.Append($" -ifx {ImageEffect.ToString().ToLowerInvariant()}");
|
||||
|
||||
if (ImageColorEffectU >= 0 && ImageColorEffectV >= 0)
|
||||
{
|
||||
sb.Append(
|
||||
$" -cfx {ImageColorEffectU.Clamp(0, 255).ToString(Ci)}:{ImageColorEffectV.Clamp(0, 255).ToString(Ci)}");
|
||||
}
|
||||
|
||||
if (CaptureMeteringMode != CameraMeteringMode.Average)
|
||||
sb.Append($" -mm {CaptureMeteringMode.ToString().ToLowerInvariant()}");
|
||||
|
||||
if (ImageRotation != CameraImageRotation.None)
|
||||
sb.Append($" -rot {((int)ImageRotation).ToString(Ci)}");
|
||||
|
||||
if (ImageFlipHorizontally)
|
||||
sb.Append(" -hf");
|
||||
|
||||
if (ImageFlipVertically)
|
||||
sb.Append(" -vf");
|
||||
|
||||
if (CaptureSensorRoi.IsDefault == false)
|
||||
sb.Append($" -roi {CaptureSensorRoi}");
|
||||
|
||||
if (CaptureShutterSpeedMicroseconds > 0)
|
||||
sb.Append($" -ss {CaptureShutterSpeedMicroseconds.Clamp(0, 6000000).ToString(Ci)}");
|
||||
|
||||
if (CaptureDynamicRangeCompensation != CameraDynamicRangeCompensation.Off)
|
||||
sb.Append($" -drc {CaptureDynamicRangeCompensation.ToString().ToLowerInvariant()}");
|
||||
|
||||
if (CaptureWhiteBalanceControl == CameraWhiteBalanceMode.Off &&
|
||||
(CaptureWhiteBalanceGainBlue != 0M || CaptureWhiteBalanceGainRed != 0M))
|
||||
sb.Append($" -awbg {CaptureWhiteBalanceGainBlue.ToString(Ci)},{CaptureWhiteBalanceGainRed.ToString(Ci)}");
|
||||
|
||||
if (ImageAnnotationFontSize > 0)
|
||||
{
|
||||
sb.Append($" -ae {ImageAnnotationFontSize.Clamp(6, 160).ToString(Ci)}");
|
||||
sb.Append($",{(ImageAnnotationFontColor == null ? "0xff" : ImageAnnotationFontColor.ToYuvHex(true))}");
|
||||
|
||||
if (ImageAnnotationBackground != null)
|
||||
{
|
||||
ImageAnnotations |= CameraAnnotation.SolidBackground;
|
||||
sb.Append($",{ImageAnnotationBackground.ToYuvHex(true)}");
|
||||
}
|
||||
}
|
||||
|
||||
if (ImageAnnotations != CameraAnnotation.None)
|
||||
sb.Append($" -a {((int)ImageAnnotations).ToString(Ci)}");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ImageAnnotationsText) == false)
|
||||
sb.Append($" -a \"{ImageAnnotationsText.Replace("\"", "'")}\"");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
namespace Unosquare.RaspberryIO.Camera
|
||||
{
|
||||
using Swan;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Defines a wrapper for the raspistill program and its settings (command-line arguments)
|
||||
/// </summary>
|
||||
/// <seealso cref="CameraSettingsBase" />
|
||||
public class CameraStillSettings : CameraSettingsBase
|
||||
{
|
||||
private int _rotate;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string CommandName => "raspistill";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the preview window (if enabled) uses native capture resolution
|
||||
/// This may slow down preview FPS
|
||||
/// </summary>
|
||||
public bool CaptureDisplayPreviewAtResolution { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the encoding format the hardware will use for the output.
|
||||
/// </summary>
|
||||
public CameraImageEncodingFormat CaptureEncoding { get; set; } = CameraImageEncodingFormat.Jpg;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the quality for JPEG only encoding mode.
|
||||
/// Value ranges from 0 to 100
|
||||
/// </summary>
|
||||
public int CaptureJpegQuality { get; set; } = 90;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the JPEG encoder should add raw bayer metadata.
|
||||
/// </summary>
|
||||
public bool CaptureJpegIncludeRawBayerMetadata { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// JPEG EXIF data
|
||||
/// Keys and values must be already properly escaped. Otherwise the command will fail.
|
||||
/// </summary>
|
||||
public Dictionary<string, string> CaptureJpegExtendedInfo { get; } = new Dictionary<string, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [horizontal flip].
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if [horizontal flip]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool HorizontalFlip { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether [vertical flip].
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if [vertical flip]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool VerticalFlip { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the rotation.
|
||||
/// </summary>
|
||||
/// <exception cref="ArgumentOutOfRangeException">Valid range 0-359</exception>
|
||||
public int Rotation
|
||||
{
|
||||
get => _rotate;
|
||||
set
|
||||
{
|
||||
if (value < 0 || value > 359)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(value), "Valid range 0-359");
|
||||
}
|
||||
|
||||
_rotate = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string CreateProcessArguments()
|
||||
{
|
||||
var sb = new StringBuilder(base.CreateProcessArguments());
|
||||
sb.Append($" -e {CaptureEncoding.ToString().ToLowerInvariant()}");
|
||||
|
||||
// JPEG Encoder specific arguments
|
||||
if (CaptureEncoding == CameraImageEncodingFormat.Jpg)
|
||||
{
|
||||
sb.Append($" -q {CaptureJpegQuality.Clamp(0, 100).ToString(Ci)}");
|
||||
|
||||
if (CaptureJpegIncludeRawBayerMetadata)
|
||||
sb.Append(" -r");
|
||||
|
||||
// JPEG EXIF data
|
||||
if (CaptureJpegExtendedInfo.Count > 0)
|
||||
{
|
||||
foreach (var kvp in CaptureJpegExtendedInfo)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(kvp.Key) || string.IsNullOrWhiteSpace(kvp.Value))
|
||||
continue;
|
||||
|
||||
sb.Append($" -x \"{kvp.Key.Replace("\"", "'")}={kvp.Value.Replace("\"", "'")}\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Display preview settings
|
||||
if (CaptureDisplayPreview && CaptureDisplayPreviewAtResolution) sb.Append(" -fp");
|
||||
|
||||
if (Rotation != 0) sb.Append($" -rot {Rotation}");
|
||||
|
||||
if (HorizontalFlip) sb.Append(" -hf");
|
||||
|
||||
if (VerticalFlip) sb.Append(" -vf");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
namespace Unosquare.RaspberryIO.Camera
|
||||
{
|
||||
using Swan;
|
||||
using System.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the raspivid camera settings for video capture functionality
|
||||
/// </summary>
|
||||
/// <seealso cref="CameraSettingsBase" />
|
||||
public class CameraVideoSettings : CameraSettingsBase
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public override string CommandName => "raspivid";
|
||||
|
||||
/// <summary>
|
||||
/// Use bits per second, so 10Mbits/s would be -b 10000000. For H264, 1080p30 a high quality bitrate would be 15Mbits/s or more.
|
||||
/// Maximum bitrate is 25Mbits/s (-b 25000000), but much over 17Mbits/s won't show noticeable improvement at 1080p30.
|
||||
/// Default -1
|
||||
/// </summary>
|
||||
public int CaptureBitrate { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the framerate.
|
||||
/// Default 25, range 2 to 30
|
||||
/// </summary>
|
||||
public int CaptureFramerate { get; set; } = 25;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the intra refresh period (GoP) rate for the recorded video. H264 video uses a complete frame (I-frame) every intra
|
||||
/// refresh period, from which subsequent frames are based. This option specifies the number of frames between each I-frame.
|
||||
/// Larger numbers here will reduce the size of the resulting video, and smaller numbers make the stream less error-prone.
|
||||
/// </summary>
|
||||
public int CaptureKeyframeRate { get; set; } = 25;
|
||||
|
||||
/// <summary>
|
||||
/// Sets the initial quantisation parameter for the stream. Varies from approximately 10 to 40, and will greatly affect
|
||||
/// the quality of the recording. Higher values reduce quality and decrease file size. Combine this setting with a
|
||||
/// bitrate of 0 to set a completely variable bitrate.
|
||||
/// </summary>
|
||||
public int CaptureQuantisation { get; set; } = 23;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the profile.
|
||||
/// Sets the H264 profile to be used for the encoding.
|
||||
/// Default is Main mode
|
||||
/// </summary>
|
||||
public CameraH264Profile CaptureProfile { get; set; } = CameraH264Profile.Main;
|
||||
|
||||
/// <summary>
|
||||
/// Forces the stream to include PPS and SPS headers on every I-frame. Needed for certain streaming cases
|
||||
/// e.g. Apple HLS. These headers are small, so don't greatly increase the file size.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if [interleave headers]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool CaptureInterleaveHeaders { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Switch on an option to display the preview after compression. This will show any compression artefacts in the preview window. In normal operation,
|
||||
/// the preview will show the camera output prior to being compressed. This option is not guaranteed to work in future releases.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if [capture display preview encoded]; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool CaptureDisplayPreviewEncoded { get; set; } = false;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string CreateProcessArguments()
|
||||
{
|
||||
var sb = new StringBuilder(base.CreateProcessArguments());
|
||||
|
||||
sb.Append($" -pf {CaptureProfile.ToString().ToLowerInvariant()}");
|
||||
if (CaptureBitrate < 0)
|
||||
sb.Append($" -b {CaptureBitrate.Clamp(0, 25000000).ToString(Ci)}");
|
||||
|
||||
if (CaptureFramerate >= 2)
|
||||
sb.Append($" -fps {CaptureFramerate.Clamp(2, 30).ToString(Ci)}");
|
||||
|
||||
if (CaptureDisplayPreview && CaptureDisplayPreviewEncoded)
|
||||
sb.Append(" -e");
|
||||
|
||||
if (CaptureKeyframeRate > 0)
|
||||
sb.Append($" -g {CaptureKeyframeRate.ToString(Ci)}");
|
||||
|
||||
if (CaptureQuantisation >= 0)
|
||||
sb.Append($" -qp {CaptureQuantisation.Clamp(0, 40).ToString(Ci)}");
|
||||
|
||||
if (CaptureInterleaveHeaders)
|
||||
sb.Append(" -ih");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,423 @@
|
||||
namespace Unosquare.RaspberryIO.Camera
|
||||
{
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Defines the available encoding formats for the Raspberry Pi camera module
|
||||
/// </summary>
|
||||
public enum CameraImageEncodingFormat
|
||||
{
|
||||
/// <summary>
|
||||
/// The JPG
|
||||
/// </summary>
|
||||
Jpg,
|
||||
|
||||
/// <summary>
|
||||
/// The BMP
|
||||
/// </summary>
|
||||
Bmp,
|
||||
|
||||
/// <summary>
|
||||
/// The GIF
|
||||
/// </summary>
|
||||
Gif,
|
||||
|
||||
/// <summary>
|
||||
/// The PNG
|
||||
/// </summary>
|
||||
Png,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the different exposure modes for the Raspberry Pi's camera module
|
||||
/// </summary>
|
||||
public enum CameraExposureMode
|
||||
{
|
||||
/// <summary>
|
||||
/// The automatic
|
||||
/// </summary>
|
||||
Auto,
|
||||
|
||||
/// <summary>
|
||||
/// The night
|
||||
/// </summary>
|
||||
Night,
|
||||
|
||||
/// <summary>
|
||||
/// The night preview
|
||||
/// </summary>
|
||||
NightPreview,
|
||||
|
||||
/// <summary>
|
||||
/// The backlight
|
||||
/// </summary>
|
||||
Backlight,
|
||||
|
||||
/// <summary>
|
||||
/// The spotlight
|
||||
/// </summary>
|
||||
Spotlight,
|
||||
|
||||
/// <summary>
|
||||
/// The sports
|
||||
/// </summary>
|
||||
Sports,
|
||||
|
||||
/// <summary>
|
||||
/// The snow
|
||||
/// </summary>
|
||||
Snow,
|
||||
|
||||
/// <summary>
|
||||
/// The beach
|
||||
/// </summary>
|
||||
Beach,
|
||||
|
||||
/// <summary>
|
||||
/// The very long
|
||||
/// </summary>
|
||||
VeryLong,
|
||||
|
||||
/// <summary>
|
||||
/// The fixed FPS
|
||||
/// </summary>
|
||||
FixedFps,
|
||||
|
||||
/// <summary>
|
||||
/// The anti shake
|
||||
/// </summary>
|
||||
AntiShake,
|
||||
|
||||
/// <summary>
|
||||
/// The fireworks
|
||||
/// </summary>
|
||||
Fireworks
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the different AWB (Auto White Balance) modes for the Raspberry Pi's camera module
|
||||
/// </summary>
|
||||
public enum CameraWhiteBalanceMode
|
||||
{
|
||||
/// <summary>
|
||||
/// No white balance
|
||||
/// </summary>
|
||||
Off,
|
||||
|
||||
/// <summary>
|
||||
/// The automatic
|
||||
/// </summary>
|
||||
Auto,
|
||||
|
||||
/// <summary>
|
||||
/// The sun
|
||||
/// </summary>
|
||||
Sun,
|
||||
|
||||
/// <summary>
|
||||
/// The cloud
|
||||
/// </summary>
|
||||
Cloud,
|
||||
|
||||
/// <summary>
|
||||
/// The shade
|
||||
/// </summary>
|
||||
Shade,
|
||||
|
||||
/// <summary>
|
||||
/// The tungsten
|
||||
/// </summary>
|
||||
Tungsten,
|
||||
|
||||
/// <summary>
|
||||
/// The fluorescent
|
||||
/// </summary>
|
||||
Fluorescent,
|
||||
|
||||
/// <summary>
|
||||
/// The incandescent
|
||||
/// </summary>
|
||||
Incandescent,
|
||||
|
||||
/// <summary>
|
||||
/// The flash
|
||||
/// </summary>
|
||||
Flash,
|
||||
|
||||
/// <summary>
|
||||
/// The horizon
|
||||
/// </summary>
|
||||
Horizon
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the available image effects for the Raspberry Pi's camera module
|
||||
/// </summary>
|
||||
public enum CameraImageEffect
|
||||
{
|
||||
/// <summary>
|
||||
/// No effect
|
||||
/// </summary>
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// The negative
|
||||
/// </summary>
|
||||
Negative,
|
||||
|
||||
/// <summary>
|
||||
/// The solarise
|
||||
/// </summary>
|
||||
Solarise,
|
||||
|
||||
/// <summary>
|
||||
/// The whiteboard
|
||||
/// </summary>
|
||||
Whiteboard,
|
||||
|
||||
/// <summary>
|
||||
/// The blackboard
|
||||
/// </summary>
|
||||
Blackboard,
|
||||
|
||||
/// <summary>
|
||||
/// The sketch
|
||||
/// </summary>
|
||||
Sketch,
|
||||
|
||||
/// <summary>
|
||||
/// The denoise
|
||||
/// </summary>
|
||||
Denoise,
|
||||
|
||||
/// <summary>
|
||||
/// The emboss
|
||||
/// </summary>
|
||||
Emboss,
|
||||
|
||||
/// <summary>
|
||||
/// The oil paint
|
||||
/// </summary>
|
||||
OilPaint,
|
||||
|
||||
/// <summary>
|
||||
/// The hatch
|
||||
/// </summary>
|
||||
Hatch,
|
||||
|
||||
/// <summary>
|
||||
/// Graphite Pen
|
||||
/// </summary>
|
||||
GPen,
|
||||
|
||||
/// <summary>
|
||||
/// The pastel
|
||||
/// </summary>
|
||||
Pastel,
|
||||
|
||||
/// <summary>
|
||||
/// The water colour
|
||||
/// </summary>
|
||||
WaterColour,
|
||||
|
||||
/// <summary>
|
||||
/// The film
|
||||
/// </summary>
|
||||
Film,
|
||||
|
||||
/// <summary>
|
||||
/// The blur
|
||||
/// </summary>
|
||||
Blur,
|
||||
|
||||
/// <summary>
|
||||
/// The saturation
|
||||
/// </summary>
|
||||
Saturation,
|
||||
|
||||
/// <summary>
|
||||
/// The solour swap
|
||||
/// </summary>
|
||||
SolourSwap,
|
||||
|
||||
/// <summary>
|
||||
/// The washed out
|
||||
/// </summary>
|
||||
WashedOut,
|
||||
|
||||
/// <summary>
|
||||
/// The colour point
|
||||
/// </summary>
|
||||
ColourPoint,
|
||||
|
||||
/// <summary>
|
||||
/// The colour balance
|
||||
/// </summary>
|
||||
ColourBalance,
|
||||
|
||||
/// <summary>
|
||||
/// The cartoon
|
||||
/// </summary>
|
||||
Cartoon
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the different metering modes for the Raspberry Pi's camera module
|
||||
/// </summary>
|
||||
public enum CameraMeteringMode
|
||||
{
|
||||
/// <summary>
|
||||
/// The average
|
||||
/// </summary>
|
||||
Average,
|
||||
|
||||
/// <summary>
|
||||
/// The spot
|
||||
/// </summary>
|
||||
Spot,
|
||||
|
||||
/// <summary>
|
||||
/// The backlit
|
||||
/// </summary>
|
||||
Backlit,
|
||||
|
||||
/// <summary>
|
||||
/// The matrix
|
||||
/// </summary>
|
||||
Matrix,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the different image rotation modes for the Raspberry Pi's camera module
|
||||
/// </summary>
|
||||
public enum CameraImageRotation
|
||||
{
|
||||
/// <summary>
|
||||
/// No rerotation
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// 90 Degrees
|
||||
/// </summary>
|
||||
Degrees90 = 90,
|
||||
|
||||
/// <summary>
|
||||
/// 180 Degrees
|
||||
/// </summary>
|
||||
Degrees180 = 180,
|
||||
|
||||
/// <summary>
|
||||
/// 270 degrees
|
||||
/// </summary>
|
||||
Degrees270 = 270
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the different DRC (Dynamic Range Compensation) modes for the Raspberry Pi's camera module
|
||||
/// Helpful for low light photos
|
||||
/// </summary>
|
||||
public enum CameraDynamicRangeCompensation
|
||||
{
|
||||
/// <summary>
|
||||
/// The off setting
|
||||
/// </summary>
|
||||
Off,
|
||||
|
||||
/// <summary>
|
||||
/// The low
|
||||
/// </summary>
|
||||
Low,
|
||||
|
||||
/// <summary>
|
||||
/// The medium
|
||||
/// </summary>
|
||||
Medium,
|
||||
|
||||
/// <summary>
|
||||
/// The high
|
||||
/// </summary>
|
||||
High
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the bit-wise mask flags for the available annotation elements for the Raspberry Pi's camera module
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum CameraAnnotation
|
||||
{
|
||||
/// <summary>
|
||||
/// The none
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// The time
|
||||
/// </summary>
|
||||
Time = 4,
|
||||
|
||||
/// <summary>
|
||||
/// The date
|
||||
/// </summary>
|
||||
Date = 8,
|
||||
|
||||
/// <summary>
|
||||
/// The shutter settings
|
||||
/// </summary>
|
||||
ShutterSettings = 16,
|
||||
|
||||
/// <summary>
|
||||
/// The caf settings
|
||||
/// </summary>
|
||||
CafSettings = 32,
|
||||
|
||||
/// <summary>
|
||||
/// The gain settings
|
||||
/// </summary>
|
||||
GainSettings = 64,
|
||||
|
||||
/// <summary>
|
||||
/// The lens settings
|
||||
/// </summary>
|
||||
LensSettings = 128,
|
||||
|
||||
/// <summary>
|
||||
/// The motion settings
|
||||
/// </summary>
|
||||
MotionSettings = 256,
|
||||
|
||||
/// <summary>
|
||||
/// The frame number
|
||||
/// </summary>
|
||||
FrameNumber = 512,
|
||||
|
||||
/// <summary>
|
||||
/// The solid background
|
||||
/// </summary>
|
||||
SolidBackground = 1024,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the different H.264 encoding profiles to be used when capturing video.
|
||||
/// </summary>
|
||||
public enum CameraH264Profile
|
||||
{
|
||||
/// <summary>
|
||||
/// BP: Primarily for lower-cost applications with limited computing resources,
|
||||
/// this profile is used widely in videoconferencing and mobile applications.
|
||||
/// </summary>
|
||||
Baseline,
|
||||
|
||||
/// <summary>
|
||||
/// MP: Originally intended as the mainstream consumer profile for broadcast
|
||||
/// and storage applications, the importance of this profile faded when the High profile was developed for those applications.
|
||||
/// </summary>
|
||||
Main,
|
||||
|
||||
/// <summary>
|
||||
/// HiP: The primary profile for broadcast and disc storage applications, particularly
|
||||
/// for high-definition television applications (this is the profile adopted into HD DVD and Blu-ray Disc, for example).
|
||||
/// </summary>
|
||||
High
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user