Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Текст программы.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
102.68 Кб
Скачать

SteganogramBmp.Cs

using System;

using System.IO;

using VStepanov.CourseWork.First;

using VStepanov.CourseWork.First.Binary;

namespace VStepanov.CourseWork.First.Steganography

{

    /// <summary>

    /// Представляет стеганограмму, в качестве контейнера использующую изображения в BMP-формате

    /// и методы работы с ней.

    /// </summary>

    public sealed class SteganogramBmp : Steganogram

    {

        #region Поля объекта класса

        /// <summary>

        /// Информация о BMP-контейнере.

        /// </summary>

        private BmpFileHeader _bmpFileHeader; 

        #endregion

        #region Конструкторы

        /// <summary>

        /// Связывает стеганограмму с BMP-контейнером и выполняет инициализацию полей информации.

        /// </summary>

        /// <param name="fileInfo">Информация и методы для работы с файлом-контейнером.</param>

        public SteganogramBmp(FileInfo fileInfo) : base(fileInfo) {}

        #endregion

        #region Запись стеганографических данных в файл

        /// <summary>

        /// Записывает информацию о стеганограмме в файл.

        /// </summary>

        /// <param name="steganogramInfo">Информация о записываемой стеганограмме.</param>

        protected override void WriteInfoToFile(SteganogramInfo steganogramInfo)

        {

            byte[] infoData = SteganogramInfo.GetBytes(steganogramInfo);

            byte[] mixedData = MixDataToImageBytes(infoData, SteganogramInfo.nLastBitsUsingForInfo);

            WriteBytesToFile(mixedData, _bmpFileHeader.Offset);

        }

        /// <summary>

        /// Записывает сообщение в файл-контейнер.

        /// </summary>

        /// <param name="steganogramInfo">Информация о записываемой стеганограмме, определяет параметры записи сообщения.</param>

        /// <param name="steganogramMessage">Сообщение, подлежащее записи.</param>

        protected override void WriteMessageToFile(SteganogramInfo steganogramInfo, SteganogramMessage steganogramMessage)

        {

            byte[] messageData = SteganogramMessage.GetBytes(steganogramMessage);

            byte[] mixedData   = MixDataToImageBytes(messageData, steganogramInfo.nLastBitsUsing);

            int totalOffset = _bmpFileHeader.Offset + SteganogramInfo.StructureSize * SteganogramInfo.PartsForInfo;

            WriteBytesToFile(mixedData, totalOffset);

        }

        /// <summary>

        /// Объединяет данные для записи и исходные байты изображения. Непосредственное стеганографирование производится именно этим методом.

        /// </summary>

        /// <param name="data">Данные, подлежащие стеганографированию.</param>

        /// <param name="nLastBitsUsing">Число последних бит в каждом байте изображения, используемое для записи.</param>

        /// <returns>Массив исходных байт изображения, последние <see cref="nLastBitsUsing"/> байт которого замещены частями данных <see cref="data"/>.</returns>

        private byte[] MixDataToImageBytes(byte[] data, int nLastBitsUsing)

        {

            int parts = CommonMethods.GetPartsCount(nLastBitsUsing);

            int totalOffset = _bmpFileHeader.Offset + SteganogramInfo.StructureSize * SteganogramInfo.PartsForInfo;

            byte[] imageBytes = ReadBytesFromFile(data.Length * parts, totalOffset);

            byte[] mixedData  = ByteMixer.MixDataIntoBytes(imageBytes, data, nLastBitsUsing);

            return mixedData;

        } 

        #endregion

        #region Чтение стеганографических данных из файла

        /// <summary>

        /// Возвращает сообщение, считанное из файла-контейнера.

        /// </summary>

        /// <returns>Сообщение, содержавшееся в стеганограмме.</returns>

        public override SteganogramMessage GetMessage()

        {

            if (Info == null)

            {

                throw new NullReferenceException("Контейнер не содержит стеганограмму.");

            }

            var steganogramInfo = Info.Value;

            int parts = CommonMethods.GetPartsCount(steganogramInfo.nLastBitsUsing);

            int nBytesToGet = steganogramInfo.MessageSize * parts;

            int totalOffset = _bmpFileHeader.Offset + SteganogramInfo.StructureSize * SteganogramInfo.PartsForInfo;

            byte[] data = ReadBytesFromFile(nBytesToGet, totalOffset);

            data = ByteMixer.ExtractDataFromBytes(data, steganogramInfo.nLastBitsUsing);

            return SteganogramMessage.FromBytes(data);

        }

        #endregion

        #region Прочие методы класса

        /// <summary>

        /// Возвращает максимальное число байт, которое можно записать в контейнер.

        /// </summary>

        /// <param name="nLastBitsUsing">Число последних бит в каждом байте изображения, используемое для записи.</param>

        /// <returns>Максимальное число байт</returns>

        public override int GetMessageMaxLength(int nLastBitsUsing)

        {

            int parts = CommonMethods.GetPartsCount(nLastBitsUsing);

            int infoOverhead = SteganogramInfo.StructureSize * SteganogramInfo.PartsForInfo

                + SteganogramMessage.MessageHeaderSize * parts;

            return _bmpFileHeader.ImageSize / parts - infoOverhead;

        }

        /// <summary>

        /// Производит необходимые действия для инициализации объекта класса.

        /// 

        /// Проверяет файл-контейнер на соответствие формату BMP, в случае валидности -

        /// проверяет его на наличие стеганографической информации.

        /// </summary>

        protected override void InitializeSteganogram()

        {

            _bmpFileHeader = new BmpFileHeader(ContainerFile.FullName);

            if (!_bmpFileHeader.IsValidBmpFile())

            {

                throw new FileLoadException("Файл не является подходящим файлом формата BMP.", ContainerFile.FullName);

            }

            byte[] imageData = ReadBytesFromFile(SteganogramInfo.StructureSize * SteganogramInfo.PartsForInfo, _bmpFileHeader.Offset);

            byte[] extractedData = ByteMixer.ExtractDataFromBytes(imageData, SteganogramInfo.nLastBitsUsingForInfo);

            SteganogramInfo steganogramInfo = SteganogramInfo.FromBytes(extractedData);

            if (steganogramInfo.Signature == CommonConstants.SteganographicalSignature)

            {

                Info = steganogramInfo;

            }

            else

            {

                Info = null;

            }

        }

        #endregion

    }

}