Przeglądaj źródła

removed bug on non-avx2 systems

Nicolas Winkler 5 lat temu
rodzic
commit
7702c52051

+ 2 - 4
libmandel/CMakeLists.txt

@@ -116,13 +116,11 @@ if (ARCH STREQUAL "X86_64" OR ARCH STREQUAL "X86")
 
     if (MSVC)
         set_source_files_properties(src/CpuGeneratorsAVX.cpp PROPERTIES COMPILE_FLAGS /arch:AVX)
-        set_source_files_properties(src/CpuGeneratorsAVXFMA.cpp PROPERTIES COMPILE_FLAGS /arch:AVX2)
-        set_source_files_properties(src/CpuGeneratorsAVXFMA.cpp PROPERTIES COMPILE_FLAGS /arch:FMA)
+        set_source_files_properties(src/CpuGeneratorsAVXFMA.cpp PROPERTIES COMPILE_FLAGS "/arch:FMA /arch:AVX2")
         set_source_files_properties(src/CpuGeneratorsSSE2.cpp PROPERTIES COMPILE_FLAGS /arch:SSE2)
     else()
         set_source_files_properties(src/CpuGeneratorsAVX.cpp PROPERTIES COMPILE_FLAGS -mavx)
-        set_source_files_properties(src/CpuGeneratorsAVXFMA.cpp PROPERTIES COMPILE_FLAGS -mavx2)
-        set_source_files_properties(src/CpuGeneratorsAVXFMA.cpp PROPERTIES COMPILE_FLAGS -mfma)
+        set_source_files_properties(src/CpuGeneratorsAVXFMA.cpp PROPERTIES COMPILE_FLAGS "-mavx2 -mfma")
         set_source_files_properties(src/CpuGeneratorsSSE2.cpp PROPERTIES COMPILE_FLAGS -msse2)
     endif(MSVC)
 

+ 37 - 14
libmandel/src/CpuGeneratorsAVXFMA.cpp

