/// File: fracGen.cc /// Copyright (C) 2025 Tyler Triplett /// License: GNU GPL 3.0 or later <https://www.gnu.org/licenses/gpl-3.0.html> /// /// This is free software: you can redistribute it and/or modify it /// under the terms of the GNU General Public License as published by /// the Free Software Foundation, either version 3 of the License, or /// (at your option) any later version. /// /// This program is distributed in the hope that it will be useful, /// but WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /// GNU General Public License for more details. #include <generators/fracGen.hh> #include <utils/safeJsonParse.hh> namespace ty { fracGen::fracGen(const int& w, const int& h) : baseGen(w, h) { } fracGen::~fracGen() { } void fracGen::loadJson(const json& j) { for (const auto& v : settings) { const auto r = getJsonValues<double>(j, v.first); if (r) { v.second = *r; } } setMembers(); } std::pair<double, double> fracGen::scaleRange() const { const double scaledRange = range_ / zoomFactor_; const double doubleWidth = width_; const double doubleHeight = height_; if (width_ >= height_) { const double scaledNew = scaledRange * doubleWidth / doubleHeight; return std::make_pair(scaledNew, scaledRange); } else { const double scaledNew = scaledRange * doubleHeight / doubleWidth; return std::make_pair(scaledRange, scaledNew); } } fracGen::pixel fracGen::pixelFromIt(const int& it) const { const double t = static_cast<double>(it) / static_cast<double>(maxIter_); const unsigned char r = 9 * (1 - t) * t * t * t * uCharMax_; const unsigned char g = 15 * (1 - t) * (1 - t) * t * t * uCharMax_; const unsigned char b = 8.5 * (1 - t) * (1 - t) * (1 - t) * t * uCharMax_; return pixel{r, g, b}; /// spared a constructor... } void fracGen::setMembers() { maxIter_ = std::clamp(maxIter_, 0.0, iterLimit_); const auto [rangeX, rangeY] = scaleRange(); minX_ = realCenter_ - rangeX; maxX_ = realCenter_ + rangeX; minY_ = imagCenter_ - rangeY; maxY_ = imagCenter_ + rangeY; scaleX_ = (maxX_ - minX_) / width_; scaleY_ = (maxY_ - minY_) / height_; } std::vector<unsigned char> fracGen::runGen() { const int size = width_ * height_ * 4; std::vector<unsigned char> image(size); for (int py = 0; py < height_; py++) { #pragma omp parallel for schedule(dynamic, 16) for (int px = 0; px < width_; px++) { const int iteration = computeIteration(px, py); const auto [r, g, b] = pixelFromIt(iteration); const int i = (py * width_ + px) * 4; image[i] = r; image[i + 1] = g; image[i + 2] = b; image[i + 3] = uCharMax_; } } return image; } std::complex<double> fracGen::pixelTranslation(const int& px, const int& py) const { const double real = minX_ + px * scaleX_; const double imag = minY_ + py * scaleY_; return std::complex<double>(real, imag); } } /// ty::gen