diff --git a/bmpimage.cpp b/bmpimage.cpp index b2ba7ec..8e3c24e 100644 --- a/bmpimage.cpp +++ b/bmpimage.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include "bmpimage.h" BMPImage::BMPImage(const BitmapFileHeader &fileHeader, const BITMAPINFOHEADER &infoHeader, const PixelArray &pixelArray) @@ -83,6 +85,7 @@ BMPImage BMPImage::appendRight(BMPImage &img) { uint32_t newWidth = this->infoHeader.BitmapWidth + img.width(); // Pixel **newPixelArray; PixelArray newPixelArray(newWidth, newHeight); +// std::shared_ptr newPixelArray = std::make_shared(newWidth, newHeight); // newPixelArray = new Pixel *[newHeight]; for (int i = 0; i < this->infoHeader.BitmapHeight; ++i) { // newPixelArray[i] = new Pixel[newWidth]; @@ -105,6 +108,32 @@ BMPImage BMPImage::overlay(BMPImage &img, uint32_t pos_x, uint32_t pos_y) { return {pixels}; } +BMPImage BMPImage::applyFilter(const std::function &)> &filter) { + auto origPixels = this->pixels_copy(); + PixelArray pixels(this->width(), this->height()); + for (int y = 1; y < this->height() - 1; ++y) { + for (int x = 1; x < this->width() - 1; ++x) { + auto p1 = origPixels(y - 1, x - 1); + auto p2 = origPixels(y - 1, x); + auto p3 = origPixels(y - 1, x + 1); + auto p4 = origPixels(y, x - 1); + auto p5 = origPixels(y, x); + auto p6 = origPixels(y, x + 1); + auto p7 = origPixels(y + 1, x - 1); + auto p8 = origPixels(y + 1, x); + auto p9 = origPixels(y + 1, x + 1); + std::array red_channel = {p1.r, p2.r, p3.r, p4.r, p5.r, p6.r, p7.r, p8.r, p9.r}; + std::array green_channel = {p1.g, p2.g, p3.g, p4.g, p5.g, p6.g, p7.g, p8.g, p9.g}; + std::array blue_channel = {p1.b, p2.b, p3.b, p4.b, p5.b, p6.b, p7.b, p8.b, p9.b}; + auto r = filter(red_channel); + auto g = filter(green_channel); + auto b = filter(blue_channel); + pixels(y, x) = {r, g, b}; + } + } + return {pixels}; +} + BMPImage readBMPImage(const std::string &filename) { BitmapFileHeader bitmapFileHeader; @@ -405,30 +434,39 @@ BMPImage upscale2x_ver2(BMPImage &img) { return {newPixelArray}; } -BMPImage filter(BMPImage &img, int mask[9], uint8_t modifier) { - auto origPixels = img.pixels_copy(); - PixelArray pixels(img.width(), img.height()); - for (int y = 1; y < img.height() - 1; ++y) { - for (int x = 1; x < img.width() - 1; ++x) { - auto p1 = origPixels(y - 1, x - 1); - auto p2 = origPixels(y - 1, x); - auto p3 = origPixels(y - 1, x + 1); - auto p4 = origPixels(y, x - 1); - auto p5 = origPixels(y, x); - auto p6 = origPixels(y, x + 1); - auto p7 = origPixels(y + 1, x - 1); - auto p8 = origPixels(y + 1, x); - auto p9 = origPixels(y + 1, x + 1); - auto r = p1.r * mask[0] + p2.r * mask[1] + p3.r * mask[2] + p4.r * mask[3] + p5.r * mask[4] + - p6.r * mask[5] + p7.r * mask[6] + p8.r * mask[7] + p9.r * mask[8]; - auto g = p1.g * mask[0] + p2.g * mask[1] + p3.g * mask[2] + p4.g * mask[3] + p5.g * mask[4] + - p6.g * mask[5] + p7.g * mask[6] + p8.g * mask[7] + p9.g * mask[8]; - auto b = p1.b * mask[0] + p2.b * mask[1] + p3.b * mask[2] + p4.b * mask[3] + p5.b * mask[4] + - p6.b * mask[5] + p7.b * mask[6] + p8.b * mask[7] + p9.b * mask[8]; - pixels(y, x) = {ui8_clamp(r / modifier), ui8_clamp(g / modifier), ui8_clamp(b / modifier)}; - } - } - return {pixels}; +uint8_t medianFilter(std::array &pixels) { + std::sort(pixels.begin(), pixels.end()); + return ui8_clamp(pixels[5]); +} + +uint8_t averageFilter(std::array &pixels) { + return ui8_clamp((pixels[0] * AVERAGE_MASK[0] + pixels[1] * AVERAGE_MASK[1] + pixels[2] * AVERAGE_MASK[2] + + pixels[3] * AVERAGE_MASK[3] + pixels[4] * AVERAGE_MASK[4] + pixels[5] * AVERAGE_MASK[5] + + pixels[6] * AVERAGE_MASK[6] + pixels[7] * AVERAGE_MASK[7] + pixels[8] * AVERAGE_MASK[8]) / 9); +} + +uint8_t prewittDXFilter(std::array &pixels) { + return ui8_clamp(pixels[0] * PREWITT_MASK_DX[0] + pixels[1] * PREWITT_MASK_DX[1] + pixels[2] * PREWITT_MASK_DX[2] + + pixels[3] * PREWITT_MASK_DX[3] + pixels[4] * PREWITT_MASK_DX[4] + pixels[5] * PREWITT_MASK_DX[5] + + pixels[6] * PREWITT_MASK_DX[6] + pixels[7] * PREWITT_MASK_DX[7] + pixels[8] * PREWITT_MASK_DX[8]); +} + +uint8_t prewittDYFilter(std::array &pixels) { + return ui8_clamp(pixels[0] * PREWITT_MASK_DY[0] + pixels[1] * PREWITT_MASK_DY[1] + pixels[2] * PREWITT_MASK_DY[2] + + pixels[3] * PREWITT_MASK_DY[3] + pixels[4] * PREWITT_MASK_DY[4] + pixels[5] * PREWITT_MASK_DY[5] + + pixels[6] * PREWITT_MASK_DY[6] + pixels[7] * PREWITT_MASK_DY[7] + pixels[8] * PREWITT_MASK_DY[8]); +} + +uint8_t sobelDXFilter(std::array &pixels) { + return ui8_clamp(pixels[0] * SOBEL_MASK_DX[0] + pixels[1] * SOBEL_MASK_DX[1] + pixels[2] * SOBEL_MASK_DX[2] + + pixels[3] * SOBEL_MASK_DX[3] + pixels[4] * SOBEL_MASK_DX[4] + pixels[5] * SOBEL_MASK_DX[5] + + pixels[6] * SOBEL_MASK_DX[6] + pixels[7] * SOBEL_MASK_DX[7] + pixels[8] * SOBEL_MASK_DX[8]); +} + +uint8_t sobelDYFilter(std::array &pixels) { + return ui8_clamp(pixels[0] * SOBEL_MASK_DY[0] + pixels[1] * SOBEL_MASK_DY[1] + pixels[2] * SOBEL_MASK_DY[2] + + pixels[3] * SOBEL_MASK_DY[3] + pixels[4] * SOBEL_MASK_DY[4] + pixels[5] * SOBEL_MASK_DY[5] + + pixels[6] * SOBEL_MASK_DY[6] + pixels[7] * SOBEL_MASK_DY[7] + pixels[8] * SOBEL_MASK_DY[8]); } PixelArray::PixelArray(uint32_t width, uint32_t height) { diff --git a/bmpimage.h b/bmpimage.h index 77de907..dc5e6a5 100644 --- a/bmpimage.h +++ b/bmpimage.h @@ -3,9 +3,17 @@ #include #include #include +#include +#include #include "psf.h" const char PADDING_ZEROES[3] = {0, 0, 0}; +const int AVERAGE_MASK[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; +const int PREWITT_MASK_DX[9] = {-1, 0, 1, -1, 0, 1, -1, 0, 1}; +const int PREWITT_MASK_DY[9] = {-1, -1, -1, 0, 0, 0, 1, 1, 1}; +const int SOBEL_MASK_DX[9] = {-1, 0, 1, -2, 0, 2, -1, 0, 1}; +const int SOBEL_MASK_DY[9] = {-1, -2, -1, 0, 0, 0, 1, 2, 1}; + #pragma pack(push, 1) struct BitmapFileHeader { @@ -91,6 +99,8 @@ public: BMPImage appendRight(BMPImage &); BMPImage overlay(BMPImage &, uint32_t, uint32_t); + + BMPImage applyFilter(const std::function&)>& filter); }; BMPImage readBMPImage(const std::string &filename); @@ -126,4 +136,14 @@ BMPImage textImg(const std::u16string &, Font *font, uint8_t scale = 1, Pixel ba uint8_t ui8_clamp(int value, uint8_t min = 0, uint8_t max = 255); -BMPImage filter(BMPImage &img, int mask[9], uint8_t modifier = 9); \ No newline at end of file +uint8_t medianFilter(std::array &); + +uint8_t averageFilter(std::array &); + +uint8_t prewittDXFilter(std::array &); + +uint8_t prewittDYFilter(std::array &); + +uint8_t sobelDXFilter(std::array &); + +uint8_t sobelDYFilter(std::array &); \ No newline at end of file diff --git a/main.cpp b/main.cpp index d35987a..9c9d12d 100644 --- a/main.cpp +++ b/main.cpp @@ -2,11 +2,8 @@ #include "bmpimage.h" #include "psf.h" -const std::string FILENAME = "../elef.bmp"; -const std::string FILENAME_OUT = "../elef_out.bmp"; auto font = readPSF("../fonts/ruscii_8x16_2.psf"); -// void lab01() { auto og_image = readBMPImage("../elef.bmp"); auto pixels1 = og_image.pixels_copy(); @@ -31,7 +28,6 @@ void lab01() { orig_text, 0, 0).save("../lab01/elef1.bmp"); } -// void lab02_01() { auto img = readBMPImage("../tea.bmp"); auto text1024 = textImg(u"1024", &font, 3); @@ -63,7 +59,6 @@ void lab02_01() { // newImg2->save("../lab02/tea_upscale.bmp"); } -// void lab02_02() { auto img = readBMPImage("../tea.bmp"); auto ogText = textImg(u"Оригинал", &font, 3); @@ -103,7 +98,6 @@ void lab02_02() { gsImg64).appendRight(gsImg32).save("../lab02/tea_grayscale.bmp"); } -// void lab02_03() { auto img = readBMPImage("../tea.bmp"); auto text = textImg(u"Оригинал", &font, 3); @@ -134,40 +128,39 @@ void lab02_03() { } void lab03() { - auto img = readBMPImage("../tea.bmp"); + auto img = readBMPImage("../bike.bmp"); auto imgGS = grayscale(img); - int avrg_mask[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; - int previtt_mask1[9] = {-1, 0, 1, -1, 0, 1, -1, 0, 1}; - int previtt_mask2[9] = {-1, -1, -1, 0, 0, 0, 1, 1, 1}; - int sobel_mask1[9] = {-1, 0, 1, -2, 0, 2, -1, 0, 1}; - int sobel_mask2[9] = {-1, -2, -1, 0, 0, 0, 1, 2, 1}; + auto avrg_text = textImg(u"Осреднение", &font, 3); - auto previtt_text = textImg(u"Фильтр Превитта", &font, 3); + auto median_text = textImg(u"Медиана", &font, 3); + auto prewitt_text = textImg(u"Фильтр Превитта", &font, 3); auto sobel_text = textImg(u"Фильтр Собеля", &font, 3); auto text = textImg(u"Оригинал", &font, 3); - auto avrg_image = filter(imgGS, avrg_mask).overlay(avrg_text, 0, 0); - auto previtt_image1 = filter(imgGS, previtt_mask1, 1);//.overlay(previtt_text, 0, 0); - auto previtt_image2 = filter(imgGS, previtt_mask2, 1);//.overlay(previtt_text, 0, 0); - previtt_image1.save("../lab03/previtt1.bmp"); - previtt_image2.save("../lab03/previtt2.bmp"); - PixelArray previttPixels(previtt_image1.width(), previtt_image1.height()); - for (int y = 0; y < previtt_image1.height(); ++y) { - for (int x = 0; x < previtt_image1.width(); ++x) { - previttPixels(y, x) = previtt_image1.pixels()(y, x) + previtt_image2.pixels()(y, x); + + auto avrg_image = imgGS.applyFilter(averageFilter).overlay(avrg_text, 0, 0); + auto median_image = imgGS.applyFilter(medianFilter).overlay(median_text, 0, 0); + auto prewitt_dx_image = imgGS.applyFilter(prewittDXFilter); + auto prewitt_dy_image = imgGS.applyFilter(prewittDYFilter); + prewitt_dx_image.save("../lab03/prewitt1.bmp"); + prewitt_dy_image.save("../lab03/prewitt2.bmp"); + PixelArray prewittPixels(prewitt_dx_image.width(), prewitt_dy_image.height()); + for (int y = 0; y < prewitt_dx_image.height(); ++y) { + for (int x = 0; x < prewitt_dx_image.width(); ++x) { + prewittPixels(y, x) = prewitt_dx_image.pixels()(y, x) + prewitt_dy_image.pixels()(y, x); } } - auto previtt_image = BMPImage(previttPixels).overlay(previtt_text, 0, 0); - auto sobel_image1 = filter(imgGS, sobel_mask1, 1).overlay(sobel_text, 0, 0); - auto sobel_image2 = filter(imgGS, sobel_mask2, 1).overlay(sobel_text, 0, 0); - PixelArray sobelPixels(sobel_image1.width(), sobel_image2.height()); - for (int y = 0; y < sobel_image1.height(); ++y) { - for (int x = 0; x < sobel_image1.width(); ++x) { - previttPixels(y, x) = sobel_image1.pixels()(y, x) + sobel_image2.pixels()(y, x); + auto prewitt_image = BMPImage(prewittPixels).overlay(prewitt_text, 0, 0); + auto sobel_dx_image = imgGS.applyFilter(sobelDXFilter).overlay(sobel_text, 0, 0); + auto sobel_dy_image2 = imgGS.applyFilter(sobelDYFilter).overlay(sobel_text, 0, 0); + PixelArray sobelPixels(sobel_dx_image.width(), sobel_dx_image.height()); + for (int y = 0; y < sobel_dx_image.height(); ++y) { + for (int x = 0; x < sobel_dx_image.width(); ++x) { + sobelPixels(y, x) = sobel_dx_image.pixels()(y, x) + sobel_dy_image2.pixels()(y, x); } } - auto sobel_image = BMPImage(previttPixels).overlay(sobel_text, 0, 0); - imgGS.overlay(text, 0, 0).appendRight(avrg_image).save("../lab03/avrg_filter.bmp"); - imgGS.overlay(text, 0, 0).appendRight(previtt_image).save("../lab03/previtt_filter.bmp"); + auto sobel_image = BMPImage(sobelPixels).overlay(sobel_text, 0, 0); + imgGS.overlay(text, 0, 0).appendRight(avrg_image).appendRight(median_image).save("../lab03/avrg_median_filter.bmp"); + imgGS.overlay(text, 0, 0).appendRight(prewitt_image).save("../lab03/prewitt_filter.bmp"); imgGS.overlay(text, 0, 0).appendRight(sobel_image).save("../lab03/sobel_filter.bmp"); } diff --git a/psf.cpp b/psf.cpp index 50d731a..9377be2 100644 --- a/psf.cpp +++ b/psf.cpp @@ -49,7 +49,7 @@ Font readPSF(const std::string &filename) { if (curByte != 0xFF) { vectorOfBytes.push_back(curByte); } else { - unsigned long long int bytesCount = vectorOfBytes.size(); + auto bytesCount = vectorOfBytes.size(); unsigned char bytes[bytesCount]; for (int i = 0; i < bytesCount; ++i) { bytes[i] = vectorOfBytes[i];