问题描述
我目前正在尝试使用expo-camera
在博览会项目中通过设备相机实现颜色选择。为此,我需要访问与屏幕上特定像素有关的颜色信息,这些颜色信息是根据用户交互选择的。
我的第一个想法是拍摄一张图片,然后使用拍打坐标找到我要在图像中搜索的像素,然后从该图像中提取信息。为此,我尝试使用react-native-pixel-color
库(及类似库),但似乎已被放弃。
请注意,我目前尚不了解Swift,因此,如果其他所有方法均失败,则对本地解决方案进行编码通常是最后的选择。
谢谢!
解决方法
我想通了。好消息:与完全托管的 Expo 兼容。坏消息:它非常丑陋(您的模块仍然值得编写)。
总结如下:
- 使用 expo-camera 显示来自用户相机的视图
- 使用 expo-gl 将相机视图从 expo-camera 加载到 GLView
- 使用 expo-gl 拍摄 GLView 的快照
- 使用 expo-image-manipulator 将步骤 3 中拍摄的快照缩小到屏幕上所需的区域
- 使用 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);
});
});
};
请告诉我是否有更好的方法来做到这一点:)