2012-05-14 40 views
10

Tôi thấy có thiếu tài liệu tốt trong RenderScript, cho những gì tôi biết, forEach trong RS là thực thi gốc() cho từng mục riêng lẻ trong phân bổ.Truyền mảng tới rsForEach trong Renderscript Compute

Tôi đang cố gắng tạo một thư viện cho Renderscript xử lý hình ảnh, làm điểm bắt đầu, tôi đã đạt được điều này great answer. Nhưng vấn đề là hoạt động mờ là trên Mỗi pixel và mỗi pixel yêu cầu một vòng lặp khác (n với chiều rộng mờ) của phép tính. Mặc dù chạy trên đa lõi, nó vẫn còn hơi chậm.

Tôi đang cố gắng sửa đổi nó để cho phép bộ lọc hộp (hai lần), nhưng điều đó yêu cầu làm việc trên một hàng hoặc cột thay vì ô. Vì vậy, có cách nào để yêu cầu foreach để gửi một mảng để root()?

+0

Bạn có thể có 2 kịch bản cho mờ theo chiều ngang và dọc. http://stackoverflow.com/questions/13435561/android-blur-bitmap-instantly –

Trả lời

16

rsForEach chỉ có thể hoạt động khi Phân bổ.

Nếu bạn muốn có hàm gọi hàm rsForEach() cho mỗi hàng hình ảnh bạn phải chuyển trong Phân bổ có kích thước bằng với chiều dài bằng số hàng và sau đó tìm ra hàng bạn nên hoạt động bên trong root() (tương tự cho hoạt động trên mỗi cột). RenderScript sau đó sẽ chia công việc để chạy trên các tài nguyên có sẵn (nhiều hơn một hàng đang được xử lý cùng một lúc trên các thiết bị đa lõi).

Một cách bạn có thể làm điều đó là bằng cách chuyển giao trong Phân bổ cung cấp bù trừ (trong mảng dữ liệu hình ảnh) của các hàng hình ảnh. Đối số v_in bên trong root() sau đó sẽ là hàng offset. Vì cuộc gọi rsForEach của Allocations đang hoạt động không phải là dữ liệu hình ảnh mà bạn không thể ghi hình ảnh ra bằng cách sử dụng đối số v_out và bạn phải ràng buộc hình ảnh đầu ra một cách riêng biệt.

Dưới đây là một số RenderScript cho thấy điều này:

#pragma version(1) 
#pragma rs java_package_name(com.android.example.hellocompute) 

rs_allocation gIn; 
rs_allocation gOut; 
rs_script gScript; 

int mImageWidth; 
const uchar4 *gInPixels; 
uchar4 *gOutPixels; 

void init() { 
} 

static const int kBlurWidth = 20; 

// 
// This is called per row. 
// The row indices are passed in as v_in or you could also use the x argument and multiply it by image width. 
// 
void root(const int32_t *v_in, int32_t *v_out, const void *usrData, uint32_t x, uint32_t y) { 
    float3 blur[kBlurWidth]; 
    float3 cur_colour = {0.0f, 0.0f, 0.0f}; 

    for (int i = 0; i < kBlurWidth; i++) { 
     float3 init_colour = {0.0f, 0.0f, 0.0f}; 
     blur[i] = init_colour; 
    } 

    int32_t row_index = *v_in; 
    int blur_index = 0; 

    for (int i = 0; i < mImageWidth; i++) { 
     float4 pixel_colour = rsUnpackColor8888(gInPixels[i + row_index]); 

     cur_colour -= blur[blur_index]; 
     blur[blur_index] = pixel_colour.rgb; 
     cur_colour += blur[blur_index]; 

     blur_index += 1; 
     if (blur_index >= kBlurWidth) { 
      blur_index = 0; 
     } 

     gOutPixels[i + row_index] = rsPackColorTo8888(cur_colour/(float)kBlurWidth); 
     //gOutPixels[i + row_index] = rsPackColorTo8888(pixel_colour); 
    } 
} 


void filter() { 
    rsDebug("Number of rows:", rsAllocationGetDimX(gIn)); 
    rsForEach(gScript, gIn, gOut, NULL); 
} 

này sẽ được thiết lập bằng cách sử dụng Java sau:

mBlurRowScript = new ScriptC_blur_row(mRS, getResources(), R.raw.blur_row); 

    int row_width = mBitmapIn.getWidth(); 

    // 
    // Create an allocation that indexes each row. 
    // 
    int num_rows = mBitmapIn.getHeight(); 
    int[] row_indices = new int[num_rows]; 
    for (int i = 0; i < num_rows; i++) { 
     row_indices[i] = i * row_width; 
    } 
    Allocation row_indices_alloc = Allocation.createSized(mRS, Element.I32(mRS), num_rows, Allocation.USAGE_SCRIPT); 
    row_indices_alloc.copyFrom(row_indices); 

    // 
    // The image data has to be bound to the pointers within the RenderScript so it can be accessed 
    // from the root() function. 
    // 
    mBlurRowScript.bind_gInPixels(mInAllocation); 
    mBlurRowScript.bind_gOutPixels(mOutAllocation); 

    // Pass in the image width 
    mBlurRowScript.set_mImageWidth(row_width); 

    // 
    // Pass in the row indices Allocation as the input. It is also passed in as the output though the output is not used. 
    // 
    mBlurRowScript.set_gIn(row_indices_alloc); 
    mBlurRowScript.set_gOut(row_indices_alloc); 
    mBlurRowScript.set_gScript(mBlurRowScript); 
    mBlurRowScript.invoke_filter(); 
+0

+100 điều này rất thông minh, không bao giờ nghĩ đến việc chuyển "chỉ mục" sang giả mạo nó. – xandy

+0

Tôi tiếp tục nhận được "không có chức năng phù hợp cho cuộc gọi đến 'rsForEach'" cho tập lệnh này. làm thế nào mà? Các dòng tiếp theo trên lỗi là: "... lưu ý: chức năng ứng cử viên không khả thi: yêu cầu 3 đối số, nhưng 4 đã được cung cấp ... lưu ý: chức năng ứng cử viên không khả thi: yêu cầu 5 đối số, nhưng 4 đã được cung cấp ... lưu ý: chức năng ứng cử viên không khả thi: yêu cầu 6 đối số, nhưng 4 đã được cung cấp " –

+1

Phương pháp này không hoạt động nữa vì" API 20+ chỉ cho phép phân bổ 1D đơn giản được sử dụng với liên kết "(Trích dẫn từ thông báo lỗi). Do đó mBlurRowScript.bind_gInPixels (mInAllocation); không thành công. – Searles

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