1 //
2 // Copyright (c) 2010-2024 Antmicro
3 //
4 //  This file is licensed under the MIT License.
5 //  Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using System.IO;
9 using System.Linq;
10 using Antmicro.Renode.UserInterface.Tokenizer;
11 using AntShell.Commands;
12 using Antmicro.Renode.Exceptions;
13 using Antmicro.Renode.Utilities;
14 using Antmicro.Renode.Backends.Display;
15 
16 namespace Antmicro.Renode.UserInterface.Commands
17 {
18     public class DisplayImageCommand : AutoLoadCommand
19     {
PrintHelp(ICommandInteraction writer)20         public override void PrintHelp(ICommandInteraction writer)
21         {
22             base.PrintHelp(writer);
23             writer.WriteLine();
24             writer.WriteLine("Usage:");
25             writer.WriteLine($"{Name} width height");
26             writer.WriteLine("Generates testing image");
27             writer.WriteLine();
28             writer.WriteLine($"{Name} path_to_image");
29             writer.WriteLine("Supported file formats:");
30             writer.WriteLine("jpeg");
31             writer.WriteLine("png");
32         }
33 
34         [Runnable]
Run(ICommandInteraction writer, StringToken pathToImage)35         public void Run(ICommandInteraction writer, StringToken pathToImage)
36         {
37             Run(writer, pathToImage.Value);
38         }
39 
40         [Runnable]
Run(ICommandInteraction writer, DecimalIntegerToken widthToken, DecimalIntegerToken heightToken)41         public void Run(ICommandInteraction writer, DecimalIntegerToken widthToken, DecimalIntegerToken heightToken)
42         {
43             // This method creates white rectangle, intended for testing purposes.
44             var width = (int)widthToken.Value;
45             var height = (int)heightToken.Value;
46             if(width <= 0 || height <= 0)
47             {
48                 throw new RecoverableException("Width and height must be positive values");
49             }
50 
51             var bytes = new byte[width * height * RawImageData.PixelFormat.GetColorDepth()];
52             for(var i = 0; i < bytes.Length; ++i)
53             {
54                 bytes[i] = (byte)0xFF;
55             }
56             var image = new RawImageData(bytes, width, height);
57             writer.WriteRaw(InlineImage.Encode(image.ToPng()));
58         }
59 
DisplayImageCommand(Monitor monitor)60         public DisplayImageCommand(Monitor monitor)
61             : base(monitor, "displayImage", "Displays image in Monitor")
62         {
63         }
64 
Run(ICommandInteraction writer, ReadFilePath pathToImage)65         private void Run(ICommandInteraction writer, ReadFilePath pathToImage)
66         {
67             using(var file = new FileStream(pathToImage, FileMode.Open))
68             {
69                 if(!CheckFormat(file))
70                 {
71                     writer.WriteError("Bad image format. Supported formats: jpeg, png");
72                     return;
73                 }
74 
75                 writer.WriteRaw(InlineImage.Encode(file));
76             }
77         }
78 
CheckFormat(Stream file)79         private static bool CheckFormat(Stream file)
80         {
81             var head = new byte[8];
82             file.Seek(0, SeekOrigin.Begin);
83             file.Read(head, 0, 8);
84             file.Seek(0, SeekOrigin.Begin);
85 
86             if(head.Take(JpegPrefix.Length).SequenceEqual(JpegPrefix))
87             {
88                 return true;
89             }
90 
91             if(head.Take(PngPrefix.Length).SequenceEqual(PngPrefix))
92             {
93                 return true;
94             }
95 
96             return false;
97         }
98 
99         private static readonly byte[] JpegPrefix = {0xff, 0xd8, 0xff};
100         private static readonly byte[] PngPrefix = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
101     }
102 }
103