在 Android 中将位图转换为灰度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3373860/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert a Bitmap to GrayScale in Android
提问by leparlon
I am new to this site, and I come with a question about Android.
我是这个网站的新手,我有一个关于 Android 的问题。
Is there any way to convert a Bitmap to grayscale? I know how to draw a grayscale bitmap (using canvas operations: http://www.mail-archive.com/[email protected]/msg38890.html) but I really need The actual bitmap in gray colors (or at least something that could be converted to a bitmap later on). Do I have to implement it by hand (pixel by pixel operations)?
有没有办法将位图转换为灰度?我知道如何绘制灰度位图(使用画布操作:http: //www.mail-archive.com/[email protected]/msg38890.html)但我真的需要灰色的实际位图(或在至少可以稍后转换为位图的东西)。我是否必须手动实现它(逐像素操作)?
I've searched a lot, and still could not find. Anyone knows a easy/efficient way to do it?
我已经搜索了很多,仍然找不到。任何人都知道一种简单/有效的方法吗?
Thanks a lot!
非常感谢!
采纳答案by EboMike
Isn't that exactly what the code you're linking to does? It takes a color bitmap ("bmp"), creates a duplicate bitmap ("bm"), and then draws the color bitmap into "bm" using the filter to turn it into grayscale. From that point on, you can use "bm" as an actual grayscale bitmap and do whatever you want to do with it.
这不正是您链接到的代码所做的吗?它需要一个颜色位图(“bmp”),创建一个重复的位图(“bm”),然后使用过滤器将颜色位图绘制到“bm”中,将其转换为灰度。从那时起,您可以使用“bm”作为实际的灰度位图,并使用它做任何您想做的事情。
You'd need to tweak the sample a bit (it's using hard-coded sizes, you may want to just clone the size of the original bitmap), but other than that, this seems to be as ready-to-use as it gets, depending on what you want.
您需要稍微调整样本(它使用硬编码大小,您可能只想克隆原始位图的大小),但除此之外,这似乎是随时可用的,取决于你想要什么。
回答by leparlon
OH, yes, it does. I was using it wrong, thanks for pointing it out to me. (Sorry for the useless question) Here is the end code (heavily based on the one linked) since it may help someone:
哦,是的,确实如此。我用错了,谢谢你给我指出来。(抱歉没用的问题)这是最终代码(主要基于链接的代码),因为它可能对某人有所帮助:
public Bitmap toGrayscale(Bitmap bmpOriginal)
{
int width, height;
height = bmpOriginal.getHeight();
width = bmpOriginal.getWidth();
Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bmpGrayscale);
Paint paint = new Paint();
ColorMatrix cm = new ColorMatrix();
cm.setSaturation(0);
ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
paint.setColorFilter(f);
c.drawBitmap(bmpOriginal, 0, 0, paint);
return bmpGrayscale;
}
Any remarks or comments on it are very welcome.
非常欢迎任何评论或评论。
Thanks
谢谢
回答by E Player Plus
If you are going to show that Bitmap on ImageView
. Then Instead of converting Bitmap to Gray Scale, you can try below code:
如果您要在ImageView
. 然后,您可以尝试以下代码,而不是将位图转换为灰度:
ColorMatrix matrix = new ColorMatrix();
matrix.setSaturation(0);
ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrix);
imageview.setColorFilter(filter);
回答by Code-Monkey
I'd like to mention that with this approach one important aspect must be taken in account. BitMap's on Android are stored in the NativeHeap. By just "creating bitmaps", you'll eventually clog the memory, getting an OutOfMemoryException
(OOM).
我想提一下,使用这种方法必须考虑一个重要方面。Android 上的 BitMap 存储在 NativeHeap 中。仅仅通过“创建位图”,你最终会阻塞内存,得到一个OutOfMemoryException
(OOM)。
Therefor, the bitmap must always be .recycled()
.
因此,位图必须始终为.recycled()
.
回答by android developer
Here's a more efficient way, which I've made to support all versions of Android:
这是一种更有效的方法,我已经用它来支持所有版本的 Android:
// https://xjaphx.wordpress.com/2011/06/21/image-processing-grayscale-image-on-the-fly/
@JvmStatic
fun getGrayscaledBitmapFallback(src: Bitmap, redVal: Float = 0.299f, greenVal: Float = 0.587f, blueVal: Float = 0.114f): Bitmap {
// create output bitmap
val bmOut = Bitmap.createBitmap(src.width, src.height, src.config)
// pixel information
var A: Int
var R: Int
var G: Int
var B: Int
var pixel: Int
// get image size
val width = src.width
val height = src.height
// scan through every single pixel
for (x in 0 until width) {
for (y in 0 until height) {
// get one pixel color
pixel = src.getPixel(x, y)
// retrieve color of all channels
A = Color.alpha(pixel)
R = Color.red(pixel)
G = Color.green(pixel)
B = Color.blue(pixel)
// take conversion up to one single value
B = (redVal * R + greenVal * G + blueVal * B).toInt()
G = B
R = G
// set new pixel color to output bitmap
bmOut.setPixel(x, y, Color.argb(A, R, G, B))
}
}
// return final image
return bmOut
}
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@JvmStatic
fun getGrayscaledBitmap(context: Context, src: Bitmap): Bitmap {
// https://gist.github.com/imminent/cf4ab750104aa286fa08
// https://en.wikipedia.org/wiki/Grayscale
val redVal = 0.299f
val greenVal = 0.587f
val blueVal = 0.114f
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1)
return getGrayscaledBitmapFallback(src, redVal, greenVal, blueVal)
val render = RenderScript.create(context)
val matrix = Matrix4f(floatArrayOf(-redVal, -redVal, -redVal, 1.0f, -greenVal, -greenVal, -greenVal, 1.0f, -blueVal, -blueVal, -blueVal, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f))
val result = src.copy(src.config, true)
val input = Allocation.createFromBitmap(render, src, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT)
val output = Allocation.createTyped(render, input.type)
// Inverts and do grayscale to the image
@Suppress("DEPRECATION")
val inverter =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
ScriptIntrinsicColorMatrix.create(render)
else
ScriptIntrinsicColorMatrix.create(render, Element.U8_4(render))
inverter.setColorMatrix(matrix)
inverter.forEach(input, output)
output.copyTo(result)
src.recycle()
render.destroy()
return result
}