MandelVideoGenerator.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include "MandelVideoGenerator.h"
  2. #include "VideoStream.h"
  3. #include <thread>
  4. #include <cmath>
  5. MandelVideoGenerator::MandelVideoGenerator(const ExportVideoInfo& evi) :
  6. evi{ evi }
  7. {
  8. }
  9. void MandelVideoGenerator::generate(void)
  10. {
  11. mnd::MandelContext ctxt = mnd::initializeContext();
  12. mnd::Generator& gen = *ctxt.getDevices()[0].getGeneratorDouble();
  13. mnd::MandelInfo mi;
  14. mi.bWidth = evi.width * 2;
  15. mi.bHeight = evi.height * 2;
  16. mi.maxIter = evi.maxIterations;
  17. VideoStream vs(evi.width, evi.height, evi.path);
  18. double x = evi.end.x + evi.end.width / 2;
  19. double y = evi.end.y + evi.end.height / 2;
  20. double w = evi.start.width;
  21. double h = evi.start.height;
  22. double bigW = 10000000000000000.0;
  23. double bigFac = 1.0;
  24. Bitmap<RGBColor> big;
  25. Bitmap<RGBColor> small;
  26. while(w > evi.end.width || h > evi.end.height) {
  27. mi.view = mnd::MandelViewport{ x - w/2, y - h/2, w, h };
  28. if (bigW > 2 * w) {
  29. Bitmap<float> raw{ evi.width * 2, evi.height * 2 };
  30. gen.generate(mi, raw.pixels.get());
  31. big = raw.map<RGBColor>([&mi, this] (float i) {
  32. return i >= mi.maxIter ? RGBColor{ 0,0,0 } : evi.gradient.get(i);
  33. });
  34. /*mi.view.zoomCenter(0.5);
  35. gen.generate(mi, raw.pixels.get());
  36. small = raw.map<RGBColor>([] (float x) { return
  37. RGBColor{ uint8_t(::sin(x / 100) * 127 + 127), uint8_t(::sin(x / 213) * 127 + 127), uint8_t(::cos(x / 173) * 127 + 127) };
  38. });*/
  39. bigW = w;
  40. bigFac = 1.0;
  41. }
  42. vs.addFrame(overlay(big, small, bigFac));
  43. w *= 0.99;
  44. h *= 0.99;
  45. bigFac *= 0.99;
  46. }
  47. }
  48. inline RGBColor biliniear(const Bitmap<RGBColor>& img, double x, double y)
  49. {
  50. int xfloor = int(::floor(x));
  51. int yfloor = int(::floor(y));
  52. int xceil = int(::ceil(x));
  53. int yceil = int(::ceil(y));
  54. double xLerp = x - xfloor;
  55. double yLerp = y - yfloor;
  56. RGBColor samples[2][2] = {
  57. {
  58. img.get(xfloor, yfloor),
  59. img.get(xfloor, yceil),
  60. },
  61. {
  62. img.get(xceil, yfloor),
  63. img.get(xceil, yceil),
  64. }
  65. };
  66. double r = 0, g = 0, b = 0;
  67. auto mklin = [] (double x) {
  68. return ::pow(x, 2.4);
  69. };
  70. auto unlin = [] (double x) {
  71. return ::pow(x, 1.0 / 2.4);
  72. };
  73. r += (1 - xLerp) * (1 - yLerp) * mklin(samples[0][0].r);
  74. r += (1 - xLerp) * yLerp * mklin(samples[0][1].r);
  75. r += xLerp * (1 - yLerp) * mklin(samples[1][0].r);
  76. r += xLerp * yLerp * mklin(samples[1][1].r);
  77. g += (1 - xLerp) * (1 - yLerp) * mklin(samples[0][0].g);
  78. g += (1 - xLerp) * yLerp * mklin(samples[0][1].g);
  79. g += xLerp * (1 - yLerp) * mklin(samples[1][0].g);
  80. g += xLerp * yLerp * mklin(samples[1][1].g);
  81. b += (1 - xLerp) * (1 - yLerp) * mklin(samples[0][0].b);
  82. b += (1 - xLerp) * yLerp * mklin(samples[0][1].b);
  83. b += xLerp * (1 - yLerp) * mklin(samples[1][0].b);
  84. b += xLerp * yLerp * mklin(samples[1][1].b);
  85. return RGBColor{ uint8_t(unlin(r)), uint8_t(unlin(g)), uint8_t(unlin(b)) };
  86. }
  87. Bitmap<RGBColor> MandelVideoGenerator::overlay(const Bitmap<RGBColor>& outer,
  88. const Bitmap<RGBColor>& inner, double scale)
  89. {
  90. printf("%lf\n", scale);
  91. Bitmap<RGBColor> ret{ outer.width / 2, outer.height / 2 };
  92. double newW = outer.width * scale * 2;
  93. double newH = outer.height * scale * 2;
  94. double newX = outer.width * (1 - scale) / 2;
  95. double newY = outer.height * (1 - scale) / 2;
  96. for (int i = 0; i < ret.height; i++) {
  97. for (int j = 0; j < ret.width; j++) {
  98. double newJ = newX + j * newW / outer.width;
  99. double newI = newY + i * newH / outer.height;
  100. RGBColor a = biliniear(outer, newJ, newI);
  101. ret.get(j, i) = a;
  102. }
  103. }
  104. /*for (int i = 0; i < ret.height * ret.width; i++) {
  105. ret.pixels[i] = outer.pixels[i];
  106. }*/
  107. return ret;
  108. }