使用Renderscript启动选项

时间:2016-03-04 09:04:07

标签: android arrays crop renderscript

我有一个greyvalue图像dataIn的byte []数组,其尺寸宽度为* height。现在,我想通过应用平移(dx,dy)并截断边界区域来裁剪图像,以便dataOut具有尺寸(width-abs(dx))*(height-abs(dy) ))。

在RenderScript中,我会对输入和输出使用2-d uchar-Allocation。为了有效地应用裁剪操作,它考虑使用LaunchOptions(例如)setX(dx,width)和setY(0,height-dy)并应用一个简单的内核,该内核只接受来自子集的值原始尺寸。

然而,当使用启动选项时,out-Allocation仍然具有原始大小width * height,即裁剪的部分将仅显示为零 - 但是,我实际上希望它们被删除,即out-Allocation be尺寸减小。

问题:RS中是否有解决方案以更优雅地执行此裁剪工作?感谢您的反馈。

更新:我想,我找到了解决方案。通过从一开始就以缩小的维度将out-Allocation定义为脚本全局,传递dx和dy以及全局变量,然后应用rsSetElementAt_uchar来设置out-Allocation的值。稍后会给出一个udpate。

2 个答案:

答案 0 :(得分:3)

所以,这是我的快速裁剪工具,用于裁剪500k像素图像需要5ms。它使用LaunchOptions和缩小的输出尺寸。如果你需要裁剪一个Bitmap,只需使用元素类型U8_4和分配uchar_4而不是U8和uchar。

crop.rs文件:

#pragma version(1)
#pragma rs java_package_name(com.xxx.yyy)
#pragma rs_fp_relaxed

int32_t width;
int32_t height;

rs_allocation croppedImg;
uint xStart, yStart;

 void __attribute__((kernel)) doCrop(uchar in,uint32_t x, uint32_t y) {
    rsSetElementAt_uchar(croppedImg,in, x-xStart, y-yStart);
 }

Java部分:

   // data1 is the byte[] array with (grayvalue) data of size 
   // width*height you want to crop.


    // define crop shift (dx, dy) here
    int dx=0;       // (-width < dx < width);
    int dy=250;     // (- height < dy < height);

    int xStart=0, xEnd=0;
    int yStart=0, yEnd=0;

    // x direction
    if (dx<0) {
        xStart= Math.abs(dx);
        xEnd=width;
    }
    else
    {
        xStart = 0;
        xEnd = width - Math.abs(dx);
    }

    // same for y direction
    if (dy<0) {
        yStart= Math.abs(dy);
        yEnd=height;
    }
    else
    {
        yStart = 0;
        yEnd = height - Math.abs(dy);
    }

    // initiate rs and crop script
    RenderScript rs = RenderScript.create(this);
    ScriptC_crop mcropScr=new ScriptC_crop (rs);

    // define allocations. Note the reduced size of cropAlloc 
    Type.Builder typeUCHAR = new Type.Builder(rs, Element.U8(rs));  
    typeUCHAR.setX(width).setY(height);

    inAlloc = Allocation.createTyped(rs, typeUCHAR.create());
    inAlloc.copyFrom(data1);

    Type.Builder TypeUCHARCropped = new Type.Builder(rs, Element.U8(rs));
    TypeUCHARCropped.setX(xEnd-xStart).setY(yEnd-yStart);

    Allocation cropAlloc = Allocation.createTyped(rs,  TypeUCHARCropped.create());
    mcropScr.set_croppedImg(cropAlloc);
    mcropScr.set_xStart(xStart);
    mcropScr.set_yStart(yStart);

    Script.LaunchOptions lo = new Script.LaunchOptions();
    lo.setX(xStart, xEnd);
    lo.setY(yStart, yEnd);

    mcropScr.forEach_doCrop(inAlloc, lo);


    byte[] data1_cropped =new byte[(xEnd-xStart)*(yEnd-yStart)];
    cropAlloc.copyTo(data1_cropped);

答案 1 :(得分:0)

与其他答案相似的想法,但这与Google的Intrinsics API的风格相符:

#pragma version(1)
#pragma rs java_package_name(com.sicariusnoctis.collaborativeintelligence)
#pragma rs_fp_relaxed

rs_allocation input;
uint32_t xStart, yStart;

uchar4 RS_KERNEL crop(uint32_t x, uint32_t y) {
    return rsGetElementAt_uchar4(input, x + xStart, y + yStart);
}

要设置:

fun setup(
    width: Int, height: Int,
    new_width: Int, new_height: Int,
    xStart: Int, yStart: Int
) {
    val inputType = Type.createXY(rs, Element.RGBA_8888(rs), width, height)
    val outputType = Type.createXY(rs, Element.RGBA_8888(rs), new_width, new_height)

    inputAllocation = Allocation.createTyped(rs, inputType, Allocation.USAGE_SCRIPT)
    outputAllocation = Allocation.createTyped(rs, outputType, Allocation.USAGE_SCRIPT)

    crop = ScriptC_crop(rs)
    crop._xStart = xStart.toLong()
    crop._yStart = yStart.toLong()
    crop._input = inputAllocation
}

并执行:

fun execute(inputArray: ByteArray): ByteArray {
    inputAllocation.copyFrom(inputArray)
    crop.forEach_crop(outputAllocation)

    val outputArray = ByteArray(outputAllocation.bytesSize)
    outputAllocation.copyTo(outputArray)
    return outputArray
}