使用RenderScript在android中浮雕形状

时间:2015-09-20 12:05:47

标签: android renderscript

这个问题基于link。 我试了@ miloslaw-smyk的答案。但是我无法让它发挥作用。我不确定createPath(1)的含义。我不知道如何创建具有一定笔画宽度的路径。我们可以使用fillpaint来做到这一点。无论如何,我已经展示了完整的代码。问题是我没有看到原始链接显示的任何浮雕效果(参见下面的输出图像)。请让我知道我做错了什么。 (我使用的是targetSdkVersion 23,设备已更新4.1.2 android)

private Bitmap puzzelImage; // screen size image
private Bitmap mBitmapIn;
private Bitmap mBitmapPuzzle;
private RenderScript mRS;
private Allocation mInAllocation;
private Allocation mPuzzleAllocation;
private Allocation mCutterAllocation;

private Allocation mOutAllocation;
private Allocation mOutAllocation2;
private Allocation mAllocationHist;
private ScriptIntrinsicBlur mScriptBlur;
private ScriptIntrinsicBlend mScriptBlend;
private ScriptIntrinsicHistogram mScriptHistogram;
private ScriptIntrinsicLUT mScriptLUT;
public Activity ctx;
private int bw = 780;
private int bh = 780; Path path2;

private void init() {
    if (puzzel.mybitmap == null)
        return;
    bw = puzzelImage.getWidth();
    bh = puzzelImage.getHeight();
    mBitmapIn = puzzelImage ;
    mBitmapPuzzle = Bitmap.createBitmap(bw, bh, Bitmap.Config.ARGB_8888);  // this will hold the puzzle
    Canvas c = new Canvas(mBitmapPuzzle);

     createPath();
    //path2 = path1;
    fillPaint.setStrokeWidth(5);
    c.drawPath(path2, fillPaint);  // draw it on canvas

    createScript();  // get renderscripts and Allocations ready

    // Apply gaussian blur of radius 25 to our drawing
    mScriptBlur.setRadius(25);
    mScriptBlur.setInput(mPuzzleAllocation);
    mScriptBlur.forEach(mOutAllocation);

    // Now apply the blur of radius 1
    mScriptBlur.setRadius(1);
    mScriptBlur.setInput(mPuzzleAllocation);
    mScriptBlur.forEach(mOutAllocation2);

    // Subtract one blur result from another
    mScriptBlend.forEachSubtract(mOutAllocation, mOutAllocation2);

    // We now want to normalize the result (e.g. make it use full 0-255 range).
    // To do that, we will first compute the histogram of our image
    mScriptHistogram.setOutput(mAllocationHist);
    mScriptHistogram.forEach(mOutAllocation2);

    // copy the histogram to Java array...
    int []hist = new int[256 * 4];
    mAllocationHist.copyTo(hist);

    // ...and walk it from the end looking for the first non empty bin
    int i;
    for(i = 255; i > 1; i--)
        if((hist[i * 4] | hist[i * 4 + 1] | hist[i * 4 + 2]) != 0)
            break;

    // Now setup the LUTs that will map the image to the new, wider range.
    // We also use the opportunity to inverse the image ("255 -").
    for(int x = 0; x <= i; x++)
    {
        int val = 255 - x * 255 / i;

        mScriptLUT.setAlpha(x, 255);  // note we always make it fully opaque
        mScriptLUT.setRed(x, val);
        mScriptLUT.setGreen(x, val);
        mScriptLUT.setBlue(x, val);
    }


    // the mapping itself.
    mScriptLUT.forEach(mOutAllocation2, mOutAllocation);

    Bitmap mBitmapCutter = Bitmap.createBitmap(bw, bh, Bitmap.Config.ARGB_8888);
    c = new Canvas(mBitmapCutter);
    createPath();
    fillPaint.setStrokeWidth(1);
    c.drawPath(path2, fillPaint);
    mCutterAllocation = Allocation.createFromBitmap(mRS, mBitmapCutter);

    // cookie cutter now
    mScriptBlend.forEachDstIn(mCutterAllocation, mOutAllocation);

    mScriptBlend.forEachMultiply(mOutAllocation, mInAllocation);
    mInAllocation.copyTo(mBitmapPuzzle);
}


