Compare commits
No commits in common. "9762c44796e5575782216b4c2d39d3bc55c869d6" and "5c69bc10341958d3818b54a96264f91f580d6c68" have entirely different histories.
9762c44796
...
5c69bc1034
4 changed files with 21 additions and 195 deletions
|
@ -3,6 +3,4 @@ project(image_test_cpp)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
add_executable(image_test_cpp main.cpp
|
add_executable(image_test_cpp main.cpp)
|
||||||
bmpimage.h
|
|
||||||
bmpimage.cpp)
|
|
||||||
|
|
97
bmpimage.cpp
97
bmpimage.cpp
|
@ -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};
|
|
||||||
}
|
|
67
bmpimage.h
67
bmpimage.h
|
@ -1,67 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
#include <fstream>
|
|
||||||
|
|
||||||
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);
|
|
48
main.cpp
48
main.cpp
|
@ -1,35 +1,27 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "bmpimage.h"
|
#include <cstdint>
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
const std::string FILENAME = "../elef.bmp";
|
struct BitmapFileHeader {
|
||||||
const std::string FILENAME_OUT = "../elef_out.bmp";
|
char signature[2] = {0, 0};
|
||||||
|
uint32_t fileSize = 0;
|
||||||
|
uint16_t reserved1 = 0;
|
||||||
|
uint16_t reserved2 = 0;
|
||||||
|
uint32_t imageDataOffset = 0;
|
||||||
|
};
|
||||||
|
|
||||||
void lab01() {
|
const std::string FILENAME = "elef.bmp";
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main() {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue