diff --git a/AbstractCommand.h b/AbstractCommand.h index 295f9f102..0377e3874 100644 --- a/AbstractCommand.h +++ b/AbstractCommand.h @@ -22,31 +22,12 @@ #include "ref_countable.h" #include "intrusive_ptr.h" -template -class AbstractCommand0 : public ref_countable { +template +class AbstractCommand : public ref_countable { public: - typedef intrusive_ptr Ptr; + typedef intrusive_ptr Ptr; - virtual R operator()() = 0; + virtual Res operator()(ArgTypes... args) = 0; }; - -template -class AbstractCommand1 : public ref_countable { -public: - typedef intrusive_ptr Ptr; - - virtual R operator()(A1 arg1) = 0; -}; - - -template -class AbstractCommand2 : public ref_countable { -public: - typedef intrusive_ptr Ptr; - - virtual R operator()(T1 arg1, T2 arg2) = 0; -}; - - #endif // ifndef ABSTRACTCOMMAND_H_ diff --git a/BackgroundExecutor.h b/BackgroundExecutor.h index a61f0bcc1..0e0dca3d2 100644 --- a/BackgroundExecutor.h +++ b/BackgroundExecutor.h @@ -29,8 +29,8 @@ class BackgroundExecutor { DECLARE_NON_COPYABLE(BackgroundExecutor) public: - typedef intrusive_ptr> TaskResultPtr; - typedef intrusive_ptr> TaskPtr; + typedef intrusive_ptr> TaskResultPtr; + typedef intrusive_ptr> TaskPtr; BackgroundExecutor(); diff --git a/BackgroundTask.h b/BackgroundTask.h index 557f8289d..41ebf071e 100644 --- a/BackgroundTask.h +++ b/BackgroundTask.h @@ -26,7 +26,7 @@ #include #include -class BackgroundTask : public AbstractCommand0, public TaskStatus { +class BackgroundTask : public AbstractCommand, public TaskStatus { public: enum Type { INTERACTIVE, BATCH }; diff --git a/BlackOnWhiteEstimator.cpp b/BlackOnWhiteEstimator.cpp deleted file mode 100644 index 19166cace..000000000 --- a/BlackOnWhiteEstimator.cpp +++ /dev/null @@ -1,103 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include "BlackOnWhiteEstimator.h" -#include "Despeckle.h" -#include "DebugImages.h" -#include "TaskStatus.h" - -using namespace imageproc; - -bool BlackOnWhiteEstimator::isBlackOnWhiteRefining(const imageproc::GrayImage& grayImage, - const ImageTransformation& xform, - const TaskStatus& status, - DebugImages* dbg) { - BinaryImage bw150; - { - ImageTransformation xform150dpi(xform); - xform150dpi.preScaleToDpi(Dpi(150, 150)); - - if (xform150dpi.resultingRect().toRect().isEmpty()) { - return true; - } - - QImage gray150(transformToGray(grayImage, xform150dpi.transform(), xform150dpi.resultingRect().toRect(), - OutsidePixels::assumeColor(Qt::white))); - bw150 = binarizeOtsu(gray150); - - Despeckle::despeckleInPlace(bw150, Dpi(150, 150), Despeckle::NORMAL, status); - bw150.invert(); - Despeckle::despeckleInPlace(bw150, Dpi(150, 150), Despeckle::NORMAL, status); - bw150.invert(); - if (dbg) { - dbg->add(bw150, "bw150"); - } - } - - status.throwIfCancelled(); - - BinaryImage contentMask; - { - BinaryImage whiteTopHat = whiteTopHatTransform(bw150, QSize(13, 13)); - BinaryImage blackTopHat = blackTopHatTransform(bw150, QSize(13, 13)); - - contentMask = whiteTopHat; - rasterOp>(contentMask, blackTopHat); - - contentMask = closeBrick(contentMask, QSize(200, 200)); - contentMask = dilateBrick(contentMask, QSize(30, 30)); - if (dbg) { - dbg->add(contentMask, "content_mask"); - } - } - - status.throwIfCancelled(); - - rasterOp>(bw150, contentMask); - - return (2 * bw150.countBlackPixels() <= contentMask.countBlackPixels()); -} - -bool BlackOnWhiteEstimator::isBlackOnWhite(const imageproc::GrayImage& grayImage, - const ImageTransformation& xform, - const TaskStatus& status, - DebugImages* dbg) { - if (isBlackOnWhite(grayImage, xform.resultingPreCropArea())) { - return true; - } else { - // The black borders of the page can make the method above giving the wrong result. - return isBlackOnWhiteRefining(grayImage, xform, status, dbg); - } -} - -bool BlackOnWhiteEstimator::isBlackOnWhite(const GrayImage& img, const BinaryImage& mask) { - if (img.isNull()) { - throw std::invalid_argument("BlackOnWhiteEstimator: image is null."); - } - if (img.size() != mask.size()) { - throw std::invalid_argument("BlackOnWhiteEstimator: img and mask have different sizes"); - } - - BinaryImage bwImage(img, BinaryThreshold::otsuThreshold(GrayscaleHistogram(img, mask))); - rasterOp>(bwImage, mask); - - return (2 * bwImage.countBlackPixels() <= mask.countBlackPixels()); -} - -bool BlackOnWhiteEstimator::isBlackOnWhite(const GrayImage& img, const QPolygonF& cropArea) { - if (img.isNull()) { - throw std::invalid_argument("BlackOnWhiteEstimator: image is null."); - } - if (cropArea.intersected(QRectF(img.rect())).isEmpty()) { - throw std::invalid_argument("BlackOnWhiteEstimator: the cropping area is wrong."); - } - - BinaryImage mask(img.size(), BLACK); - PolygonRasterizer::fillExcept(mask, WHITE, cropArea, Qt::WindingFill); - - return isBlackOnWhite(img, mask); -} diff --git a/BlackOnWhiteEstimator.h b/BlackOnWhiteEstimator.h deleted file mode 100644 index 0bff46b9b..000000000 --- a/BlackOnWhiteEstimator.h +++ /dev/null @@ -1,35 +0,0 @@ - -#ifndef SCANTAILOR_BLACKONWHITEESTIMATOR_H -#define SCANTAILOR_BLACKONWHITEESTIMATOR_H - -#include -#include -#include "ImageTransformation.h" - -class TaskStatus; -class DebugImages; - -namespace imageproc { -class GrayImage; -class BinaryImage; -} // namespace imageproc - -class BlackOnWhiteEstimator { -public: - static bool isBlackOnWhite(const imageproc::GrayImage& grayImage, - const ImageTransformation& xform, - const TaskStatus& status, - DebugImages* dbg = nullptr); - - static bool isBlackOnWhiteRefining(const imageproc::GrayImage& grayImage, - const ImageTransformation& xform, - const TaskStatus& status, - DebugImages* dbg = nullptr); - - static bool isBlackOnWhite(const imageproc::GrayImage& img, const imageproc::BinaryImage& mask); - - static bool isBlackOnWhite(const imageproc::GrayImage& img, const QPolygonF& cropArea); -}; - - -#endif // SCANTAILOR_BLACKONWHITEESTIMATOR_H diff --git a/BubbleAnimation.cpp b/BubbleAnimation.cpp index be0abfaac..2c3f7c510 100644 --- a/BubbleAnimation.cpp +++ b/BubbleAnimation.cpp @@ -64,8 +64,8 @@ bool BubbleAnimation::nextFrame(const QColor& head_color, for (int i = 0; i < m_numBubbles; ++i) { const double angle = -0.5 * PI + 2.0 * PI * (m_curFrame - i) / m_numBubbles; - const double s = sin(angle); - const double c = cos(angle); + const double s = std::sin(angle); + const double c = std::cos(angle); const QPointF vec(c * reduced_radius, s * reduced_radius); QRectF r(0.0, 0.0, 2.0 * bubble_radius, 2.0 * bubble_radius); r.moveCenter(center + vec); diff --git a/CMakeLists.txt b/CMakeLists.txt index cd3498727..e9a10faf2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -557,7 +557,6 @@ SET( DefaultParamsProvider.cpp DefaultParamsProvider.h DeviationProvider.h OrderByDeviationProvider.cpp OrderByDeviationProvider.h - BlackOnWhiteEstimator.cpp BlackOnWhiteEstimator.h ImageSettings.cpp ImageSettings.h version.h config.h.in diff --git a/ConsoleBatch.cpp b/ConsoleBatch.cpp index 24f2cf6b2..65876e741 100644 --- a/ConsoleBatch.cpp +++ b/ConsoleBatch.cpp @@ -139,8 +139,8 @@ BackgroundTaskPtr ConsoleBatch::createCompositeTask(const PageInfo& page, const } assert(fix_orientation_task); - return BackgroundTaskPtr( - new LoadFileTask(BackgroundTask::BATCH, page, m_ptrThumbnailCache, m_ptrPages, fix_orientation_task)); + return make_intrusive(BackgroundTask::BATCH, page, m_ptrThumbnailCache, m_ptrPages, + fix_orientation_task); } // ConsoleBatch::createCompositeTask // process the image vector **images** and save output to **output_dir** diff --git a/ContentSpanFinder.cpp b/ContentSpanFinder.cpp index c0036092e..c5b22e7b1 100644 --- a/ContentSpanFinder.cpp +++ b/ContentSpanFinder.cpp @@ -21,7 +21,8 @@ using namespace imageproc; -void ContentSpanFinder::findImpl(const SlicedHistogram& histogram, VirtualFunction1& handler) const { +void ContentSpanFinder::findImpl(const SlicedHistogram& histogram, + const VirtualFunction& handler) const { const auto hist_size = static_cast(histogram.size()); int i = 0; diff --git a/ContentSpanFinder.h b/ContentSpanFinder.h index 07942c0c5..b2f06268a 100644 --- a/ContentSpanFinder.h +++ b/ContentSpanFinder.h @@ -51,17 +51,16 @@ class ContentSpanFinder { void find(const imageproc::SlicedHistogram& histogram, T handler) const; private: - void findImpl(const imageproc::SlicedHistogram& histogram, VirtualFunction1& handler) const; + void findImpl(const imageproc::SlicedHistogram& histogram, const VirtualFunction& handler) const; int m_minContentWidth; int m_minWhitespaceWidth; }; -template -void ContentSpanFinder::find(const imageproc::SlicedHistogram& histogram, T handler) const { - ProxyFunction1 proxy(handler); - findImpl(histogram, proxy); +template +void ContentSpanFinder::find(const imageproc::SlicedHistogram& histogram, Callable handler) const { + findImpl(histogram, ProxyFunction(handler)); } #endif // ifndef CONTENTSPANFINDER_H_ diff --git a/DebugImageView.cpp b/DebugImageView.cpp index 67f202a64..9b30da914 100644 --- a/DebugImageView.cpp +++ b/DebugImageView.cpp @@ -25,7 +25,7 @@ #include #include -class DebugImageView::ImageLoadResult : public AbstractCommand0 { +class DebugImageView::ImageLoadResult : public AbstractCommand { public: ImageLoadResult(QPointer owner, const QImage& image) : m_ptrOwner(std::move(owner)), m_image(image) { @@ -44,7 +44,7 @@ class DebugImageView::ImageLoadResult : public AbstractCommand0 { }; -class DebugImageView::ImageLoader : public AbstractCommand0 { +class DebugImageView::ImageLoader : public AbstractCommand { public: ImageLoader(DebugImageView* owner, const QString& file_path) : m_ptrOwner(owner), m_filePath(file_path) { } @@ -52,7 +52,7 @@ class DebugImageView::ImageLoader : public AbstractCommand0(m_ptrOwner, image); } private: @@ -74,8 +74,7 @@ DebugImageView::DebugImageView(AutoRemovingFile file, void DebugImageView::setLive(const bool live) { if (live && !m_isLive) { - ImageViewBase::backgroundExecutor().enqueueTask( - BackgroundExecutor::TaskPtr(new ImageLoader(this, m_file.get()))); + ImageViewBase::backgroundExecutor().enqueueTask(make_intrusive(this, m_file.get())); } else if (!live && m_isLive) { if (QWidget* wgt = currentWidget()) { if (wgt != m_pPlaceholderWidget) { diff --git a/DefaultParams.cpp b/DefaultParams.cpp index 04a389a13..ad6bec441 100644 --- a/DefaultParams.cpp +++ b/DefaultParams.cpp @@ -2,6 +2,7 @@ #include "DefaultParams.h" #include "XmlUnmarshaller.h" #include "XmlMarshaller.h" +#include "Utils.h" using namespace page_split; using namespace output; @@ -156,7 +157,7 @@ DefaultParams::DeskewParams::DeskewParams(const QDomElement& el) QDomElement DefaultParams::DeskewParams::toXml(QDomDocument& doc, const QString& name) const { QDomElement el(doc.createElement(name)); - el.setAttribute("deskewAngleDeg", deskewAngleDeg); + el.setAttribute("deskewAngleDeg", Utils::doubleToString(deskewAngleDeg)); el.setAttribute("mode", (mode == MODE_AUTO) ? "auto" : "manual"); return el; @@ -405,7 +406,7 @@ QDomElement DefaultParams::OutputParams::toXml(QDomDocument& doc, const QString& el.appendChild(colorParams.toXml(doc, "colorParams")); el.appendChild(splittingOptions.toXml(doc, "splittingOptions")); el.appendChild(pictureShapeOptions.toXml(doc, "pictureShapeOptions")); - el.setAttribute("depthPerception", depthPerception.value()); + el.setAttribute("depthPerception", Utils::doubleToString(depthPerception.value())); el.appendChild(dewarpingOptions.toXml(doc, "dewarpingOptions")); el.setAttribute("despeckleLevel", despeckleLevelToString(despeckleLevel)); diff --git a/Despeckle.cpp b/Despeckle.cpp index 7b86012cd..e5506a6b6 100644 --- a/Despeckle.cpp +++ b/Despeckle.cpp @@ -48,9 +48,9 @@ namespace { * We want horizontal proximity to have greater weight, so we * multiply the vertical component distances by VERTICAL_SCALE, * so that the distance is not:\n - * sqrt(dx^2 + dy^2)\n + * std::sqrt(dx^2 + dy^2)\n * but:\n - * sqrt(dx^2 + (VERTICAL_SCALE*dy)^2)\n + * std::sqrt(dx^2 + (VERTICAL_SCALE*dy)^2)\n * Keep in mind that we actually operate on squared distances, * so we don't need to take that square root. */ diff --git a/DeviationProvider.h b/DeviationProvider.h index 17835a685..c2fe18557 100644 --- a/DeviationProvider.h +++ b/DeviationProvider.h @@ -129,7 +129,7 @@ void DeviationProvider::update() const { template void DeviationProvider::setComputeValueByKey(const std::function& computeValueByKey) { - DeviationProvider::computeValueByKey = computeValueByKey; + this->computeValueByKey = std::move(computeValueByKey); } template diff --git a/EstimateBackground.cpp b/EstimateBackground.cpp index 68debf1d5..47d3b8d26 100644 --- a/EstimateBackground.cpp +++ b/EstimateBackground.cpp @@ -42,7 +42,7 @@ using namespace imageproc; struct AbsoluteDifference { static uint8_t transform(uint8_t src, uint8_t dst) { - return static_cast(abs(int(src) - int(dst))); + return static_cast(std::abs(int(src) - int(dst))); } }; diff --git a/FilterData.cpp b/FilterData.cpp index cad9c1ab1..0755525a7 100644 --- a/FilterData.cpp +++ b/FilterData.cpp @@ -51,10 +51,6 @@ const imageproc::GrayImage& FilterData::grayImage() const { return m_grayImage; } -bool FilterData::isBlackOnWhite() const { - return m_imageParams.isBlackOnWhite(); -} - void FilterData::updateImageParams(const ImageSettings::PageParams& imageParams) { m_imageParams = imageParams; } diff --git a/FilterData.h b/FilterData.h index 11b328aaf..4fb85f865 100644 --- a/FilterData.h +++ b/FilterData.h @@ -42,8 +42,6 @@ class FilterData { const imageproc::GrayImage& grayImage() const; - bool isBlackOnWhite() const; - void updateImageParams(const ImageSettings::PageParams& imageParams); private: diff --git a/FilterUiInterface.h b/FilterUiInterface.h index a6b270bef..80432667c 100644 --- a/FilterUiInterface.h +++ b/FilterUiInterface.h @@ -51,7 +51,7 @@ class FilterUiInterface { /** * Returns a callable object that when called will open a relinking dialog. */ - virtual intrusive_ptr> relinkingDialogRequester() = 0; + virtual intrusive_ptr> relinkingDialogRequester() = 0; }; diff --git a/ImageMetadataLoader.cpp b/ImageMetadataLoader.cpp index c9a9a20e3..e99937076 100644 --- a/ImageMetadataLoader.cpp +++ b/ImageMetadataLoader.cpp @@ -29,7 +29,7 @@ void ImageMetadataLoader::registerLoader(intrusive_ptr load } ImageMetadataLoader::Status ImageMetadataLoader::loadImpl(QIODevice& io_device, - VirtualFunction1& out) { + const VirtualFunction& out) { auto it(m_sLoaders.begin()); const auto end(m_sLoaders.end()); for (; it != end; ++it) { @@ -43,7 +43,7 @@ ImageMetadataLoader::Status ImageMetadataLoader::loadImpl(QIODevice& io_device, } ImageMetadataLoader::Status ImageMetadataLoader::loadImpl(const QString& file_path, - VirtualFunction1& out) { + const VirtualFunction& out) { QFile file(file_path); if (!file.open(QIODevice::ReadOnly)) { return GENERIC_ERROR; diff --git a/ImageMetadataLoader.h b/ImageMetadataLoader.h index 7e1a21255..e6edb087b 100644 --- a/ImageMetadataLoader.h +++ b/ImageMetadataLoader.h @@ -67,30 +67,26 @@ class ImageMetadataLoader : public ref_countable { * the image metadata. If there are multiple images (pages) in * the file, this object will be called multiple times. */ - virtual Status loadMetadata(QIODevice& io_device, VirtualFunction1& out) = 0; + virtual Status loadMetadata(QIODevice& io_device, const VirtualFunction& out) = 0; private: - static Status loadImpl(QIODevice& io_device, VirtualFunction1& out); + static Status loadImpl(QIODevice& io_device, const VirtualFunction& out); - static Status loadImpl(const QString& file_path, VirtualFunction1& out); + static Status loadImpl(const QString& file_path, const VirtualFunction& out); typedef std::vector> LoaderList; static LoaderList m_sLoaders; }; -template -ImageMetadataLoader::Status ImageMetadataLoader::load(QIODevice& io_device, OutFunc out) { - ProxyFunction1 proxy(out); - - return loadImpl(io_device, proxy); +template +ImageMetadataLoader::Status ImageMetadataLoader::load(QIODevice& io_device, Callable out) { + return loadImpl(io_device, ProxyFunction(out)); } -template -ImageMetadataLoader::Status ImageMetadataLoader::load(const QString& file_path, OutFunc out) { - ProxyFunction1 proxy(out); - - return loadImpl(file_path, proxy); +template +ImageMetadataLoader::Status ImageMetadataLoader::load(const QString& file_path, Callable out) { + return loadImpl(file_path, ProxyFunction(out)); } #endif // ifndef IMAGEMETADATALOADER_H_ diff --git a/ImageSettings.cpp b/ImageSettings.cpp index db92ae7d4..df8451819 100644 --- a/ImageSettings.cpp +++ b/ImageSettings.cpp @@ -41,21 +41,18 @@ std::unique_ptr ImageSettings::getPageParams(const Pa /*=============================== ImageSettings::Params ==================================*/ -ImageSettings::PageParams::PageParams() : bwThreshold(0), blackOnWhite(true) { +ImageSettings::PageParams::PageParams() : bwThreshold(0) { } -ImageSettings::PageParams::PageParams(const BinaryThreshold& bwThreshold, bool blackOnWhite) - : bwThreshold(bwThreshold), blackOnWhite(blackOnWhite) { +ImageSettings::PageParams::PageParams(const BinaryThreshold& bwThreshold) : bwThreshold(bwThreshold) { } -ImageSettings::PageParams::PageParams(const QDomElement& el) - : bwThreshold(el.attribute("bwThreshold").toInt()), blackOnWhite(el.attribute("blackOnWhite") == "1") { +ImageSettings::PageParams::PageParams(const QDomElement& el) : bwThreshold(el.attribute("bwThreshold").toInt()) { } QDomElement ImageSettings::PageParams::toXml(QDomDocument& doc, const QString& name) const { QDomElement el(doc.createElement(name)); el.setAttribute("bwThreshold", bwThreshold); - el.setAttribute("blackOnWhite", blackOnWhite ? "1" : "0"); return el; } @@ -66,12 +63,4 @@ const BinaryThreshold& ImageSettings::PageParams::getBwThreshold() const { void ImageSettings::PageParams::setBwThreshold(const BinaryThreshold& bwThreshold) { PageParams::bwThreshold = bwThreshold; -} - -bool ImageSettings::PageParams::isBlackOnWhite() const { - return blackOnWhite; -} - -void ImageSettings::PageParams::setBlackOnWhite(bool blackOnWhite) { - PageParams::blackOnWhite = blackOnWhite; -} +} \ No newline at end of file diff --git a/ImageSettings.h b/ImageSettings.h index a27cb8473..d9ac44ad2 100644 --- a/ImageSettings.h +++ b/ImageSettings.h @@ -19,7 +19,7 @@ class ImageSettings : public ref_countable { public: PageParams(); - PageParams(const imageproc::BinaryThreshold& bwThreshold, bool blackOnWhite); + explicit PageParams(const imageproc::BinaryThreshold& bwThreshold); explicit PageParams(const QDomElement& el); @@ -29,13 +29,8 @@ class ImageSettings : public ref_countable { void setBwThreshold(const imageproc::BinaryThreshold& bwThreshold); - bool isBlackOnWhite() const; - - void setBlackOnWhite(bool blackOnWhite); - private: imageproc::BinaryThreshold bwThreshold; - bool blackOnWhite; }; ImageSettings() = default; diff --git a/ImageViewBase.cpp b/ImageViewBase.cpp index f17661cba..ca720cd2f 100644 --- a/ImageViewBase.cpp +++ b/ImageViewBase.cpp @@ -40,7 +40,7 @@ using namespace imageproc; -class ImageViewBase::HqTransformTask : public AbstractCommand0>>, public QObject { +class ImageViewBase::HqTransformTask : public AbstractCommand>>, public QObject { DECLARE_NON_COPYABLE(HqTransformTask) public: @@ -54,10 +54,10 @@ class ImageViewBase::HqTransformTask : public AbstractCommand0isCancelled(); } - intrusive_ptr> operator()() override; + intrusive_ptr> operator()() override; private: - class Result : public AbstractCommand0 { + class Result : public AbstractCommand { public: explicit Result(ImageViewBase* image_view); @@ -321,7 +321,7 @@ void ImageViewBase::moveTowardsIdealPosition(const double pixel_length) { } QPointF vec(ideal_widget_fp - m_widgetFocalPoint); - const double max_length = sqrt(vec.x() * vec.x() + vec.y() * vec.y()); + const double max_length = std::sqrt(vec.x() * vec.x() + vec.y() * vec.y()); if (pixel_length >= max_length) { m_widgetFocalPoint = ideal_widget_fp; } else { @@ -626,8 +626,8 @@ void ImageViewBase::updateScrollBars() { ymin = std::min(viewport_center.y(), viewport.bottom() - 0.5 * picture.height()); } - const auto xrange = (int) ceil(xmax - xmin); - const auto yrange = (int) ceil(ymax - ymin); + const auto xrange = (int) std::ceil(xmax - xmin); + const auto yrange = (int) std::ceil(ymax - ymin); const int xfirst = 0; const int xlast = xrange - 1; const int yfirst = 0; @@ -788,12 +788,12 @@ QPointF ImageViewBase::getIdealWidgetFocalPoint(const FocalPointMode mode) const } else if ((left_margin < 0.0) && (right_margin > 0.0)) { // Move image to the right so that either left_margin or // right_margin becomes zero, whichever requires less movement. - const double movement = std::min(fabs(left_margin), fabs(right_margin)); + const double movement = std::min(std::fabs(left_margin), std::fabs(right_margin)); widget_focal_point.rx() += movement; } else if ((right_margin < 0.0) && (left_margin > 0.0)) { // Move image to the left so that either left_margin or // right_margin becomes zero, whichever requires less movement. - const double movement = std::min(fabs(left_margin), fabs(right_margin)); + const double movement = std::min(std::fabs(left_margin), std::fabs(right_margin)); widget_focal_point.rx() -= movement; } @@ -805,12 +805,12 @@ QPointF ImageViewBase::getIdealWidgetFocalPoint(const FocalPointMode mode) const } else if ((top_margin < 0.0) && (bottom_margin > 0.0)) { // Move image down so that either top_margin or bottom_margin // becomes zero, whichever requires less movement. - const double movement = std::min(fabs(top_margin), fabs(bottom_margin)); + const double movement = std::min(std::fabs(top_margin), std::fabs(bottom_margin)); widget_focal_point.ry() += movement; } else if ((bottom_margin < 0.0) && (top_margin > 0.0)) { // Move image up so that either top_margin or bottom_margin // becomes zero, whichever requires less movement. - const double movement = std::min(fabs(top_margin), fabs(bottom_margin)); + const double movement = std::min(std::fabs(top_margin), std::fabs(bottom_margin)); widget_focal_point.ry() -= movement; } @@ -859,7 +859,7 @@ void ImageViewBase::adjustAndSetNewWidgetFP(const QPointF proposed_widget_fp, co if (towards_ideal.x() * towards_proposed.x() < 0.0) { // Wrong direction - no movement at all. movement.setX(0.0); - } else if (fabs(towards_proposed.x()) > fabs(towards_ideal.x())) { + } else if (std::fabs(towards_proposed.x()) > std::fabs(towards_ideal.x())) { // Too much movement - limit it. movement.setX(towards_ideal.x()); } @@ -867,7 +867,7 @@ void ImageViewBase::adjustAndSetNewWidgetFP(const QPointF proposed_widget_fp, co if (towards_ideal.y() * towards_proposed.y() < 0.0) { // Wrong direction - no movement at all. movement.setY(0.0); - } else if (fabs(towards_proposed.y()) > fabs(towards_ideal.y())) { + } else if (std::fabs(towards_proposed.y()) > std::fabs(towards_ideal.y())) { // Too much movement - limit it. movement.setY(towards_ideal.y()); } @@ -1019,7 +1019,7 @@ ImageViewBase::HqTransformTask::HqTransformTask(ImageViewBase* image_view, : m_ptrResult(new Result(image_view)), m_image(image), m_xform(xform), m_targetSize(target_size) { } -intrusive_ptr> ImageViewBase::HqTransformTask::operator()() { +intrusive_ptr> ImageViewBase::HqTransformTask::operator()() { if (isCancelled()) { return nullptr; } diff --git a/JpegMetadataLoader.cpp b/JpegMetadataLoader.cpp index 3b6d4c1f8..bd2301723 100644 --- a/JpegMetadataLoader.cpp +++ b/JpegMetadataLoader.cpp @@ -195,7 +195,7 @@ void JpegMetadataLoader::registerMyself() { } ImageMetadataLoader::Status JpegMetadataLoader::loadMetadata(QIODevice& io_device, - VirtualFunction1& out) { + const VirtualFunction& out) { if (!io_device.isReadable()) { return GENERIC_ERROR; } diff --git a/JpegMetadataLoader.h b/JpegMetadataLoader.h index 548321e44..569690dba 100644 --- a/JpegMetadataLoader.h +++ b/JpegMetadataLoader.h @@ -37,7 +37,7 @@ class JpegMetadataLoader : public ImageMetadataLoader { static void registerMyself(); protected: - Status loadMetadata(QIODevice& io_device, VirtualFunction1& out) override; + Status loadMetadata(QIODevice& io_device, const VirtualFunction& out) override; }; diff --git a/LoadFileTask.cpp b/LoadFileTask.cpp index 380d22b8d..cd43f7e80 100644 --- a/LoadFileTask.cpp +++ b/LoadFileTask.cpp @@ -73,7 +73,7 @@ FilterResultPtr LoadFileTask::operator()() { throwIfCancelled(); if (image.isNull()) { - return FilterResultPtr(new ErrorResult(m_imageId.filePath())); + return make_intrusive(m_imageId.filePath()); } else { updateImageSizeIfChanged(image); overrideDpi(image); @@ -118,7 +118,7 @@ LoadFileTask::ErrorResult::ErrorResult(const QString& file_path) void LoadFileTask::ErrorResult::updateUI(FilterUiInterface* ui) { class ErrWidget : public ErrorWidget { public: - ErrWidget(intrusive_ptr> relinking_dialog_requester, + ErrWidget(intrusive_ptr> relinking_dialog_requester, const QString& text, Qt::TextFormat fmt = Qt::AutoText) : ErrorWidget(text, fmt), m_ptrRelinkingDialogRequester(std::move(relinking_dialog_requester)) { @@ -129,7 +129,7 @@ void LoadFileTask::ErrorResult::updateUI(FilterUiInterface* ui) { (*m_ptrRelinkingDialogRequester)(); } - intrusive_ptr> m_ptrRelinkingDialogRequester; + intrusive_ptr> m_ptrRelinkingDialogRequester; }; diff --git a/MainWindow.cpp b/MainWindow.cpp index 70d290447..916a1b107 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -448,7 +448,7 @@ void MainWindow::setupThumbView() { inner_width -= thumbView->frameWidth() * 2; } const int delta_x = thumbView->size().width() - inner_width; - thumbView->setMinimumWidth((int) ceil(m_maxLogicalThumbSize.width() + delta_x)); + thumbView->setMinimumWidth((int) std::ceil(m_maxLogicalThumbSize.width() + delta_x)); m_ptrThumbSequence->attachView(thumbView); @@ -710,8 +710,8 @@ void MainWindow::invalidateAllThumbnails() { m_ptrThumbSequence->invalidateAllThumbnails(); } -intrusive_ptr> MainWindow::relinkingDialogRequester() { - class Requester : public AbstractCommand0 { +intrusive_ptr> MainWindow::relinkingDialogRequester() { + class Requester : public AbstractCommand { public: Requester(MainWindow* wnd) : m_ptrWnd(wnd) { } @@ -1923,8 +1923,8 @@ BackgroundTaskPtr MainWindow::createCompositeTask(const PageInfo& page, } assert(fix_orientation_task); - return BackgroundTaskPtr(new LoadFileTask(batch ? BackgroundTask::BATCH : BackgroundTask::INTERACTIVE, page, - m_ptrThumbnailCache, m_ptrPages, fix_orientation_task)); + return make_intrusive(batch ? BackgroundTask::BATCH : BackgroundTask::INTERACTIVE, page, + m_ptrThumbnailCache, m_ptrPages, fix_orientation_task); } // MainWindow::createCompositeTask intrusive_ptr MainWindow::createCompositeCacheDrivenTask(const int last_filter_idx) { diff --git a/MainWindow.h b/MainWindow.h index 08a10887a..39756e831 100644 --- a/MainWindow.h +++ b/MainWindow.h @@ -208,7 +208,7 @@ private slots: DebugImages* debug_images = nullptr, bool clear_image_widget = true) override; - intrusive_ptr> relinkingDialogRequester() override; + intrusive_ptr> relinkingDialogRequester() override; void switchToNewProject(const intrusive_ptr& pages, const QString& out_dir, diff --git a/PngMetadataLoader.cpp b/PngMetadataLoader.cpp index 6f4ddeaf5..dc8bf61d9 100644 --- a/PngMetadataLoader.cpp +++ b/PngMetadataLoader.cpp @@ -84,7 +84,7 @@ void PngMetadataLoader::registerMyself() { } ImageMetadataLoader::Status PngMetadataLoader::loadMetadata(QIODevice& io_device, - VirtualFunction1& out) { + const VirtualFunction& out) { if (!io_device.isReadable()) { return GENERIC_ERROR; } diff --git a/PngMetadataLoader.h b/PngMetadataLoader.h index a31ef15c0..1413c92f2 100644 --- a/PngMetadataLoader.h +++ b/PngMetadataLoader.h @@ -37,7 +37,7 @@ class PngMetadataLoader : public ImageMetadataLoader { static void registerMyself(); protected: - Status loadMetadata(QIODevice& io_device, VirtualFunction1& out) override; + Status loadMetadata(QIODevice& io_device, const VirtualFunction& out) override; }; diff --git a/ProjectPages.cpp b/ProjectPages.cpp index 4dcdb4ed9..fca0182f6 100644 --- a/ProjectPages.cpp +++ b/ProjectPages.cpp @@ -128,7 +128,7 @@ PageSequence ProjectPages::toPageSequence(const PageView view) const { return pages; } // ProjectPages::toPageSequence -void ProjectPages::listRelinkablePaths(VirtualFunction1& sink) const { +void ProjectPages::listRelinkablePaths(const VirtualFunction& sink) const { // It's generally a bad idea to do callbacks while holding an internal mutex, // so we accumulate results into this vector first. std::vector files; diff --git a/ProjectPages.h b/ProjectPages.h index 4a5bab92c..ca4c04c80 100644 --- a/ProjectPages.h +++ b/ProjectPages.h @@ -65,7 +65,7 @@ class ProjectPages : public QObject, public ref_countable { PageSequence toPageSequence(PageView view) const; - void listRelinkablePaths(VirtualFunction1& sink) const; + void listRelinkablePaths(const VirtualFunction& sink) const; /** * \note It's up to the caller to make sure different paths aren't collapsed into one. diff --git a/ProjectWriter.cpp b/ProjectWriter.cpp index 553ec73f5..9b0fe2268 100644 --- a/ProjectWriter.cpp +++ b/ProjectWriter.cpp @@ -242,13 +242,13 @@ int ProjectWriter::pageId(const PageId& page_id) const { return it->numericId; } -void ProjectWriter::enumImagesImpl(VirtualFunction2& out) const { +void ProjectWriter::enumImagesImpl(const VirtualFunction& out) const { for (const Image& image : m_images.get()) { out(image.id, image.numericId); } } -void ProjectWriter::enumPagesImpl(VirtualFunction2& out) const { +void ProjectWriter::enumPagesImpl(const VirtualFunction& out) const { for (const Page& page : m_pages.get()) { out(page.id, page.numericId); } diff --git a/ProjectWriter.h b/ProjectWriter.h index 538c454d1..02ca5f1fb 100644 --- a/ProjectWriter.h +++ b/ProjectWriter.h @@ -154,9 +154,9 @@ class ProjectWriter { int pageId(const PageId& page_id) const; - void enumImagesImpl(VirtualFunction2& out) const; + void enumImagesImpl(const VirtualFunction& out) const; - void enumPagesImpl(VirtualFunction2& out) const; + void enumPagesImpl(const VirtualFunction& out) const; PageSequence m_pageSequence; OutputFileNameGenerator m_outFileNameGen; @@ -170,16 +170,14 @@ class ProjectWriter { }; -template -void ProjectWriter::enumImages(OutFunc out) const { - ProxyFunction2 proxy(out); - enumImagesImpl(proxy); +template +void ProjectWriter::enumImages(Callable out) const { + enumImagesImpl(ProxyFunction(out)); } -template -void ProjectWriter::enumPages(OutFunc out) const { - ProxyFunction2 proxy(out); - enumPagesImpl(proxy); +template +void ProjectWriter::enumPages(Callable out) const { + enumPagesImpl(ProxyFunction(out)); } #endif // ifndef PROJECTWRITER_H_ diff --git a/README.md b/README.md index 5d957d5c7..0804839a1 100644 --- a/README.md +++ b/README.md @@ -179,9 +179,6 @@ Features * Added option to control highlighting (with red asterisks) the thumbnails of pages with high deviation. The option refreshes the thumbnails instantly. - * Support for processing of images with light content on dark background. - Now that kind of images can correctly be handled on all the stages. Many book covers are examples of such images. - * Deviation feature reworked. 1. A deviation provider implemented. It supports caching and recalculates the values on demand. There isn't more any necessity to store deviation in page parameters and so in the project file, that approach caused some problems as the deviation is not actually a page parameter and depends on all the pages in the project. diff --git a/RelinkingDialog.h b/RelinkingDialog.h index c759cfb4b..023f351c6 100644 --- a/RelinkingDialog.h +++ b/RelinkingDialog.h @@ -36,8 +36,8 @@ class RelinkingDialog : public QDialog { public: explicit RelinkingDialog(const QString& project_file_path, QWidget* parent = nullptr); - VirtualFunction1& pathCollector() { - return m_model; + ProxyFunction pathCollector() { + return ProxyFunction(m_model); } /** diff --git a/RelinkingModel.h b/RelinkingModel.h index 7b82c65ae..d9f0c1f14 100644 --- a/RelinkingModel.h +++ b/RelinkingModel.h @@ -36,7 +36,7 @@ #include #include -class RelinkingModel : public QAbstractListModel, public VirtualFunction1 { +class RelinkingModel : public QAbstractListModel { DECLARE_NON_COPYABLE(RelinkingModel) public: @@ -65,7 +65,7 @@ class RelinkingModel : public QAbstractListModel, public VirtualFunction1setChecked(settings.value("settings/auto_save_project").toBool()); ui.highlightDeviationCB->setChecked(settings.value("settings/highlight_deviation", true).toBool()); - connect(ui.colorSchemeBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onColorSchemeChanged(int))); + connect(ui.colorSchemeBox, static_cast(&QComboBox::currentIndexChanged), [this](int) { + QMessageBox::information(this, tr("Information"), + tr("ScanTailor need to be restarted to apply the color scheme changes.")); + }); } SettingsDialog::~SettingsDialog() = default; @@ -116,9 +119,4 @@ void SettingsDialog::commitChanges() { settings.setValue("settings/marginsDeviationThreshold", ui.marginsDeviationThresholdSB->value()); emit settingsChanged(); -} - -void SettingsDialog::onColorSchemeChanged(int idx) { - QMessageBox::information(this, tr("Information"), - tr("ScanTailor need to be restarted to apply the color scheme changes.")); -} +} \ No newline at end of file diff --git a/SettingsDialog.h b/SettingsDialog.h index c26d4f859..730a8e136 100644 --- a/SettingsDialog.h +++ b/SettingsDialog.h @@ -38,8 +38,6 @@ private slots: void commitChanges(); - void onColorSchemeChanged(int idx); - private: Ui::SettingsDialog ui; }; diff --git a/StatusBarPanel.cpp b/StatusBarPanel.cpp index f7d0aaf09..def6b152d 100644 --- a/StatusBarPanel.cpp +++ b/StatusBarPanel.cpp @@ -77,12 +77,12 @@ void StatusBarPanel::mousePosChanged() { switch (UnitsProvider::getInstance()->getUnits()) { case PIXELS: case MILLIMETRES: - x = ceil(x); - y = ceil(y); + x = std::ceil(x); + y = std::ceil(y); break; default: - x = ceil(x * 10) / 10; - y = ceil(y * 10) / 10; + x = std::ceil(x * 10) / 10; + y = std::ceil(y * 10) / 10; break; } @@ -103,20 +103,20 @@ void StatusBarPanel::physSizeChanged() { const Units units = UnitsProvider::getInstance()->getUnits(); switch (units) { case PIXELS: - width = round(width); - height = round(height); + width = std::round(width); + height = std::round(height); break; case MILLIMETRES: - width = round(width); - height = round(height); + width = std::round(width); + height = std::round(height); break; case CENTIMETRES: - width = round(width * 10) / 10; - height = round(height * 10) / 10; + width = std::round(width * 10) / 10; + height = std::round(height * 10) / 10; break; case INCHES: - width = round(width * 10) / 10; - height = round(height * 10) / 10; + width = std::round(width * 10) / 10; + height = std::round(height * 10) / 10; break; } diff --git a/ThumbnailBase.cpp b/ThumbnailBase.cpp index d74e5d173..ad5e81159 100644 --- a/ThumbnailBase.cpp +++ b/ThumbnailBase.cpp @@ -29,7 +29,7 @@ using namespace imageproc; -class ThumbnailBase::LoadCompletionHandler : public AbstractCommand1 { +class ThumbnailBase::LoadCompletionHandler : public AbstractCommand { DECLARE_NON_COPYABLE(LoadCompletionHandler) public: diff --git a/ThumbnailPixmapCache.h b/ThumbnailPixmapCache.h index c9d702ade..5cb3a56d5 100644 --- a/ThumbnailPixmapCache.h +++ b/ThumbnailPixmapCache.h @@ -38,7 +38,7 @@ class ThumbnailPixmapCache : public ref_countable { public: enum Status { LOADED, LOAD_FAILED, QUEUED }; - typedef AbstractCommand1 CompletionHandler; + typedef AbstractCommand CompletionHandler; /** * \brief Constructor. To be called from the GUI thread only. diff --git a/TiffMetadataLoader.cpp b/TiffMetadataLoader.cpp index ecef5c7fe..dbe5e323f 100644 --- a/TiffMetadataLoader.cpp +++ b/TiffMetadataLoader.cpp @@ -28,6 +28,6 @@ void TiffMetadataLoader::registerMyself() { } ImageMetadataLoader::Status TiffMetadataLoader::loadMetadata(QIODevice& io_device, - VirtualFunction1& out) { + const VirtualFunction& out) { return TiffReader::readMetadata(io_device, out); } diff --git a/TiffMetadataLoader.h b/TiffMetadataLoader.h index 7ff80c6e0..aa20a614c 100644 --- a/TiffMetadataLoader.h +++ b/TiffMetadataLoader.h @@ -37,7 +37,7 @@ class TiffMetadataLoader : public ImageMetadataLoader { static void registerMyself(); protected: - Status loadMetadata(QIODevice& io_device, VirtualFunction1& out) override; + Status loadMetadata(QIODevice& io_device, const VirtualFunction& out) override; }; diff --git a/TiffReader.cpp b/TiffReader.cpp index a2ba5b99c..fc2fab96e 100644 --- a/TiffReader.cpp +++ b/TiffReader.cpp @@ -237,7 +237,7 @@ bool TiffReader::canRead(QIODevice& device) { } ImageMetadataLoader::Status TiffReader::readMetadata(QIODevice& device, - VirtualFunction1& out) { + const VirtualFunction& out) { if (!device.isReadable()) { return ImageMetadataLoader::GENERIC_ERROR; } diff --git a/TiffReader.h b/TiffReader.h index 4de0dd6e8..424d5d785 100644 --- a/TiffReader.h +++ b/TiffReader.h @@ -32,7 +32,7 @@ class TiffReader { static bool canRead(QIODevice& device); static ImageMetadataLoader::Status readMetadata(QIODevice& device, - VirtualFunction1& out); + const VirtualFunction& out); /** * \brief Reads the image from io device to QImage. diff --git a/TiffWriter.cpp b/TiffWriter.cpp index e96e573b8..1408d1ec7 100644 --- a/TiffWriter.cpp +++ b/TiffWriter.cpp @@ -199,9 +199,9 @@ void TiffWriter::setDpm(const TiffHandle& tif, const Dpm& dpm) { // write it as DPI rather than dots per cm. const double xdpi = dpm.horizontal() * DPM2DPI; const double ydpi = dpm.vertical() * DPM2DPI; - const double rounded_xdpi = floor(xdpi + 0.5); - const double rounded_ydpi = floor(ydpi + 0.5); - if ((fabs(xdpi - rounded_xdpi) < 0.02) && (fabs(ydpi - rounded_ydpi) < 0.02)) { + const double rounded_xdpi = std::floor(xdpi + 0.5); + const double rounded_ydpi = std::floor(ydpi + 0.5); + if ((std::fabs(xdpi - rounded_xdpi) < 0.02) && (std::fabs(ydpi - rounded_ydpi) < 0.02)) { xres = (float) rounded_xdpi; yres = (float) rounded_ydpi; unit = RESUNIT_INCH; diff --git a/dewarping/CylindricalSurfaceDewarper.cpp b/dewarping/CylindricalSurfaceDewarper.cpp index 07e01d13c..2b4eb903b 100644 --- a/dewarping/CylindricalSurfaceDewarper.cpp +++ b/dewarping/CylindricalSurfaceDewarper.cpp @@ -107,7 +107,7 @@ CylindricalSurfaceDewarper::Generatrix CylindricalSurfaceDewarper::mapGeneratrix boost::array, 3> pairs; pairs[0] = std::make_pair(0.0, img_directrix1_proj); pairs[1] = std::make_pair(1.0, img_directrix2_proj); - if ((fabs(m_plnStraightLineY) < 0.05) || (fabs(m_plnStraightLineY - 1.0) < 0.05)) { + if ((std::fabs(m_plnStraightLineY) < 0.05) || (std::fabs(m_plnStraightLineY - 1.0) < 0.05)) { pairs[2] = std::make_pair(0.5, 0.5 * (img_directrix1_proj + img_directrix2_proj)); } else { pairs[2] = std::make_pair(m_plnStraightLineY, img_straight_line_proj); @@ -139,7 +139,7 @@ QPointF CylindricalSurfaceDewarper::mapToDewarpedSpace(const QPointF& img_pt) co boost::array, 3> pairs; pairs[0] = std::make_pair(img_directrix1_proj, 0.0); pairs[1] = std::make_pair(img_directrix2_proj, 1.0); - if ((fabs(m_plnStraightLineY) < 0.05) || (fabs(m_plnStraightLineY - 1.0) < 0.05)) { + if ((std::fabs(m_plnStraightLineY) < 0.05) || (std::fabs(m_plnStraightLineY - 1.0) < 0.05)) { pairs[2] = std::make_pair(0.5 * (img_directrix1_proj + img_directrix2_proj), 0.5); } else { pairs[2] = std::make_pair(img_straight_line_proj, m_plnStraightLineY); @@ -193,7 +193,7 @@ double CylindricalSurfaceDewarper::calcPlnStraightLineY(const std::vector(abs(line.p1().x() - vert_line_x), abs(line.p2().x() - vert_line_x)); + return (bool) std::min(std::abs(line.p1().x() - vert_line_x), std::abs(line.p2().x() - vert_line_x)); } Segment(const QLine& line, const Vec2d& vec, int dist) : line(line), unitVec(vec), vertDist(dist) { @@ -137,7 +137,7 @@ class SequentialColumnProcessor { RansacAlgo::RansacAlgo(const std::vector& segments) - : m_rSegments(segments), m_cosThreshold(cos(4.0 * constants::DEG2RAD)) { + : m_rSegments(segments), m_cosThreshold(std::cos(4.0 * constants::DEG2RAD)) { } void RansacAlgo::buildAndAssessModel(const Segment& seed_segment) { @@ -259,12 +259,12 @@ QLineF SequentialColumnProcessor::approximateWithLine(std::vector* dbg_ assert(pt2.y() > pt1.y()); Vec2d vec(pt2 - pt1); - if (fabs(vec[0]) > fabs(vec[1])) { + if (std::fabs(vec[0]) > std::fabs(vec[1])) { // We don't want segments that are more horizontal than vertical. continue; } - vec /= sqrt(vec.squaredNorm()); + vec /= std::sqrt(vec.squaredNorm()); segments.emplace_back(QLine(pt1, pt2), vec, pt2.y() - pt1.y()); } @@ -312,7 +312,7 @@ QLineF SequentialColumnProcessor::interpolateSegments(const std::vector double accum_weight = 0; for (const Segment& seg : segments) { - const double weight = sqrt(double(seg.vertDist)); + const double weight = std::sqrt(double(seg.vertDist)); accum_vec += weight * seg.unitVec; accum_weight += weight; } diff --git a/dewarping/DistortionModel.cpp b/dewarping/DistortionModel.cpp index a86bb062f..395a2fcf6 100644 --- a/dewarping/DistortionModel.cpp +++ b/dewarping/DistortionModel.cpp @@ -75,7 +75,7 @@ bool DistortionModel::isValid() const { return false; } - if ((fabs(min_dot) < 0.01) || (fabs(max_dot) < 0.01)) { + if ((std::fabs(min_dot) < 0.01) || (std::fabs(max_dot) < 0.01)) { // Too close - possible problems with calculating homography. return false; } diff --git a/dewarping/DistortionModelBuilder.cpp b/dewarping/DistortionModelBuilder.cpp index 215f8d673..32fcbe2e5 100644 --- a/dewarping/DistortionModelBuilder.cpp +++ b/dewarping/DistortionModelBuilder.cpp @@ -487,7 +487,7 @@ void DistortionModelBuilder::RansacAlgo::buildAndAssessModel(const TracedCurve* double sum_abs_err = 0; for (size_t i = 0; i < polyline_size; ++i) { - sum_abs_err += fabs(errvec[i]) * r_reference_height; + sum_abs_err += std::fabs(errvec[i]) * r_reference_height; } // Penalty for not being straight. error += sum_abs_err / polyline_size; @@ -518,7 +518,7 @@ catch (const std::runtime_error&) { const QPointF pt1(dewarper.mapToDewarpedSpace(loc + QPointF(0.0, -10))); const QPointF pt2(dewarper.mapToDewarpedSpace(loc + QPointF(0.0, 10))); - return fabs(pt1.y() - pt2.y()); + return std::fabs(pt1.y() - pt2.y()); } #endif @@ -530,7 +530,7 @@ QImage DistortionModelBuilder::visualizeTrimmedPolylines(const QImage& backgroun const int width = background.width(); const int height = background.height(); - const double stroke_width = sqrt(double(width * width + height * height)) / 500; + const double stroke_width = std::sqrt(double(width * width + height * height)) / 500; // Extend / trim bounds. QLineF bound1(m_bound1); @@ -575,7 +575,7 @@ QImage DistortionModelBuilder::visualizeModel(const QImage& background, const int width = background.width(); const int height = background.height(); - const double stroke_width = sqrt(double(width * width + height * height)) / 500; + const double stroke_width = std::sqrt(double(width * width + height * height)) / 500; // Extend / trim bounds. QLineF bound1(m_bound1); diff --git a/dewarping/RasterDewarper.cpp b/dewarping/RasterDewarper.cpp index c8bd44c86..23e2b10fc 100644 --- a/dewarping/RasterDewarper.cpp +++ b/dewarping/RasterDewarper.cpp @@ -113,8 +113,8 @@ void dewarpGeneric(const PixelType* const src_data, const float model_y = ((float) dst_y - model_domain_top) * model_y_scale; const Vec2f src_pt(origin + vec * homog(model_y)); - const int src_x0 = (int) floor(src_pt[0] - 0.5f); - const int src_y0 = (int) floor(src_pt[1] - 0.5f); + const int src_x0 = (int) std::floor(src_pt[0] - 0.5f); + const int src_y0 = (int) std::floor(src_pt[1] - 0.5f); const int src_x1 = src_x0 + 1; const int src_y1 = src_y0 + 1; const float x = src_pt[0] - src_x0; @@ -213,7 +213,7 @@ void areaMapGeneratrix(const PixelType* const src_data, // Note: the code below is more or less the same as in transformGeneric() // in imageproc/Transform.cpp - // Note that without using floor() and ceil() + // Note that without using std::floor() and std::ceil() // we can't guarantee that src_bottom >= src_top // and src_right >= src_left. auto src32_left = (int) std::floor(f_src32_left); diff --git a/dewarping/TextLineRefiner.cpp b/dewarping/TextLineRefiner.cpp index d38afb960..b297c7a4a 100644 --- a/dewarping/TextLineRefiner.cpp +++ b/dewarping/TextLineRefiner.cpp @@ -172,8 +172,8 @@ void TextLineRefiner::calcBlurredGradient(Grid& gradient, float h_sigma, } float TextLineRefiner::externalEnergyAt(const Grid& gradient, const Vec2f& pos, float penalty_if_outside) { - const auto x_base = static_cast(floor(pos[0])); - const auto y_base = static_cast(floor(pos[1])); + const auto x_base = static_cast(std::floor(pos[0])); + const auto y_base = static_cast(std::floor(pos[1])); const auto x_base_i = (int) x_base; const auto y_base_i = (int) y_base; @@ -197,7 +197,7 @@ TextLineRefiner::Snake TextLineRefiner::makeSnake(const std::vector& po const size_t polyline_size = polyline.size(); for (size_t i = 1; i < polyline_size; ++i) { - total_length += sqrt(Vec2f(polyline[i] - polyline[i - 1]).squaredNorm()); + total_length += std::sqrt(Vec2f(polyline[i] - polyline[i - 1]).squaredNorm()); } const auto points_in_snake = static_cast(total_length / 20); @@ -210,7 +210,7 @@ TextLineRefiner::Snake TextLineRefiner::makeSnake(const std::vector& po for (size_t i = 1; i < polyline_size; ++i) { const Vec2f base(polyline[i - 1]); const Vec2f vec((polyline[i] - base)); - const auto next_t = static_cast(base_t + sqrt(vec.squaredNorm())); + const auto next_t = static_cast(base_t + std::sqrt(vec.squaredNorm())); while (next_t >= next_insert_t) { const float fraction = (next_insert_t - base_t) / (next_t - base_t); @@ -261,7 +261,7 @@ void TextLineRefiner::calcFrenetFrames(std::vector& frenet_frames, } Vec2f tangent_vec(0.5 * (prev_segment + next_segment)); - const auto len = static_cast(sqrt(tangent_vec.squaredNorm())); + const auto len = static_cast(std::sqrt(tangent_vec.squaredNorm())); if (len > std::numeric_limits::epsilon()) { tangent_vec /= len; } @@ -435,7 +435,7 @@ TextLineRefiner::SnakeLength::SnakeLength(const Snake& snake) float arc_length_accum = 0; for (size_t i = 1; i < num_nodes; ++i) { const Vec2f vec(snake.nodes[i].center - snake.nodes[i - 1].center); - arc_length_accum += sqrt(vec.squaredNorm()); + arc_length_accum += std::sqrt(vec.squaredNorm()); m_integralLength[i] = arc_length_accum; } m_totalLength = arc_length_accum; @@ -730,7 +730,7 @@ float TextLineRefiner::Optimizer::calcExternalEnergy(const Grid& gradient float TextLineRefiner::Optimizer::calcElasticityEnergy(const SnakeNode& node1, const SnakeNode& node2, float avg_dist) { const Vec2f vec(node1.center - node2.center); - const auto vec_len = static_cast(sqrt(vec.squaredNorm())); + const auto vec_len = static_cast(std::sqrt(vec.squaredNorm())); if (vec_len < 1.0f) { return 1000.0f; // Penalty for moving too close to another node. @@ -745,14 +745,14 @@ float TextLineRefiner::Optimizer::calcBendingEnergy(const SnakeNode& node, const SnakeNode& prev_node, const SnakeNode& prev_prev_node) { const Vec2f vec(node.center - prev_node.center); - const auto vec_len = static_cast(sqrt(vec.squaredNorm())); + const auto vec_len = static_cast(std::sqrt(vec.squaredNorm())); if (vec_len < 1.0f) { return 1000.0f; // Penalty for moving too close to another node. } const Vec2f prev_vec(prev_node.center - prev_prev_node.center); - const auto prev_vec_len = static_cast(sqrt(prev_vec.squaredNorm())); + const auto prev_vec_len = static_cast(std::sqrt(prev_vec.squaredNorm())); if (prev_vec_len < 1.0f) { return 1000.0f; // Penalty for moving too close to another node. } diff --git a/dewarping/TextLineTracer.cpp b/dewarping/TextLineTracer.cpp index 844eae7d7..6e29bf269 100644 --- a/dewarping/TextLineTracer.cpp +++ b/dewarping/TextLineTracer.cpp @@ -102,7 +102,7 @@ void TextLineTracer::trace(const GrayImage& input, } Vec2f unit_down_vector(calcAvgUnitVector(vert_bounds)); - unit_down_vector /= sqrt(unit_down_vector.squaredNorm()); + unit_down_vector /= std::sqrt(unit_down_vector.squaredNorm()); if (unit_down_vector[1] < 0) { unit_down_vector = -unit_down_vector; } @@ -171,7 +171,7 @@ bool TextLineTracer::isCurvatureConsistent(const std::vector& polyline) return true; } // Threshold angle between a polyline segment and a normal to the previous one. - const auto cos_threshold = static_cast(cos((90.0f - 6.0f) * constants::DEG2RAD)); + const auto cos_threshold = static_cast(std::cos((90.0f - 6.0f) * constants::DEG2RAD)); const float cos_sq_threshold = cos_threshold * cos_threshold; bool significant_positive = false; bool significant_negative = false; @@ -413,13 +413,13 @@ void TextLineTracer::extractTextLines(std::list>& out, Vec2f TextLineTracer::calcAvgUnitVector(const std::pair& bounds) { Vec2f v1(bounds.first.p2() - bounds.first.p1()); - v1 /= sqrt(v1.squaredNorm()); + v1 /= std::sqrt(v1.squaredNorm()); Vec2f v2(bounds.second.p2() - bounds.second.p1()); - v2 /= sqrt(v2.squaredNorm()); + v2 /= std::sqrt(v2.squaredNorm()); Vec2f v3(v1 + v2); - v3 /= sqrt(v3.squaredNorm()); + v3 /= std::sqrt(v3.squaredNorm()); return v3; } @@ -473,8 +473,8 @@ QLineF TextLineTracer::calcMidLine(const QLineF& line1, const QLineF& line2) { // Lines do intersect. Vec2d v1(line1.p2() - line1.p1()); Vec2d v2(line2.p2() - line2.p1()); - v1 /= sqrt(v1.squaredNorm()); - v2 /= sqrt(v2.squaredNorm()); + v1 /= std::sqrt(v1.squaredNorm()); + v2 /= std::sqrt(v2.squaredNorm()); return QLineF(intersection, intersection + 0.5 * (v1 + v2)); } diff --git a/dewarping/TopBottomEdgeTracer.cpp b/dewarping/TopBottomEdgeTracer.cpp index 657997d0f..c5bc4bfec 100644 --- a/dewarping/TopBottomEdgeTracer.cpp +++ b/dewarping/TopBottomEdgeTracer.cpp @@ -162,8 +162,8 @@ float TopBottomEdgeTracer::interpolatedGridValue(const Grid& grid, Extractor extractor, const Vec2f pos, float default_value) { - const auto x_base = static_cast(floor(pos[0])); - const auto y_base = static_cast(floor(pos[1])); + const auto x_base = static_cast(std::floor(pos[0])); + const auto y_base = static_cast(std::floor(pos[1])); const auto x_base_i = (int) x_base; const auto y_base_i = (int) y_base; @@ -427,13 +427,13 @@ void TopBottomEdgeTracer::verticalSobelInPlace(Grid& grid) { Vec2f TopBottomEdgeTracer::calcAvgUnitVector(const std::pair& bounds) { Vec2f v1(bounds.first.p2() - bounds.first.p1()); - v1 /= sqrt(v1.squaredNorm()); + v1 /= std::sqrt(v1.squaredNorm()); Vec2f v2(bounds.second.p2() - bounds.second.p1()); - v2 /= sqrt(v2.squaredNorm()); + v2 /= std::sqrt(v2.squaredNorm()); Vec2f v3(v1 + v2); - v3 /= sqrt(v3.squaredNorm()); + v3 /= std::sqrt(v3.squaredNorm()); return v3; } @@ -730,7 +730,7 @@ void TopBottomEdgeTracer::downTheHillSnake(std::vector& snake, const Gr float avg_dist = 0; for (size_t i = 1; i < num_nodes; ++i) { const Vec2f vec(snake[i] - snake[i - 1]); - avg_dist += sqrt(vec.squaredNorm()); + avg_dist += std::sqrt(vec.squaredNorm()); } avg_dist /= num_nodes - 1; @@ -782,7 +782,7 @@ void TopBottomEdgeTracer::downTheHillSnake(std::vector& snake, const Gr float cost = prev_step.pathCost + step.pathCost; const Vec2f vec(step.pt - prev_step.pt); - const auto vec_len = static_cast(sqrt(vec.squaredNorm())); + const auto vec_len = static_cast(std::sqrt(vec.squaredNorm())); if (vec_len < segment_dist_threshold) { cost += 1000; } @@ -796,12 +796,12 @@ void TopBottomEdgeTracer::downTheHillSnake(std::vector& snake, const Gr Vec2f prev_normal(prev_step.pt - prev_prev_step.pt); std::swap(prev_normal[0], prev_normal[1]); prev_normal[0] = -prev_normal[0]; - const auto prev_normal_len = static_cast(sqrt(prev_normal.squaredNorm())); + const auto prev_normal_len = static_cast(std::sqrt(prev_normal.squaredNorm())); if (prev_normal_len < segment_dist_threshold) { cost += 1000; } else { const float cos = vec.dot(prev_normal) / (vec_len * prev_normal_len); - // cost += 0.7 * fabs(cos); + // cost += 0.7 * std::fabs(cos); cost += bending_weight * cos * cos; } } @@ -859,7 +859,7 @@ void TopBottomEdgeTracer::upTheHillSnake(std::vector& snake, const Grid float avg_dist = 0; for (size_t i = 1; i < num_nodes; ++i) { const Vec2f vec(snake[i] - snake[i - 1]); - avg_dist += sqrt(vec.squaredNorm()); + avg_dist += std::sqrt(vec.squaredNorm()); } avg_dist /= num_nodes - 1; @@ -913,7 +913,7 @@ void TopBottomEdgeTracer::upTheHillSnake(std::vector& snake, const Grid float cost = prev_step.pathCost + step.pathCost; const Vec2f vec(step.pt - prev_step.pt); - const auto vec_len = static_cast(sqrt(vec.squaredNorm())); + const auto vec_len = static_cast(std::sqrt(vec.squaredNorm())); if (vec_len < segment_dist_threshold) { cost += 1000; } @@ -927,12 +927,12 @@ void TopBottomEdgeTracer::upTheHillSnake(std::vector& snake, const Grid Vec2f prev_normal(prev_step.pt - prev_prev_step.pt); std::swap(prev_normal[0], prev_normal[1]); prev_normal[0] = -prev_normal[0]; - const auto prev_normal_len = static_cast(sqrt(prev_normal.squaredNorm())); + const auto prev_normal_len = static_cast(std::sqrt(prev_normal.squaredNorm())); if (prev_normal_len < segment_dist_threshold) { cost += 1000; } else { const float cos = vec.dot(prev_normal) / (vec_len * prev_normal_len); - // cost += 0.7 * fabs(cos); + // cost += 0.7 * std::fabs(cos); cost += bending_weight * cos * cos; } } diff --git a/dewarping/TowardsLineTracer.cpp b/dewarping/TowardsLineTracer.cpp index 26fc2dbbb..598cd8696 100644 --- a/dewarping/TowardsLineTracer.cpp +++ b/dewarping/TowardsLineTracer.cpp @@ -159,7 +159,7 @@ void TowardsLineTracer::setupSteps() { Step& step = m_steps[m_numSteps]; step.vec = dir; step.unitVec = Vec2d(step.vec.x(), step.vec.y()); - step.unitVec /= sqrt(step.unitVec.squaredNorm()); + step.unitVec /= std::sqrt(step.unitVec.squaredNorm()); step.dmOffset = step.vec.y() * m_dmStride + step.vec.x(); step.pmOffset = step.vec.y() * m_pmStride + step.vec.x(); ++m_numSteps; diff --git a/filters/deskew/Filter.cpp b/filters/deskew/Filter.cpp index 111e28eb5..f281ed10f 100644 --- a/filters/deskew/Filter.cpp +++ b/filters/deskew/Filter.cpp @@ -44,7 +44,7 @@ Filter::Filter(const PageSelectionAccessor& page_selection_accessor) typedef PageOrderOption::ProviderPtr ProviderPtr; const ProviderPtr default_order; - const ProviderPtr order_by_deviation(new OrderByDeviationProvider(m_ptrSettings->deviationProvider())); + const auto order_by_deviation = make_intrusive(m_ptrSettings->deviationProvider()); m_pageOrderOptions.emplace_back(tr("Natural order"), default_order); m_pageOrderOptions.emplace_back(tr("Order by decreasing deviation"), order_by_deviation); } diff --git a/filters/deskew/ImageView.cpp b/filters/deskew/ImageView.cpp index 278b3d694..e3e21e38f 100644 --- a/filters/deskew/ImageView.cpp +++ b/filters/deskew/ImageView.cpp @@ -28,7 +28,7 @@ namespace deskew { const double ImageView::m_maxRotationDeg = 45.0; -const double ImageView::m_maxRotationSin = sin(m_maxRotationDeg * imageproc::constants::DEG2RAD); +const double ImageView::m_maxRotationSin = std::sin(m_maxRotationDeg * imageproc::constants::DEG2RAD); const int ImageView::m_cellSize = 20; ImageView::ImageView(const QImage& image, const QImage& downscaled_image, const ImageTransformation& xform) @@ -194,7 +194,7 @@ void ImageView::handleMoveRequest(int idx, const QPointF& pos) { double rel_y = abs_y - arc_square.center().y(); rel_y = qBound(-arc_radius, rel_y, arc_radius); - double angle_rad = asin(rel_y / arc_radius); + double angle_rad = std::asin(rel_y / arc_radius); if (idx == 0) { angle_rad = -angle_rad; } @@ -219,7 +219,7 @@ void ImageView::dragFinished() { QPointF ImageView::getImageRotationOrigin() const { const QRectF viewport_rect(maxViewportRect()); - return QPointF(floor(0.5 * viewport_rect.width()) + 0.5, floor(0.5 * viewport_rect.height()) + 0.5); + return QPointF(std::floor(0.5 * viewport_rect.width()) + 0.5, std::floor(0.5 * viewport_rect.height()) + 0.5); } /** diff --git a/filters/deskew/Task.cpp b/filters/deskew/Task.cpp index 8eb686421..34e146a7b 100644 --- a/filters/deskew/Task.cpp +++ b/filters/deskew/Task.cpp @@ -19,7 +19,6 @@ #include #include -#include #include "Task.h" #include "Filter.h" #include "OptionsWidget.h" @@ -123,12 +122,9 @@ FilterResultPtr Task::process(const TaskStatus& status, FilterData data) { status.throwIfCancelled(); if (bounded_image_area.isValid()) { - BinaryImage rotated_image(orthogonalRotation( - BinaryImage(data.isBlackOnWhite() ? data.grayImage() : data.grayImage().inverted(), - bounded_image_area, - data.isBlackOnWhite() ? data.bwThreshold() - : BinaryThreshold(256 - int(data.bwThreshold()))), - data.xform().preRotation().toDegrees())); + BinaryImage rotated_image( + orthogonalRotation(BinaryImage(data.grayImage(), bounded_image_area, data.bwThreshold()), + data.xform().preRotation().toDegrees())); if (m_ptrDbg) { m_ptrDbg->add(rotated_image, "bw_rotated"); } @@ -166,8 +162,8 @@ FilterResultPtr Task::process(const TaskStatus& status, FilterData data) { if (m_ptrNextTask) { return m_ptrNextTask->process(status, FilterData(data, new_xform)); } else { - return FilterResultPtr(new UiUpdater(m_ptrFilter, std::move(m_ptrDbg), data.origImage(), m_pageId, new_xform, - ui_data, m_batchProcessing)); + return make_intrusive(m_ptrFilter, std::move(m_ptrDbg), data.origImage(), m_pageId, new_xform, + ui_data, m_batchProcessing); } } // Task::process @@ -232,9 +228,7 @@ void Task::updateFilterData(const TaskStatus& status, FilterData& data, bool nee const GrayImage& img = data.grayImage(); BinaryImage mask(img.size(), BLACK); PolygonRasterizer::fillExcept(mask, WHITE, data.xform().resultingPreCropArea(), Qt::WindingFill); - ImageSettings::PageParams new_params( - BinaryThreshold::otsuThreshold(GrayscaleHistogram(img, mask)), - BlackOnWhiteEstimator::isBlackOnWhite(data.grayImage(), data.xform(), status, m_ptrDbg.get())); + ImageSettings::PageParams new_params(BinaryThreshold::otsuThreshold(GrayscaleHistogram(img, mask))); m_ptrImageSettings->setPageParams(m_pageId, new_params); data.updateImageParams(new_params); diff --git a/filters/fix_orientation/Task.cpp b/filters/fix_orientation/Task.cpp index 698c263f1..b4e7bde61 100644 --- a/filters/fix_orientation/Task.cpp +++ b/filters/fix_orientation/Task.cpp @@ -86,7 +86,7 @@ FilterResultPtr Task::process(const TaskStatus& status, FilterData data) { if (m_ptrNextTask) { return m_ptrNextTask->process(status, FilterData(data, xform)); } else { - return FilterResultPtr(new UiUpdater(m_ptrFilter, data.origImage(), m_imageId, xform, m_batchProcessing)); + return make_intrusive(m_ptrFilter, data.origImage(), m_imageId, xform, m_batchProcessing); } } @@ -94,7 +94,7 @@ void Task::updateFilterData(FilterData& data) { if (const std::unique_ptr params = m_ptrImageSettings->getPageParams(m_pageId)) { data.updateImageParams(*params); } else { - ImageSettings::PageParams new_params(BinaryThreshold::otsuThreshold(data.grayImage()), true); + ImageSettings::PageParams new_params(BinaryThreshold::otsuThreshold(data.grayImage())); m_ptrImageSettings->setPageParams(m_pageId, new_params); data.updateImageParams(new_params); diff --git a/filters/output/BlackWhiteOptions.cpp b/filters/output/BlackWhiteOptions.cpp index a90232c3e..3ead784ce 100644 --- a/filters/output/BlackWhiteOptions.cpp +++ b/filters/output/BlackWhiteOptions.cpp @@ -17,6 +17,7 @@ */ #include "BlackWhiteOptions.h" +#include "../../Utils.h" #include #include @@ -55,10 +56,10 @@ QDomElement BlackWhiteOptions::toXml(QDomDocument& doc, const QString& name) con el.setAttribute("morphologicalSmoothing", morphologicalSmoothingEnabled ? "1" : "0"); el.setAttribute("normalizeIlluminationBW", m_normalizeIllumination ? "1" : "0"); el.setAttribute("windowSize", windowSize); - el.setAttribute("sauvolaCoef", sauvolaCoef); + el.setAttribute("sauvolaCoef", Utils::doubleToString(sauvolaCoef)); el.setAttribute("wolfLowerBound", wolfLowerBound); el.setAttribute("wolfUpperBound", wolfUpperBound); - el.setAttribute("wolfCoef", wolfCoef); + el.setAttribute("wolfCoef", Utils::doubleToString(wolfCoef)); el.setAttribute("binarizationMethod", formatBinarizationMethod(binarizationMethod)); el.appendChild(colorSegmenterOptions.toXml(doc, "color-segmenter-options")); @@ -216,7 +217,7 @@ BlackWhiteOptions::ColorSegmenterOptions::ColorSegmenterOptions(const QDomElemen QDomElement BlackWhiteOptions::ColorSegmenterOptions::toXml(QDomDocument& doc, const QString& name) const { QDomElement el(doc.createElement(name)); - el.setAttribute("colorSegmentationEnabled", enabled ? "1" : "0"); + el.setAttribute("enabled", enabled ? "1" : "0"); el.setAttribute("noiseReduction", noiseReduction); el.setAttribute("redThresholdAdjustment", redThresholdAdjustment); el.setAttribute("greenThresholdAdjustment", greenThresholdAdjustment); diff --git a/filters/output/DespeckleView.cpp b/filters/output/DespeckleView.cpp index c43c564cb..33f00d4f5 100644 --- a/filters/output/DespeckleView.cpp +++ b/filters/output/DespeckleView.cpp @@ -56,7 +56,7 @@ class DespeckleView::TaskCancelHandle : public TaskStatus, public ref_countable }; -class DespeckleView::DespeckleTask : public AbstractCommand0 { +class DespeckleView::DespeckleTask : public AbstractCommand { public: DespeckleTask(DespeckleView* owner, const DespeckleState& despeckle_state, @@ -75,7 +75,7 @@ class DespeckleView::DespeckleTask : public AbstractCommand0 { +class DespeckleView::DespeckleResult : public AbstractCommand { public: DespeckleResult(QPointer owner, intrusive_ptr cancel_handle, @@ -164,8 +164,8 @@ void DespeckleView::initiateDespeckling(const AnimationAction anim_action) { // Note that we are getting rid of m_initialSpeckles, // as we wouldn't need it any more. - const BackgroundExecutor::TaskPtr task( - new DespeckleTask(this, m_despeckleState, m_ptrCancelHandle, m_despeckleLevel, m_debug)); + const auto task + = make_intrusive(this, m_despeckleState, m_ptrCancelHandle, m_despeckleLevel, m_debug); ImageViewBase::backgroundExecutor().enqueueTask(task); } @@ -241,8 +241,8 @@ BackgroundExecutor::TaskResultPtr DespeckleView::DespeckleTask::operator()() { m_ptrCancelHandle->throwIfCancelled(); - return BackgroundExecutor::TaskResultPtr(new DespeckleResult(m_ptrOwner, m_ptrCancelHandle, m_despeckleState, - visualization, std::move(m_ptrDbg))); + return make_intrusive(m_ptrOwner, m_ptrCancelHandle, m_despeckleState, visualization, + std::move(m_ptrDbg)); } catch (const TaskCancelException&) { return nullptr; } diff --git a/filters/output/FillZoneEditor.cpp b/filters/output/FillZoneEditor.cpp index 97edea33d..45de5ef2d 100644 --- a/filters/output/FillZoneEditor.cpp +++ b/filters/output/FillZoneEditor.cpp @@ -83,7 +83,7 @@ FillZoneEditor::FillZoneEditor(const QImage& image, rootInteractionHandler().makeLastFollower(m_zoomHandler); for (const Zone& zone : m_ptrSettings->fillZonesForPage(page_id)) { - EditableSpline::Ptr spline(new EditableSpline(zone.spline().transformed(m_origToImage))); + auto spline = make_intrusive(zone.spline().transformed(m_origToImage)); m_zones.addZone(spline, zone.properties()); } } diff --git a/filters/output/OutputGenerator.cpp b/filters/output/OutputGenerator.cpp index 34a8ba3ef..b5dd1f207 100644 --- a/filters/output/OutputGenerator.cpp +++ b/filters/output/OutputGenerator.cpp @@ -56,7 +56,6 @@ #include #include #include -#include #include "imageproc/OrthogonalRotation.h" using namespace imageproc; @@ -474,6 +473,7 @@ QImage OutputGenerator::processWithoutDewarping(const TaskStatus& status, const QPolygonF contentArea = m_xform.resultingPreCropArea().intersected( QRectF(render_params.cutMargins() ? m_contentRect : m_outRect)); const QRect contentRect = contentArea.boundingRect().toRect(); + const QPolygonF outCropArea = m_xform.resultingPreCropArea().intersected(QRectF(m_outRect)); const QSize target_size(m_outRect.size().expandedTo(QSize(1, 1))); // If the content area is empty or outside the cropping area, return a blank page. @@ -506,26 +506,24 @@ QImage OutputGenerator::processWithoutDewarping(const TaskStatus& status, .toRect()); const QRect contentRectInWorkingCs(contentRect.translated(-workingBoundingRect.topLeft())); const QPolygonF contentAreaInWorkingCs(contentArea.translated(-workingBoundingRect.topLeft())); + const QPolygonF outCropAreaInWorkingCs(outCropArea.translated(-workingBoundingRect.topLeft())); const QPolygonF preCropAreaInOriginalCs(m_xform.transformBack().map(m_xform.resultingPreCropArea())); const QPolygonF contentAreaInOriginalCs(m_xform.transformBack().map(contentArea)); + const QPolygonF outCropAreaInOriginalCs(m_xform.transformBack().map(outCropArea)); - const bool isBlackOnWhite = BlackOnWhiteEstimator::isBlackOnWhite(input.grayImage(), contentAreaInOriginalCs); - const GrayImage inputGrayImage = isBlackOnWhite ? input.grayImage() : input.grayImage().inverted(); - const QImage inputOrigImage = [&input, isBlackOnWhite]() { + const GrayImage inputGrayImage = input.grayImage(); + const QImage inputOrigImage = [&input]() { QImage result = input.origImage(); if (!result.allGray() && (result.format() != QImage::Format_ARGB32) && (result.format() != QImage::Format_RGB32)) { result = result.convertToFormat(QImage::Format_RGB32); } - if (!isBlackOnWhite) { - result.invertPixels(); - } return result; }(); QColor outsideBackgroundColor = BackgroundColorCalculator::calcDominantBackgroundColor( - inputOrigImage.allGray() ? inputGrayImage : inputOrigImage, contentAreaInOriginalCs); + inputOrigImage.allGray() ? inputGrayImage : inputOrigImage, outCropAreaInOriginalCs, dbg); const bool needNormalizeIllumination = (render_params.normalizeIllumination() && render_params.needBinarization()) @@ -562,7 +560,7 @@ QImage OutputGenerator::processWithoutDewarping(const TaskStatus& status, if (needNormalizeIllumination) { outsideBackgroundColor - = BackgroundColorCalculator::calcDominantBackgroundColor(maybe_normalized, contentAreaInWorkingCs); + = BackgroundColorCalculator::calcDominantBackgroundColor(maybe_normalized, outCropAreaInWorkingCs, dbg); } status.throwIfCancelled(); @@ -614,10 +612,6 @@ QImage OutputGenerator::processWithoutDewarping(const TaskStatus& status, maybeDespeckleInPlace(dst, m_outRect, m_outRect, m_despeckleLevel, speckles_image, m_dpi, status, dbg); if (!render_params.needColorSegmentation()) { - if (!isBlackOnWhite) { - dst.invert(); - } - applyFillZonesInPlace(dst, fill_zones); return dst.toQImage(); @@ -642,10 +636,6 @@ QImage OutputGenerator::processWithoutDewarping(const TaskStatus& status, status.throwIfCancelled(); - if (!isBlackOnWhite) { - segmented_image.invertPixels(); - } - applyFillZonesInPlace(segmented_image, fill_zones, false); if (dbg) { @@ -785,7 +775,7 @@ QImage OutputGenerator::processWithoutDewarping(const TaskStatus& status, if (needNormalizeIllumination && !render_params.normalizeIlluminationColor()) { outsideBackgroundColor = BackgroundColorCalculator::calcDominantBackgroundColor( - inputOrigImage.allGray() ? inputGrayImage : inputOrigImage, contentAreaInOriginalCs); + inputOrigImage.allGray() ? inputGrayImage : inputOrigImage, outCropAreaInOriginalCs, dbg); if (inputOrigImage.allGray()) { maybe_normalized = transformToGray(inputGrayImage, m_xform.transform(), workingBoundingRect, @@ -812,7 +802,7 @@ QImage OutputGenerator::processWithoutDewarping(const TaskStatus& status, QColor outsideOriginalBackgroundColor = outsideBackgroundColor; if (m_colorParams.colorCommonOptions().getFillingColor() == FILL_WHITE) { - outsideOriginalBackgroundColor = isBlackOnWhite ? Qt::white : Qt::black; + outsideOriginalBackgroundColor = Qt::white; } fillMarginsInPlace(original_background, contentAreaInWorkingCs, outsideOriginalBackgroundColor); original_background_dst.fill(outsideOriginalBackgroundColor); @@ -883,7 +873,7 @@ QImage OutputGenerator::processWithoutDewarping(const TaskStatus& status, if (render_params.needBinarization()) { outsideBackgroundColor = Qt::white; } else if (m_colorParams.colorCommonOptions().getFillingColor() == FILL_WHITE) { - outsideBackgroundColor = isBlackOnWhite ? Qt::white : Qt::black; + outsideBackgroundColor = Qt::white; if (!render_params.needBinarization()) { reserveBlackAndWhite(maybe_normalized); } @@ -894,10 +884,6 @@ QImage OutputGenerator::processWithoutDewarping(const TaskStatus& status, drawOver(dst, contentRect, maybe_normalized, contentRectInWorkingCs); maybe_normalized = QImage(); - if (!isBlackOnWhite) { - dst.invertPixels(); - } - if (render_params.mixedOutput() && render_params.needBinarization()) { applyFillZonesToMixedInPlace(dst, fill_zones, bw_content_mask_output, !render_params.needColorSegmentation()); } else { @@ -919,19 +905,11 @@ QImage OutputGenerator::processWithoutDewarping(const TaskStatus& status, splitImage->setBackgroundImage(dst); if (render_params.needBinarization() && render_params.originalBackground()) { - if (!isBlackOnWhite) { - dst.invertPixels(); - } - BinaryImage background_mask = BinaryImage(dst, BinaryThreshold(255)).inverted(); fillMarginsInPlace(background_mask, m_xform.resultingPreCropArea(), BLACK); - applyMask(original_background, background_mask, isBlackOnWhite ? WHITE : BLACK); + applyMask(original_background, background_mask, WHITE); + applyMask(original_background, bw_content_mask_output, BLACK); - applyMask(original_background, bw_content_mask_output, isBlackOnWhite ? BLACK : WHITE); - - if (!isBlackOnWhite) { - original_background.invertPixels(); - } splitImage->setOriginalBackgroundImage(original_background); } @@ -968,6 +946,7 @@ QImage OutputGenerator::processWithDewarping(const TaskStatus& status, const QPolygonF contentArea = m_xform.resultingPreCropArea().intersected( QRectF(render_params.cutMargins() ? m_contentRect : m_outRect)); const QRect contentRect = contentArea.boundingRect().toRect(); + const QPolygonF outCropArea = m_xform.resultingPreCropArea().intersected(QRectF(m_outRect)); const QSize target_size(m_outRect.size().expandedTo(QSize(1, 1))); // If the content area is empty or outside the cropping area, return a blank page. @@ -1000,26 +979,24 @@ QImage OutputGenerator::processWithDewarping(const TaskStatus& status, .toRect()); const QRect contentRectInWorkingCs(contentRect.translated(-workingBoundingRect.topLeft())); const QPolygonF contentAreaInWorkingCs(contentArea.translated(-workingBoundingRect.topLeft())); + const QPolygonF outCropAreaInWorkingCs(outCropArea.translated(-workingBoundingRect.topLeft())); const QPolygonF preCropAreaInOriginalCs(m_xform.transformBack().map(m_xform.resultingPreCropArea())); const QPolygonF contentAreaInOriginalCs(m_xform.transformBack().map(contentArea)); + const QPolygonF outCropAreaInOriginalCs(m_xform.transformBack().map(outCropArea)); - const bool isBlackOnWhite = BlackOnWhiteEstimator::isBlackOnWhite(input.grayImage(), contentAreaInOriginalCs); - const GrayImage inputGrayImage = isBlackOnWhite ? input.grayImage() : input.grayImage().inverted(); - const QImage inputOrigImage = [&input, isBlackOnWhite]() { + const GrayImage inputGrayImage = input.grayImage(); + const QImage inputOrigImage = [&input]() { QImage result = input.origImage(); if (!result.allGray() && (result.format() != QImage::Format_ARGB32) && (result.format() != QImage::Format_RGB32)) { result = result.convertToFormat(QImage::Format_RGB32); } - if (!isBlackOnWhite) { - result.invertPixels(); - } return result; }(); QColor outsideBackgroundColor = BackgroundColorCalculator::calcDominantBackgroundColor( - inputOrigImage.allGray() ? inputGrayImage : inputOrigImage, contentAreaInOriginalCs); + inputOrigImage.allGray() ? inputGrayImage : inputOrigImage, outCropAreaInOriginalCs, dbg); const bool color_original = !inputOrigImage.allGray(); @@ -1088,8 +1065,8 @@ QImage OutputGenerator::processWithDewarping(const TaskStatus& status, } } - outsideBackgroundColor - = BackgroundColorCalculator::calcDominantBackgroundColor(normalized_original, contentAreaInOriginalCs); + outsideBackgroundColor = BackgroundColorCalculator::calcDominantBackgroundColor(normalized_original, + outCropAreaInOriginalCs, dbg); } status.throwIfCancelled(); @@ -1467,10 +1444,6 @@ QImage OutputGenerator::processWithDewarping(const TaskStatus& status, status, dbg); if (!render_params.needColorSegmentation()) { - if (!isBlackOnWhite) { - dewarped_bw_content.invert(); - } - applyFillZonesInPlace(dewarped_bw_content, fill_zones, orig_to_output, postTransform); return dewarped_bw_content.toQImage(); @@ -1485,10 +1458,6 @@ QImage OutputGenerator::processWithDewarping(const TaskStatus& status, status.throwIfCancelled(); - if (!isBlackOnWhite) { - segmented_image.invertPixels(); - } - applyFillZonesInPlace(segmented_image, fill_zones, orig_to_output, postTransform, false); if (dbg) { @@ -1594,7 +1563,7 @@ QImage OutputGenerator::processWithDewarping(const TaskStatus& status, if (needNormalizeIllumination && !render_params.normalizeIlluminationColor()) { outsideBackgroundColor = BackgroundColorCalculator::calcDominantBackgroundColor( - inputOrigImage.allGray() ? inputGrayImage : inputOrigImage, contentAreaInOriginalCs); + inputOrigImage.allGray() ? inputGrayImage : inputOrigImage, outCropAreaInOriginalCs, dbg); QImage orig_without_illumination; if (color_original) { @@ -1625,7 +1594,7 @@ QImage OutputGenerator::processWithDewarping(const TaskStatus& status, QColor outsideOriginalBackgroundColor = outsideBackgroundColor; if (m_colorParams.colorCommonOptions().getFillingColor() == FILL_WHITE) { - outsideOriginalBackgroundColor = isBlackOnWhite ? Qt::white : Qt::black; + outsideOriginalBackgroundColor = Qt::white; } fillMarginsInPlace(original_background, dewarping_content_area_mask, outsideOriginalBackgroundColor); @@ -1677,17 +1646,13 @@ QImage OutputGenerator::processWithDewarping(const TaskStatus& status, if (render_params.needBinarization()) { outsideBackgroundColor = Qt::white; } else if (m_colorParams.colorCommonOptions().getFillingColor() == FILL_WHITE) { - outsideBackgroundColor = isBlackOnWhite ? Qt::white : Qt::black; + outsideBackgroundColor = Qt::white; if (!render_params.needBinarization()) { reserveBlackAndWhite(dewarped); } } fillMarginsInPlace(dewarped, dewarping_content_area_mask, outsideBackgroundColor); - if (!isBlackOnWhite) { - dewarped.invertPixels(); - } - if (render_params.mixedOutput() && render_params.needBinarization()) { applyFillZonesToMixedInPlace(dewarped, fill_zones, orig_to_output, postTransform, dewarped_bw_content_mask, !render_params.needColorSegmentation()); @@ -1710,19 +1675,11 @@ QImage OutputGenerator::processWithDewarping(const TaskStatus& status, splitImage->setBackgroundImage(dewarped); if (render_params.needBinarization() && render_params.originalBackground()) { - if (!isBlackOnWhite) { - dewarped.invertPixels(); - } - BinaryImage background_mask = BinaryImage(dewarped, BinaryThreshold(255)).inverted(); fillMarginsInPlace(background_mask, dewarping_content_area_mask, BLACK); - applyMask(original_background, background_mask, isBlackOnWhite ? WHITE : BLACK); - - applyMask(original_background, dewarped_bw_content_mask, isBlackOnWhite ? BLACK : WHITE); + applyMask(original_background, background_mask, WHITE); + applyMask(original_background, dewarped_bw_content_mask, BLACK); - if (!isBlackOnWhite) { - original_background.invertPixels(); - } splitImage->setOriginalBackgroundImage(original_background); } diff --git a/filters/output/OutputImageParams.cpp b/filters/output/OutputImageParams.cpp index c019dfaa8..dcb551687 100644 --- a/filters/output/OutputImageParams.cpp +++ b/filters/output/OutputImageParams.cpp @@ -238,6 +238,6 @@ bool OutputImageParams::PartialXform::matches(const PartialXform& other) const { } bool OutputImageParams::PartialXform::closeEnough(double v1, double v2) { - return fabs(v1 - v2) < 0.0001; + return std::fabs(v1 - v2) < 0.0001; } } // namespace output \ No newline at end of file diff --git a/filters/output/PictureZoneEditor.cpp b/filters/output/PictureZoneEditor.cpp index c7b1f4df2..bb0ce5f6a 100644 --- a/filters/output/PictureZoneEditor.cpp +++ b/filters/output/PictureZoneEditor.cpp @@ -39,7 +39,7 @@ static const QRgb mask_color = 0xff587ff4; using namespace imageproc; -class PictureZoneEditor::MaskTransformTask : public AbstractCommand0>>, +class PictureZoneEditor::MaskTransformTask : public AbstractCommand>>, public QObject { DECLARE_NON_COPYABLE(MaskTransformTask) @@ -57,10 +57,10 @@ class PictureZoneEditor::MaskTransformTask : public AbstractCommand0isCancelled(); } - intrusive_ptr> operator()() override; + intrusive_ptr> operator()() override; private: - class Result : public AbstractCommand0 { + class Result : public AbstractCommand { public: explicit Result(PictureZoneEditor* zone_editor); @@ -133,7 +133,7 @@ PictureZoneEditor::PictureZoneEditor(const QImage& image, m_pictureMaskRebuildTimer.setInterval(150); for (const Zone& zone : m_ptrSettings->pictureZonesForPage(page_id)) { - EditableSpline::Ptr spline(new EditableSpline(zone.spline())); + auto spline = make_intrusive(zone.spline()); m_zones.addZone(spline, zone.properties()); } } @@ -149,7 +149,7 @@ void PictureZoneEditor::onPaint(QPainter& painter, const InteractionState& inter if (!validateScreenPictureMask()) { schedulePictureMaskRebuild(); } else { - const double sn = sin(constants::DEG2RAD * m_pictureMaskAnimationPhase); + const double sn = std::sin(constants::DEG2RAD * m_pictureMaskAnimationPhase); const double scale = 0.5 * (sn + 1.0); // 0 .. 1 const double opacity = 0.35 * scale + 0.15; @@ -306,7 +306,7 @@ PictureZoneEditor::MaskTransformTask::MaskTransformTask(PictureZoneEditor* zone_ : m_ptrResult(new Result(zone_editor)), m_origMask(mask), m_xform(xform), m_targetSize(target_size) { } -intrusive_ptr> PictureZoneEditor::MaskTransformTask::operator()() { +intrusive_ptr> PictureZoneEditor::MaskTransformTask::operator()() { if (isCancelled()) { return nullptr; } diff --git a/filters/output/TabbedImageView.cpp b/filters/output/TabbedImageView.cpp index 320d2ac26..f84739d28 100644 --- a/filters/output/TabbedImageView.cpp +++ b/filters/output/TabbedImageView.cpp @@ -126,10 +126,10 @@ void TabbedImageView::setFocus(QScrollBar& hor_bar, const int hor_bar_length = hor_bar.maximum() - hor_bar.minimum() + hor_bar.pageStep(); const int ver_bar_length = ver_bar.maximum() - ver_bar.minimum() + ver_bar.pageStep(); - auto hor_value - = (int) round(((focal.x() - rect.left()) / rect.width()) * hor_bar_length - (hor_bar.pageStep() / 2.0)); - auto ver_value - = (int) round(((focal.y() - rect.top()) / rect.height()) * ver_bar_length - (ver_bar.pageStep() / 2.0)); + auto hor_value = (int) std::round(((focal.x() - rect.left()) / rect.width()) * hor_bar_length + - (hor_bar.pageStep() / 2.0)); + auto ver_value = (int) std::round(((focal.y() - rect.top()) / rect.height()) * ver_bar_length + - (ver_bar.pageStep() / 2.0)); hor_value = qBound(hor_bar.minimum(), hor_value, hor_bar.maximum()); ver_value = qBound(ver_bar.minimum(), ver_value, ver_bar.maximum()); diff --git a/filters/output/Task.cpp b/filters/output/Task.cpp index 03ba5fd63..6fc8f3dfc 100644 --- a/filters/output/Task.cpp +++ b/filters/output/Task.cpp @@ -447,10 +447,10 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data, } if (CommandLine::get().isGui()) { - return FilterResultPtr(new UiUpdater(m_ptrFilter, m_ptrSettings, std::move(m_ptrDbg), params, new_xform, - generator.getPostTransform(), generator.outputContentRect(), m_pageId, - data.origImage(), out_img, automask_img, despeckle_state, - despeckle_visualization, m_batchProcessing, m_debug)); + return make_intrusive(m_ptrFilter, m_ptrSettings, std::move(m_ptrDbg), params, new_xform, + generator.getPostTransform(), generator.outputContentRect(), m_pageId, + data.origImage(), out_img, automask_img, despeckle_state, + despeckle_visualization, m_batchProcessing, m_debug); } else { return nullptr; } diff --git a/filters/page_layout/CacheDrivenTask.cpp b/filters/page_layout/CacheDrivenTask.cpp index dc70abe6c..1129936cf 100644 --- a/filters/page_layout/CacheDrivenTask.cpp +++ b/filters/page_layout/CacheDrivenTask.cpp @@ -60,8 +60,9 @@ void CacheDrivenTask::process(const PageInfo& page_info, const QPolygonF page_rect_phys(Utils::calcPageRectPhys(xform, content_rect_phys, new_params, m_ptrSettings->getAggregateHardSizeMM(), m_ptrSettings->getAggregateContentRect())); + ImageTransformation new_xform(xform); - new_xform.setPostCropArea(xform.transform().map(page_rect_phys)); + new_xform.setPostCropArea(shiftToRoundedOrigin(new_xform.transform().map(page_rect_phys))); if (m_ptrNextTask) { m_ptrNextTask->process(page_info, collector, new_xform, content_rect_phys); @@ -80,4 +81,13 @@ void CacheDrivenTask::process(const PageInfo& page_info, m_ptrSettings->deviationProvider().isDeviant(page_info.id(), deviationCoef, deviationThreshold)))); } } // CacheDrivenTask::process + +QPolygonF CacheDrivenTask::shiftToRoundedOrigin(const QPolygonF& poly) { + const double x = poly.boundingRect().left(); + const double y = poly.boundingRect().top(); + const double shift_value_x = -(x - std::round(x)); + const double shift_value_y = -(y - std::round(y)); + + return poly.translated(shift_value_x, shift_value_y); +} } // namespace page_layout \ No newline at end of file diff --git a/filters/page_layout/CacheDrivenTask.h b/filters/page_layout/CacheDrivenTask.h index 7c5d15561..bf0b97836 100644 --- a/filters/page_layout/CacheDrivenTask.h +++ b/filters/page_layout/CacheDrivenTask.h @@ -22,6 +22,7 @@ #include "NonCopyable.h" #include "ref_countable.h" #include "intrusive_ptr.h" +#include class QRectF; class PageInfo; @@ -50,6 +51,8 @@ class CacheDrivenTask : public ref_countable { const QRectF& content_rect); private: + static QPolygonF shiftToRoundedOrigin(const QPolygonF& poly); + intrusive_ptr m_ptrNextTask; intrusive_ptr m_ptrSettings; }; diff --git a/filters/page_layout/Filter.cpp b/filters/page_layout/Filter.cpp index b84d8ad0b..4e8c9c400 100644 --- a/filters/page_layout/Filter.cpp +++ b/filters/page_layout/Filter.cpp @@ -52,9 +52,9 @@ Filter::Filter(intrusive_ptr pages, const PageSelectionAccessor& p typedef PageOrderOption::ProviderPtr ProviderPtr; const ProviderPtr default_order; - const ProviderPtr order_by_width(new OrderByWidthProvider(m_ptrSettings)); - const ProviderPtr order_by_height(new OrderByHeightProvider(m_ptrSettings)); - const ProviderPtr order_by_deviation(new OrderByDeviationProvider(m_ptrSettings->deviationProvider())); + const auto order_by_width = make_intrusive(m_ptrSettings); + const auto order_by_height = make_intrusive(m_ptrSettings); + const auto order_by_deviation = make_intrusive(m_ptrSettings->deviationProvider()); m_pageOrderOptions.emplace_back(tr("Natural order"), default_order); m_pageOrderOptions.emplace_back(tr("Order by increasing width"), order_by_width); m_pageOrderOptions.emplace_back(tr("Order by increasing height"), order_by_height); diff --git a/filters/page_layout/Task.cpp b/filters/page_layout/Task.cpp index ca4a765f1..ccedc78a7 100644 --- a/filters/page_layout/Task.cpp +++ b/filters/page_layout/Task.cpp @@ -104,15 +104,24 @@ FilterResultPtr Task::process(const TaskStatus& status, m_ptrSettings->getAggregateContentRect())); ImageTransformation new_xform(data.xform()); - new_xform.setPostCropArea(new_xform.transform().map(page_rect_phys)); + new_xform.setPostCropArea(shiftToRoundedOrigin(new_xform.transform().map(page_rect_phys))); return m_ptrNextTask->process(status, FilterData(data, new_xform), content_rect_phys); } else { - return FilterResultPtr(new UiUpdater(m_ptrFilter, m_ptrSettings, m_pageId, data.origImage(), data.xform(), - adapted_content_rect, agg_hard_size_before != agg_hard_size_after, - m_batchProcessing)); + return make_intrusive(m_ptrFilter, m_ptrSettings, m_pageId, data.origImage(), data.xform(), + adapted_content_rect, agg_hard_size_before != agg_hard_size_after, + m_batchProcessing); } -} // Task::process +} + +QPolygonF Task::shiftToRoundedOrigin(const QPolygonF& poly) { + const double x = poly.boundingRect().left(); + const double y = poly.boundingRect().top(); + const double shift_value_x = -(x - std::round(x)); + const double shift_value_y = -(y - std::round(y)); + + return poly.translated(shift_value_x, shift_value_y); +} /*============================ Task::UiUpdater ==========================*/ diff --git a/filters/page_layout/Task.h b/filters/page_layout/Task.h index 48f86a041..7d742dc99 100644 --- a/filters/page_layout/Task.h +++ b/filters/page_layout/Task.h @@ -23,6 +23,7 @@ #include "ref_countable.h" #include "FilterResult.h" #include "PageId.h" +#include class TaskStatus; class FilterData; @@ -59,7 +60,7 @@ class Task : public ref_countable { private: class UiUpdater; - void loadDefaultSettings(const Dpi& dpi); + static QPolygonF shiftToRoundedOrigin(const QPolygonF& poly); intrusive_ptr m_ptrFilter; intrusive_ptr m_ptrNextTask; diff --git a/filters/page_split/Filter.cpp b/filters/page_split/Filter.cpp index e26722656..bf49604ef 100644 --- a/filters/page_split/Filter.cpp +++ b/filters/page_split/Filter.cpp @@ -45,9 +45,9 @@ Filter::Filter(intrusive_ptr page_sequence, const PageSelectionAcc typedef PageOrderOption::ProviderPtr ProviderPtr; const ProviderPtr default_order; - const ProviderPtr order_by_splitline(new OrderBySplitTypeProvider(m_ptrSettings)); + const auto order_by_split_type = make_intrusive(m_ptrSettings); m_pageOrderOptions.emplace_back(tr("Natural order"), default_order); - m_pageOrderOptions.emplace_back(tr("Order by split type"), order_by_splitline); + m_pageOrderOptions.emplace_back(tr("Order by split type"), order_by_split_type); } Filter::~Filter() = default; diff --git a/filters/page_split/PageLayoutEstimator.cpp b/filters/page_split/PageLayoutEstimator.cpp index 9b10a8424..ce916c1ff 100644 --- a/filters/page_split/PageLayoutEstimator.cpp +++ b/filters/page_split/PageLayoutEstimator.cpp @@ -98,14 +98,14 @@ std::unique_ptr autoDetectSinglePageLayout(const LayoutType layout_t if (!ltr_lines.empty()) { const QLineF& first_line = ltr_lines.front(); const double line_center = lineCenterX(first_line); - if (fabs(image_center - line_center) > 0.65 * image_center) { + if (std::fabs(image_center - line_center) > 0.65 * image_center) { break; } } if (ltr_lines.size() > 1) { const QLineF& last_line = ltr_lines.back(); const double line_center = lineCenterX(last_line); - if (fabs(image_center - line_center) > 0.65 * image_center) { + if (std::fabs(image_center - line_center) > 0.65 * image_center) { break; } } @@ -157,7 +157,7 @@ std::unique_ptr autoDetectTwoPageLayout(const std::vector& l const QLineF* best_line = nullptr; for (const QLineF& line : ltr_lines) { const double line_center = lineCenterX(line); - const double distance = fabs(line_center - image_center); + const double distance = std::fabs(line_center - image_center); if (distance < min_distance) { min_distance = distance; best_line = &line; @@ -219,7 +219,7 @@ class BadTwoPageSplitter { * to be the line splitting two pages */ bool operator()(const QLineF& line) { - const double dist = fabs(lineCenterX(line) - m_imageCenter); + const double dist = std::fabs(lineCenterX(line) - m_imageCenter); return dist > m_distFromCenterThreshold; } @@ -281,8 +281,8 @@ std::unique_ptr PageLayoutEstimator::tryCutAtFoldingLine(const Layou break; } - left_dist = fabs(left_dist); - right_dist = fabs(right_dist); + left_dist = std::fabs(left_dist); + right_dist = std::fabs(right_dist); if ((left_dist < threshold) || (right_dist < threshold)) { // At least one of them is relatively close // to the center. @@ -359,9 +359,9 @@ PageLayout PageLayoutEstimator::cutAtWhitespace(const LayoutType layout_type, const int w = img.width(); const int h = img.height(); const double angle_deg = skew.angle(); - const double tg = tan(angle_deg * constants::DEG2RAD); + const double tg = std::tan(angle_deg * constants::DEG2RAD); - const auto margin = (int) ceil(fabs(0.5 * h * tg)); + const auto margin = (int) std::ceil(std::fabs(0.5 * h * tg)); const int new_width = w - margin * 2; if (new_width > 0) { hShearInPlace(img, tg, 0.5 * h, WHITE); @@ -465,15 +465,15 @@ imageproc::BinaryImage PageLayoutEstimator::to300DpiBinary(const QImage& img, const BinaryThreshold binary_threshold) { const double xfactor = (300.0 * constants::DPI2DPM) / img.dotsPerMeterX(); const double yfactor = (300.0 * constants::DPI2DPM) / img.dotsPerMeterY(); - if ((fabs(xfactor - 1.0) < 0.1) && (fabs(yfactor - 1.0) < 0.1)) { + if ((std::fabs(xfactor - 1.0) < 0.1) && (std::fabs(yfactor - 1.0) < 0.1)) { return BinaryImage(img, binary_threshold); } QTransform scale_xform; scale_xform.scale(xfactor, yfactor); xform *= scale_xform; - const QSize new_size(std::max(1, (int) ceil(xfactor * img.width())), - std::max(1, (int) ceil(yfactor * img.height()))); + const QSize new_size(std::max(1, (int) std::ceil(xfactor * img.width())), + std::max(1, (int) std::ceil(yfactor * img.height()))); const GrayImage new_image(scaleToGray(GrayImage(img), new_size)); @@ -772,7 +772,7 @@ PageLayout PageLayoutEstimator::processTwoPagesWithSingleSpan(const Span& span, const double page_center = 0.5 * width; const double box_center = span.center(); const double box_half_width = 0.5 * span.width(); - const double distance_to_page_center = fabs(page_center - box_center) - box_half_width; + const double distance_to_page_center = std::fabs(page_center - box_center) - box_half_width; double x; diff --git a/filters/page_split/Task.cpp b/filters/page_split/Task.cpp index e24e04a54..7760b7075 100644 --- a/filters/page_split/Task.cpp +++ b/filters/page_split/Task.cpp @@ -204,8 +204,8 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data) return m_ptrNextTask->process(status, FilterData(data, new_xform)); } - return FilterResultPtr(new UiUpdater(m_ptrFilter, m_ptrPages, std::move(m_ptrDbg), data.origImage(), m_pageInfo, - data.xform(), ui_data, m_batchProcessing)); + return make_intrusive(m_ptrFilter, m_ptrPages, std::move(m_ptrDbg), data.origImage(), m_pageInfo, + data.xform(), ui_data, m_batchProcessing); } // Task::process /*============================ Task::UiUpdater =========================*/ diff --git a/filters/page_split/VertLineFinder.cpp b/filters/page_split/VertLineFinder.cpp index ee405df5f..7dbf30b72 100644 --- a/filters/page_split/VertLineFinder.cpp +++ b/filters/page_split/VertLineFinder.cpp @@ -123,7 +123,7 @@ std::vector VertLineFinder::findLines(const QImage& image, // We don't want to process areas too close to the vertical edges. const double margin_mm = 3.5; - const auto margin = (int) floor(0.5 + margin_mm * constants::MM2INCH * dpi); + const auto margin = (int) std::floor(0.5 + margin_mm * constants::MM2INCH * dpi); const int x_limit = raster_lines.width() - margin; const int height = raster_lines.height(); diff --git a/filters/select_content/ContentBoxFinder.cpp b/filters/select_content/ContentBoxFinder.cpp index 207af7fff..559856123 100644 --- a/filters/select_content/ContentBoxFinder.cpp +++ b/filters/select_content/ContentBoxFinder.cpp @@ -92,11 +92,10 @@ QRectF ContentBoxFinder::findContentBox(const TaskStatus& status, return QRectF(); } - const GrayImage dataGrayImage = data.isBlackOnWhite() ? data.grayImage() : data.grayImage().inverted(); - const uint8_t darkest_gray_level = darkestGrayLevel(dataGrayImage); + const uint8_t darkest_gray_level = darkestGrayLevel(data.grayImage()); const QColor outside_color(darkest_gray_level, darkest_gray_level, darkest_gray_level); - QImage gray150(transformToGray(dataGrayImage, xform_150dpi.transform(), xform_150dpi.resultingRect().toRect(), + QImage gray150(transformToGray(data.grayImage(), xform_150dpi.transform(), xform_150dpi.resultingRect().toRect(), OutsidePixels::assumeColor(outside_color))); // Note that we fill new areas that appear as a result of // rotation with black, not white. Filling them with white @@ -830,7 +829,7 @@ imageproc::BinaryImage ContentBoxFinder::estimateTextMask(const imageproc::Binar } // Extend the top and bottom of the text line. - while ((top > first || bottom < last) && abs((center_y - top) - (bottom - center_y)) <= 1) { + while ((top > first || bottom < last) && std::abs((center_y - top) - (bottom - center_y)) <= 1) { const int new_top = (top > first) ? top - 1 : top; const int new_bottom = (bottom < last) ? bottom + 1 : bottom; num_black += hist[new_top] + hist[new_bottom]; @@ -1149,8 +1148,8 @@ QRect ContentBoxFinder::trim(const imageproc::BinaryImage& content, double text_influence = max_text_influence; if (num_text_pixels < upper_threshold) { text_influence = min_text_influence - + (max_text_influence - min_text_influence) * log((double) num_text_pixels) - / log((double) upper_threshold); + + (max_text_influence - min_text_influence) * std::log((double) num_text_pixels) + / std::log((double) upper_threshold); } // qDebug() << "text_influence = " << text_influence; @@ -1183,8 +1182,8 @@ QRect ContentBoxFinder::trim(const imageproc::BinaryImage& content, for (int y = removed_area.top(); y <= removed_area.bottom(); ++y) { for (int x = removed_area.left(); x <= removed_area.right(); ++x) { if (cb_line[x >> 5] & (msb >> (x & 31))) { - sum_dist_to_garbage += sqrt((double) dm_garbage_line[x]); - sum_dist_to_others += sqrt((double) dm_others_line[x]); + sum_dist_to_garbage += std::sqrt((double) dm_garbage_line[x]); + sum_dist_to_others += std::sqrt((double) dm_others_line[x]); ++count; } } diff --git a/filters/select_content/Filter.cpp b/filters/select_content/Filter.cpp index daeee0b0d..83461d6c2 100644 --- a/filters/select_content/Filter.cpp +++ b/filters/select_content/Filter.cpp @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include namespace select_content { Filter::Filter(const PageSelectionAccessor& page_selection_accessor) @@ -46,9 +49,9 @@ Filter::Filter(const PageSelectionAccessor& page_selection_accessor) typedef PageOrderOption::ProviderPtr ProviderPtr; const ProviderPtr default_order; - const ProviderPtr order_by_width(new OrderByWidthProvider(m_ptrSettings)); - const ProviderPtr order_by_height(new OrderByHeightProvider(m_ptrSettings)); - const ProviderPtr order_by_deviation(new OrderByDeviationProvider(m_ptrSettings->deviationProvider())); + const auto order_by_width = make_intrusive(m_ptrSettings); + const auto order_by_height = make_intrusive(m_ptrSettings); + const auto order_by_deviation = make_intrusive(m_ptrSettings->deviationProvider()); m_pageOrderOptions.emplace_back(tr("Natural order"), default_order); m_pageOrderOptions.emplace_back(tr("Order by increasing width"), order_by_width); m_pageOrderOptions.emplace_back(tr("Order by increasing height"), order_by_height); @@ -90,9 +93,8 @@ void Filter::preUpdateUI(FilterUiInterface* ui, const PageInfo& page_info) { QDomElement Filter::saveSettings(const ProjectWriter& writer, QDomDocument& doc) const { QDomElement filter_el(doc.createElement("select-content")); - filter_el.setAttribute("pageDetectionBoxWidth", m_ptrSettings->pageDetectionBox().width()); - filter_el.setAttribute("pageDetectionBoxHeight", m_ptrSettings->pageDetectionBox().height()); - filter_el.setAttribute("pageDetectionTolerance", m_ptrSettings->pageDetectionTolerance()); + filter_el.appendChild(XmlMarshaller(doc).sizeF(m_ptrSettings->pageDetectionBox(), "page-detection-box")); + filter_el.setAttribute("pageDetectionTolerance", Utils::doubleToString(m_ptrSettings->pageDetectionTolerance())); writer.enumPages([&](const PageId& page_id, int numeric_id) { this->writePageSettings(doc, filter_el, page_id, numeric_id); @@ -119,11 +121,7 @@ void Filter::loadSettings(const ProjectReader& reader, const QDomElement& filter const QDomElement filter_el(filters_el.namedItem("select-content").toElement()); - QSizeF box(0.0, 0.0); - box.setWidth(filter_el.attribute("pageDetectionBoxWidth", "0.0").toDouble()); - box.setHeight(filter_el.attribute("pageDetectionBoxHeight", "0.0").toDouble()); - m_ptrSettings->setPageDetectionBox(box); - + m_ptrSettings->setPageDetectionBox(XmlUnmarshaller::sizeF(filter_el.namedItem("page-detection-box").toElement())); m_ptrSettings->setPageDetectionTolerance(filter_el.attribute("pageDetectionTolerance", "0.1").toDouble()); const QString page_tag_name("page"); diff --git a/filters/select_content/PageFinder.cpp b/filters/select_content/PageFinder.cpp index 6fd5e829b..7332136b4 100644 --- a/filters/select_content/PageFinder.cpp +++ b/filters/select_content/PageFinder.cpp @@ -55,11 +55,10 @@ QRectF PageFinder::findPageBox(const TaskStatus& status, std::cout << "exp_width = " << exp_width << "; exp_height" << exp_height << std::endl; #endif - const GrayImage dataGrayImage = data.isBlackOnWhite() ? data.grayImage() : data.grayImage().inverted(); - const uint8_t darkest_gray_level = darkestGrayLevel(dataGrayImage); + const uint8_t darkest_gray_level = darkestGrayLevel(data.grayImage()); const QColor outside_color(darkest_gray_level, darkest_gray_level, darkest_gray_level); - QImage gray150(transformToGray(dataGrayImage, xform_150dpi.transform(), xform_150dpi.resultingRect().toRect(), + QImage gray150(transformToGray(data.grayImage(), xform_150dpi.transform(), xform_150dpi.resultingRect().toRect(), OutsidePixels::assumeColor(outside_color))); if (dbg) { dbg->add(gray150, "gray150"); @@ -104,8 +103,8 @@ QRectF PageFinder::findPageBox(const TaskStatus& status, std::cout << "width = " << rects[i].width() << "; height=" << rects[i].height() << std::endl; #endif - double err_w = double(abs(exp_width - rects[i].width())) / double(exp_width); - double err_h = double(abs(exp_height - rects[i].height())) / double(exp_height); + double err_w = double(std::abs(exp_width - rects[i].width())) / double(exp_width); + double err_h = double(std::abs(exp_height - rects[i].height())) / double(exp_height); #ifdef DEBUG std::cout << "err_w=" << err_w << "; err_h" << err_h << std::endl; #endif @@ -227,8 +226,8 @@ bool PageFinder::fineTuneCorner(const QImage& img, int pixel = img.pixelIndex(x, y); int tx = x + inc_x; int ty = y + inc_y; - int w = abs(max_x - x); - int h = abs(max_y - y); + int w = std::abs(max_x - x); + int h = std::abs(max_y - y); if ((!size.isEmpty()) && ((w < width_t) || (h < height_t))) { return true; diff --git a/filters/select_content/Task.cpp b/filters/select_content/Task.cpp index 6eafdaf95..4ba6b0581 100644 --- a/filters/select_content/Task.cpp +++ b/filters/select_content/Task.cpp @@ -186,9 +186,8 @@ FilterResultPtr Task::process(const TaskStatus& status, const FilterData& data) return m_ptrNextTask->process(status, FilterData(data, data.xform()), ui_data.pageRect(), ui_data.contentRect()); } else { - return FilterResultPtr(new UiUpdater(m_ptrFilter, m_pageId, std::move(m_ptrDbg), data.origImage(), data.xform(), - data.isBlackOnWhite() ? data.grayImage() : data.grayImage().inverted(), - ui_data, m_batchProcessing)); + return make_intrusive(m_ptrFilter, m_pageId, std::move(m_ptrDbg), data.origImage(), data.xform(), + data.grayImage(), ui_data, m_batchProcessing); } } // Task::process diff --git a/filters/select_content/Task.h b/filters/select_content/Task.h index f52ca54ba..e6162b32b 100644 --- a/filters/select_content/Task.h +++ b/filters/select_content/Task.h @@ -59,8 +59,6 @@ class Task : public ref_countable { private: class UiUpdater; - void loadDefaultSettings(const Dpi& dpi); - intrusive_ptr m_ptrFilter; intrusive_ptr m_ptrNextTask; intrusive_ptr m_ptrSettings; diff --git a/foundation/GridLineTraverser.cpp b/foundation/GridLineTraverser.cpp index 16ed1e573..cca5205fa 100644 --- a/foundation/GridLineTraverser.cpp +++ b/foundation/GridLineTraverser.cpp @@ -24,7 +24,7 @@ GridLineTraverser::GridLineTraverser(const QLineF& line) { const QPoint p2(line.p2().toPoint()); int h_spans, v_spans, num_spans; double s1 = 0.0, s2 = 0.0; - if ((h_spans = abs(p1.x() - p2.x())) > (v_spans = abs(p1.y() - p2.y()))) { + if ((h_spans = std::abs(p1.x() - p2.x())) > (v_spans = std::abs(p1.y() - p2.y()))) { // Major direction: horizontal. num_spans = h_spans; lineIntersectionScalar(line, QLineF(p1, QPoint(p1.x(), p1.y() + 1)), s1); diff --git a/foundation/Proximity.h b/foundation/Proximity.h index 87a923ba2..300a8a175 100644 --- a/foundation/Proximity.h +++ b/foundation/Proximity.h @@ -43,7 +43,7 @@ class Proximity { static Proximity pointAndLineSegment(const QPointF& pt, const QLineF& segment, QPointF* point_on_segment = nullptr); double dist() const { - return sqrt(m_sqDist); + return std::sqrt(m_sqDist); } double sqDist() const { diff --git a/foundation/ValueConv.h b/foundation/ValueConv.h index a4d4e84ac..0aac063d3 100644 --- a/foundation/ValueConv.h +++ b/foundation/ValueConv.h @@ -50,7 +50,7 @@ class RoundAndClipValueConv { } else if (val > FromType(m_max)) { return m_max; } else { - return static_cast(floor(val + 0.5)); + return static_cast(std::floor(val + 0.5)); } } diff --git a/foundation/VirtualFunction.h b/foundation/VirtualFunction.h index 256dc6c11..adc29a8c0 100644 --- a/foundation/VirtualFunction.h +++ b/foundation/VirtualFunction.h @@ -19,74 +19,26 @@ #ifndef VIRTUALFUNCTION_H_ #define VIRTUALFUNCTION_H_ -template -class VirtualFunction1 { -public: - virtual ~VirtualFunction1() { - } - - virtual R operator()(A1 arg1) = 0; -}; - - -template -class ProxyFunction1 : public VirtualFunction1 { -public: - explicit ProxyFunction1(Delegate delegate) : m_delegate(delegate) { - } - - virtual R operator()(A1 arg1) { - return m_delegate(arg1); - } - -private: - Delegate m_delegate; -}; - - -template -class VirtualFunction2 { -public: - virtual ~VirtualFunction2() { - } - - virtual R operator()(A1 arg1, A2 arg2) = 0; -}; - - -template -class ProxyFunction2 : public VirtualFunction2 { -public: - explicit ProxyFunction2(Delegate delegate) : m_delegate(delegate) { - } - - virtual R operator()(A1 arg1, A2 arg2) { - return m_delegate(arg1, arg2); - } - -private: - Delegate m_delegate; -}; - +#include -template -class VirtualFunction3 { +template +class VirtualFunction { public: - virtual ~VirtualFunction3() { + virtual ~VirtualFunction() { } - virtual R operator()(A1 arg1, A2 arg2, A3 arg3) = 0; + virtual Res operator()(ArgTypes... args) const = 0; }; -template -class ProxyFunction3 : public VirtualFunction3 { +template +class ProxyFunction : public VirtualFunction { public: - explicit ProxyFunction3(Delegate delegate) : m_delegate(delegate) { + explicit ProxyFunction(Delegate delegate) : m_delegate(delegate) { } - virtual R operator()(A1 arg1, A2 arg2, A3 arg3) { - return m_delegate(arg1, arg2, arg3); + Res operator()(ArgTypes... args) const override { + return m_delegate(args...); } private: diff --git a/imageproc/BackgroundColorCalculator.cpp b/imageproc/BackgroundColorCalculator.cpp index fa10a32b7..e74d41114 100644 --- a/imageproc/BackgroundColorCalculator.cpp +++ b/imageproc/BackgroundColorCalculator.cpp @@ -7,6 +7,7 @@ #include "RasterOp.h" #include "PolygonRasterizer.h" #include "Morphology.h" +#include "DebugImages.h" namespace imageproc { @@ -120,6 +121,16 @@ void grayHistToArray(int* raw_hist, GrayscaleHistogram hist) { raw_hist[i] = hist[i]; } } + +void checkImageIsValid(const QImage& img) { + if (!((img.format() == QImage::Format_RGB32) || (img.format() == QImage::Format_ARGB32) + || ((img.format() == QImage::Format_Indexed8) && img.isGrayscale()))) { + throw std::invalid_argument("BackgroundColorCalculator: wrong image format"); + } + if (img.isNull()) { + throw std::invalid_argument("BackgroundColorCalculator: image is null."); + } +} } // namespace uint8_t BackgroundColorCalculator::calcDominantLevel(const int* hist) { @@ -156,80 +167,42 @@ uint8_t BackgroundColorCalculator::calcDominantLevel(const int* hist) { } // BackgroundColorCalculator::calcDominantLevel QColor BackgroundColorCalculator::calcDominantBackgroundColor(const QImage& img) { - if (!((img.format() == QImage::Format_RGB32) || (img.format() == QImage::Format_ARGB32) - || ((img.format() == QImage::Format_Indexed8) && img.isGrayscale()))) { - throw std::invalid_argument("BackgroundColorCalculator: wrong image format"); - } - if (img.isNull()) { - throw std::invalid_argument("BackgroundColorCalculator: image is null."); - } + checkImageIsValid(img); BinaryImage background_mask(img, BinaryThreshold::otsuThreshold(img)); - if (2 * background_mask.countBlackPixels() < background_mask.width() * background_mask.height()) { + if (2 * background_mask.countBlackPixels() <= (background_mask.width() * background_mask.height())) { background_mask.invert(); } - if (img.format() == QImage::Format_Indexed8) { - const GrayscaleHistogram hist(img, background_mask); - int raw_hist[256]; - grayHistToArray(raw_hist, hist); - uint8_t dominant_gray = calcDominantLevel(raw_hist); - - return QColor(dominant_gray, dominant_gray, dominant_gray); - } else { - const RgbHistogram hist(img, background_mask); - uint8_t dominant_red = calcDominantLevel(hist.redChannel()); - uint8_t dominant_green = calcDominantLevel(hist.greenChannel()); - uint8_t dominant_blue = calcDominantLevel(hist.blueChannel()); - - return QColor(dominant_red, dominant_green, dominant_blue); - } + return calcDominantColor(img, background_mask); } -QColor BackgroundColorCalculator::calcDominantBackgroundColor(const QImage& img, const BinaryImage& mask) { - if (!((img.format() == QImage::Format_RGB32) || (img.format() == QImage::Format_ARGB32) - || ((img.format() == QImage::Format_Indexed8) && img.isGrayscale()))) { - throw std::invalid_argument("BackgroundColorCalculator: wrong image format"); - } - if (img.isNull()) { - throw std::invalid_argument("BackgroundColorCalculator: image is null."); - } +QColor BackgroundColorCalculator::calcDominantBackgroundColor(const QImage& img, + const BinaryImage& mask, + DebugImages* dbg) { + checkImageIsValid(img); + if (img.size() != mask.size()) { throw std::invalid_argument("BackgroundColorCalculator: img and mask have different sizes"); } BinaryImage background_mask(img, BinaryThreshold::otsuThreshold(GrayscaleHistogram(img, mask))); - rasterOp>(background_mask, mask); if (2 * background_mask.countBlackPixels() <= mask.countBlackPixels()) { background_mask.invert(); - rasterOp>(background_mask, mask); } - - if ((img.format() == QImage::Format_Indexed8) && img.isGrayscale()) { - const GrayscaleHistogram hist(img, background_mask); - int raw_hist[256]; - grayHistToArray(raw_hist, hist); - uint8_t dominant_gray = calcDominantLevel(raw_hist); - - return QColor(dominant_gray, dominant_gray, dominant_gray); - } else { - const RgbHistogram hist(img, background_mask); - uint8_t dominant_red = calcDominantLevel(hist.redChannel()); - uint8_t dominant_green = calcDominantLevel(hist.greenChannel()); - uint8_t dominant_blue = calcDominantLevel(hist.blueChannel()); - - return QColor(dominant_red, dominant_green, dominant_blue); + rasterOp>(background_mask, mask); + if (dbg) { + dbg->add(background_mask, "background_mask"); } + + return calcDominantColor(img, background_mask); } -QColor BackgroundColorCalculator::calcDominantBackgroundColor(const QImage& img, const QPolygonF& crop_area) { - if (!((img.format() == QImage::Format_RGB32) || (img.format() == QImage::Format_ARGB32) - || ((img.format() == QImage::Format_Indexed8) && img.isGrayscale()))) { - throw std::invalid_argument("BackgroundColorCalculator: wrong image format"); - } - if (img.isNull()) { - throw std::invalid_argument("BackgroundColorCalculator: image is null."); - } +QColor BackgroundColorCalculator::calcDominantBackgroundColor(const QImage& img, + const QPolygonF& crop_area, + DebugImages* dbg) { + checkImageIsValid(img); + if (crop_area.intersected(QRectF(img.rect())).isEmpty()) { throw std::invalid_argument("BackgroundColorCalculator: the cropping area is wrong."); } @@ -237,13 +210,10 @@ QColor BackgroundColorCalculator::calcDominantBackgroundColor(const QImage& img, BinaryImage mask(img.size(), BLACK); PolygonRasterizer::fillExcept(mask, WHITE, crop_area, Qt::WindingFill); - BinaryImage background_mask(img, BinaryThreshold::otsuThreshold(GrayscaleHistogram(img, mask))); - rasterOp>(background_mask, mask); - if (2 * background_mask.countBlackPixels() <= mask.countBlackPixels()) { - background_mask.invert(); - rasterOp>(background_mask, mask); - } + return calcDominantBackgroundColor(img, mask, dbg); +} +QColor BackgroundColorCalculator::calcDominantColor(const QImage& img, const BinaryImage& background_mask) { if ((img.format() == QImage::Format_Indexed8) && img.isGrayscale()) { const GrayscaleHistogram hist(img, background_mask); int raw_hist[256]; diff --git a/imageproc/BackgroundColorCalculator.h b/imageproc/BackgroundColorCalculator.h index 1f000b882..94fc4e59c 100644 --- a/imageproc/BackgroundColorCalculator.h +++ b/imageproc/BackgroundColorCalculator.h @@ -8,6 +8,7 @@ class QImage; class QColor; class QPolygonF; +class DebugImages; namespace imageproc { class GrayscaleHistogram; @@ -17,12 +18,16 @@ class BackgroundColorCalculator { public: static QColor calcDominantBackgroundColor(const QImage& img); - static QColor calcDominantBackgroundColor(const QImage& img, const BinaryImage& mask); + static QColor calcDominantBackgroundColor(const QImage& img, const BinaryImage& mask, DebugImages* dbg = nullptr); - static QColor calcDominantBackgroundColor(const QImage& img, const QPolygonF& crop_area); + static QColor calcDominantBackgroundColor(const QImage& img, + const QPolygonF& crop_area, + DebugImages* dbg = nullptr); private: static uint8_t calcDominantLevel(const int* hist); + + static QColor calcDominantColor(const QImage& img, const BinaryImage& background_mask); }; } // namespace imageproc diff --git a/imageproc/Binarize.cpp b/imageproc/Binarize.cpp index b2ba5482f..9ef983f2b 100644 --- a/imageproc/Binarize.cpp +++ b/imageproc/Binarize.cpp @@ -91,7 +91,7 @@ BinaryImage binarizeSauvola(const QImage& src, const QSize window_size, const do const double sqmean = window_sqsum * r_area; const double variance = sqmean - mean * mean; - const double deviation = sqrt(fabs(variance)); + const double deviation = std::sqrt(std::fabs(variance)); const double threshold = mean * (1.0 + k * (deviation / 128.0 - 1.0)); @@ -176,7 +176,7 @@ BinaryImage binarizeWolf(const QImage& src, const double sqmean = window_sqsum * r_area; const double variance = sqmean - mean * mean; - const double deviation = sqrt(fabs(variance)); + const double deviation = std::sqrt(std::fabs(variance)); max_deviation = std::max(max_deviation, deviation); means[w * y + x] = (float) mean; deviations[w * y + x] = (float) deviation; diff --git a/imageproc/FindPeaksGeneric.h b/imageproc/FindPeaksGeneric.h index 83da9a389..e2093d782 100644 --- a/imageproc/FindPeaksGeneric.h +++ b/imageproc/FindPeaksGeneric.h @@ -84,7 +84,7 @@ void raiseAllButPeaks(MostSignificantSelector most_significant, * \param least_significant Same as most_significant, but the oposite operation. * \param increase_significance A functor or a pointer to a free function that * takes one argument and returns the next most significant value next - * to it. Hint: for floating point data, use the nextafter() family of + * to it. Hint: for floating point data, use the std::nextafter() family of * functions. Their generic versions are available in Boost. * \param peak_mutator A functor or a pointer to a free function that will * transform a peak value. Two typical cases would be returning diff --git a/imageproc/GaussBlur.cpp b/imageproc/GaussBlur.cpp index a0e0a08da..3f31534ac 100644 --- a/imageproc/GaussBlur.cpp +++ b/imageproc/GaussBlur.cpp @@ -33,7 +33,7 @@ void find_iir_constants(float* n_p, float* n_m, float* d_p, float* d_m, float* b * using a 4th order approximation of the gaussian operator */ - const auto div = static_cast(sqrt(2.0 * constants::PI) * std_dev); + const auto div = static_cast(std::sqrt(2.0 * constants::PI) * std_dev); const auto x0 = static_cast(-1.783 / std_dev); const auto x1 = static_cast(-1.723 / std_dev); const auto x2 = static_cast(0.6318 / std_dev); diff --git a/imageproc/HoughLineDetector.cpp b/imageproc/HoughLineDetector.cpp index 17009cf35..465a67450 100644 --- a/imageproc/HoughLineDetector.cpp +++ b/imageproc/HoughLineDetector.cpp @@ -60,7 +60,7 @@ HoughLineDetector::HoughLineDetector(const QSize& input_dimensions, double angle = start_angle + angle_delta * i; angle *= constants::DEG2RAD; - const QPointF uv(cos(angle), sin(angle)); + const QPointF uv(std::cos(angle), std::sin(angle)); for (const QPoint& p : checkpoints) { const double distance = uv.x() * p.x() + uv.y() * p.y(); max_distance = std::max(max_distance, distance); @@ -122,7 +122,7 @@ QImage HoughLineDetector::visualizeHoughSpace(const unsigned lower_bound) const hist_line = &m_histogram[0]; for (int y = 0; y < m_histHeight; ++y) { for (int x = 0; x < m_histWidth; ++x) { - const auto intensity = (unsigned) floor(hist_line[x] * 255.0 / max_value + 0.5); + const auto intensity = (unsigned) std::floor(hist_line[x] * 255.0 / max_value + 0.5); intensity_line[x] = (unsigned char) intensity; } intensity_line += intensity_bpl; diff --git a/imageproc/Morphology.cpp b/imageproc/Morphology.cpp index 7beb9bbd5..87fec7f95 100644 --- a/imageproc/Morphology.cpp +++ b/imageproc/Morphology.cpp @@ -293,7 +293,7 @@ void spreadInDirection(BinaryImage& dst, return; } - const auto first_phase_steps = (int) sqrt((double) num_steps); + const auto first_phase_steps = (int) std::sqrt((double) num_steps); BinaryImage tmp(tmp_images.retrieveOrCreate(tmp_image_size)); diff --git a/imageproc/PolygonUtils.cpp b/imageproc/PolygonUtils.cpp index ae6d7bba3..c7969e88c 100644 --- a/imageproc/PolygonUtils.cpp +++ b/imageproc/PolygonUtils.cpp @@ -45,7 +45,7 @@ class PolygonUtils::Before { static int compare(const QPointF& lhs, const QPointF& rhs) { const double dx = lhs.x() - rhs.x(); const double dy = lhs.y() - rhs.y(); - if (fabs(dx) > fabs(dy)) { + if (std::fabs(dx) > std::fabs(dy)) { if (dx < 0.0) { return -1; } else if (dx > 0.0) { @@ -112,7 +112,7 @@ QPointF PolygonUtils::roundPoint(const QPointF& p) { } double PolygonUtils::roundValue(const double val) { - return floor(val * ROUNDING_MULTIPLIER + 0.5) * ROUNDING_RECIP_MULTIPLIER; + return std::floor(val * ROUNDING_MULTIPLIER + 0.5) * ROUNDING_RECIP_MULTIPLIER; } std::vector PolygonUtils::extractAndNormalizeEdges(const QPolygonF& poly) { @@ -158,8 +158,8 @@ bool PolygonUtils::fuzzyCompareImpl(const QLineF& line1, const QLineF& line2) { } bool PolygonUtils::fuzzyCompareImpl(const QPointF& p1, const QPointF& p2) { - const double dx = fabs(p1.x() - p2.x()); - const double dy = fabs(p1.y() - p2.y()); + const double dx = std::fabs(p1.x() - p2.x()); + const double dy = std::fabs(p1.y() - p2.y()); return dx <= ROUNDING_RECIP_MULTIPLIER && dy <= ROUNDING_RECIP_MULTIPLIER; } diff --git a/imageproc/PolynomialLine.h b/imageproc/PolynomialLine.h index 6b00e499a..d4e1b90f9 100644 --- a/imageproc/PolynomialLine.h +++ b/imageproc/PolynomialLine.h @@ -135,7 +135,7 @@ PolynomialLine::RoundAndClipPostProcessor::RoundAndClipPostProcessor() template inline T PolynomialLine::RoundAndClipPostProcessor::operator()(const double val) const { - const double rounded = floor(val + 0.5); + const double rounded = std::floor(val + 0.5); if (rounded < m_min) { return m_min; } else if (rounded > m_max) { diff --git a/imageproc/RastLineFinder.cpp b/imageproc/RastLineFinder.cpp index 5b9ef446a..09f780237 100644 --- a/imageproc/RastLineFinder.cpp +++ b/imageproc/RastLineFinder.cpp @@ -99,13 +99,13 @@ RastLineFinder::RastLineFinder(const std::vector& points, const RastLin } } - const auto max_dist = static_cast(sqrt(max_sqdist) + 1.0); // + 1.0 to combant rounding issues + const auto max_dist = static_cast(std::sqrt(max_sqdist) + 1.0); // + 1.0 to combant rounding issues - double delta_deg = fmod(params.maxAngleDeg() - params.minAngleDeg(), 360.0); + double delta_deg = std::fmod(params.maxAngleDeg() - params.minAngleDeg(), 360.0); if (delta_deg < 0) { delta_deg += 360; } - const double min_angle_deg = fmod(params.minAngleDeg(), 360.0); + const double min_angle_deg = std::fmod(params.minAngleDeg(), 360.0); const double max_angle_deg = min_angle_deg + delta_deg; SearchSpace ssp(*this, -max_dist, max_dist, static_cast(min_angle_deg * constants::DEG2RAD), diff --git a/imageproc/ReduceThreshold.h b/imageproc/ReduceThreshold.h index c8cb95672..166a0c797 100644 --- a/imageproc/ReduceThreshold.h +++ b/imageproc/ReduceThreshold.h @@ -27,8 +27,8 @@ namespace imageproc { * * The dimensions of the target image will be: * \code - * dst_width = max(1, floor(src_width / 2)); - * dst_height = max(1, floor(src_height / 2)); + * dst_width = max(1, std::floor(src_width / 2)); + * dst_height = max(1, std::floor(src_height / 2)); * \endcode * \n * Processing a null image results in a null image. diff --git a/imageproc/SavGolKernel.cpp b/imageproc/SavGolKernel.cpp index 2cd34a87e..21fa04bdf 100644 --- a/imageproc/SavGolKernel.cpp +++ b/imageproc/SavGolKernel.cpp @@ -16,7 +16,7 @@ along with this program. If not, see . */ -#define _ISOC99SOURCE // For copysign() +#define _ISOC99SOURCE // For std::copysign() #include "SavGolKernel.h" #include @@ -25,10 +25,6 @@ #include #include -#ifdef _MSC_VER -#undef copysign // Just in case. -#define copysign _copysign -#endif namespace imageproc { namespace { @@ -106,17 +102,17 @@ void SavGolKernel::QR() { if (a == 0.0) { cos = 0.0; - sin = copysign(1.0, b); - m_equations[jj] = fabs(b); - } else if (fabs(b) > fabs(a)) { + sin = std::copysign(1.0, b); + m_equations[jj] = std::fabs(b); + } else if (std::fabs(b) > std::fabs(a)) { const double t = a / b; - const double u = copysign(sqrt(1.0 + t * t), b); + const double u = std::copysign(std::sqrt(1.0 + t * t), b); sin = 1.0 / u; cos = sin * t; m_equations[jj] = b * u; } else { const double t = b / a; - const double u = copysign(sqrt(1.0 + t * t), a); + const double u = std::copysign(std::sqrt(1.0 + t * t), a); cos = 1.0 / u; sin = cos * t; m_equations[jj] = a * u; diff --git a/imageproc/Shear.cpp b/imageproc/Shear.cpp index b26e2c56a..e0e0206aa 100644 --- a/imageproc/Shear.cpp +++ b/imageproc/Shear.cpp @@ -37,12 +37,12 @@ void hShearFromTo(const BinaryImage& src, const int width = src.width(); const int height = src.height(); - // shift = floor(0.5 + shear * (y + 0.5 - y_origin)); + // shift = std::floor(0.5 + shear * (y + 0.5 - y_origin)); double shift = 0.5 + shear * (0.5 - y_origin); const double shift_end = 0.5 + shear * (height - 0.5 - y_origin); - auto shift1 = (int) floor(shift); + auto shift1 = (int) std::floor(shift); - if (shift1 == floor(shift_end)) { + if (shift1 == std::floor(shift_end)) { assert(shift1 == 0); dst = src; @@ -55,10 +55,10 @@ void hShearFromTo(const BinaryImage& src, for (;;) { ++y2; shift += shear; - shift2 = (int) floor(shift); + shift2 = (int) std::floor(shift); if ((shift1 != shift2) || (y2 == height)) { const int block_height = y2 - y1; - if (abs(shift1) >= width) { + if (std::abs(shift1) >= width) { // The shifted block would be completely off the image. const QRect fr(0, y1, width, block_height); dst.fill(fr, background_color); @@ -108,12 +108,12 @@ void vShearFromTo(const BinaryImage& src, const int width = src.width(); const int height = src.height(); - // shift = floor(0.5 + shear * (x + 0.5 - x_origin)); + // shift = std::floor(0.5 + shear * (x + 0.5 - x_origin)); double shift = 0.5 + shear * (0.5 - x_origin); const double shift_end = 0.5 + shear * (width - 0.5 - x_origin); - auto shift1 = (int) floor(shift); + auto shift1 = (int) std::floor(shift); - if (shift1 == floor(shift_end)) { + if (shift1 == std::floor(shift_end)) { assert(shift1 == 0); dst = src; @@ -126,10 +126,10 @@ void vShearFromTo(const BinaryImage& src, for (;;) { ++x2; shift += shear; - shift2 = (int) floor(shift); + shift2 = (int) std::floor(shift); if ((shift1 != shift2) || (x2 == width)) { const int block_width = x2 - x1; - if (abs(shift1) >= height) { + if (std::abs(shift1) >= height) { // The shifted block would be completely off the image. const QRect fr(x1, 0, block_width, height); dst.fill(fr, background_color); diff --git a/imageproc/SkewFinder.cpp b/imageproc/SkewFinder.cpp index ef4b262c7..a95616aa0 100644 --- a/imageproc/SkewFinder.cpp +++ b/imageproc/SkewFinder.cpp @@ -178,7 +178,7 @@ Skew SkewFinder::findSkew(const BinaryImage& image) const { } // SkewFinder::findSkew double SkewFinder::process(const BinaryImage& src, BinaryImage& dst, const double angle) const { - const double tg = tan(angle * constants::DEG2RAD); + const double tg = std::tan(angle * constants::DEG2RAD); const double x_center = 0.5 * dst.width(); vShearFromTo(src, dst, tg / m_resolutionRatio, x_center, WHITE); diff --git a/imageproc/tests/TestPolygonRasterizer.cpp b/imageproc/tests/TestPolygonRasterizer.cpp index 37c4829d2..12c3763b3 100644 --- a/imageproc/tests/TestPolygonRasterizer.cpp +++ b/imageproc/tests/TestPolygonRasterizer.cpp @@ -49,10 +49,10 @@ static QPolygonF createShape(const QSize& image_size, double radius) { QPolygonF poly; - poly.push_back(center + QPointF(cos(angle), sin(angle)) * radius); + poly.push_back(center + QPointF(std::cos(angle), std::sin(angle)) * radius); for (int i = 1; i < num_steps; ++i) { angle += step * 2; - poly.push_back(center + QPointF(cos(angle), sin(angle)) * radius); + poly.push_back(center + QPointF(std::cos(angle), std::sin(angle)) * radius); } return poly; diff --git a/imageproc/tests/TestScale.cpp b/imageproc/tests/TestScale.cpp index 9f761fbc1..9c398e9b1 100644 --- a/imageproc/tests/TestScale.cpp +++ b/imageproc/tests/TestScale.cpp @@ -49,7 +49,7 @@ static bool fuzzyCompare(const QImage& img1, const QImage& img2) { for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { - if (abs(int(line1[x]) - int(line2[x])) > 1) { + if (std::abs(int(line1[x]) - int(line2[x])) > 1) { return false; } } diff --git a/imageproc/tests/TestSkewFinder.cpp b/imageproc/tests/TestSkewFinder.cpp index 383d45681..7961f655a 100644 --- a/imageproc/tests/TestSkewFinder.cpp +++ b/imageproc/tests/TestSkewFinder.cpp @@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE(test_positive_detection) { SkewFinder skew_finder; const Skew skew(skew_finder.findSkew(BinaryImage(image))); - BOOST_REQUIRE(fabs(skew.angle() - 4.5) < 0.15); + BOOST_REQUIRE(std::fabs(skew.angle() - 4.5) < 0.15); BOOST_CHECK(skew.confidence() >= Skew::GOOD_CONFIDENCE); } diff --git a/interaction/DragWatcher.cpp b/interaction/DragWatcher.cpp index 41fe2d2f4..f6ea3bc2f 100644 --- a/interaction/DragWatcher.cpp +++ b/interaction/DragWatcher.cpp @@ -36,7 +36,7 @@ bool DragWatcher::haveSignificantDrag() const { msec_passed += 60 * 60 * 24; } - const double dist_score = sqrt((double) m_dragMaxSqDist) / 12.0; + const double dist_score = std::sqrt((double) m_dragMaxSqDist) / 12.0; const double time_score = msec_passed / 500.0; return dist_score + time_score >= 1.0; diff --git a/interaction/InteractiveXSpline.cpp b/interaction/InteractiveXSpline.cpp index 854082f78..7134862c1 100644 --- a/interaction/InteractiveXSpline.cpp +++ b/interaction/InteractiveXSpline.cpp @@ -184,8 +184,8 @@ double findAngle(QPointF p1, QPointF p2) { // return angle between vector (0,0) p2 -= p1; // get angle with (1,0) - double a = p2.x() / sqrt(p2.x() * p2.x() + p2.y() * p2.y()); - return acos(a) * 180.0 / 3.14159265; + double a = p2.x() / std::sqrt(p2.x() * p2.x() + p2.y() * p2.y()); + return std::acos(a) * 180.0 / 3.14159265; } void InteractiveXSpline::controlPointMoveRequest(int idx, const QPointF& pos, Qt::KeyboardModifiers mask) { diff --git a/interaction/ZoomHandler.cpp b/interaction/ZoomHandler.cpp index bbf6ca20e..3999b554f 100644 --- a/interaction/ZoomHandler.cpp +++ b/interaction/ZoomHandler.cpp @@ -57,7 +57,7 @@ void ZoomHandler::onWheelEvent(QWheelEvent* event, InteractionState& interaction } const double degrees = event->delta() / 8.0; - zoom *= pow(2.0, degrees / 60.0); // 2 times zoom for every 60 degrees + zoom *= std::pow(2.0, degrees / 60.0); // 2 times zoom for every 60 degrees if (zoom < 1.0) { zoom = 1.0; } diff --git a/math/ArcLengthMapper.cpp b/math/ArcLengthMapper.cpp index 575d0d4c4..459e27a0d 100644 --- a/math/ArcLengthMapper.cpp +++ b/math/ArcLengthMapper.cpp @@ -38,7 +38,7 @@ void ArcLengthMapper::addSample(double x, double fx) { const double dx = x - m_samples.back().x; const double dy = fx - m_prevFX; assert(dx > 0); - arc_len = m_samples.back().arcLen + sqrt(dx * dx + dy * dy); + arc_len = m_samples.back().arcLen + std::sqrt(dx * dx + dy * dy); } m_samples.emplace_back(x, arc_len); diff --git a/math/LineIntersectionScalar.cpp b/math/LineIntersectionScalar.cpp index 80d217fa3..be9c21189 100644 --- a/math/LineIntersectionScalar.cpp +++ b/math/LineIntersectionScalar.cpp @@ -34,7 +34,7 @@ bool lineIntersectionScalar(const QLineF& line1, const QLineF& line2, double& s1 // s1 = |b -v2|/|A| // s2 = |v1 b|/|A| const double det_A = v2.x() * v1.y() - v1.x() * v2.y(); - if (fabs(det_A) < std::numeric_limits::epsilon()) { + if (std::fabs(det_A) < std::numeric_limits::epsilon()) { return false; } @@ -62,7 +62,7 @@ bool lineIntersectionScalar(const QLineF& line1, const QLineF& line2, double& s1 // s1 = |b -v2|/|A| // s2 = |v1 b|/|A| const double det_A = v2.x() * v1.y() - v1.x() * v2.y(); - if (fabs(det_A) < std::numeric_limits::epsilon()) { + if (std::fabs(det_A) < std::numeric_limits::epsilon()) { return false; } diff --git a/math/LinearSolver.h b/math/LinearSolver.h index b1b976258..91db43190 100644 --- a/math/LinearSolver.h +++ b/math/LinearSolver.h @@ -78,8 +78,8 @@ class LinearSolver { template void LinearSolver::solve(const T* A, T* X, const T* B, T* tbuffer, size_t* pbuffer) const { - using namespace std; // To catch different overloads of abs() - const T epsilon(sqrt(numeric_limits::epsilon())); + using namespace std; // To catch different overloads of std::abs() + const T epsilon(std::sqrt(numeric_limits::epsilon())); const size_t num_elements_A = m_rowsAB * m_colsArowsX; @@ -101,9 +101,9 @@ void LinearSolver::solve(const T* A, T* X, const T* B, T* tbuffer, size_t* pbuff for (size_t i = 0; i < m_colsArowsX; ++i, p_col += m_rowsAB) { // Find the largest pivot. size_t virt_pivot_row = i; - T largest_abs_pivot(abs(p_col[perm[i]])); + T largest_abs_pivot(std::abs(p_col[perm[i]])); for (size_t j = i + 1; j < m_rowsAB; ++j) { - const T abs_pivot(abs(p_col[perm[j]])); + const T abs_pivot(std::abs(p_col[perm[j]])); if (abs_pivot > largest_abs_pivot) { largest_abs_pivot = abs_pivot; virt_pivot_row = j; @@ -125,7 +125,7 @@ void LinearSolver::solve(const T* A, T* X, const T* B, T* tbuffer, size_t* pbuff for (size_t j = i + 1; j < m_rowsAB; ++j) { const T* p1 = p_pivot; T* p2 = p_col + perm[j]; - if (abs(*p2) <= epsilon) { + if (std::abs(*p2) <= epsilon) { // We consider it's already zero. *p2 = T(); continue; @@ -177,7 +177,7 @@ void LinearSolver::solve(const T* A, T* X, const T* B, T* tbuffer, size_t* pbuff right -= *p_lu * p_y_col[lu_col]; p_lu += m_rowsAB; } - if (abs(right) > epsilon) { + if (std::abs(right) > epsilon) { throw std::runtime_error("LinearSolver: inconsistent overdetermined system"); } } diff --git a/math/PolylineIntersector.cpp b/math/PolylineIntersector.cpp index 9d0066989..5851841bf 100644 --- a/math/PolylineIntersector.cpp +++ b/math/PolylineIntersector.cpp @@ -135,7 +135,7 @@ bool PolylineIntersector::tryIntersectingOutsideOfPolyline(const QLineF& line, const ToLineProjector proj(line); - if (fabs(front_dot) < fabs(back_dot)) { + if (std::fabs(front_dot) < std::fabs(back_dot)) { hint.update(-1); intersection = proj.projectionPoint(m_polyline.front()); } else { diff --git a/math/ToLineProjector.cpp b/math/ToLineProjector.cpp index 097e7c0b0..70625d758 100644 --- a/math/ToLineProjector.cpp +++ b/math/ToLineProjector.cpp @@ -24,7 +24,7 @@ ToLineProjector::ToLineProjector(const QLineF& line) : m_origin(line.p1()), m_ve // At*A*x = At*b const double AtA = m_mat.dot(m_mat); - if (abs(AtA) > numeric_limits::epsilon()) { + if (std::abs(AtA) > numeric_limits::epsilon()) { // x = (At*A)-1 * At m_mat /= AtA; } else { @@ -48,7 +48,7 @@ QPointF ToLineProjector::projectionVector(const QPointF& pt) const { } double ToLineProjector::projectionDist(const QPointF& pt) const { - return sqrt(projectionSqDist(pt)); + return std::sqrt(projectionSqDist(pt)); } double ToLineProjector::projectionSqDist(const QPointF& pt) const { diff --git a/math/XSpline.cpp b/math/XSpline.cpp index e55f3bcff..25a0f3f46 100644 --- a/math/XSpline.cpp +++ b/math/XSpline.cpp @@ -91,7 +91,8 @@ struct XSpline::DecomposedDerivs { int numControlPoints; bool hasNonZeroCoeffs(int idx) const { - double sum = fabs(zeroDerivCoeffs[idx]) + fabs(firstDerivCoeffs[idx]) + fabs(secondDerivCoeffs[idx]); + double sum = std::fabs(zeroDerivCoeffs[idx]) + std::fabs(firstDerivCoeffs[idx]) + + std::fabs(secondDerivCoeffs[idx]); return sum > std::numeric_limits::epsilon(); } @@ -157,7 +158,7 @@ QPointF XSpline::pointAt(double t) const { return pointAtImpl(num_segments - 1, 1.0); } else { const double t2 = t * num_segments; - const double segment = floor(t2); + const double segment = std::floor(t2); return pointAtImpl((int) segment, t2 - segment); } @@ -176,7 +177,7 @@ QPointF XSpline::pointAtImpl(int segment, double t) const { return pt; } -void XSpline::sample(VirtualFunction3& sink, +void XSpline::sample(const VirtualFunction& sink, const SamplingParams& params, double from_t, double to_t) const { @@ -210,7 +211,7 @@ void XSpline::sample(VirtualFunction3& sink, sink(to_pt, to_t, TAIL_SAMPLE); } // XSpline::sample -void XSpline::maybeAddMoreSamples(VirtualFunction3& sink, +void XSpline::maybeAddMoreSamples(const VirtualFunction& sink, double max_sqdist_to_spline, double max_sqdist_between_samples, double num_segments, @@ -227,7 +228,7 @@ void XSpline::maybeAddMoreSamples(VirtualFunction3 0) @@ -273,7 +274,7 @@ void XSpline::linearCombinationAt(double t, std::vector& coef num_coeffs = linearCombinationFor(static_coeffs, num_segments - 1, 1.0); } else { const double t2 = t * num_segments; - const double segment = floor(t2); + const double segment = std::floor(t2); num_coeffs = linearCombinationFor(static_coeffs, (int) segment, t2 - segment); } @@ -365,7 +366,7 @@ XSpline::DecomposedDerivs XSpline::decomposedDerivs(const double t) const { return decomposedDerivsImpl(num_segments - 1, 1.0); } else { const double t2 = t * num_segments; - const double segment = floor(t2); + const double segment = std::floor(t2); return decomposedDerivsImpl((int) segment, t2 - segment); } @@ -701,18 +702,12 @@ QPointF XSpline::pointClosestTo(const QPointF to, double accuracy) const { } std::vector XSpline::toPolyline(const SamplingParams& params, double from_t, double to_t) const { - struct Sink : public VirtualFunction3 { - std::vector polyline; + std::vector polyline; - void operator()(QPointF pt, double, SampleFlags) override { - polyline.push_back(pt); - } - }; - - Sink sink; - sample(sink, params, from_t, to_t); + auto sink = [&polyline](const QPointF& pt, double, SampleFlags) { polyline.push_back(pt); }; + sample(ProxyFunction(sink), params, from_t, to_t); - return sink.polyline; + return polyline; } double XSpline::sqDistToLine(const QPointF& pt, const QLineF& line) { @@ -841,7 +836,7 @@ double XSpline::HBlendFunc::secondDerivative(double u) const { double XSpline::PointAndDerivs::signedCurvature() const { const double cross = firstDeriv.x() * secondDeriv.y() - firstDeriv.y() * secondDeriv.x(); - double tlen = sqrt(firstDeriv.x() * firstDeriv.x() + firstDeriv.y() * firstDeriv.y()); + double tlen = std::sqrt(firstDeriv.x() * firstDeriv.x() + firstDeriv.y() * firstDeriv.y()); return cross / (tlen * tlen * tlen); } diff --git a/math/XSpline.h b/math/XSpline.h index 16e8f1af2..534b49af0 100644 --- a/math/XSpline.h +++ b/math/XSpline.h @@ -162,7 +162,7 @@ class XSpline : public spfit::FittableSpline { QPointF pointClosestTo(QPointF to, double accuracy = 0.2) const; /** \see spfit::FittableSpline::sample() */ - void sample(VirtualFunction3& sink, + void sample(const VirtualFunction& sink, const SamplingParams& params = SamplingParams(), double from_t = 0.0, double to_t = 1.0) const override; @@ -207,7 +207,7 @@ class XSpline : public spfit::FittableSpline { DecomposedDerivs decomposedDerivsImpl(int segment, double t) const; - void maybeAddMoreSamples(VirtualFunction3& sink, + void maybeAddMoreSamples(const VirtualFunction& sink, double max_sqdist_to_spline, double max_sqdist_between_samples, double num_segments, diff --git a/math/spfit/FittableSpline.h b/math/spfit/FittableSpline.h index f506fa29a..d890a200d 100644 --- a/math/spfit/FittableSpline.h +++ b/math/spfit/FittableSpline.h @@ -107,7 +107,7 @@ class FittableSpline { * corresponding to them will be marked with HEAD_SAMPLE * and TAIL_SAMPLE respectably. */ - virtual void sample(VirtualFunction3& sink, + virtual void sample(const VirtualFunction& sink, const SamplingParams& params, double from_t = 0.0, double to_t = 1.0) const = 0; diff --git a/math/spfit/FrenetFrame.cpp b/math/spfit/FrenetFrame.cpp index 804750e3b..d983db4bc 100644 --- a/math/spfit/FrenetFrame.cpp +++ b/math/spfit/FrenetFrame.cpp @@ -23,7 +23,7 @@ namespace spfit { FrenetFrame::FrenetFrame(const Vec2d& origin, const Vec2d& tangent_vector, YAxisDirection ydir) : m_origin(origin) { const double sqlen = tangent_vector.squaredNorm(); if (sqlen > 1e-6) { - m_unitTangent = tangent_vector / sqrt(sqlen); + m_unitTangent = tangent_vector / std::sqrt(sqlen); if (ydir == Y_POINTS_UP) { m_unitNormal[0] = -m_unitTangent[1]; m_unitNormal[1] = m_unitTangent[0]; diff --git a/math/spfit/LinearForceBalancer.cpp b/math/spfit/LinearForceBalancer.cpp index f3747793a..f3e5b6376 100644 --- a/math/spfit/LinearForceBalancer.cpp +++ b/math/spfit/LinearForceBalancer.cpp @@ -46,7 +46,7 @@ double LinearForceBalancer::calcInternalForceWeight(double internal_force, doubl // (internal * lambda) / external = ratio // internal * lambda = external * ratio double lambda = 0; - if (fabs(internal_force) > 1e-6) { + if (std::fabs(internal_force) > 1e-6) { lambda = m_currentRatio * external_force / internal_force; } diff --git a/math/spfit/SplineFitter.cpp b/math/spfit/SplineFitter.cpp index e624417e9..09c1cb58e 100644 --- a/math/spfit/SplineFitter.cpp +++ b/math/spfit/SplineFitter.cpp @@ -110,26 +110,16 @@ void SplineFitter::addAttractionForce(const Vec2d& spline_point, } // SplineFitter::addAttractionForce void SplineFitter::addAttractionForces(const ModelShape& model_shape, double from_t, double to_t) { - class SampleProcessor : public VirtualFunction3 { - public: - SampleProcessor(SplineFitter& owner, const ModelShape& model_shape) - : m_rOwner(owner), m_rModelShape(model_shape) { - } - - void operator()(QPointF pt, double t, FittableSpline::SampleFlags flags) override { - m_rOwner.m_pSpline->linearCombinationAt(t, m_rOwner.m_tempCoeffs); - const SqDistApproximant approx(m_rModelShape.localSqDistApproximant(pt, flags)); - m_rOwner.addAttractionForce(pt, m_rOwner.m_tempCoeffs, approx); - } - - private: - SplineFitter& m_rOwner; - const ModelShape& m_rModelShape; + auto sample_processor = [this, &model_shape](const QPointF& pt, double t, FittableSpline::SampleFlags flags) { + m_pSpline->linearCombinationAt(t, m_tempCoeffs); + const SqDistApproximant approx(model_shape.localSqDistApproximant(pt, flags)); + addAttractionForce(pt, m_tempCoeffs, approx); }; - - SampleProcessor sample_processor(*this, model_shape); - m_pSpline->sample(sample_processor, m_samplingParams, from_t, to_t); + m_pSpline->sample( + ProxyFunction( + sample_processor), + m_samplingParams, from_t, to_t); } void SplineFitter::addExternalForce(const QuadraticFunction& force) { diff --git a/math/spfit/SqDistApproximant.cpp b/math/spfit/SqDistApproximant.cpp index ebd6506d3..5b666e46f 100644 --- a/math/spfit/SqDistApproximant.cpp +++ b/math/spfit/SqDistApproximant.cpp @@ -22,9 +22,9 @@ namespace spfit { SqDistApproximant::SqDistApproximant(const Vec2d& origin, const Vec2d& u, const Vec2d& v, double m, double n) { - assert(fabs(u.squaredNorm() - 1.0) < 1e-06 && "u is not normalized"); - assert(fabs(v.squaredNorm() - 1.0) < 1e-06 && "v is not normalized"); - assert(fabs(u.dot(v)) < 1e-06 && "u and v are not orthogonal"); + assert(std::fabs(u.squaredNorm() - 1.0) < 1e-06 && "u is not normalized"); + assert(std::fabs(v.squaredNorm() - 1.0) < 1e-06 && "v is not normalized"); + assert(std::fabs(u.dot(v)) < 1e-06 && "u and v are not orthogonal"); // Consider the following equation: // w = R*x + t @@ -69,7 +69,7 @@ SqDistApproximant SqDistApproximant::weightedLineDistance(const QLineF& line, do Vec2d u(line.p2() - line.p1()); const double sqlen = u.squaredNorm(); if (sqlen > 1e-6) { - u /= sqrt(sqlen); + u /= std::sqrt(sqlen); } else { return pointDistance(line.p1()); } @@ -90,13 +90,13 @@ SqDistApproximant SqDistApproximant::weightedCurveDistance(const Vec2d& referenc const FrenetFrame& frenet_frame, const double signed_curvature, const double weight) { - const double abs_curvature = fabs(signed_curvature); + const double abs_curvature = std::fabs(signed_curvature); double m = 0; if (abs_curvature > std::numeric_limits::epsilon()) { const Vec2d to_reference_point(reference_point - frenet_frame.origin()); const double p = 1.0 / abs_curvature; - const double d = fabs(frenet_frame.unitNormal().dot(to_reference_point)); + const double d = std::fabs(frenet_frame.unitNormal().dot(to_reference_point)); m = d / (d + p); // Formula 7 in [2]. } diff --git a/math/spfit/tests/TestSqDistApproximant.cpp b/math/spfit/tests/TestSqDistApproximant.cpp index e39d8fc3e..0457619b0 100644 --- a/math/spfit/tests/TestSqDistApproximant.cpp +++ b/math/spfit/tests/TestSqDistApproximant.cpp @@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE(test_line_distance) { for (int i = 0; i < 100; ++i) { const Vec2d pt1(frand(-50, 50), frand(-50, 50)); const double angle = frand(0, 2.0 * PI); - const Vec2d delta(cos(angle), sin(angle)); + const Vec2d delta(std::cos(angle), std::sin(angle)); const QLineF line(pt1, pt1 + delta); const SqDistApproximant approx(SqDistApproximant::lineDistance(line)); const ToLineProjector proj(line); @@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE(test_general_case) { for (int i = 0; i < 100; ++i) { const Vec2d origin(frand(-50, 50), frand(-50, 50)); const double angle = frand(0, 2.0 * PI); - const Vec2d u(cos(angle), sin(angle)); + const Vec2d u(std::cos(angle), std::sin(angle)); Vec2d v(-u[1], u[0]); if (rand() & 1) { v = -v; diff --git a/version.h b/version.h index a1babed11..e3243c85a 100644 --- a/version.h +++ b/version.h @@ -19,7 +19,7 @@ #ifndef SCANTAILOR_VERSION_H_ #define SCANTAILOR_VERSION_H_ -#define VERSION "1.0.13" +#define VERSION "1.0.14" #define VERSION_QUAD "" // Must be "x.x.x.x" or an empty string. #define PROJECT_VERSION 2 diff --git a/zones/SplineVertex.cpp b/zones/SplineVertex.cpp index 7e7a8def0..5059d1fb8 100644 --- a/zones/SplineVertex.cpp +++ b/zones/SplineVertex.cpp @@ -60,7 +60,7 @@ SplineVertex::Ptr SplineVertex::next(const Loop loop) { } SplineVertex::Ptr SplineVertex::insertBefore(const QPointF& pt) { - SplineVertex::Ptr new_vertex(new RealSplineVertex(pt, m_pPrev, this)); + auto new_vertex = make_intrusive(pt, m_pPrev, this); m_pPrev->m_ptrNext = new_vertex; m_pPrev = new_vertex.get(); @@ -68,7 +68,7 @@ SplineVertex::Ptr SplineVertex::insertBefore(const QPointF& pt) { } SplineVertex::Ptr SplineVertex::insertAfter(const QPointF& pt) { - SplineVertex::Ptr new_vertex(new RealSplineVertex(pt, this, m_ptrNext.get())); + auto new_vertex = make_intrusive(pt, this, m_ptrNext.get()); m_ptrNext->m_pPrev = new_vertex.get(); m_ptrNext = new_vertex; diff --git a/zones/ZoneDefaultInteraction.cpp b/zones/ZoneDefaultInteraction.cpp index 5096e2d9f..557067e1e 100644 --- a/zones/ZoneDefaultInteraction.cpp +++ b/zones/ZoneDefaultInteraction.cpp @@ -205,7 +205,7 @@ void ZoneDefaultInteraction::onMousePressEvent(QMouseEvent* event, InteractionSt delete this; event->accept(); } else if (interaction.proximityLeader(m_zoneAreaDragCopyProximity)) { - EditableSpline::Ptr new_spline(new EditableSpline(SerializableSpline(*m_ptrUnderCursorSpline))); + auto new_spline = make_intrusive(SerializableSpline(*m_ptrUnderCursorSpline)); m_rContext.zones().addZone(new_spline, *m_rContext.zones().propertiesFor(m_ptrUnderCursorSpline)); makePeerPreceeder(*m_rContext.createZoneDragInteraction(interaction, new_spline)); delete this; @@ -238,7 +238,7 @@ void ZoneDefaultInteraction::onMouseReleaseEvent(QMouseEvent* event, Interaction serializable_spline = serializable_spline.transformed(QTransform().translate(shift.x(), shift.y())); - EditableSpline::Ptr new_spline(new EditableSpline(serializable_spline)); + auto new_spline = make_intrusive(serializable_spline); m_rContext.zones().addZone(new_spline, *(*latest_zone).properties()); m_rContext.zones().commit(); } diff --git a/zones/ZoneVertexDragInteraction.cpp b/zones/ZoneVertexDragInteraction.cpp index 05b5fafca..c68e8b14d 100644 --- a/zones/ZoneVertexDragInteraction.cpp +++ b/zones/ZoneVertexDragInteraction.cpp @@ -118,14 +118,17 @@ void ZoneVertexDragInteraction::onMouseMoveEvent(QMouseEvent* event, Interaction QPointF next = to_screen.map(m_ptrVertex->next(SplineVertex::LOOP)->point()); if (!((current == prev) && (current == next))) { - double prev_angle_cos = abs((prev.x() - current.x()) - / sqrt(pow((prev.y() - current.y()), 2) + pow((prev.x() - current.x()), 2))); - double next_angle_cos = abs((next.x() - current.x()) - / sqrt(pow((next.y() - current.y()), 2) + pow((next.x() - current.x()), 2))); + double prev_angle_cos = std::abs( + (prev.x() - current.x()) + / std::sqrt(std::pow((prev.y() - current.y()), 2) + std::pow((prev.x() - current.x()), 2))); + double next_angle_cos = std::abs( + (next.x() - current.x()) + / std::sqrt(std::pow((next.y() - current.y()), 2) + std::pow((next.x() - current.x()), 2))); - if ((prev_angle_cos < next_angle_cos) || (std::isnan(prev_angle_cos) && (next_angle_cos > (1.0 / sqrt(2)))) - || (std::isnan(next_angle_cos) && (prev_angle_cos < (1.0 / sqrt(2))))) { + if ((prev_angle_cos < next_angle_cos) + || (std::isnan(prev_angle_cos) && (next_angle_cos > (1.0 / std::sqrt(2)))) + || (std::isnan(next_angle_cos) && (prev_angle_cos < (1.0 / std::sqrt(2))))) { prev.setX(current.x()); next.setY(current.y()); } else {