| 1 | |
| 2 | #include "render-sdf.h" |
| 3 | |
| 4 | #include "arithmetics.hpp" |
| 5 | #include "pixel-conversion.hpp" |
| 6 | #include "bitmap-interpolation.hpp" |
| 7 | |
| 8 | namespace msdfgen { |
| 9 | |
| 10 | static float distVal(float dist, double pxRange, float midValue) { |
| 11 | if (!pxRange) |
| 12 | return (float) (dist > midValue); |
| 13 | return (float) clamp((dist-midValue)*pxRange+.5); |
| 14 | } |
| 15 | |
| 16 | void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 1> &sdf, double pxRange, float midValue) { |
| 17 | Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height); |
| 18 | pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height); |
| 19 | for (int y = 0; y < output.height; ++y) |
| 20 | for (int x = 0; x < output.width; ++x) { |
| 21 | float sd; |
| 22 | interpolate(&sd, sdf, scale*Point2(x+.5, y+.5)); |
| 23 | *output(x, y) = distVal(sd, pxRange, midValue); |
| 24 | } |
| 25 | } |
| 26 | |
| 27 | void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 1> &sdf, double pxRange, float midValue) { |
| 28 | Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height); |
| 29 | pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height); |
| 30 | for (int y = 0; y < output.height; ++y) |
| 31 | for (int x = 0; x < output.width; ++x) { |
| 32 | float sd; |
| 33 | interpolate(&sd, sdf, scale*Point2(x+.5, y+.5)); |
| 34 | float v = distVal(sd, pxRange, midValue); |
| 35 | output(x, y)[0] = v; |
| 36 | output(x, y)[1] = v; |
| 37 | output(x, y)[2] = v; |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 3> &sdf, double pxRange, float midValue) { |
| 42 | Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height); |
| 43 | pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height); |
| 44 | for (int y = 0; y < output.height; ++y) |
| 45 | for (int x = 0; x < output.width; ++x) { |
| 46 | float sd[3]; |
| 47 | interpolate(sd, sdf, scale*Point2(x+.5, y+.5)); |
| 48 | *output(x, y) = distVal(median(sd[0], sd[1], sd[2]), pxRange, midValue); |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 3> &sdf, double pxRange, float midValue) { |
| 53 | Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height); |
| 54 | pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height); |
| 55 | for (int y = 0; y < output.height; ++y) |
| 56 | for (int x = 0; x < output.width; ++x) { |
| 57 | float sd[3]; |
| 58 | interpolate(sd, sdf, scale*Point2(x+.5, y+.5)); |
| 59 | output(x, y)[0] = distVal(sd[0], pxRange, midValue); |
| 60 | output(x, y)[1] = distVal(sd[1], pxRange, midValue); |
| 61 | output(x, y)[2] = distVal(sd[2], pxRange, midValue); |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 4> &sdf, double pxRange, float midValue) { |
| 66 | Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height); |
| 67 | pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height); |
| 68 | for (int y = 0; y < output.height; ++y) |
| 69 | for (int x = 0; x < output.width; ++x) { |
| 70 | float sd[4]; |
| 71 | interpolate(sd, sdf, scale*Point2(x+.5, y+.5)); |
| 72 | *output(x, y) = distVal(median(sd[0], sd[1], sd[2]), pxRange, midValue); |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | void renderSDF(const BitmapRef<float, 4> &output, const BitmapConstRef<float, 4> &sdf, double pxRange, float midValue) { |
| 77 | Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height); |
| 78 | pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height); |
| 79 | for (int y = 0; y < output.height; ++y) |
| 80 | for (int x = 0; x < output.width; ++x) { |
| 81 | float sd[4]; |
| 82 | interpolate(sd, sdf, scale*Point2(x+.5, y+.5)); |
| 83 | output(x, y)[0] = distVal(sd[0], pxRange, midValue); |
| 84 | output(x, y)[1] = distVal(sd[1], pxRange, midValue); |
| 85 | output(x, y)[2] = distVal(sd[2], pxRange, midValue); |
| 86 | output(x, y)[3] = distVal(sd[3], pxRange, midValue); |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | void simulate8bit(const BitmapRef<float, 1> &bitmap) { |
| 91 | const float *end = bitmap.pixels+1*bitmap.width*bitmap.height; |
| 92 | for (float *p = bitmap.pixels; p < end; ++p) |
| 93 | *p = pixelByteToFloat(pixelFloatToByte(*p)); |
| 94 | } |
| 95 | |
| 96 | void simulate8bit(const BitmapRef<float, 3> &bitmap) { |
| 97 | const float *end = bitmap.pixels+3*bitmap.width*bitmap.height; |
| 98 | for (float *p = bitmap.pixels; p < end; ++p) |
| 99 | *p = pixelByteToFloat(pixelFloatToByte(*p)); |
| 100 | } |
| 101 | |
| 102 | void simulate8bit(const BitmapRef<float, 4> &bitmap) { |
| 103 | const float *end = bitmap.pixels+4*bitmap.width*bitmap.height; |
| 104 | for (float *p = bitmap.pixels; p < end; ++p) |
| 105 | *p = pixelByteToFloat(pixelFloatToByte(*p)); |
| 106 | } |
| 107 | |
| 108 | } |
| 109 | |