diff --git a/ImageUtils.cpp b/ImageUtils.cpp index 1906f4b..823247b 100644 --- a/ImageUtils.cpp +++ b/ImageUtils.cpp @@ -180,6 +180,80 @@ void ImageUtils::pasteImage(T* sourceImgDataPtr, const Dim& sourceDim, long star } } +template +std::pair ImageUtils::maxPool(T* sourceImgDataPtr, const Dim& sourceDim, const long poolSize) +{ + Dim targetDim = { sourceDim.width/poolSize, sourceDim.height/poolSize }; + Dim poolDim = { poolSize, poolSize }; + + T* t = new T[targetDim.getLength()]; + + for (auto y = 0; y < targetDim.height; y++) + { + for (auto x = 0; x < targetDim.width; x++) + { + T* clip = subImage(sourceImgDataPtr, sourceDim, x * poolSize, y * poolSize, poolDim); + T* tPixel = getPixelPtr(t, targetDim, x, y); + + auto max = 0.0; + + eachPixel(clip, poolDim, [&](T* rgbArray, long, long) + { + auto sum = rgbArray[0] + rgbArray[1] + rgbArray[2]; + if (sum > max) + { + max = sum; + tPixel[0] = rgbArray[0]; + tPixel[1] = rgbArray[1]; + tPixel[2] = rgbArray[2]; + } + }); + + delete[] clip; + } + } + + return { t, targetDim }; +} + +template +std::pair ImageUtils::meanPool(T* sourceImgDataPtr, const Dim& sourceDim, const long poolSize) +{ + Dim targetDim = { sourceDim.width / poolSize, sourceDim.height / poolSize }; + Dim poolDim = { poolSize, poolSize }; + const double numPoolPixels = poolDim.width * poolDim.height; + + T* t = new T[targetDim.getLength()]; + + for (auto y = 0; y < targetDim.height; y++) + { + for (auto x = 0; x < targetDim.width; x++) + { + T* clip = subImage(sourceImgDataPtr, sourceDim, x * poolSize, y * poolSize, poolDim); + T* tPixel = getPixelPtr(t, targetDim, x, y); + + double rSum = 0; + double gSum = 0; + double bSum = 0; + + eachPixel(clip, poolDim, [&](T* rgbArray, long, long) + { + rSum += rgbArray[0]; + gSum += rgbArray[1]; + bSum += rgbArray[2]; + }); + + tPixel[0] = static_cast(rSum / numPoolPixels); + tPixel[1] = static_cast(gSum / numPoolPixels); + tPixel[2] = static_cast(bSum / numPoolPixels); + + delete[] clip; + } + } + + return { t, targetDim }; +} + template U* ImageUtils::toNewType(T* fromImgDataPtr, const Dim& dim) { diff --git a/ImageUtils.h b/ImageUtils.h index 5bc3e2c..f9e058b 100644 --- a/ImageUtils.h +++ b/ImageUtils.h @@ -139,8 +139,24 @@ class ImageUtils template static T* subImage(T* sourceImgDataPtr, const Dim& sourceDim, long startX, long startY, const Dim& targetDim); + /** + * + * @tparam T type of image data array. + * @param sourceImgDataPtr pointer to the source image data array. + * @param sourceDim dimension of the source image. + * @param startX x-location of the top left coordinate of the source of the sub image in the source image. + * @param startY y-location of the top left coordinate of the source of the sub image in the source image. + * @param pasteImgDataPtr pointer to the smaller image data array. + * @param pasteDim dimension of the smaller image. + */ template static void pasteImage(T* sourceImgDataPtr, const Dim& sourceDim, long startX, long startY, T* pasteImgDataPtr, const Dim& pasteDim); + + template + static std::pair maxPool(T* sourceImgDataPtr, const Dim& sourceDim, long poolSize); + + template + static std::pair meanPool(T* sourceImgDataPtr, const Dim& sourceDim, long poolSize); }; //Template prototype functions @@ -166,6 +182,10 @@ template unsigned char* ImageUtils::subImage(unsigned char*, const Dim&, long, l template double* ImageUtils::subImage(double*, const Dim&, long, long, const Dim&); template void ImageUtils::pasteImage(unsigned char*, const Dim&, long, long, unsigned char*, const Dim&); template void ImageUtils::pasteImage(double*, const Dim&, long, long, double*, const Dim&); +template std::pair ImageUtils::maxPool(double* sourceImgDataPtr, const Dim& sourceDim, long poolSize); +template std::pair ImageUtils::maxPool(unsigned char* sourceImgDataPtr, const Dim& sourceDim, long poolSize); +template std::pair ImageUtils::meanPool(double* sourceImgDataPtr, const Dim& sourceDim, long poolSize); +template std::pair ImageUtils::meanPool(unsigned char* sourceImgDataPtr, const Dim& sourceDim, long poolSize); template struct ImageWrapper @@ -227,6 +247,22 @@ struct ImageWrapper { ImageUtils::pasteImage(dataPtr, dim, x, y, other.dataPtr, other.dim); } + ImageWrapper maxPool(long poolSize) + { + auto[pooledImage, pooledDim] = ImageUtils::maxPool(dataPtr, dim, poolSize); + return { + pooledImage, + pooledDim + }; + } + ImageWrapper meanPool(long poolSize) + { + auto[pooledImage, pooledDim] = ImageUtils::meanPool(dataPtr, dim, poolSize); + return { + pooledImage, + pooledDim + }; + } ImageWrapper(T* imgDataPtr, const Dim& dim): dataPtr(imgDataPtr), dim(dim) {} ImageWrapper(const ImageWrapper& other) { diff --git a/MosaicBuilder.cpp b/MosaicBuilder.cpp index 5d2719b..f6985c0 100644 --- a/MosaicBuilder.cpp +++ b/MosaicBuilder.cpp @@ -147,7 +147,9 @@ ImageWrapper MosaicBuilder::makeGradientImage(const ImageWrapper< rgbArray[2] = 255; }); - return sobelY; + auto gradient = sobelY.maxPool(5); + + return gradient; } ImageWrapper MosaicBuilder::makeColorImage(const ImageWrapper& imgWrapper) @@ -175,8 +177,9 @@ ImageWrapper MosaicBuilder::makeColorImage(const ImageWrapper{ readBMP(entry.path().string().c_str(), width, height), - TILE_DIM + { width, height } }, new ImageWrapper{ - readBMP(entry.path().string().c_str(), width, height), - TILE_DIM + readBMP(resultGradientPath.string().c_str(), width, height), + { width, height } }, new ImageWrapper{ - readBMP(entry.path().string().c_str(), width, height), - TILE_DIM + readBMP(resultColorPath.string().c_str(), width, height), + { width, height } } }; } @@ -264,7 +267,9 @@ void MosaicBuilder::saveGradientImage(ImageWrapper& imgWrapper, c imgWrapper.dataPtr = readBMP(imgPath.string().c_str(), width, height); } - writeBMP(resultGradientPath.string().c_str(), TILE_DIM.width, TILE_DIM.height, makeGradientImage(imgWrapper).dataPtr); + const auto gradient = makeGradientImage(imgWrapper); + + writeBMP(resultGradientPath.string().c_str(), gradient.dim.width, gradient.dim.height, gradient.dataPtr); } } @@ -282,6 +287,8 @@ void MosaicBuilder::saveColorImage(ImageWrapper& imgWrapper, cons imgWrapper.dataPtr = readBMP(imgPath.string().c_str(), width, height); } - writeBMP(resultColorPath.string().c_str(), TILE_DIM.width, TILE_DIM.height, makeColorImage(imgWrapper).dataPtr); + const auto color = makeColorImage(imgWrapper); + + writeBMP(resultColorPath.string().c_str(), color.dim.width, color.dim.height, color.dataPtr); } } diff --git a/MosaicImage.cpp b/MosaicImage.cpp index 76a32b4..68c060c 100644 --- a/MosaicImage.cpp +++ b/MosaicImage.cpp @@ -45,14 +45,14 @@ void MosaicImage::applySubstitutions() auto limit = static_cast(MosaicBuilder::tileLimitSliderPtr->value()); - for (auto& pair : MosaicBuilder::imagePool) + for (auto& [key, set] : MosaicBuilder::imagePool) { if (limit == 0) break; - const auto score = MosaicBuilder::calculateScores(sourceTile, pair.second); + const auto score = MosaicBuilder::calculateScores(sourceTile, set); if (score < bestScore) { bestScore = score; - bestImagePtr = pair.second.original; + bestImagePtr = set.original; } limit--; }