File indexing completed on 2024-05-12 04:44:33

0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT
0003 
0004 // Own header
0005 #include "interlacingpass.h"
0006 
0007 #include "helpermath.h"
0008 #include <qglobal.h>
0009 #include <qmath.h>
0010 #include <type_traits>
0011 
0012 namespace PerceptualColor
0013 {
0014 /** @brief Constructor
0015  *
0016  * Constructs an object for a new interlacing cycle.
0017  *
0018  * @param passCount Number of passes within this interlacing cycle. This MUST
0019  * be a positive odd number (otherwise an exception is thrown). Use <tt>7</tt>
0020  * for <a href="https://en.wikipedia.org/wiki/Adam7_algorithm">Adam7</a>
0021  * interlacing, or any other positive odd number for
0022  * <a href="https://en.wikipedia.org/wiki/Adam7_algorithm">Adam7</a>-like
0023  * interlacing, but with a different number of steps.
0024  *
0025  * @exception int Thrown when the parameter is not a positive odd number. */
0026 InterlacingPass::InterlacingPass(const int passCount)
0027 {
0028     if (!isOdd(passCount)) {
0029         throw 0;
0030     }
0031     if (passCount < 1) {
0032         throw 0;
0033     }
0034 
0035     const int floorOfHalfCoundown = qFloor(passCount / 2.0);
0036     const int baseSize = qRound(qPow(2, floorOfHalfCoundown));
0037 
0038     countdown = passCount;
0039     rectangleSize.setWidth(baseSize);
0040     rectangleSize.setHeight(baseSize);
0041     columnFrequency = baseSize;
0042     columnOffset = 0;
0043     lineFrequency = baseSize;
0044     lineOffset = 0;
0045 }
0046 
0047 /** @brief Switches to the next pass, reducing @ref countdown by 1 and
0048  * changing all other values accordingly.
0049  *
0050  * If @ref countdown ≤ 0 than nothing happens. */
0051 void InterlacingPass::switchToNextPass()
0052 {
0053     if (countdown <= 1) {
0054         return;
0055     }
0056 
0057     countdown--;
0058 
0059     const int floorOfHalfCoundown = qFloor(countdown / 2.0);
0060     const int baseSize = qRound(qPow(2, floorOfHalfCoundown));
0061 
0062     if (isOdd(countdown)) {
0063         rectangleSize.setWidth(baseSize);
0064         rectangleSize.setHeight(baseSize);
0065         columnFrequency = baseSize;
0066         columnOffset = 0;
0067         lineFrequency = baseSize * 2;
0068         lineOffset = baseSize;
0069     } else {
0070         const int halfBaseSize = baseSize / 2; // Dividing without rounding
0071         // problems because baseSize is always an even number (it’s always
0072         // a power of two and bigger than 2 while countdown is ≥ 1).
0073         rectangleSize.setWidth(halfBaseSize);
0074         rectangleSize.setHeight(baseSize);
0075         columnFrequency = baseSize;
0076         columnOffset = halfBaseSize;
0077         lineFrequency = baseSize;
0078         lineOffset = 0;
0079     }
0080 }
0081 
0082 static_assert(std::is_trivially_copyable_v<InterlacingPass>);
0083 
0084 static_assert(std::is_standard_layout_v<InterlacingPass>);
0085 
0086 } // namespace PerceptualColor