2016-08-13 48 views
0

最近我正在学习使用RenderScript,而我实现了模糊效果。现在我想放大一部分位图。使用renderScript放大部分位图

like this

我用流动.rs代码来处理位图:

#pragma version(1) 
#pragma rs_fp_relaxed 
#pragma rs java_package_name(com.uniquestudio.renderscript) 

#include "rs_debug.rsh" 

int center_x,center_y; 
int radius; 
int scale; 
int i; 
int width; 

uchar4 tempArray[4194304]; 

void init() { 
    i = 0; 
} 
uchar4 __attribute__((kernel)) traversal(uchar4 in, uint32_t x, uint32_t y)  { 
    tempArray[i] = in; 
    i++; 
    return in; 
} 

uchar4 __attribute__((kernel)) invert(uchar4 in, uint32_t x, uint32_t y) { 
     int distance = (int) ((center_x -x) * (center_x - x) + (center_y - y) * (center_y - y)); 

     if(distance<radius*radius){ 
     int src_x = (int)((float)(x - center_x)/scale + center_x); 
     int src_y = (int)((float)(x - center_y)/scale + center_y); 

     return tempArray[src_y * width + src_x]; 
     } 
     return in; 
} 

正如你看到的,首先,我把 像素数据到一个数组tempArray

的Java代码:

public static Bitmap magnifierBitmap(Bitmap bitmap, int x, int y, int radius,int scale, Context context){ 
    RenderScript rs = RenderScript.create(context); 

    Allocation in = Allocation.createFromBitmap(rs, bitmap); 
    Allocation out = Allocation.createTyped(rs,in.getType()); 

    int width = bitmap.getWidth(); 
    ScriptC_magnifier magnifier = new ScriptC_magnifier(rs); 

    magnifier.set_center_x(x); 
    magnifier.set_center_y(y); 
    magnifier.set_radius(radius); 
    magnifier.set_scale(scale); 
    magnifier.set_width(width); 

    // first call kernel method 
    magnifier.forEach_traversal(in,in); 
    // second call kernel method 
    magnifier.forEach_invert(in,out); 

    out.copyTo(bitmap); 

    rs.destroy(); 
    magnifier.destroy(); 
    in.destroy(); 
    out.destroy(); 

    return bitmap; 


} 

在Java代码中,我首先调用traversal核方法。然后我拨打invert

但它不适用于我。

回答

1

我刚刚创建了一个示例来向您显示过程。你可以在这里找到它:https://bitbucket.org/cmaster11/rsbookexamples/src/tip/ImageZoomExample/

主要的代码(我试图使它自动explicative)如下:

的renderScript侧

// Store the input allocation 
rs_allocation inputAllocation; 

// Magnifying 
// TODO: here, some checks should be performed to prevent atX and atY to be < 0, as well 
// as them to not be greater than width and height 
int atX; 
int atY; 
float radius; 
float scale; // The scale is >= 1 

// Magnifier border size, to distinguish between magnified image and original one 
static float borderSize = 8.0f; 
// Border color, defaults to red 
static uchar4 border = {255.0f, 0.0f, 0.0f, 255.0f}; 

uchar4 __attribute__((kernel)) magnify(uchar4 in, int x, int y) { 

    // Calculates the distance between the touched point and the current kernel 
    // iteration pixel coordinated 
    // Reference: http://math.stackexchange.com/a/198769 
    float pointDistanceFromCircleCenter = sqrt(pow((float)(x - atX),2) + pow((float)(y - atY),2)); 

    // Notice: NOT OPTIMIZED, is good to understand the process 
    float distancePow = pow(pointDistanceFromCircleCenter,2); 
    float radiusPow = pow(radius, 2); 

    // These distances show two different radiuses, which belong to the border 
    // of the magnifier 
    float borderInnerRadius = radiusPow - pow(borderSize,2); 
    float borderOuterRadius = radiusPow + pow(borderSize,2); 

    // Is this pixel outside the magnify radius? 
    if(distancePow > borderOuterRadius) 
    { 
     // In this case, just copy the original image 
     return in; 
    } 
    // Is the current pixel inside the magnifier border 
    else if (distancePow >= borderInnerRadius && distancePow <= borderOuterRadius) 
    { 
     // Draw border 
     return border; 
    } 

    // If the point is inside the magnifying inner radius, draw the magnified image 

    // Calculates the current distance from the chosen magnifying center 
    float diffX = x - atX; 
    float diffY = y - atY; 

    // Scales down the distance accordingly to scale and returns the original coordinates 
    int originalX = atX + round(diffX/scale); 
    int originalY = atY + round(diffY/scale); 

    // Return the original image pixel at the calculated coordinates 
    return rsGetElementAt_uchar4(inputAllocation, originalX, originalY); 
} 

Java方面

// Example code 
RenderScript mRS; 
Allocation inputAllocation; 
Allocation outputAllocation; 
ScriptC_magnifier magnifier; 

ImageView originalImageView; 
ImageView zoomedImageView; 

Bitmap inputImage, outputImage; 

private void example() { 
    // ImageViews that will handle input and output 
    originalImageView = (ImageView) findViewById(R.id.imageView); 
    zoomedImageView = (ImageView) findViewById(R.id.imageView2); 

    // Initialize RenderScript context 
    initRS(); 

    // Perform first magnification 
    magnify(); 

    // Set up a click listener on the magnified image. 
    // When touched, the magnifier will be moved to the touch position. 
    zoomedImageView.setOnTouchListener(new View.OnTouchListener() { 
     @Override 
     public boolean onTouch(View v, MotionEvent event) { 
      int touchX = (int) event.getX(); 
      int touchY = (int) event.getY(); 

      Log.d("Touch", String.format("Touch: %d, %d", touchX, touchY)); 

      magnifier.set_atX(touchX); 
      magnifier.set_atY(touchY); 

      magnify(); 

      return false; 
     } 
    }); 
} 

private void initRS() { 
    mRS = RenderScript.create(this); 

    // Our magnifier script 
    magnifier = new ScriptC_magnifier(mRS); 

    // Input image 
    inputImage = BitmapFactory.decodeResource(getResources(), R.drawable.houseimage); 
    originalImageView.setImageBitmap(inputImage); 
    inputAllocation = Allocation.createFromBitmap(mRS, inputImage); 
    outputAllocation = Allocation.createTyped(mRS, inputAllocation.getType()); 

    // Initializes magnifier 
    magnifier.set_inputAllocation(inputAllocation); 
    magnifier.set_atX(300); 
    magnifier.set_atY(230); 
    magnifier.set_radius(100); 
    magnifier.set_scale(3); 
} 

private void magnify() { 
    // Run the kernel 
    magnifier.forEach_magnify(inputAllocation, outputAllocation); 

    // Displays the magnification output 
    outputImage = Bitmap.createBitmap(inputImage.getWidth(), inputImage.getHeight(), Bitmap.Config.ARGB_8888); 
    outputAllocation.copyTo(outputImage); 

    zoomedImageView.setImageBitmap(outputImage); 
} 

参考:RenderScript: parallel computing on Android, the easy way

+0

谢谢!它适用于我 – CoXier

+0

不客气! :) – cmaster11

+0

我对内核方法的参数类型感到困惑。'int'和'uint32_t'之间有什么不同? – CoXier