Android位图不带透明区域保存

Android位图不带透明区域保存,android,bitmap,crop,Android,Bitmap,Crop,我想保存没有透明区域的位图 位图具有较大的透明像素 所以我想把它去掉 我该怎么做 我不能添加图片,所以用符号解释 我不想裁剪函数。 我希望使用过滤器 ┌────────────────────────┐ │ 透明区 │ ┌────────┐ │ 裁剪此 └────────┘ └────────────────────────┘ 要查找位图的非透明区域,请在位图的x和y方向上迭代,并找到非透明区域的最小值和最大值。然后将位图裁剪到这些坐标 Bitmap CropBitmapTransp

我想保存没有透明区域的位图

位图具有较大的透明像素

所以我想把它去掉

我该怎么做

我不能添加图片,所以用符号解释

我不想裁剪函数。 我希望使用过滤器

┌────────────────────────┐

│ 透明区

│ ┌────────┐

│ 裁剪此
└────────┘

└────────────────────────┘

要查找位图的非透明区域,请在位图的x和y方向上迭代,并找到非透明区域的最小值和最大值。然后将位图裁剪到这些坐标

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);
}
位图CropBitmapTransparency(位图源位图)
{
int minX=sourceBitmap.getWidth();
int minY=sourceBitmap.getHeight();
int maxX=-1;
int maxY=-1;
对于(int y=0;y>24)和255;
如果(alpha>0)//像素不是100%透明的
{
if(xmaxX)
maxX=x;
if(ymaxY)
maxY=y;
}
}
}
if((maxX
使用此选项裁剪透明边框

公共静态位图裁剪(位图){
int height=bitmap.getHeight();
int width=bitmap.getWidth();
int[]空=新int[宽度];
int[]缓冲区=新的int[宽度];
数组。填充(空,0);
int-top=0;
int左=0;
内底=高度;
int right=宽度;
对于(int y=0;y顶部;y--){
getPixels(缓冲区,0,宽度,0,y,宽度,1);
如果(!array.equals(空,缓冲区)){
底部=y;
打破
}
}
空=新整数[高度];
缓冲区=新整数[高度];
数组。填充(空,0);
对于(int x=0;xleft;x--){
getPixels(缓冲区,0,1,x,0,1,高度);
如果(!array.equals(空,缓冲区)){
右=x;
打破
}
}
返回Bitmap.createBitmap(位图,左,上,右-左+1,下-上+1);
}
我将其作为Kotlin扩展函数进行了改进。我对它进行了一些调整,更改了一些变量名以提高可读性,并为所提到的引发IllegalArgumentException的问题添加了更多修复

请注意,按照公认的答案,逐行读取像素可以大大提高独立读取像素的性能

/**
 * Trims a bitmap borders of a given color.
 *
 */
fun Bitmap.trim(@ColorInt color: Int = Color.TRANSPARENT): Bitmap {

    var top = height
    var bottom = 0
    var right = width
    var left = 0

    var colored = IntArray(width, { color })
    var buffer = IntArray(width)

    for (y in bottom until top) {
        getPixels(buffer, 0, width, 0, y, width, 1)
        if (!Arrays.equals(colored, buffer)) {
            bottom = y
            break
        }
    }

    for (y in top - 1 downTo bottom) {
        getPixels(buffer, 0, width, 0, y, width, 1)
        if (!Arrays.equals(colored, buffer)) {
            top = y
            break
        }
    }

    val heightRemaining = top - bottom
    colored = IntArray(heightRemaining, { color })
    buffer = IntArray(heightRemaining)

    for (x in left until right) {
        getPixels(buffer, 0, 1, x, bottom, 1, heightRemaining)
        if (!Arrays.equals(colored, buffer)) {
            left = x
            break
        }
    }

    for (x in right - 1 downTo left) {
        getPixels(buffer, 0, 1, x, bottom, 1, heightRemaining)
        if (!Arrays.equals(colored, buffer)) {
            right = x
            break
        }
    }
    return Bitmap.createBitmap(this, left, bottom, right - left, top - bottom)
}

在官方文件之后:

新位图可能是与源相同的对象,或者可能已经制作了副本


在使用源位图执行
.recycle()
时,您应该考虑到这一点。

您想用颜色填充透明区域吗?不,我想使用过滤器裁剪没有透明区域的位图。请尝试以下回答:非常好,亲爱的!最近几天才发现这件事!再次感谢你!这真的很棒。但执行起来需要一段时间。这是完成此任务的最快方法吗?@nitech如果在位图上调用getPixels()或copyPixelsToBuffer(),则可以遍历像素数据,而不必为每个像素调用getPixel()。这应该会加快速度,但会使事情复杂化,因为你必须考虑步幅,自己做像素索引。使用本机代码可能会更快,但似乎不必要的复杂。谢谢。我会对速度做更多的研究。@nitech更改算法也会加快速度。因为它做了很多不必要的检查。例如,您可以从顶部向下扫描,然后从底部向上扫描以找到最小值和最大值y,然后在剩余区域中扫描每行,但在每行中仅检查小于当前最小值x且大于当前最大值x的区域以计算最小值和最大值x。但是,读取内存的顺序可能会影响性能。您是否可以在此处添加代码片段,以便其他人不必访问github repo?完成;)@MartinGottweis。此代码不读取所有像素,只对垂直和水平矩阵进行切片,因此在我的测试中速度更快。在这一行上崩溃。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。位图.getPixels(缓冲区,0,1,x,top+1,1,bufferSize);////java.lang.IllegalArgumentException:y+高度必须为
/**
 * Trims a bitmap borders of a given color.
 *
 */
fun Bitmap.trim(@ColorInt color: Int = Color.TRANSPARENT): Bitmap {

    var top = height
    var bottom = 0
    var right = width
    var left = 0

    var colored = IntArray(width, { color })
    var buffer = IntArray(width)

    for (y in bottom until top) {
        getPixels(buffer, 0, width, 0, y, width, 1)
        if (!Arrays.equals(colored, buffer)) {
            bottom = y
            break
        }
    }

    for (y in top - 1 downTo bottom) {
        getPixels(buffer, 0, width, 0, y, width, 1)
        if (!Arrays.equals(colored, buffer)) {
            top = y
            break
        }
    }

    val heightRemaining = top - bottom
    colored = IntArray(heightRemaining, { color })
    buffer = IntArray(heightRemaining)

    for (x in left until right) {
        getPixels(buffer, 0, 1, x, bottom, 1, heightRemaining)
        if (!Arrays.equals(colored, buffer)) {
            left = x
            break
        }
    }

    for (x in right - 1 downTo left) {
        getPixels(buffer, 0, 1, x, bottom, 1, heightRemaining)
        if (!Arrays.equals(colored, buffer)) {
            right = x
            break
        }
    }
    return Bitmap.createBitmap(this, left, bottom, right - left, top - bottom)
}