Beispiel #1
0
        public static void Compose()
        {
            ComposeConfiguration currentConfig = new ComposeConfiguration();

            GetFilePath(currentConfig);
            using (FileStream fileStream = new FileStream(currentConfig.WorkingPath, FileMode.Open))
            {
                currentConfig.FileLength = fileStream.Length;
                WriteLine($"The size of this file is {currentConfig.FileLength} bytes. ");
                GetOffsetGenerator(currentConfig);
                WriteOffset(currentConfig, fileStream);
                ProcessFileTail(currentConfig, fileStream);
                GetImageSize(currentConfig);
                Bitmap    bitmap    = new Bitmap(currentConfig.ImgWidth.Value, currentConfig.ImgHeight.Value);
                Stopwatch stopWatch = Stopwatch.StartNew();
                stopWatch.Start();
                WriteLine("Started generating image... ");
                PlotPixels(currentConfig, fileStream, bitmap);
                stopWatch.Stop();
                WriteLine($"Process completed in {stopWatch.Elapsed}. ");
                SaveImage(bitmap, currentConfig);
            }
            File.Delete(currentConfig.WorkingPath); // However, if the user terminates the program before it finishes by itself, the temp file will not be deleted and thus disk space will be unnecessarily occupied in a relatively long term.
            WriteLine("Done. ");
        }
Beispiel #2
0
        private static void ParseWidthArg(Dictionary <int, string> inputArgs, ComposeConfiguration parsedConfig)
        {
            Func <KeyValuePair <int, string>, bool> isWidthArg = x => x.Value == "-w" || x.Value == "/w";

            switch (inputArgs.Count(isWidthArg))
            {
            case 0:
                break;

            case 1:
                try
                {
                    parsedConfig.ImgWidth = int.Parse(inputArgs[inputArgs.First(isWidthArg).Key + 1]);
                }
                catch (Exception e)
                {
                    WriteLine($"Error: {e.Message} Please check your input and try again. ");
                }
                break;

            default:
                WriteLine("Error: -w argument can only be used once. Please check your input and try again. ");
                break;
            }
        }
Beispiel #3
0
        private static void GetImageSize(ComposeConfiguration currentConfig)
        {
            WriteLine("By default, an image with width and height as consistent as possible will be generated. However, you may specify the width, height, or both dimensions of the image. ");
            while (true)
            {
                WriteLine("Please specify the width of the image if you would like to, otherwise, press Enter to continue. ");
                try
                {
                    string inputWidth = ReadLine();
                    if (!string.IsNullOrWhiteSpace(inputWidth))
                    {
                        currentConfig.ImgWidth = int.Parse(inputWidth);
                    }
                    break;
                }
                catch (Exception e)
                {
                    WriteLine($"Error: {e.Message} Please check your input and try again: ");
                }
            }

            WriteLine("Please specify the height of the image if you would like to, otherwise, press Enter to continue. ");
            while (true)
            {
                try
                {
                    string inputHeight = ReadLine();
                    if (!string.IsNullOrWhiteSpace(inputHeight))
                    {
                        currentConfig.ImgHeight = int.Parse(inputHeight);
                    }
                    break;
                }
                catch (Exception e)
                {
                    WriteLine($"Error: {e.Message} Please check your input and try again: ");
                }
            }

            long pixelCount = currentConfig.FileLength / 3;

            if (currentConfig.ImgHeight.HasValue && currentConfig.ImgWidth.HasValue)
            {
                if (currentConfig.ImgHeight * currentConfig.ImgWidth > pixelCount)
                {
                    WriteLine("Warning: Your specified size of image has a larger capability than the size of the file. Please note that the remaining pixels will be filled with black color. ");
                }
                else if (currentConfig.ImgHeight * currentConfig.ImgWidth < pixelCount)
                {
                    WriteLine("Warning: Your specified size of image cannot fully contain the information stored in the file. Please note that the part of the file beyond the capability of the image will be truncated. ");
                }
            }
            else
            {
                CalculateImageSize(currentConfig);
                WriteLine($"An image of {currentConfig.ImgWidth} pixels in width and {currentConfig.ImgHeight} pixels in height will be generated. ");
            }
        }
