浮雕图像形状的边缘显示android中的深度

前端之家收集整理的这篇文章主要介绍了浮雕图像形状的边缘显示android中的深度前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想显示3D浮雕外观和感觉,如下图所示.我使用EmbossMaskFilter但无法让它显示效果(请参阅下面的代码).有没有不同的方法来做到这一点?或者我如何使用EmbossMaskFilter.

要求的输出

我的输出

Path path2 = new Path();
public Paint fillPaint = null;
// called in constructor
public void createPath()
{
    //path 2 Big one
    araay = new Point[]{new Point(144,320),new Point(109,200),new Point(171,308),new Point(178,240),172),282),new Point(144,160)};
    AddBeziers(path2,araay,320,144);
    AddLine(path2,216,144 );
    AddLine(path2,216 );
    AddLine(path2,144,320);

     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.setStyle(Paint.Style.FILL);
    paint.setMaskFilter(mEmboss);   
}

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

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

// add curves to the 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 + 2].Y);

    return path;
}

//draw on canvas
@Override
public void onDraw(Canvas canvas) {

    canvas.drawPath(path2,fillPaint);
    super.onDraw(canvas);
}

解决方法

如果您只想进行位图处理(而不是3D或矢量),最好的选择可能是:

>从你的拼图中生成一个模板面具,
>使用Difference of Gaussians来处理它(在本例中我使用了大小为12和2像素的内核),然后标准化并反转结果,
>使用掩模(1.)作为模板通道,将“2”的输出混合到原始图像中.

更新:这里是代码.我试图重用你的变量名,以便更容易理解.代码尽可能使用Renderscript内在函数,以使事情更快,更有趣.

private Paint fillPaint = null;
private Path path2;
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;
private Context ctx;
private int bw = 780;
private int bh = 780;

private void init()
{
    mBitmapIn = loadBitmap(R.drawable.cat7); // background image
    mBitmapPuzzle = Bitmap.createBitmap(bw,bh,Bitmap.Config.ARGB_8888);  // this will hold the puzzle
    Canvas c = new Canvas(mBitmapPuzzle);

    path2 = new Path();
    createPath(5);  // create the path with stroke width of 5 pixels
    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,Bitmap.Config.ARGB_8888);
    c = new Canvas(mBitmapCutter);
    path2 = new Path();
    createPath(1);  // stroke width 1
    c.drawPath(path2,fillPaint);
    mCutterAllocation = Allocation.createFromBitmap(mRS,mBitmapCutter);

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

…为了更好看的结果.我们用它来掩盖背景图像.

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

你好!现在只是Renderscript设置代码.

private void createScript() {
    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));
}

最后onDraw():

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

TODO:检查其他中风杆是否会给出更舒适的角落.

猜你在找的Android相关文章