From 4d3a0d28cdcdd2044aeb099bb0c56a9416e292b5 Mon Sep 17 00:00:00 2001 From: Ashley Towns Date: Sun, 27 Apr 2025 01:15:07 +1000 Subject: [PATCH] wip --- CMakeLists.txt | 48 ++++ src/colourmaps/cividis_lut.h | 264 +++++++++++++++++++ src/colourmaps/colourmaps.h | 29 +++ src/colourmaps/cubehelix_lut.h | 264 +++++++++++++++++++ src/colourmaps/hsv_lut.h | 264 +++++++++++++++++++ src/colourmaps/inferno_lut.h | 264 +++++++++++++++++++ src/colourmaps/magma_lut.h | 264 +++++++++++++++++++ src/colourmaps/parula_lut.h | 264 +++++++++++++++++++ src/colourmaps/pastel_rainbow_lut.h | 41 +++ src/colourmaps/plasma_lut.h | 264 +++++++++++++++++++ src/colourmaps/turbo_lut.h | 264 +++++++++++++++++++ src/colourmaps/viridis_lut.h | 264 +++++++++++++++++++ src/input.c | 65 +++++ src/input.h | 8 + src/main.c | 233 +++++++++++++++++ src/mandelbrot.c | 382 ++++++++++++++++++++++++++++ src/mandelbrot.h | 12 + src/mandelbrot_kernel.cl | 174 +++++++++++++ src/mandelbrot_opencl_kernels.c | 94 +++++++ src/mandelbrot_opencl_kernels.h | 12 + src/render.c | 59 +++++ src/render.h | 10 + src/stb_easy_font.h | 305 ++++++++++++++++++++++ 23 files changed, 3848 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 src/colourmaps/cividis_lut.h create mode 100644 src/colourmaps/colourmaps.h create mode 100644 src/colourmaps/cubehelix_lut.h create mode 100644 src/colourmaps/hsv_lut.h create mode 100644 src/colourmaps/inferno_lut.h create mode 100644 src/colourmaps/magma_lut.h create mode 100644 src/colourmaps/parula_lut.h create mode 100644 src/colourmaps/pastel_rainbow_lut.h create mode 100644 src/colourmaps/plasma_lut.h create mode 100644 src/colourmaps/turbo_lut.h create mode 100644 src/colourmaps/viridis_lut.h create mode 100644 src/input.c create mode 100644 src/input.h create mode 100644 src/main.c create mode 100644 src/mandelbrot.c create mode 100644 src/mandelbrot.h create mode 100644 src/mandelbrot_kernel.cl create mode 100644 src/mandelbrot_opencl_kernels.c create mode 100644 src/mandelbrot_opencl_kernels.h create mode 100644 src/render.c create mode 100644 src/render.h create mode 100644 src/stb_easy_font.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d1b6a67 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,48 @@ +cmake_minimum_required(VERSION 3.31) + +project(MandelbrotRenderer) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) # Enables LTO + +# Set the required libraries +find_package(PkgConfig) +find_package(OpenGL REQUIRED) +find_package(GLEW REQUIRED) +find_package(glfw3 REQUIRED) +find_package(OpenCL REQUIRED) +find_package(OpenMP REQUIRED) +if (OpenMP_C_FOUND) + message(STATUS "OpenMP found") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") +else () + message(STATUS "OpenMP not found") +endif () + +include_directories(${OPENGL_INCLUDE_DIRS} ${GLEW_INCLUDE_DIRS} ${GLFW_INCLUDE_DIRS}) + +# Path to your OpenCL kernel +set(OPENCL_KERNEL_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/mandelbrot_kernel.cl") + +# Copy it into the binary directory automatically +configure_file(${OPENCL_KERNEL_FILE} ${CMAKE_CURRENT_BINARY_DIR}/mandelbrot_kernel.cl COPYONLY) + +add_executable(MandelbrotRenderer src/main.c src/mandelbrot.c src/render.c src/input.c src/mandelbrot_opencl_kernels.c) +target_compile_options(MandelbrotRenderer PRIVATE + # -g # Debugging information + -O3 # Optimize for speed + -march=native # Use the best available instruction set for the host CPU + -ffast-math # Looser IEEE compliance, allows math reordering and vectorization + -ftree-vectorize # Enable vectorization (SIMD) + -funroll-loops # Unroll loops for better performance + -flto # Link Time Optimization + -fopenmp # Enable OpenMP for parallel processing + -fomit-frame-pointer # Omit frame pointers for better performance + -mavx2 # Enable AVX2 instructions\ + -mavx512f # Enable AVX512 instructions + -mfma # Enable FMA (Fused Multiply-Add) instructions + -mfpmath=sse # Use SSE for floating-point math + -fvectorize # Enable vectorization +) +target_link_libraries(MandelbrotRenderer ${OPENGL_LIBRARIES} ${GLEW_LIBRARIES} glfw OpenMP::OpenMP_C m OpenCL::OpenCL) diff --git a/src/colourmaps/cividis_lut.h b/src/colourmaps/cividis_lut.h new file mode 100644 index 0000000..24161c7 --- /dev/null +++ b/src/colourmaps/cividis_lut.h @@ -0,0 +1,264 @@ +#ifndef CIVIDIS_LUT_H +#define CIVIDIS_LUT_H + +static const unsigned char cividis_name[] = "Cividis"; +static const unsigned char cividis[256][3] = { + {0, 32, 77}, + {0, 33, 78}, + {0, 33, 80}, + {0, 34, 82}, + {0, 35, 83}, + {0, 36, 85}, + {0, 36, 87}, + {0, 37, 88}, + {0, 38, 90}, + {0, 38, 92}, + {0, 39, 94}, + {0, 40, 95}, + {0, 40, 97}, + {0, 41, 99}, + {0, 42, 101}, + {0, 43, 103}, + {0, 43, 105}, + {0, 44, 106}, + {0, 45, 108}, + {0, 46, 110}, + {0, 46, 111}, + {0, 46, 111}, + {0, 47, 111}, + {0, 47, 111}, + {0, 48, 111}, + {0, 49, 111}, + {0, 50, 111}, + {0, 50, 111}, + {0, 51, 111}, + {0, 52, 111}, + {0, 53, 110}, + {1, 53, 110}, + {6, 54, 110}, + {10, 55, 110}, + {14, 55, 110}, + {18, 56, 109}, + {21, 57, 109}, + {23, 58, 109}, + {26, 58, 109}, + {28, 59, 109}, + {30, 60, 109}, + {32, 61, 108}, + {34, 61, 108}, + {36, 62, 108}, + {38, 63, 108}, + {40, 63, 108}, + {41, 64, 108}, + {43, 65, 108}, + {44, 66, 108}, + {46, 66, 108}, + {47, 67, 107}, + {49, 68, 107}, + {50, 68, 107}, + {51, 69, 107}, + {53, 70, 107}, + {54, 71, 107}, + {55, 71, 107}, + {57, 72, 107}, + {58, 73, 107}, + {59, 74, 107}, + {60, 74, 107}, + {61, 75, 107}, + {63, 76, 107}, + {64, 76, 107}, + {65, 77, 107}, + {66, 78, 107}, + {67, 79, 107}, + {68, 79, 107}, + {69, 80, 107}, + {70, 81, 107}, + {71, 81, 107}, + {73, 82, 107}, + {74, 83, 107}, + {75, 84, 107}, + {76, 84, 108}, + {77, 85, 108}, + {78, 86, 108}, + {79, 86, 108}, + {80, 87, 108}, + {81, 88, 108}, + {82, 89, 108}, + {83, 89, 108}, + {84, 90, 108}, + {85, 91, 109}, + {86, 91, 109}, + {86, 92, 109}, + {87, 93, 109}, + {88, 94, 109}, + {89, 94, 109}, + {90, 95, 109}, + {91, 96, 110}, + {92, 97, 110}, + {93, 97, 110}, + {94, 98, 110}, + {95, 99, 110}, + {96, 99, 111}, + {97, 100, 111}, + {98, 101, 111}, + {99, 102, 111}, + {99, 102, 111}, + {100, 103, 112}, + {101, 104, 112}, + {102, 105, 112}, + {103, 105, 112}, + {104, 106, 113}, + {105, 107, 113}, + {106, 107, 113}, + {107, 108, 113}, + {107, 109, 114}, + {108, 110, 114}, + {109, 110, 114}, + {110, 111, 115}, + {111, 112, 115}, + {112, 113, 115}, + {113, 113, 116}, + {114, 114, 116}, + {114, 115, 116}, + {115, 116, 117}, + {116, 116, 117}, + {117, 117, 117}, + {118, 118, 118}, + {119, 119, 118}, + {120, 119, 119}, + {120, 120, 119}, + {121, 121, 119}, + {122, 122, 120}, + {123, 122, 120}, + {124, 123, 120}, + {125, 124, 120}, + {126, 125, 120}, + {127, 125, 120}, + {128, 126, 121}, + {129, 127, 121}, + {130, 128, 121}, + {131, 128, 121}, + {132, 129, 121}, + {133, 130, 121}, + {133, 131, 121}, + {134, 131, 121}, + {135, 132, 121}, + {136, 133, 121}, + {137, 134, 121}, + {138, 135, 121}, + {139, 135, 121}, + {140, 136, 121}, + {141, 137, 121}, + {142, 138, 121}, + {143, 139, 121}, + {144, 139, 121}, + {145, 140, 120}, + {146, 141, 120}, + {147, 142, 120}, + {148, 142, 120}, + {149, 143, 120}, + {150, 144, 120}, + {151, 145, 120}, + {152, 146, 120}, + {153, 146, 120}, + {154, 147, 119}, + {155, 148, 119}, + {156, 149, 119}, + {157, 150, 119}, + {158, 150, 119}, + {159, 151, 119}, + {160, 152, 119}, + {161, 153, 118}, + {163, 154, 118}, + {164, 155, 118}, + {165, 155, 118}, + {166, 156, 117}, + {167, 157, 117}, + {168, 158, 117}, + {169, 159, 117}, + {170, 160, 117}, + {171, 160, 116}, + {172, 161, 116}, + {173, 162, 116}, + {174, 163, 116}, + {175, 164, 115}, + {176, 164, 115}, + {177, 165, 115}, + {178, 166, 114}, + {179, 167, 114}, + {180, 168, 114}, + {181, 169, 113}, + {182, 170, 113}, + {183, 170, 113}, + {184, 171, 112}, + {186, 172, 112}, + {187, 173, 112}, + {188, 174, 111}, + {189, 175, 111}, + {190, 176, 111}, + {191, 176, 110}, + {192, 177, 110}, + {193, 178, 109}, + {194, 179, 109}, + {195, 180, 109}, + {196, 181, 108}, + {197, 182, 108}, + {198, 183, 107}, + {200, 183, 107}, + {201, 184, 106}, + {202, 185, 106}, + {203, 186, 105}, + {204, 187, 105}, + {205, 188, 104}, + {206, 189, 104}, + {207, 190, 103}, + {208, 191, 103}, + {209, 191, 102}, + {211, 192, 101}, + {212, 193, 101}, + {213, 194, 100}, + {214, 195, 100}, + {215, 196, 99}, + {216, 197, 99}, + {217, 198, 98}, + {218, 199, 97}, + {219, 200, 97}, + {221, 201, 96}, + {222, 201, 95}, + {223, 202, 95}, + {224, 203, 94}, + {225, 204, 93}, + {226, 205, 92}, + {227, 206, 92}, + {229, 207, 91}, + {230, 208, 90}, + {231, 209, 89}, + {232, 210, 88}, + {233, 211, 88}, + {234, 212, 87}, + {235, 213, 86}, + {237, 214, 85}, + {238, 215, 84}, + {239, 216, 83}, + {240, 217, 82}, + {241, 218, 81}, + {242, 219, 80}, + {244, 219, 79}, + {245, 220, 78}, + {246, 221, 77}, + {247, 222, 76}, + {248, 223, 75}, + {250, 224, 74}, + {251, 225, 73}, + {252, 226, 71}, + {253, 227, 70}, + {254, 228, 69}, + {255, 229, 67}, + {255, 230, 66}, + {255, 231, 66}, + {255, 232, 67}, + {255, 233, 68}, + {255, 234, 69}, +}; + +#endif // CIVIDIS_LUT_H diff --git a/src/colourmaps/colourmaps.h b/src/colourmaps/colourmaps.h new file mode 100644 index 0000000..f28d0a9 --- /dev/null +++ b/src/colourmaps/colourmaps.h @@ -0,0 +1,29 @@ +#ifndef COLOURMAPS_H +#define COLOURMAPS_H + +#include "cividis_lut.h" +#include "cubehelix_lut.h" +#include "hsv_lut.h" +#include "inferno_lut.h" +#include "magma_lut.h" +#include "parula_lut.h" +#include "pastel_rainbow_lut.h" +#include "plasma_lut.h" +#include "turbo_lut.h" +#include "viridis_lut.h" + +typedef enum +{ + CIVIDIS_LUT_COLOR, + CUBEHELIX_LUT_COLOR, + HSV_LUT_COLOR, + INFERNO_LUT_COLOR, + MAGMA_LUT_COLOR, + PARULA_LUT_COLOR, + PASTEL_RAINBOW_LUT_COLOR, + PLASMA_LUT_COLOR, + TURBO_LUT_COLOR, + VIRIDIS_LUT_COLOR +} colourmap_type; + +#endif // COLOURMAPS_H diff --git a/src/colourmaps/cubehelix_lut.h b/src/colourmaps/cubehelix_lut.h new file mode 100644 index 0000000..ceabf22 --- /dev/null +++ b/src/colourmaps/cubehelix_lut.h @@ -0,0 +1,264 @@ +#ifndef CUBEHELIX_LUT_H +#define CUBEHELIX_LUT_H + +static const unsigned char cubehelix_name[] = "Cubehelix"; +static const unsigned char cubehelix[256][3] = { + {0, 0, 0}, + {1, 0, 1}, + {3, 1, 3}, + {5, 1, 4}, + {6, 2, 6}, + {8, 2, 8}, + {9, 3, 9}, + {10, 4, 11}, + {12, 4, 13}, + {13, 5, 15}, + {14, 6, 17}, + {16, 6, 19}, + {17, 7, 21}, + {18, 8, 23}, + {19, 9, 25}, + {20, 10, 27}, + {20, 11, 29}, + {21, 12, 31}, + {22, 12, 33}, + {23, 13, 35}, + {23, 14, 37}, + {24, 16, 39}, + {24, 17, 41}, + {25, 18, 43}, + {25, 19, 45}, + {25, 20, 47}, + {26, 21, 49}, + {26, 23, 50}, + {26, 24, 52}, + {26, 25, 54}, + {26, 26, 56}, + {26, 28, 57}, + {26, 29, 59}, + {26, 31, 61}, + {26, 32, 62}, + {26, 34, 64}, + {26, 35, 65}, + {25, 37, 66}, + {25, 38, 68}, + {25, 40, 69}, + {25, 42, 70}, + {24, 43, 71}, + {24, 45, 72}, + {24, 47, 73}, + {24, 48, 74}, + {23, 50, 75}, + {23, 52, 75}, + {23, 53, 76}, + {22, 55, 77}, + {22, 57, 77}, + {22, 59, 77}, + {22, 60, 78}, + {21, 62, 78}, + {21, 64, 78}, + {21, 66, 78}, + {21, 68, 78}, + {21, 69, 78}, + {21, 71, 78}, + {21, 73, 78}, + {21, 75, 78}, + {21, 76, 77}, + {21, 78, 77}, + {21, 80, 77}, + {21, 81, 76}, + {21, 83, 76}, + {22, 85, 75}, + {22, 86, 74}, + {22, 88, 74}, + {23, 90, 73}, + {24, 91, 72}, + {24, 93, 71}, + {25, 94, 70}, + {26, 96, 70}, + {27, 97, 69}, + {28, 98, 68}, + {29, 100, 67}, + {30, 101, 66}, + {31, 102, 65}, + {32, 104, 64}, + {33, 105, 63}, + {35, 106, 62}, + {36, 107, 61}, + {38, 108, 60}, + {40, 109, 59}, + {41, 110, 58}, + {43, 111, 57}, + {45, 112, 56}, + {47, 113, 55}, + {49, 114, 54}, + {51, 115, 53}, + {53, 116, 52}, + {55, 116, 52}, + {58, 117, 51}, + {60, 118, 50}, + {62, 118, 49}, + {65, 119, 49}, + {67, 119, 48}, + {70, 120, 48}, + {73, 120, 47}, + {75, 120, 47}, + {78, 121, 47}, + {81, 121, 47}, + {84, 121, 47}, + {87, 122, 46}, + {90, 122, 47}, + {93, 122, 47}, + {96, 122, 47}, + {99, 122, 47}, + {102, 122, 47}, + {105, 122, 48}, + {108, 123, 48}, + {111, 123, 49}, + {114, 123, 50}, + {117, 123, 51}, + {120, 122, 52}, + {123, 122, 53}, + {126, 122, 54}, + {129, 122, 55}, + {132, 122, 56}, + {135, 122, 57}, + {138, 122, 59}, + {141, 122, 61}, + {144, 122, 62}, + {147, 122, 64}, + {150, 121, 66}, + {153, 121, 68}, + {156, 121, 70}, + {159, 121, 72}, + {162, 121, 74}, + {164, 121, 76}, + {167, 121, 78}, + {169, 121, 81}, + {172, 121, 83}, + {174, 121, 86}, + {177, 121, 89}, + {179, 121, 91}, + {181, 121, 94}, + {184, 121, 97}, + {186, 121, 100}, + {188, 121, 103}, + {190, 121, 106}, + {192, 121, 109}, + {193, 122, 112}, + {195, 122, 115}, + {197, 122, 118}, + {198, 122, 121}, + {200, 123, 124}, + {201, 123, 127}, + {203, 124, 131}, + {204, 124, 134}, + {205, 125, 137}, + {206, 125, 140}, + {207, 126, 144}, + {208, 126, 147}, + {209, 127, 150}, + {210, 128, 153}, + {210, 128, 156}, + {211, 129, 160}, + {211, 130, 163}, + {212, 131, 166}, + {212, 132, 169}, + {212, 133, 172}, + {213, 134, 175}, + {213, 135, 178}, + {213, 136, 181}, + {213, 137, 184}, + {213, 139, 187}, + {213, 140, 190}, + {212, 141, 193}, + {212, 142, 196}, + {212, 144, 198}, + {212, 145, 201}, + {211, 146, 203}, + {211, 148, 206}, + {210, 149, 208}, + {210, 151, 211}, + {209, 153, 213}, + {209, 154, 215}, + {208, 156, 217}, + {207, 157, 219}, + {207, 159, 221}, + {206, 161, 223}, + {205, 162, 225}, + {205, 164, 226}, + {204, 166, 228}, + {203, 168, 230}, + {203, 170, 231}, + {202, 171, 232}, + {201, 173, 234}, + {201, 175, 235}, + {200, 177, 236}, + {199, 179, 237}, + {199, 180, 238}, + {198, 182, 239}, + {197, 184, 240}, + {197, 186, 240}, + {196, 188, 241}, + {196, 190, 242}, + {195, 192, 242}, + {195, 193, 243}, + {195, 195, 243}, + {194, 197, 243}, + {194, 199, 243}, + {194, 201, 244}, + {194, 202, 244}, + {194, 204, 244}, + {194, 206, 244}, + {194, 207, 244}, + {194, 209, 244}, + {194, 211, 244}, + {194, 212, 244}, + {194, 214, 244}, + {195, 216, 243}, + {195, 217, 243}, + {195, 219, 243}, + {196, 220, 243}, + {196, 222, 242}, + {197, 223, 242}, + {198, 224, 242}, + {199, 226, 241}, + {199, 227, 241}, + {200, 228, 241}, + {201, 230, 241}, + {202, 231, 240}, + {203, 232, 240}, + {205, 233, 240}, + {206, 234, 240}, + {207, 235, 239}, + {208, 237, 239}, + {210, 238, 239}, + {211, 239, 239}, + {213, 240, 239}, + {214, 240, 239}, + {216, 241, 239}, + {217, 242, 239}, + {219, 243, 239}, + {221, 244, 240}, + {222, 245, 240}, + {224, 245, 240}, + {226, 246, 240}, + {228, 247, 241}, + {230, 247, 241}, + {231, 248, 242}, + {233, 249, 243}, + {235, 249, 243}, + {237, 250, 244}, + {239, 251, 245}, + {241, 251, 246}, + {243, 252, 247}, + {245, 252, 248}, + {246, 253, 249}, + {248, 253, 250}, + {250, 254, 251}, + {252, 254, 253}, + {254, 255, 254}, + {255, 255, 255}, +}; + +#endif // CUBEHELIX_LUT_H diff --git a/src/colourmaps/hsv_lut.h b/src/colourmaps/hsv_lut.h new file mode 100644 index 0000000..be6e91d --- /dev/null +++ b/src/colourmaps/hsv_lut.h @@ -0,0 +1,264 @@ +#ifndef _HSV_LUT_H_ +#define _HSV_LUT_H_ + +static const unsigned char hsv_name[] = "HSV"; +static const unsigned char hsv[256][3] = { + {255, 0, 0}, + {255, 5, 0}, + {255, 12, 0}, + {255, 17, 0}, + {255, 24, 0}, + {255, 30, 0}, + {255, 35, 0}, + {255, 42, 0}, + {255, 48, 0}, + {255, 53, 0}, + {255, 60, 0}, + {255, 65, 0}, + {255, 71, 0}, + {255, 78, 0}, + {255, 83, 0}, + {255, 90, 0}, + {255, 96, 0}, + {255, 101, 0}, + {255, 108, 0}, + {255, 113, 0}, + {255, 120, 0}, + {255, 126, 0}, + {255, 131, 0}, + {255, 138, 0}, + {255, 144, 0}, + {255, 149, 0}, + {255, 156, 0}, + {255, 161, 0}, + {255, 167, 0}, + {255, 174, 0}, + {255, 179, 0}, + {255, 186, 0}, + {255, 192, 0}, + {255, 197, 0}, + {255, 204, 0}, + {255, 209, 0}, + {255, 216, 0}, + {255, 222, 0}, + {255, 227, 0}, + {255, 234, 0}, + {255, 240, 0}, + {255, 245, 0}, + {255, 252, 0}, + {254, 255, 0}, + {248, 255, 0}, + {241, 255, 0}, + {236, 255, 0}, + {229, 255, 0}, + {224, 255, 0}, + {218, 255, 0}, + {211, 255, 0}, + {206, 255, 0}, + {199, 255, 0}, + {193, 255, 0}, + {188, 255, 0}, + {181, 255, 0}, + {176, 255, 0}, + {170, 255, 0}, + {163, 255, 0}, + {158, 255, 0}, + {152, 255, 0}, + {145, 255, 0}, + {140, 255, 0}, + {133, 255, 0}, + {128, 255, 0}, + {122, 255, 0}, + {115, 255, 0}, + {110, 255, 0}, + {103, 255, 0}, + {97, 255, 0}, + {92, 255, 0}, + {85, 255, 0}, + {80, 255, 0}, + {74, 255, 0}, + {67, 255, 0}, + {62, 255, 0}, + {56, 255, 0}, + {49, 255, 0}, + {44, 255, 0}, + {37, 255, 0}, + {32, 255, 0}, + {26, 255, 0}, + {19, 255, 0}, + {14, 255, 0}, + {7, 255, 0}, + {1, 255, 0}, + {0, 255, 3}, + {0, 255, 10}, + {0, 255, 16}, + {0, 255, 21}, + {0, 255, 28}, + {0, 255, 33}, + {0, 255, 39}, + {0, 255, 46}, + {0, 255, 51}, + {0, 255, 58}, + {0, 255, 64}, + {0, 255, 69}, + {0, 255, 76}, + {0, 255, 81}, + {0, 255, 88}, + {0, 255, 94}, + {0, 255, 99}, + {0, 255, 106}, + {0, 255, 112}, + {0, 255, 117}, + {0, 255, 124}, + {0, 255, 129}, + {0, 255, 135}, + {0, 255, 142}, + {0, 255, 147}, + {0, 255, 154}, + {0, 255, 160}, + {0, 255, 165}, + {0, 255, 172}, + {0, 255, 177}, + {0, 255, 184}, + {0, 255, 190}, + {0, 255, 195}, + {0, 255, 202}, + {0, 255, 208}, + {0, 255, 213}, + {0, 255, 220}, + {0, 255, 225}, + {0, 255, 231}, + {0, 255, 238}, + {0, 255, 243}, + {0, 255, 250}, + {0, 255, 255}, + {0, 250, 255}, + {0, 243, 255}, + {0, 238, 255}, + {0, 231, 255}, + {0, 225, 255}, + {0, 220, 255}, + {0, 213, 255}, + {0, 208, 255}, + {0, 202, 255}, + {0, 195, 255}, + {0, 190, 255}, + {0, 184, 255}, + {0, 177, 255}, + {0, 172, 255}, + {0, 165, 255}, + {0, 160, 255}, + {0, 154, 255}, + {0, 147, 255}, + {0, 142, 255}, + {0, 135, 255}, + {0, 129, 255}, + {0, 124, 255}, + {0, 117, 255}, + {0, 112, 255}, + {0, 106, 255}, + {0, 99, 255}, + {0, 94, 255}, + {0, 88, 255}, + {0, 81, 255}, + {0, 76, 255}, + {0, 69, 255}, + {0, 64, 255}, + {0, 58, 255}, + {0, 51, 255}, + {0, 46, 255}, + {0, 39, 255}, + {0, 33, 255}, + {0, 28, 255}, + {0, 21, 255}, + {0, 16, 255}, + {0, 10, 255}, + {0, 3, 255}, + {1, 0, 255}, + {7, 0, 255}, + {14, 0, 255}, + {19, 0, 255}, + {26, 0, 255}, + {32, 0, 255}, + {37, 0, 255}, + {44, 0, 255}, + {49, 0, 255}, + {56, 0, 255}, + {62, 0, 255}, + {67, 0, 255}, + {74, 0, 255}, + {80, 0, 255}, + {85, 0, 255}, + {92, 0, 255}, + {97, 0, 255}, + {103, 0, 255}, + {110, 0, 255}, + {115, 0, 255}, + {122, 0, 255}, + {128, 0, 255}, + {133, 0, 255}, + {140, 0, 255}, + {145, 0, 255}, + {152, 0, 255}, + {158, 0, 255}, + {163, 0, 255}, + {170, 0, 255}, + {176, 0, 255}, + {181, 0, 255}, + {188, 0, 255}, + {193, 0, 255}, + {199, 0, 255}, + {206, 0, 255}, + {211, 0, 255}, + {218, 0, 255}, + {224, 0, 255}, + {229, 0, 255}, + {236, 0, 255}, + {241, 0, 255}, + {248, 0, 255}, + {254, 0, 255}, + {255, 0, 252}, + {255, 0, 245}, + {255, 0, 240}, + {255, 0, 234}, + {255, 0, 227}, + {255, 0, 222}, + {255, 0, 216}, + {255, 0, 209}, + {255, 0, 204}, + {255, 0, 197}, + {255, 0, 192}, + {255, 0, 186}, + {255, 0, 179}, + {255, 0, 174}, + {255, 0, 167}, + {255, 0, 161}, + {255, 0, 156}, + {255, 0, 149}, + {255, 0, 144}, + {255, 0, 138}, + {255, 0, 131}, + {255, 0, 126}, + {255, 0, 120}, + {255, 0, 113}, + {255, 0, 108}, + {255, 0, 101}, + {255, 0, 96}, + {255, 0, 90}, + {255, 0, 83}, + {255, 0, 78}, + {255, 0, 71}, + {255, 0, 65}, + {255, 0, 60}, + {255, 0, 53}, + {255, 0, 48}, + {255, 0, 42}, + {255, 0, 35}, + {255, 0, 30}, + {255, 0, 24}, + {255, 0, 17}, + {255, 0, 12}, + {255, 0, 5}, +}; + +#endif // _HSV_LUT_H_ diff --git a/src/colourmaps/inferno_lut.h b/src/colourmaps/inferno_lut.h new file mode 100644 index 0000000..126da28 --- /dev/null +++ b/src/colourmaps/inferno_lut.h @@ -0,0 +1,264 @@ +#ifndef INFERNO_LUT_H +#define INFERNO_LUT_H + +static const unsigned char inferno_name[] = "Inferno"; +static const unsigned char inferno[256][3] = { + {0, 0, 3}, + {0, 0, 4}, + {0, 0, 6}, + {1, 0, 7}, + {1, 1, 9}, + {1, 1, 11}, + {2, 1, 14}, + {2, 2, 16}, + {3, 2, 18}, + {4, 3, 20}, + {4, 3, 22}, + {5, 4, 24}, + {6, 4, 27}, + {7, 5, 29}, + {8, 6, 31}, + {9, 6, 33}, + {10, 7, 36}, + {12, 7, 38}, + {13, 8, 40}, + {14, 8, 43}, + {15, 9, 45}, + {16, 9, 47}, + {18, 10, 50}, + {19, 10, 52}, + {20, 11, 55}, + {22, 11, 57}, + {23, 11, 59}, + {25, 11, 62}, + {26, 12, 64}, + {28, 12, 67}, + {29, 12, 69}, + {31, 12, 72}, + {33, 12, 74}, + {34, 11, 76}, + {36, 11, 78}, + {38, 11, 81}, + {39, 11, 83}, + {41, 11, 85}, + {43, 10, 87}, + {45, 10, 89}, + {46, 10, 90}, + {48, 10, 92}, + {50, 9, 94}, + {52, 9, 95}, + {54, 9, 96}, + {55, 9, 98}, + {57, 9, 99}, + {59, 9, 100}, + {60, 9, 101}, + {62, 9, 102}, + {64, 9, 103}, + {66, 9, 104}, + {67, 10, 104}, + {69, 10, 105}, + {71, 10, 106}, + {72, 11, 106}, + {74, 11, 107}, + {76, 12, 107}, + {77, 12, 108}, + {79, 13, 108}, + {80, 13, 108}, + {82, 14, 109}, + {84, 14, 109}, + {85, 15, 109}, + {87, 15, 109}, + {89, 16, 110}, + {90, 17, 110}, + {92, 17, 110}, + {93, 18, 110}, + {95, 18, 110}, + {97, 19, 110}, + {98, 20, 110}, + {100, 20, 110}, + {101, 21, 110}, + {103, 21, 110}, + {104, 22, 110}, + {106, 23, 110}, + {108, 23, 110}, + {109, 24, 110}, + {111, 24, 110}, + {112, 25, 110}, + {114, 26, 110}, + {116, 26, 110}, + {117, 27, 110}, + {119, 27, 109}, + {120, 28, 109}, + {122, 28, 109}, + {124, 29, 109}, + {125, 29, 108}, + {127, 30, 108}, + {128, 31, 108}, + {130, 31, 108}, + {132, 32, 107}, + {133, 32, 107}, + {135, 33, 107}, + {136, 33, 106}, + {138, 34, 106}, + {140, 35, 105}, + {141, 35, 105}, + {143, 36, 104}, + {144, 36, 104}, + {146, 37, 104}, + {148, 37, 103}, + {149, 38, 103}, + {151, 39, 102}, + {152, 39, 101}, + {154, 40, 101}, + {155, 40, 100}, + {157, 41, 100}, + {159, 42, 99}, + {160, 42, 98}, + {162, 43, 98}, + {163, 43, 97}, + {165, 44, 96}, + {167, 45, 96}, + {168, 45, 95}, + {170, 46, 94}, + {171, 47, 93}, + {173, 47, 93}, + {174, 48, 92}, + {176, 49, 91}, + {177, 49, 90}, + {179, 50, 89}, + {180, 51, 89}, + {182, 52, 88}, + {183, 52, 87}, + {185, 53, 86}, + {186, 54, 85}, + {188, 55, 84}, + {189, 56, 83}, + {191, 56, 82}, + {192, 57, 81}, + {194, 58, 80}, + {195, 59, 79}, + {197, 60, 78}, + {198, 61, 77}, + {199, 62, 76}, + {201, 63, 75}, + {202, 64, 74}, + {203, 65, 73}, + {205, 66, 72}, + {206, 67, 71}, + {207, 68, 70}, + {209, 69, 69}, + {210, 70, 68}, + {211, 71, 67}, + {213, 72, 65}, + {214, 73, 64}, + {215, 74, 63}, + {216, 76, 62}, + {217, 77, 61}, + {219, 78, 60}, + {220, 79, 59}, + {221, 81, 57}, + {222, 82, 56}, + {223, 83, 55}, + {224, 85, 54}, + {225, 86, 53}, + {226, 87, 51}, + {227, 89, 50}, + {228, 90, 49}, + {229, 91, 48}, + {230, 93, 47}, + {231, 94, 45}, + {232, 96, 44}, + {233, 97, 43}, + {234, 99, 42}, + {235, 100, 40}, + {236, 102, 39}, + {237, 103, 38}, + {237, 105, 37}, + {238, 106, 35}, + {239, 108, 34}, + {240, 110, 33}, + {241, 111, 32}, + {241, 113, 30}, + {242, 114, 29}, + {243, 116, 28}, + {243, 118, 26}, + {244, 119, 25}, + {244, 121, 24}, + {245, 123, 22}, + {246, 125, 21}, + {246, 126, 20}, + {247, 128, 18}, + {247, 130, 17}, + {248, 132, 16}, + {248, 133, 14}, + {248, 135, 13}, + {249, 137, 12}, + {249, 139, 11}, + {250, 141, 9}, + {250, 142, 8}, + {250, 144, 8}, + {251, 146, 7}, + {251, 148, 6}, + {251, 150, 6}, + {251, 152, 6}, + {252, 153, 6}, + {252, 155, 6}, + {252, 157, 6}, + {252, 159, 7}, + {252, 161, 7}, + {252, 163, 8}, + {252, 165, 10}, + {252, 167, 11}, + {252, 169, 13}, + {252, 170, 14}, + {252, 172, 16}, + {252, 174, 18}, + {252, 176, 20}, + {252, 178, 22}, + {252, 180, 24}, + {252, 182, 26}, + {252, 184, 28}, + {252, 186, 30}, + {251, 188, 33}, + {251, 190, 35}, + {251, 192, 37}, + {251, 194, 40}, + {250, 196, 42}, + {250, 198, 45}, + {250, 200, 47}, + {249, 202, 50}, + {249, 204, 52}, + {249, 206, 55}, + {248, 208, 58}, + {248, 210, 61}, + {247, 212, 63}, + {247, 214, 66}, + {246, 216, 69}, + {246, 217, 73}, + {245, 219, 76}, + {245, 221, 79}, + {244, 223, 82}, + {244, 225, 86}, + {244, 227, 89}, + {243, 229, 93}, + {243, 231, 97}, + {242, 233, 101}, + {242, 234, 105}, + {242, 236, 109}, + {242, 238, 113}, + {242, 239, 117}, + {242, 241, 121}, + {242, 243, 125}, + {243, 244, 130}, + {243, 245, 134}, + {244, 247, 138}, + {245, 248, 142}, + {246, 249, 146}, + {247, 251, 150}, + {248, 252, 154}, + {249, 253, 157}, + {251, 254, 161}, + {253, 255, 165}, +}; + +#endif // INFERNO_LUT_H diff --git a/src/colourmaps/magma_lut.h b/src/colourmaps/magma_lut.h new file mode 100644 index 0000000..0ae8fac --- /dev/null +++ b/src/colourmaps/magma_lut.h @@ -0,0 +1,264 @@ +#ifndef MAGMA_LUT_H +#define MAGMA_LUT_H + +static const unsigned char magma_name[] = "Magma"; +static const unsigned char magma[256][3] = { + {0, 0, 3}, + {0, 0, 4}, + {0, 0, 6}, + {1, 0, 7}, + {1, 1, 9}, + {1, 1, 11}, + {2, 2, 13}, + {2, 2, 15}, + {3, 3, 17}, + {4, 3, 19}, + {4, 4, 21}, + {5, 4, 23}, + {6, 5, 25}, + {7, 5, 27}, + {8, 6, 29}, + {9, 7, 32}, + {10, 7, 34}, + {11, 8, 36}, + {12, 9, 38}, + {13, 10, 40}, + {14, 10, 42}, + {15, 11, 45}, + {16, 12, 47}, + {17, 12, 49}, + {19, 13, 51}, + {20, 13, 54}, + {21, 14, 56}, + {22, 14, 58}, + {23, 15, 61}, + {25, 15, 63}, + {26, 16, 66}, + {27, 16, 68}, + {28, 16, 70}, + {30, 17, 73}, + {31, 17, 75}, + {33, 17, 78}, + {34, 17, 80}, + {36, 17, 83}, + {37, 17, 85}, + {39, 17, 87}, + {40, 17, 90}, + {42, 17, 92}, + {43, 17, 94}, + {45, 17, 97}, + {47, 16, 99}, + {49, 16, 101}, + {50, 16, 103}, + {52, 16, 105}, + {54, 15, 107}, + {55, 15, 108}, + {57, 15, 110}, + {59, 15, 112}, + {61, 15, 113}, + {62, 15, 114}, + {64, 15, 116}, + {66, 15, 117}, + {67, 15, 118}, + {69, 15, 119}, + {71, 15, 120}, + {72, 16, 120}, + {74, 16, 121}, + {76, 16, 122}, + {77, 17, 123}, + {79, 17, 123}, + {81, 18, 124}, + {82, 18, 124}, + {84, 19, 125}, + {85, 20, 125}, + {87, 20, 126}, + {88, 21, 126}, + {90, 21, 126}, + {92, 22, 127}, + {93, 23, 127}, + {95, 23, 127}, + {96, 24, 128}, + {98, 25, 128}, + {99, 25, 128}, + {101, 26, 128}, + {103, 26, 128}, + {104, 27, 129}, + {106, 28, 129}, + {107, 28, 129}, + {109, 29, 129}, + {110, 30, 129}, + {112, 30, 129}, + {113, 31, 129}, + {115, 32, 129}, + {117, 32, 129}, + {118, 33, 129}, + {120, 33, 129}, + {121, 34, 130}, + {123, 35, 130}, + {124, 35, 130}, + {126, 36, 130}, + {128, 36, 130}, + {129, 37, 129}, + {131, 37, 129}, + {132, 38, 129}, + {134, 39, 129}, + {136, 39, 129}, + {137, 40, 129}, + {139, 40, 129}, + {140, 41, 129}, + {142, 41, 129}, + {144, 42, 129}, + {145, 42, 129}, + {147, 43, 128}, + {148, 43, 128}, + {150, 44, 128}, + {152, 44, 128}, + {153, 45, 128}, + {155, 46, 127}, + {157, 46, 127}, + {158, 47, 127}, + {160, 47, 127}, + {161, 48, 126}, + {163, 48, 126}, + {165, 49, 126}, + {166, 49, 125}, + {168, 50, 125}, + {170, 50, 125}, + {171, 51, 124}, + {173, 51, 124}, + {175, 52, 123}, + {176, 52, 123}, + {178, 53, 123}, + {180, 53, 122}, + {181, 54, 122}, + {183, 55, 121}, + {185, 55, 121}, + {186, 56, 120}, + {188, 56, 120}, + {189, 57, 119}, + {191, 57, 118}, + {193, 58, 118}, + {194, 59, 117}, + {196, 59, 117}, + {198, 60, 116}, + {199, 61, 115}, + {201, 61, 115}, + {202, 62, 114}, + {204, 63, 113}, + {206, 63, 113}, + {207, 64, 112}, + {209, 65, 111}, + {210, 66, 110}, + {212, 67, 110}, + {213, 67, 109}, + {215, 68, 108}, + {216, 69, 107}, + {218, 70, 107}, + {219, 71, 106}, + {221, 72, 105}, + {222, 73, 104}, + {223, 74, 103}, + {225, 75, 103}, + {226, 76, 102}, + {227, 78, 101}, + {229, 79, 100}, + {230, 80, 100}, + {231, 81, 99}, + {232, 83, 98}, + {233, 84, 97}, + {234, 85, 97}, + {236, 87, 96}, + {237, 88, 95}, + {238, 90, 95}, + {239, 91, 94}, + {239, 93, 94}, + {240, 95, 93}, + {241, 96, 93}, + {242, 98, 93}, + {243, 100, 92}, + {243, 101, 92}, + {244, 103, 92}, + {245, 105, 92}, + {246, 107, 92}, + {246, 108, 92}, + {247, 110, 92}, + {247, 112, 92}, + {248, 114, 92}, + {248, 116, 92}, + {249, 118, 92}, + {249, 120, 92}, + {250, 121, 93}, + {250, 123, 93}, + {250, 125, 94}, + {251, 127, 94}, + {251, 129, 95}, + {251, 131, 95}, + {252, 133, 96}, + {252, 135, 97}, + {252, 137, 97}, + {252, 139, 98}, + {253, 140, 99}, + {253, 142, 100}, + {253, 144, 101}, + {253, 146, 102}, + {253, 148, 103}, + {254, 150, 104}, + {254, 152, 105}, + {254, 154, 106}, + {254, 156, 107}, + {254, 157, 108}, + {254, 159, 109}, + {254, 161, 110}, + {254, 163, 111}, + {254, 165, 112}, + {255, 167, 114}, + {255, 169, 115}, + {255, 171, 116}, + {255, 172, 118}, + {255, 174, 119}, + {255, 176, 120}, + {255, 178, 122}, + {255, 180, 123}, + {255, 182, 124}, + {255, 184, 126}, + {255, 185, 127}, + {255, 187, 129}, + {255, 189, 130}, + {255, 191, 132}, + {255, 193, 133}, + {255, 195, 135}, + {255, 197, 136}, + {255, 198, 138}, + {255, 200, 140}, + {255, 202, 141}, + {255, 204, 143}, + {254, 206, 144}, + {254, 208, 146}, + {254, 209, 148}, + {254, 211, 149}, + {254, 213, 151}, + {254, 215, 153}, + {254, 217, 155}, + {254, 219, 156}, + {254, 220, 158}, + {254, 222, 160}, + {254, 224, 162}, + {254, 226, 163}, + {253, 228, 165}, + {253, 230, 167}, + {253, 231, 169}, + {253, 233, 171}, + {253, 235, 172}, + {253, 237, 174}, + {253, 239, 176}, + {253, 241, 178}, + {253, 242, 180}, + {253, 244, 182}, + {253, 246, 184}, + {252, 248, 186}, + {252, 250, 188}, + {252, 251, 189}, + {252, 253, 191}, +}; + +#endif // MAGMA_LUT_H diff --git a/src/colourmaps/parula_lut.h b/src/colourmaps/parula_lut.h new file mode 100644 index 0000000..90824c0 --- /dev/null +++ b/src/colourmaps/parula_lut.h @@ -0,0 +1,264 @@ +#ifndef PARULA_LUT_H +#define PARULA_LUT_H + +static const unsigned char parula_name[] = "Parula"; +static const unsigned char parula[256][3] = { + {53, 42, 135}, + {53, 44, 138}, + {53, 45, 141}, + {53, 47, 144}, + {54, 48, 147}, + {54, 50, 150}, + {54, 51, 153}, + {54, 53, 157}, + {54, 54, 160}, + {54, 56, 163}, + {54, 57, 166}, + {53, 59, 169}, + {53, 60, 172}, + {52, 62, 176}, + {52, 64, 179}, + {51, 65, 182}, + {50, 67, 185}, + {49, 69, 188}, + {47, 70, 192}, + {46, 72, 195}, + {44, 74, 198}, + {42, 76, 201}, + {39, 78, 205}, + {36, 80, 208}, + {33, 82, 211}, + {29, 84, 214}, + {25, 86, 217}, + {20, 89, 219}, + {16, 91, 221}, + {12, 93, 223}, + {8, 95, 224}, + {5, 97, 225}, + {3, 98, 225}, + {2, 100, 225}, + {1, 101, 226}, + {1, 102, 226}, + {1, 104, 226}, + {1, 105, 225}, + {2, 106, 225}, + {2, 107, 225}, + {3, 108, 225}, + {4, 109, 224}, + {5, 110, 224}, + {6, 111, 223}, + {7, 112, 223}, + {8, 113, 223}, + {10, 114, 222}, + {11, 115, 222}, + {12, 116, 221}, + {13, 117, 220}, + {14, 118, 220}, + {14, 119, 219}, + {15, 120, 219}, + {16, 121, 218}, + {17, 122, 218}, + {17, 123, 217}, + {18, 124, 217}, + {18, 125, 216}, + {19, 126, 216}, + {19, 127, 215}, + {19, 128, 214}, + {20, 129, 214}, + {20, 130, 213}, + {20, 131, 213}, + {20, 132, 213}, + {20, 133, 212}, + {20, 134, 212}, + {19, 135, 211}, + {19, 136, 211}, + {19, 137, 211}, + {18, 139, 211}, + {17, 140, 211}, + {17, 141, 211}, + {16, 142, 210}, + {15, 144, 210}, + {14, 145, 210}, + {13, 146, 210}, + {12, 147, 210}, + {11, 149, 210}, + {10, 150, 210}, + {9, 151, 210}, + {8, 152, 209}, + {8, 153, 209}, + {7, 155, 209}, + {7, 156, 208}, + {6, 157, 208}, + {6, 158, 207}, + {6, 159, 207}, + {6, 160, 206}, + {6, 160, 205}, + {6, 161, 205}, + {6, 162, 204}, + {5, 163, 203}, + {5, 164, 202}, + {5, 164, 201}, + {5, 165, 200}, + {5, 166, 200}, + {5, 167, 198}, + {5, 167, 198}, + {6, 168, 197}, + {6, 169, 195}, + {6, 169, 194}, + {7, 170, 193}, + {7, 171, 192}, + {8, 171, 191}, + {9, 172, 190}, + {10, 173, 189}, + {11, 173, 188}, + {13, 174, 187}, + {14, 174, 186}, + {16, 175, 184}, + {17, 176, 183}, + {19, 176, 182}, + {20, 177, 181}, + {22, 177, 179}, + {24, 178, 178}, + {26, 178, 177}, + {28, 179, 176}, + {30, 179, 174}, + {32, 180, 173}, + {34, 180, 172}, + {36, 181, 170}, + {38, 181, 169}, + {40, 182, 167}, + {42, 182, 166}, + {45, 183, 165}, + {47, 183, 163}, + {49, 184, 162}, + {52, 184, 160}, + {54, 185, 159}, + {56, 185, 157}, + {59, 186, 156}, + {62, 186, 154}, + {64, 187, 153}, + {67, 187, 151}, + {70, 187, 150}, + {72, 188, 148}, + {75, 188, 147}, + {78, 188, 145}, + {81, 189, 144}, + {84, 189, 142}, + {87, 189, 141}, + {90, 190, 139}, + {93, 190, 138}, + {96, 190, 136}, + {99, 190, 135}, + {102, 191, 133}, + {105, 191, 132}, + {107, 191, 131}, + {110, 191, 129}, + {113, 191, 128}, + {116, 191, 127}, + {119, 191, 126}, + {122, 191, 124}, + {125, 191, 123}, + {128, 191, 122}, + {130, 191, 121}, + {133, 191, 120}, + {136, 191, 119}, + {138, 191, 118}, + {141, 191, 117}, + {143, 191, 115}, + {146, 191, 114}, + {148, 191, 113}, + {151, 191, 112}, + {153, 191, 111}, + {156, 191, 110}, + {158, 191, 110}, + {161, 191, 109}, + {163, 190, 108}, + {165, 190, 107}, + {168, 190, 106}, + {170, 190, 105}, + {172, 190, 104}, + {174, 190, 103}, + {177, 190, 102}, + {179, 190, 101}, + {181, 189, 100}, + {183, 189, 100}, + {185, 189, 99}, + {188, 189, 98}, + {190, 189, 97}, + {192, 189, 96}, + {194, 188, 95}, + {196, 188, 94}, + {198, 188, 94}, + {200, 188, 93}, + {202, 188, 92}, + {204, 187, 91}, + {206, 187, 90}, + {209, 187, 89}, + {211, 187, 88}, + {213, 187, 88}, + {215, 187, 87}, + {217, 186, 86}, + {219, 186, 85}, + {221, 186, 84}, + {223, 186, 83}, + {225, 186, 82}, + {227, 186, 81}, + {229, 186, 80}, + {231, 185, 79}, + {233, 185, 78}, + {235, 185, 77}, + {237, 185, 76}, + {239, 185, 75}, + {241, 185, 74}, + {243, 185, 73}, + {244, 186, 71}, + {246, 186, 70}, + {248, 186, 69}, + {250, 187, 67}, + {251, 188, 65}, + {252, 189, 64}, + {254, 190, 62}, + {254, 191, 60}, + {255, 192, 59}, + {255, 193, 57}, + {255, 195, 56}, + {255, 196, 54}, + {255, 197, 53}, + {255, 199, 52}, + {255, 200, 51}, + {254, 201, 49}, + {254, 203, 48}, + {253, 204, 47}, + {253, 205, 46}, + {252, 206, 45}, + {252, 208, 44}, + {251, 209, 43}, + {251, 210, 42}, + {250, 212, 41}, + {249, 213, 40}, + {249, 214, 39}, + {248, 216, 38}, + {248, 217, 37}, + {247, 218, 36}, + {247, 220, 35}, + {246, 221, 34}, + {246, 223, 33}, + {246, 224, 32}, + {245, 226, 31}, + {245, 227, 29}, + {245, 229, 28}, + {245, 230, 27}, + {245, 232, 26}, + {245, 234, 25}, + {245, 236, 24}, + {246, 237, 22}, + {246, 239, 21}, + {246, 241, 20}, + {247, 243, 19}, + {247, 245, 17}, + {248, 247, 16}, + {249, 249, 15}, + {249, 251, 13}, +}; + +#endif // PARULA_LUT_H diff --git a/src/colourmaps/pastel_rainbow_lut.h b/src/colourmaps/pastel_rainbow_lut.h new file mode 100644 index 0000000..eec2c32 --- /dev/null +++ b/src/colourmaps/pastel_rainbow_lut.h @@ -0,0 +1,41 @@ +#ifndef PASTEL_RAINBOW_LUT_H +#define PASTEL_RAINBOW_LUT_H + +static const unsigned char pastel_rainbow_name[] = "Pastel Rainbow"; +static const unsigned char pastel_rainbow[256][3] = { + {255, 179, 186}, {255, 223, 186}, {255, 255, 186}, {186, 255, 201}, + {186, 255, 255}, {186, 223, 255}, {186, 186, 255}, {223, 186, 255}, + {255, 186, 255}, {255, 186, 223}, {255, 210, 210}, {255, 220, 210}, + {255, 230, 210}, {255, 240, 210}, {250, 250, 210}, {240, 255, 210}, + {230, 255, 210}, {220, 255, 210}, {210, 255, 210}, {210, 255, 220}, + {210, 255, 230}, {210, 255, 240}, {210, 250, 250}, {210, 240, 255}, + {210, 230, 255}, {210, 220, 255}, {210, 210, 255}, {220, 210, 255}, + {230, 210, 255}, {240, 210, 255}, {250, 210, 250}, {255, 210, 240}, + {255, 210, 230}, {255, 210, 220}, {255, 210, 210}, {255, 220, 220}, + {255, 230, 230}, {255, 240, 230}, {250, 250, 230}, {240, 255, 230}, + {230, 255, 230}, {220, 255, 230}, {210, 255, 230}, {210, 255, 240}, + {210, 255, 250}, {210, 250, 255}, {210, 240, 255}, {210, 230, 255}, + {210, 220, 255}, {210, 210, 255}, {220, 210, 255}, {230, 210, 255}, + {240, 210, 255}, {250, 210, 255}, {255, 210, 250}, {255, 210, 240}, + {255, 210, 230}, {255, 210, 220}, {255, 210, 210}, {255, 220, 220}, + {255, 230, 220}, {255, 240, 220}, {250, 250, 220}, {240, 255, 220}, + {230, 255, 220}, {220, 255, 220}, {210, 255, 220}, {210, 255, 230}, + {210, 255, 240}, {210, 250, 250}, {210, 240, 255}, {210, 230, 255}, + {210, 220, 255}, {210, 210, 255}, {220, 210, 255}, {230, 210, 255}, + {240, 210, 255}, {250, 210, 255}, {255, 210, 250}, {255, 210, 240}, + {255, 210, 230}, {255, 210, 220}, {255, 210, 210}, {255, 220, 220}, + {255, 230, 220}, {255, 240, 220}, {250, 250, 220}, {240, 255, 220}, + {230, 255, 220}, {220, 255, 220}, {210, 255, 220}, {210, 255, 230}, + {210, 255, 240}, {210, 250, 250}, {210, 240, 255}, {210, 230, 255}, + {210, 220, 255}, {210, 210, 255}, {220, 210, 255}, {230, 210, 255}, + {240, 210, 255}, {250, 210, 255}, {255, 210, 250}, {255, 210, 240}, + {255, 210, 230}, {255, 210, 220}, {255, 210, 210}, {255, 220, 220}, + {255, 230, 220}, {255, 240, 220}, {250, 250, 220}, {240, 255, 220}, + {230, 255, 220}, {220, 255, 220}, {210, 255, 220}, {210, 255, 230}, + {210, 255, 240}, {210, 250, 250}, {210, 240, 255}, {210, 230, 255}, + {210, 220, 255}, {210, 210, 255}, {220, 210, 255}, {230, 210, 255}, + {240, 210, 255}, {250, 210, 255}, {255, 210, 250}, {255, 210, 240}, + {255, 210, 230}, {255, 210, 220}, {255, 210, 210} +}; + +#endif // PASTEL_RAINBOW_LUT_H diff --git a/src/colourmaps/plasma_lut.h b/src/colourmaps/plasma_lut.h new file mode 100644 index 0000000..e5791f9 --- /dev/null +++ b/src/colourmaps/plasma_lut.h @@ -0,0 +1,264 @@ +#ifndef PLASMA_LUT_H +#define PLASMA_LUT_H + +static const unsigned char plasma_name[] = "Plasma"; +static const unsigned char plasma[256][3] = { + {12, 7, 135}, + {16, 7, 136}, + {19, 6, 137}, + {22, 6, 138}, + {24, 6, 140}, + {27, 6, 141}, + {29, 6, 142}, + {31, 5, 143}, + {33, 5, 144}, + {35, 5, 145}, + {38, 5, 146}, + {40, 5, 146}, + {42, 5, 147}, + {43, 5, 148}, + {45, 4, 149}, + {47, 4, 150}, + {49, 4, 151}, + {51, 4, 151}, + {53, 4, 152}, + {54, 4, 153}, + {56, 4, 154}, + {58, 4, 154}, + {60, 3, 155}, + {61, 3, 156}, + {63, 3, 156}, + {65, 3, 157}, + {66, 3, 158}, + {68, 3, 158}, + {70, 3, 159}, + {71, 2, 160}, + {73, 2, 160}, + {75, 2, 161}, + {76, 2, 161}, + {78, 2, 162}, + {80, 2, 162}, + {81, 1, 163}, + {83, 1, 163}, + {84, 1, 164}, + {86, 1, 164}, + {88, 1, 165}, + {89, 1, 165}, + {91, 0, 165}, + {92, 0, 166}, + {94, 0, 166}, + {95, 0, 166}, + {97, 0, 167}, + {99, 0, 167}, + {100, 0, 167}, + {102, 0, 167}, + {103, 0, 168}, + {105, 0, 168}, + {106, 0, 168}, + {108, 0, 168}, + {110, 0, 168}, + {111, 0, 168}, + {113, 0, 168}, + {114, 0, 169}, + {116, 0, 169}, + {117, 0, 169}, + {119, 1, 168}, + {120, 1, 168}, + {122, 1, 168}, + {123, 2, 168}, + {125, 2, 168}, + {126, 3, 168}, + {128, 3, 168}, + {129, 4, 167}, + {131, 4, 167}, + {132, 5, 167}, + {134, 6, 167}, + {135, 7, 166}, + {136, 7, 166}, + {138, 8, 166}, + {139, 9, 165}, + {141, 11, 165}, + {142, 12, 164}, + {144, 13, 164}, + {145, 14, 163}, + {146, 15, 163}, + {148, 16, 162}, + {149, 17, 161}, + {150, 18, 161}, + {152, 19, 160}, + {153, 20, 160}, + {155, 21, 159}, + {156, 23, 158}, + {157, 24, 157}, + {158, 25, 157}, + {160, 26, 156}, + {161, 27, 155}, + {162, 28, 154}, + {164, 29, 154}, + {165, 30, 153}, + {166, 32, 152}, + {167, 33, 151}, + {169, 34, 150}, + {170, 35, 149}, + {171, 36, 149}, + {172, 37, 148}, + {173, 38, 147}, + {175, 40, 146}, + {176, 41, 145}, + {177, 42, 144}, + {178, 43, 143}, + {179, 44, 142}, + {180, 45, 141}, + {181, 46, 140}, + {183, 47, 139}, + {184, 49, 138}, + {185, 50, 137}, + {186, 51, 137}, + {187, 52, 136}, + {188, 53, 135}, + {189, 54, 134}, + {190, 55, 133}, + {191, 57, 132}, + {192, 58, 131}, + {193, 59, 130}, + {194, 60, 129}, + {195, 61, 128}, + {196, 62, 127}, + {197, 63, 126}, + {198, 64, 125}, + {199, 66, 124}, + {200, 67, 123}, + {201, 68, 122}, + {202, 69, 122}, + {203, 70, 121}, + {204, 71, 120}, + {205, 72, 119}, + {206, 73, 118}, + {207, 75, 117}, + {208, 76, 116}, + {208, 77, 115}, + {209, 78, 114}, + {210, 79, 113}, + {211, 80, 112}, + {212, 81, 112}, + {213, 83, 111}, + {214, 84, 110}, + {215, 85, 109}, + {215, 86, 108}, + {216, 87, 107}, + {217, 88, 106}, + {218, 89, 105}, + {219, 91, 105}, + {220, 92, 104}, + {220, 93, 103}, + {221, 94, 102}, + {222, 95, 101}, + {223, 96, 100}, + {224, 98, 99}, + {224, 99, 98}, + {225, 100, 98}, + {226, 101, 97}, + {227, 102, 96}, + {227, 104, 95}, + {228, 105, 94}, + {229, 106, 93}, + {230, 107, 92}, + {230, 108, 92}, + {231, 110, 91}, + {232, 111, 90}, + {232, 112, 89}, + {233, 113, 88}, + {234, 114, 87}, + {235, 116, 86}, + {235, 117, 86}, + {236, 118, 85}, + {237, 119, 84}, + {237, 121, 83}, + {238, 122, 82}, + {238, 123, 81}, + {239, 124, 80}, + {240, 126, 80}, + {240, 127, 79}, + {241, 128, 78}, + {241, 129, 77}, + {242, 131, 76}, + {242, 132, 75}, + {243, 133, 74}, + {244, 135, 73}, + {244, 136, 73}, + {245, 137, 72}, + {245, 139, 71}, + {246, 140, 70}, + {246, 141, 69}, + {247, 143, 68}, + {247, 144, 67}, + {247, 145, 67}, + {248, 147, 66}, + {248, 148, 65}, + {249, 149, 64}, + {249, 151, 63}, + {249, 152, 62}, + {250, 154, 61}, + {250, 155, 60}, + {251, 156, 60}, + {251, 158, 59}, + {251, 159, 58}, + {251, 161, 57}, + {252, 162, 56}, + {252, 164, 55}, + {252, 165, 54}, + {252, 166, 54}, + {253, 168, 53}, + {253, 169, 52}, + {253, 171, 51}, + {253, 172, 50}, + {253, 174, 49}, + {254, 175, 49}, + {254, 177, 48}, + {254, 178, 47}, + {254, 180, 46}, + {254, 181, 46}, + {254, 183, 45}, + {254, 185, 44}, + {254, 186, 43}, + {254, 188, 43}, + {254, 189, 42}, + {254, 191, 41}, + {254, 192, 41}, + {254, 194, 40}, + {254, 195, 40}, + {254, 197, 39}, + {254, 199, 39}, + {253, 200, 38}, + {253, 202, 38}, + {253, 203, 37}, + {253, 205, 37}, + {253, 207, 37}, + {252, 208, 36}, + {252, 210, 36}, + {252, 212, 36}, + {251, 213, 36}, + {251, 215, 36}, + {251, 217, 36}, + {250, 218, 36}, + {250, 220, 36}, + {249, 222, 36}, + {249, 223, 36}, + {248, 225, 37}, + {248, 227, 37}, + {247, 229, 37}, + {247, 230, 37}, + {246, 232, 38}, + {246, 234, 38}, + {245, 235, 38}, + {244, 237, 39}, + {244, 239, 39}, + {243, 241, 39}, + {242, 242, 38}, + {242, 244, 38}, + {241, 246, 37}, + {241, 247, 36}, + {240, 249, 33}, +}; + +#endif // PLASMA_LUT_H diff --git a/src/colourmaps/turbo_lut.h b/src/colourmaps/turbo_lut.h new file mode 100644 index 0000000..f3284c7 --- /dev/null +++ b/src/colourmaps/turbo_lut.h @@ -0,0 +1,264 @@ +#ifndef TURBO_LUT_H +#define TURBO_LUT_H + +static const unsigned char turbo_name[] = "Turbo"; +static const unsigned char turbo[256][3] = { + {48, 18, 59}, + {49, 21, 66}, + {51, 24, 74}, + {52, 27, 81}, + {53, 30, 88}, + {54, 33, 95}, + {55, 36, 102}, + {56, 38, 108}, + {57, 41, 115}, + {58, 44, 121}, + {59, 47, 128}, + {60, 50, 134}, + {61, 53, 139}, + {62, 56, 145}, + {62, 58, 151}, + {63, 61, 156}, + {64, 64, 162}, + {64, 67, 167}, + {65, 70, 172}, + {66, 72, 177}, + {66, 75, 182}, + {67, 78, 186}, + {67, 81, 191}, + {68, 83, 195}, + {68, 86, 199}, + {69, 89, 203}, + {69, 91, 207}, + {69, 94, 211}, + {69, 97, 215}, + {70, 99, 218}, + {70, 102, 221}, + {70, 105, 225}, + {70, 107, 228}, + {70, 110, 231}, + {70, 113, 233}, + {70, 115, 236}, + {70, 118, 238}, + {70, 120, 241}, + {70, 123, 243}, + {70, 125, 245}, + {70, 128, 247}, + {70, 130, 249}, + {70, 133, 250}, + {69, 135, 252}, + {69, 138, 253}, + {68, 140, 254}, + {68, 143, 254}, + {67, 145, 255}, + {66, 148, 255}, + {65, 150, 255}, + {63, 153, 255}, + {62, 155, 255}, + {61, 158, 254}, + {59, 161, 253}, + {58, 163, 253}, + {56, 166, 251}, + {54, 168, 250}, + {53, 171, 249}, + {51, 173, 247}, + {49, 176, 246}, + {47, 178, 244}, + {45, 181, 242}, + {44, 183, 240}, + {42, 185, 238}, + {40, 188, 236}, + {38, 190, 234}, + {37, 192, 231}, + {35, 195, 229}, + {33, 197, 226}, + {32, 199, 224}, + {31, 201, 221}, + {29, 204, 219}, + {28, 206, 216}, + {27, 208, 213}, + {26, 210, 211}, + {25, 212, 208}, + {24, 214, 205}, + {24, 216, 203}, + {24, 218, 200}, + {23, 219, 197}, + {23, 221, 195}, + {23, 223, 192}, + {24, 224, 190}, + {24, 226, 187}, + {25, 227, 185}, + {26, 229, 183}, + {27, 230, 180}, + {29, 232, 178}, + {30, 233, 175}, + {32, 234, 173}, + {34, 236, 170}, + {36, 237, 167}, + {39, 238, 164}, + {41, 239, 161}, + {44, 240, 158}, + {47, 241, 155}, + {50, 242, 152}, + {53, 243, 148}, + {56, 244, 145}, + {60, 245, 142}, + {63, 246, 139}, + {67, 247, 135}, + {70, 248, 132}, + {74, 249, 128}, + {78, 250, 125}, + {81, 250, 121}, + {85, 251, 118}, + {89, 252, 115}, + {93, 252, 111}, + {97, 253, 108}, + {101, 253, 105}, + {105, 254, 101}, + {109, 254, 98}, + {113, 254, 95}, + {117, 255, 92}, + {121, 255, 89}, + {125, 255, 86}, + {128, 255, 83}, + {132, 255, 80}, + {136, 255, 78}, + {139, 255, 75}, + {143, 255, 73}, + {146, 255, 70}, + {150, 255, 68}, + {153, 255, 66}, + {156, 254, 64}, + {159, 254, 62}, + {162, 253, 61}, + {164, 253, 59}, + {167, 252, 58}, + {170, 252, 57}, + {172, 251, 56}, + {175, 250, 55}, + {177, 249, 54}, + {180, 248, 53}, + {183, 248, 53}, + {185, 246, 52}, + {188, 245, 52}, + {191, 244, 52}, + {193, 243, 52}, + {196, 242, 51}, + {198, 240, 51}, + {201, 239, 52}, + {203, 238, 52}, + {206, 236, 52}, + {208, 235, 52}, + {210, 233, 52}, + {213, 232, 53}, + {215, 230, 53}, + {217, 228, 53}, + {219, 226, 54}, + {221, 225, 54}, + {224, 223, 55}, + {226, 221, 55}, + {228, 219, 56}, + {230, 217, 56}, + {231, 215, 56}, + {233, 213, 57}, + {235, 211, 57}, + {237, 209, 57}, + {238, 207, 58}, + {240, 205, 58}, + {241, 203, 58}, + {243, 201, 58}, + {244, 199, 58}, + {245, 197, 58}, + {247, 195, 58}, + {248, 193, 58}, + {249, 191, 57}, + {250, 189, 57}, + {250, 186, 56}, + {251, 184, 56}, + {252, 182, 55}, + {252, 180, 54}, + {253, 177, 53}, + {253, 175, 53}, + {254, 172, 52}, + {254, 169, 51}, + {254, 167, 50}, + {254, 164, 49}, + {255, 161, 47}, + {255, 158, 46}, + {255, 156, 45}, + {255, 153, 44}, + {254, 150, 43}, + {254, 147, 42}, + {254, 144, 40}, + {254, 141, 39}, + {253, 138, 38}, + {253, 135, 36}, + {252, 132, 35}, + {252, 129, 34}, + {251, 126, 32}, + {251, 123, 31}, + {250, 120, 30}, + {249, 117, 28}, + {248, 114, 27}, + {248, 111, 26}, + {247, 108, 25}, + {246, 105, 23}, + {245, 102, 22}, + {244, 99, 21}, + {243, 96, 20}, + {242, 93, 19}, + {240, 91, 17}, + {239, 88, 16}, + {238, 85, 15}, + {237, 83, 14}, + {235, 80, 14}, + {234, 78, 13}, + {233, 75, 12}, + {231, 73, 11}, + {230, 71, 10}, + {228, 69, 10}, + {227, 66, 9}, + {225, 64, 9}, + {223, 62, 8}, + {222, 60, 7}, + {220, 58, 7}, + {218, 56, 6}, + {216, 54, 6}, + {214, 52, 5}, + {212, 50, 5}, + {210, 49, 5}, + {208, 47, 4}, + {206, 45, 4}, + {204, 43, 3}, + {202, 41, 3}, + {200, 40, 3}, + {198, 38, 2}, + {195, 36, 2}, + {193, 35, 2}, + {191, 33, 2}, + {188, 31, 1}, + {186, 30, 1}, + {183, 28, 1}, + {180, 27, 1}, + {178, 25, 1}, + {175, 24, 1}, + {172, 22, 1}, + {170, 21, 1}, + {167, 20, 1}, + {164, 18, 1}, + {161, 17, 1}, + {158, 16, 1}, + {155, 15, 1}, + {152, 13, 1}, + {149, 12, 1}, + {146, 11, 1}, + {142, 10, 1}, + {139, 9, 1}, + {136, 8, 1}, + {133, 7, 1}, + {129, 6, 2}, + {126, 5, 2}, + {122, 4, 2}, +}; + +#endif // TURBO_LUT_H diff --git a/src/colourmaps/viridis_lut.h b/src/colourmaps/viridis_lut.h new file mode 100644 index 0000000..6d023da --- /dev/null +++ b/src/colourmaps/viridis_lut.h @@ -0,0 +1,264 @@ +#ifndef VIRIDIS_LUT_H +#define VIRIDIS_LUT_H + +static const unsigned char viridis_name[] = "Viridis"; +static const unsigned char viridis[256][3] = { + {68, 1, 84}, + {68, 2, 85}, + {69, 3, 87}, + {69, 5, 88}, + {69, 6, 90}, + {70, 8, 91}, + {70, 9, 93}, + {70, 11, 94}, + {70, 12, 96}, + {71, 14, 97}, + {71, 15, 98}, + {71, 17, 100}, + {71, 18, 101}, + {71, 20, 102}, + {72, 21, 104}, + {72, 22, 105}, + {72, 24, 106}, + {72, 25, 108}, + {72, 26, 109}, + {72, 28, 110}, + {72, 29, 111}, + {72, 30, 112}, + {72, 32, 113}, + {72, 33, 115}, + {72, 34, 116}, + {72, 36, 117}, + {72, 37, 118}, + {72, 38, 119}, + {72, 39, 120}, + {71, 41, 121}, + {71, 42, 121}, + {71, 43, 122}, + {71, 44, 123}, + {71, 46, 124}, + {70, 47, 125}, + {70, 48, 126}, + {70, 49, 126}, + {70, 51, 127}, + {69, 52, 128}, + {69, 53, 129}, + {69, 54, 129}, + {68, 56, 130}, + {68, 57, 131}, + {68, 58, 131}, + {67, 59, 132}, + {67, 60, 132}, + {67, 62, 133}, + {66, 63, 133}, + {66, 64, 134}, + {65, 65, 134}, + {65, 66, 135}, + {65, 67, 135}, + {64, 69, 136}, + {64, 70, 136}, + {63, 71, 136}, + {63, 72, 137}, + {62, 73, 137}, + {62, 74, 137}, + {61, 75, 138}, + {61, 77, 138}, + {60, 78, 138}, + {60, 79, 138}, + {59, 80, 139}, + {59, 81, 139}, + {58, 82, 139}, + {58, 83, 139}, + {57, 84, 140}, + {57, 85, 140}, + {56, 86, 140}, + {56, 87, 140}, + {55, 88, 140}, + {55, 89, 140}, + {54, 91, 141}, + {54, 92, 141}, + {53, 93, 141}, + {53, 94, 141}, + {52, 95, 141}, + {52, 96, 141}, + {51, 97, 141}, + {51, 98, 141}, + {51, 99, 141}, + {50, 100, 142}, + {50, 101, 142}, + {49, 102, 142}, + {49, 103, 142}, + {48, 104, 142}, + {48, 105, 142}, + {47, 106, 142}, + {47, 107, 142}, + {47, 108, 142}, + {46, 109, 142}, + {46, 110, 142}, + {45, 111, 142}, + {45, 112, 142}, + {45, 112, 142}, + {44, 113, 142}, + {44, 114, 142}, + {43, 115, 142}, + {43, 116, 142}, + {43, 117, 142}, + {42, 118, 142}, + {42, 119, 142}, + {41, 120, 142}, + {41, 121, 142}, + {41, 122, 142}, + {40, 123, 142}, + {40, 124, 142}, + {40, 125, 142}, + {39, 126, 142}, + {39, 127, 142}, + {38, 128, 142}, + {38, 129, 142}, + {38, 130, 142}, + {37, 131, 142}, + {37, 131, 142}, + {37, 132, 142}, + {36, 133, 142}, + {36, 134, 142}, + {35, 135, 142}, + {35, 136, 142}, + {35, 137, 142}, + {34, 138, 141}, + {34, 139, 141}, + {34, 140, 141}, + {33, 141, 141}, + {33, 142, 141}, + {33, 143, 141}, + {32, 144, 141}, + {32, 145, 140}, + {32, 146, 140}, + {32, 147, 140}, + {31, 147, 140}, + {31, 148, 140}, + {31, 149, 139}, + {31, 150, 139}, + {31, 151, 139}, + {30, 152, 139}, + {30, 153, 138}, + {30, 154, 138}, + {30, 155, 138}, + {30, 156, 137}, + {30, 157, 137}, + {30, 158, 137}, + {30, 159, 136}, + {30, 160, 136}, + {31, 161, 136}, + {31, 162, 135}, + {31, 163, 135}, + {31, 163, 134}, + {32, 164, 134}, + {32, 165, 134}, + {33, 166, 133}, + {33, 167, 133}, + {34, 168, 132}, + {35, 169, 131}, + {35, 170, 131}, + {36, 171, 130}, + {37, 172, 130}, + {38, 173, 129}, + {39, 174, 129}, + {40, 175, 128}, + {41, 175, 127}, + {42, 176, 127}, + {43, 177, 126}, + {44, 178, 125}, + {46, 179, 124}, + {47, 180, 124}, + {48, 181, 123}, + {50, 182, 122}, + {51, 183, 121}, + {53, 183, 121}, + {54, 184, 120}, + {56, 185, 119}, + {57, 186, 118}, + {59, 187, 117}, + {61, 188, 116}, + {62, 189, 115}, + {64, 190, 114}, + {66, 190, 113}, + {68, 191, 112}, + {70, 192, 111}, + {72, 193, 110}, + {73, 194, 109}, + {75, 194, 108}, + {77, 195, 107}, + {79, 196, 106}, + {81, 197, 105}, + {83, 198, 104}, + {85, 198, 102}, + {88, 199, 101}, + {90, 200, 100}, + {92, 201, 99}, + {94, 201, 98}, + {96, 202, 96}, + {98, 203, 95}, + {101, 204, 94}, + {103, 204, 92}, + {105, 205, 91}, + {108, 206, 90}, + {110, 206, 88}, + {112, 207, 87}, + {115, 208, 85}, + {117, 208, 84}, + {119, 209, 82}, + {122, 210, 81}, + {124, 210, 79}, + {127, 211, 78}, + {129, 212, 76}, + {132, 212, 75}, + {134, 213, 73}, + {137, 213, 72}, + {139, 214, 70}, + {142, 215, 68}, + {144, 215, 67}, + {147, 216, 65}, + {149, 216, 63}, + {152, 217, 62}, + {155, 217, 60}, + {157, 218, 58}, + {160, 218, 57}, + {163, 219, 55}, + {165, 219, 53}, + {168, 220, 51}, + {171, 220, 50}, + {173, 221, 48}, + {176, 221, 46}, + {179, 221, 45}, + {181, 222, 43}, + {184, 222, 41}, + {187, 223, 39}, + {189, 223, 38}, + {192, 223, 36}, + {195, 224, 35}, + {197, 224, 33}, + {200, 225, 32}, + {203, 225, 30}, + {205, 225, 29}, + {208, 226, 28}, + {211, 226, 27}, + {213, 226, 26}, + {216, 227, 25}, + {219, 227, 24}, + {221, 227, 24}, + {224, 228, 24}, + {226, 228, 24}, + {229, 228, 24}, + {232, 229, 25}, + {234, 229, 25}, + {237, 229, 26}, + {239, 230, 27}, + {242, 230, 28}, + {244, 230, 30}, + {247, 230, 31}, + {249, 231, 33}, + {251, 231, 35}, + {254, 231, 36}, +}; + +#endif // VIRIDIS_LUT_H diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..702778a --- /dev/null +++ b/src/input.c @@ -0,0 +1,65 @@ +#include "input.h" +#include "mandelbrot.h" +#include + +void processInput(GLFWwindow *window, double *zoom, double *offsetX, + double *offsetY) { + if (glfwGetKey(window, GLFW_KEY_0) == GLFW_PRESS) { + set_palette(VIRIDIS_LUT_COLOR); + } + if (glfwGetKey(window, GLFW_KEY_1) == GLFW_PRESS) { + set_palette(CUBEHELIX_LUT_COLOR); + } + if (glfwGetKey(window, GLFW_KEY_2) == GLFW_PRESS) { + set_palette(HSV_LUT_COLOR); + } + if (glfwGetKey(window, GLFW_KEY_3) == GLFW_PRESS) { + set_palette(INFERNO_LUT_COLOR); + } + if (glfwGetKey(window, GLFW_KEY_4) == GLFW_PRESS) { + set_palette(MAGMA_LUT_COLOR); + } + if (glfwGetKey(window, GLFW_KEY_5) == GLFW_PRESS) { + set_palette(PARULA_LUT_COLOR); + } + if (glfwGetKey(window, GLFW_KEY_6) == GLFW_PRESS) { + set_palette(PASTEL_RAINBOW_LUT_COLOR); + } + if (glfwGetKey(window, GLFW_KEY_7) == GLFW_PRESS) { + set_palette(PLASMA_LUT_COLOR); + } + if (glfwGetKey(window, GLFW_KEY_8) == GLFW_PRESS) { + set_palette(TURBO_LUT_COLOR); + } + if (glfwGetKey(window, GLFW_KEY_9) == GLFW_PRESS) { + set_palette(CIVIDIS_LUT_COLOR); + } + + if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS) { + glfwSetWindowShouldClose(window, GLFW_TRUE); + } + if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS) { + *offsetY += 0.11 / *zoom; + } + if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS) { + *offsetY -= 0.11 / *zoom; + } + if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) { + *offsetX -= 0.11 / *zoom; + } + if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS) { + *offsetX += 0.11 / *zoom; + } + if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS) { + *zoom = 1.0; + *offsetX = -0.75; + *offsetY = 0.0; + } + + if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS) { + *zoom *= 1.07; + } + if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS) { + *zoom /= 1.08; + } +} diff --git a/src/input.h b/src/input.h new file mode 100644 index 0000000..12f4fcc --- /dev/null +++ b/src/input.h @@ -0,0 +1,8 @@ +#ifndef INPUT_H +#define INPUT_H + +#include + +void processInput(GLFWwindow *window, double *zoom, double *offsetX, double *offsetY); + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..e16d8e5 --- /dev/null +++ b/src/main.c @@ -0,0 +1,233 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define STB_EASY_FONT_IMPLEMENTATION +#include "stb_easy_font.h" + +#include "input.h" +#include "mandelbrot.h" +#include "mandelbrot_opencl_kernels.h" +#include "render.h" + +#define WINDOW_WIDTH 960 +#define WINDOW_HEIGHT 540 + +// Global variables for zoom and offsets +double zoom = 1.0; +double offsetX = -0.75; +double offsetY = 0.0; + +// Mouse state for panning +bool isMouseDragging = false; +double lastMouseX = 0, lastMouseY = 0; + +double lastTime = 0.0; +int frameCount = 0; +double currentFPS = 0.0; +double targetFrameTime = 1.0 / 10.0; // Target 30 FPS + +// Mouse scroll callback for zooming +void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) { + // Zoom in or out depending on the scroll direction + if (yoffset > 0) { + zoom *= 1.1; // Zoom in (increase resolution) + } else { + zoom /= 1.1; // Zoom out (decrease resolution) + } + + // Clamp zoom to a reasonable range to avoid excessive zooming + if (zoom < 0.1) + zoom = 0.1; // Minimum zoom limit + if (zoom > 10000) + zoom = 10000; // Maximum zoom limit +} + +// Mouse button callback for panning +void mouse_button_callback(GLFWwindow *window, int button, int action, + int mods) { + if (button == GLFW_MOUSE_BUTTON_LEFT) { + if (action == GLFW_PRESS) { + isMouseDragging = true; + glfwGetCursorPos(window, &lastMouseX, &lastMouseY); + } else if (action == GLFW_RELEASE) { + isMouseDragging = false; + } + } +} + +// Mouse motion callback for panning +void cursor_pos_callback(GLFWwindow *window, double xpos, double ypos) { + if (isMouseDragging) { + double dx = xpos - lastMouseX; + double dy = ypos - lastMouseY; + + // Base pan factor for adjusting sensitivity + double basePanFactor = 0.01; // Base pan factor for small movements + + // Apply logarithmic scaling to pan factor based on zoom level + // We reduce the pan factor more gradually at high zoom levels + double zoomAdjustedFactor = + basePanFactor / log(zoom * 100.0); // Logarithmic scaling with zoom + + // Clamp pan factor to avoid excessive movement or tiny shifts + zoomAdjustedFactor = fmin(fmax(zoomAdjustedFactor, 0.0001), + 0.0001); // Limit sensitivity range + + // Update offsets based on mouse movement with the adjusted sensitivity + offsetX -= dx * zoomAdjustedFactor; // Horizontal pan + offsetY += dy * zoomAdjustedFactor; // Vertical pan + + lastMouseX = xpos; + lastMouseY = ypos; + } +} + +void drawText(const char *text, const float x, const float y) { + char buffer[99999]; // ~500 chars + + glColor3f(1.0f, 1.0f, 1.0f); // White text + + glEnableClientState(GL_VERTEX_ARRAY); + const int num_quads = + stb_easy_font_print(x, y, (char *)text, NULL, buffer, sizeof(buffer)); + glVertexPointer(2, GL_FLOAT, 16, buffer); + glDrawArrays(GL_QUADS, 0, num_quads * 4); + glDisableClientState(GL_VERTEX_ARRAY); +} + +int main() { + opencl_kernel_manager_init(); + double frameDuration = 0.0; + if (!glfwInit()) { + return -1; + } + + GLFWwindow *window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, + "Mandelbrot Renderer", NULL, NULL); + if (!window) { + glfwTerminate(); + return -1; + } + + glfwMakeContextCurrent(window); + + // Set up input callbacks + glfwSetScrollCallback(window, scroll_callback); + glfwSetMouseButtonCallback(window, mouse_button_callback); + glfwSetCursorPosCallback(window, cursor_pos_callback); + + glfwSwapInterval(1); // Enable vsync + + // Initialize OpenGL context (GLEW) + if (glewInit() != GLEW_OK) { + printf("GLEW initialization failed.\n"); + return -1; + } + + // SuperSample setup + GLuint fbo, highResTexture; + const int scaleFactor = 2; // Render at 2x + const int highW = WINDOW_WIDTH * scaleFactor; + const int highH = WINDOW_HEIGHT * scaleFactor; + + glGenTextures(1, &highResTexture); + glBindTexture(GL_TEXTURE_2D, highResTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, highW, highH, 0, GL_RGB, + GL_UNSIGNED_BYTE, NULL); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glGenFramebuffers(1, &fbo); + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + highResTexture, 0); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { + printf("Framebuffer not complete.\n"); + return -1; + } + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + + // Main rendering loop + unsigned char *image = malloc(highW * highH * 3); + while (!glfwWindowShouldClose(window)) { + const double currentTime = + glfwGetTime(); // glfwGetTime() returns seconds as double + frameCount++; + + // If 1 second has passed, update FPS + if (currentTime - lastTime >= 1.0) { + currentFPS = frameCount / (currentTime - lastTime); + lastTime = currentTime; + frameCount = 0; + } + + // Poll for events and handle input + processInput(window, &zoom, &offsetX, &offsetY); + + // Clear screen + glClear(GL_COLOR_BUFFER_BIT); + + // Render Mandelbrot set, passing the window as an argument + renderMandelbrot(window, zoom, offsetX, offsetY, image, highResTexture, + scaleFactor, fbo); + + char info[256]; + snprintf(info, sizeof(info), + "Zoom: %.6e\nOffset: (%.6e, %.6e)\nFPS: %.1f\nFrame Time: %.2f " + "ms\nPalette: %s", + zoom, offsetX, offsetY, currentFPS, frameDuration * 1000.0, + get_palette_name()); + + // Set orthographic projection for 2D text + int winW, winH; + glfwGetFramebufferSize(window, &winW, &winH); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, winW, winH, 0, -1, 1); // Top-left = (0,0) + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + // Draw the text + drawText(info, 10, 10); + + // Restore previous matrices + glPopMatrix(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + + // Swap buffers + glfwSwapBuffers(window); + glfwPollEvents(); + + const double frameEndTime = glfwGetTime(); + frameDuration = frameEndTime - currentTime; + + if (frameDuration < targetFrameTime) { + const double sleepTime = targetFrameTime - frameDuration; + + struct timespec ts; + ts.tv_sec = (time_t)sleepTime; + ts.tv_nsec = (long)((sleepTime - ts.tv_sec) * 1e9); + nanosleep(&ts, NULL); + } + } + free(image); + + glfwDestroyWindow(window); + glfwTerminate(); + + opencl_kernel_manager_shutdown(); + return 0; +} diff --git a/src/mandelbrot.c b/src/mandelbrot.c new file mode 100644 index 0000000..e836596 --- /dev/null +++ b/src/mandelbrot.c @@ -0,0 +1,382 @@ +#include +#include +#include + +#include "mandelbrot.h" + +#include "colourmaps/colourmaps.h" +#include "mandelbrot_opencl_kernels.h" + +#define MAX_ITERATIONS 10000 // Increase iterations for more detail +#define VEC_SIZE 8 // AVX2 vector size + +static double colorShift = 0.0; +static const unsigned char (*activePalette)[256][3] = &viridis; +static colourmap_type currentPalette = VIRIDIS_LUT_COLOR; + +const char *get_palette_name() { + switch (currentPalette) { + case VIRIDIS_LUT_COLOR: + return (const char *)viridis_name; + case CUBEHELIX_LUT_COLOR: + return (const char *)cubehelix_name; + case CIVIDIS_LUT_COLOR: + return (const char *)cividis_name; + case HSV_LUT_COLOR: + return (const char *)hsv_name; + case INFERNO_LUT_COLOR: + return (const char *)inferno_name; + case MAGMA_LUT_COLOR: + return (const char *)magma_name; + case PARULA_LUT_COLOR: + return (const char *)parula_name; + case PASTEL_RAINBOW_LUT_COLOR: + return (const char *)pastel_rainbow_name; + case PLASMA_LUT_COLOR: + return (const char *)plasma_name; + case TURBO_LUT_COLOR: + return (const char *)turbo_name; + } +} + +void set_palette(const colourmap_type choice) { + currentPalette = choice; + switch (choice) { + case CIVIDIS_LUT_COLOR: + activePalette = &cividis; + break; + case CUBEHELIX_LUT_COLOR: + activePalette = &cubehelix; + break; + case HSV_LUT_COLOR: + activePalette = &hsv; + break; + case INFERNO_LUT_COLOR: + activePalette = &inferno; + break; + case MAGMA_LUT_COLOR: + activePalette = &magma; + break; + case PARULA_LUT_COLOR: + activePalette = &parula; + break; + case PASTEL_RAINBOW_LUT_COLOR: + activePalette = &pastel_rainbow; + break; + case PLASMA_LUT_COLOR: + activePalette = &plasma; + break; + case TURBO_LUT_COLOR: + activePalette = &turbo; + break; + case VIRIDIS_LUT_COLOR: + activePalette = &viridis; + break; + default: + activePalette = &viridis; + break; + } +} + +void mandelbrot_long_double(const long double zoom, const long double offsetX, + const long double offsetY, const int width, + const int height, const int maxIterations, + unsigned char *restrict image) { + const long double scale = 3.0L / zoom; + const long double invW = 1.0L / width; + const long double invH = 1.0L / height; + const long double baseReal = -0.5L * scale + offsetX; + const long double baseImag = -0.5L * scale + offsetY; + +#pragma omp parallel for schedule(dynamic) + for (int py = 0; py < height; py++) { + long double imagPart = py * invH * scale + baseImag; + +#pragma omp simd + for (int px = 0; px < width; px++) { + long double realPart = px * invW * scale + baseReal; + + long double real = realPart; + long double imag = imagPart; + + int iteration = 0; + while (iteration < maxIterations) { + long double realSquared = real * real; + long double imagSquared = imag * imag; + if (realSquared + imagSquared > 4.0L) + break; + + long double tempReal = realSquared - imagSquared + realPart; + imag = 2.0L * real * imag + imagPart; + real = tempReal; + + iteration++; + } + + int i = (py * width + px) * 3; + if (iteration == maxIterations) { + image[i + 0] = 0; + image[i + 1] = 0; + image[i + 2] = 0; + } else { + image[i + 0] = (*activePalette)[iteration][0]; + image[i + 1] = (*activePalette)[iteration][1]; + image[i + 2] = (*activePalette)[iteration][2]; + } + } + } +} + +static inline __m256d fast_log2_avx2(__m256d x) { + __m256i xi = _mm256_castpd_si256(x); + xi = _mm256_srli_epi64(xi, 52); + __m256d exp = _mm256_cvtepi64_pd(xi); + exp = _mm256_sub_pd(exp, _mm256_set1_pd(1023.0)); + return exp; +} + +void mandelbrot_avx2(const double zoom, const double offsetX, + const double offsetY, const int width, const int height, + const int maxIterations, unsigned char *restrict image) { + const double scale = 3.0 / zoom; + const double invW = 1.0 / width; + const double invH = 1.0 / height; + const double scaledInvW = invW * scale; + const double offsetReal = offsetX - 0.5 * scale; + +#pragma omp parallel for + for (int py = 0; py < height; py++) { + const double y0 = ((double)py * invH - 0.5) * scale + offsetY; + + for (int px = 0; px < width; px += VEC_SIZE) { + __m256d x_pixel = _mm256_set_pd(px + 3, px + 2, px + 1, px); + __m256d x0 = _mm256_fmadd_pd(x_pixel, _mm256_set1_pd(scaledInvW), + _mm256_set1_pd(offsetReal)); + __m256d y0v = _mm256_set1_pd(y0); + + __m256d x = x0; + __m256d y = y0v; + __m256d iter = _mm256_setzero_pd(); + + const __m256d two = _mm256_set1_pd(2.0); + const __m256d four = _mm256_set1_pd(4.0); + + for (int i = 0; i < maxIterations; i++) { + __m256d x2 = _mm256_mul_pd(x, x); + __m256d y2 = _mm256_mul_pd(y, y); + __m256d xy = _mm256_mul_pd(x, y); + + __m256d mag2 = _mm256_add_pd(x2, y2); + __m256d mask = _mm256_cmp_pd(mag2, four, _CMP_LT_OQ); + + if (_mm256_movemask_pd(mask) == 0) + break; + + x = _mm256_add_pd(_mm256_sub_pd(x2, y2), x0); + y = _mm256_fmadd_pd(two, xy, y0v); + + iter = _mm256_add_pd(iter, _mm256_and_pd(mask, _mm256_set1_pd(1.0))); + } + + __m256d final_iter = iter; + __m256d x2 = _mm256_mul_pd(x, x); + __m256d y2 = _mm256_mul_pd(y, y); + __m256d zn = _mm256_add_pd(x2, y2); + + __m256d log2_zn = fast_log2_avx2(zn); + __m256d log_zn = _mm256_mul_pd(log2_zn, _mm256_set1_pd(log(2.0) / 2.0)); + __m256d log2_logzn = fast_log2_avx2(log_zn); + __m256d nu = _mm256_div_pd(log2_logzn, _mm256_set1_pd(log(2.0))); + + __m256d smooth = + _mm256_sub_pd(_mm256_add_pd(final_iter, _mm256_set1_pd(1.0)), nu); + __m256d t = _mm256_div_pd(smooth, _mm256_set1_pd((double)maxIterations)); + + double smooth_vals[VEC_SIZE]; + double iter_vals[VEC_SIZE]; + _mm256_storeu_pd(smooth_vals, t); + _mm256_storeu_pd(iter_vals, final_iter); + + for (int i = 0; i < VEC_SIZE; i++) { + int offset = ((py * width) + (px + i)) * 3; + + if ((int)iter_vals[i] >= maxIterations) { + image[offset + 0] = 0; + image[offset + 1] = 0; + image[offset + 2] = 0; + } else { + double t_shifted = fmod(smooth_vals[i] + colorShift, 1.0); + int idx = (int)(t_shifted * 255.0); + if (idx < 0) + idx = 0; + if (idx > 255) + idx = 255; + + image[offset + 0] = viridis[idx][0]; + image[offset + 1] = viridis[idx][1]; + image[offset + 2] = viridis[idx][2]; + } + } + } + } +} + +__m512d fast_log2_avx512(__m512d x) { + __m512i xi = _mm512_castpd_si512(x); + xi = _mm512_srli_epi64(xi, 52); + __m512d exp = _mm512_cvtepi64_pd(xi); + exp = _mm512_sub_pd(exp, _mm512_set1_pd(1023.0)); + return exp; +} + +void mandelbrot_avx512(const double zoom, const double offsetX, + const double offsetY, const int width, const int height, + const int maxIterations, unsigned char *restrict image) { + const double scale = 3.0 / zoom; + const double invW = 1.0 / width; + const double invH = 1.0 / height; + const double scaledInvW = invW * scale; + const double offsetReal = offsetX - 0.5 * scale; + +#pragma omp parallel for + for (int py = 0; py < height; py++) { + const double y0 = ((double)py * invH - 0.5) * scale + offsetY; + + for (int px = 0; px < width; px += VEC_SIZE) { + const __m512d x_pixel = _mm512_set_pd(px + 7, px + 6, px + 5, px + 4, + px + 3, px + 2, px + 1, px); + const __m512d x0 = _mm512_fmadd_pd(x_pixel, _mm512_set1_pd(scaledInvW), + _mm512_set1_pd(offsetReal)); + const __m512d y0v = _mm512_set1_pd(y0); + + __m512d x = x0; + __m512d y = y0v; + __m512d iter = _mm512_setzero_pd(); + + const __m512d two = _mm512_set1_pd(2.0); + const __m512d four = _mm512_set1_pd(4.0); + + for (int i = 0; i < maxIterations; i++) { + const __m512d x2 = _mm512_mul_pd(x, x); + const __m512d y2 = _mm512_mul_pd(y, y); + const __m512d xy = _mm512_mul_pd(x, y); + + const __m512d mag2 = _mm512_add_pd(x2, y2); + const __mmask8 mask = _mm512_cmp_pd_mask(mag2, four, _CMP_LT_OQ); + + if (mask == 0) + break; + + x = _mm512_add_pd(_mm512_sub_pd(x2, y2), x0); + y = _mm512_fmadd_pd(two, xy, y0v); + + iter = _mm512_mask_add_pd(iter, mask, iter, _mm512_set1_pd(1.0)); + } + + const __m512d final_iter = iter; + const __m512d x2 = _mm512_mul_pd(x, x); + const __m512d y2 = _mm512_mul_pd(y, y); + const __m512d zn = _mm512_add_pd(x2, y2); + + const __m512d log2_zn = fast_log2_avx512(zn); + const __m512d log_zn = + _mm512_mul_pd(log2_zn, _mm512_set1_pd(log(2.0) / 2.0)); + const __m512d log2_logzn = fast_log2_avx512(log_zn); + const __m512d nu = _mm512_div_pd(log2_logzn, _mm512_set1_pd(log(2.0))); + + const __m512d smooth = + _mm512_sub_pd(_mm512_add_pd(final_iter, _mm512_set1_pd(1.0)), nu); + const __m512d t = + _mm512_div_pd(smooth, _mm512_set1_pd((double)maxIterations)); + + double smooth_vals[VEC_SIZE]; + double iter_vals[VEC_SIZE]; + _mm512_storeu_pd(smooth_vals, t); + _mm512_storeu_pd(iter_vals, final_iter); + + for (int i = 0; i < VEC_SIZE; i++) { + const int offset = ((py * width) + (px + i)) * 3; + + if ((int)iter_vals[i] >= maxIterations) { + image[offset + 0] = 0; + image[offset + 1] = 0; + image[offset + 2] = 0; + } else { + const double t_shifted = fmod(smooth_vals[i] + colorShift, 1.0); + const double ft = t_shifted * 255.0; + int idx = (int)ft; + const double frac = ft - idx; + if (idx < 0) + idx = 0; + if (idx >= 255) + idx = 254; + + for (int ch = 0; ch < 3; ++ch) { + image[offset + ch] = + (unsigned char)((1.0 - frac) * (*activePalette)[idx][ch] + + frac * (*activePalette)[idx + 1][ch]); + } + } + } + } + } +} + +int computeMaxIterations(const long double zoom) { + const int baseIterations = 150; + const double growthRate = 150.0; // How fast it grows + + int dynamicMax = (int)(baseIterations + log2l(zoom) * growthRate); + + // Clamp to reasonable bounds + if (dynamicMax < baseIterations) + dynamicMax = baseIterations; + if (dynamicMax > MAX_ITERATIONS) + dynamicMax = MAX_ITERATIONS; + + return dynamicMax; +} + +// OpenCL standard (double) Mandelbrot call +void mandelbrot_opencl_standard(const double zoom, const double offsetX, + const double offsetY, const int width, + const int height, int maxIterations, + unsigned char *restrict image) { + launch_opencl_kernel("mandelbrot_kernel", zoom, offsetX, offsetY, width, + height, maxIterations, image); +} + +// OpenCL double-double Mandelbrot call +void mandelbrot_opencl_double_double(const double zoom, const double offsetX, + const double offsetY, const int width, + const int height, int maxIterations, + unsigned char *restrict image) { + launch_opencl_kernel("mandelbrot_kernel_dd", zoom, offsetX, offsetY, width, + height, maxIterations, image); +} + +void mandelbrot(const long double zoom, const long double offsetX, + const long double offsetY, const int width, const int height, + unsigned char *restrict image) { + colorShift += 0.0005; // Slow shift + if (colorShift > 0.9) + colorShift -= 0.9; + + const int dynamicIterations = computeMaxIterations(zoom); + +#ifdef USE_OPENCL + if (zoom < 1e12) + mandelbrot_opencl_standard(zoom, offsetX, offsetY, width, height, + dynamicIterations, image); + else + mandelbrot_opencl_double_double(zoom, offsetX, offsetY, width, height, + dynamicIterations, image); +#else + if (zoom < 1e14) + mandelbrot_avx512(zoom, offsetX, offsetY, width, height, dynamicIterations, + image); + else + mandelbrot_long_double(zoom, offsetX, offsetY, width, height, + dynamicIterations, image); +#endif +} diff --git a/src/mandelbrot.h b/src/mandelbrot.h new file mode 100644 index 0000000..a3e1c80 --- /dev/null +++ b/src/mandelbrot.h @@ -0,0 +1,12 @@ +#ifndef MANDELBROT_H +#define MANDELBROT_H + +#include "colourmaps/colourmaps.h" + +void set_palette(colourmap_type choice); +const char* get_palette_name(); + +void mandelbrot(long double zoom, long double offsetX, long double offsetY, int width, int height, + unsigned char* restrict image); + +#endif diff --git a/src/mandelbrot_kernel.cl b/src/mandelbrot_kernel.cl new file mode 100644 index 0000000..3ae9ed3 --- /dev/null +++ b/src/mandelbrot_kernel.cl @@ -0,0 +1,174 @@ +__kernel void mandelbrot_kernel( + __global uchar *output, + const double zoom, + const double offsetX, + const double offsetY, + const int width, + const int height, + const int maxIterations +) +{ + const int px = get_global_id(0); + const int py = get_global_id(1); + + if (px >= width || py >= height) + return; + + const double scale = 3.0 / zoom; + const double real0 = ((double)px / width - 0.5) * scale + offsetX; + const double imag0 = ((double)py / height - 0.5) * scale + offsetY; + + double real = real0; + double imag = imag0; + + int iteration = 0; + while (real*real + imag*imag <= 4.0 && iteration < maxIterations) + { + double realTemp = real * real - imag * imag + real0; + imag = 2.0 * real * imag + imag0; + real = realTemp; + iteration++; + } + + const int idx = (py * width + px) * 3; + + if (iteration == maxIterations) { + output[idx + 0] = 0; + output[idx + 1] = 0; + output[idx + 2] = 0; + } else { + float t = (float)iteration / (float)maxIterations; + output[idx + 0] = (uchar)(9.0f * (1.0f - t) * t * t * t * 255.0f); + output[idx + 1] = (uchar)(15.0f * (1.0f - t) * (1.0f - t) * t * t * 255.0f); + output[idx + 2] = (uchar)(8.5f * (1.0f - t) * (1.0f - t) * (1.0f - t) * t * 255.0f); + } +} + +// Double Double +typedef struct { + double hi; + double lo; +} dd_real; + +inline dd_real dd_add(dd_real a, dd_real b) +{ + double s = a.hi + b.hi; + double v = s - a.hi; + double t = ((b.hi - v) + (a.hi - (s - v))) + a.lo + b.lo; + dd_real result; + result.hi = s + t; + result.lo = t - (result.hi - s); + return result; +} + +inline dd_real dd_sub(dd_real a, dd_real b) +{ + double s = a.hi - b.hi; + double v = s - a.hi; + double t = ((-b.hi - v) + (a.hi - (s - v))) + a.lo - b.lo; + dd_real result; + result.hi = s + t; + result.lo = t - (result.hi - s); + return result; +} + +inline dd_real dd_mul(dd_real a, dd_real b) +{ + const double split = 134217729.0; // 2^27 + 1 + + double cona = a.hi * split; + double conb = b.hi * split; + double a1 = cona - (cona - a.hi); + double b1 = conb - (conb - b.hi); + double a2 = a.hi - a1; + double b2 = b.hi - b1; + + double c11 = a.hi * b.hi; + double c21 = a2 * b2 - (((c11 - a1 * b1) - a2 * b1) - a1 * b2); + + double c2 = a.hi * b.lo + a.lo * b.hi; + + double t1 = c11 + c2; + double e = t1 - c11; + double t2 = ((c2 - e) + (c11 - (t1 - e))) + c21 + a.lo * b.lo; + + dd_real result; + result.hi = t1 + t2; + result.lo = t2 - (result.hi - t1); + return result; +} + +inline dd_real dd_sqr(dd_real a) +{ + return dd_mul(a, a); +} + +inline double dd_mag2(dd_real a, dd_real b) +{ + double r = a.hi * a.hi + b.hi * b.hi; + return r; +} + +__kernel void mandelbrot_kernel_dd( + __global uchar *output, + const double zoom, + const double offsetX, + const double offsetY, + const int width, + const int height, + const int maxIterations +) +{ + const int px = get_global_id(0); + const int py = get_global_id(1); + + if (px >= width || py >= height) + return; + + const double scale = 3.0 / zoom; + const double centerReal = offsetX; + const double centerImag = offsetY; + + dd_real real0; + real0.hi = ((double)px / width - 0.5) * scale + centerReal; + real0.lo = 0.0; + + dd_real imag0; + imag0.hi = ((double)py / height - 0.5) * scale + centerImag; + imag0.lo = 0.0; + + dd_real real = real0; + dd_real imag = imag0; + + int iteration = 0; + while (dd_mag2(real, imag) <= 4.0 && iteration < maxIterations) + { + dd_real realSq = dd_sqr(real); + dd_real imagSq = dd_sqr(imag); + dd_real realTemp = dd_add(dd_sub(realSq, imagSq), real0); + + dd_real two; + two.hi = 2.0; + two.lo = 0.0; + + dd_real realImag = dd_mul(real, imag); + imag = dd_add(dd_mul(two, realImag), imag0); + + real = realTemp; + + iteration++; + } + + const int idx = (py * width + px) * 3; + + if (iteration == maxIterations) { + output[idx + 0] = 0; + output[idx + 1] = 0; + output[idx + 2] = 0; + } else { + float t = (float)iteration / (float)maxIterations; + output[idx + 0] = (uchar)(9.0f * (1.0f - t) * t * t * t * 255.0f); + output[idx + 1] = (uchar)(15.0f * (1.0f - t) * (1.0f - t) * t * t * 255.0f); + output[idx + 2] = (uchar)(8.5f * (1.0f - t) * (1.0f - t) * (1.0f - t) * t * 255.0f); + } +} diff --git a/src/mandelbrot_opencl_kernels.c b/src/mandelbrot_opencl_kernels.c new file mode 100644 index 0000000..3080d2c --- /dev/null +++ b/src/mandelbrot_opencl_kernels.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include + +static cl_context context = NULL; +static cl_command_queue queue = NULL; +static cl_program program = NULL; +static cl_device_id device = NULL; + +void opencl_kernel_manager_init() { + cl_platform_id platform; + cl_int err; + + err = clGetPlatformIDs(1, &platform, NULL); + err |= clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL); + + context = clCreateContext(NULL, 1, &device, NULL, NULL, &err); + queue = clCreateCommandQueueWithProperties(context, device, 0, &err); + + // Load source + FILE *f = fopen("mandelbrot_kernel.cl", "rb"); + if (!f) { + perror("Failed to open mandelbrot_opencl.cl"); + exit(1); + } + fseek(f, 0, SEEK_END); + size_t src_size = ftell(f); + rewind(f); + + char *src = (char *)malloc(src_size + 1); + fread(src, 1, src_size, f); + src[src_size] = '\0'; + fclose(f); + + program = + clCreateProgramWithSource(context, 1, (const char **)&src, NULL, &err); + free(src); + + err = clBuildProgram(program, 1, &device, NULL, NULL, NULL); + + if (err != CL_SUCCESS) { + size_t log_size; + clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, + &log_size); + char *log = malloc(log_size); + clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, log_size, log, + NULL); + printf("CL Build Error:\n%s\n", log); + free(log); + exit(1); + } +} + +void opencl_kernel_manager_shutdown() { + clReleaseProgram(program); + clReleaseCommandQueue(queue); + clReleaseContext(context); +} + +void launch_opencl_kernel(const char *kernel_name, double zoom, double offsetX, + double offsetY, int width, int height, + int maxIterations, unsigned char *restrict image) { + cl_int err; + cl_kernel kernel = clCreateKernel(program, kernel_name, &err); + if (err != CL_SUCCESS) { + printf("Failed to create kernel: %s\n", kernel_name); + exit(1); + } + + size_t img_size = width * height * 3; + cl_mem output_buffer = + clCreateBuffer(context, CL_MEM_WRITE_ONLY, img_size, NULL, &err); + + err |= clSetKernelArg(kernel, 0, sizeof(cl_mem), &output_buffer); + err |= clSetKernelArg(kernel, 1, sizeof(double), &zoom); + err |= clSetKernelArg(kernel, 2, sizeof(double), &offsetX); + err |= clSetKernelArg(kernel, 3, sizeof(double), &offsetY); + err |= clSetKernelArg(kernel, 4, sizeof(int), &width); + err |= clSetKernelArg(kernel, 5, sizeof(int), &height); + err |= clSetKernelArg(kernel, 6, sizeof(int), &maxIterations); + + const size_t global_size[2] = {(size_t)width, (size_t)height}; + err |= clEnqueueNDRangeKernel(queue, kernel, 2, NULL, global_size, NULL, 0, + NULL, NULL); + + err |= clEnqueueReadBuffer(queue, output_buffer, CL_TRUE, 0, img_size, image, + 0, NULL, NULL); + + clReleaseMemObject(output_buffer); + clReleaseKernel(kernel); + + clFinish(queue); +} diff --git a/src/mandelbrot_opencl_kernels.h b/src/mandelbrot_opencl_kernels.h new file mode 100644 index 0000000..4ee4fda --- /dev/null +++ b/src/mandelbrot_opencl_kernels.h @@ -0,0 +1,12 @@ +#ifndef MANDELBROT_OPENCL_KERNELS +#define MANDELBROT_OPENCL_KERNELS + +void opencl_kernel_manager_init(); +void opencl_kernel_manager_shutdown(); + +void launch_opencl_kernel(const char* kernel_name, + double zoom, double offsetX, double offsetY, + int width, int height, int maxIterations, + unsigned char* restrict image); + +#endif diff --git a/src/render.c b/src/render.c new file mode 100644 index 0000000..2422363 --- /dev/null +++ b/src/render.c @@ -0,0 +1,59 @@ +#include +#include + +#include +#include +#include + +#include "mandelbrot.h" +#include "render.h" + +void renderMandelbrot(GLFWwindow *window, const double zoom, + const double offsetX, const double offsetY, + unsigned char *restrict image, + const GLuint highResTexture, const int scaleFactor, + const GLuint fbo) { + int winW, winH; + glfwGetFramebufferSize(window, &winW, &winH); + const int highW = winW * scaleFactor; + const int highH = winH * scaleFactor; + memset(image, 0, highW * highH * 3); // Clear the image buffer + + glBindTexture(GL_TEXTURE_2D, highResTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, highW, highH, 0, GL_RGB, + GL_UNSIGNED_BYTE, NULL); + + // Generate the Mandelbrot set into the image buffer + mandelbrot(zoom, offsetX, offsetY, highW, highH, image); + + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glViewport(0, 0, highW, highH); + + glClear(GL_COLOR_BUFFER_BIT); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, highW, highH, GL_RGB, + GL_UNSIGNED_BYTE, image); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, highResTexture); + + glBegin(GL_QUADS); + glTexCoord2f(0.0f, 0.0f); + glVertex2f(-1.0f, -1.0f); + glTexCoord2f(1.0f, 0.0f); + glVertex2f(1.0f, -1.0f); + glTexCoord2f(1.0f, 1.0f); + glVertex2f(1.0f, 1.0f); + glTexCoord2f(0.0f, 1.0f); + glVertex2f(-1.0f, 1.0f); + glEnd(); + + glDisable(GL_TEXTURE_2D); + + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, highW, highH, 0, 0, winW, winH, GL_COLOR_BUFFER_BIT, + GL_LINEAR); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, winW, winH); +} diff --git a/src/render.h b/src/render.h new file mode 100644 index 0000000..1077cab --- /dev/null +++ b/src/render.h @@ -0,0 +1,10 @@ +#ifndef RENDER_H +#define RENDER_H + +#include + +// Function to render the Mandelbrot set +void renderMandelbrot(GLFWwindow* window, const double zoom, const double offsetX, const double offsetY, + unsigned char* image, GLuint highResTexture, int scaleFactor, GLuint fbo); + +#endif diff --git a/src/stb_easy_font.h b/src/stb_easy_font.h new file mode 100644 index 0000000..b663258 --- /dev/null +++ b/src/stb_easy_font.h @@ -0,0 +1,305 @@ +// stb_easy_font.h - v1.1 - bitmap font for 3D rendering - public domain +// Sean Barrett, Feb 2015 +// +// Easy-to-deploy, +// reasonably compact, +// extremely inefficient performance-wise, +// crappy-looking, +// ASCII-only, +// bitmap font for use in 3D APIs. +// +// Intended for when you just want to get some text displaying +// in a 3D app as quickly as possible. +// +// Doesn't use any textures, instead builds characters out of quads. +// +// DOCUMENTATION: +// +// int stb_easy_font_width(char *text) +// int stb_easy_font_height(char *text) +// +// Takes a string and returns the horizontal size and the +// vertical size (which can vary if 'text' has newlines). +// +// int stb_easy_font_print(float x, float y, +// char *text, unsigned char color[4], +// void *vertex_buffer, int vbuf_size) +// +// Takes a string (which can contain '\n') and fills out a +// vertex buffer with renderable data to draw the string. +// Output data assumes increasing x is rightwards, increasing y +// is downwards. +// +// The vertex data is divided into quads, i.e. there are four +// vertices in the vertex buffer for each quad. +// +// The vertices are stored in an interleaved format: +// +// x:float +// y:float +// z:float +// color:uint8[4] +// +// You can ignore z and color if you get them from elsewhere +// This format was chosen in the hopes it would make it +// easier for you to reuse existing vertex-buffer-drawing code. +// +// If you pass in NULL for color, it becomes 255,255,255,255. +// +// Returns the number of quads. +// +// If the buffer isn't large enough, it will truncate. +// Expect it to use an average of ~270 bytes per character. +// +// If your API doesn't draw quads, build a reusable index +// list that allows you to render quads as indexed triangles. +// +// void stb_easy_font_spacing(float spacing) +// +// Use positive values to expand the space between characters, +// and small negative values (no smaller than -1.5) to contract +// the space between characters. +// +// E.g. spacing = 1 adds one "pixel" of spacing between the +// characters. spacing = -1 is reasonable but feels a bit too +// compact to me; -0.5 is a reasonable compromise as long as +// you're scaling the font up. +// +// LICENSE +// +// See end of file for license information. +// +// VERSION HISTORY +// +// (2020-02-02) 1.1 make everything static so can compile it in more than one src file +// (2017-01-15) 1.0 space character takes same space as numbers; fix bad spacing of 'f' +// (2016-01-22) 0.7 width() supports multiline text; add height() +// (2015-09-13) 0.6 #include ; updated license +// (2015-02-01) 0.5 First release +// +// CONTRIBUTORS +// +// github:vassvik -- bug report +// github:podsvirov -- fix multiple definition errors + +#if 0 +// SAMPLE CODE: +// +// Here's sample code for old OpenGL; it's a lot more complicated +// to make work on modern APIs, and that's your problem. +// +void print_string(float x, float y, char *text, float r, float g, float b) +{ + static char buffer[99999]; // ~500 chars + int num_quads; + + num_quads = stb_easy_font_print(x, y, text, NULL, buffer, sizeof(buffer)); + + glColor3f(r,g,b); + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 16, buffer); + glDrawArrays(GL_QUADS, 0, num_quads*4); + glDisableClientState(GL_VERTEX_ARRAY); +} +#endif + +#ifndef INCLUDE_STB_EASY_FONT_H +#define INCLUDE_STB_EASY_FONT_H + +#include +#include + +static struct stb_easy_font_info_struct { + unsigned char advance; + unsigned char h_seg; + unsigned char v_seg; +} stb_easy_font_charinfo[96] = { + { 6, 0, 0 }, { 3, 0, 0 }, { 5, 1, 1 }, { 7, 1, 4 }, + { 7, 3, 7 }, { 7, 6, 12 }, { 7, 8, 19 }, { 4, 16, 21 }, + { 4, 17, 22 }, { 4, 19, 23 }, { 23, 21, 24 }, { 23, 22, 31 }, + { 20, 23, 34 }, { 22, 23, 36 }, { 19, 24, 36 }, { 21, 25, 36 }, + { 6, 25, 39 }, { 6, 27, 43 }, { 6, 28, 45 }, { 6, 30, 49 }, + { 6, 33, 53 }, { 6, 34, 57 }, { 6, 40, 58 }, { 6, 46, 59 }, + { 6, 47, 62 }, { 6, 55, 64 }, { 19, 57, 68 }, { 20, 59, 68 }, + { 21, 61, 69 }, { 22, 66, 69 }, { 21, 68, 69 }, { 7, 73, 69 }, + { 9, 75, 74 }, { 6, 78, 81 }, { 6, 80, 85 }, { 6, 83, 90 }, + { 6, 85, 91 }, { 6, 87, 95 }, { 6, 90, 96 }, { 7, 92, 97 }, + { 6, 96,102 }, { 5, 97,106 }, { 6, 99,107 }, { 6,100,110 }, + { 6,100,115 }, { 7,101,116 }, { 6,101,121 }, { 6,101,125 }, + { 6,102,129 }, { 7,103,133 }, { 6,104,140 }, { 6,105,145 }, + { 7,107,149 }, { 6,108,151 }, { 7,109,155 }, { 7,109,160 }, + { 7,109,165 }, { 7,118,167 }, { 6,118,172 }, { 4,120,176 }, + { 6,122,177 }, { 4,122,181 }, { 23,124,182 }, { 22,129,182 }, + { 4,130,182 }, { 22,131,183 }, { 6,133,187 }, { 22,135,191 }, + { 6,137,192 }, { 22,139,196 }, { 6,144,197 }, { 22,147,198 }, + { 6,150,202 }, { 19,151,206 }, { 21,152,207 }, { 6,155,209 }, + { 3,160,210 }, { 23,160,211 }, { 22,164,216 }, { 22,165,220 }, + { 22,167,224 }, { 22,169,228 }, { 21,171,232 }, { 21,173,233 }, + { 5,178,233 }, { 22,179,234 }, { 23,180,238 }, { 23,180,243 }, + { 23,180,248 }, { 22,189,248 }, { 22,191,252 }, { 5,196,252 }, + { 3,203,252 }, { 5,203,253 }, { 22,210,253 }, { 0,214,253 }, +}; + +static unsigned char stb_easy_font_hseg[214] = { + 97,37,69,84,28,51,2,18,10,49,98,41,65,25,81,105,33,9,97,1,97,37,37,36, + 81,10,98,107,3,100,3,99,58,51,4,99,58,8,73,81,10,50,98,8,73,81,4,10,50, + 98,8,25,33,65,81,10,50,17,65,97,25,33,25,49,9,65,20,68,1,65,25,49,41, + 11,105,13,101,76,10,50,10,50,98,11,99,10,98,11,50,99,11,50,11,99,8,57, + 58,3,99,99,107,10,10,11,10,99,11,5,100,41,65,57,41,65,9,17,81,97,3,107, + 9,97,1,97,33,25,9,25,41,100,41,26,82,42,98,27,83,42,98,26,51,82,8,41, + 35,8,10,26,82,114,42,1,114,8,9,73,57,81,41,97,18,8,8,25,26,26,82,26,82, + 26,82,41,25,33,82,26,49,73,35,90,17,81,41,65,57,41,65,25,81,90,114,20, + 84,73,57,41,49,25,33,65,81,9,97,1,97,25,33,65,81,57,33,25,41,25, +}; + +static unsigned char stb_easy_font_vseg[253] = { + 4,2,8,10,15,8,15,33,8,15,8,73,82,73,57,41,82,10,82,18,66,10,21,29,1,65, + 27,8,27,9,65,8,10,50,97,74,66,42,10,21,57,41,29,25,14,81,73,57,26,8,8, + 26,66,3,8,8,15,19,21,90,58,26,18,66,18,105,89,28,74,17,8,73,57,26,21, + 8,42,41,42,8,28,22,8,8,30,7,8,8,26,66,21,7,8,8,29,7,7,21,8,8,8,59,7,8, + 8,15,29,8,8,14,7,57,43,10,82,7,7,25,42,25,15,7,25,41,15,21,105,105,29, + 7,57,57,26,21,105,73,97,89,28,97,7,57,58,26,82,18,57,57,74,8,30,6,8,8, + 14,3,58,90,58,11,7,74,43,74,15,2,82,2,42,75,42,10,67,57,41,10,7,2,42, + 74,106,15,2,35,8,8,29,7,8,8,59,35,51,8,8,15,35,30,35,8,8,30,7,8,8,60, + 36,8,45,7,7,36,8,43,8,44,21,8,8,44,35,8,8,43,23,8,8,43,35,8,8,31,21,15, + 20,8,8,28,18,58,89,58,26,21,89,73,89,29,20,8,8,30,7, +}; + +typedef struct +{ + unsigned char c[4]; +} stb_easy_font_color; + +static int stb_easy_font_draw_segs(float x, float y, unsigned char *segs, int num_segs, int vertical, stb_easy_font_color c, char *vbuf, int vbuf_size, int offset) +{ + int i,j; + for (i=0; i < num_segs; ++i) { + int len = segs[i] & 7; + x += (float) ((segs[i] >> 3) & 1); + if (len && offset+64 <= vbuf_size) { + float y0 = y + (float) (segs[i]>>4); + for (j=0; j < 4; ++j) { + * (float *) (vbuf+offset+0) = x + (j==1 || j==2 ? (vertical ? 1 : len) : 0); + * (float *) (vbuf+offset+4) = y0 + ( j >= 2 ? (vertical ? len : 1) : 0); + * (float *) (vbuf+offset+8) = 0.f; + * (stb_easy_font_color *) (vbuf+offset+12) = c; + offset += 16; + } + } + } + return offset; +} + +static float stb_easy_font_spacing_val = 0; +static void stb_easy_font_spacing(float spacing) +{ + stb_easy_font_spacing_val = spacing; +} + +static int stb_easy_font_print(float x, float y, char *text, unsigned char color[4], void *vertex_buffer, int vbuf_size) +{ + char *vbuf = (char *) vertex_buffer; + float start_x = x; + int offset = 0; + + stb_easy_font_color c = { 255,255,255,255 }; // use structure copying to avoid needing depending on memcpy() + if (color) { c.c[0] = color[0]; c.c[1] = color[1]; c.c[2] = color[2]; c.c[3] = color[3]; } + + while (*text && offset < vbuf_size) { + if (*text == '\n') { + y += 12; + x = start_x; + } else { + unsigned char advance = stb_easy_font_charinfo[*text-32].advance; + float y_ch = advance & 16 ? y+1 : y; + int h_seg, v_seg, num_h, num_v; + h_seg = stb_easy_font_charinfo[*text-32 ].h_seg; + v_seg = stb_easy_font_charinfo[*text-32 ].v_seg; + num_h = stb_easy_font_charinfo[*text-32+1].h_seg - h_seg; + num_v = stb_easy_font_charinfo[*text-32+1].v_seg - v_seg; + offset = stb_easy_font_draw_segs(x, y_ch, &stb_easy_font_hseg[h_seg], num_h, 0, c, vbuf, vbuf_size, offset); + offset = stb_easy_font_draw_segs(x, y_ch, &stb_easy_font_vseg[v_seg], num_v, 1, c, vbuf, vbuf_size, offset); + x += advance & 15; + x += stb_easy_font_spacing_val; + } + ++text; + } + return (unsigned) offset/64; +} + +static int stb_easy_font_width(char *text) +{ + float len = 0; + float max_len = 0; + while (*text) { + if (*text == '\n') { + if (len > max_len) max_len = len; + len = 0; + } else { + len += stb_easy_font_charinfo[*text-32].advance & 15; + len += stb_easy_font_spacing_val; + } + ++text; + } + if (len > max_len) max_len = len; + return (int) ceil(max_len); +} + +static int stb_easy_font_height(char *text) +{ + float y = 0; + int nonempty_line=0; + while (*text) { + if (*text == '\n') { + y += 12; + nonempty_line = 0; + } else { + nonempty_line = 1; + } + ++text; + } + return (int) ceil(y + (nonempty_line ? 12 : 0)); +} +#endif + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/