如何在React Native中获取像素颜色信息

问题描述

我目前正在尝试使用expo-camera在博览会项目中通过设备相机实现颜色选择。为此,我需要访问与屏幕上特定像素有关的颜色信息,这些颜色信息是根据用户交互选择的。

获取该信息的最佳方法是什么?

我的第一个想法是拍摄一张图片,然后使用拍打坐标找到我要在图像中搜索的像素,然后从该图像中提取信息。为此,我尝试使用react-native-pixel-color库(及类似库),但似乎已被放弃。

请注意,我目前尚不了解Swift,因此,如果其他所有方法均失败,则对本地解决方案进行编码通常是最后的选择。

谢谢!

解决方法

我想通了。好消息:与完全托管的 Expo 兼容。坏消息:它非常丑陋(您的模块仍然值得编写)。

总结如下:

  1. 使用 expo-camera 显示来自用户相机的视图
  2. 使用 expo-gl 将相机视图从 expo-camera 加载到 GLView
  3. 使用 expo-gl 拍摄 GLView 的快照
  4. 使用 expo-image-manipulator 将步骤 3 中拍摄的快照缩小到屏幕上所需的区域
  5. 使用 react-native-canvas 将像素读入 ImageData 对象

部分代码: 首先,我的进口:

import { Camera } from "expo-camera";
import React,{ useState,useEffect,useRef,useCallback } from "react";
import { GLView } from "expo-gl";
import * as FileSystem from "expo-file-system";
import * as ImageManipulator from "expo-image-manipulator";
import Canvas,{ Image as CanvasImage } from "react-native-canvas";
import { StyleSheet,Text,TouchableOpacity,View,Image } from "react-native";

步骤 1 和 2 在这里完成: https://github.com/expo/expo/blob/master/apps/native-component-list/src/screens/GL/GLCameraScreen.tsx

唯一需要修改的是将 fragShaderSource 的结尾更改为以下内容:

void main() {
  fragColor = vec4(texture(cameraTexture,uv).rgb,1.0);
}`;

这是因为 Expo 的演示会反转颜色。

第3步:把用GLView的onContextCreate传入的gl变量传给这个:

const takeFrame = async (gl) => {
  const snapshot = await GLView.takeSnapshotAsync(gl,{
    format: "jpeg",});
  return snapshot.uri;
};

第 4 步:在此处传入来自 takeFrame 的 uri:

const cropFrame = async (uri) => {
  // Find minX,minY,width,height

  const result = await ImageManipulator.manipulateAsync(uri,[
    {
      crop: {
        originX: minX,originY: minY,height
      },},]);

  return result.uri;
};

第五步:需要提取base64版本的图片并传入react-native-canvas:

const readImage = async (imgSrc,height) => {
  setImgUri(imgSrc);
  canvas.width = width;
  canvas.height = height;
  const context = canvas.getContext("2d");
  const image = new CanvasImage(canvas);

  const options = { encoding: "base64",compress: 0.4 };
  const base64 = await FileSystem.readAsStringAsync(imgSrc,options);
  const src = "data:image/jpeg;base64," + base64;
  image.src = src;
  image.addEventListener("load",() => {
    context.drawImage(image,0);
    context
      .getImageData(0,canvas.width,canvas.height)
      .then((imageData) => {
        console.log(
          "Image data:",imageData,Object.values(imageData.data).length
        );
      })
      .catch((e) => {
        console.error("Error with fetching image data:",e);
      });
  });
};

请告诉我是否有更好的方法来做到这一点:)