Skip to the digitizer
CDIGIT

Curve digitizer online

Linear and log10 maps, plus a small-angle rotation for a tilted scan. Open the digitizer to watch the midpoint change.

Anchors

X1, X2, Y1, and Y2

X1 X2 Y2 t = 0.5

X1 and Y1 share the lower-left tick in this sketch. X2 is the other end of the horizontal axis. Y2 is the top of the vertical axis. The halfway mark is t = 0.5, not a third anchor you have to click.

Formulas

One fraction, two scales

t = (p − p1) / (p2 − p1). Log values must be > 0.
ScaleMapHalfway pixel
LinearV1 + t (V2 − V1)(V1 + V2) / 2
Log1010^(log10 V1 + t (log10 V2 − log10 V1))√(V1 × V2)
Rotationx′ = x cos θ − y sin θ|θ| ≤ 15°
Rotationy′ = x sin θ + y cos θaround the axis origin

Every readout on ChartDigitizer is one of two maps. Linear axes scale a pixel fraction into a difference. Log10 axes scale that same fraction into a difference of logarithms. Mixing them up is the usual way a careful click still produces a wrong table.

Write the pixel fraction first: t = (p − p1) / (p2 − p1). For the halfway pixel, p is the average of p1 and p2, so t is exactly 1/2 as long as p2 is not p1. Identical anchors are rejected because the denominator would be zero.

Linear X is X1 + t (X2 − X1). Linear Y uses Y1, Y2, and the vertical pixels. The home bench shows this with 0 and 10 mapping to 5.0000, and 0 and 100 mapping to 50.0000. Four decimal places are part of the display contract, not extra precision in the pixels.

Log10 X is 10 raised to log10(X1) + t (log10(X2) − log10(X1)). At t = 1/2 that exponent is the average of the logs, which is the log of the geometric mean. Square-root form is the same identity: √(X1 × X2). Both anchors must be positive.

The worked log row is Y1 = 10 and Y2 = 1000. The geometric mean is 100. The readout is 100.0000. Relative error is |actual − 100| / 100. A correct implementation prints 0.0000e+0 and passes a 1e-4 tolerance. The MOSFET defaults, 1e-9 and 1e-1, land on 1.0000e-5.

Scientific notation is reserved for log values outside [1e-4, 1e4). Inside that window, including 100 and 10, the bench prints four fixed decimals. Relative error always uses scientific notation so a tiny miss is not rounded into a misleading zero of another kind. A true zero still prints 0.0000e+0.

Deskew is a rotation, not a second calibration. If a phone photo is rotated by θ degrees, a pixel (x, y) measured from the axis origin moves to x′ = x cos θ − y sin θ and y′ = x sin θ + y cos θ. The paid pack applies this before it records px and py. |θ| must be at most 15.

θ = 0 leaves pixels unchanged. The stress-strain acceptance anchors put data (0, 0) on pixel (80, 460). That pair is the check that deskew was a no-op. A 15° rotation moves the point on a circle around the origin. It does not change the data value you already typed.

Do not deskew by dragging one anchor and calling it a rotation. Dragging changes the axis direction for the whole map. Rotation corrects a scan that is tilted relative to an axis you have already marked. Use the degree field when the page itself is crooked and the ticks are still readable.

Shared-X resampling is independent of the pixel map. Once points are in data coordinates, row i is Xmin + i (Xmax − Xmin) / (M − 1). M = 2 returns the two endpoints. M = 100 on months 0 through 60 returns 100 rows. X increases even after rounding to four decimals on that span.

Linear interpolation on a segment is y = yL + (x − xL) / (xR − xL) × (yR − yL). The Alloy A segment from (0, 0) to (2, 35) gives 8.75 at strain 0.5, printed 8.7500. The segment from (4, 62) to (6, 78) gives 66 at strain 4.5, printed 66.0000.

Monotonic cubic uses Fritsch–Carlson tangents so a locally monotone polyline stays monotone between knots. It is the default on the bench and not the method behind the acceptance rows. Select linear before you compare a matrix to the published Kaplan–Meier row.

R² is 1 − SSres / SStot for a polynomial of degree at most 2. X is centered at its mean before the normal equations, which keeps a 200–400 axis from dominating x⁴. The pump head H = 32 + 1.4 Q − 0.08 Q² fits with R² 1.0000. Fewer than two points yields no R².

The maps are deterministic. No model looks at the bitmap on the server. Your image stays in the browser. If two implementations disagree, compare t, the scale flag, and the anchor values before you compare anti-aliased pixels. Most mismatches are a linear formula left on a log axis.

Use the home digitizer to watch 5.0000 and 50.0000 update as you type. Use the log bench for 100.0000 and 1.0000e-5. Use the bar bench when the mark is a mean plus a half-width rather than a polyline. The algebra on this page is what those three screens share.

Try the numbers on the log scale plot digitizer or the bar reader. The meta-analysis checklist is separate and is not clinical advice.

FAQ

Checks you can do with a calculator

What is the linear map?

X = X1 + (px − px1) / (px2 − px1) × (X2 − X1). The same form applies to Y with the vertical anchors. At the halfway pixel the fraction is 1/2, so the value is the arithmetic mean. 0 and 10 become 5.0000.

What is the log10 map?

Replace each value with its log10, interpolate with the same pixel fraction, then raise 10 to that power. The halfway pixel is √(V1 × V2). Y1 = 10 and Y2 = 1000 give 100, and the relative error is 0, which is within 1e-4.

Why not use a linear formula on a log axis?

Equal pixels are equal ratios, not equal differences. The midpoint of 10 and 1000 would read 505 if you averaged them. The printed tick in the middle of those decades is 100. The wrong map is off by a factor of about five.

How is a tilted scan corrected?

For a rotation θ with |θ| ≤ 15°, x′ = x cos θ − y sin θ and y′ = x sin θ + y cos θ. The paid routes apply that rotation to reconstructed pixels around the axis origin. Angles outside ±15° are rejected.

Does the midpoint need the image width?

No. t = 0.5 is defined by the two anchors, whatever their pixel gap. A 640×400 upload and an 800×520 built-in sheet produce the same data midpoint when the anchor values match. The picture only locates the ticks.

Which interpolation does the matrix use?

Linear, unless you select monotonic cubic. Shared X is Xmin + i (Xmax − Xmin) / (M − 1) for i from 0 to M − 1, so there are exactly M rows. Kaplan–Meier at M = 100 has row 10 equal to 5.4545 0.9636 0.9345.