App crashing when swapping image - expo app react-native

73 Views Asked by At

below is the code that keeps crashing the app when it is ran

ImageManipulator.manipulateAsync(
      flippedImageUri,
      [
        {
          crop: {
            originX: swappedFaceX,
            originY: swappedFaceY,
            width: swappedFaceWidth,
            height: swappedFaceHeight,
          },
        },
      ],
      { format: 'png' }
    );

and below is the code that swaps

import { Dimensions, Image, StyleSheet, Text, TouchableOpacity, View } from 'react-native'
import React, { useCallback, useEffect, useRef } from 'react'
import { Camera } from "expo-camera";
import * as FaceDetector from 'expo-face-detector';
import * as ImageManipulator from 'expo-image-manipulator';
import useFaceContext from '../context/FaceProvider';

const windowWidth = Dimensions.get("window").width;
const windowHeight = Dimensions.get("window").height;
const CameraComponent = () => {

    const cameraRef = useRef(null);
    const {image, setFaces, faces, setSwappedImage, swappedImage} = useFaceContext();

    useEffect(() => {
      (async () => {
        const { status } = await Camera.requestCameraPermissionsAsync();
        if (status !== "granted") {
          alert("Camera permission not granted");
        }
      })();
    }, []);

    const handleFacesDetected = useCallback(({ faces }) => {
      setFaces(faces);
    }, []);

    const swapFaces = async () => {
        if (faces.length === 0) {
            alert('No face detected');
            return;
        }

        if (image === null) {
            alert('No image selected');
            return;
        }

  const [faceLandmarks] = faces;

  try {
        const manipResult = await ImageManipulator.manipulateAsync(
        image,
        [{ flip: ImageManipulator.FlipType.Horizontal }],
        { format: 'png' }
        );

    const { uri: flippedImageUri } = manipResult;

    const { width: imageWidth, height: imageHeight } = manipResult;

    const leftEye = faceLandmarks["LEFT_EYE"];
    const rightEye = faceLandmarks["RIGHT_EYE"];
    const nose = faceLandmarks["NOSE_BASE"];
    const mouth = faceLandmarks["LEFT_MOUTH"];

    if (!leftEye || !rightEye || !nose || !mouth) {
      alert('Cannot detect facial features');
      return;
    }

    const offsetX = 0.25; // Adjust the offset values to fit your face swapping needs
    const offsetY = 0.15;

    const leftEyeX = leftEye.x * imageWidth;
    const leftEyeY = leftEye.y * imageHeight;
    const rightEyeX = rightEye.x * imageWidth;
    const rightEyeY = rightEye.y * imageHeight;
    const noseX = nose.x * imageWidth;
    const noseY = nose.y * imageHeight;
    const mouthX = mouth.x * imageWidth;
    const mouthY = mouth.y * imageHeight;

    const swappedFaceWidth = Math.abs(rightEyeX - leftEyeX);
    const swappedFaceHeight = Math.abs(mouthY - noseY);
    const swappedFaceX = leftEyeX - offsetX * swappedFaceWidth;
    const swappedFaceY = noseY - offsetY * swappedFaceHeight;

    const result = await ImageManipulator.manipulateAsync(
      flippedImageUri,
      [
        {
          crop: {
            originX: swappedFaceX,
            originY: swappedFaceY,
            width: swappedFaceWidth,
            height: swappedFaceHeight,
          },
        },
      ],
      { format: 'png' }
    );

    setSwappedImage(result.uri);
  } catch (error) {
    console.error(error);
    alert('Error occurred during face swapping');
  }
};



  return <View style={styles.container}>
      <Camera style={styles.camera} type={Camera.Constants.Type.front} ref={cameraRef} onFacesDetected={handleFacesDetected} faceDetectorSettings={{ mode: FaceDetector.FaceDetectorMode.accurate, detectLandmarks: FaceDetector.FaceDetectorLandmarks.all, runClassifications: FaceDetector.FaceDetectorClassifications.all }}>
        {/* Render any additional UI components or overlays if needed */}
        {faces.map((face, index) =>
          <View
            key={index}
            style={[
              styles.faceOutline,
              {
                top: face.bounds.origin.y,
                left: face.bounds.origin.x,
                width: face.bounds.size.width,
                height: face.bounds.size.height
              }
            ]}
          />
        )}
      </Camera>

      <View style={{
        flexDirection: "row",
        alignItems: "center",
        gap: 20
        
      }}>

        {image && <Image source={{ uri: image }} style={styles.image} />}
        {swappedImage && <Image source={{ uri: swappedImage }} style={styles.image} />}
      </View>


      <TouchableOpacity style={styles.button} onPress={swapFaces}>
        <Text style={styles.buttonText}>Swap Faces</Text>
      </TouchableOpacity>
    </View>;
}

export default CameraComponent

const styles = StyleSheet.create({
  container: {
    width: windowWidth,
    height: windowHeight,
    justifyContent: 'center',
    alignItems: 'center',
  },
  camera: {
    flex: 1,
    width: "100%",
    height: "50%",
  },
  faceOutline: {
    position: 'absolute',
    borderWidth: 2,
    borderColor: 'red',
    borderRadius: 5,
    opacity: 0.7,
  },
  image: {
    width: 100,
    height: 100,
    resizeMode: 'contain',
    marginVertical: 10,
  },
  button: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'black',
    borderRadius: 5,
    padding: 10,
    marginVertical: 10,
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
    marginLeft: 5,
  },
  buttonIcon: {
    width: 20,
    height: 20,
    tintColor: 'white',
  },
});


this is an expo managed workflow

0

There are 0 best solutions below