aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.43k stars 2.13k forks source link

Predictions.identify FileReader.readAsArrayBuffer is not implemented and ReferenceError: Property 'Buffer' doesn't exist #12218

Open rpostulart opened 1 year ago

rpostulart commented 1 year ago

Before opening, please confirm:

JavaScript Framework

React Native

Amplify APIs

Predictions

Amplify Categories

predictions

Environment information

``` # Put output below this line System: OS: macOS 14.0 CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz Memory: 32.33 MB / 16.00 GB Shell: 5.0.11 - /usr/local/bin/bash Binaries: Node: 18.16.0 - ~/.nvm/versions/node/v18.16.0/bin/node Yarn: 1.22.19 - /usr/local/bin/yarn npm: 9.5.1 - ~/.nvm/versions/node/v18.16.0/bin/npm Browsers: Chrome: 117.0.5938.149 Safari: 17.0 npmPackages: @aws-amplify/core: ^5.0.16 => 5.3.1 @aws-amplify/datastore: ^4.0.16 => 4.4.1 @aws-amplify/notifications: ^1.0.16 => 1.1.7 @aws-sdk/client-rekognition: ^3.425.0 => 3.425.0 (3.6.1) @babel/core: ^7.19.3 => 7.22.1 @expo/vector-icons: ^13.0.0 => 13.0.0 @react-native-async-storage/async-storage: 1.17.11 => 1.17.11 @react-native-community/netinfo: 9.3.7 => 9.3.7 @react-native-picker/picker: 2.4.8 => 2.4.8 @react-navigation/bottom-tabs: ^6.3.1 => 6.5.7 @react-navigation/native: ^6.0.10 => 6.1.6 @react-navigation/stack: ^6.2.1 => 6.3.16 @shopify/flash-list: 1.4.0 => 1.4.0 @types/react: ~18.0.24 => 18.0.38 (18.2.8) @types/react-native: ~0.70.6 => 0.70.14 HelloWorld: 0.0.1 amazon-cognito-identity-js: ^5.2.10 => 5.2.14 (6.2.0) aws-amplify: ^5.0.16 => 5.2.4 aws-amplify-react-native: ^7.0.2 => 7.0.2 aws-sdk: ^2.1471.0 => 2.1471.0 base-64: ^1.0.0 => 1.0.0 expo: ~48.0.18 => 48.0.20 expo-barcode-scanner: ~12.3.2 => 12.3.2 expo-blur: ~12.2.2 => 12.2.2 expo-camera: ~13.2.1 => 13.2.1 expo-constants: ~14.2.1 => 14.2.1 expo-dev-client: ~2.2.1 => 2.2.1 expo-font: ~11.1.1 => 11.1.1 expo-image-manipulator: ~11.1.1 => 11.1.1 expo-image-picker: ~14.1.1 => 14.1.1 expo-splash-screen: ~0.18.2 => 0.18.2 expo-status-bar: ~1.4.2 => 1.4.4 jimp: ^0.22.10 => 0.22.10 jsbarcode: ^3.11.5 => 3.11.5 metro-config: ^0.71.1 => 0.71.3 (0.73.10) pako: ^2.1.0 => 2.1.0 (2.0.4, 1.0.11) react: 18.2.0 => 18.2.0 react-dom: 18.2.0 => 18.2.0 react-native: 0.71.13 => 0.71.13 react-native-dropdown-picker: ^5.4.2 => 5.4.6 react-native-gesture-handler: ~2.9.0 => 2.9.0 react-native-get-random-values: ^1.9.0 => 1.9.0 react-native-image-resizer: ^1.4.5 => 1.4.5 react-native-loading-spinner-overlay: ^3.0.0 => 3.0.1 react-native-mlkit-ocr: ^0.3.0 => 0.3.0 react-native-paper: 4.9.2 => 4.9.2 react-native-quick-base64: ^2.0.7 => 2.0.7 react-native-reanimated: ~2.14.4 => 2.14.4 react-native-safe-area-context: 4.5.0 => 4.5.0 react-native-svg: 13.4.0 => 13.4.0 react-native-tesseract-ocr: ^2.0.3 => 2.0.3 react-native-web: ~0.18.7 => 0.18.12 tesseract.js: ^5.0.0 => 5.0.0 typescript: ^4.6.3 => 4.9.5 npmGlobalPackages: @aws-amplify/cli: 12.6.0 corepack: 0.17.0 eas-cli: 5.4.0 expo-cli: 6.3.10 npm: 9.5.1 ```

Describe the bug

When calling 
  try {
        const response = Predictions.identify({
          text: {
            source: { bytes: resizePhoto }
            format: "PLAIN",
          },
        });
      } catch (error) {
        console.log("AAA", error);
      }

i get: ReferenceError: Property 'Buffer' doesn't exist

 When calling 
  try {
        const response = Predictions.identify({
          text: {
            source: { bytes: resizePhoto }
            format: "PLAIN",
          },
        });
      } catch (error) {
        console.log("AAA", error);
      }

