render-sdf.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. #include "render-sdf.h"
  2. #include "arithmetics.hpp"
  3. namespace msdfgen {
  4. template <typename S>
  5. inline FloatRGB mix(FloatRGB a, FloatRGB b, S weight) {
  6. FloatRGB output = {
  7. mix(a.r, b.r, weight),
  8. mix(a.g, b.g, weight),
  9. mix(a.b, b.b, weight)
  10. };
  11. return output;
  12. }
  13. template <typename T>
  14. static T sample(const Bitmap<T> &bitmap, Point2 pos) {
  15. int w = bitmap.width(), h = bitmap.height();
  16. double x = pos.x*w-.5;
  17. double y = pos.y*h-.5;
  18. int l = (int) floor(x);
  19. int b = (int) floor(y);
  20. int r = l+1;
  21. int t = b+1;
  22. double lr = x-l;
  23. double bt = y-b;
  24. l = clamp(l, w-1), r = clamp(r, w-1);
  25. b = clamp(b, h-1), t = clamp(t, h-1);
  26. return mix(mix(bitmap(l, b), bitmap(r, b), lr), mix(bitmap(l, t), bitmap(r, t), lr), bt);
  27. }
  28. static float distVal(float dist, double pxRange) {
  29. if (!pxRange)
  30. return dist > .5f;
  31. return (float) clamp((dist-.5f)*pxRange+.5);
  32. }
  33. void renderSDF(Bitmap<float> &output, const Bitmap<float> &sdf, double pxRange) {
  34. int w = output.width(), h = output.height();
  35. pxRange *= (double) (w+h)/(sdf.width()+sdf.height());
  36. for (int y = 0; y < h; ++y)
  37. for (int x = 0; x < w; ++x) {
  38. float s = sample(sdf, Point2((x+.5)/w, (y+.5)/h));
  39. output(x, y) = distVal(s, pxRange);
  40. }
  41. }
  42. void renderSDF(Bitmap<FloatRGB> &output, const Bitmap<float> &sdf, double pxRange) {
  43. int w = output.width(), h = output.height();
  44. pxRange *= (double) (w+h)/(sdf.width()+sdf.height());
  45. for (int y = 0; y < h; ++y)
  46. for (int x = 0; x < w; ++x) {
  47. float s = sample(sdf, Point2((x+.5)/w, (y+.5)/h));
  48. float v = distVal(s, pxRange);
  49. output(x, y).r = v;
  50. output(x, y).g = v;
  51. output(x, y).b = v;
  52. }
  53. }
  54. void renderSDF(Bitmap<float> &output, const Bitmap<FloatRGB> &sdf, double pxRange) {
  55. int w = output.width(), h = output.height();
  56. pxRange *= (double) (w+h)/(sdf.width()+sdf.height());
  57. for (int y = 0; y < h; ++y)
  58. for (int x = 0; x < w; ++x) {
  59. FloatRGB s = sample(sdf, Point2((x+.5)/w, (y+.5)/h));
  60. output(x, y) = distVal(median(s.r, s.g, s.b), pxRange);
  61. }
  62. }
  63. void renderSDF(Bitmap<FloatRGB> &output, const Bitmap<FloatRGB> &sdf, double pxRange) {
  64. int w = output.width(), h = output.height();
  65. pxRange *= (double) (w+h)/(sdf.width()+sdf.height());
  66. for (int y = 0; y < h; ++y)
  67. for (int x = 0; x < w; ++x) {
  68. FloatRGB s = sample(sdf, Point2((x+.5)/w, (y+.5)/h));
  69. output(x, y).r = distVal(s.r, pxRange);
  70. output(x, y).g = distVal(s.g, pxRange);
  71. output(x, y).b = distVal(s.b, pxRange);
  72. }
  73. }
  74. void simulate8bit(Bitmap<float> &bitmap) {
  75. int w = bitmap.width(), h = bitmap.height();
  76. for (int y = 0; y < h; ++y)
  77. for (int x = 0; x < w; ++x) {
  78. unsigned char v = clamp(int(bitmap(x, y)*0x100), 0xff);
  79. bitmap(x, y) = v/255.f;
  80. }
  81. }
  82. void simulate8bit(Bitmap<FloatRGB> &bitmap) {
  83. int w = bitmap.width(), h = bitmap.height();
  84. for (int y = 0; y < h; ++y)
  85. for (int x = 0; x < w; ++x) {
  86. unsigned char r = clamp(int(bitmap(x, y).r*0x100), 0xff);
  87. unsigned char g = clamp(int(bitmap(x, y).g*0x100), 0xff);
  88. unsigned char b = clamp(int(bitmap(x, y).b*0x100), 0xff);
  89. bitmap(x, y).r = r/255.f;
  90. bitmap(x, y).g = g/255.f;
  91. bitmap(x, y).b = b/255.f;
  92. }
  93. }
  94. }