Android位图保存无透明区域
Android Bitmap save without transparent area
我想保存没有透明区域的位图
位图具有较大的透明像素。
所以我想删除那个
我该怎么做?
我不会添加图片所以用符号解释。
我不想裁剪功能。
我希望使用过滤器
┌────────────────────────┐
│透明区域
│ ┌──────────┐
│裁剪这个
└──────────┘
└──────────────────────────┘
要找到位图的非透明区域,请在 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);
}
裁剪透明边框github。
public static Bitmap crop(Bitmap bitmap) {
int height = bitmap.getHeight();
int width = bitmap.getWidth();
int[] empty = new int[width];
int[] buffer = new int[width];
Arrays.fill(empty, 0);
int top = 0;
int left = 0;
int bottom = height;
int right = width;
for (int y = 0; y < height; y++) {
bitmap.getPixels(buffer, 0, width, 0, y, width, 1);
if (!Arrays.equals(empty, buffer)) {
top = y;
break;
}
}
for (int y = height - 1; y > top; y--) {
bitmap.getPixels(buffer, 0, width, 0, y, width, 1);
if (!Arrays.equals(empty, buffer)) {
bottom = y;
break;
}
}
empty = new int[height];
buffer = new int[height];
Arrays.fill(empty, 0);
for (int x = 0; x < width; x++) {
bitmap.getPixels(buffer, 0, 1, x, 0, 1, height);
if (!Arrays.equals(empty, buffer)) {
left = x;
break;
}
}
for (int x = width - 1; x > left; x--) {
bitmap.getPixels(buffer, 0, 1, x, 0, 1, height);
if (!Arrays.equals(empty, buffer)) {
right = x;
break;
}
}
return Bitmap.createBitmap(bitmap, left, top, right - left + 1, bottom - top + 1);
}
我 and improved it as a Kotlin extension function. I tweaked it a bit, changed some variable names for better readability and it adds more fixes to the issue mentioned by 抛出 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)
}
按照官方文档:
The new bitmap may be the same object as source, or a copy may have been made.
在使用源位图执行 .recycle()
时应该考虑到。
我想保存没有透明区域的位图
位图具有较大的透明像素。
所以我想删除那个
我该怎么做?
我不会添加图片所以用符号解释。
我不想裁剪功能。 我希望使用过滤器
┌────────────────────────┐
│透明区域
│ ┌──────────┐
│裁剪这个
└──────────┘
└──────────────────────────┘
要找到位图的非透明区域,请在 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);
}
裁剪透明边框github。
public static Bitmap crop(Bitmap bitmap) {
int height = bitmap.getHeight();
int width = bitmap.getWidth();
int[] empty = new int[width];
int[] buffer = new int[width];
Arrays.fill(empty, 0);
int top = 0;
int left = 0;
int bottom = height;
int right = width;
for (int y = 0; y < height; y++) {
bitmap.getPixels(buffer, 0, width, 0, y, width, 1);
if (!Arrays.equals(empty, buffer)) {
top = y;
break;
}
}
for (int y = height - 1; y > top; y--) {
bitmap.getPixels(buffer, 0, width, 0, y, width, 1);
if (!Arrays.equals(empty, buffer)) {
bottom = y;
break;
}
}
empty = new int[height];
buffer = new int[height];
Arrays.fill(empty, 0);
for (int x = 0; x < width; x++) {
bitmap.getPixels(buffer, 0, 1, x, 0, 1, height);
if (!Arrays.equals(empty, buffer)) {
left = x;
break;
}
}
for (int x = width - 1; x > left; x--) {
bitmap.getPixels(buffer, 0, 1, x, 0, 1, height);
if (!Arrays.equals(empty, buffer)) {
right = x;
break;
}
}
return Bitmap.createBitmap(bitmap, left, top, right - left + 1, bottom - top + 1);
}
我
请注意,如公认的答案所建议的,与独立阅读相比,逐行读取像素会提高很多性能。
/**
* 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)
}
按照官方文档:
The new bitmap may be the same object as source, or a copy may have been made.
在使用源位图执行 .recycle()
时应该考虑到。