Reputation: 3911
I have a set of bitmaps. They are all transparent to some extent, and I don't know in advance which parts are transparent. I would like to create a new bitmap out of the original bitmap that excludes the transparent parts, but in a square. I think this image explains it:
I know how to create a bitmap out of a existing bitmap, but I don't know how to find out which part is transparent and how to use that to achieve my goal.
This is how I plan on doing this:
public Bitmap cutImage(Bitmap image) {
Bitmap newBitmap = null;
int width = image.getWidth();
int height = image.getHeight();
newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newBitmap);
//This is where I need to find out correct values of r1 and r1.
Rect r1 = new Rect(?, ?, ?, ?);
Rect r2 = new Rect(?, ?, ?, ?);
canvas.drawBitmap(image, r1, r2, null);
return newBitmap;
}
Does anyone know how to achieve this?
EDIT:
I got it work using the following algorithm to find left, right, top and bottom values:
private int x1;
private int x2;
private int y1;
private int y2;
private void findRectValues(Bitmap image)
{
for(int x = 0; x < image.getWidth(); x++)
{
for(int y = 0; y < image.getHeight(); y++)
{
if(image.getPixel(x, y) != Color.TRANSPARENT)
{
System.out.println("X1 is: " + x);
x1 = x;
break;
}
}
if(x1 != 0)
break;
}
for(int x = image.getWidth()-1; x > 0; x--)
{
for(int y = 0; y < image.getHeight(); y++)
{
if(image.getPixel(x, y) != Color.TRANSPARENT)
{
System.out.println("X2 is: " + x);
x2 = x;
break;
}
}
if(x2 != 0)
break;
}
for(int y = 0; y < image.getHeight(); y++)
{
for(int x = 0; x < image.getWidth(); x++)
{
if(image.getPixel(x, y) != Color.TRANSPARENT)
{
System.out.println("Y1 is: " + y);
y1 = y;
break;
}
}
if(y1 != 0)
break;
}
for(int y = image.getHeight()-1; y > 0; y--)
{
for(int x = 0; x < image.getWidth(); x++)
{
if(image.getPixel(x, y) != Color.TRANSPARENT)
{
System.out.println("Y2 is: " + y);
y2 = y;
break;
}
}
if(y2 != 0)
break;
}
}
Upvotes: 8
Views: 2673
Reputation: 1722
To find the non-transparent area of your bitmap, iterate across the bitmap in x and y and find the min and max of the non-transparent region. Then crop the bitmap to those co-ordinates.
Bitmap CropBitmapTransparency(Bitmap sourceBitmap)
{
int minX = sourceBitmap.getWidth();
int minY = sourceBitmap.getHeight();
int maxX = -1;
int maxY = -1;
for(int y = 0; y < sourceBitmap.getHeight(); y++)
{
for(int x = 0; x < sourceBitmap.getWidth(); x++)
{
int alpha = (sourceBitmap.getPixel(x, y) >> 24) & 255;
if(alpha > 0) // pixel is not 100% transparent
{
if(x < minX)
minX = x;
if(x > maxX)
maxX = x;
if(y < minY)
minY = y;
if(y > maxY)
maxY = y;
}
}
}
if((maxX < minX) || (maxY < minY))
return null; // Bitmap is entirely transparent
// crop bitmap to non-transparent area and return:
return Bitmap.createBitmap(sourceBitmap, minX, minY, (maxX - minX) + 1, (maxY - minY) + 1);
}
Upvotes: 0
Reputation: 71
i think this is a bit more efficient and it works great for me
public Bitmap cropBitmapToBoundingBox(Bitmap picToCrop, int unusedSpaceColor) {
int[] pixels = new int[picToCrop.getHeight() * picToCrop.getWidth()];
int marginTop = 0, marginBottom = 0, marginLeft = 0, marginRight = 0, i;
picToCrop.getPixels(pixels, 0, picToCrop.getWidth(), 0, 0,
picToCrop.getWidth(), picToCrop.getHeight());
for (i = 0; i < pixels.length; i++) {
if (pixels[i] != unusedSpaceColor) {
marginTop = i / picToCrop.getWidth();
break;
}
}
outerLoop1: for (i = 0; i < picToCrop.getWidth(); i++) {
for (int j = i; j < pixels.length; j += picToCrop.getWidth()) {
if (pixels[j] != unusedSpaceColor) {
marginLeft = j % picToCrop.getWidth();
break outerLoop1;
}
}
}
for (i = pixels.length - 1; i >= 0; i--) {
if (pixels[i] != unusedSpaceColor) {
marginBottom = (pixels.length - i) / picToCrop.getWidth();
break;
}
}
outerLoop2: for (i = pixels.length - 1; i >= 0; i--) {
for (int j = i; j >= 0; j -= picToCrop.getWidth()) {
if (pixels[j] != unusedSpaceColor) {
marginRight = picToCrop.getWidth()
- (j % picToCrop.getWidth());
break outerLoop2;
}
}
}
return Bitmap.createBitmap(picToCrop, marginLeft, marginTop,
picToCrop.getWidth() - marginLeft - marginRight,
picToCrop.getHeight() - marginTop - marginBottom);
}
Upvotes: 6
Reputation: 11567
If all the images you want to crop are more or less in the center of the original canvas, I guess you could so something like this:
Now, the question remains is what you consider a transparent pixel. Does alpha trasparency counts? if so, how much alpha until you decide it's transparent enough to be cut from the image?
Upvotes: 5