using Unosquare.Swan; using System; using System.Collections.Generic; using System.Text; namespace Unosquare.RaspberryIO.Camera { /// /// Defines a wrapper for the raspistill program and its settings (command-line arguments) /// /// public class CameraStillSettings : CameraSettingsBase { private Int32 _rotate; /// public override String CommandName => "raspistill"; /// /// Gets or sets a value indicating whether the preview window (if enabled) uses native capture resolution /// This may slow down preview FPS /// public Boolean CaptureDisplayPreviewAtResolution { get; set; } = false; /// /// Gets or sets the encoding format the hardware will use for the output. /// public CameraImageEncodingFormat CaptureEncoding { get; set; } = CameraImageEncodingFormat.Jpg; /// /// Gets or sets the quality for JPEG only encoding mode. /// Value ranges from 0 to 100 /// public Int32 CaptureJpegQuality { get; set; } = 90; /// /// Gets or sets a value indicating whether the JPEG encoder should add raw bayer metadata. /// public Boolean CaptureJpegIncludeRawBayerMetadata { get; set; } = false; /// /// JPEG EXIF data /// Keys and values must be already properly escaped. Otherwise the command will fail. /// public Dictionary CaptureJpegExtendedInfo { get; } = new Dictionary(); /// /// Gets or sets a value indicating whether [horizontal flip]. /// /// /// true if [horizontal flip]; otherwise, false. /// public Boolean HorizontalFlip { get; set; } = false; /// /// Gets or sets a value indicating whether [vertical flip]. /// /// /// true if [vertical flip]; otherwise, false. /// public Boolean VerticalFlip { get; set; } = false; /// /// Gets or sets the rotation. /// /// Valid range 0-359 public Int32 Rotation { get => this._rotate; set { if(value < 0 || value > 359) { throw new ArgumentOutOfRangeException(nameof(value), "Valid range 0-359"); } this._rotate = value; } } /// public override String CreateProcessArguments() { StringBuilder sb = new StringBuilder(base.CreateProcessArguments()); _ = sb.Append($" -e {this.CaptureEncoding.ToString().ToLowerInvariant()}"); // JPEG Encoder specific arguments if(this.CaptureEncoding == CameraImageEncodingFormat.Jpg) { _ = sb.Append($" -q {this.CaptureJpegQuality.Clamp(0, 100).ToString(Ci)}"); if(this.CaptureJpegIncludeRawBayerMetadata) { _ = sb.Append(" -r"); } // JPEG EXIF data if(this.CaptureJpegExtendedInfo.Count > 0) { foreach(KeyValuePair kvp in this.CaptureJpegExtendedInfo) { if(String.IsNullOrWhiteSpace(kvp.Key) || String.IsNullOrWhiteSpace(kvp.Value)) { continue; } _ = sb.Append($" -x \"{kvp.Key.Replace("\"", "'")}={kvp.Value.Replace("\"", "'")}\""); } } } // Display preview settings if(this.CaptureDisplayPreview && this.CaptureDisplayPreviewAtResolution) { _ = sb.Append(" -fp"); } if(this.Rotation != 0) { _ = sb.Append($" -rot {this.Rotation}"); } if(this.HorizontalFlip) { _ = sb.Append(" -hf"); } if(this.VerticalFlip) { _ = sb.Append(" -vf"); } return sb.ToString(); } } }