diff --git a/09/do_sprawdzenia/cpp/edge_sobel.cpp b/09/do_sprawdzenia/cpp/edge_sobel.cpp new file mode 100644 index 0000000..1afb829 --- /dev/null +++ b/09/do_sprawdzenia/cpp/edge_sobel.cpp @@ -0,0 +1,55 @@ +#include "edge_sobel.h" +#include + +EdgeSobel::EdgeSobel(PNM* img, ImageViewer* iv) : + EdgeGradient(img, iv) +{ + prepareMatrices(); +} + +EdgeSobel::EdgeSobel(PNM* img) : + EdgeGradient(img) +{ + prepareMatrices(); +} + +void EdgeSobel::prepareMatrices() +{ + g_x = math::matrix(3, 3, {-1, 0, 1, -2, 0, 2, -1, 0, 1}); + g_y = math::matrix(3, 3, {-1, -2, -1, 0, 0, 0, 1, 2, 1}); +} + +math::matrix* EdgeSobel::rawHorizontalDetection() +{ + int width = image->width(); + int height = image->height(); + + math::matrix* x_gradient = new math::matrix(width, height); + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + (*x_gradient)(i, j) = sum(join(g_x, getWindow(i, j, 3, LChannel, RepeatEdge))); + } + } + return x_gradient; +} + +math::matrix* EdgeSobel::rawVerticalDetection() +{ + int width = image->width(); + int height = image->height(); + + math::matrix* y_gradient = new math::matrix(width, height); + math::matrix window; + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + (*y_gradient)(i, j) = sum(join(g_y, getWindow(i, j, 3, LChannel, RepeatEdge))); + } + } + return y_gradient; +} diff --git a/09/do_sprawdzenia/cpp/image1.png b/09/do_sprawdzenia/cpp/image1.png new file mode 100644 index 0000000..783227d Binary files /dev/null and b/09/do_sprawdzenia/cpp/image1.png differ diff --git a/09/do_sprawdzenia/cpp/image2.png b/09/do_sprawdzenia/cpp/image2.png new file mode 100644 index 0000000..437f8e4 Binary files /dev/null and b/09/do_sprawdzenia/cpp/image2.png differ diff --git a/09/do_sprawdzenia/cpp/map_height.cpp b/09/do_sprawdzenia/cpp/map_height.cpp new file mode 100644 index 0000000..4caa43b --- /dev/null +++ b/09/do_sprawdzenia/cpp/map_height.cpp @@ -0,0 +1,24 @@ +#include "map_height.h" +#include "conversion_grayscale.h" + +MapHeight::MapHeight(PNM* img) : + Transformation(img) +{ +} + +MapHeight::MapHeight(PNM* img, ImageViewer* iv) : + Transformation(img, iv) +{ +} + +PNM* MapHeight::transform() +{ + int width = image->width(); + int height = image->height(); + + PNM* newImage = new PNM(width, height, image->format()); + ConversionGrayscale* grayscale = new ConversionGrayscale(image); + + newImage = grayscale->transform(); + return newImage; +} diff --git a/09/do_sprawdzenia/cpp/map_horizon.cpp b/09/do_sprawdzenia/cpp/map_horizon.cpp new file mode 100644 index 0000000..64aa9eb --- /dev/null +++ b/09/do_sprawdzenia/cpp/map_horizon.cpp @@ -0,0 +1,83 @@ +#include "map_horizon.h" + +#include "map_height.h" + +MapHorizon::MapHorizon(PNM* img) : + Transformation(img) +{ +} + +MapHorizon::MapHorizon(PNM* img, ImageViewer* iv) : + Transformation(img, iv) +{ +} + +PNM* MapHorizon::transform() +{ + int width = image->width(), + height = image->height(); + + double scale = getParameter("scale").toDouble(); + int sun_alpha = getParameter("alpha").toInt(); + int dx, dy; + + switch (getParameter("direction").toInt()) + { + case NORTH: dx = 0; dy = -1; break; + case SOUTH: dx = 0; dy = 1; break; + case EAST: dx = 1; dy = 0; break; + case WEST: dx = -1; dy = 0; break; + default: + qWarning() << "Unknown direction!"; + dx = 0; + dy = -1; + } + + PNM* newImage = new PNM(width, height, image->format()); + + MapHeight* mapHeight = new MapHeight(image); + + image = mapHeight->transform(); + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + double alpha = 0; + int current_h = qGray(image->pixel(i, j)); + + for (int k = i + dx, l = j + dy; k < width && l < height && k >= 0 && l >= 0; k = k + dx, l = l + dy) + { + int ray_h = qGray(image->pixel(k, l)); + + if (current_h < ray_h) + { + double dist = sqrt(pow(k - i, 2) + pow(l - j, 2)) * scale; + double ray_alpha = atan((ray_h - current_h) / dist); + + if (ray_alpha > alpha) + { + alpha = ray_alpha; + } + } + + } + + double delta = alpha - sun_alpha * M_PI / 180; + + if (delta > 0) + { + double val = cos(delta) * 255; + QColor color = QColor(val, val, val); + newImage->setPixel(i, j, color.rgb()); + } + else + { + QColor color = QColor(255, 255, 255); + newImage->setPixel(i, j, color.rgb()); + } + + } + } + return newImage; +} diff --git a/09/do_sprawdzenia/cpp/map_normal.cpp b/09/do_sprawdzenia/cpp/map_normal.cpp new file mode 100644 index 0000000..0a8faa8 --- /dev/null +++ b/09/do_sprawdzenia/cpp/map_normal.cpp @@ -0,0 +1,61 @@ +#include "map_normal.h" + +#include "edge_sobel.h" +#include "map_height.h" +#include + +MapNormal::MapNormal(PNM* img) : + Convolution(img) +{ +} + +MapNormal::MapNormal(PNM* img, ImageViewer* iv) : + Convolution(img, iv) +{ +} + +PNM* MapNormal::transform() +{ + int width = image->width(); + int height = image->height(); + + // The power constant of the generated normal map. + double strength = getParameter("strength").toDouble(); + + PNM* newImage = new PNM(width, height, image->format()); + + MapHeight* mh = new MapHeight(image); + PNM* image = mh->transform(); + + EdgeSobel* es = new EdgeSobel(image); + math::matrix* Gx = es->rawHorizontalDetection(); + math::matrix* Gy = es->rawVerticalDetection(); + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + // For each pixel (i,j), determine the coordinates of the vector d + float dx = (*Gx)(i, j) / 255; + float dy = (*Gy)(i, j) / 255; + float dz = 1.0 / strength; + + // Normalise the vector d + double dw = sqrt(pow(dx, 2) + pow(dy, 2) + pow(dz, 2)); + + // Scale these values to the interval + dx = dx / dw; + dy = dy / dw; + dz = dz / dw; + + dx = (dx + 1.0) * (255 / strength); + dy = (dy + 1.0) * (255 / strength); + dz = (dz + 1.0) * (255 / strength); + + QColor newPixel = QColor(dx, dy, dz); + newImage->setPixel(i, j, newPixel.rgb()); + } + } + + return newImage; +} diff --git a/app/cpp/mysimplegimp/src/core/transformations/edge_sobel.cpp b/app/cpp/mysimplegimp/src/core/transformations/edge_sobel.cpp index 237ef1d..1afb829 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/edge_sobel.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/edge_sobel.cpp @@ -1,4 +1,5 @@ #include "edge_sobel.h" +#include EdgeSobel::EdgeSobel(PNM* img, ImageViewer* iv) : EdgeGradient(img, iv) @@ -20,18 +21,35 @@ void EdgeSobel::prepareMatrices() math::matrix* EdgeSobel::rawHorizontalDetection() { - math::matrix* x_gradient = new math::matrix(this->image->width(), this->image->height()); + int width = image->width(); + int height = image->height(); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + math::matrix* x_gradient = new math::matrix(width, height); + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + (*x_gradient)(i, j) = sum(join(g_x, getWindow(i, j, 3, LChannel, RepeatEdge))); + } + } return x_gradient; } math::matrix* EdgeSobel::rawVerticalDetection() { - math::matrix* y_gradient = new math::matrix(this->image->width(), this->image->height()); + int width = image->width(); + int height = image->height(); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + math::matrix* y_gradient = new math::matrix(width, height); + math::matrix window; + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + (*y_gradient)(i, j) = sum(join(g_y, getWindow(i, j, 3, LChannel, RepeatEdge))); + } + } return y_gradient; } diff --git a/app/cpp/mysimplegimp/src/core/transformations/map_height.cpp b/app/cpp/mysimplegimp/src/core/transformations/map_height.cpp index 71687d3..4caa43b 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/map_height.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/map_height.cpp @@ -1,4 +1,5 @@ #include "map_height.h" +#include "conversion_grayscale.h" MapHeight::MapHeight(PNM* img) : Transformation(img) @@ -12,12 +13,12 @@ MapHeight::MapHeight(PNM* img, ImageViewer* iv) : PNM* MapHeight::transform() { - int width = image->width(), - height = image->height(); + int width = image->width(); + int height = image->height(); - PNM* newImage = new PNM(width, height, QImage::Format_Grayscale8); - - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + PNM* newImage = new PNM(width, height, image->format()); + ConversionGrayscale* grayscale = new ConversionGrayscale(image); + newImage = grayscale->transform(); return newImage; } diff --git a/app/cpp/mysimplegimp/src/core/transformations/map_horizon.cpp b/app/cpp/mysimplegimp/src/core/transformations/map_horizon.cpp index ebcef32..64aa9eb 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/map_horizon.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/map_horizon.cpp @@ -33,9 +33,51 @@ PNM* MapHorizon::transform() dy = -1; } - PNM* newImage = new PNM(width, height, QImage::Format_Grayscale8); + PNM* newImage = new PNM(width, height, image->format()); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + MapHeight* mapHeight = new MapHeight(image); + image = mapHeight->transform(); + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + double alpha = 0; + int current_h = qGray(image->pixel(i, j)); + + for (int k = i + dx, l = j + dy; k < width && l < height && k >= 0 && l >= 0; k = k + dx, l = l + dy) + { + int ray_h = qGray(image->pixel(k, l)); + + if (current_h < ray_h) + { + double dist = sqrt(pow(k - i, 2) + pow(l - j, 2)) * scale; + double ray_alpha = atan((ray_h - current_h) / dist); + + if (ray_alpha > alpha) + { + alpha = ray_alpha; + } + } + + } + + double delta = alpha - sun_alpha * M_PI / 180; + + if (delta > 0) + { + double val = cos(delta) * 255; + QColor color = QColor(val, val, val); + newImage->setPixel(i, j, color.rgb()); + } + else + { + QColor color = QColor(255, 255, 255); + newImage->setPixel(i, j, color.rgb()); + } + + } + } return newImage; } diff --git a/app/cpp/mysimplegimp/src/core/transformations/map_normal.cpp b/app/cpp/mysimplegimp/src/core/transformations/map_normal.cpp index 472632b..0a8faa8 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/map_normal.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/map_normal.cpp @@ -2,6 +2,7 @@ #include "edge_sobel.h" #include "map_height.h" +#include MapNormal::MapNormal(PNM* img) : Convolution(img) @@ -15,14 +16,46 @@ MapNormal::MapNormal(PNM* img, ImageViewer* iv) : PNM* MapNormal::transform() { - int width = image->width(), - height = image->height(); + int width = image->width(); + int height = image->height(); + // The power constant of the generated normal map. double strength = getParameter("strength").toDouble(); PNM* newImage = new PNM(width, height, image->format()); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + MapHeight* mh = new MapHeight(image); + PNM* image = mh->transform(); + + EdgeSobel* es = new EdgeSobel(image); + math::matrix* Gx = es->rawHorizontalDetection(); + math::matrix* Gy = es->rawVerticalDetection(); + + for (int i = 0; i < width; i++) + { + for (int j = 0; j < height; j++) + { + // For each pixel (i,j), determine the coordinates of the vector d + float dx = (*Gx)(i, j) / 255; + float dy = (*Gy)(i, j) / 255; + float dz = 1.0 / strength; + + // Normalise the vector d + double dw = sqrt(pow(dx, 2) + pow(dy, 2) + pow(dz, 2)); + + // Scale these values to the interval + dx = dx / dw; + dy = dy / dw; + dz = dz / dw; + + dx = (dx + 1.0) * (255 / strength); + dy = (dy + 1.0) * (255 / strength); + dz = (dz + 1.0) * (255 / strength); + + QColor newPixel = QColor(dx, dy, dz); + newImage->setPixel(i, j, newPixel.rgb()); + } + } return newImage; }