@@ -694,7 +694,7 @@ void CpuGenerator<mnd::QuadDouble, mnd::X86_AVX_FMA, parallel>::generate(const m
 {
     const MandelViewport& view = info.view;
 
-    using T = mnd::QuadDouble;
+    using T = mnd::Float256;
 
     T viewx = mnd::convert<T>(view.x);
     T viewy = mnd::convert<T>(view.y);
@@ -705,8 +705,40 @@ void CpuGenerator<mnd::QuadDouble, mnd::X86_AVX_FMA, parallel>::generate(const m
     T jX = mnd::convert<T>(info.juliaX);
     T jY = mnd::convert<T>(info.juliaY);
 
-    AvxQuadDouble juliaX = { jX[0], jX[1], jX[2], jX[3] };
-    AvxQuadDouble juliaY = { jY[0], jY[1], jY[2], jY[3] };
+
+    auto toQd = [] (const mnd::Float256& x) -> std::tuple<double, double, double, double> {
+        double a = double(x);
+        mnd::Float256 rem = x - a;
+        double b = double(rem);
+        rem = rem - b;
+        double c = double(rem);
+        rem = rem - c;
+        double d = double(rem);
+        return { a, b, c, d };
+    };
+
+    auto toAvxQuadDouble = [&toQd] (const mnd::Float256& x) -> AvxQuadDouble {
+        auto [a, b, c, d] = toQd(x);
+        return AvxQuadDouble{ a, b, c, d };
+    };
+
+    auto toAvxQuadDouble4 = [&toQd] (const mnd::Float256& a, const mnd::Float256& b,
+                            const mnd::Float256& c, const mnd::Float256& d) -> AvxQuadDouble {
+        auto [x0, y0, z0, u0] = toQd(a);
+        auto [x1, y1, z1, u1] = toQd(b);
+        auto [x2, y2, z2, u2] = toQd(c);
+        auto [x3, y3, z3, u3] = toQd(d);
+
+        __m256d xs = { x0, x1, x2, x3 };
+        __m256d ys = { y0, y1, y2, y3 };
+        __m256d zs = { z0, z1, z2, z3 };
+        __m256d us = { u0, u1, u2, u3 };
+
+        return AvxQuadDouble{ xs, ys, zs, us };
+    };
+
+    AvxQuadDouble juliaX = toAvxQuadDouble(jX);
+    AvxQuadDouble juliaY = toAvxQuadDouble(jY);
 
 #if defined(_OPENMP)
     if constexpr(parallel)
@@ -715,23 +747,14 @@ void CpuGenerator<mnd::QuadDouble, mnd::X86_AVX_FMA, parallel>::generate(const m
 #endif
     for (long j = 0; j < info.bHeight; j++) {
         T y = viewy + T(double(j)) * hpp;
-        __m256d y0s = { y.x[0], y.x[0], y.x[0], y.x[0] };
-        __m256d y1s = { y.x[1], y.x[1], y.x[1], y.x[1] };
-        __m256d y2s = { y.x[2], y.x[2], y.x[2], y.x[2] };
-        __m256d y3s = { y.x[3], y.x[3], y.x[3], y.x[3] };
-        AvxQuadDouble ys{ y0s, y1s, y2s, y3s };
+        AvxQuadDouble ys = toAvxQuadDouble(y);
         for (long i = 0; i < info.bWidth; i += 4) {
             T x1 = viewx + T(double(i)) * wpp;
             T x2 = x1 + wpp;
             T x3 = x2 + wpp;
             T x4 = x3 + wpp;
 
-            __m256d x0s = { x1[0], x2[0], x3[0], x4[0] };
-            __m256d x1s = { x1[1], x2[1], x3[1], x4[1] };
-            __m256d x2s = { x1[2], x2[2], x3[2], x4[2] };
-            __m256d x3s = { x1[3], x2[3], x3[3], x4[3] };
-
-            AvxQuadDouble xs{ x0s, x1s, x2s, x3s };
+            AvxQuadDouble xs = toAvxQuadDouble4(x1, x2, x3, x4);
 
             AvxQuadDouble cx = info.julia ? juliaX : xs;
             AvxQuadDouble cy = info.julia ? juliaY : ys;

+ 3 - 58
mandelvid/CMakeLists.txt

@@ -2,21 +2,7 @@ cmake_minimum_required(VERSION 3.13)
 
 project(mandelvid VERSION 1.0.0 DESCRIPTION "mandel video generator")
 
-set(ARCH "X86_64" CACHE STRING "Target Architecture")
-
-
-set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../CMakeModules)
-find_package(FFmpeg COMPONENTS AVCODEC AVDEVICE AVFORMAT AVUTIL SWSCALE REQUIRED)
-
-
-add_subdirectory(../libmandel ./libmandel)
-
-find_package(OpenCL)
-find_package(OpenMP)
-#set(Boost_DEBUG 1)
-set(Boost_USE_STATIC_LIBS ON)
-find_package(Boost 1.65 REQUIRED)
-
+add_subdirectory(../libalmond ./libalmond)
 
 set(CMAKE_CXX_STANDARD 17)
 
@@ -25,47 +11,6 @@ FILE(GLOB mvidsources src/*.cpp)
 FILE(GLOB mvidheaders include/*.h)
 
 add_executable(mvg ${mvidsources})
-target_include_directories(mvg PUBLIC "include")
-target_include_directories(mvg SYSTEM PUBLIC ${FFMPEG_INCLUDE_DIRS})
-target_link_libraries(mvg PUBLIC mandel)
-target_link_libraries(mvg PUBLIC qd)
-target_link_libraries(mvg PUBLIC ${FFMPEG_LIBRARIES})
-
-include(CheckIPOSupported)
-check_ipo_supported(RESULT LTO_SUPPORTED)
-
-if (LTO_SUPPORTED AND WITH_LTO)
-    message("Enabling link-time optimization.")
-    set_property(TARGET mvg PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
-endif()
-
-
-#if(OPENCL_FOUND)
-#    target_compile_definitions(mvg PUBLIC WITH_OPENCL)
-#    target_include_directories(mvg PUBLIC
-#        "include"
-#        ${OpenCL_INCLUDE_DIRS}
-#    )
-#    link_directories(${OpenCL_LIBRARY})
-#else(OPENCL_FOUND)
-#    include_directories("include")
-#endif(OPENCL_FOUND)
-#
-#if (APPLE AND OpenCL_FOUND)
-#    SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -framework OpenCL")
-#endif()
-#
-#    target_compile_definitions(mandel PUBLIC WITH_BOOST)
-#if(Boost_FOUND)
-#    target_compile_definitions(mandel PUBLIC WITH_BOOST)
-#    target_include_directories(mandel PRIVATE ${Boost_INCLUDE_DIRS})
-#    target_link_libraries(mandel PRIVATE ${Boost_LIBRARIES})
-#endif(Boost_FOUND)
-#
-#if(OpenMP_CXX_FOUND)
-#    target_link_libraries(mandel PUBLIC OpenMP::OpenMP_CXX)
-#endif()
-#if(OpenCL_FOUND)
-#    target_link_libraries(mandel PUBLIC OpenCL::OpenCL)
-#endif()
+#target_include_directories(mvg PUBLIC "include")
+target_link_libraries(mvg PUBLIC libalmond)
 

+ 0 - 62
mandelvid/include/Bitmap.h

@@ -1,62 +0,0 @@
-#pragma once
-#ifndef BITMAP_H_
-#define BITMAP_H_
-
-#include "Color.h"
-#include <memory>
-#include <string>
-#include <functional>
-
-template<typename Pixel>
-struct Bitmap
-{
-    long width, height;
-    std::unique_ptr<Pixel[]> pixels;
-public:
-    Bitmap(void) :
-        width{ 0 },
-        height{ 0 },
-        pixels{ 0 }
-    {
-    }
-
-
-    Bitmap(long width, long height) :
-        width{ width }, height{ height },
-        pixels{ std::make_unique<Pixel[]>(width * height) }
-    {
-    }
-
-    Bitmap(Bitmap&&) = default;
-    Bitmap& operator = (Bitmap&&) = default;
-
-    ~Bitmap() = default;
-
-    template<typename T>
-    Bitmap<T> map(std::function<T(Pixel)> f) const {
-        Bitmap<T> b{ width, height };
-        for (long i = 0; i < width * height; i++) {
-            b.pixels[i] = f(pixels[i]);
-        }
-        return b;
-    }
-
-    Pixel& get(long x, long y)
-    {
-        return pixels[x + y * width];
-    }
-
-    const Pixel& get(long x, long y) const
-    {
-        return pixels[x + y * width];
-    }
-
-    void print(void)
-    {
-        for (size_t i = 0; i < width * height; i++) {
-            printf("%03d ", int(pixels[i].r));
-        }
-    }
-};
-
-#endif // BITMAP_H_

+ 0 - 48
mandelvid/include/Color.h

@@ -1,48 +0,0 @@
-#pragma once
-#ifndef COLOR_H_
-#define COLOR_H_
-
-#include <cinttypes>
-
-
-struct RGBColor;
-struct RGBColorf;
-
-/*!
- * \brief Represents a color in the sRGB color space with 8-bit channels
- */
-struct RGBColor
-{
-    uint8_t r, g, b;
-
-    inline RGBColor(void) :
-        r{ 0 }, g{ 0 }, b{ 0 }
-    {
-    }
-
-    inline RGBColor(uint8_t r, uint8_t g, uint8_t b) :
-        r{ r }, g{ g }, b{ b }
-    {
-    }
-
-    RGBColor(const RGBColorf& rgb);
-};
-
-
-/*!
- * \brief Represents a color in a linear RGB color space with 32-bit floating
- *        point numbers as channels.
- */
-struct RGBColorf
-{
-    float r, g, b;
-
-    inline RGBColorf(float r, float g, float b) :
-        r{ r }, g{ g }, b{ b }
-    {
-    }
-
-    RGBColorf(const RGBColor& srgb);
-};
-
-#endif // COLOR_H_

+ 0 - 19
mandelvid/include/CubicSpline.h

@@ -1,19 +0,0 @@
-#ifndef CUBICSPLINE_H
-#define CUBICSPLINE_H
-
-#include <vector>
-#include <utility>
-#include <tuple>
-
-class CubicSpline
-{
-    /// contains x, y and y' of each interpolation point
-    std::vector<std::tuple<float, float, float>> points;
-    bool useSlopes;
-public:
-    CubicSpline(const std::vector<std::pair<float, float>>& dataPoints, bool useSlopes);
-
-    float interpolateAt(float x);
-};
-
-#endif // CUBICSPLINE_H

+ 0 - 38
mandelvid/include/Gradient.h

@@ -1,38 +0,0 @@
-#ifndef GRADIENT_H
-#define GRADIENT_H
-
-#include <vector>
-#include <string>
-#include "Color.h"
-#include <tuple>
-#include <cinttypes>
-
-
-class Gradient
-{
-    /// the colors of this gradient stored in linear RGB format
-    /// so they can be easily interpolated
-    std::vector<RGBColorf> colors;
-    float max;
-    bool repeat;
-public:
-    Gradient(void);
-    Gradient(std::vector<std::pair<RGBColor, float>> colors, bool repeat = false, int precalcSteps = -1);
-
-    static Gradient defaultGradient(void);
-
-    //static Gradient readXml(const std::string& xml);
-
-    /*!
-     * \brief get a color at a specific position in this gradient
-     * \param x the position
-     * \return the color in sRGB format
-     */
-    RGBColor get(float x) const;
-private:
-    static RGBColorf lerpColors(RGBColorf a, RGBColorf b, float val);
-    static RGBColor lerpColors(RGBColor a, RGBColor b, float val);
-    std::tuple<RGBColor, RGBColor, float> getNeighbors(float x) const;
-};
-
-#endif // GRADIENT_H

+ 0 - 43
mandelvid/include/MandelVideoGenerator.h

@@ -1,43 +0,0 @@
-#ifndef MANDELVIDEOGENERATOR_H
-#define MANDELVIDEOGENERATOR_H
-
-#include "MandelUtil.h"
-#include "Gradient.h"
-#include "Bitmap.h"
-
-struct ExportVideoInfo
-{
-    mnd::MandelViewport start;
-    mnd::MandelViewport end;
-    Gradient gradient;
-
-    int width;
-    int height;
-    int maxIterations;
-    int fps;
-    double zoomSpeed;
-
-    std::string path;
-
-    /// bitrate in kbps
-    int bitrate;
-
-    std::string preset;
-};
-
-
-class MandelVideoGenerator
-{
-    const ExportVideoInfo evi;
-public:
-    MandelVideoGenerator(const ExportVideoInfo& evi);
-
-    void generate(void);
-
-private:
-    Bitmap<RGBColor> overlay(const Bitmap<RGBColor>& outer,
-                             const Bitmap<RGBColor>& inner,
-                             double scale);
-};
-
-#endif // MANDELVIDEOGENERATOR_H

+ 0 - 50
mandelvid/include/VideoStream.h

@@ -1,50 +0,0 @@
-#pragma once
-#define FFMPEG_ENABLED
-#ifdef FFMPEG_ENABLED
-
-
-#ifndef VIDEO_STREAM_H_
-#define VIDEO_STREAM_H_
-
-#include <string>
-#include "Bitmap.h"
-
-extern "C" {
-#   include <libavformat/avformat.h>
-#   include <libavformat/avio.h>
-#   include <libavcodec/avcodec.h>
-#   include <libavformat/avformat.h>
-#   include <libavutil/imgutils.h>
-#   include <libavutil/opt.h>
-#   include <libswscale/swscale.h>
-}
-
-class VideoStream
-{
-    const AVCodec* codec;
-    AVCodecContext* codecContext;
-    AVFormatContext* formatContext;
-    AVCodecParameters* params;
-    //FILE* file;
-    AVFrame* picture;
-    AVPacket* pkt;
-    AVStream* stream;
-    SwsContext* swsContext;
-    static const uint8_t endcode[];
-
-    int width;
-    int height;
-
-    int64_t frameIndex = 0;
-public:
-    VideoStream(int width, int height, const std::string& filename, int bitrate, int fps, const char* preset);
-    ~VideoStream(void);
-
-    void encode(AVFrame* frame);
-
-    void addFrame(const Bitmap<RGBColor>& frame);
-};
-
-#endif // VIDEO_STREAM_H_
-
-#endif // FFMPEG_ENABLED

+ 0 - 2
mandelvid/src/Bitmap.cpp

@@ -1,2 +0,0 @@
-#include "Bitmap.h"
-

+ 0 - 22
mandelvid/src/Color.cpp

@@ -1,22 +0,0 @@
-#include "Color.h"
-#include <cmath>
-#include <algorithm>
-
-
-RGBColor::RGBColor(const RGBColorf& rgb)
-{
-    float cr = std::clamp(rgb.r, 0.0f, 1.0f);
-    float cg = std::clamp(rgb.g, 0.0f, 1.0f);
-    float cb = std::clamp(rgb.b, 0.0f, 1.0f);
-    r = uint8_t(cr * cr * 255.0f);
-    g = uint8_t(cg * cg * 255.0f);
-    b = uint8_t(cb * cb * 255.0f);
-}
-
-
-RGBColorf::RGBColorf(const RGBColor& srgb)
-{
-    r = ::sqrtf(srgb.r / 255.0f);
-    g = ::sqrtf(srgb.g / 255.0f);
-    b = ::sqrtf(srgb.b / 255.0f);
-}

+ 0 - 66
mandelvid/src/CubicSpline.cpp

@@ -1,66 +0,0 @@
-#include "CubicSpline.h"
-
-CubicSpline::CubicSpline(const std::vector<std::pair<float, float> >& dataPoints, bool useSlopes) :
-    useSlopes{ useSlopes }
-{
-    if (dataPoints.size() < 2) {
-        return;
-    }
-
-    points.push_back({ dataPoints[0].first, dataPoints[0].second,
-                       (dataPoints[1].second - dataPoints[0].second) /
-                       (dataPoints[1].first - dataPoints[0].first) });
-    for (size_t i = 1; i < dataPoints.size() - 1; i++) {
-
-        auto& dp1 = dataPoints[i - 1];
-        auto& dp2 = dataPoints[i];
-        auto& dp3 = dataPoints[i + 1];
-
-        float w1 = dp2.first - dp1.first;
-        float w2 = dp3.first - dp2.first;
-        float h1 = dp2.second - dp1.second;
-        float h2 = dp3.second - dp2.second;
-
-        float s1 = h1 / w1;
-        float s2 = h2 / w2;
-
-        float avgSlope = (s1 + s2) / 2;
-        points.push_back({ dp2.first, dp2.second, avgSlope });
-    }
-    points.push_back({ dataPoints[dataPoints.size() - 1].first, dataPoints[dataPoints.size() - 1].second,
-                       (dataPoints[dataPoints.size() - 2].second - dataPoints[dataPoints.size() - 1].second) /
-                       (dataPoints[dataPoints.size() - 2].first - dataPoints[dataPoints.size() - 1].first) });
-}
-
-
-float CubicSpline::interpolateAt(float x)
-{
-    const static auto h00 = [] (float t) { return (1 + 2 * t) * (1 - t) * (1 - t); };
-    const static auto h01 = [] (float t) { return t * t * (3 - 2 * t); };
-    const static auto h10 = [] (float t) { return t * (1 - t) * (1 - t); };
-    const static auto h11 = [] (float t) { return t * t * (t - 1); };
-    for (auto it = points.begin(); it != points.end() && (it + 1) != points.end(); ++it) {
-        auto& left = *it;
-        auto& right = *(it + 1);
-        float xleft = std::get<0>(left);
-        float xright = std::get<0>(right);
-        if (xleft < x && xright >= x) {
-            float w = (xright - xleft);
-            float t = (x - xleft) / w;
-            float yleft = std::get<1>(left);
-            float yright = std::get<1>(right);
-            float sleft = std::get<2>(left);
-            float sright = std::get<2>(right);
-
-            float inter = h00(t) * yleft +
-                          h01(t) * yright;
-
-            if (useSlopes)
-                inter += h10(t) * w * sleft +
-                         h11(t) * w * sright;
-
-            return inter;
-        }
-    }
-    return std::get<1>(points[points.size() - 1]);
-}

+ 0 - 152
mandelvid/src/Gradient.cpp

@@ -1,152 +0,0 @@
-#include "Gradient.h"
-
-#include "CubicSpline.h"
-
-#include <cmath>
-#include <algorithm>
-#include <functional>
-
-
-Gradient::Gradient(void) :
-    max{ 1.0 }
-{
-}
-
-
-Gradient::Gradient(std::vector<std::pair<RGBColor, float>> colors, bool repeat, int precalcSteps) :
-    repeat{ repeat }
-{
-    if(colors.empty() || colors.size() < 2)
-        return;
-    std::sort(colors.begin(), colors.end(),
-        [] (const auto& a, const auto& b) {
-            return a.second < b.second;
-        });
-
-    max = colors.at(colors.size() - 1).second;
-
-    std::vector<std::pair<RGBColorf, float>> linearColors;
-    std::transform(colors.begin(), colors.end(), std::back_inserter(linearColors),
-                   [] (auto c) { return c; });
-
-    std::vector<std::pair<float, float>> rs;
-    std::vector<std::pair<float, float>> gs;
-    std::vector<std::pair<float, float>> bs;
-
-    std::transform(linearColors.begin(), linearColors.end(), std::back_inserter(rs),
-                   [] (auto p) { return std::pair{ p.second, p.first.r }; });
-    std::transform(linearColors.begin(), linearColors.end(), std::back_inserter(gs),
-                   [] (auto p) { return std::pair{ p.second, p.first.g }; });
-    std::transform(linearColors.begin(), linearColors.end(), std::back_inserter(bs),
-                   [] (auto p) { return std::pair{ p.second, p.first.b }; });
-
-    CubicSpline rsp(rs, false);
-    CubicSpline gsp(gs, false);
-    CubicSpline bsp(bs, false);
-
-    if(precalcSteps <= 0) {
-        precalcSteps = int(max * 15) + 10;
-    }
-
-    for (int i = 0; i < precalcSteps; i++) {
-        float position = i * max / precalcSteps;
-        RGBColorf at = {
-            rsp.interpolateAt(position),
-            gsp.interpolateAt(position),
-            bsp.interpolateAt(position)
-        };
-        this->colors.push_back(at);
-    }
-}
-
-
-Gradient Gradient::defaultGradient(void)
-{
-    /*QFile res(":/gradients/default");
-    res.open(QIODevice::ReadOnly);
-    QString str = QString::fromUtf8(res.readAll());
-    return readXml(str);*/
-    return Gradient({
-        { RGBColor{ 0, 0, 0 }, 0.0f },
-        { RGBColor{ 0, 255, 255 }, 30.0f },
-        { RGBColor{ 50, 100, 170 }, 60.0f },
-        { RGBColor{ 180, 140, 20 }, 90.0f },
-        { RGBColor{ 255, 255, 0 }, 120.0f },
-        { RGBColor{ 143, 67, 0 }, 150.0f },
-        { RGBColor{ 255, 255, 255 }, 180.0f },
-        { RGBColor{ 20, 30, 180 }, 210.0f },
-        { RGBColor{ 20, 190, 30 }, 240.0f },
-        { RGBColor{ 120, 240, 120 }, 270.0f },
-        { RGBColor{ 40, 40, 40 }, 300.0f },
-    }, true);
-}
-
-
-RGBColor Gradient::get(float x) const
-{
-    if (colors.empty() || std::isnan(x) || std::isinf(x))
-        return RGBColor();
-    /*const auto [left, right, lerp] = getNeighbors(x);
-    RGBColor lerped = lerpColors(left, right, lerp);
-    return lerped;*/
-
-    if (x < 0)
-        return colors[0];
-    if (x > this->max) {
-        if (repeat)
-            x = ::fmodf(x, this->max);
-        else
-            x = this->max;
-    }
-    float pos = x * colors.size() / max;
-    if (pos < 0) {
-        pos = 0;
-    }
-    if (pos > colors.size() - 1) {
-        pos = colors.size() - 1;
-    }
-
-    int left = int(pos);
-    int right = int(pos + 1);
-    float lerp = pos - left;
-
-    if (lerp < 1e-5f) {
-        return colors[left];
-    }
-    else {
-        return lerpColors(colors[left], colors[right], lerp);
-    }
-}
-
-
-RGBColorf Gradient::lerpColors(RGBColorf a, RGBColorf b, float val)
-{
-    return RGBColorf {
-        b.r * val + a.r * (1 - val),
-        b.g * val + a.g * (1 - val),
-        b.b * val + a.b * (1 - val)
-    };
-}
-
-
-RGBColor Gradient::lerpColors(RGBColor a, RGBColor b, float val)
-{
-    return RGBColor{ lerpColors(RGBColorf{ a }, RGBColorf{ b }, val) };
-}
-
-
-/*std::tuple<RGBColor, RGBColor, float> Gradient::getNeighbors(float x) const
-{
-    for (auto it = colors.begin(); it != colors.end(); ++it) {
-        if (it->second > x) {
-            if (it == colors.begin()) {
-                return { it->first, it->first, 0 };
-            }
-            else {
-                float lerp = (x - (it - 1)->second) / (it->second - (it - 1)->second);
-                return { (it - 1)->first, it->first, lerp };
-            }
-        }
-    }
-    return { (colors.end() - 1)->first, (colors.end() - 1)->first, 0 };
-}*/

+ 0 - 147
mandelvid/src/MandelVideoGenerator.cpp

@@ -1,147 +0,0 @@
-#include "MandelVideoGenerator.h"
-#include "VideoStream.h"
-#include "Mandel.h"
-#include <thread>
-#include <cmath>
-
-MandelVideoGenerator::MandelVideoGenerator(const ExportVideoInfo& evi) :
-    evi{ evi }
-{
-}
-
-
-void MandelVideoGenerator::generate(void)
-{
-    mnd::MandelContext ctxt = mnd::initializeContext();
-    mnd::MandelGenerator& gen = ctxt.getDefaultGenerator();
-    mnd::MandelInfo mi;
-    mi.bWidth = evi.width * 2;
-    mi.bHeight = evi.height * 2;
-    mi.maxIter = evi.maxIterations;
-
-    VideoStream vs(evi.width, evi.height, evi.path, evi.bitrate, evi.fps, evi.preset.c_str());
-
-    mnd::Real x = evi.end.x + evi.end.width / 2;
-    mnd::Real y = evi.end.y + evi.end.height / 2;
-    mnd::Real w = evi.start.width;
-    mnd::Real h = evi.start.height;
-
-    mnd::Real bigW = 10000000000000000.0;
-    double bigFac = 1.0;
-    Bitmap<RGBColor> big;
-    Bitmap<RGBColor> small;
-
-    while(w > evi.end.width || h > evi.end.height) {
-        mi.view = mnd::MandelViewport{ x - w/2, y - h/2, w, h };
-
-        if (bigW > 2 * w) {
-            Bitmap<float> raw{ evi.width * 2, evi.height * 2 };
-            gen.generate(mi, raw.pixels.get());
-            //auto before = std::chrono::high_resolution_clock::now();
-            big = raw.map<RGBColor>([&mi, this] (float i) {
-                return i >= mi.maxIter ? RGBColor{ 0, 0, 0 } : evi.gradient.get(i);
-            });
-            /*mi.view.zoomCenter(0.5);
-            gen.generate(mi, raw.pixels.get());
-            small = raw.map<RGBColor>([] (float x) { return
-                RGBColor{ uint8_t(::sin(x / 100) * 127 + 127), uint8_t(::sin(x / 213) * 127 + 127), uint8_t(::cos(x / 173) * 127 + 127) };
-            });*/
-            bigW = w;
-            bigFac = 1.0;
-        }
-
-        vs.addFrame(overlay(big, small, bigFac));
-
-        w *= ::pow(0.99, evi.zoomSpeed);
-        h *= ::pow(0.99, evi.zoomSpeed);
-        bigFac *= ::pow(0.99, evi.zoomSpeed);
-    }
-}
-
-
-inline RGBColor biliniear(const Bitmap<RGBColor>& img, double x, double y)
-{
-    int xfloor = int(::floor(x));
-    int yfloor = int(::floor(y));
-    int xceil = int(::ceil(x));
-    int yceil = int(::ceil(y));
-
-    double xLerp = x - xfloor;
-    double yLerp = y - yfloor;
-
-    RGBColor samples[2][2] = {
-        {
-            img.get(xfloor, yfloor),
-            img.get(xfloor, yceil),
-        },
-        {
-            img.get(xceil, yfloor),
-            img.get(xceil, yceil),
-        }
-    };
-
-    double r = 0, g = 0, b = 0;
-
-    auto mklin = [] (double x) {
-        return x;
-    };
-    auto unlin = [] (double x) {
-        return x;
-    };
-
-    r += (1 - xLerp) * (1 - yLerp) * mklin(samples[0][0].r);
-    r += (1 - xLerp) * yLerp * mklin(samples[0][1].r);
-    r += xLerp * (1 - yLerp) * mklin(samples[1][0].r);
-    r += xLerp * yLerp * mklin(samples[1][1].r);
-
-    g += (1 - xLerp) * (1 - yLerp) * mklin(samples[0][0].g);
-    g += (1 - xLerp) * yLerp * mklin(samples[0][1].g);
-    g += xLerp * (1 - yLerp) * mklin(samples[1][0].g);
-    g += xLerp * yLerp * mklin(samples[1][1].g);
-
-    b += (1 - xLerp) * (1 - yLerp) * mklin(samples[0][0].b);
-    b += (1 - xLerp) * yLerp * mklin(samples[0][1].b);
-    b += xLerp * (1 - yLerp) * mklin(samples[1][0].b);
-    b += xLerp * yLerp * mklin(samples[1][1].b);
-
-    return RGBColor{ uint8_t(unlin(r)), uint8_t(unlin(g)), uint8_t(unlin(b)) };
-}
-
-
-inline RGBColor nearest(const Bitmap<RGBColor>& img, double x, double y)
-{
-    int xfloor = int(::floor(x));
-    int yfloor = int(::floor(y));
-    return img.get(xfloor, yfloor);
-}
-
-
-Bitmap<RGBColor> MandelVideoGenerator::overlay(const Bitmap<RGBColor>& outer,
-                         const Bitmap<RGBColor>& inner, double scale)
-{
-    printf("%lf\n", scale);
-    Bitmap<RGBColor> ret{ outer.width / 2, outer.height / 2 };
-    double newW = outer.width * scale * 2;
-    double newH = outer.height * scale * 2;
-    double newX = outer.width * (1 - scale) / 2;
-    double newY = outer.height * (1 - scale) / 2;
-
-    auto before = std::chrono::high_resolution_clock::now();
-#pragma omp parallel for schedule(static, 1)
-    for (int i = 0; i < ret.height; i++) {
-        for (int j = 0; j < ret.width; j++) {
-            double newJ = newX + j * newW / outer.width;
-            double newI = newY + i * newH / outer.height;
-            RGBColor a = biliniear(outer, newJ, newI);
-            ret.get(j, i) = a;
-        }
-    }
-    auto after = std::chrono::high_resolution_clock::now();
-    printf("gradient applied in: %lld microseconds\n", std::chrono::duration_cast<std::chrono::microseconds>(after - before).count());
-    fflush(stdout);
-    /*for (int i = 0; i < ret.height * ret.width; i++) {
-        ret.pixels[i] = outer.pixels[i];
-    }*/
-
-    return ret;
-}

+ 0 - 232
mandelvid/src/VideoStream.cpp

@@ -1,232 +0,0 @@
-#include "VideoStream.h"
-
-#include <iostream>
-
-
-
-#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,28,1)
-#define av_frame_alloc  avcodec_alloc_frame
-#define av_frame_free  avcodec_free_frame
-#endif
-
-const uint8_t VideoStream::endcode[] = { 0, 0, 1, 0xb7 };
-
-
-VideoStream::VideoStream(int width, int height, const std::string& filename, int bitrate, int fps, const char* preset) :
-    width{ width & (~1) }, height{ height & (~1) }
-{
-    // only needed with ffmpeg version < 4
-    //avcodec_register_all();
-
-    codec = avcodec_find_encoder(AV_CODEC_ID_H264);
-    if (!codec) {
-        fprintf(stderr, "invalid codec\n");
-        exit(1);
-    }
-
-    AVOutputFormat* oformat = av_guess_format(nullptr, filename.c_str(), nullptr);
-    if (!oformat)
-        oformat = av_guess_format("mp4", nullptr, nullptr);
-    if (oformat == nullptr)
-        throw "invalid format";
-
-    codecContext = avcodec_alloc_context3(codec);
-
-    pkt = av_packet_alloc();
-    if (!pkt)
-        exit(1);
-
-    codecContext->bit_rate = bitrate * 1000;
-    codecContext->width = width;
-    codecContext->height = height;
-    codecContext->time_base = AVRational{ 1, fps };
-    codecContext->framerate = AVRational{ fps, 1 };
-
-    codecContext->gop_size = 5; /* emit one intra frame every five frames */
-    codecContext->max_b_frames = 1;
-    codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
-
-    formatContext = avformat_alloc_context();
-    formatContext->oformat = oformat;
-    formatContext->video_codec_id = oformat->video_codec;
-
-    stream = avformat_new_stream(formatContext, codec);
-    if (!stream)
-        throw "error";
-
-    params = avcodec_parameters_alloc();
-    avcodec_parameters_from_context(params, codecContext);
-    stream->codecpar = params;
-
-    /*AVCPBProperties *props;
-    props = (AVCPBProperties*) av_stream_new_side_data(
-        stream, AV_PKT_DATA_CPB_PROPERTIES, sizeof(*props));
-    props->buffer_size = 1024 * 1024;
-    props->max_bitrate = 0;
-    props->min_bitrate = 0;
-    props->avg_bitrate = 0;
-    props->vbv_delay = UINT64_MAX;*/
-
-    if (codec->id == AV_CODEC_ID_H264)
-        av_opt_set(codecContext->priv_data, "preset", preset, 0);
-
-    if (avcodec_open2(codecContext, codec, nullptr) < 0) {
-        fprintf(stderr, "could not open codec\n");
-        exit(1);
-    }
-    avio_open(&formatContext->pb, filename.c_str(), AVIO_FLAG_WRITE);
-
-    if (avformat_write_header(formatContext, NULL) < 0) {
-        throw "error";
-    }
-    /*file = fopen(filename.c_str(), "wb");
-    if (!file) {
-        fprintf(stderr, "could not open %s\n", filename.c_str());
-        exit(1);
-    }*/
-
-    picture = av_frame_alloc();
-    av_frame_make_writable(picture);
-    picture->format = codecContext->pix_fmt;
-    picture->width  = codecContext->width;
-    picture->height = codecContext->height;
-
-    int retval = av_frame_get_buffer(picture, 0);
-    if (retval < 0) {
-        fprintf(stderr, "could not alloc the frame data\n");
-        exit(1);
-    }
-    //av_image_alloc(picture->data, picture->linesize, width, height, codecContext->pix_fmt, 32);
-
-    swsContext = sws_getContext(width, height,
-        AV_PIX_FMT_RGB24, width, height,
-        AV_PIX_FMT_YUV420P, 0, 0, 0, 0);
-}
-
-
-void VideoStream::encode(AVFrame* frame)
-{
-    int ret;
-
-    /* send the frame to the encoder */
-    ret = avcodec_send_frame(codecContext, frame);
-    if (ret < 0) {
-        fprintf(stderr, "error sending a frame for encoding\n");
-        exit(1);
-    }
-
-    while (ret >= 0) {
-        ret = avcodec_receive_packet(codecContext, pkt);
-        //ret = avcodec_encode_video2(codecContext, pkt, picture, &gotPacket);
-        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
-            return;
-        else if (ret < 0) {
-            fprintf(stderr, "error during encoding\n");
-            exit(1);
-        }
-
-        printf("encoded frame %3d\"PRId64\" (size=%5d)\n", pkt->pts, pkt->size);
-        //fwrite(pkt->data, 1, pkt->size, outfile);
-        //av_interleaved_write_frame(formatContext, pkt);
-
-        av_packet_rescale_ts(pkt, AVRational{1, 60}, stream->time_base);
-        pkt->stream_index = stream->index;
-
-        av_write_frame(formatContext, pkt);
-        av_packet_unref(pkt);
-    }
-}
-
-
-VideoStream::~VideoStream()
-{
-    /* flush the encoder */
-    encode(nullptr);
-    av_write_trailer(this->formatContext);
-
-    /* add sequence end code to have a real MPEG file */
-    //fwrite(endcode, 1, sizeof(endcode), file);
-    //fclose(file);
-
-    avcodec_close(codecContext);
-    avio_close(formatContext->pb);
-    av_frame_unref(picture);
-    //av_free(codecContext);
-    avcodec_parameters_free(&params);
-    avcodec_free_context(&codecContext);
-    av_frame_free(&picture);
-    av_packet_free(&pkt);
-
-/*
-    AVPacket pkt;
-    av_init_packet(&pkt);
-    pkt.data = nullptr;
-    pkt.size = 0;
-
-    for (;;) {
-        avcodec_send_frame(codecContext, NULL);
-        if (avcodec_receive_packet(codecContext, &pkt) == 0) {
-            av_interleaved_write_frame(codecContext, &pkt);
-            av_packet_unref(&pkt);
-        }
-        else {
-            break;
-        }
-    }
-
-    av_write_trailer();
-    if (!(oformat->flags & AVFMT_NOFILE)) {
-        int err = avio_close(ofctx->pb);
-        if (err < 0) {
-            Debug("Failed to close file", err);
-        }
-    }*/
-
-}
-
-
-void VideoStream::addFrame(const Bitmap<RGBColor>& frame)
-{
-    int retval = av_frame_make_writable(picture);
-    if (retval < 0)
-        exit(1);
-
-    /* prepare a dummy image */
-    /* Y */
-    /*for(int y = 0; y < height; y++) {
-        for(int x = 0; x < width; x++) {
-            picture->data[0][y * picture->linesize[0] + x] = frame.get(x, y).r / 2;
-        }
-    }*/
-
-    /* Cb and Cr */
-    /*for(int y=0;y<height / 2;y++) {
-        for(int x=0;x<width / 2;x++) {
-            picture->data[1][y * picture->linesize[1] + x] = frame.get(x * 2, y * 2).g / 2;
-            picture->data[2][y * picture->linesize[2] + x] = frame.get(x * 2, y * 2).b / 2;
-        }
-    }*/
-
-    /*auto gammaCorrect = [] (const RGBColor& rgb) {
-        const float gamma = 2.2f;
-        return RGBColor {
-            uint8_t(::powf(rgb.r / 255.0f, 1.0f / gamma) * 255),
-            uint8_t(::powf(rgb.g / 255.0f, 1.0f / gamma) * 255),
-            uint8_t(::powf(rgb.b / 255.0f, 1.0f / gamma) * 255),
-        };
-    };
-
-    Bitmap<RGBColor> gammaCorrected = frame.map<RGBColor>(gammaCorrect);*/
-
-    const uint8_t* pixelPointer[] = { reinterpret_cast<const uint8_t*>(frame.pixels.get()), 0 };
-    const int linesizeIn[] = { int(frame.width * sizeof(RGBColor)) };
-
-    sws_scale(swsContext, pixelPointer, linesizeIn, 0,
-        frame.height, picture->data, picture->linesize);
-
-    picture->pts = frameIndex++;
-
-    /* encode the image */
-    encode(picture);
-}
-