Images.cs 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. using SixLabors.ImageSharp;
  2. using SixLabors.ImageSharp.PixelFormats;
  3. using SixLabors.ImageSharp.Processing;
  4. using System;
  5. using System.Collections.Concurrent;
  6. using System.IO;
  7. using Terminal.Gui;
  8. using Color = Terminal.Gui.Color;
  9. namespace UICatalog.Scenarios {
  10. [ScenarioMetadata (Name: "Images", Description: "Demonstration of how to render an image with/without true color support.")]
  11. [ScenarioCategory ("Colors")]
  12. public class Images : Scenario {
  13. public override void Setup ()
  14. {
  15. base.Setup ();
  16. var x = 0;
  17. var y = 0;
  18. var canTrueColor = Application.Driver.SupportsTrueColor;
  19. var lblDriverName = new Label ($"Current driver is {Application.Driver.GetType ().Name}") {
  20. X = x,
  21. Y = y++
  22. };
  23. Win.Add (lblDriverName);
  24. y++;
  25. var cbSupportsTrueColor = new CheckBox ("Driver supports true color ") {
  26. X = x,
  27. Y = y++,
  28. Checked = canTrueColor,
  29. CanFocus = false
  30. };
  31. Win.Add (cbSupportsTrueColor);
  32. var cbUseTrueColor = new CheckBox ("Use true color") {
  33. X = x,
  34. Y = y++,
  35. Checked = Application.Driver.Force16Colors,
  36. Enabled = canTrueColor,
  37. };
  38. cbUseTrueColor.Toggled += (_, evt) => Application.Driver.Force16Colors = evt.NewValue ?? false;
  39. Win.Add (cbUseTrueColor);
  40. var btnOpenImage = new Button ("Open Image") {
  41. X = x,
  42. Y = y++
  43. };
  44. Win.Add (btnOpenImage);
  45. var imageView = new ImageView () {
  46. X = x,
  47. Y = y++,
  48. Width = Dim.Fill (),
  49. Height = Dim.Fill (),
  50. };
  51. Win.Add (imageView);
  52. btnOpenImage.Clicked += (_, _) => {
  53. var ofd = new OpenDialog ("Open Image") { AllowsMultipleSelection = false };
  54. Application.Run (ofd);
  55. if (ofd.Canceled)
  56. return;
  57. var path = ofd.FilePaths [0];
  58. if (string.IsNullOrWhiteSpace (path)) {
  59. return;
  60. }
  61. if (!File.Exists (path)) {
  62. return;
  63. }
  64. Image<Rgba32> img;
  65. try {
  66. img = Image.Load<Rgba32> (File.ReadAllBytes (path));
  67. } catch (Exception ex) {
  68. MessageBox.ErrorQuery ("Could not open file", ex.Message, "Ok");
  69. return;
  70. }
  71. imageView.SetImage (img);
  72. };
  73. }
  74. class ImageView : View {
  75. private Image<Rgba32> fullResImage;
  76. private Image<Rgba32> matchSize;
  77. ConcurrentDictionary<Rgba32, Attribute> cache = new ConcurrentDictionary<Rgba32, Attribute> ();
  78. internal void SetImage (Image<Rgba32> image)
  79. {
  80. fullResImage = image;
  81. this.SetNeedsDisplay ();
  82. }
  83. public override void OnDrawContent(Rect bounds)
  84. {
  85. base.OnDrawContent (bounds);
  86. if (fullResImage == null) {
  87. return;
  88. }
  89. // if we have not got a cached resized image of this size
  90. if (matchSize == null || bounds.Width != matchSize.Width || bounds.Height != matchSize.Height) {
  91. // generate one
  92. matchSize = fullResImage.Clone (x => x.Resize (bounds.Width, bounds.Height));
  93. }
  94. for (int y = 0; y < bounds.Height; y++) {
  95. for (int x = 0; x < bounds.Width; x++) {
  96. var rgb = matchSize [x, y];
  97. var attr = cache.GetOrAdd (rgb, (rgb) => new Attribute (new Color (), new Color (rgb.R, rgb.G, rgb.B)));
  98. Driver.SetAttribute (attr);
  99. AddRune (x, y, (System.Text.Rune)' ');
  100. }
  101. }
  102. }
  103. }
  104. }
  105. }