使用RenderScript压印在机器人的形状 [英] Use RenderScript to emboss a shape in android

查看:161
本文介绍了使用RenderScript压印在机器人的形状的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这问题是关于<基地href=\"http://stackoverflow.com/questions/31562845/emboss-edges-of-a-image-shape-showing-the-depth-in-android/32667714?noredirect=1#comment53181435_32667714\">link.
我尝试了@米沃斯瓦夫-smyk答案。不过,我无法得到它的工作。我不知道是什么createPath(1)表示。我不知道如何创建具有一定的笔画宽度的路径。我们可以做到这一点使用fillpaint。反正下面我已经展示了完整的code.Problem是我没有看到原文链接(见下面的输出图像)显示出任何浮雕效果。请让我知道我做错了。 (我用targetSdkVersion 23和设备是最新的Andr​​oid 4.1.2)

This question is base on link. I tried out @miloslaw-smyk answer. However I could not get it to work. I am not sure what createPath(1) means. I am not sure how to create a path with a certain stroke width. We can do that using the fillpaint. Anyway below I have shown the complete code.Problem is I don't see any emboss effect shown by the original link (see output image below). Please let me know what I have done wrong. (I am using targetSdkVersion 23 and device is on updated 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);
}

在这里输入的形象描述

推荐答案

您可以尝试用我的版本的createPath()?我修改了它稍微吸取更大的问题,并接受笔划宽度作为参数。<​​/ P>

Can you try with my version of createPath()? I modified it slightly to draw larger puzzle and to accept stroke width as an argument.

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);
}

这篇关于使用RenderScript压印在机器人的形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