2016-08-13 2 views
0

Недавно я узнал об использовании RenderScript, пока я внедрил blur effet. Теперь я хочу увеличить часть растрового изображения.Использование 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/.

Основной код (я пытался сделать его авто-поясняющий) заключается в следующем:

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

Меня смущает тип param метода kernel.Что отличается от 'int' и 'uint32_t'? – CoXier