2016-06-29 40 views
8

Tôi có Hình ảnh được tải từ thư viện ảnh hoặc bất kỳ nguồn nào khác, thường là địa phương.Cách truy cập dữ liệu pixel hình ảnh trong phản ứng có nguồn gốc

Tôi làm cách nào để truy cập vào bản đồ dữ liệu pixel để thực hiện một số phép tính hoặc số đo?

+1

Bạn đã bao giờ tìm được giải pháp cho điều này chưa? – James

+1

Tôi nghĩ bạn có thể vẽ hình ảnh vào một khung vẽ, sau đó sử dụng 'getImageData()' để lấy bản đồ dữ liệu: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData. Mặc dù, nó không phải là một giải pháp dựa trên React. –

Trả lời

9

Có cách để nhận thông tin này bằng các mô-đun gốc, nhưng hiện tại tôi chỉ có triển khai Android. Thử nghiệm trên RN 0,42,3. Trước hết, bạn sẽ cần phải tạo một mô-đun gốc trong ứng dụng của mình. Giả sử ứng dụng được khởi tạo với tên SampleApp, tạo thư mục mới trong bạn Phản ứng dự án Native android/app/src/main/java/com/sampleapp/bitmap với hai tập tin trong đó:

android/app/src/main/java/com/SampleApp/bitmap/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/app/src/main/java/com/SampleApp/bitmap/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); 
    } 

    } 

} 

Như bạn có thể thấy trong các tập tin thứ hai có một phương pháp getPixels, mà sẽ có sẵn từ JS là một một phần của Bitmap mô-đun gốc. Nó chấp nhận một đường dẫn đến một tập tin hình ảnh, chuyển đổi hình ảnh thành một loại bitmap nội bộ, cho phép đọc các điểm ảnh. Tất cả các điểm ảnh được đọc từng cái một và được lưu vào mảng pixel dưới dạng chuỗi hex (vì React Native không cho phép truyền các giá trị hex qua cầu). Các chuỗi hex này có 8 ký tự, 2 ký tự trên mỗi kênh ARGB: hai ký tự đầu tiên là giá trị hex cho kênh alpha, thứ hai - cho màu đỏ, thứ ba - cho màu xanh lục và hai ký tự cuối cùng - cho kênh màu xanh lam. Ví dụ: giá trị ffffffff - là màu trắng và ff0000ff - là màu xanh dương. Để thuận tiện, chiều rộng hình ảnh, chiều cao và sự hiện diện của kênh alpha được trả về cùng với mảng pixel. Phương thức trả về một lời hứa với một đối tượng:

{ 
    width: 1200, 
    height: 800, 
    hasAlpha: false, 
    pixels: ['ffffffff', 'ff00ffff', 'ffff00ff', ...] 
} 

mô-đun Native cũng phải được đăng ký trong ứng dụng, sửa đổi android/app/src/main/java/com/sampleapp/MainApplication.java và thêm mô-đun mới trong đó:

@Override 
protected List<ReactPackage> getPackages() { 
    return Arrays.<ReactPackage>asList(
     new MainReactPackage(), 
     new BitmapReactPackage() // <--- 
); 
} 

Làm thế nào để sử dụng từ 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); 
    }); 

Tôi cần đề cập, rằng nó hoạt động khá chậm, rất có thể do chuyển một mảng lớn thông qua cây cầu.

+1

Cảm ơn câu trả lời của bạn! Hình như mô-đun gốc là cách để đi. Nhân tiện, [Android API] (https://developer.android.com/reference/android/graphics/Color.html) đề cập đến màu sắc được mã hóa theo thứ tự ARGB chứ không phải RGBA. Bạn đã đề cập rằng "giá trị hex" không được hỗ trợ. Các mảng số nguyên * có thực sự * không được hỗ trợ không? Không phải là nó quan trọng, bất kỳ xử lý hình ảnh có lẽ nên được thực hiện trên anyways bản địa. – cubrr

+1

@cubrr, bạn chính xác, tôi không chú ý đến nó. Màu sắc thực sự là ARGB. Về hex: Tôi đã cố gắng chuyển giá trị màu được trả về trực tiếp từ cuộc gọi 'bitmap.getPixel (x, y)' thông qua cầu, nhưng giá trị int mà tôi nhận được không mang nhiều thông tin cho tôi, đây là một loạt ints âm. Sau khi thực thi 'pixel.toString (16)' trong JS thì tốt hơn. Ví dụ: '(-4153434) .toString (16) =" -3f605a "'. Tôi đoán là tùy bạn quyết định định dạng nào bạn thích. –

+0

Ah, phải, Java không có số không dấu nên dĩ nhiên chúng có thể âm.Những gì có thể hoạt động là truyền qua các thời gian dài: 'long color = bitmap.getPixel (x, y) & 0xFFFFFFFFL' – cubrr

Các vấn đề liên quan