
Лаб. 3 ЗИ
.docxЛабораторная работа #3
#include <iostream>
#include <vector>
#include <cstdint>
#include <windows.h>
#include <locale>
#include <codecvt>
using namespace std;
void print_binary(uint8_t byte);
void hide_byte_into_pixel(RGBQUAD* pixel, uint8_t hide_byte);
uint8_t extract_byte_from_pixel(RGBQUAD& pixel);
void read_file(wstring& file_name, vector<char>& buffer) {
HANDLE hFile = CreateFile(file_name.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
cout << "Ошибка при открытии файла для чтения!" << endl;
return;
}
DWORD fileSize = GetFileSize(hFile, NULL);
buffer.resize(fileSize);
DWORD bytesRead;
ReadFile(hFile, buffer.data(), fileSize, &bytesRead, NULL);
CloseHandle(hFile);
}
void write_file(wstring& file_name, vector<char>& buffer) {
HANDLE hFile = CreateFile(file_name.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
cout << "Ошибка при открытии файла для записи!" << endl;
return;
}
DWORD bytesWritten;
WriteFile(hFile, buffer.data(), buffer.size(), &bytesWritten, NULL);
CloseHandle(hFile);
}
void read_bmp(wstring& bmp_file_name, vector<char>& buffer) {
HANDLE hFile = CreateFile(bmp_file_name.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
cout << "Ошибка при открытии BMP файла для чтения!" << endl;
return;
}
DWORD fileSize = GetFileSize(hFile, NULL);
buffer.resize(fileSize);
DWORD bytesRead;
ReadFile(hFile, buffer.data(), fileSize, &bytesRead, NULL);
CloseHandle(hFile);
}
void write_bmp(wstring& bmp_file_name, vector<char>& buffer) {
HANDLE hFile = CreateFile(bmp_file_name.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
cout << "Ошибка при открытии BMP файла для записи!" << endl;
return;
}
DWORD bytesWritten;
WriteFile(hFile, buffer.data(), buffer.size(), &bytesWritten, NULL);
CloseHandle(hFile);
}
// Функция для печати байта в бинарном формате
void print_binary(uint8_t byte) {
for (int i = 7; i >= 0; --i) {
cout << ((byte >> i) & 0x1);
}
}
// Функция для кодирования сообщения в BMP
void encode_message_to_bmp(string& text_file_name, string& bmp_file_name, string& output_bmp_file_name) {
wstring_convert<codecvt_utf8<wchar_t>> converter;
wstring wide_text_file_name = converter.from_bytes(text_file_name);
wstring wide_bmp_file_name = converter.from_bytes(bmp_file_name);
wstring wide_output_bmp_file_name = converter.from_bytes(output_bmp_file_name);
// Чтение текста
vector<char> message_buffer;
read_file(wide_text_file_name, message_buffer);
string message(message_buffer.begin(), message_buffer.end());
message.push_back(0xFF); // Завершающий байт для конца сообщения
// Чтение BMP файла
vector<char> bmp_buffer;
read_bmp(wide_bmp_file_name, bmp_buffer);
// Запись BMP в новый файл
write_bmp(wide_output_bmp_file_name, bmp_buffer);
// Изменение содержимого BMP
HANDLE hFile = CreateFile(wide_output_bmp_file_name.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) {
cout << "Не удалось открыть BMP файл для модификации!" << endl;
return;
}
// Чтение заголовков BMP
DWORD bytesRead;
DWORD fileSize = GetFileSize(hFile, NULL);
vector<char> fileBuffer(fileSize);
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
//read_bmp(wide_output_bmp_file_name, fileBuffer);
ReadFile(hFile, fileBuffer.data(), fileSize, &bytesRead, NULL);
BITMAPFILEHEADER bmpHeader;
memcpy(&bmpHeader, fileBuffer.data(), sizeof(bmpHeader));
BITMAPINFOHEADER dibHeader;
memcpy(&dibHeader, fileBuffer.data() + sizeof(bmpHeader), sizeof(dibHeader));
DWORD offset = bmpHeader.bfOffBits; // Место начала пикселей
RGBQUAD pixel;
size_t message_index = 0;
// Модификация BMP
while (offset < fileSize && message_index < message.size()) {
memcpy(&pixel, fileBuffer.data() + offset, sizeof(pixel)); // Получаем пиксель из буффера
hide_byte_into_pixel(&pixel, message[message_index]);
memcpy(fileBuffer.data() + offset, &pixel, sizeof(pixel)); // Запись изменённого пикселя обратно в буфер
offset += sizeof(pixel);
message_index++;
}
// Запись измененного BMP в файл
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
//write_bmp(wide_output_bmp_file_name, fileBuffer);
WriteFile(hFile, fileBuffer.data(), fileSize, &bytesRead, NULL);
CloseHandle(hFile);
cout << "Сообщение закодировано в новый файл: " << output_bmp_file_name << endl;
}
// Функция для извлечения сообщения из BMP
void extract_message_from_bmp(string& file_name) {
wstring_convert<codecvt_utf8<wchar_t>> converter;
wstring wide_file_name = converter.from_bytes(file_name);
vector<char> file_buffer;
read_bmp(wide_file_name, file_buffer);
BITMAPFILEHEADER bmpHeader;
memcpy(&bmpHeader, file_buffer.data(), sizeof(bmpHeader));
BITMAPINFOHEADER dibHeader;
memcpy(&dibHeader, file_buffer.data() + sizeof(bmpHeader), sizeof(dibHeader));
DWORD offset = bmpHeader.bfOffBits; // Место начала пикселей
vector<uint8_t> message;
RGBQUAD pixel;
for (size_t i = offset; i < file_buffer.size(); i += sizeof(pixel)) {
memcpy(&pixel, file_buffer.data() + i, sizeof(pixel)); // Получаем пиксель из буффера
uint8_t byte = extract_byte_from_pixel(pixel);
if (byte == 0xFF) {
break;
}
message.push_back(byte);
}
// Декодирование сообщения
string decoded_message(message.begin(), message.end());
cout << "Извлеченное сообщение: " << endl;
cout << decoded_message << endl;
}
// Функция для скрытия байта в пикселе
void hide_byte_into_pixel(RGBQUAD* pixel, uint8_t hide_byte) {
//RGBQUAD new_pixel = pixel;
pixel->rgbBlue &= 0xFC; // очистка 2 младших бит
pixel->rgbBlue |= (hide_byte >> 6) & 0x03;
pixel->rgbGreen &= 0xFC;
pixel->rgbGreen |= (hide_byte >> 4) & 0x03;
pixel->rgbRed &= 0xFC;
pixel->rgbRed |= (hide_byte >> 2) & 0x03;
pixel->rgbReserved &= 0xFC;
pixel->rgbReserved |= hide_byte & 0x03;
//return new_pixel;
}
// Функция для извлечения байта из пикселя
uint8_t extract_byte_from_pixel(RGBQUAD& pixel) {
uint8_t byte = 0;
byte |= (pixel.rgbBlue & 0x3) << 6;
byte |= (pixel.rgbGreen & 0x3) << 4;
byte |= (pixel.rgbRed & 0x3) << 2;
byte |= (pixel.rgbReserved & 0x3);
return byte;
}
int main() {
//setlocale(LC_ALL, "Russian");
setlocale(LC_ALL, "ru_RU.utf8");
string text_file_name = "lab2_source.txt";
//string bmp_file_name = "chess16-24.bmp";
string bmp_file_name = "source_1920_1280.bmp";
string output_bmp_file_name = "encoded_image.bmp";
encode_message_to_bmp(text_file_name, bmp_file_name, output_bmp_file_name);
string file_name = "encoded_image.bmp";
//string file_name = "1.bmp";
extract_message_from_bmp(file_name);
return 0;
}