OpenGLES使用glReadPixels保存并旋转处理一张Bitmap图片,记录一下

复制代码
1. 必须GLThread线程里调用
fun saveFrame(filename: String, width: Int, height: Int) {
val startTime = System.currentTimeMillis()
//1.glReadPixels返回的是大端的RGBA Byte组数,我们使用小端Buffer接收得到ABGR Byte组数
val buffer: ByteBuffer = ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.LITTLE_ENDIAN)
GLES20.glReadPixels(0, 0, width, height, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buffer)
buffer.rewind()//reset position
val pixelCount = width * height
val colors = IntArray(pixelCount)
buffer.asIntBuffer().get(colors)
for (i in 0 until pixelCount) {
val c = colors[i] //2.每个int类型的c是接收到的ABGR,但bitmap需要ARGB格式,所以需要交换B和R的位置
colors[i] = c and -0xff0100 or (c and 0x00ff0000 shr 16) or (c and 0x000000ff shl 16) //交换B和R,得到ARGB
}
//上下翻转
for (y in 0 until height / 2) {
for (x in 0 until width) {
val temp: Int = colors[(height - y - 1) * width + x]
colors[(height - y - 1) * width + x] = colors[y * width + x]
colors[y * width + x] = temp
}
}
//写入文件
var fos: FileOutputStream? = null
try {
fos = FileOutputStream(filename)
val bmp = Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888)
bmp.compress(Bitmap.CompressFormat.PNG, 90, fos)
bmp.recycle()
} catch (ioe: IOException) {
throw RuntimeException("Failed to write file $filename", ioe)
} finally {
try {
fos?.close()
} catch (ioe2: IOException) {
throw RuntimeException("Failed to close file $filename", ioe2)
}
}
val endTime = System.currentTimeMillis()
Log.d(TAG, "Saved duration:" + (endTime - startTime) + "ms -> " + width + "x" + height + " frame as '" + filename + "'")
}
2.使用方法
glSurfaceView.queueEvent { //run on GLThread
val filename = Environment.getExternalStorageDirectory().absolutePath + "/fbo_${System.currentTimeMillis()}.png"
File(filename).createNewFile()
GLHelper.saveFrame(filename, glSurfaceView.width, glSurfaceView.height)
runOnUiThread {//run on UIThread
Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show()
}
}
复制代码

 

posted @   yongfengnice  阅读(2725)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
历史上的今天:
2017-07-07 ffmpeg格式转换基础知识
点击右上角即可分享
微信分享提示