SixelEncoderTests.cs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Color = Terminal.Gui.Color;
  7. namespace UnitTests.Drawing;
  8. public class SixelEncoderTests
  9. {
  10. [Fact]
  11. public void EncodeSixel_RedSquare12x12_ReturnsExpectedSixel ()
  12. {
  13. var expected = "\u001bP" + // Start sixel sequence
  14. "0;0;0" + // Defaults for aspect ratio and grid size
  15. "q" + // Signals beginning of sixel image data
  16. "\"1;1;12;2" + // no scaling factors (1x1) and filling 12px width with 2 'sixel' height = 12 px high
  17. /*
  18. * Definition of the color palette
  19. */
  20. "#0;2;100;0;0" + // Red color definition in the format "#<index>;<type>;<R>;<G>;<B>" - 2 means RGB. The values range 0 to 100
  21. /*
  22. * Start of the Pixel data
  23. * We draw 6 rows at once, so end up with 2 'lines'
  24. * Both are basically the same and terminate with dollar hyphen (except last row)
  25. * Format is:
  26. * #0 (selects to use color palette index 0 i.e. red)
  27. * !12 (repeat next byte 12 times i.e. the whole length of the row)
  28. * ~ (the byte 111111 i.e. fill completely)
  29. * $ (return to start of line)
  30. * - (move down to next line)
  31. */
  32. "#0!12~$-" +
  33. "#0!12~$" + // Next 6 rows of red pixels
  34. "\u001b\\"; // End sixel sequence
  35. // Arrange: Create a 12x12 bitmap filled with red
  36. var pixels = new Color [12, 12];
  37. for (int x = 0; x < 12; x++)
  38. {
  39. for (int y = 0; y < 12; y++)
  40. {
  41. pixels [x, y] = new Color(255,0,0);
  42. }
  43. }
  44. // Act: Encode the image
  45. var encoder = new SixelEncoder (); // Assuming SixelEncoder is the class that contains the EncodeSixel method
  46. string result = encoder.EncodeSixel (pixels);
  47. // Since image is only red we should only have 1 color definition
  48. Color c1 = Assert.Single (encoder.Quantizer.Palette);
  49. Assert.Equal (new Color(255,0,0),c1);
  50. Assert.Equal (expected, result);
  51. }
  52. [Fact]
  53. public void EncodeSixel_12x12GridPattern3x3_ReturnsExpectedSixel ()
  54. {
  55. /*
  56. * Each block is a 3x3 square, alternating black and white.
  57. * The pattern alternates between rows, creating a checkerboard.
  58. * We have 4 blocks per row, and this repeats over 12x12 pixels.
  59. ███...███...
  60. ███...███...
  61. ███...███...
  62. ...███...███
  63. ...███...███
  64. ...███...███
  65. ███...███...
  66. ███...███...
  67. ███...███...
  68. ...███...███
  69. ...███...███
  70. ...███...███
  71. Because we are dealing with sixels (drawing 6 rows at once) we will
  72. see 2 bands being drawn. We will also see how we have to 'go back over'
  73. the current line after drawing the black (so we can draw the white).
  74. */
  75. var expected = "\u001bP" + // Start sixel sequence
  76. "0;0;0" + // Defaults for aspect ratio and grid size
  77. "q" + // Signals beginning of sixel image data
  78. "\"1;1;12;2" + // no scaling factors (1x1) and filling 12px width with 2 'sixel' height = 12 px high
  79. /*
  80. * Definition of the color palette
  81. */
  82. "#0;2;0;0;0" + // Black color definition (index 0: RGB 0,0,0)
  83. "#1;2;100;100;100" + // White color definition (index 1: RGB 100,100,100)
  84. /*
  85. * Start of the Pixel data
  86. *
  87. * Lets consider only the first 6 pixel (vertically). We have to fill the top 3 black and bottom 3 white.
  88. * So we need to select black and fill 000111. To convert this into a character we must +63 and convert to ASCII
  89. * Later on we will also need to select white and fill the inverse i.e. 111000.
  90. *
  91. * 111000 (binary) → w (ASCII 119).
  92. * 000111 (binary) → F (ASCII 70).
  93. *
  94. * Therefore the lines become
  95. *
  96. * #0 (Select black)
  97. * FFF (fill first 3 pixels horizontally - and top half of band black)
  98. * www (fill next 3 pixels horizontally - bottom half of band black)
  99. * FFFwww (as above to finish the line
  100. *
  101. * Next we must go back and fill the white (on the same band)
  102. * #1 (Select white)
  103. *
  104. */
  105. "#0FFFwwwFFFwww$" + // First pass of top band (Filling black)
  106. "#1wwwFFFwwwFFF$-" + // Second pass of top band (Filling white)
  107. // Sequence repeats exactly the same because top band is actually identical pixels to bottom band
  108. "#0FFFwwwFFFwww$" + // First pass of bottom band (Filling white)
  109. "#1wwwFFFwwwFFF$" + // Second pass of bottom band (Filling black)
  110. "\u001b\\"; // End sixel sequence
  111. // Arrange: Create a 12x12 bitmap with a 3x3 checkerboard pattern
  112. var pixels = new Color [12, 12];
  113. for (int y = 0; y < 12; y++)
  114. {
  115. for (int x = 0; x < 12; x++)
  116. {
  117. // Create a 3x3 checkerboard by alternating the color based on pixel coordinates
  118. if (((x / 3) + (y / 3)) % 2 == 0)
  119. {
  120. pixels [x, y] = new Color (0, 0, 0); // Black
  121. }
  122. else
  123. {
  124. pixels [x, y] = new Color (255, 255, 255); // White
  125. }
  126. }
  127. }
  128. // Act: Encode the image
  129. var encoder = new SixelEncoder (); // Assuming SixelEncoder is the class that contains the EncodeSixel method
  130. string result = encoder.EncodeSixel (pixels);
  131. // We should have only black and white in the palette
  132. Assert.Equal (2, encoder.Quantizer.Palette.Count);
  133. Color black = encoder.Quantizer.Palette.ElementAt (0);
  134. Color white = encoder.Quantizer.Palette.ElementAt(1);
  135. Assert.Equal (new Color (0, 0, 0), black);
  136. Assert.Equal (new Color (255, 255, 255), white);
  137. // Compare the generated SIXEL string with the expected one
  138. Assert.Equal (expected, result);
  139. }
  140. }