import { Platform } from 'react-native'; import type { CameraProps, Frame } from 'react-native-vision-camera'; import type { Barcode, Highlight, PointMapperFn, Size } from 'src/types'; import { computeBoundingBoxFromCornerPoints } from './convert'; import { applyScaleFactor, applyTransformation } from './geometry'; export const computeHighlights = ( barcodes: Barcode[], frame: Pick, layout: Size, resizeMode: CameraProps['resizeMode'] = 'cover', pointMapper?: PointMapperFn, ): Highlight[] => { 'worklet'; // If the layout is not yet known, we can't compute the highlights if (layout.width === 0 || layout.height === 0) { return []; } let adjustedLayout = { width: layout.height, height: layout.width, }; if (Platform.OS === 'ios') { /* iOS: * "portrait" -> "landscape-right" * "portrait-upside-down" -> "landscape-left" * "landscape-left" -> "portrait" * "landscape-right" -> "portrait-upside-down" */ // @NOTE destructure the object to make sure we don't hold a reference to the original layout adjustedLayout = ['landscape-left'].includes(frame.orientation) ? { width: layout.height, height: layout.width, } : { width: layout.width, height: layout.height, }; } const highlights = barcodes.map((barcode, index) => { const { value, cornerPoints } = barcode; let translatedCornerPoints = cornerPoints; translatedCornerPoints = translatedCornerPoints?.map((point) => applyScaleFactor(point, frame, adjustedLayout, resizeMode), ); if (pointMapper) { translatedCornerPoints = translatedCornerPoints?.map((point) => pointMapper(point, layout, frame.orientation), ); } else { translatedCornerPoints = translatedCornerPoints?.map((point) => applyTransformation(point, adjustedLayout, frame.orientation), ); } const valueFromCornerPoints = computeBoundingBoxFromCornerPoints( translatedCornerPoints!, ); return { ...barcode, key: `${value}.${index}`, cornerPoints: translatedCornerPoints, boundingBox: valueFromCornerPoints, }; }); // console.log(JSON.stringify(highlights, null, 2)); return highlights; };