2015-09-26 175 views
8

给定带有alpha通道(透明度)的图像我想删除图像边界和实际图像之间的空白区域。 这应该在背景任务或加载屏幕中完成,并且具有可接受的运行时间以不削弱用户体验。如何删除Android中图像的空白区域?

enter image description here

我怎样才能实现这个结果?

回答

17

我很难找到最佳实践或甚至建议来解决我的问题。基于this anwer by JannGabriel,他们通过缩小图像大小来裁剪图像的右下角,我设法进一步去除了顶部和左侧的空白区域,并且通常可以缩短加工时间。结果很好,我目前在我的项目中使用它。 我对Android编程相当陌生,欢迎对此方法提出任何建议。

public static Bitmap TrimBitmap(Bitmap bmp) { 
    int imgHeight = bmp.getHeight(); 
    int imgWidth = bmp.getWidth(); 


    //TRIM WIDTH - LEFT 
    int startWidth = 0; 
    for(int x = 0; x < imgWidth; x++) { 
     if (startWidth == 0) { 
      for (int y = 0; y < imgHeight; y++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        startWidth = x; 
        break; 
       } 
      } 
     } else break; 
    } 


    //TRIM WIDTH - RIGHT 
    int endWidth = 0; 
    for(int x = imgWidth - 1; x >= 0; x--) { 
     if (endWidth == 0) { 
      for (int y = 0; y < imgHeight; y++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        endWidth = x; 
        break; 
       } 
      } 
     } else break; 
    } 



    //TRIM HEIGHT - TOP 
    int startHeight = 0; 
    for(int y = 0; y < imgHeight; y++) { 
     if (startHeight == 0) { 
      for (int x = 0; x < imgWidth; x++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        startHeight = y; 
        break; 
       } 
      } 
     } else break; 
    } 



    //TRIM HEIGHT - BOTTOM 
    int endHeight = 0; 
    for(int y = imgHeight - 1; y >= 0; y--) { 
     if (endHeight == 0) { 
      for (int x = 0; x < imgWidth; x++) { 
       if (bmp.getPixel(x, y) != Color.TRANSPARENT) { 
        endHeight = y; 
        break; 
       } 
      } 
     } else break; 
    } 


    return Bitmap.createBitmap(
      bmp, 
      startWidth, 
      startHeight, 
      endWidth - startWidth, 
      endHeight - startHeight 
    ); 

} 

说明: 对于图像的每一侧,一个FOR循环运行,以检查是否像素不包含透明的颜色,返回第一非透明像素有用坐标。这是通过使用作为基础的坐标来完成的,该坐标与要修剪的维度相反:找到y,为每个y扫描x。

要检查其中的垂直顶部空格结束,它运行下列步骤:

  1. 起动是从顶行(Y = 0)
  2. 检查所有的行的列(X从0到图像宽度)
  3. 如果找到不透明的像素,请打破循环并保存y坐标。否则继续。
  4. 在列的结尾处,转到下一行(y + 1)并开始检查列重复。如果已经找到一个不透明的像素,请打破它。

对其他维度使用了类似的方法,只是改变了扫描的方向。

一旦获得图像第一个有用像素的4个坐标,将调用Bitmap.createBitmap方法,将原始位图作为基准图像,并将有用像素坐标调整为调整大小的左上角和右下角限制。

注意1:有用的是要注意坐标0,0等于左上角。注意2:Bitmap.createBitmap中的结束宽度和高度被新的起始相对坐标减少,否则新图像将错误地向右下方推动边界。像这样:你有一个图像100x100px,所以结束坐标100,100。将开始坐标更改为50,50将使精化矩形的结束坐标达到150,150(100原始坐标+修改后的起始点的50),将其推到原始图像边界之外。为了避免这种情况,新的结束坐标由新的起始坐标减少(100 + 50新起始坐标 - 50个新起始坐标调整)

注意3:在原始答案中,检查给定的所有像素方向使用坐标的相同尺寸进行查找,返回最先进的有用像素。检查相反的尺寸并停止在第一个有用像素处增加性能。

+1

您的示例代码将修剪至少一个像素,即使图像没有透明列或行。最好使用'http:// stackoverflow.com/a/886979/1043882'中描述的方式,而不是'if(startWidth == 0)'和其他类似的语句。 – hasanghaforian

+0

'startWidth'和'startHeight'最初不应设置为0,因为如果您的图像顶部和左侧没有空白空间,则for循环将运行至结束。所以你会浪费等于'2 *宽*高'的计算时间。我认为将它们设置为“-1”更好。 – Ruslan