
- •VStepanov.CourseWork.First Common.Cs
- •VStepanov.CourseWork.First.Binary BmpInfo.Cs
- •ByteMixer.Cs
- •Relocator.Cs
- •VStepanov.CourseWork.First.Cryptography
- •XorCodec.Cs
- •VStepanov.CourseWork.First.Steganography Steganogram.Cs
- •SteganogramBmp.Cs
- •SteganogramInfo.Cs
- •SteganogramMessage.Cs
- •VStepanov.CourseWork.First.Gui AnimatedForm.Cs
- •FileAddForm.Cs
- •GuiMethods.Cs
- •PasswordRequest.Cs
- •Program.Cs
- •SplashForm.Cs
- •TextAddForm.Cs
- •TextReadForm.Cs
- •Лист регистрации изменений
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
}
}