BlackRoot
BlackRoot

Reputation: 516

How to Smooth corner for image in android [Algorithm not using Path ...etc]

I'm asking about how do apply Xiaolin algorithm to have a smooth corner for image in android I've wrote a algorithm that iterate over the pixels and determine wither this pixel should removed or not to have an corner for image also removing pixel by making it transparent 255 for alpha value but the corner isn't smooth and I'm reading about Xiaolin algorithm for smooth line but because I'm in intermediate java programmer I don't know how to apply this algorithm >>> can any one help me on how to apply this algorithm or suggest another algorithm and how to use it this is my code

int radius = Integer.parseInt(((EditText)MainActivity.this.findViewById(R.id.editTextRadius)).getText().toString());
    int xCenter ;
    int yCenter;
    Bitmap mutableBitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.h); 
    Bitmap drawaBitmap = mutableBitmap.copy(Bitmap.Config.ARGB_4444, true);


    for (int i = 0; i < radius; i++) {
        xCenter = radius;
        yCenter = radius;
        for (int j = 0; j < radius; j++) {
            if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

                    drawaBitmap.setPixel(i, j,
                            Color.argb(255, 255, 255, 255));
            }

        }
        xCenter = radius;
        yCenter =  drawaBitmap.getHeight()-radius;
        for (int j = drawaBitmap.getHeight()-1; j > drawaBitmap.getHeight()-radius; j--) {
            if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

                    drawaBitmap.setPixel(i, j,
                            Color.argb(255, 255, 255, 255));
            }

        }
    }
    for (int i = drawaBitmap.getWidth()-1; i > drawaBitmap.getWidth()-radius; i--) {
        xCenter = drawaBitmap.getWidth() - radius;
        yCenter =  radius;
        for (int j = 0; j < radius; j++) {
            if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2)) {

                    drawaBitmap.setPixel(i, j,
                            Color.argb(255, 255, 255, 255));
            }

        }
        xCenter = drawaBitmap.getWidth()-radius;
        yCenter =  drawaBitmap.getHeight()-radius;
        for (int j = drawaBitmap.getHeight()-1; j > drawaBitmap.getHeight()-radius; j--) {
            if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

                    drawaBitmap.setPixel(i, j,
                            Color.argb(255, 255, 255, 255));
            }

        }
    }
    ((ImageView)this.findViewById(R.id.image)).setImageBitmap(drawaBitmap);

thanks in advance

Upvotes: 0

Views: 1728

Answers (2)

pskink
pskink

Reputation: 24730

this is a bas stuff to start with:

int radius = 10;
Bitmap b = Bitmap.createBitmap(radius, radius, Config.ARGB_8888);
Bitmap mask = Bitmap.createBitmap(2 * radius, 2 * radius, Config.ARGB_8888);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
Canvas c;

// create mask
p.setColor(0xff000000);
c = new Canvas(mask);
c.drawCircle(radius, radius, radius, p);

// draw something on the original bitmap
// skip it if you have original bitmap drawn
c = new Canvas(b);
LinearGradient lg = new LinearGradient(0, 0, radius, radius, 0xffff0000, 0xff00ff00, TileMode.CLAMP);
p.setShader(lg);
c.drawRect(0, 0, radius, radius, p);
// end of skip

for (int x = 0; x < radius; x++) {
    for (int y = 0; y < radius; y++) {
        int maskPixel = mask.getPixel(x, y);
        if ((maskPixel & 0xff000000) != 0xff000000) {
            int bPixel = b.getPixel(x, y);
            bPixel &= 0xffffff;
            bPixel |= (maskPixel & 0xff000000);
            b.setPixel(x, y, bPixel);
        }
    }
}

try {
    OutputStream stream;
    stream = new FileOutputStream("/sdcard/image.png");
    b.compress(CompressFormat.PNG, 100, stream);
    stream = new FileOutputStream("/sdcard/mask.png");
    mask.compress(CompressFormat.PNG, 100, stream);
} catch (FileNotFoundException e) {
    e.printStackTrace();
}

Upvotes: 0

Vikram
Vikram

Reputation: 51571

So, I gave your code a try and its working fine for me. I did add the changes I suggested to you. Here's the xml for ImageView:

<ImageView
    android:id="@+id/imageView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layerType="hardware"/>

The reason why you are seeing black instead of transparent pixels could be because the layerType is not set. Corrected code:

// hardcoded this value for testing purposes
int radius = 120;
int xCenter;
int yCenter;
Bitmap mutableBitmap = BitmapFactory.decodeResource(
                                  this.getResources(), R.drawable.h); 

// ARGB_8888 // ARGB_4444 has been deprecated
Bitmap drawaBitmap = mutableBitmap.copy(Bitmap.Config.ARGB_8888, true);

for (int i = 0; i < radius; i++) {
    xCenter = radius;
    yCenter = radius;

    for (int j = 0; j < radius; j++) {
    if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

            drawaBitmap.setPixel(i, j,
                            Color.argb(0, 0, 0, 0));
        }

    }

    xCenter = radius;
    yCenter =  drawaBitmap.getHeight()-radius;

    for (int j = drawaBitmap.getHeight()-1; j > drawaBitmap.getHeight()-radius; j--) {

        if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

            drawaBitmap.setPixel(i, j,
                            Color.argb(0, 0, 0, 0));
        }

    }
}
for (int i = drawaBitmap.getWidth()-1; i > drawaBitmap.getWidth()-radius; i--) {
    xCenter = drawaBitmap.getWidth() - radius;
    yCenter =  radius;

    for (int j = 0; j < radius; j++) {
        if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2)) {

        drawaBitmap.setPixel(i, j,
                            Color.argb(0, 0, 0, 0));
    }

}

xCenter = drawaBitmap.getWidth()-radius;
yCenter =  drawaBitmap.getHeight()-radius;

for (int j = drawaBitmap.getHeight()-1; j > drawaBitmap.getHeight()-radius; j--) {
    if (Math.pow(i - xCenter , 2) + Math.pow(j - yCenter , 2) > Math.pow(radius, 2) ) {

        drawaBitmap.setPixel(i, j,
                            Color.argb(0, 0, 0, 0));


    }

}

}

((ImageView) findViewById(R.id.image)).
    setBackgroundColor(getResources().getColor(android.R.color.transparent));

((ImageView) findViewById(R.id.imageView1)).setImageBitmap(drawaBitmap);

By the way, you can also use Color.TRANSPARENT in place of Color.argb(0, 0, 0, 0).

Result: Original & Processed

enter image description here

Upvotes: 1

Related Questions