diff --git a/admin-lehrer/components/ocr-overlay/OverlayReconstruction.tsx b/admin-lehrer/components/ocr-overlay/OverlayReconstruction.tsx index dd0548a..3161926 100644 --- a/admin-lehrer/components/ocr-overlay/OverlayReconstruction.tsx +++ b/admin-lehrer/components/ocr-overlay/OverlayReconstruction.tsx @@ -40,6 +40,8 @@ export function OverlayReconstruction({ sessionId, onNext }: OverlayReconstructi const [fontScale, setFontScale] = useState(0.7) const [globalBold, setGlobalBold] = useState(false) const [imageRotation, setImageRotation] = useState<0 | 180>(0) + const [textOpacity, setTextOpacity] = useState(100) + const [textColor, setTextColor] = useState<'red' | 'blue' | 'black'>('red') const reconRef = useRef(null) const [reconWidth, setReconWidth] = useState(0) @@ -381,6 +383,34 @@ export function OverlayReconstruction({ sessionId, onNext }: OverlayReconstructi
+ {/* Text color */} + {(['red', 'blue', 'black'] as const).map(c => ( +
- {/* Side-by-side: Original + Overlay */} -
- {/* Left: Original image */} -
-
- Originalbild -
-
- {/* eslint-disable-next-line @next/next/no-img-element */} - Original { - const img = e.target as HTMLImageElement - setImageNaturalSize({ w: img.naturalWidth, h: img.naturalHeight }) - }} - /> -
-
+ {/* True overlay: text layer on top of original image */} +
+
+ {/* Background: original image */} + {/* eslint-disable-next-line @next/next/no-img-element */} + Original { + const img = e.target as HTMLImageElement + setImageNaturalSize({ w: img.naturalWidth, h: img.naturalHeight }) + }} + /> - {/* Right: Reconstructed overlay */} -
-
- Rekonstruktion ({cells.length} Zellen) -
-
-
- {/* Row lines */} - {rows.map((row, i) => ( -
- ))} + {/* Text overlay layer */} +
+ {/* Row lines */} + {rows.map((row, i) => ( +
+ ))} - {/* Pixel-positioned words / editable inputs */} - {cells.map((cell) => { - const displayText = getDisplayText(cell) - const edited = isEdited(cell) - const wordPos = cellWordPositions.get(cell.cellId) - const bboxPct = cell.bboxPct - const cellHeightPx = containerH * (bboxPct.h / 100) + {/* Pixel-positioned words / editable inputs */} + {cells.map((cell) => { + const displayText = getDisplayText(cell) + const edited = isEdited(cell) + const wordPos = cellWordPositions.get(cell.cellId) + const bboxPct = cell.bboxPct + const cellHeightPx = containerH * (bboxPct.h / 100) + const colorValue = textColor === 'black' ? '#1a1a1a' : textColor - // Pixel-analysed: render word-groups at detected positions - if (wordPos && wordPos.length > 0) { - return wordPos.map((wp, i) => { - const autoFontPx = cellHeightPx * wp.fontRatio * fontScale - const fs = Math.max(6, autoFontPx) - - if (wordPos.length > 1) { - return ( - - {wp.text} - - ) - } + // Pixel-analysed: render word-groups at detected positions + if (wordPos && wordPos.length > 0) { + return wordPos.map((wp, i) => { + const autoFontPx = cellHeightPx * wp.fontRatio * fontScale + const fs = Math.max(6, autoFontPx) + if (wordPos.length > 1) { return ( -
- handleTextChange(cell.cellId, e.target.value)} - onKeyDown={(e) => handleKeyDown(e, cell.cellId)} - className={`w-full h-full bg-transparent border-0 outline-none px-0 transition-colors ${ - edited ? 'bg-green-50/30' : '' - }`} - style={{ - fontSize: `${fs}px`, - fontWeight: globalBold ? 'bold' : 'normal', - fontFamily: "'Liberation Sans', Arial, sans-serif", - lineHeight: '1', - color: '#1a1a1a', - }} - title={`${cell.cellId} (${cell.colType})`} - /> - {edited && ( - - )} -
- ) - }) - } - - // Fallback: no pixel data — single input at cell bbox - if (!cell.text) return null - - const fontSize = Math.max(6, cellHeightPx * fontScale) - return ( -
- handleTextChange(cell.cellId, e.target.value)} - onKeyDown={(e) => handleKeyDown(e, cell.cellId)} - className={`w-full h-full bg-transparent border-0 outline-none px-0 transition-colors ${ - edited ? 'bg-green-50/30' : '' - }`} - style={{ - fontSize: `${fontSize}px`, - fontWeight: globalBold ? 'bold' : 'normal', - fontFamily: "'Liberation Sans', Arial, sans-serif", - lineHeight: '1', - color: '#1a1a1a', - }} - title={`${cell.cellId} (${cell.colType})`} - /> - {edited && ( - - )} -
- ) - })} -
+ {wp.text} + + ) + } + + return ( +
+ handleTextChange(cell.cellId, e.target.value)} + onKeyDown={(e) => handleKeyDown(e, cell.cellId)} + className={`w-full h-full bg-transparent border-0 outline-none px-0 transition-colors ${ + edited ? 'bg-green-50/30' : '' + }`} + style={{ + fontSize: `${fs}px`, + fontWeight: globalBold ? 'bold' : 'normal', + fontFamily: "'Liberation Sans', Arial, sans-serif", + lineHeight: '1', + color: colorValue, + }} + title={`${cell.cellId} (${cell.colType})`} + /> + {edited && ( + + )} +
+ ) + }) + } + + // Fallback: no pixel data — single input at cell bbox + if (!cell.text) return null + + const fontSize = Math.max(6, cellHeightPx * fontScale) + return ( +
+ handleTextChange(cell.cellId, e.target.value)} + onKeyDown={(e) => handleKeyDown(e, cell.cellId)} + className={`w-full h-full bg-transparent border-0 outline-none px-0 transition-colors ${ + edited ? 'bg-green-50/30' : '' + }`} + style={{ + fontSize: `${fontSize}px`, + fontWeight: globalBold ? 'bold' : 'normal', + fontFamily: "'Liberation Sans', Arial, sans-serif", + lineHeight: '1', + color: colorValue, + }} + title={`${cell.cellId} (${cell.colType})`} + /> + {edited && ( + + )} +
+ ) + })}