Ver Fonte

Added output distance shift argument

Viktor Chlumský há 4 anos atrás
pai
commit
9d5c7c54e8
3 ficheiros alterados com 74 adições e 39 exclusões
  1. 20 20
      core/render-sdf.cpp
  2. 6 6
      core/render-sdf.h
  3. 48 13
      main.cpp

+ 20 - 20
core/render-sdf.cpp

@@ -7,83 +7,83 @@
 
 namespace msdfgen {
 
-static float distVal(float dist, double pxRange) {
+static float distVal(float dist, double pxRange, float midValue) {
     if (!pxRange)
-        return (float) (dist > .5f);
-    return (float) clamp((dist-.5f)*pxRange+.5);
+        return (float) (dist > midValue);
+    return (float) clamp((dist-midValue)*pxRange+.5);
 }
 
-void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 1> &sdf, double pxRange) {
+void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 1> &sdf, double pxRange, float midValue) {
     Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);
     pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);
     for (int y = 0; y < output.height; ++y)
         for (int x = 0; x < output.width; ++x) {
             float sd;
             interpolate(&sd, sdf, scale*Point2(x+.5, y+.5));
-            *output(x, y) = distVal(sd, pxRange);
+            *output(x, y) = distVal(sd, pxRange, midValue);
         }
 }
 
-void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 1> &sdf, double pxRange) {
+void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 1> &sdf, double pxRange, float midValue) {
     Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);
     pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);
     for (int y = 0; y < output.height; ++y)
         for (int x = 0; x < output.width; ++x) {
             float sd;
             interpolate(&sd, sdf, scale*Point2(x+.5, y+.5));
-            float v = distVal(sd, pxRange);
+            float v = distVal(sd, pxRange, midValue);
             output(x, y)[0] = v;
             output(x, y)[1] = v;
             output(x, y)[2] = v;
         }
 }
 
-void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 3> &sdf, double pxRange) {
+void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 3> &sdf, double pxRange, float midValue) {
     Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);
     pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);
     for (int y = 0; y < output.height; ++y)
         for (int x = 0; x < output.width; ++x) {
             float sd[3];
             interpolate(sd, sdf, scale*Point2(x+.5, y+.5));
-            *output(x, y) = distVal(median(sd[0], sd[1], sd[2]), pxRange);
+            *output(x, y) = distVal(median(sd[0], sd[1], sd[2]), pxRange, midValue);
         }
 }
 
-void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 3> &sdf, double pxRange) {
+void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 3> &sdf, double pxRange, float midValue) {
     Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);
     pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);
     for (int y = 0; y < output.height; ++y)
         for (int x = 0; x < output.width; ++x) {
             float sd[3];
             interpolate(sd, sdf, scale*Point2(x+.5, y+.5));
-            output(x, y)[0] = distVal(sd[0], pxRange);
-            output(x, y)[1] = distVal(sd[1], pxRange);
-            output(x, y)[2] = distVal(sd[2], pxRange);
+            output(x, y)[0] = distVal(sd[0], pxRange, midValue);
+            output(x, y)[1] = distVal(sd[1], pxRange, midValue);
+            output(x, y)[2] = distVal(sd[2], pxRange, midValue);
         }
 }
 
-void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 4> &sdf, double pxRange) {
+void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 4> &sdf, double pxRange, float midValue) {
     Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);
     pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);
     for (int y = 0; y < output.height; ++y)
         for (int x = 0; x < output.width; ++x) {
             float sd[4];
             interpolate(sd, sdf, scale*Point2(x+.5, y+.5));
-            *output(x, y) = distVal(median(sd[0], sd[1], sd[2]), pxRange);
+            *output(x, y) = distVal(median(sd[0], sd[1], sd[2]), pxRange, midValue);
         }
 }
 