private void createScript() {
    try {
        mRS = RenderScript.create(ctx);

        mPuzzleAllocation = Allocation.createFromBitmap(mRS, mBitmapPuzzle);

        // three following allocations could actually use createSized(),
        // but the code would be longer.
        mInAllocation = Allocation.createFromBitmap(mRS, mBitmapIn);
        mOutAllocation = Allocation.createFromBitmap(mRS, mBitmapPuzzle);
        mOutAllocation2 = Allocation.createFromBitmap(mRS, mBitmapPuzzle);

        mAllocationHist = Allocation.createSized(mRS, Element.I32_3(mRS), 256);

        mScriptBlur = ScriptIntrinsicBlur.create(mRS, Element.U8_4(mRS));
        mScriptBlend = ScriptIntrinsicBlend.create(mRS, Element.U8_4(mRS));
        mScriptHistogram = ScriptIntrinsicHistogram.create(mRS, Element.U8_4(mRS));
        mScriptLUT = ScriptIntrinsicLUT.create(mRS, Element.U8_4(mRS));
    }catch (Exception e)
    {

    }
}

public void createPath()
{
    path2 = new Path();
    //path 1 samll one
    Point[] araay = new Point[]{new Point(144,320),new Point(109,200), new Point(171,308),new Point(178,240),new Point(171,172),new Point(109,282),new Point(144,160)};
    AddBeziers(path2, araay, 320, 144);
    AddLine(path2, 216, 144 );
    AddLine(path2, 216, 216 );
    AddLine(path2, 144, 320);

    fillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    fillPaint.setColor(Color.WHITE);
    fillPaint.setFlags(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
    fillPaint.setAntiAlias(true);
    fillPaint.setDither(true);
    fillPaint.setStrokeJoin(Paint.Join.ROUND);
    fillPaint.setStrokeCap(Paint.Cap.ROUND);
    fillPaint.setStyle(Paint.Style.FILL_AND_STROKE);

}


 protected Path AddLine(Path path, int endX, int endY) {
    //path.moveTo(startX, startY);

    path.lineTo(endX, endY);
    return path;
}

protected Path AddBeziers(Path path, Point[] points, int lastX, int lastY) {

    if (points[0].X != lastX && points[0].Y != lastY)
        path.moveTo(points[0].X, points[0].Y);

    int index = 1;

    path.cubicTo(points[index].X, points[index].Y, points[index + 1].X,
            points[index + 1].Y, points[index + 2].X, points[index + 2].Y);
    index = index + 3;
    path.cubicTo(points[index].X, points[index].Y, points[index + 1].X,
            points[index + 1].Y, points[index + 2].X, points[index + 2].Y);

    return path;


    /*pointsCounter = points.length;
    //point = new PointNew(new PointF(points[1].X, points[1].Y));
    prev = new PointNew(new PointF(points[0].X, points[0].Y));
    //next = new PointNew(new PointF(points[2].X, points[2].Y));
    for (int i =1; i < points.length; i++)
        appendToPath(path, new PointF(points[i].X, points[i].Y), null);

    return path;*/
}



    @Override
protected void onDraw(Canvas canvas) {
    canvas.drawBitmap(mBitmapPuzzle, 0, 0, fillPaint);
    super.onDraw(canvas);
}

enter image description here

1 个答案:

答案 0 :(得分:0)

您可以试用我的createPath()版本吗?我稍微修改它以绘制更大的拼图并接受笔画宽度作为参数。

public void createPath(int strokeWidth)
{
    //path 2 Big one
    Point[]araay = new Point[]{new Point(144,320),new Point(109,200), new Point(171,308),new Point(178,240),new Point(171,172),new Point(109,282),new Point(144,160)};
    Point[]braay = new Point[araay.length];

    int idx = 6;
    for(Point p : araay)
        braay[idx--] = new Point((200 + p.x), p.y);

    path2.moveTo(144,320);
    AddBeziers(path2, araay, 320, 144);
    AddLine(path2, 216, 144);
    AddBeziers(path2, braay, 320, 144);
    AddLine(path2, 144, 320);
    path2.close();

    Matrix m = new Matrix();
    m.setScale(2, 2);

    path2.transform(m);

    MaskFilter mEmboss = new EmbossMaskFilter(new float[] { 1, 1, 1 }, 0.4f, 6,   3.5f);
    fillPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    fillPaint.setColor(Color.WHITE);
    fillPaint.setFlags(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
    fillPaint.setAntiAlias(true);
    fillPaint.setDither(true);
    fillPaint.setStrokeJoin(Paint.Join.ROUND);
    fillPaint.setStrokeCap(Paint.Cap.ROUND);
    fillPaint.setStrokeWidth(strokeWidth);
    fillPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    fillPaint.setStrokeMiter(0);
}