Beispiel #4
0
        private static void ParseForCompose(string[] args)
        {
            switch (args.Count())
            {
            case 1:
                Composer.Compose();
                break;

            case 3:
                try
                {
                    Composer.SilentCompose(new ComposeConfiguration
                    {
                        SourcePath = args[1],
                        SavePath   = args[2]
                    });
                }
                catch (Exception e)
                {
                    WriteLine($"Error: {e.Message} Please check your input and try again. ");
                }
                break;

            case 5:
            case 7:
            case 9:
                Dictionary <int, string> inputArgs = new Dictionary <int, string>();
                for (int i = 0; i < args.Count(); i++)
                {
                    inputArgs.Add(i, args[i]);
                }
                ComposeConfiguration parsedConfig = new ComposeConfiguration
                {
                    SourcePath = args[1],
                    SavePath   = args[2]
                };
                ParseWidthArg(inputArgs, parsedConfig);
                ParseHeightArg(inputArgs, parsedConfig);
                ParseSeedArg(inputArgs, parsedConfig);
                try
                {
                    Composer.SilentCompose(parsedConfig);
                }
                catch (Exception e)
                {
                    WriteLine($"Error: {e.Message} Please check your input and try again. ");
                }
                break;

            default:
                WriteLine("Error: Improper number of arguments. Please check your input and try again. ");
                break;
            }
        }
Beispiel #5
0
 private static void WriteOffset(ComposeConfiguration currentConfig, FileStream fileStream)
 {
     if (currentConfig.OffsetGenerator != null)
     {
         fileStream.Seek(0, SeekOrigin.Begin);
         for (int i = 0; i < currentConfig.FileLength; i++)
         {
             int  originalByte   = fileStream.ReadByte();
             byte byteWithOffset = (byte)((originalByte + currentConfig.OffsetGenerator.Next(256)) % 256); // Expectation: ((0 + 0) % 256) = 0 to ((255 + 255) % 256) = 254
             fileStream.Seek(-1, SeekOrigin.Current);
             fileStream.WriteByte(byteWithOffset);
         }
     }
 }
Beispiel #6
0
        private static void PlotPixels(ComposeConfiguration currentConfig, FileStream fileStream, Bitmap bitmap)
        {
            long currentPosition = 0;

            for (int y = 0; y < currentConfig.ImgHeight.Value; y++)
            {
                for (int x = 0; x < currentConfig.ImgWidth.Value; x++)
                {
                    Color currentColor = GetCurrentColor(currentPosition, fileStream, currentConfig);
                    bitmap.SetPixel(x, y, currentColor);
                    currentPosition += 3;
                }
            }
        }
Beispiel #7
0
 public static void SilentCompose(ComposeConfiguration currentConfig)
 {
     currentConfig.WorkingPath = Path.GetTempFileName();
     File.Copy(currentConfig.SourcePath, currentConfig.WorkingPath, true);
     using (FileStream fileStream = new FileStream(currentConfig.WorkingPath, FileMode.Open))
     {
         currentConfig.FileLength = fileStream.Length;
         WriteOffset(currentConfig, fileStream);
         ProcessFileTail(currentConfig, fileStream);
         CalculateImageSize(currentConfig);
         Bitmap bitmap = new Bitmap(currentConfig.ImgWidth.Value, currentConfig.ImgHeight.Value);
         PlotPixels(currentConfig, fileStream, bitmap);
         bitmap.Save(currentConfig.SavePath);
     }
     File.Delete(currentConfig.WorkingPath);
 }