-void renderSDF(const BitmapRef<float, 4> &output, const BitmapConstRef<float, 4> &sdf, double pxRange) {
+void renderSDF(const BitmapRef<float, 4> &output, const BitmapConstRef<float, 4> &sdf, double pxRange, float midValue) {
     Vector2 scale((double) sdf.width/output.width, (double) sdf.height/output.height);
     pxRange *= (double) (output.width+output.height)/(sdf.width+sdf.height);
     for (int y = 0; y < output.height; ++y)
         for (int x = 0; x < output.width; ++x) {
             float sd[4];
             interpolate(sd, sdf, scale*Point2(x+.5, y+.5));
-            output(x, y)[0] = distVal(sd[0], pxRange);
-            output(x, y)[1] = distVal(sd[1], pxRange);
-            output(x, y)[2] = distVal(sd[2], pxRange);
-            output(x, y)[3] = distVal(sd[3], pxRange);
+            output(x, y)[0] = distVal(sd[0], pxRange, midValue);
+            output(x, y)[1] = distVal(sd[1], pxRange, midValue);
+            output(x, y)[2] = distVal(sd[2], pxRange, midValue);
+            output(x, y)[3] = distVal(sd[3], pxRange, midValue);
         }
 }
 

+ 6 - 6
core/render-sdf.h

@@ -7,12 +7,12 @@
 namespace msdfgen {
 
 /// Reconstructs the shape's appearance into output from the distance field sdf.
-void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 1> &sdf, double pxRange = 0);
-void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 1> &sdf, double pxRange = 0);
-void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 3> &sdf, double pxRange = 0);
-void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 3> &sdf, double pxRange = 0);
-void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 4> &sdf, double pxRange = 0);
-void renderSDF(const BitmapRef<float, 4> &output, const BitmapConstRef<float, 4> &sdf, double pxRange = 0);
+void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 1> &sdf, double pxRange = 0, float midValue = .5f);
+void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 1> &sdf, double pxRange = 0, float midValue = .5f);
+void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 3> &sdf, double pxRange = 0, float midValue = .5f);
+void renderSDF(const BitmapRef<float, 3> &output, const BitmapConstRef<float, 3> &sdf, double pxRange = 0, float midValue = .5f);
+void renderSDF(const BitmapRef<float, 1> &output, const BitmapConstRef<float, 4> &sdf, double pxRange = 0, float midValue = .5f);
+void renderSDF(const BitmapRef<float, 4> &output, const BitmapConstRef<float, 4> &sdf, double pxRange = 0, float midValue = .5f);
 
 /// Snaps the values of the floating-point bitmaps into one of the 256 values representable in a standard 8-bit bitmap.
 void simulate8bit(const BitmapRef<float, 1> &bitmap);

+ 48 - 13
main.cpp

