Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
21dcdee1f0 | ||
|
|
39afb5c9e0 |
+10
-7
@@ -174,17 +174,20 @@ const PreviewPanel = ({ lensCurves, previewDistanceMeters }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const blurMm = stat?.blurMm ?? 0;
|
const blurMm = stat?.blurMm ?? 0;
|
||||||
|
const blurPercent = stat?.blurPercentOfDiagonal ??
|
||||||
|
((curve.sensor?.diagonal ?? 0) > 0 ? (blurMm / curve.sensor.diagonal) * 100 : 0);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
lens: curve.lens,
|
lens: curve.lens,
|
||||||
blurMm,
|
blurMm,
|
||||||
|
blurPercent,
|
||||||
sensorDiagonal: curve.sensor?.diagonal ?? 1,
|
sensorDiagonal: curve.sensor?.diagonal ?? 1,
|
||||||
colorIndex: curve.colorIndex,
|
colorIndex: curve.colorIndex,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const maxBlurMm = previewItems.reduce((maxValue, item) => Math.max(maxValue, item.blurMm), 0);
|
const maxBlurPercent = previewItems.reduce((maxValue, item) => Math.max(maxValue, item.blurPercent), 0);
|
||||||
const denominator = maxBlurMm > 0 ? maxBlurMm : 1;
|
const denominator = maxBlurPercent > 0 ? maxBlurPercent : 1;
|
||||||
const distanceLabel = Number.isFinite(previewDistanceMeters)
|
const distanceLabel = Number.isFinite(previewDistanceMeters)
|
||||||
? `${formatNumber(previewDistanceMeters, previewDistanceMeters >= 10 ? 0 : 1)} m`
|
? `${formatNumber(previewDistanceMeters, previewDistanceMeters >= 10 ? 0 : 1)} m`
|
||||||
: '∞';
|
: '∞';
|
||||||
@@ -200,7 +203,7 @@ const PreviewPanel = ({ lensCurves, previewDistanceMeters }) => {
|
|||||||
) : (
|
) : (
|
||||||
<div className="flex flex-wrap justify-center gap-4">
|
<div className="flex flex-wrap justify-center gap-4">
|
||||||
{previewItems.map((item) => {
|
{previewItems.map((item) => {
|
||||||
const normalized = Math.min(item.blurMm / denominator, 1);
|
const normalized = Math.min(item.blurPercent / denominator, 1);
|
||||||
const diameter = Math.max(18, 30 + normalized * 70);
|
const diameter = Math.max(18, 30 + normalized * 70);
|
||||||
const paletteColor = COLOR_PALETTE[item.colorIndex % COLOR_PALETTE.length];
|
const paletteColor = COLOR_PALETTE[item.colorIndex % COLOR_PALETTE.length];
|
||||||
|
|
||||||
@@ -221,7 +224,7 @@ const PreviewPanel = ({ lensCurves, previewDistanceMeters }) => {
|
|||||||
<div className="text-xs text-slate-200">
|
<div className="text-xs text-slate-200">
|
||||||
<div className="font-medium text-slate-100">{item.lens.name}</div>
|
<div className="font-medium text-slate-100">{item.lens.name}</div>
|
||||||
<div className="text-[10px] uppercase tracking-wide text-slate-500">
|
<div className="text-[10px] uppercase tracking-wide text-slate-500">
|
||||||
Blur {formatNumber(item.blurMm, 2)} mm
|
Blur {formatNumber(item.blurPercent, 2)}% diag
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -321,7 +324,7 @@ const PlotSection = ({ lensCurves, plotType, setPlotType, previewDistanceMeters
|
|||||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||||
<div>
|
<div>
|
||||||
<h2 className="text-lg font-semibold text-slate-100">Blur comparison</h2>
|
<h2 className="text-lg font-semibold text-slate-100">Blur comparison</h2>
|
||||||
<p className="text-xs uppercase tracking-wide text-slate-400">Blur radius as % of sensor diagonal</p>
|
<p className="text-xs uppercase tracking-wide text-slate-400">Blur diameter as % of sensor diagonal</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap items-center gap-3">
|
<div className="flex flex-wrap items-center gap-3">
|
||||||
<select
|
<select
|
||||||
@@ -355,7 +358,7 @@ const PlotSection = ({ lensCurves, plotType, setPlotType, previewDistanceMeters
|
|||||||
...(axisConfig.ticksuffix ? { ticksuffix: axisConfig.ticksuffix } : {}),
|
...(axisConfig.ticksuffix ? { ticksuffix: axisConfig.ticksuffix } : {}),
|
||||||
},
|
},
|
||||||
yaxis: {
|
yaxis: {
|
||||||
title: 'Blur radius (% of sensor diagonal)',
|
title: 'Blur diameter (% of sensor diagonal)',
|
||||||
type: 'linear',
|
type: 'linear',
|
||||||
gridcolor: 'rgba(148, 163, 184, 0.2)',
|
gridcolor: 'rgba(148, 163, 184, 0.2)',
|
||||||
zerolinecolor: 'rgba(148, 163, 184, 0.4)',
|
zerolinecolor: 'rgba(148, 163, 184, 0.4)',
|
||||||
@@ -976,7 +979,7 @@ const App = () => {
|
|||||||
<div>
|
<div>
|
||||||
<h1 className="text-2xl font-semibold text-slate-100">Lens & Sensor Blur Comparison</h1>
|
<h1 className="text-2xl font-semibold text-slate-100">Lens & Sensor Blur Comparison</h1>
|
||||||
<p className="text-sm text-slate-400">
|
<p className="text-sm text-slate-400">
|
||||||
Explore blur radius as % of sensor diagonal across lens and sensor combinations.
|
Explore blur diameter as % of sensor diagonal across lens and sensor combinations.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+11
-4
@@ -83,13 +83,20 @@ export const calculateBlurCircle = ({ focalLengthMm, aperture, subjectDistanceM,
|
|||||||
const safeAperture = coercePositiveNumber(aperture, 1);
|
const safeAperture = coercePositiveNumber(aperture, 1);
|
||||||
const f = focalLengthMm;
|
const f = focalLengthMm;
|
||||||
const u = metersToMillimeters(coercePositiveNumber(subjectDistanceM, 0.5));
|
const u = metersToMillimeters(coercePositiveNumber(subjectDistanceM, 0.5));
|
||||||
const s = metersToMillimeters(coercePositiveNumber(sceneDistanceM, 0.51));
|
|
||||||
|
|
||||||
if (Math.abs(s - u) < 1e-6) {
|
if (Math.abs(u - f) < 1e-6) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.abs(u - f) < 1e-6) {
|
if (!Number.isFinite(sceneDistanceM)) {
|
||||||
|
const denominator = safeAperture * (u - f);
|
||||||
|
return Math.abs((f ** 2) / denominator);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sceneMeters = Math.max(sceneDistanceM, 0.2);
|
||||||
|
const s = metersToMillimeters(sceneMeters);
|
||||||
|
|
||||||
|
if (Math.abs(s - u) < 1e-6) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +204,7 @@ export const buildStatsAtCheckpoints = ({
|
|||||||
sceneDistanceM: Infinity,
|
sceneDistanceM: Infinity,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
sceneDistance = safeSubjectDistance + separation;
|
sceneDistance = Math.max(safeSubjectDistance + separation, 0.2);
|
||||||
blurMm = calculateBlurCircle({
|
blurMm = calculateBlurCircle({
|
||||||
focalLengthMm: lens.focalLength,
|
focalLengthMm: lens.focalLength,
|
||||||
aperture,
|
aperture,
|
||||||
|
|||||||
Reference in New Issue
Block a user