fix(camera): constrain brightness and adjust side photo previews

This commit is contained in:
xsl
2026-10-15 20:41:28 +08:00
parent 480fed40cc
commit 8115db4ec2
6 changed files with 56 additions and 15 deletions
+16 -5
View File
@@ -1733,7 +1733,7 @@
});
/* ─── 报告页:每张维度卡各自的子 Tab;点检测图放大,再点返回 ─── */
function reportZoomSource(img, frame) {
function reportZoomSource(img, frame, fillScale, contentDown) {
// Bake the thumbnail's CSS zoom/translation and clipping into the large
// image. Annotations are already composited with their own photograph.
try {
@@ -1743,17 +1743,28 @@
if (style.objectFit==='cover' || style.objectFit==='contain') {
scaleX=scaleY=style.objectFit==='cover' ? Math.max(scaleX,scaleY) : Math.min(scaleX,scaleY);
}
var width=img.naturalWidth*scaleX, height=img.naturalHeight*scaleY;
fillScale=fillScale || 1;
var width=img.naturalWidth*scaleX*fillScale, height=img.naturalHeight*scaleY*fillScale;
var position=style.objectPosition.split(' ');
var px=position[0].endsWith('%') ? parseFloat(position[0])/100 : .5;
var py=position[1] && position[1].endsWith('%') ? parseFloat(position[1])/100 : .5;
var left=box.left-windowBox.left+(box.width-width)*px;
var top=box.top-windowBox.top+(box.height-height)*py;
// Smaller side-photo fill keeps its center, but never exposes a blank
// edge when the earlier vertical offset would push the image outside.
if (fillScale < 1) {
if (width >= windowBox.width) left=Math.max(windowBox.width-width,Math.min(0,left));
if (height >= windowBox.height) top=Math.max(windowBox.height-height,Math.min(0,top));
}
// Explicit preview adjustment uses the scaled photo's own height,
// not the frame height. Do not clamp away the requested displacement.
top += height * (contentDown || 0);
var ratio=Math.min(4,1600/Math.max(windowBox.width,windowBox.height));
var cv=document.createElement('canvas');
cv.width=Math.round(windowBox.width*ratio);cv.height=Math.round(windowBox.height*ratio);
var ctx=cv.getContext('2d');
ctx.fillStyle=getComputedStyle(frame).backgroundColor;ctx.fillRect(0,0,cv.width,cv.height);
ctx.drawImage(img,(box.left-windowBox.left+(box.width-width)*px)*ratio,
(box.top-windowBox.top+(box.height-height)*py)*ratio,width*ratio,height*ratio);
ctx.drawImage(img,left*ratio,top*ratio,width*ratio,height*ratio);
return cv.toDataURL('image/jpeg',.95);
} catch (_) { return img.src; }
}
@@ -1805,7 +1816,7 @@
var sideButton = e.target.closest('.contour-side-photo, .wrinkle-side-photo');
var img = sideButton ? sideButton.querySelector('img') : e.target.closest('.ditem-img');
if (img && img.src && !img.hidden && img.closest('.dpanel').classList.contains('active')) {
$('#zoom-img').src = reportZoomSource(img, sideButton || img.closest('.viz-frame'));
$('#zoom-img').src = reportZoomSource(img, sideButton || img.closest('.viz-frame'), sideButton ? .5 : 1, sideButton ? .5 : 0);
openOverlay('p-zoom');
history.pushState({ screen: currentScreen, overlay: 'p-zoom' }, '');
}
+2 -2
View File
@@ -6,9 +6,9 @@
'use strict';
// Real-phone feedback: ease alignment and normal hand/head movement while
// retaining two checked frames, one face, framing and final JPEG validation.
var config = Object.freeze({ version: '2026-10-15-dark-100-v4', score: 0.4,
var config = Object.freeze({ version: '2026-10-15-light-150-220-v5', score: 0.4,
near: 0.30, far: 0.68, center: 0.16, edge: 0.01,
dark: 100, bright: 235, holdMs: 450, minFrames: 2, maxGapMs: 2000,
dark: 150, bright: 220, holdMs: 450, minFrames: 2, maxGapMs: 2000,
yawDrift: 8, pitchDrift: 8, centerDrift: 0.055, sizeDrift: 0.065 });
function finite(v) { return typeof v === 'number' && isFinite(v); }
function evaluate(d, options) {