Изображение сохраняется битым,дай исправленный полный код:  #pragma once
#include <cstdint>
#include <vector>
#include <string>
#include <fstream>
#include <iostream>
#include <unordered_map>
#include <algorithm>
#include <cmath>
#include <thread>
#include <mutex> 
#include <condition_variable>
#include <functional>
#include <queue>
namespace png {
	struct Image {
		uint32_t width;
		uint32_t height;
		uint8_t channels;
		std::vector<uint8_t> data;
	};
	class BitWriter {
	public:
		BitWriter() : bit_pos_(0), current_byte_(0) {}
		void writeBits(uint16_t value, int num_bits) {
			for (int i = 0; i < num_bits; ++i) {
				uint8_t bit = (value >> i) & 0x01;
				current_byte_ |= (bit << bit_pos_);
				bit_pos_++;
				if (bit_pos_ == 8) {
					std::lock_guard<std::mutex> lock(mutex_); // Синхронизация доступа
					buffer_.push_back(current_byte_);
					current_byte_ = 0;
					bit_pos_ = 0;
				}
			}
		}
		void flush() {
			if (bit_pos_ != 0) {
				std::lock_guard<std::mutex> lock(mutex_); // Синхронизация доступа
				buffer_.push_back(current_byte_);
				current_byte_ = 0;
				bit_pos_ = 0;
			}
		}
		const std::vector<uint8_t>& getBuffer() const { return buffer_; }
		// Добавляем метод для получения буфера (нужно для объединения сжатых блоков)
		std::vector<uint8_t>& getMutableBuffer() { return buffer_; }
	private:
		std::vector<uint8_t> buffer_;
		uint8_t current_byte_;
		int bit_pos_;
		std::mutex mutex_; // Мьютекс для синхронизации доступа к buffer_
	};
	class PngImage {
	public:
		PngImage() : width_(0), height_(0), bit_depth_(8), color_type_(6), channels_(4) {
			makeCRCTable();
			generateFixedHuffmanCodes();
		}
		bool read(const std::string& filename) {
			std::ifstream file(filename, std::ios::binary);
			if (!file) {
				std::cerr << "Не удалось открыть файл для чтения: " << filename << "\n";
				return false;
			}
			uint8_t png_signature[8];
			file.read(reinterpret_cast<char*>(png_signature), 8);
			uint8_t expected_signature[8] = { 0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n' };
			if (memcmp(png_signature, expected_signature, 8) != 0) {
				std::cerr << "Файл не является PNG изображением.\n";
				return false;
			}
			std::vector<uint8_t> idat_data;
			bool ihdr_read = false;
			while (!file.eof()) {
				uint32_t chunk_length = 0;
				if (!file.read(reinterpret_cast<char*>(&chunk_length), 4)) break;
				chunk_length = swapEndian(chunk_length);
				char chunk_type[5] = { 0 };
				if (!file.read(chunk_type, 4)) break;
				if (file.eof()) {
					break;
				}
				std::vector<uint8_t> chunk_data(chunk_length);
				if (!file.read(reinterpret_cast<char*>(chunk_data.data()), chunk_length)) break;
				uint32_t crc = 0;
				if (!file.read(reinterpret_cast<char*>(&crc), 4)) break;
				uint32_t computed_crc = crcFunction(reinterpret_cast<uint8_t*>(chunk_type), 4);
				computed_crc = updateCRC(computed_crc, chunk_data.data(), chunk_data.size());
				if (swapEndian(crc) != computed_crc) {
					std::cerr << "CRC ошибка в чанке " << chunk_type << ".\n";
					return false;
				}
				if (strcmp(chunk_type, "IHDR") == 0) {
					if (ihdr_read) {
						std::cerr << "Найдено более одного чанка IHDR.\n";
						return false;
					}
					ihdr_read = true;
					width_ = (chunk_data[0] << 24) | (chunk_data[1] << 16) | (chunk_data[2] << 8) | chunk_data[3];
					height_ = (chunk_data[4] << 24) | (chunk_data[5] << 16) | (chunk_data[6] << 8) | chunk_data[7];
					bit_depth_ = chunk_data[8];
					color_type_ = chunk_data[9];
					if (bit_depth_ != 8) {
						std::cerr << "Поддерживаются только 8-битные изображения.\n";
						return false;
					}
					if (color_type_ == 2) {
						std::cout << "\nЦветовой тип: RGB\n";
						channels_ = 3;
					}
					else if (color_type_ == 6) {
						std::cout << "\nЦветовой тип: RGBA\n";
						channels_ = 4;
					}
					else {
						std::cerr << "Поддерживаются только цветовые типы RGB и RGBA.\n";
						return false;
					}
				}
				else if (strcmp(chunk_type, "IDAT") == 0) {
					idat_data.insert(idat_data.end(), chunk_data.begin(), chunk_data.end());
				}
				else if (strcmp(chunk_type, "IEND") == 0) {
					break;
				}
				else {
					continue;
				}
			}
			if (!ihdr_read) {
				std::cerr << "Не найден чанк IHDR.\n";
				return false;
			}
			std::vector<uint8_t> decompressed_data;
			if (!decompressData(idat_data, decompressed_data)) {
				std::cerr << "Ошибка при распаковке данных изображения.\n";
				return false;
			}
			if (!processImageData(decompressed_data)) {
				std::cerr << "Ошибка при обработке данных изображения.\n";
				return false;
			}
			std::cout << "PNG файл успешно загружен: " << filename << "\n";
			return true;
		}
		bool save(const std::string& filename) {
			if (image_.width == 0 || image_.height == 0 || image_.data.empty()) {
				std::cerr << "Данные изображения не инициализированы.\n";
				return false;
			}
			std::ofstream file(filename, std::ios::binary);
			if (!file) {
				std::cerr << "Не удалось открыть файл для записи: " << filename << "\n";
				return false;
			}
			uint8_t png_signature[8] = { 0x89, 'P', 'N', 'G', '\r', '\n', 0x1A, '\n' };
			file.write(reinterpret_cast<char*>(png_signature), 8);
			uint8_t ihdr_data[13];
			ihdr_data[0] = (image_.width >> 24) & 0xFF;
			ihdr_data[1] = (image_.width >> 16) & 0xFF;
			ihdr_data[2] = (image_.width >> 8) & 0xFF;
			ihdr_data[3] = image_.width & 0xFF;
			ihdr_data[4] = (image_.height >> 24) & 0xFF;
			ihdr_data[5] = (image_.height >> 16) & 0xFF;
			ihdr_data[6] = (image_.height >> 8) & 0xFF;
			ihdr_data[7] = image_.height & 0xFF;
			ihdr_data[8] = 8;
			ihdr_data[9] = color_type_;
			ihdr_data[10] = 0;
			ihdr_data[11] = 0;
			ihdr_data[12] = 0;
			writeChunk(file, "IHDR", ihdr_data, 13);
			// Параллельная подготовка данных изображения
			std::vector<uint8_t> filtered_data;
			if (!prepareImageDataParallel(filtered_data)) {
				std::cerr << "Ошибка при подготовке данных изображения.\n";
				return false;
			}
			// Параллельное сжатие данных изображения
			std::vector<uint8_t> compressed_data;
			if (!compressDataParallel(filtered_data, compressed_data)) {
				std::cerr << "Ошибка при сжатии данных изображения.\n";
				return false;
			}
			size_t chunk_size = 1024; // Размер чанка
			for (size_t i = 0; i < compressed_data.size(); i += chunk_size) {
				size_t length = std::min(chunk_size, compressed_data.size() - i);
				writeChunk(file, "IDAT", &compressed_data[i], length);
			}

			writeChunk(file, "IEND", nullptr, 0);
			file.close();
			std::cout << "PNG файл успешно сохранен: " << filename << "\n";
			return true;
		}
		void setImage(const Image& image) {
			image_ = image;
			width_ = image_.width;
			height_ = image_.height;
			bit_depth_ = 8;
			channels_ = image_.channels;
			color_type_ = (channels_ == 4) ? 6 : 2;
		}
		Image& getImage() {
			return image_;
		}
		void flipVertically() {
			if (image_.data.empty()) {
				std::cerr << "Данные изображения не инициализированы.\n";
				return;
			}
			size_t stride = width_ * channels_;
			size_t half_height = height_ / 2;
			// Параллельная вертикальная инверсия
			std::vector<std::thread> threads;
			unsigned int num_threads = std::thread::hardware_concurrency();
			if (num_threads == 0) num_threads = 4;
			size_t rows_per_thread = half_height / num_threads;
			for (unsigned int i = 0; i < num_threads; ++i) {
				size_t start_row = i * rows_per_thread;
				size_t end_row = (i == num_threads - 1) ? half_height : start_row + rows_per_thread;
				threads.emplace_back([this, start_row, end_row, stride]() {
					for (size_t y = start_row; y < end_row; ++y) {
						size_t top = y * stride;
						size_t bottom = (height_ - 1 - y) * stride;
						std::swap_ranges(image_.data.begin() + top, image_.data.begin() + top + stride, image_.data.begin() + bottom);
					}
					});
			}
			for (auto& t : threads) {
				t.join();
			}
		}
		uint32_t getPixel(uint32_t x, uint32_t y) {
			if (x >= image_.width || y >= image_.height) {
				std::cerr << "Координаты пикселя (" << x << ", " << y << ") выходят за границы изображения.\n";
				return 0;
			}
			size_t index = (y * image_.width + x) * image_.channels;
			uint32_t color = 0;
			if (image_.channels == 4) {
				color |= static_cast<uint32_t>(image_.data[index + 0]) << 24; // Красный
				color |= static_cast<uint32_t>(image_.data[index + 1]) << 16; // Зелёный
				color |= static_cast<uint32_t>(image_.data[index + 2]) << 8;  // Синий
				color |= static_cast<uint32_t>(image_.data[index + 3]);       // Альфа
			}
			else if (image_.channels == 3) {
				color |= static_cast<uint32_t>(image_.data[index + 0]) << 24; // Красный
				color |= static_cast<uint32_t>(image_.data[index + 1]) << 16; // Зелёный
				color |= static_cast<uint32_t>(image_.data[index + 2]) << 8;  // Синий
				color |= 0xFF; // Альфа по умолчанию
			}
			else {
				std::cerr << "Неподдерживаемое количество каналов: " << static_cast<int>(image_.channels) << "\n";
			}
			return color;
		}
		void setPixel(uint32_t x, uint32_t y, uint32_t color) {
			if (x >= image_.width || y >= image_.height) {
				std::cerr << "Координаты пикселя (" << x << ", " << y << ") выходят за границы изображения.\n";
				return;
			}
			size_t index = (y * image_.width + x) * image_.channels;
			if (image_.channels == 4) {
				image_.data[index + 0] = (color >> 24) & 0xFF; // Красный
				image_.data[index + 1] = (color >> 16) & 0xFF; // Зелёный
				image_.data[index + 2] = (color >> 8) & 0xFF;  // Синий
				image_.data[index + 3] = color & 0xFF;         // Альфа
			}
			else if (image_.channels == 3) {
				image_.data[index + 0] = (color >> 24) & 0xFF; // Красный
				image_.data[index + 1] = (color >> 16) & 0xFF; // Зелёный
				image_.data[index + 2] = (color >> 8) & 0xFF;  // Синий
				// Альфа-канал отсутствует
			}
		}
		void initialize(uint32_t width, uint32_t height, bool has_alpha = true) {
			width_ = width;
			height_ = height;
			bit_depth_ = 8;
			channels_ = has_alpha ? 4 : 3;
			color_type_ = has_alpha ? 6 : 2;
			image_.width = width;
			image_.height = height;
			image_.channels = channels_;
			image_.data.resize(width * height * channels_, 0);
		}
	private:
		// Создаем список узлов
		struct Node {
			uint16_t symbol;
			uint32_t freq;
			Node* left;
			Node* right;
		};
		// Добавляем приватные методы generateCodes и deleteTree
		void generateCodes(
			Node* node,
			uint16_t code,
			uint8_t length,
			std::unordered_map<uint16_t, uint16_t>& symbolCodeMap,
			std::unordered_map<uint16_t, uint8_t>& symbolBitsMap,
			std::unordered_map<uint16_t, uint32_t>& bl_count) {
			if (!node->left && !node->right) {
				// Листовой узел
				symbolCodeMap[node->symbol] = code;
				symbolBitsMap[node->symbol] = length;
				bl_count[length]++;
				return;
			}
			generateCodes(node->left, (code << 1), length + 1, symbolCodeMap, symbolBitsMap, bl_count);
			generateCodes(node->right, (code << 1) | 1, length + 1, symbolCodeMap, symbolBitsMap, bl_count);
		}
		bool adjustCodeLengths(
			std::unordered_map<uint16_t, uint8_t>& symbolBitsMap,
			std::unordered_map<uint16_t, uint32_t>& bl_count,
			int max_code_length) {
			// Создаем массив для подсчета количества кодов для каждой длины
			std::vector<uint32_t> counts(max_code_length + 1, 0);
			// Заполняем counts на основе текущих длин кодов
			for (const auto& kvp : symbolBitsMap) {
				uint8_t length = kvp.second;
				if (length > max_code_length) {
					counts[max_code_length]++;
				}
				else {
					counts[length]++;
				}
			}
			// Подсчитываем общее количество кодовых комбинаций
			int total_codes = 1 << max_code_length;
			int used_codes = 0;
			for (int i = 1; i <= max_code_length; ++i) {
				used_codes += counts[i] << (max_code_length - i);
			}
			// Если количество используемых кодов превышает доступное, корректируем длины кодов
			while (used_codes > total_codes) {
				// Ищем наибольшую длину кода, для которой есть символы
				int max_length_found = max_code_length;
				while (max_length_found > 0 && counts[max_length_found] == 0) {
					max_length_found--;
				}
				if (max_length_found <= 1) {
					std::cerr << "Не удается корректировать длины кодов.\n";
					return false;
				}
				// Перемещаем один символ на длину кода на 1 больше
				counts[max_length_found] -= 1;
				counts[max_length_found - 1] += 2;
				counts[max_length_found + 1] += 1;
				used_codes -= 1 << (max_code_length - max_length_found);
				used_codes += 2 << (max_code_length - max_length_found + 1);
			}
			// Обновляем bl_count
			bl_count.clear();
			for (int i = 1; i <= max_code_length; ++i) {
				bl_count[i] = counts[i];
			}
			// Теперь обновляем symbolBitsMap с новыми длинами кодов
			// Создаем вектор символов, отсортированных по длине кодов и символам
			std::vector<std::pair<uint16_t, uint8_t>> symbols;
			for (const auto& kvp : symbolBitsMap) {
				symbols.emplace_back(kvp.first, kvp.second);
			}
			// Сортируем символы по длине кодов и по символам (для стабильности)
			std::sort(symbols.begin(), symbols.end(), [](const auto& a, const auto& b) {
				if (a.second != b.second) return a.second < b.second;
				return a.first < b.first;
				});
			// Присваиваем новые длины кодов на основе counts
			size_t index = 0;
			for (int len = 1; len <= max_code_length; ++len) {
				uint32_t count = counts[len];
				for (uint32_t i = 0; i < count && index < symbols.size(); ++i, ++index) {
					symbolBitsMap[symbols[index].first] = len;
				}
			}
			return true;
		}
		void deleteTree(Node* node) {
			if (node->left) deleteTree(node->left);
			if (node->right) deleteTree(node->right);
			delete node;
		}
		static constexpr int length_base[29] = {
			3,4,5,6,7,8,9,10,
			11,13,15,17,19,23,27,31,
			35,43,51,59,67,83,99,115,
			131,163,195,227,258
		};
		static constexpr int length_extra_bits[29] = {
			0,0,0,0,0,0,0,0,
			1,1,1,1,2,2,2,2,
			3,3,3,3,4,4,4,4,
			5,5,5,5,0
		};
		static constexpr int dist_base[30] = {
			1,2,3,4,
			5,7,9,13,
			17,25,33,49,
			65,97,129,193,
			257,385,513,769,
			1025,1537,2049,3073,
			4097,6145,8193,12289,
			16385,24577
		};
		static constexpr int dist_extra_bits[30] = {
			0,0,0,0,
			1,1,2,2,
			3,3,4,4,
			5,5,6,6,
			7,7,8,8,
			9,9,10,10,
			11,11,12,12,
			13,13
		};
		using CodeMap = std::unordered_map<uint16_t, uint16_t>;
		using LengthMap = std::unordered_map<uint16_t, uint8_t>;
		// Карты для кодирования (символ -> код и длина)
		std::unordered_map<uint16_t, uint16_t> fixedLitSymbolCodeMap; // символ -> код
		std::unordered_map<uint16_t, uint8_t> fixedLitSymbolBitsMap; // символ -> длина кода
		std::unordered_map<uint16_t, uint16_t> fixedDistSymbolCodeMap; // символ -> код
		std::unordered_map<uint16_t, uint8_t> fixedDistSymbolBitsMap; // символ -> длина кода
		// Карты для декодирования (код -> символ)
		std::unordered_map<uint16_t, uint16_t> fixedLitCodeMap; // код -> символ
		std::unordered_map<uint16_t, uint16_t> fixedDistCodeMap; // код -> символ
		bool decompressData(const std::vector<uint8_t>& input, std::vector<uint8_t>& output) {
			if (input.size() < 2) {
				std::cerr << "Недостаточно данных для проверки заголовка zlib.\n";
				return false;
			}
			uint8_t cmf = input[0];
			uint8_t flg = input[1];
			if ((cmf & 0x0F) != 8) {
				std::cerr << "Неподдерживаемый метод компрессии.\n";
				return false;
			}
			// Проверка валидности заголовка zlib
			if (((cmf * 256 + flg) % 31) != 0) {
				std::cerr << "Неверный заголовок zlib. Проверка контрольной суммы FLEVEL не пройдена.\n";
				return false;
			}
			size_t pos = 2;
			output.clear();
			if (!inflateData(input, pos, output)) {
				std::cerr << "Ошибка при распаковке DEFLATE.\n";
				return false;
			}
			return true;
		}
		// Остальные функции декомпрессии и кодирования остаются без изменений
		bool inflateData(const std::vector<uint8_t>& input, size_t& pos, std::vector<uint8_t>& output) {
			std::vector<uint8_t> bit_buffer;
			for (size_t i = pos; i < input.size(); ++i) {
				bit_buffer.push_back(input[i]);
			}
			size_t bb_pos = 0;
			bool is_final_block = false;
			while (!is_final_block) {
				uint16_t temp_final_block = 0;
				if (!readBits(bit_buffer, bb_pos, 1, temp_final_block)) {
					std::cerr << "Ошибка чтения BFINAL.\n";
					return false;
				}
				is_final_block = (temp_final_block != 0);
				uint16_t btype = 0;
				if (!readBits(bit_buffer, bb_pos, 2, btype)) {
					std::cerr << "Ошибка чтения BTYPE.\n";
					return false;
				}
				if (btype == 0) {
					std::cerr << "Найден несжатый блок. Не поддерживается.\n";
					return false;
				}
				else if (btype == 1) {
					if (!inflateFixedHuffmanBlock(bit_buffer, bb_pos, output)) {
						std::cerr << "Ошибка декодирования фиксированного блока Хаффмана.\n";
						return false;
					}
				}
				else if (btype == 2) {
					if (!inflateDynamicHuffmanBlock(bit_buffer, bb_pos, output)) {
						std::cerr << "Ошибка декодирования динамического блока Хаффмана.\n";
						return false;
					}
				}
				else {
					std::cerr << "Неподдерживаемый тип блока: " << btype << ".\n";
					return false;
				}
			}
			return true;
		}
		bool inflateDynamicHuffmanBlock(const std::vector<uint8_t>& bit_buffer, size_t& bb_pos, std::vector<uint8_t>& output) {
			uint16_t HLIT = 0, HDIST = 0, HCLEN = 0;
			if (!readBits(bit_buffer, bb_pos, 5, HLIT)) {
				std::cerr << "Ошибка чтения HLIT.\n";
				return false;
			}
			if (!readBits(bit_buffer, bb_pos, 5, HDIST)) {
				std::cerr << "Ошибка чтения HDIST.\n";
				return false;
			}
			if (!readBits(bit_buffer, bb_pos, 4, HCLEN)) {
				std::cerr << "Ошибка чтения HCLEN.\n";
				return false;
			}
			HLIT += 257;
			HDIST += 1;
			HCLEN += 4;
			std::vector<uint8_t> code_length_code_lengths(19, 0);
			int code_length_order[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
			for (int i = 0; i < HCLEN; ++i) {
				uint16_t len = 0;
				if (!readBits(bit_buffer, bb_pos, 3, len)) {
					std::cerr << "Ошибка чтения кодов длины для алфавита кодов длин.\n";
					return false;
				}
				code_length_code_lengths[code_length_order[i]] = len;
			}
			CodeMap code_length_codes;
			LengthMap code_length_bitsToSymbol;
			if (!buildHuffmanCodes(code_length_code_lengths, code_length_codes, code_length_bitsToSymbol, 7)) {
				std::cerr << "Ошибка построения кодов Хаффмана для кодов длин.\n";
				return false;
			}
			//std::cout << "Коды длин: " << code_length_codes.size() << "\n";
			std::vector<uint8_t> code_lengths;
			size_t total_codes = HLIT + HDIST;
			size_t i = 0;
			while (i < total_codes) {
				uint16_t symbol;
				if (!decodeSymbolDynamic(bit_buffer, bb_pos, symbol, code_length_codes, code_length_bitsToSymbol)) {
					std::cerr << "Ошибка декодирования кода длины.\n";
					return false;
				}
				if (symbol <= 15) {
					code_lengths.push_back(symbol);
					++i;
				}
				else if (symbol == 16) {
					uint16_t repeat_count = 0;
					if (!readBits(bit_buffer, bb_pos, 2, repeat_count)) {
						std::cerr << "Ошибка чтения дополнительных битов для символа 16.\n";
						return false;
					}
					repeat_count += 3;
					if (i == 0) {
						std::cerr << "Символ повторения 16, когда нет предыдущего кода длины.\n";
						return false;
					}
					uint8_t prev_code_length = code_lengths.back();
					for (int j = 0; j < repeat_count && i < total_codes; ++j, ++i) {
						code_lengths.push_back(prev_code_length);
					}
				}
				else if (symbol == 17) {
					uint16_t repeat_count = 0;
					if (!readBits(bit_buffer, bb_pos, 3, repeat_count)) {
						std::cerr << "Ошибка чтения дополнительных битов для символа 17.\n";
						return false;
					}
					repeat_count += 3;
					for (int j = 0; j < repeat_count && i < total_codes; ++j, ++i) {
						code_lengths.push_back(0);
					}
				}
				else if (symbol == 18) {
					uint16_t repeat_count = 0;
					if (!readBits(bit_buffer, bb_pos, 7, repeat_count)) {
						std::cerr << "Ошибка чтения дополнительных битов для символа 18.\n";
						return false;
					}
					repeat_count += 11;
					for (int j = 0; j < repeat_count && i < total_codes; ++j, ++i) {
						code_lengths.push_back(0);
					}
				}
				else {
					std::cerr << "Недопустимый символ в кодах длин: " << symbol << "\n";
					return false;
				}
			}
			if (code_lengths.size() != total_codes) {
				std::cerr << "Количество кодов длин не соответствует ожидаемому.\n";
				return false;
			}
			std::vector<uint8_t> lit_len_code_lengths(code_lengths.begin(), code_lengths.begin() + HLIT);
			std::vector<uint8_t> dist_code_lengths(code_lengths.begin() + HLIT, code_lengths.end());
			CodeMap lit_len_codes;
			LengthMap lit_len_bitsToSymbol;
			if (!buildHuffmanCodes(lit_len_code_lengths, lit_len_codes, lit_len_bitsToSymbol, 15)) {
				std::cerr << "Ошибка построения кодов Хаффмана для литералов и длин.\n";
				return false;
			}
			//std::cout << "Коды литералов и длин: " << lit_len_codes.size() << "\n";
			CodeMap dist_codes;
			LengthMap dist_bitsToSymbol;
			if (!buildHuffmanCodes(dist_code_lengths, dist_codes, dist_bitsToSymbol, 15)) {
				std::cerr << "Ошибка построения кодов Хаффмана для расстояний.\n";
				return false;
			}
			//std::cout << "Коды расстояний: " << dist_codes.size() << "\n";
			while (true) {
				uint16_t symbol;
				if (!decodeSymbolDynamic(bit_buffer, bb_pos, symbol, lit_len_codes, lit_len_bitsToSymbol)) {
					std::cerr << "Ошибка декодирования символа.\n";
					return false;
				}
				if (symbol < 256) {
					output.push_back(static_cast<uint8_t>(symbol));
				}
				else if (symbol == 256) {
					break;
				}
				else if (symbol >= 257 && symbol <= 285) {
					int length = 0;
					int extra_bits = 0;
					int length_index = symbol - 257;
					length = length_base[length_index];
					extra_bits = length_extra_bits[length_index];
					if (extra_bits > 0) {
						uint16_t extra_value = 0;
						if (!readBits(bit_buffer, bb_pos, extra_bits, extra_value)) {
							std::cerr << "Ошибка чтения дополнительных битов для длины.\n";
							return false;
						}
						length += extra_value;
					}
					uint16_t dist_symbol = 0;
					if (!decodeSymbolDynamic(bit_buffer, bb_pos, dist_symbol, dist_codes, dist_bitsToSymbol)) {
						std::cerr << "Ошибка декодирования символа расстояния.\n";
						return false;
					}
					int distance = 0;
					int dist_extra_bits_val = 0;
					if (dist_symbol <= 29) {
						distance = dist_base[dist_symbol];
						dist_extra_bits_val = dist_extra_bits[dist_symbol];
						if (dist_extra_bits_val > 0) {
							uint16_t extra_value = 0;
							if (!readBits(bit_buffer, bb_pos, dist_extra_bits_val, extra_value)) {
								std::cerr << "Ошибка чтения дополнительных битов для расстояния.\n";
								return false;
							}
							distance += extra_value;
						}
					}
					else {
						std::cerr << "Недопустимый символ расстояния: " << dist_symbol << ".\n";
						return false;
					}
					if (distance > output.size()) {
						std::cerr << "Расстояние больше, чем доступные данные.\n";
						return false;
					}
					size_t copy_pos = output.size() - distance;
					for (int i = 0; i < length; ++i) {
						output.push_back(output[copy_pos + i]);
					}
				}
				else {
					std::cerr << "Недопустимый символ: " << symbol << ".\n";
					return false;
				}
			}
			return true;
		}
		bool buildHuffmanCodes(const std::vector<uint8_t>& code_lengths, CodeMap& codes, LengthMap& code_lengths_map, int max_code_length) {
			std::vector<uint16_t> bl_count(max_code_length + 1, 0);
			for (uint8_t len : code_lengths) {
				if (len > 0)
					bl_count[len]++;
			}
			std::vector<uint16_t> next_code(max_code_length + 1, 0);
			uint16_t code = 0;
			for (int bits = 1; bits <= max_code_length; bits++) {
				code = (code + bl_count[bits - 1]) << 1;
				next_code[bits] = code;
			}
			for (size_t n = 0; n < code_lengths.size(); n++) {
				uint8_t len = code_lengths[n];
				if (len != 0) {
					code = next_code[len];
					next_code[len]++;
					uint16_t code_reversed = reverseBits(code, len);
					codes[code_reversed] = n;
					code_lengths_map[code_reversed] = len;
				}
			}
			return true;
		}
		bool inflateFixedHuffmanBlock(const std::vector<uint8_t>& bit_buffer, size_t& bb_pos, std::vector<uint8_t>& output) {
			while (true) {
				uint16_t symbol;
				if (!decodeSymbolFixed(bit_buffer, bb_pos, symbol, 15)) {
					std::cerr << "Ошибка декодирования символа.\n";
					return false;
				}
				if (symbol < 256) {
					output.push_back(static_cast<uint8_t>(symbol));
				}
				else if (symbol == 256) {
					break;
				}
				else if (symbol >= 257 && symbol <= 285) {
					int length = 0;
					int extra_bits = 0;
					int length_index = symbol - 257;
					length = length_base[length_index];
					extra_bits = length_extra_bits[length_index];
					if (extra_bits > 0) {
						uint16_t extra_value = 0;
						if (!readBits(bit_buffer, bb_pos, extra_bits, extra_value)) {
							std::cerr << "Ошибка чтения дополнительных битов для длины.\n";
							return false;
						}
						length += extra_value;
					}
					uint16_t dist_symbol = 0;
					if (!decodeSymbolFixedDistance(bit_buffer, bb_pos, dist_symbol, 5)) {
						std::cerr << "Ошибка декодирования символа расстояния.\n";
						return false;
					}
					int distance = 0;
					int dist_extra_bits_val = 0;
					if (dist_symbol <= 29) {
						distance = dist_base[dist_symbol];
						dist_extra_bits_val = dist_extra_bits[dist_symbol];
						if (dist_extra_bits_val > 0) {
							uint16_t extra_value = 0;
							if (!readBits(bit_buffer, bb_pos, dist_extra_bits_val, extra_value)) {
								std::cerr << "Ошибка чтения дополнительных битов для расстояния.\n";
								return false;
							}
							distance += extra_value;
						}
					}
					else {
						std::cerr << "Недопустимый символ расстояния: " << dist_symbol << ".\n";
						return false;
					}
					if (distance > output.size()) {
						std::cerr << "Расстояние больше, чем доступные данные.\n";
						return false;
					}
					size_t copy_pos = output.size() - distance;
					for (int i = 0; i < length; ++i) {
						output.push_back(output[copy_pos + i]);
					}
				}
				else {
					std::cerr << "Недопустимый символ: " << symbol << ".\n";
					return false;
				}
			}
			return true;
		}
		bool decodeSymbolDynamic(const std::vector<uint8_t>& bit_buffer, size_t& bb_pos, uint16_t& symbol,
			const CodeMap& codes, const LengthMap& code_lengths_map) {
			uint16_t code = 0;
			for (int bits_read = 1; bits_read <= 15; ++bits_read) {
				uint16_t bit = 0;
				if (!readBits(bit_buffer, bb_pos, 1, bit)) {
					return false;
				}
				code |= (bit << (bits_read - 1));
				auto it = code_lengths_map.find(code);
				if (it != code_lengths_map.end() && it->second == bits_read) {
					symbol = codes.at(code);
					return true;
				}
			}
			std::cerr << "Не удалось декодировать символ с кодом: " << code << "\n";
			return false;
		}
		bool decodeSymbolFixed(const std::vector<uint8_t>& bit_buffer, size_t& bb_pos, uint16_t& symbol, int max_code_length) {
			uint16_t code = 0;
			for (int bits_read = 1; bits_read <= max_code_length; ++bits_read) {
				uint16_t bit = 0;
				if (!readBits(bit_buffer, bb_pos, 1, bit)) {
					return false;
				}
				code |= (bit << (bits_read - 1));
				auto it = fixedLitCodeMap.find(code);
				if (it != fixedLitCodeMap.end()) {
					symbol = it->second;
					// Проверяем длину кода
					auto bits_it = fixedLitSymbolBitsMap.find(symbol);
					if (bits_it != fixedLitSymbolBitsMap.end() &&
						bits_it->second == bits_read) {
						return true;
					}
				}
			}
			std::cerr << "Не удалось декодировать фиксированный символ с кодом: " << code << "\n";
			return false;
		}
		bool decodeSymbolFixedDistance(const std::vector<uint8_t>& bit_buffer, size_t& bb_pos, uint16_t& symbol, int max_code_length) {
			uint16_t code = 0;
			for (int bits_read = 1; bits_read <= max_code_length; ++bits_read) {
				uint16_t bit = 0;
				if (!readBits(bit_buffer, bb_pos, 1, bit)) {
					return false;
				}
				code |= (bit << (bits_read - 1));
				auto it = fixedDistCodeMap.find(code);
				if (it != fixedDistCodeMap.end()) {
					symbol = it->second;
					// Проверяем длину кода
					auto bits_it = fixedDistSymbolBitsMap.find(symbol);
					if (bits_it != fixedDistSymbolBitsMap.end() &&
						bits_it->second == bits_read) {
						return true;
					}
				}
			}
			std::cerr << "Не удалось декодировать фиксированный символ расстояния с кодом: " << code << "\n";
			return false;
		}
		uint16_t reverseBits(uint16_t code, int length) {
			uint16_t reversed = 0;
			for (int i = 0; i < length; ++i) {
				reversed |= ((code >> i) & 1) << (length - i - 1);
			}
			return reversed;
		}
		bool readBits(const std::vector<uint8_t>& bit_buffer, size_t& bb_pos, int num_bits, uint16_t& result) {
			result = 0;
			for (int i = 0; i < num_bits; ++i) {
				if (bb_pos >= bit_buffer.size() * 8) {
					return false;
				}
				size_t byte_pos = bb_pos / 8;
				uint8_t byte = bit_buffer[byte_pos];
				int bit_offset = bb_pos % 8;
				uint8_t bit = (byte >> bit_offset) & 0x01;
				result |= (bit << i);
				bb_pos++;
			}
			return true;
		}
		bool processImageData(const std::vector<uint8_t>& data) {
			size_t bytesPerPixel = channels_;
			size_t stride = width_ * bytesPerPixel;
			image_.width = width_;
			image_.height = height_;
			image_.channels = channels_;
			image_.data.resize(width_ * height_ * bytesPerPixel);
			size_t src_offset = 0;
			size_t dst_offset = 0;
			for (uint32_t y = 0; y < height_; ++y) {
				if (src_offset >= data.size()) {
					std::cerr << "Размер данных меньше ожидаемого.\n";
					return false;
				}
				uint8_t filter_type = data[src_offset++];
				const uint8_t* src_line = &data[src_offset];
				uint8_t* dst_line = &image_.data[dst_offset];
				if (src_offset + stride > data.size()) {
					std::cerr << "Несоответствие размера данных.\n";
					return false;
				}
				switch (filter_type) {
				case 0:
					memcpy(dst_line, src_line, stride);
					break;
				case 1:
					for (size_t i = 0; i < stride; ++i) {
						uint8_t val = src_line[i];
						uint8_t left = (i >= bytesPerPixel) ? dst_line[i - bytesPerPixel] : 0;
						dst_line[i] = val + left;
					}
					break;
				case 2:
					for (size_t i = 0; i < stride; ++i) {
						uint8_t val = src_line[i];
						uint8_t up = (y > 0) ? image_.data[dst_offset - stride + i] : 0;
						dst_line[i] = val + up;
					}
					break;
				case 3:
					for (size_t i = 0; i < stride; ++i) {
						uint8_t val = src_line[i];
						uint8_t left = (i >= bytesPerPixel) ? dst_line[i - bytesPerPixel] : 0;
						uint8_t up = (y > 0) ? image_.data[dst_offset - stride + i] : 0;
						dst_line[i] = val + static_cast<uint8_t>((left + up) / 2);
					}
					break;
				case 4:
					for (size_t i = 0; i < stride; ++i) {
						uint8_t val = src_line[i];
						uint8_t left = (i >= bytesPerPixel) ? dst_line[i - bytesPerPixel] : 0;
						uint8_t up = (y > 0) ? image_.data[dst_offset - stride + i] : 0;
						uint8_t up_left = (y > 0 && i >= bytesPerPixel) ? image_.data[dst_offset - stride + i - bytesPerPixel] : 0;
						dst_line[i] = val + paethPredictor(left, up, up_left);
					}
					break;
				default:
					std::cerr << "Неизвестный тип фильтра: " << static_cast<int>(filter_type) << "\n";
					return false;
				}
				src_offset += stride;
				dst_offset += stride;
			}
			return true;
		}
		// Параллельная подготовка данных изображения
		bool prepareImageDataParallel(std::vector<uint8_t>& output) {
			size_t bytesPerPixel = channels_;
			size_t stride = image_.width * bytesPerPixel;
			size_t total_size = image_.height * (stride + 1);
			output.resize(total_size);
			unsigned int num_threads = std::thread::hardware_concurrency();
			if (num_threads == 0) num_threads = 4;
			std::vector<std::thread> threads;
			size_t rows_per_thread = image_.height / num_threads;
			for (unsigned int i = 0; i < num_threads; ++i) {
				uint32_t start_row = i * rows_per_thread;
				uint32_t end_row = (i == num_threads - 1) ? image_.height : start_row + rows_per_thread;
				threads.emplace_back([this, &output, start_row, end_row, stride, bytesPerPixel]() {
					size_t src_offset = start_row * stride;
					size_t dst_offset = start_row * (stride + 1);
					for (uint32_t y = start_row; y < end_row; ++y) {
						output[dst_offset++] = 0; // Фильтр типа 0 (None)
						memcpy(&output[dst_offset], &image_.data[src_offset], stride);
						src_offset += stride;
						dst_offset += stride;
					}
					});
			}
			for (auto& t : threads) {
				t.join();
			}
			return true;
		}
		bool compressDataParallel(const std::vector<uint8_t>& input, std::vector<uint8_t>& output) {
			// Параметры дефляции
			uint8_t cmf = 0x78;  // Начальный байт для дефляции
			uint8_t flg = 0x9C;   // Флаг для корректности (для обеспечения (cmf * 256 + flg) % 31 == 0)

			// Запись заголовка сжатия
			output.push_back(cmf);
			output.push_back(flg);

			// Генерация фиксированных кодов Хаффмана (используется для сжатия)
			generateFixedHuffmanCodes();

			// Размер блока сжатия
			const size_t block_size = 65536; // 64 КБ на блок
			size_t total_blocks = (input.size() + block_size - 1) / block_size; // Количество блоков
			std::vector<std::vector<uint8_t>> compressed_blocks(total_blocks); // Вектор для хранения сжатых блоков
			std::vector<std::thread> threads; // Потоки для параллельной обработки

			// Мьютекс для синхронизации записи в общий результат
			std::mutex output_mutex;

			for (size_t block_idx = 0; block_idx < total_blocks; ++block_idx) {
				size_t start_pos = block_idx * block_size;
				size_t end_pos = std::min(start_pos + block_size, input.size());

				// Создание потока для сжатия каждого блока
				threads.emplace_back([this, &input, &compressed_blocks, block_idx, start_pos, end_pos, &output_mutex]() {
					std::vector<uint8_t> block_data(input.begin() + start_pos, input.begin() + end_pos); // Данные блока

					BitWriter bit_writer;  // Класс для записи битов
					uint8_t BFINAL = (block_idx == compressed_blocks.size() - 1) ? 1 : 0; // Признак последнего блока
					uint8_t BTYPE = 1;  // Используем фиксированные коды Хаффмана

					// Запись заголовка для блока
					bit_writer.writeBits(BFINAL, 1);
					bit_writer.writeBits(BTYPE, 2);

					// Сжатие данных блока с использованием фиксированных кодов
					if (!deflateFixedBlock(block_data, bit_writer)) {
						std::cerr << "Ошибка при сжатии блока " << block_idx << ".\n";
						return;
					}

					// Завершаем запись битов
					bit_writer.flush();

					// Сохраняем сжатые данные блока
					{
						std::lock_guard<std::mutex> lock(output_mutex); // Синхронизация записи
						compressed_blocks[block_idx] = bit_writer.getBuffer();
					}
					});
			}

			// Ожидание завершения всех потоков
			for (auto& t : threads) {
				t.join();
			}

			// Объединяем сжатые данные всех блоков
			for (const auto& block : compressed_blocks) {
				output.insert(output.end(), block.begin(), block.end());
			}

			// Добавление контрольной суммы Adler-32
			uint32_t adler = computeAdler32(input.data(), input.size());
			output.push_back((adler >> 24) & 0xFF);
			output.push_back((adler >> 16) & 0xFF);
			output.push_back((adler >> 8) & 0xFF);
			output.push_back(adler & 0xFF);

			return true;
		}

		// Функция для сжатия данных блока
		bool deflateFixedBlock(const std::vector<uint8_t>& data, BitWriter& bit_writer) {
			size_t pos = 0;
			const size_t window_size = 32768;
			const size_t min_match = 3;
			const size_t max_match = 258;
			while (pos < data.size()) {
				size_t match_length = 0;
				size_t match_distance = 0;
				// Поиск совпадений
				size_t start_search = (pos >= window_size) ? pos - window_size : 0;
				for (size_t i = start_search; i + min_match <= pos; ++i) {
					size_t length = 0;
					while (length < max_match && pos + length < data.size() && data[i + length] == data[pos + length]) {
						++length;
					}
					if (length >= min_match && length > match_length) {
						match_length = length;
						match_distance = pos - i;
						if (length == max_match) break;
					}
				}
				if (match_length >= min_match) {
					// Кодируем длину совпадения
					uint16_t length_code, length_extra_bits;
					getLengthCode(match_length, length_code, length_extra_bits);
					if (!encodeSymbol(bit_writer, length_code, fixedLitSymbolCodeMap, fixedLitSymbolBitsMap)) {
						std::cerr << "Ошибка кодирования длины.\n";
						return false;
					}
					if (length_extra_bits > 0) {
						uint16_t extra_bits = match_length - length_base[length_code - 257];
						bit_writer.writeBits(extra_bits, length_extra_bits);
					}
					// Кодируем расстояние совпадения
					uint16_t dist_code, dist_extra_bits;
					getDistanceCode(match_distance, dist_code, dist_extra_bits);
					if (!encodeSymbol(bit_writer, dist_code, fixedDistSymbolCodeMap, fixedDistSymbolBitsMap)) {
						std::cerr << "Ошибка кодирования расстояния.\n";
						return false;
					}
					if (dist_extra_bits > 0) {
						uint16_t extra_bits = match_distance - dist_base[dist_code];
						bit_writer.writeBits(extra_bits, dist_extra_bits);
					}
					pos += match_length;
				}
				else {
					// Кодируем литерал
					uint16_t symbol = data[pos];
					if (!encodeSymbol(bit_writer, symbol, fixedLitSymbolCodeMap, fixedLitSymbolBitsMap)) {
						std::cerr << "Ошибка кодирования литерала.\n";
						return false;
					}
					++pos;
				}
			}
			// Кодируем символ конца блока
			if (!encodeSymbol(bit_writer, 256, fixedLitSymbolCodeMap, fixedLitSymbolBitsMap)) {
				std::cerr << "Ошибка кодирования символа конца блока.\n";
				return false;
			}
			return true;
		}
		void getLengthCode(size_t length, uint16_t& code, uint16_t& extra_bits) {
			for (int i = 0; i < 29; ++i) {
				if (length >= length_base[i] && length <= length_base[i] + ((1 << length_extra_bits[i]) - 1)) {
					code = 257 + i;
					extra_bits = length_extra_bits[i];
					return;
				}
			}
			code = 285;
			extra_bits = 0;
		}
		void getDistanceCode(size_t distance, uint16_t& code, uint16_t& extra_bits) {
			for (int i = 0; i < 30; ++i) {
				if (distance >= dist_base[i] && distance <= dist_base[i] + ((1 << dist_extra_bits[i]) - 1)) {
					code = i;
					extra_bits = dist_extra_bits[i];
					return;
				}
			}
			code = 29;
			extra_bits = 0;
		}
		// Функция для построения локальных кодов Хаффмана для блока
		void buildLocalHuffmanCodes(
			const std::vector<uint8_t>& data,
			std::unordered_map<uint16_t, uint16_t>& litSymbolCodeMap,
			std::unordered_map<uint16_t, uint8_t>& litSymbolBitsMap,
			std::unordered_map<uint16_t, uint16_t>& distSymbolCodeMap,
			std::unordered_map<uint16_t, uint8_t>& distSymbolBitsMap) {
			std::unordered_map<uint16_t, uint32_t> lit_freq;
			std::unordered_map<uint16_t, uint32_t> dist_freq;
			size_t pos = 0;
			const size_t window_size = 32768;
			const size_t min_match = 3;
			const size_t max_match = 258;
			while (pos < data.size()) {
				size_t match_length = 0;
				size_t match_distance = 0;
				// Поиск совпадений
				size_t start_search = (pos >= window_size) ? pos - window_size : 0;
				for (size_t i = start_search; i < pos; ++i) {
					size_t length = 0;
					while (length < max_match && pos + length < data.size() && data[i + length] == data[pos + length]) {
						++length;
					}
					if (length >= min_match && length > match_length) {
						match_length = length;
						match_distance = pos - i;
						if (length == max_match) break;
					}
				}
				if (match_length >= min_match) {
					// Обновляем частоты для длины
					uint16_t length_code, length_extra_bits;
					getLengthCode(match_length, length_code, length_extra_bits);
					lit_freq[length_code]++;
					// Обновляем частоты для расстояния
					uint16_t dist_code, dist_extra_bits;
					getDistanceCode(match_distance, dist_code, dist_extra_bits);
					dist_freq[dist_code]++;
					pos += match_length;
				}
				else {
					// Обновляем частоты для литерала
					uint16_t symbol = data[pos];
					lit_freq[symbol]++;
					++pos;
				}
			}
			// Добавляем символ конца блока
			lit_freq[256] = 1;
			// Строим дерево Хаффмана для литералов/длин
			buildHuffmanTree(lit_freq, litSymbolCodeMap, litSymbolBitsMap, 15);
			// Строим дерево Хаффмана для расстояний
			buildHuffmanTree(dist_freq, distSymbolCodeMap, distSymbolBitsMap, 15);
		}
		// Функция для записи заголовка с динамическими кодами Хаффмана
		bool writeDynamicHuffmanHeader(
			BitWriter& bit_writer,
			const std::unordered_map<uint16_t, uint8_t>& litSymbolBitsMap,
			const std::unordered_map<uint16_t, uint8_t>& distSymbolBitsMap) {
			// Шаг 1: Определяем HLIT и HDIST
			int HLIT = 0;
			int HDIST = 0;
			std::vector<uint8_t> litlen_code_lengths(286, 0); // Максимум 286 кодов для литералов/длин
			std::vector<uint8_t> dist_code_lengths(30, 0);    // Максимум 30 кодов расстояний
			// Заполняем длины кодов для литералов/длин
			for (const auto& kvp : litSymbolBitsMap) {
				uint16_t symbol = kvp.first;
				uint8_t length = kvp.second;
				litlen_code_lengths[symbol] = length;
			}
			// Заполняем длины кодов для расстояний
			for (const auto& kvp : distSymbolBitsMap) {
				uint16_t symbol = kvp.first;
				uint8_t length = kvp.second;
				dist_code_lengths[symbol] = length;
			}
			// Определяем максимальный индекс ненулевой длины кода для HLIT
			for (int i = 285; i >= 0; --i) {
				if (litlen_code_lengths[i] != 0) {
					HLIT = i + 1 - 257;
					break;
				}
			}
			// Определяем максимальный индекс ненулевой длины кода для HDIST
			for (int i = 29; i >= 0; --i) {
				if (dist_code_lengths[i] != 0) {
					HDIST = i + 1 - 1;
					break;
				}
			}
			// Шаг 2: Собираем все длины кодов в один вектор
			std::vector<uint8_t> code_lengths;
			code_lengths.insert(code_lengths.end(), litlen_code_lengths.begin(), litlen_code_lengths.begin() + HLIT + 257);
			code_lengths.insert(code_lengths.end(), dist_code_lengths.begin(), dist_code_lengths.begin() + HDIST + 1);
			// Шаг 3: Кодируем длины кодов с помощью кодов длин кодов
			// Порядок кодов длин кодов
			int code_length_order[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 };
			std::vector<uint8_t> code_length_code_lengths(19, 0);
			// Частоты для кодов длин кодов
			std::unordered_map<uint16_t, uint32_t> code_length_freq;
			// Кодируем длины кодов и собираем частоты
			std::vector<uint16_t> encoded_code_lengths;
			for (size_t i = 0; i < code_lengths.size();) {
				uint8_t len = code_lengths[i];
				size_t count = 1;
				while (i + count < code_lengths.size() && code_lengths[i + count] == len) {
					++count;
				}
				if (len == 0 && count >= 3) {
					if (count <= 10) {
						encoded_code_lengths.push_back(17);
						encoded_code_lengths.push_back(count - 3);
						code_length_freq[17]++;
					}
					else {
						size_t repeat_count = std::min(count, (size_t)138);
						encoded_code_lengths.push_back(18);
						encoded_code_lengths.push_back(repeat_count - 11);
						code_length_freq[18]++;
						count = repeat_count;
					}
				}
				else if (len != 0 && count >= 4) {
					encoded_code_lengths.push_back(len);
					code_length_freq[len]++;
					size_t repeat_count = std::min(count - 1, (size_t)6);
					encoded_code_lengths.push_back(16);
					encoded_code_lengths.push_back(repeat_count - 3);
					code_length_freq[16]++;
					count = repeat_count + 1;
				}
				else {
					for (size_t j = 0; j < count; ++j) {
						encoded_code_lengths.push_back(len);
						code_length_freq[len]++;
					}
				}
				i += count;
			}
			// Шаг 4: Строим дерево Хаффмана для кодов длин кодов
			std::unordered_map<uint16_t, uint16_t> codeLengthCodeMap;
			std::unordered_map<uint16_t, uint8_t> codeLengthBitsMap;
			buildHuffmanTree(code_length_freq, codeLengthCodeMap, codeLengthBitsMap, 7);
			// Заполняем длины кодов для кодов длин кодов
			for (auto& kvp : codeLengthBitsMap) {
				code_length_code_lengths[kvp.first] = kvp.second;
			}
			// Определяем HCLEN
			int HCLEN = 19;
			while (HCLEN > 4 && code_length_code_lengths[code_length_order[HCLEN - 1]] == 0) {
				--HCLEN;
			}
			HCLEN -= 4;
			// Шаг 5: Записываем HLIT, HDIST и HCLEN
			bit_writer.writeBits(HLIT & 0x1F, 5);
			bit_writer.writeBits(HDIST & 0x1F, 5);
			bit_writer.writeBits(HCLEN & 0x0F, 4);
			// Шаг 6: Записываем длины кодов длин кодов в заданном порядке
			for (int i = 0; i < HCLEN + 4; ++i) {
				uint8_t len = code_length_code_lengths[code_length_order[i]];
				bit_writer.writeBits(len & 0x07, 3);
			}
			// Шаг 7: Записываем закодированные длины кодов для литералов/длин и расстояний
			for (size_t i = 0; i < encoded_code_lengths.size(); ++i) {
				uint16_t symbol = encoded_code_lengths[i];
				uint16_t code = codeLengthCodeMap[symbol];
				uint8_t bits = codeLengthBitsMap[symbol];
				bit_writer.writeBits(code, bits);
				// Если символ 16, 17 или 18, записываем дополнительные биты
				if (symbol == 16) {
					uint8_t extra_bits = encoded_code_lengths[++i];
					bit_writer.writeBits(extra_bits & 0x03, 2);
				}
				else if (symbol == 17) {
					uint8_t extra_bits = encoded_code_lengths[++i];
					bit_writer.writeBits(extra_bits & 0x07, 3);
				}
				else if (symbol == 18) {
					uint8_t extra_bits = encoded_code_lengths[++i];
					bit_writer.writeBits(extra_bits & 0x7F, 7);
				}
			}
			return true;
		}
		// Функция для построения дерева Хаффмана
		void buildHuffmanTree(
			const std::unordered_map<uint16_t, uint32_t>& freq,
			std::unordered_map<uint16_t, uint16_t>& symbolCodeMap,
			std::unordered_map<uint16_t, uint8_t>& symbolBitsMap,
			int max_code_length) {
			// Шаг 1: Подсчет количества символов для каждой частоты
			std::vector<uint32_t> counts;
			for (const auto& kvp : freq) {
				counts.push_back(kvp.second);
			}
			// Шаг 2: Построение дерева Хаффмана
			auto cmp = [](Node* a, Node* b) { return a->freq > b->freq; };
			std::priority_queue<Node*, std::vector<Node*>, decltype(cmp)> heap(cmp);
			for (const auto& kvp : freq) {
				heap.push(new Node{ kvp.first, kvp.second, nullptr, nullptr });
			}
			// Строим дерево
			while (heap.size() > 1) {
				Node* left = heap.top(); heap.pop();
				Node* right = heap.top(); heap.pop();
				Node* parent = new Node{ 0, left->freq + right->freq, left, right };
				heap.push(parent);
			}
			Node* root = heap.top();
			// Шаг 3: Генерация кодов без учета максимальной длины
			std::unordered_map<uint16_t, uint32_t> bl_count;
			generateCodes(root, 0, 0, symbolCodeMap, symbolBitsMap, bl_count);
			// Шаг 4: Проверка и корректировка длин кодов
			if (!adjustCodeLengths(symbolBitsMap, bl_count, max_code_length)) {
				std::cerr << "Ошибка при корректировке длин кодов.\n";
			}
			// После корректировки длин кодов, необходимо заново сгенерировать коды
			generateCanonicalCodes(symbolBitsMap, symbolCodeMap);
			// Очищаем память
			deleteTree(root);
		}
		void generateCanonicalCodes(
			const std::unordered_map<uint16_t, uint8_t>& symbolBitsMap,
			std::unordered_map<uint16_t, uint16_t>& symbolCodeMap) {
			// Шаг 1: Подсчитываем количество кодов для каждой длины
			std::vector<uint16_t> bl_count(16, 0); // Допустимые длины кодов от 1 до 15
			for (const auto& kvp : symbolBitsMap) {
				uint8_t len = kvp.second;
				if (len > 0) {
					bl_count[len]++;
				}
			}
			// Шаг 2: Вычисляем первое кодовое слово для каждой длины
			std::vector<uint16_t> next_code(16, 0);
			uint16_t code = 0;
			bl_count[0] = 0;
			for (uint8_t bits = 1; bits <= 15; ++bits) {
				code = (code + bl_count[bits - 1]) << 1;
				next_code[bits] = code;
			}
			// Шаг 3: Назначаем коды символам
			for (const auto& kvp : symbolBitsMap) {
				uint16_t symbol = kvp.first;
				uint8_t len = kvp.second;
				if (len != 0) {
					symbolCodeMap[symbol] = next_code[len];
					next_code[len]++;
				}
			}
		}
		// Остальные функции остаются без изменений
		bool deflateData(const std::vector<uint8_t>& input, std::vector<uint8_t>& output) {
			BitWriter bit_writer;
			uint8_t BFINAL = 1;
			uint8_t BTYPE = 1;
			bit_writer.writeBits(BFINAL, 1);
			bit_writer.writeBits(BTYPE, 2);
			size_t pos = 0;
			while (pos < input.size()) {
				size_t match_length = 0;
				size_t match_distance = 0;
				const size_t window_size = 32768;
				size_t search_start = (pos >= window_size) ? pos - window_size : 0;
				size_t max_length = 258;
				for (size_t i = search_start; i < pos && (pos - i) <= window_size; ++i) {
					size_t length = 0;
					while (length < max_length && (pos + length) < input.size() && input[i + length] == input[pos + length]) {
						length++;
					}
					if (length > match_length) {
						match_length = length;
						match_distance = pos - i;
						if (length == max_length) {
							break;
						}
					}
				}
				if (match_length >= 3) {
					if (!encodeLengthDistance(bit_writer, match_length, match_distance)) {
						std::cerr << "Ошибка кодирования длины и расстояния.\n";
						return false;
					}
					pos += match_length;
				}
				else {
					if (!encodeSymbol(bit_writer, input[pos], fixedLitSymbolCodeMap, fixedLitSymbolBitsMap)) {
						std::cerr << "Ошибка кодирования литерала.\n";
						return false;
					}
					pos++;
				}
			}
			if (!encodeSymbol(bit_writer, 256, fixedLitSymbolCodeMap, fixedLitSymbolBitsMap)) {
				std::cerr << "Ошибка кодирования окончания блока.\n";
				return false;
			}
			bit_writer.flush();
			const std::vector<uint8_t>& compressed_data = bit_writer.getBuffer();
			output.insert(output.end(), compressed_data.begin(), compressed_data.end());
			return true;
		}
		bool encodeLengthDistance(BitWriter& bit_writer, size_t length, size_t distance) {
			int length_code = 0;
			int length_extra_bits_val = 0;
			int length_extra = 0;
			for (int i = 0; i < 29; ++i) {
				int length_range = length_base[i] + ((1 << length_extra_bits[i]) - 1);
				if (length >= length_base[i] && length <= length_range) {
					length_code = 257 + i;
					length_extra_bits_val = length_extra_bits[i];
					length_extra = length - length_base[i];
					break;
				}
			}
			if (!encodeSymbol(bit_writer, length_code, fixedLitSymbolCodeMap, fixedLitSymbolBitsMap)) {
				std::cerr << "Ошибка кодирования длины: код " << length_code << "\n";
				return false;
			}
			if (length_extra_bits_val > 0) {
				bit_writer.writeBits(length_extra, length_extra_bits_val);
				//std::cout << "Код длины: " << length_code << ", дополнительные биты: " << length_extra << "\n";
			}
			int dist_code = 0;
			int dist_extra_bits_val = 0;
			int dist_extra = 0;
			for (int i = 0; i < 30; ++i) {
				int dist_range = dist_base[i] + ((1 << dist_extra_bits[i]) - 1);
				if (distance >= dist_base[i] && distance <= dist_range) {
					dist_code = i;
					dist_extra_bits_val = dist_extra_bits[i];
					dist_extra = distance - dist_base[i];
					break;
				}
			}
			if (dist_code > 29) {
				std::cerr << "Недопустимый код расстояния: " << dist_code << ".\n";
				return false;
			}
			if (!encodeSymbol(bit_writer, dist_code, fixedDistSymbolCodeMap, fixedDistSymbolBitsMap)) {
				std::cerr << "Ошибка кодирования расстояния: код " << dist_code << "\n";
				return false;
			}
			if (dist_extra_bits_val > 0) {
				bit_writer.writeBits(dist_extra, dist_extra_bits_val);
				//std::cout << "Код расстояния: " << dist_code << ", дополнительные биты: " << dist_extra << "\n";
			}
			return true;
		}
		bool encodeSymbol(BitWriter& bit_writer, uint16_t symbol, const std::unordered_map<uint16_t, uint16_t>& symbol_code_map, const std::unordered_map<uint16_t, uint8_t>& symbol_bits_map) {
			auto it = symbol_code_map.find(symbol);
			if (it == symbol_code_map.end()) {
				std::cerr << "Недопустимый символ для кодирования: " << symbol << ".\n";
				return false;
			}
			uint16_t code = it->second;
			auto bits_it = symbol_bits_map.find(symbol);
			if (bits_it == symbol_bits_map.end()) {
				std::cerr << "Не найдена длина кода для символа: " << symbol << ".\n";
				return false;
			}
			uint8_t code_length = bits_it->second;
			bit_writer.writeBits(code, code_length);
			//std::cout << "Кодирование символа: " << symbol << " -> код: " << code << ", длина: " << (int)code_length << "\n";
			return true;
		}
		void writeChunk(std::ofstream& file, const char* type, const uint8_t* data, size_t length) {
			uint32_t length_be = swapEndian(static_cast<uint32_t>(length));
			file.write(reinterpret_cast<char*>(&length_be), 4);
			file.write(type, 4);
			if (data && length > 0) {
				file.write(reinterpret_cast<const char*>(data), length);
			}
			uint32_t crc = crcFunction(reinterpret_cast<const uint8_t*>(type), 4);
			if (data && length > 0) {
				crc = updateCRC(crc, data, length);
			}
			uint32_t crc_be = swapEndian(crc);
			file.write(reinterpret_cast<char*>(&crc_be), 4);

			// Логирование для отладки
			std::cout << "Записан чанк типа: " << type << ", длина: " << length << ", CRC: " << crc_be << std::endl;
		}

		// Остальные функции остаются без изменений
		uint8_t paethPredictor(int a, int b, int c) const {
			int p = a + b - c;
			int pa = std::abs(p - a);
			int pb = std::abs(p - b);
			int pc = std::abs(p - c);
			if (pa <= pb && pa <= pc)
				return static_cast<uint8_t>(a);
			else if (pb <= pc)
				return static_cast<uint8_t>(b);
			else
				return static_cast<uint8_t>(c);
		}
		uint32_t computeAdler32(const uint8_t* data, size_t len) const {
			uint32_t a = 1, b = 0;
			const uint32_t MOD_ADLER = 65521;
			for (size_t i = 0; i < len; ++i) {
				a = (a + data[i]) % MOD_ADLER;
				b = (b + a) % MOD_ADLER;
			}
			return (b << 16) | a;
		}
		void makeCRCTable() {
			for (uint32_t n = 0; n < 256; n++) {
				uint32_t c = n;
				for (uint32_t k = 0; k < 8; k++) {
					if (c & 1)
						c = 0xedb88320L ^ (c >> 1);
					else
						c = c >> 1;
				}
				crc_table_[n] = c;
			}
		}
		uint32_t updateCRC(uint32_t crc, const uint8_t* buf, size_t len) const {
			uint32_t c = crc ^ 0xffffffffL;
			for (size_t n = 0; n < len; n++) {
				c = crc_table_[(c ^ buf[n]) & 0xff] ^ (c >> 8);
			}
			return c ^ 0xffffffffL;
		}
		uint32_t crcFunction(const uint8_t* buf, size_t len) const {
			return updateCRC(0, buf, len);
		}
		uint32_t swapEndian(uint32_t val) const {
			return ((val >> 24) & 0xFF) |
				((val >> 8) & 0xFF00) |
				((val << 8) & 0xFF0000) |
				((val << 24) & 0xFF000000);
		}
		void generateFixedHuffmanCodes() {
			// Заполнение карты длин кодов для литералов и длин
			for (int i = 0; i <= 287; ++i) {
				if (i <= 143) {
					fixedLitSymbolBitsMap[i] = 8;
				}
				else if (i <= 255) {
					fixedLitSymbolBitsMap[i] = 9;
				}
				else if (i <= 279) {
					fixedLitSymbolBitsMap[i] = 7;
				}
				else {
					fixedLitSymbolBitsMap[i] = 8;
				}
			}
			// Подсчёт количества кодов для каждого бита
			std::vector<uint16_t> bl_count(16, 0);
			for (int i = 0; i <= 287; i++) {
				bl_count[fixedLitSymbolBitsMap[i]]++;
			}
			// Вычисление следующего кода для каждого бита
			std::vector<uint16_t> next_code(16, 0);
			uint16_t code = 0;
			bl_count[0] = 0;
			for (int bits = 1; bits <= 15; bits++) {
				code = (code + bl_count[bits - 1]) << 1;
				next_code[bits] = code;
			}
			// Назначение кодов для литералов и длин
			for (int i = 0; i <= 287; ++i) {
				uint8_t len = fixedLitSymbolBitsMap[i];
				if (len != 0) {
					uint16_t current_code = next_code[len];
					next_code[len]++;
					uint16_t code_reversed = reverseBits(current_code, len);
					fixedLitCodeMap[code_reversed] = i; // Для декодирования
					fixedLitSymbolCodeMap[i] = code_reversed; // Для кодирования
					// fixedLitSymbolBitsMap[i] уже содержит len, не нужно перезаписывать
				}
			}
			// Заполнение карты расстояний с битовым обращением
			for (int i = 0; i < 30; i++) {
				fixedDistSymbolBitsMap[i] = 5;
				fixedDistSymbolCodeMap[i] = reverseBits(i, 5); // Для кодирования
				uint16_t code_reversed = reverseBits(i, 5);
				fixedDistCodeMap[code_reversed] = i; // Для декодирования
			}
			std::cout << "Фиксированные коды Хаффмана сгенерированы.\n";
			std::cout << "Литеральные коды: " << fixedLitSymbolCodeMap.size() << "\n";
			std::cout << "Расстояния коды: " << fixedDistSymbolCodeMap.size() << "\n";
		}
		uint32_t width_;
		uint32_t height_;
		uint8_t bit_depth_;
		uint8_t color_type_;
		uint8_t channels_;
		Image image_;
		uint32_t crc_table_[256];
	};
}