#include <iostream>
#include <fstream>
#include <vector>
#include <stdint.h>
#include <immintrin.h>
#pragma pack(push, 1)
struct BMPHeader {
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
};
struct BMPInfoHeader {
uint32_t biSize;
int32_t biWidth;
int32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
};
#pragma pack(pop)
void Convert32bppTo8bpp_SSE(const std::vector<uint32_t>& input, std::vector<uint8_t>& output, int width, int height) {
output.resize(width * height);
size_t num_pixels = width * height;
// 定义SSE常量
__m128i zero = _mm_setzero_si128();
__m128i red_coeff = _mm_set1_epi32((int)(0.299 * 256));
__m128i green_coeff = _mm_set1_epi32((int)(0.587 * 256));
__m128i blue_coeff = _mm_set1_epi32((int)(0.114 * 256));
__m128i shift_right = _mm_set1_epi32(8);
size_t i = 0;
for (; i + 4 <= num_pixels; i += 4) {
__m128i pixels = _mm_loadu_si128((__m128i*)&input[i]);
__m128i blue = _mm_and_si128(pixels, _mm_set1_epi32(0xFF));
__m128i green = _mm_and_si128(_mm_srli_epi32(pixels, 8), _mm_set1_epi32(0xFF));
__m128i red = _mm_and_si128(_mm_srli_epi32(pixels, 16), _mm_set1_epi32(0xFF));
__m128i gray = _mm_add_epi32(_mm_add_epi32(_mm_mullo_epi32(red, red_coeff),
_mm_mullo_epi32(green, green_coeff)),
_mm_mullo_epi32(blue, blue_coeff));
gray = _mm_srli_epi32(gray, 8);
// 提取并存储结果
uint32_t temp[4];
_mm_storeu_si128((__m128i*)temp, gray);
for (size_t j = 0; j < 4; ++j) {
output[i + j] = static_cast<uint8_t>(temp[j]);
}
}
// 处理剩余的像素
for (; i < num_pixels; ++i) {
uint32_t pixel = input[i];
uint8_t blue = pixel & 0xFF;
uint8_t green = (pixel >> 8) & 0xFF;
uint8_t red = (pixel >> 16) & 0xFF;
uint8_t gray = static_cast<uint8_t>(0.299 * red + 0.587 * green + 0.114 * blue);
output[i] = gray;
}
}
bool ReadBMP(const std::string& filename, std::vector<uint32_t>& data, int& width, int& height) {
std::ifstream file(filename, std::ios::binary);
if (!file) return false;
BMPHeader header;
BMPInfoHeader infoHeader;
file.read(reinterpret_cast<char*>(&header), sizeof(header));
file.read(reinterpret_cast<char*>(&infoHeader), sizeof(infoHeader));
if (header.bfType != 0x4D42 || infoHeader.biBitCount != 32) {
return false;
}
width = infoHeader.biWidth;
height = infoHeader.biHeight;
data.resize(width * height);
file.seekg(header.bfOffBits, std::ios::beg);
file.read(reinterpret_cast<char*>(data.data()), data.size() * sizeof(uint32_t));
return true;
}
bool WriteBMP(const std::string& filename, const std::vector<uint8_t>& data, int width, int height) {
std::ofstream file(filename, std::ios::binary);
if (!file) return false;
BMPHeader header = {};
BMPInfoHeader infoHeader = {};
header.bfType = 0x4D42;
header.bfSize = sizeof(BMPHeader) + sizeof(BMPInfoHeader) + data.size();
header.bfOffBits = sizeof(BMPHeader) + sizeof(BMPInfoHeader);
infoHeader.biSize = sizeof(BMPInfoHeader);
infoHeader.biWidth = width;
infoHeader.biHeight = height;
infoHeader.biPlanes = 1;
infoHeader.biBitCount = 8;
infoHeader.biCompression = 0;
infoHeader.biSizeImage = data.size();
infoHeader.biXPelsPerMeter = 0;
infoHeader.biYPelsPerMeter = 0;
infoHeader.biClrUsed = 256;
infoHeader.biClrImportant = 256;
file.write(reinterpret_cast<char*>(&header), sizeof(header));
file.write(reinterpret_cast<char*>(&infoHeader), sizeof(infoHeader));
// 写入颜色表
for (int i = 0; i < 256; ++i) {
uint8_t color[4] = { (uint8_t)i, (uint8_t)i, (uint8_t)i, 0 };
file.write(reinterpret_cast<char*>(color), sizeof(color));
}
file.write(reinterpret_cast<const char*>(data.data()), data.size());
return true;
}
int main() {
std::vector<uint32_t> inputImage;
std::vector<uint8_t> outputImage;
int width, height;
if (!ReadBMP("input.bmp", inputImage, width, height)) {
std::cerr << "Error reading input.bmp" << std::endl;
return 1;
}
Convert32bppTo8bpp_SSE(inputImage, outputImage, width, height);
if (!WriteBMP("output.bmp", outputImage, width, height)) {
std::cerr << "Error writing output.bmp" << std::endl;
return 1;
}
std::cout << "Conversion to 8-bit successful!" << std::endl;
return 0;
}
12-19
1498
1498

被折叠的 条评论
为什么被折叠?



