diff --git a/CMakeLists.txt b/CMakeLists.txt index 10423a5..8b0a302 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,4 @@ project(image_test_cpp) set(CMAKE_CXX_STANDARD 17) -add_executable(image_test_cpp main.cpp - bmpimage.h - bmpimage.cpp) +add_executable(image_test_cpp main.cpp) diff --git a/bmpimage.cpp b/bmpimage.cpp deleted file mode 100644 index fe29d54..0000000 --- a/bmpimage.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "bmpimage.h" - -BMPImage::BMPImage(const BitmapFileHeader &fileHeader, const BITMAPINFOHEADER &infoHeader, Pixel **pixelArray) { - this->fileHeader = fileHeader; - this->infoHeader = infoHeader; - this->pixelArray = pixelArray; -} - -const uint32_t &BMPImage::width() const { return this->infoHeader.BitmapWidth; } - -const uint32_t &BMPImage::height() const { return this->infoHeader.BitmapHeight; } - -void BMPImage::write(const std::string &filename) { - { - std::ofstream ofs(filename, std::ios_base::binary); - ofs.write((char *) &this->fileHeader, sizeof(this->fileHeader)); - ofs.write((char *) &this->infoHeader, sizeof(this->infoHeader)); - uint32_t byteByRow = this->infoHeader.BitmapWidth * 3; - uint8_t padding = 4 - this->infoHeader.BitmapWidth % 4; - for (int i = 0; i < this->infoHeader.BitmapHeight; ++i) { - ofs.write((char *) pixelArray[i], byteByRow); - if (padding != 4) ofs.write(PADDING_ZEROES, padding); // Write padding - } - } -} - - Pixel **BMPImage::pixels(){ - return this->pixelArray; -} - -Pixel **BMPImage::pixels_copy() { - Pixel **newPixelArray; - newPixelArray = new Pixel *[this->infoHeader.BitmapHeight]; - for (int i = 0; i < this->infoHeader.BitmapHeight; ++i) { - newPixelArray[i] = new Pixel[this->infoHeader.BitmapWidth]; - std::copy(this->pixelArray[i], this->pixelArray[i] + this->infoHeader.BitmapWidth, newPixelArray[i]); - } - return newPixelArray; -} - -BitmapFileHeader BMPImage::fileHeader_copy() { - return this->fileHeader; -} - -BITMAPINFOHEADER BMPImage::infoHeader_copy() { - return this->infoHeader; -} - -BMPImage::~BMPImage() { - for (int i = 0; i < this->infoHeader.BitmapHeight; ++i) { - delete[] this->pixelArray[i]; - } - delete[] this->pixelArray; -} - -BMPImage readBMPImage(const std::string &filename) { - BitmapFileHeader bitmapFileHeader; - BITMAPINFOHEADER bitmapInfoHeader; - Pixel **pixelArray; - uint32_t DIB_Header_Size; - { - std::ifstream ifs(filename, std::ios_base::binary); - if (!ifs.good()) { - throw std::runtime_error("File read error"); - } - ifs.seekg(0, std::ios::beg); - ifs.read((char *) &bitmapFileHeader, sizeof(bitmapFileHeader)); - ifs.read((char *) &DIB_Header_Size, sizeof(DIB_Header_Size)); - } - if (DIB_Header_Size != 40) { - throw std::runtime_error("Invalid header"); - } - { - std::ifstream ifs(filename, std::ios_base::binary); - if (!ifs.good()) { - throw std::runtime_error("File read error"); - } - ifs.seekg(14, std::ios::beg); - ifs.read((char *) &bitmapInfoHeader, sizeof(bitmapInfoHeader)); - } - pixelArray = new Pixel *[bitmapInfoHeader.BitmapHeight]; - { - std::ifstream ifs(filename, std::ios_base::binary); - if (!ifs.good()) { - throw std::runtime_error("File read error"); - } - ifs.seekg(bitmapFileHeader.imageDataOffset, std::ios::beg); - uint32_t byteByRow = bitmapInfoHeader.BitmapWidth * 3; - uint8_t padding = 4 - bitmapInfoHeader.BitmapWidth % 4; - for (int i = 0; i < bitmapInfoHeader.BitmapHeight; ++i) { - pixelArray[i] = new Pixel[bitmapInfoHeader.BitmapWidth]; - ifs.read((char *) pixelArray[i], byteByRow); - if (padding != 4) ifs.seekg(padding, std::ios_base::cur); // Skip padding - } - } - return {bitmapFileHeader, bitmapInfoHeader, pixelArray}; -} diff --git a/bmpimage.h b/bmpimage.h deleted file mode 100644 index fa3bf76..0000000 --- a/bmpimage.h +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include -#include -#include - -const char PADDING_ZEROES[3] = {0, 0, 0}; - -#pragma pack(push, 1) -struct BitmapFileHeader { - char signature[2] = {0, 0}; - uint32_t fileSize = 0; - uint16_t reserved1 = 0; - uint16_t reserved2 = 0; - uint32_t imageDataOffset = 0; -}; -#pragma pack(pop) - -#pragma pack(push, 1) -struct BITMAPINFOHEADER { - uint32_t HeaderSize = 0; - uint32_t BitmapWidth = 0; - uint32_t BitmapHeight = 0; - uint16_t ColorPlanes = 0; - uint16_t BitsPerPixel = 0; - uint32_t CompressionMethod = 0; - uint32_t ImageSize = 0; - int32_t HorizontalPixelPerMetre = 0; - int32_t VerticalPixelPerMetre = 0; - uint32_t NumberOfColors = 0; - uint32_t NumberOfImportantColors = 0; -}; -#pragma pack(pop) - -#pragma pack(push, 1) -struct Pixel { - uint8_t r = 0; - uint8_t g = 0; - uint8_t b = 0; -}; -#pragma pack(pop) - -class BMPImage { - BitmapFileHeader fileHeader; - BITMAPINFOHEADER infoHeader; - Pixel **pixelArray; -public: - BMPImage(const BitmapFileHeader &fileHeader, const BITMAPINFOHEADER &infoHeader, Pixel **pixelArray); - - ~BMPImage(); - - [[nodiscard]] const uint32_t &width() const; - - [[nodiscard]] const uint32_t &height() const; - - [[nodiscard]] Pixel **pixels(); - - [[nodiscard]] Pixel **pixels_copy(); - - [[nodiscard]] BitmapFileHeader fileHeader_copy(); - - [[nodiscard]] BITMAPINFOHEADER infoHeader_copy(); - - void write(const std::string &); -}; - -BMPImage readBMPImage(const std::string &filename); diff --git a/main.cpp b/main.cpp index 8444d6c..b7bd61f 100644 --- a/main.cpp +++ b/main.cpp @@ -1,35 +1,27 @@ #include -#include "bmpimage.h" +#include +#include +#include -const std::string FILENAME = "../elef.bmp"; -const std::string FILENAME_OUT = "../elef_out.bmp"; +struct BitmapFileHeader { + char signature[2] = {0, 0}; + uint32_t fileSize = 0; + uint16_t reserved1 = 0; + uint16_t reserved2 = 0; + uint32_t imageDataOffset = 0; +}; -void lab01() { - auto og_image = readBMPImage(FILENAME); - auto pixels = og_image.pixels_copy(); - for (int i = 0; i < og_image.height(); ++i) { - for (int j = 0; j < og_image.width(); ++j) { - uint8_t gray = pixels[i][j].r / 3 + pixels[i][j].g / 3 + pixels[i][j].b / 3; - pixels[i][j] = {gray, gray, gray}; - } - } - auto image1 = new BMPImage(og_image.fileHeader_copy(), og_image.infoHeader_copy(), pixels); - auto pixels2 = image1->pixels_copy(); - for (int i = 0; i < og_image.height(); ++i) { - for (int j = 0; j < og_image.width(); ++j) { - uint8_t gray = 0; - if (pixels2[i][j].r > 80) gray = 255; - pixels2[i][j] = {gray, gray, gray}; - } - } - auto image2 = new BMPImage(og_image.fileHeader_copy(), og_image.infoHeader_copy(), pixels2); - image1->write("../elef_gs.bmp"); - image2->write("../elef_bw.bmp"); - og_image.write("../elef_out.bmp"); -// image.write(FILENAME_OUT); -} +const std::string FILENAME = "elef.bmp"; int main() { - lab01(); + BitmapFileHeader bitmapFileHeader; + { + std::ifstream ifs(FILENAME, std::ios_base::binary); + ifs.seekg(0, std::ios::beg); + ifs.read((char *) &bitmapFileHeader, 14); + } + std::cout << "Structure:\n" << "Signature: " << std::string(bitmapFileHeader.signature, 2) << "\nFile size: " + << bitmapFileHeader.fileSize << "\nReserved 1: " << bitmapFileHeader.reserved1 << "\nReserved 2: " + << bitmapFileHeader.reserved2 << "\nImage data offset: " << bitmapFileHeader.imageDataOffset << std::endl; return 0; }