简体   繁体   English

如何删除 Android 中图像周围的空白区域?

[英]How to remove blank space around an image in Android?

Given an image with alpha channel (transparency) I would like to remove any blank space between the image boundaries and the actual image.给定一个带有 alpha 通道(透明度)的图像,我想删除图像边界和实际图像之间的任何空白区域。 This should be done in a backgound task or with a loading screen, with an acceptable running time to not cripple the user experience.这应该在后台任务或加载屏幕中完成,运行时间可以接受,不会削弱用户体验。

在此处输入图像描述

How can I achieve this result?我怎样才能达到这个结果?

I had difficulties to find best practices or even advices to solve my problem. 我很难找到最佳实践甚至建议来解决我的问题。 Based on this anwer by JannGabriel , who crops the image right and bottom by reducing image size, i managed to make a step further and also remove the top and left blank spaces, and to generally improve elaboration time. 基于JannGabriel的调查 ,他通过减小图像尺寸来调整图像的正确和底部,我设法更进一步,还删除了顶部和左侧的空白区域,并且通常可以改善精细化时间。 The result is good, and i am currently using it in my project. 结果很好,我目前在我的项目中使用它。 I'm fairly new to Android programming and any advice on this method is welcome. 我是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
    );

}

Explanation: For each side of the image, a FOR loop is run to check if pixels does not contains transparent color, returning the first non-transparent pixel useful coordinate. 说明:对于图像的每一侧,运行FOR循环以检查像素是否不包含透明色,返回第一个非透明像素有用坐标。 This is done elaborating coordinates using as a base the opposite dimension than the dimension to trim: to find y, scan x for every y. 这样就完成了使用与修剪尺寸相反的尺寸作为基础的坐标:找到y,扫描每个y的x。

To check where the Vertical-Top blank space ends, it runs the following steps: 要检查Vertical-Top空白区域的结束位置,请执行以下步骤:

  1. Starting is from the top row (y=0) 从第一行开始(y = 0)
  2. Checks all the columns of the row (x from 0 to imageWidth) 检查行的所有列(x从0到imageWidth)
  3. If a non-transparent pixel is found, break the loop and save the y coordinate. 如果找到非透明像素,则断开循环并保存y坐标。 Otherwise continue. 否则继续。
  4. At the ending of the columns, go to the next row (y+1) and start checking columns agains. 在列的结尾处,转到下一行(y + 1)并再次开始检查列。 Break if a non-transparent pixel has already been found. 如果已找到非透明像素,则中断。

Similiar methods are used for the other dimensions, only changing the direction of the scan. 类似的方法用于其他维度,仅改变扫描方向。

Once obtained the 4 coordinates for the first useful pixels of the image, the Bitmap.createBitmap method is invoked, with the original bitmap as a base image, and the useful pixels coordinates as Top-Left and Bottom-Right limits for the resize. 获得图像的第一个有用像素的4个坐标后,将调用Bitmap.createBitmap方法,将原始位图作为基本图像,并将有用像素坐标作为调整大小的左上角和右下角限制。

Note 1: It is useful to note that the coordinates 0, 0 equals to Top-Left . 注1:需要注意的是坐标0,0等于左上角是有用的。

Note 2: The ending width and height in Bitmap.createBitmap are reduced by the new starting relative coordinate, otherwise the new image will have the boundaries wrongly pushed bottom-right. 注意2:Bitmap.createBitmap中的结束宽度和高度减少了新的起始相对坐标,否则新图像将在右下方错误地按下边界。 Figure it like this: you have an image 100x100px, so with ending coordinates 100,100. 像这样:你有一个100x100px的图像,所以结束坐标为100,100。 Changing the starting coordinates to 50,50 will bring the ending coordinates of your elaboration rectangle to 150,150 (100 original coordinate + 50 of modified starting point), pushing it outside the original image boundaries. 将起始坐标更改为50,50将使精化矩形的结束坐标为150,150(100个原始坐标+ 50个修改的起点),将其推到原始图像边界之外。 To avoid this, the new ending coordinate is reduced by the new starting coordinate (100 + 50 new starting coord - 50 new starting coord adjustment) 为了避免这种情况,新的结束坐标减少了新的起始坐标(100 + 50新的起始坐标 - 50个新的起始坐标调整)

Note 3: in the original answer, a check for all the pixels in a given direction is run using the same dimension of the coordinate to find, returning the most advanced useful pixel. 注3:在原始答案中,使用要查找的坐标的相同维度运行给定方向上所有像素的检查,返回最高级的有用像素。 Checking the opposite dimension and stopping at the first useful pixel increased performances. 检查相反的尺寸并停在第一个有用的像素处可以提高性能。

Kotlin implementation for answer @Manzotin with fix small bugs. Kotlin实现回答@Manzotin修复小错误。

fun Bitmap.trimBorders(color: Int): Bitmap {
    var startX = 0
    loop@ for (x in 0 until width) {
        for (y in 0 until height) {
            if (getPixel(x, y) != color) {
                startX = x
                break@loop
            }
        }
    }
    var startY = 0
    loop@ for (y in 0 until height) {
        for (x in 0 until width) {
            if (getPixel(x, y) != color) {
                startY = y
                break@loop
            }
        }
    }
    var endX = width - 1
    loop@ for (x in endX downTo 0) {
        for (y in 0 until height) {
            if (getPixel(x, y) != color) {
                endX = x
                break@loop
            }
        }
    }
    var endY = height - 1
    loop@ for (y in endY downTo 0) {
        for (x in 0 until width) {
            if (getPixel(x, y) != color) {
                endY = y
                break@loop
            }
        }
    }

    val newWidth = endX - startX + 1
    val newHeight = endY - startY + 1

    return Bitmap.createBitmap(this, startX, startY, newWidth, newHeight)
}

You can trim transparent space of around the image using single property of ImageView view.您可以使用 ImageView 视图的单个属性修剪图像周围的透明空间。

You can use android:adjustViewBounds="true" property into XML layout file to trim transparent space of respective image.您可以在 XML 布局文件中使用android:adjustViewBounds="true"属性来修剪相应图像的透明空间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM