Быстрый негатив bmp изображения в C++
1 минут
Написал куда более быстрый вариант инверсии bmp изображения на C++, чем предыдущий. В этом варианте мы читаем изображение, записывая всю информацию о нём в массив, и создаём новое изображение с такими-же данными заголовков, но с инверсированными данными цветов. Всё работает значительно быстрее и код стал более простым.
Файл main.h
#ifndef MAIN_H_INCLUDED
#define MAIN_H_INCLUDED
typedef struct
{
unsigned int bfType;
unsigned long bfSize;
unsigned int bfReserved1;
unsigned int bfReserved2;
unsigned long bfOffBits;
} BITMAPFILEHEADER;
typedef struct
{
unsigned int biSize;
int biWidth;
int biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned int biCompression;
unsigned int biSizeImage;
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} BITMAPINFOHEADER;
typedef struct
{
int rgbBlue;
int rgbGreen;
int rgbRed;
int rgbReserved;
} RGBQUAD;
static unsigned short read_u16(FILE *fp);
static unsigned int read_u32(FILE *fp);
static int read_s32(FILE *fp);
static void write_u16(unsigned short input, FILE *fp);
static void write_u32(unsigned int input, FILE *fp);
static void write_s32(int input, FILE *fp);
#endif // MAIN_H_INCLUDEDs
Файл main.cpp
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "main.h"
int main()
{
printf("Starting...\n");
FILE *pFile = fopen("input.bmp", "rb");
// считываем заголовок файла
BITMAPFILEHEADER header;
header.bfType = read_u16(pFile);
header.bfSize = read_u32(pFile);
header.bfReserved1 = read_u16(pFile);
header.bfReserved2 = read_u16(pFile);
header.bfOffBits = read_u32(pFile);
// считываем заголовок изображения
BITMAPINFOHEADER bmiHeader;
bmiHeader.biSize = read_u32(pFile);
bmiHeader.biWidth = read_s32(pFile);
bmiHeader.biHeight = read_s32(pFile);
bmiHeader.biPlanes = read_u16(pFile);
bmiHeader.biBitCount = read_u16(pFile);
bmiHeader.biCompression = read_u32(pFile);
bmiHeader.biSizeImage = read_u32(pFile);
bmiHeader.biXPelsPerMeter = read_s32(pFile);
bmiHeader.biYPelsPerMeter = read_s32(pFile);
bmiHeader.biClrUsed = read_u32(pFile);
bmiHeader.biClrImportant = read_u32(pFile);
// инициализация массива пикселей
RGBQUAD *pixels = new RGBQUAD[bmiHeader.biHeight * bmiHeader.biWidth];
// читаем байты цветов
for (int i = 0; i < bmiHeader.biHeight * bmiHeader.biWidth; i++) {
pixels[i].rgbBlue = getc(pFile);
pixels[i].rgbGreen = getc(pFile);
pixels[i].rgbRed = getc(pFile);
}
fclose(pFile);
FILE *oFile = fopen("output.bmp", "wb");
// записываем заголовок файла
write_u16(header.bfType, oFile);
write_u32(header.bfSize, oFile);
write_u16(header.bfReserved1, oFile);
write_u16(header.bfReserved2, oFile);
write_u32(header.bfOffBits, oFile);
// записываем заголовок изображения
write_u32(bmiHeader.biSize, oFile);
write_s32(bmiHeader.biWidth, oFile);
write_s32(bmiHeader.biHeight, oFile);
write_u16(bmiHeader.biPlanes, oFile);
write_u16(bmiHeader.biBitCount, oFile);
write_u32(bmiHeader.biCompression, oFile);
write_u32(bmiHeader.biSizeImage, oFile);
write_s32(bmiHeader.biXPelsPerMeter, oFile);
write_s32(bmiHeader.biYPelsPerMeter, oFile);
write_u32(bmiHeader.biClrUsed, oFile);
write_u32(bmiHeader.biClrImportant, oFile);
// записываем байты цветов
for (int i = 0; i < bmiHeader.biHeight * bmiHeader.biWidth; i++) {
putc(~pixels[i].rgbBlue & 0xFF, oFile);
putc(~pixels[i].rgbGreen & 0xFF, oFile);
putc(~pixels[i].rgbRed & 0xFF, oFile);
}
fclose(oFile);
printf("Complete\n");
return 0;
}
static unsigned short read_u16(FILE *fp)
{
unsigned char b0, b1;
b0 = getc(fp);
b1 = getc(fp);
return ((b1 << 8) | b0);
}
static unsigned int read_u32(FILE *fp)
{
unsigned char b0, b1, b2, b3;
b0 = getc(fp);
b1 = getc(fp);
b2 = getc(fp);
b3 = getc(fp);
return ((((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
}
static int read_s32(FILE *fp)
{
unsigned char b0, b1, b2, b3;
b0 = getc(fp);
b1 = getc(fp);
b2 = getc(fp);
b3 = getc(fp);
return ((int)(((((b3 << 8) | b2) << 8) | b1) << 8) | b0);
}
static void write_u16(unsigned short input, FILE *fp)
{
putc(input, fp);
putc(input >> 8, fp);
}
static void write_u32(unsigned int input, FILE *fp)
{
putc(input, fp);
putc(input >> 8, fp);
putc(input >> 16, fp);
putc(input >> 24, fp);
}
static void write_s32(int input, FILE *fp)
{
putc(input, fp);
putc(input >> 8, fp);
putc(input >> 16, fp);
putc(input >> 24, fp);
}