Beispiel #8
0
        private static void ProcessFileTail(ComposeConfiguration currentConfig, FileStream fileStream)
        {
            fileStream.Seek(0, SeekOrigin.End);
            fileStream.WriteByte(23);                   // Append 'End of Transmission Block' byte at the end of the file.
            switch ((currentConfig.FileLength + 1) % 3) // Ensure the length (in bytes) is divisible by 3, which is the number of bytes that a RGB24 pixel may contain.
            {
            case 1:
                fileStream.WriteByte(0);
                fileStream.WriteByte(0);
                break;

            case 2:
                fileStream.WriteByte(0);
                break;
            }
            currentConfig.FileLength = fileStream.Length;
        }
Beispiel #9
0
 private static void SaveImage(Bitmap bitmap, ComposeConfiguration currentConfig)
 {
     WriteLine("Please specify the path for the image to be saved: ");
     while (true)
     {
         try
         {
             currentConfig.SavePath = Path.GetFullPath(ReadLine());
             bitmap.Save(currentConfig.SavePath);
             WriteLine("Image saved. ");
             break;
         }
         catch (Exception e)
         {
             WriteLine($"Error: {e.Message} Please check your input and try again: ");
         }
     }
 }
Beispiel #10
0
 private static void GetFilePath(ComposeConfiguration currentConfig)
 {
     WriteLine("Please specify the path for the file to be read: ");
     while (true)
     {
         try
         {
             currentConfig.SourcePath  = Path.GetFullPath(ReadLine());
             currentConfig.WorkingPath = Path.GetTempFileName();
             File.Copy(currentConfig.SourcePath, currentConfig.WorkingPath, true);
             break;
         }
         catch (Exception e)
         {
             WriteLine($"Error: {e.Message} Please check your input and try again: ");
         }
     }
 }
Beispiel #11
0
 private static void GetOffsetGenerator(ComposeConfiguration currentConfig)
 {
     WriteLine("You may specify an integer as seed to encrypt the image if you would like to, otherwise, press Enter to continue. Please note that you will need to enter the same seed when reading the image generated to correctly decompose it into a file. ");
     while (true)
     {
         try
         {
             string inputSeed = ReadLine();
             if (!string.IsNullOrWhiteSpace(inputSeed))
             {
                 currentConfig.OffsetSeed      = int.Parse(inputSeed);
                 currentConfig.OffsetGenerator = new Random(currentConfig.OffsetSeed.Value);
             }
             break;
         }
         catch (Exception e)
         {
             WriteLine($"Error: {e.Message} Please check your input and try again: ");
         }
     }
 }
Beispiel #12
0
        private static void CalculateImageSize(ComposeConfiguration currentConfig)
        {
            double pixelCount = currentConfig.FileLength / 3; // currentConfig.FileLength can be surely divided by 3 with no remainder, however pixelCount need to be in a non-integral type to prevent force flooring during division operation with an int.

            if (currentConfig.ImgHeight.HasValue && !currentConfig.ImgWidth.HasValue)
            {
                double imgWidth = pixelCount / currentConfig.ImgHeight.Value;
                currentConfig.ImgWidth = (int)Math.Ceiling(imgWidth);
            }
            else if (!currentConfig.ImgHeight.HasValue && currentConfig.ImgWidth.HasValue)
            {
                double imgHeight = pixelCount / currentConfig.ImgWidth.Value;
                currentConfig.ImgHeight = (int)Math.Ceiling(imgHeight);
            }
            else if (!currentConfig.ImgHeight.HasValue && !currentConfig.ImgWidth.HasValue)
            {
                currentConfig.ImgHeight = (int)Math.Ceiling(Math.Sqrt(pixelCount));
                double imgWidth = pixelCount / currentConfig.ImgHeight.Value;
                currentConfig.ImgWidth = (int)Math.Ceiling(imgWidth);
            }
        }
Beispiel #13
0
 private static Color GetCurrentColor(long currentPosition, FileStream fileStream, ComposeConfiguration currentConfig)
 {
     if (currentPosition < currentConfig.FileLength)
     {
         fileStream.Position = currentPosition;
         int red   = fileStream.ReadByte();
         int green = fileStream.ReadByte();
         int blue  = fileStream.ReadByte();
         return(Color.FromArgb(red, green, blue));
     }
     return(Color.Black);
 }