Существует способ получения этой информации с использованием собственных модулей, но на данный момент у меня есть только реализация Android. Протестировано по RN 0.42.3. Прежде всего, вам нужно создать собственный модуль в своем приложении. Если предположить, что приложение инициализируется с именем SampleApp
, создать новый каталог в вашем React Native проект android/app/src/main/java/com/sampleapp/bitmap
с двумя файлами в нем:
Android/приложение/SRC/главная/Java/COM/SampleApp/растровый/BitmapReactPackage.java
package com.sampleapp;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class BitmapReactPackage implements ReactPackage {
@Override
public List<Class<? extends JavaScriptModule>> createJSModules() {
return Collections.emptyList();
}
@Override
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
@Override
public List<NativeModule> createNativeModules(
ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new BitmapModule(reactContext));
return modules;
}
}
Android/приложение/SRC/главная/Java/COM/SampleApp/растровый/BitmapModule.java
package com.sampleapp;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.WritableNativeArray;
import com.facebook.react.bridge.WritableNativeMap;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.io.IOException;
public class BitmapModule extends ReactContextBaseJavaModule {
public BitmapModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "Bitmap";
}
@ReactMethod
public void getPixels(String filePath, final Promise promise) {
try {
WritableNativeMap result = new WritableNativeMap();
WritableNativeArray pixels = new WritableNativeArray();
Bitmap bitmap = BitmapFactory.decodeFile(filePath);
if (bitmap == null) {
promise.reject("Failed to decode. Path is incorrect or image is corrupted");
return;
}
int width = bitmap.getWidth();
int height = bitmap.getHeight();
boolean hasAlpha = bitmap.hasAlpha();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int color = bitmap.getPixel(x, y);
String hex = Integer.toHexString(color);
pixels.pushString(hex);
}
}
result.putInt("width", width);
result.putInt("height", height);
result.putBoolean("hasAlpha", hasAlpha);
result.putArray("pixels", pixels);
promise.resolve(result);
} catch (Exception e) {
promise.reject(e);
}
}
}
Как вы можете видеть, во втором файле есть метод getPixels
, который будет доступен JS как часть встроенного модуля Bitmap
. Он принимает путь к файлу изображения, преобразует изображение во внутренний тип Bitmap, что позволяет считывать пиксели изображения. Все пиксели изображений считываются один за другим и сохраняются в массиве пикселей в форме шестнадцатеричных строк (поскольку React Native не позволяет передавать шестнадцатеричные значения через мост). Эти шестнадцатеричные строки имеют 8 символов, 2 символа на канал ARGB: первые два символа - это шестнадцатеричное значение для альфа-канала, второе - для красного, третье - для зеленого, а последние два - для синего канала. Например, значение ffffffff
- это белый цвет и ff0000ff
- это синий цвет. Для удобства, ширина изображения, высота и наличие альфа-канала возвращаются вместе с массивом пикселей. Метод возвращает обещание с объектом:
{
width: 1200,
height: 800,
hasAlpha: false,
pixels: ['ffffffff', 'ff00ffff', 'ffff00ff', ...]
}
Native модуль также должен быть зарегистрирован в приложении, изменять android/app/src/main/java/com/sampleapp/MainApplication.java
и добавить новый модуль там:
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new BitmapReactPackage() // <---
);
}
Как использовать из JS:
import { NativeModules } from 'react-native';
const imagePath = '/storage/emulated/0/Pictures/blob.png';
NativeModules.Bitmap.getPixels(imagePath)
.then((image) => {
console.log(image.width);
console.log(image.height);
console.log(image.hasAlpha);
for (let x = 0; x < image.width; x++) {
for (let y = 0; y < image.height; y++) {
const offset = image.width * y + x;
const pixel = image.pixels[offset];
}
}
})
.catch((err) => {
console.error(err);
});
Я должен упомянуть, что он работает довольно медленно, скорее всего, из-за передачи огромного массива через мост.
Вы когда-нибудь находили решение этого вопроса? – James
Я думаю, вы могли бы нарисовать изображение на холсте, а затем использовать 'getImageData()' для получения карты данных: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData. Хотя это не решение на основе React. –