@@ -157,7 +157,7 @@ static bool writeTextBitmap(FILE *file, const float *values, int cols, int rows)
 static bool writeTextBitmapFloat(FILE *file, const float *values, int cols, int rows) {
     for (int row = 0; row < rows; ++row) {
         for (int col = 0; col < cols; ++col) {
-            fprintf(file, col ? " %g" : "%g", *values++);
+            fprintf(file, col ? " %.9g" : "%.9g", *values++);
         }
         fprintf(file, "\n");
     }
@@ -203,7 +203,7 @@ static bool cmpExtension(const char *path, const char *ext) {
 }
 
 template <int N>
-static const char * writeOutput(const BitmapConstRef<float, N> &bitmap, const char *filename, Format format) {
+static const char * writeOutput(const BitmapConstRef<float, N> &bitmap, const char *filename, Format &format) {
     if (filename) {
         if (format == AUTO) {
             if (cmpExtension(filename, ".png")) format = PNG;
@@ -291,6 +291,8 @@ static const char *helpText =
         "\tAutomatically scales (unless specified) and translates the shape to fit.\n"
     "  -coloringstrategy <simple / inktrap>\n"
         "\tSelects the strategy of the edge coloring heuristic.\n"
+    "  -distanceshift <shift>\n"
+        "\tShifts all normalized distances in the output distance field by this value.\n"
     "  -edgecolors <sequence>\n"
         "\tOverrides automatic edge coloring with the specified color sequence.\n"
     "  -errorcorrection <threshold>\n"
@@ -389,6 +391,7 @@ int main(int argc, const char * const *argv) {
     bool scaleSpecified = false;
     double angleThreshold = DEFAULT_ANGLE_THRESHOLD;
     double errorCorrectionThreshold = MSDFGEN_DEFAULT_ERROR_CORRECTION_THRESHOLD;
+    float outputDistanceShift = 0.f;
     const char *edgeAssignment = NULL;
     bool yFlip = false;
     bool printMetrics = false;
@@ -597,6 +600,14 @@ int main(int argc, const char * const *argv) {
             argPos += 2;
             continue;
         }
+        ARG_CASE("-distanceshift", 1) {
+            double ds;
+            if (!parseDouble(ds, argv[argPos+1]))
+                ABORT("Invalid distance shift. Use -distanceshift <shift> with a real value.");
+            outputDistanceShift = (float) ds;
+            argPos += 2;
+            continue;
+        }
         ARG_CASE("-exportshape", 1) {
             shapeExport = argv[argPos+1];
             argPos += 2;
@@ -738,10 +749,13 @@ int main(int argc, const char * const *argv) {
     if (autoFrame) {
         double l = bounds.l, b = bounds.b, r = bounds.r, t = bounds.t;
         Vector2 frame(width, height);
-        if (rangeMode == RANGE_UNIT)
-            l -= .5*range, b -= .5*range, r += .5*range, t += .5*range;
-        else if (!scaleSpecified)
-            frame -= pxRange;
+        double m = .5+(double) outputDistanceShift;
+        if (!scaleSpecified) {
+            if (rangeMode == RANGE_UNIT)
+                l -= m*range, b -= m*range, r += m*range, t += m*range;
+            else
+                frame -= 2*m*pxRange;
+        }
         if (l >= r || b >= t)
             l = 0, b = 0, r = 1, t = 1;
         if (frame.x <= 0 || frame.y <= 0)
@@ -759,7 +773,7 @@ int main(int argc, const char * const *argv) {
             }
         }
         if (rangeMode == RANGE_PX && !scaleSpecified)
-            translate += .5*pxRange/scale;
+            translate += m*pxRange/scale;
     }
 
     if (rangeMode == RANGE_PX)
@@ -879,6 +893,27 @@ int main(int argc, const char * const *argv) {
             default:;
         }
     }
+    if (outputDistanceShift) {
+        float *pixel = NULL, *pixelsEnd = NULL;
+        switch (mode) {
+            case SINGLE:
+            case PSEUDO:
+                pixel = (float *) sdf;
+                pixelsEnd = pixel+1*sdf.width()*sdf.height();
+                break;
+            case MULTI:
+                pixel = (float *) msdf;
+                pixelsEnd = pixel+3*msdf.width()*msdf.height();
+                break;
+            case MULTI_AND_TRUE:
+                pixel = (float *) mtsdf;
+                pixelsEnd = pixel+4*mtsdf.width()*mtsdf.height();
+                break;
+            default:;
+        }
+        while (pixel < pixelsEnd)
+            *pixel++ += outputDistanceShift;
+    }
 
     // Save output
     if (shapeExport) {
@@ -904,13 +939,13 @@ int main(int argc, const char * const *argv) {
             }
             if (testRenderMulti) {
                 Bitmap<float, 3> render(testWidthM, testHeightM);
-                renderSDF(render, sdf, avgScale*range);
+                renderSDF(render, sdf, avgScale*range, .5f+outputDistanceShift);
                 if (!savePng(render, testRenderMulti))
                     puts("Failed to write test render file.");
             }
             if (testRender) {
                 Bitmap<float, 1> render(testWidth, testHeight);
-                renderSDF(render, sdf, avgScale*range);
+                renderSDF(render, sdf, avgScale*range, .5f+outputDistanceShift);
                 if (!savePng(render, testRender))
                     puts("Failed to write test render file.");
             }
@@ -927,13 +962,13 @@ int main(int argc, const char * const *argv) {
             }
             if (testRenderMulti) {
                 Bitmap<float, 3> render(testWidthM, testHeightM);
-                renderSDF(render, msdf, avgScale*range);
+                renderSDF(render, msdf, avgScale*range, .5f+outputDistanceShift);
                 if (!savePng(render, testRenderMulti))
                     puts("Failed to write test render file.");
             }
             if (testRender) {
                 Bitmap<float, 1> render(testWidth, testHeight);
-                renderSDF(render, msdf, avgScale*range);
+                renderSDF(render, msdf, avgScale*range, .5f+outputDistanceShift);
                 if (!savePng(render, testRender))
                     ABORT("Failed to write test render file.");
             }
@@ -950,13 +985,13 @@ int main(int argc, const char * const *argv) {
             }
             if (testRenderMulti) {
                 Bitmap<float, 4> render(testWidthM, testHeightM);
-                renderSDF(render, mtsdf, avgScale*range);
+                renderSDF(render, mtsdf, avgScale*range, .5f+outputDistanceShift);
                 if (!savePng(render, testRenderMulti))
                     puts("Failed to write test render file.");
             }
             if (testRender) {
                 Bitmap<float, 1> render(testWidth, testHeight);
-                renderSDF(render, mtsdf, avgScale*range);
+                renderSDF(render, mtsdf, avgScale*range, .5f+outputDistanceShift);
                 if (!savePng(render, testRender))
                     ABORT("Failed to write test render file.");
             }