/
Dixix404
/
Image_Compression
Обзор
Документация
Войти
/
Dixix404
/
Image_Compression
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
Library/src/main/java/org/example/BMPImage.java
186 строк
7 KB
Dixix404
Algorithm RLE
15 дек 2025, 23:40
15 дек 2025, 23:40
4cb9d66
Код
Авторство
О чём код?
package org.example; import java.io.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; public class BMPImage { private byte[] fileHeader; // 14 байт private byte[] infoHeader; // 40 байт (BITMAPINFOHEADER) private int width; private int height; private byte[][] pixels; // [height][width * 3] - BGR данные /** * Читает BMP файл. * * @param filename путь к BMP файлу * @throws IOException при ошибках чтения или неверном формате */ public void read(String filename) throws IOException { try (DataInputStream dis = new DataInputStream( new BufferedInputStream(new FileInputStream(filename)))) { // Читаем File Header (14 байт) fileHeader = new byte[14]; dis.readFully(fileHeader); // Проверяем сигнатуру BMP ("BM") if (fileHeader[0] != 'B' || fileHeader[1] != 'M') { throw new IOException("Не BMP файл (неверная сигнатура)"); } // Читаем Info Header (40 байт) infoHeader = new byte[40]; dis.readFully(infoHeader); // Извлекаем ширину и высоту ByteBuffer buffer = ByteBuffer.wrap(infoHeader).order(ByteOrder.LITTLE_ENDIAN); width = buffer.getInt(4); // Offset 4 в Info Header height = buffer.getInt(8); // Offset 8 в Info Header short bitsPerPixel = buffer.getShort(14); if (bitsPerPixel != 24) { throw new IOException("Поддерживаются только 24-битные BMP (BGR)"); } // Вычисляем размер строки с выравниванием int rowSize = ((width * 3 + 3) / 4) * 4; int padding = rowSize - width * 3; // Читаем пиксельные данные (снизу вверх) pixels = new byte[Math.abs(height)][width * 3]; for (int y = Math.abs(height) - 1; y >= 0; y--) { dis.readFully(pixels[y]); dis.skipBytes(padding); } } } /** * Записывает BMP файл. * * @param filename путь к выходному BMP файлу * @throws IOException при ошибках записи */ public void write(String filename) throws IOException { int absHeight = Math.abs(height); int rowSize = ((width * 3 + 3) / 4) * 4; int padding = rowSize - width * 3; int pixelDataSize = rowSize * absHeight; int fileSize = 54 + pixelDataSize; // 14 (File Header) + 40 (Info Header) + Pixel Data // Создаём новый File Header byte[] newFileHeader = new byte[14]; newFileHeader[0] = 'B'; newFileHeader[1] = 'M'; // Размер файла (little-endian) newFileHeader[2] = (byte) (fileSize & 0xFF); newFileHeader[3] = (byte) ((fileSize >> 8) & 0xFF); newFileHeader[4] = (byte) ((fileSize >> 16) & 0xFF); newFileHeader[5] = (byte) ((fileSize >> 24) & 0xFF); // Зарезервированные байты newFileHeader[6] = 0; newFileHeader[7] = 0; newFileHeader[8] = 0; newFileHeader[9] = 0; // Смещение до пиксельных данных (всегда 54 для 24-бит BMP без палитры) newFileHeader[10] = 54; newFileHeader[11] = 0; newFileHeader[12] = 0; newFileHeader[13] = 0; // Создаём новый Info Header byte[] newInfoHeader = new byte[40]; ByteBuffer buffer = ByteBuffer.wrap(newInfoHeader).order(ByteOrder.LITTLE_ENDIAN); buffer.putInt(0, 40); // Размер Info Header buffer.putInt(4, width); // Ширина buffer.putInt(8, absHeight); // Высота (положительная - снизу вверх) buffer.putShort(12, (short) 1); // Planes (всегда 1) buffer.putShort(14, (short) 24); // Bits per pixel buffer.putInt(16, 0); // Compression (0 = none) buffer.putInt(20, pixelDataSize); // Image Size buffer.putInt(24, 2835); // X pixels per meter (72 DPI) buffer.putInt(28, 2835); // Y pixels per meter (72 DPI) buffer.putInt(32, 0); // Colors used (0 = all) buffer.putInt(36, 0); // Important colors (0 = all) try (DataOutputStream dos = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(filename)))) { // Записываем заголовки dos.write(newFileHeader); dos.write(newInfoHeader); // Padding байты byte[] paddingBytes = new byte[padding]; // Записываем пиксельные данные (снизу вверх) for (int y = absHeight - 1; y >= 0; y--) { dos.write(pixels[y]); if (padding > 0) { dos.write(paddingBytes); } } } } /** * @return ширина изображения в пикселях */ public int getWidth() { return width; } /** * @return высота изображения в пикселях */ public int getHeight() { return Math.abs(height); } /** * @return массив пикселей [height][width * 3] в формате BGR */ public byte[][] getPixels() { return pixels; } /** * @param pixels массив [height][width * 3] в формате BGR */ public void setPixels(byte[][] pixels) { this.pixels = pixels; } /** * @return копия File Header (14 байт) */ public byte[] getFileHeader() { return fileHeader.clone(); } /** * @return копия Info Header (40 байт) */ public byte[] getInfoHeader() { return infoHeader.clone(); } /** * Устанавливает заголовки BMP. * * @param fileHeader File Header (14 байт) * @param infoHeader Info Header (40 байт) * @param width ширина изображения * @param height высота изображения */ public void setHeaders(byte[] fileHeader, byte[] infoHeader, int width, int height) { this.fileHeader = fileHeader; this.infoHeader = infoHeader; this.width = width; this.height = height; } }