diff --git a/03/README.md b/03/README.md index 51ffbc2..c029ba6 100644 --- a/03/README.md +++ b/03/README.md @@ -1,3 +1,5 @@ # Rozwiązania laboratoria 03 -# Znajdują się w katalogu ./03/do_sprawdzenia/cpp/mysimplegimp \ No newline at end of file +Cały kod znajduje się w katalogu głównym ,,app/cpp/mysimplegimp'' +Zmienieone pliki projektu dla zadania 3-ego znajdują się w katalogu ,,03/do_sprawdzenia'' + diff --git a/03/do_sprawdzenia/histogram.cpp b/03/do_sprawdzenia/histogram.cpp new file mode 100644 index 0000000..db2d8d6 --- /dev/null +++ b/03/do_sprawdzenia/histogram.cpp @@ -0,0 +1,136 @@ +#include "histogram.h" + +#include +#include + +#include + +Histogram::Histogram(QImage* image) +{ + R = new QHash; + G = new QHash; + B = new QHash; + L = new QHash; + generate(image); +} + +Histogram::~Histogram() +{ + delete R; + delete G; + delete B; + delete L; +} + +void Histogram::generate(QImage* image) +{ + int width = image->width(); + int height = image->height(); + + for (int x = 0; x < width; x++) { + + for (int y = 0; y < height; y++) { + + QRgb pixel = image->pixel(x,y); + + // Get color values + int r = Histogram::R->value(qRed(pixel)); + int g = Histogram::G->value(qGreen(pixel)); + int b = Histogram::B->value(qBlue(pixel)); + int l = Histogram::L->value(qGray(pixel)); + + // Insert color values + Histogram::R->insert(qRed(pixel), r+1); + Histogram::G->insert(qGreen(pixel), g+1); + Histogram::B->insert(qBlue(pixel), b+1); + Histogram::L->insert(qGray(pixel), l+1); + } + } +} + +/** Returns the maximal value of the histogram in the given channel */ +int Histogram::maximumValue(Channel selectedChannel = RGB) +{ + // Create and set max value + int max = 0; + + // Iterate over values + for(int i = 0; i < R->size(); i++) + { + if(R->value(i) > max) + { + max = R->value(i); + } + } + for(int i = 0; i < G->size(); i++) + { + if(G->value(i) > max) + { + max = G->value(i); + } + } + for(int i = 0; i < B->size(); i++) + { + if(B->value(i) > max) + { + max = B->value(i); + } + } + for(int i = 0; i < L->size(); i++) + { + if(L->value(i) > max) + { + max = L->value(i); + } + } + + return max; +} + + +/** Returns a pointer to the given channel QHash */ +QHash* Histogram::get(Channel channel = LChannel) +{ + if (channel==LChannel) return L; + if (channel==RChannel) return R; + if (channel==GChannel) return G; + if (channel==BChannel) return B; + + return 0; +} + +/** + * Returns a 255 by 100 QImage containing a Histogram for the given channel. + * The background is transparent (Alpha 0, RGB=255) */ +QImage Histogram::getImage(Channel channel = LChannel, QBrush pen = Qt::gray) +{ + // Create blank QImage and fill it with transparent background: + QImage histImage(255, 100, QImage::Format_ARGB32); + histImage.fill(0); + QPainter painter(&histImage); + painter.setBrush(Qt::transparent); + painter.setPen(Qt::transparent); + painter.drawRect(0,0,255,100); + + // Calculate the aspect ratio using the maximal value of the color histograms + int maximum = (channel == LChannel ? maximumValue(LChannel) : maximumValue(RGB)); + float ratio = 100.0/float(maximum); + + // Preparing the painter: + painter.setBrush(pen); + painter.setPen(pen.color()); + + int h; + // Draw histogram + QHash* hist = get(channel); + QHash::const_iterator cit = hist->begin(); + + while (cit != hist->end()) + { + h = 100 - floor(ratio*cit.value()); + painter.drawLine(cit.key(), h, cit.key(), 100); + ++cit; + } + + return histImage; +} diff --git a/03/do_sprawdzenia/histogram_equalization.cpp b/03/do_sprawdzenia/histogram_equalization.cpp new file mode 100644 index 0000000..b3331b3 --- /dev/null +++ b/03/do_sprawdzenia/histogram_equalization.cpp @@ -0,0 +1,108 @@ +#include "histogram_equalization.h" + +#include "../histogram.h" + +HistogramEqualization::HistogramEqualization(PNM* img) : + Transformation(img) +{ +} + +HistogramEqualization::HistogramEqualization(PNM* img, ImageViewer* iv) : + Transformation(img, iv) +{ +} + +PNM* HistogramEqualization::transform() +{ + float width = image->width(); + float height = image->height(); + + PNM* newImage = new PNM(width, height, image->format()); + + // Create histogram + Histogram* histogram = image->getHistogram(); + + // Create pointers QHash + QHash* R = histogram->get(Histogram::RChannel); + QHash* G = histogram->get(Histogram::GChannel); + QHash* B = histogram->get(Histogram::BChannel); + QHash* L = histogram->get(Histogram::LChannel); + + // Setup Channel p + float Rp[255]; + float Gp[255]; + float Bp[255]; + float Lp[255]; + + // Setup Channel D + float RD[255]; + float GD[255]; + float BD[255]; + float LD[255]; + + // Get size + float size = width * height; + + // Create template values + float tempSumR=0; + float tempSumG=0; + float tempSumB=0; + float tempSumL=0; + + + for (int i=0; i<256; i++) + { + // Set Xp[i] values + Rp[i] = (R->value(i))/(size); + Gp[i] = (G->value(i))/(size); + Bp[i] = (B->value(i))/(size); + Lp[i] = (L->value(i))/(size); + } + + + for(int i=0; i<255; i++) + { + // Red + tempSumR=Rp[i]+tempSumR; + RD[i]=tempSumR; + + // Green + tempSumG=Gp[i]+tempSumG; + GD[i]=tempSumG; + + // Blue + tempSumB=Bp[i]+tempSumB; + BD[i]=tempSumB; + + // L + tempSumL=Lp[i]+tempSumL; + LD[i]=tempSumL; + } + + + // For each pixel + for (int x=0; xpixel(x, y); + + // Set new values + int r = RD[qRed(pixel)] * 255; + int g = GD[qGreen(pixel)] * 255; + int b = BD[qBlue(pixel)] * 255; + int l = LD[qGray(pixel)] * 255; + + if (image->format() == QImage::Format_RGB32) + { + newImage->setPixel(x, y, QColor(r,g,b).rgb()); + } + else + { + newImage->setPixel(x, y, l); + } + } + } + return newImage; +} diff --git a/03/do_sprawdzenia/histogram_stretching.cpp b/03/do_sprawdzenia/histogram_stretching.cpp new file mode 100644 index 0000000..f371e58 --- /dev/null +++ b/03/do_sprawdzenia/histogram_stretching.cpp @@ -0,0 +1,88 @@ +#include "histogram_stretching.h" + +#include "../histogram.h" + +HistogramStretching::HistogramStretching(PNM* img) : + Transformation(img) +{ +} + +HistogramStretching::HistogramStretching(PNM* img, ImageViewer* iv) : + Transformation(img, iv) +{ +} + +PNM* HistogramStretching::transform() +{ + int width = image->width(); + int height = image->height(); + + PNM* newImage = new PNM(width, height, image->format()); + + // Create min values + int minR = 0; + int minG = 0; + int minB = 0; + int minL = 0; + + // Create max values + int maxR = 255; + int maxG = 255; + int maxB = 255; + int maxL = 255; + + // Create histogram + Histogram* histogram = image->getHistogram(); + + // Create pointers QHash + QHash* R = histogram->get(histogram->RChannel); + QHash* G = histogram->get(histogram->GChannel); + QHash* B = histogram->get(histogram->BChannel); + QHash* L = histogram->get(histogram->LChannel); + + // Increment max values + for (int i=0; i<256; i++) + { + if (R->value(minR) == 0) minR++; + if (G->value(minG) == 0) minG++; + if (B->value(minB) == 0) minB++; + if (L->value(minL) == 0) minL++; + } + // Decrement max values + for (int i=256; i>0; i--) + { + if (R->value(maxR) == 0) maxR--; + if (G->value(maxG) == 0) maxG--; + if (B->value(maxB) == 0) maxB--; + if (L->value(maxL) == 0) maxL--; + } + + // Iterate over pixels + for (int x=0; xpixel(x, y); + + // Calculate new values + int r = (255/(maxR-minR))*(qRed(pixel)-minR); + int g = (255/(maxG-minG))*(qGreen(pixel)-minG); + int b = (255/(maxB-minB))*(qBlue(pixel)-minB); + int l = (255/(maxL-minL))*(qGray(pixel)-minL); + + if (image->format() == QImage::Format_RGB32) + { + // Set pixel in RGB32 model + newImage->setPixel(x, y, QColor(r,g,b).rgb()); + } + else + { + // Set pixel + newImage->setPixel(x, y, l); + } + } + } + return newImage; +} + + diff --git a/app/cpp/mysimplegimp/src/core/histogram.cpp b/app/cpp/mysimplegimp/src/core/histogram.cpp index 1287666..db2d8d6 100644 --- a/app/cpp/mysimplegimp/src/core/histogram.cpp +++ b/app/cpp/mysimplegimp/src/core/histogram.cpp @@ -24,15 +24,67 @@ Histogram::~Histogram() void Histogram::generate(QImage* image) { - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + int width = image->width(); + int height = image->height(); + + for (int x = 0; x < width; x++) { + + for (int y = 0; y < height; y++) { + + QRgb pixel = image->pixel(x,y); + + // Get color values + int r = Histogram::R->value(qRed(pixel)); + int g = Histogram::G->value(qGreen(pixel)); + int b = Histogram::B->value(qBlue(pixel)); + int l = Histogram::L->value(qGray(pixel)); + + // Insert color values + Histogram::R->insert(qRed(pixel), r+1); + Histogram::G->insert(qGreen(pixel), g+1); + Histogram::B->insert(qBlue(pixel), b+1); + Histogram::L->insert(qGray(pixel), l+1); + } + } } /** Returns the maximal value of the histogram in the given channel */ int Histogram::maximumValue(Channel selectedChannel = RGB) { - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + // Create and set max value + int max = 0; - return 0; + // Iterate over values + for(int i = 0; i < R->size(); i++) + { + if(R->value(i) > max) + { + max = R->value(i); + } + } + for(int i = 0; i < G->size(); i++) + { + if(G->value(i) > max) + { + max = G->value(i); + } + } + for(int i = 0; i < B->size(); i++) + { + if(B->value(i) > max) + { + max = B->value(i); + } + } + for(int i = 0; i < L->size(); i++) + { + if(L->value(i) > max) + { + max = L->value(i); + } + } + + return max; } diff --git a/app/cpp/mysimplegimp/src/core/transformations/histogram_equalization.cpp b/app/cpp/mysimplegimp/src/core/transformations/histogram_equalization.cpp index ab76cd3..b3331b3 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/histogram_equalization.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/histogram_equalization.cpp @@ -14,13 +14,95 @@ HistogramEqualization::HistogramEqualization(PNM* img, ImageViewer* iv) : PNM* HistogramEqualization::transform() { - int width = image->width(); - int height = image->height(); + float width = image->width(); + float height = image->height(); PNM* newImage = new PNM(width, height, image->format()); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + // Create histogram + Histogram* histogram = image->getHistogram(); + // Create pointers QHash + QHash* R = histogram->get(Histogram::RChannel); + QHash* G = histogram->get(Histogram::GChannel); + QHash* B = histogram->get(Histogram::BChannel); + QHash* L = histogram->get(Histogram::LChannel); + + // Setup Channel p + float Rp[255]; + float Gp[255]; + float Bp[255]; + float Lp[255]; + + // Setup Channel D + float RD[255]; + float GD[255]; + float BD[255]; + float LD[255]; + + // Get size + float size = width * height; + + // Create template values + float tempSumR=0; + float tempSumG=0; + float tempSumB=0; + float tempSumL=0; + + + for (int i=0; i<256; i++) + { + // Set Xp[i] values + Rp[i] = (R->value(i))/(size); + Gp[i] = (G->value(i))/(size); + Bp[i] = (B->value(i))/(size); + Lp[i] = (L->value(i))/(size); + } + + + for(int i=0; i<255; i++) + { + // Red + tempSumR=Rp[i]+tempSumR; + RD[i]=tempSumR; + + // Green + tempSumG=Gp[i]+tempSumG; + GD[i]=tempSumG; + + // Blue + tempSumB=Bp[i]+tempSumB; + BD[i]=tempSumB; + + // L + tempSumL=Lp[i]+tempSumL; + LD[i]=tempSumL; + } + + + // For each pixel + for (int x=0; xpixel(x, y); + + // Set new values + int r = RD[qRed(pixel)] * 255; + int g = GD[qGreen(pixel)] * 255; + int b = BD[qBlue(pixel)] * 255; + int l = LD[qGray(pixel)] * 255; + + if (image->format() == QImage::Format_RGB32) + { + newImage->setPixel(x, y, QColor(r,g,b).rgb()); + } + else + { + newImage->setPixel(x, y, l); + } + } + } return newImage; } - diff --git a/app/cpp/mysimplegimp/src/core/transformations/histogram_stretching.cpp b/app/cpp/mysimplegimp/src/core/transformations/histogram_stretching.cpp index 25440de..f371e58 100644 --- a/app/cpp/mysimplegimp/src/core/transformations/histogram_stretching.cpp +++ b/app/cpp/mysimplegimp/src/core/transformations/histogram_stretching.cpp @@ -14,13 +14,74 @@ HistogramStretching::HistogramStretching(PNM* img, ImageViewer* iv) : PNM* HistogramStretching::transform() { - int width = image->width(); + int width = image->width(); int height = image->height(); PNM* newImage = new PNM(width, height, image->format()); - qDebug() << Q_FUNC_INFO << "Not implemented yet!"; + // Create min values + int minR = 0; + int minG = 0; + int minB = 0; + int minL = 0; + // Create max values + int maxR = 255; + int maxG = 255; + int maxB = 255; + int maxL = 255; + + // Create histogram + Histogram* histogram = image->getHistogram(); + + // Create pointers QHash + QHash* R = histogram->get(histogram->RChannel); + QHash* G = histogram->get(histogram->GChannel); + QHash* B = histogram->get(histogram->BChannel); + QHash* L = histogram->get(histogram->LChannel); + + // Increment max values + for (int i=0; i<256; i++) + { + if (R->value(minR) == 0) minR++; + if (G->value(minG) == 0) minG++; + if (B->value(minB) == 0) minB++; + if (L->value(minL) == 0) minL++; + } + // Decrement max values + for (int i=256; i>0; i--) + { + if (R->value(maxR) == 0) maxR--; + if (G->value(maxG) == 0) maxG--; + if (B->value(maxB) == 0) maxB--; + if (L->value(maxL) == 0) maxL--; + } + + // Iterate over pixels + for (int x=0; xpixel(x, y); + + // Calculate new values + int r = (255/(maxR-minR))*(qRed(pixel)-minR); + int g = (255/(maxG-minG))*(qGreen(pixel)-minG); + int b = (255/(maxB-minB))*(qBlue(pixel)-minB); + int l = (255/(maxL-minL))*(qGray(pixel)-minL); + + if (image->format() == QImage::Format_RGB32) + { + // Set pixel in RGB32 model + newImage->setPixel(x, y, QColor(r,g,b).rgb()); + } + else + { + // Set pixel + newImage->setPixel(x, y, l); + } + } + } return newImage; }