i get: Error: FileReader.readAsArrayBuffer is not implemented

Expected behavior

I expect the detectText endpoint will give a response

Reproduction steps

Use Expo with AWS Amplify

Code Snippet

// Put your code below this line.
import { useState, useEffect, useRef } from "react";
import { View, Image, TouchableOpacity } from "react-native";
import { Camera } from "expo-camera";
import * as FileSystem from "expo-file-system";
import { manipulateAsync, SaveFormat } from "expo-image-manipulator";
import { Predictions } from "aws-amplify";
import { withAuthenticator } from "aws-amplify-react-native";

const CameraComponent = () => {
  const [hasPermission, setHasPermission] = useState(null);
  const cameraRef = useRef(null); // Ref for the camera component

  useEffect(() => {
    (async () => {
      const { status } = await Camera.requestCameraPermissionsAsync();
      setHasPermission(status === "granted");
    })();
  }, []);

  const resizeImage = async (uri, width, height) => {
    const resizedPhoto = await manipulateAsync(
      uri,
      [{ resize: { width, height } }],
      { format: SaveFormat.JPEG, compress: 0.6, base64: true }
    );
    return resizedPhoto;
  };

  const takePicture = async () => {
    if (cameraRef.current) {
      const photo = await cameraRef.current.takePictureAsync();
      const resizePhoto = await resizeImage(photo.uri, 500, 500);

      // // Read the image file as a binary buffer
      // // console.log("BASE^$", resizePhoto);
      const file = await FileSystem.readAsStringAsync(resizePhoto.uri, {
        encoding: FileSystem.EncodingType.Base64,
      });

      console.log(file);

      const fileBlob = await new Blob([file], { type: "image/png" });
      console.log(resizePhoto.uri);

      try {
        const response = Predictions.identify({
          text: {
            source: { file: { uri: resizePhoto.uri } }, // Use the original image file URI
            format: "PLAIN",
          },
        });
      } catch (error) {
        console.log("AAA", error);
      }
    }
  };

  const refocusCamera = () => {
    // Refocus the camera by taking another picture
    takePicture();
  };

  return (
    <View style={{ flex: 1 }}>
      <Camera
        ref={cameraRef} // Set the camera ref
        style={{ flex: 1 }}
        type={cameraType}
      >
        {/* Circular button for refocusing */}
        <TouchableOpacity
          style={{
            position: "absolute",
            bottom: 20,
            right: 20,
            width: 60,
            height: 60,
            borderRadius: 30,
            backgroundColor: "white",
            justifyContent: "center",
            alignItems: "center",
          }}
          onPress={refocusCamera}
        >
          <View
            style={{
              width: 50,
              height: 50,
              borderRadius: 25,
              backgroundColor: "#E97E91",
            }}
          />
        </TouchableOpacity>
      </Camera>
      {imageUri && <Image source={{ uri: imageUri }} style={{ flex: 1 }} />}
    </View>
  );
};

export default withAuthenticator(CameraComponent);

Log output

``` // Put your logs below this line ```

aws-exports.js

No response

Manual configuration

No response

Additional configuration

No response

Mobile Device

No response

Mobile Operating System

No response

Mobile Browser

No response

Mobile Browser Version

No response

Additional information and screenshots

No response

nadetastic commented 1 year ago

Related #11588

nadetastic commented 1 year ago

HI @rpostulart thank you for opening this issue. Looks like you are having issues with Predictions where an error Buffer is not found. This is currently being tracked on the above linked issue, however I may have a work around that can work for you which depends on a 3rd party dependency.

Could you take a look at this comment and let me know if this work around unblocks you? The difference I see between this example and what you are doing is it takes use of the base64 photo instead of the photo uri.

rpostulart commented 1 year ago

No, i get: [ReferenceError: Property 'Buffer' doesn't exist]

This is the code:

import { toByteArray } from "react-native-quick-base64";

 const options = { quality: 0.7, base64: true };
 const photo = await cameraRef.current.takePictureAsync(options);
 const bytes = toByteArray(photo.base64);

 try {
        await Predictions.identify({
          text: {
            source: { bytes },
          },
        });
      } catch (error) {
        console.log("AAA", error);
      }
rpostulart commented 1 year ago

See https://github.com/rpostulart/nbCamera

Glognus commented 10 months ago

Same issue for me

Glognus commented 9 months ago

I found a workaround if it can help, you will need to install base-64

then use it as follow :

import { decode as atob } from "base-64";

...

const base64ToArrayBuffer = (base64) => {
  const binaryString = atob(base64);
  const length = binaryString.length;
  const bytes = new Uint8Array(length);
  for (let i = 0; i < length; i++) {
    bytes[i] = binaryString.charCodeAt(i);
  }
  return bytes.buffer;
};

...

const { entities } = await Predictions.identify({
  entities: {
    source: {
      bytes: base64ToArrayBuffer(imageResult.base64),
    },
  },
});