From c0651dfb0e45c8021a075080a777f4579d5f3fc0 Mon Sep 17 00:00:00 2001 From: orfelorfel23 Date: Sun, 31 May 2026 17:07:31 +0200 Subject: [PATCH] Bypass expo-image-manipulator entirely and rely on React Native resizeMethod to prevent Android OOM --- src/screens/CameraScreen.tsx | 85 +++-------------------------------- src/screens/PreviewScreen.tsx | 13 ++++-- 2 files changed, 16 insertions(+), 82 deletions(-) diff --git a/src/screens/CameraScreen.tsx b/src/screens/CameraScreen.tsx index 46acba7e..6e39bafa 100644 --- a/src/screens/CameraScreen.tsx +++ b/src/screens/CameraScreen.tsx @@ -235,91 +235,20 @@ export default function CameraScreen({ console.log('Capturing from built-in camera fallback...'); if (expoCameraRef.current) { const photo = await expoCameraRef.current.takePictureAsync({ - quality: 0.7, // Lower quality slightly to reduce file size and OOM risk - skipProcessing: true, // Crucial for Android tablets: prevents internal OOM that corrupts the image file + quality: 0.7, // Lower quality slightly to reduce file size + skipProcessing: false, // Ensure correct orientation }); capturedUri = photo.uri; - rawWidth = photo.width; - rawHeight = photo.height; - - // Wait 500ms to ensure the OS has completely flushed the file to disk. - // This prevents "Loading bitmap failed" when ImageManipulator reads it too fast. - await new Promise((resolve) => setTimeout(resolve, 500)); } else { throw new Error('Kamera-Referenz ist nicht verfügbar.'); } } - // -- DOWNSCALE & CROP TO EXACTLY 3:2 -- - try { - console.log('Manipulating image to 3:2 ratio and downscaling to prevent OOM...'); - // ALWAYS read true dimensions from ImageManipulator. - // expo-camera rawWidth/rawHeight ignores EXIF rotation, causing crop bounds to exceed image bounds! - const info = await ImageManipulator.manipulateAsync(capturedUri, []); - let w = info.width; - let h = info.height; - - const actions: ImageManipulator.Action[] = []; - const isLandscape = w >= h; - const targetRatio = 3 / 2; - const currentRatio = isLandscape ? w / h : h / w; - - let cropWidth = w; - let cropHeight = h; - let originX = 0; - let originY = 0; - - // Tolerance for floating point inaccuracies - if (Math.abs(currentRatio - targetRatio) > 0.05) { - if (isLandscape) { - if (currentRatio > targetRatio) { - cropWidth = h * targetRatio; - originX = (w - cropWidth) / 2; - } else { - cropHeight = w / targetRatio; - originY = (h - cropHeight) / 2; - } - } else { - if (currentRatio > targetRatio) { - cropHeight = w * targetRatio; - originY = (h - cropHeight) / 2; - } else { - cropWidth = h / targetRatio; - originX = (w - cropWidth) / 2; - } - } - actions.push({ - crop: { - originX: Math.max(0, Math.floor(originX)), - originY: Math.max(0, Math.floor(originY)), - width: Math.min(w - Math.max(0, Math.floor(originX)), Math.floor(cropWidth)), - height: Math.min(h - Math.max(0, Math.floor(originY)), Math.floor(cropHeight)) - } - }); - } - - // Resize to a maximum of 1800px width (prevents memory crash) - const MAX_DIM = 1800; - if (isLandscape) { - actions.push({ resize: { width: MAX_DIM } }); - } else { - actions.push({ resize: { height: MAX_DIM } }); - } - - const manipResult = await ImageManipulator.manipulateAsync( - capturedUri, - actions, - { compress: 0.9, format: 'jpeg' as any } - ); - capturedUri = manipResult.uri; - console.log('Successfully manipulated and cropped image'); - } catch (manipError) { - console.error('Failed to manipulate image, preventing OOM crash!', manipError); - alert('Bildverarbeitungs-Fehler: ' + (manipError.message || manipError.toString())); - onCancel(); - return; // Abort here so we don't send a 16MB raw image to PreviewScreen - } - + // Instead of manipulating the image and risking an OOM or BitmapFactory crash, + // we directly use the captured photo and rely on React Native's Image component + // to safely downsample it during rendering via resizeMethod="resize". + console.log('Photo captured successfully, proceeding to PreviewScreen.'); + // Auto-save individual photo to gallery try { await saveToGallery(capturedUri); diff --git a/src/screens/PreviewScreen.tsx b/src/screens/PreviewScreen.tsx index 02a5b13a..d57cc1fe 100644 --- a/src/screens/PreviewScreen.tsx +++ b/src/screens/PreviewScreen.tsx @@ -309,7 +309,7 @@ export default function PreviewScreen({ {photoUris.slice(-3).map((uri, idx) => ( - + ))} @@ -323,7 +323,7 @@ export default function PreviewScreen({ {photoUris.slice(-4).map((uri, idx) => ( - + ))} @@ -336,7 +336,7 @@ export default function PreviewScreen({ {photoUris.slice(-2).map((uri, idx) => ( - + ))} @@ -347,7 +347,12 @@ export default function PreviewScreen({ default: return ( - + ); }