mirror of
https://github.com/markusfisch/BinaryEye.git
synced 2024-09-19 19:42:18 +02:00
Use only Y (lumo) channel from YUV input
Barcode recognition works on contrast so we don't need color information and can therefore simplify processing of input images.
This commit is contained in:
parent
7578d9b217
commit
cbcc9591ff
@ -7,9 +7,7 @@ import de.markusfisch.android.cameraview.widget.CameraView
|
||||
|
||||
import de.markusfisch.android.binaryeye.activity.MainActivity
|
||||
import de.markusfisch.android.binaryeye.app.addFragment
|
||||
import de.markusfisch.android.binaryeye.rs.Inverter
|
||||
import de.markusfisch.android.binaryeye.rs.Rotator
|
||||
import de.markusfisch.android.binaryeye.rs.YuvToBitmap
|
||||
import de.markusfisch.android.binaryeye.rs.YuvToGray
|
||||
import de.markusfisch.android.binaryeye.widget.LockOnView
|
||||
import de.markusfisch.android.binaryeye.zxing.Zxing
|
||||
import de.markusfisch.android.binaryeye.R
|
||||
@ -46,9 +44,7 @@ class CameraFragment : Fragment() {
|
||||
private lateinit var vibrator: Vibrator
|
||||
private lateinit var cameraView: CameraView
|
||||
private lateinit var lockOnView: LockOnView
|
||||
private lateinit var yuvToBitmap: YuvToBitmap
|
||||
private lateinit var rotator: Rotator
|
||||
private lateinit var inverter: Inverter
|
||||
private lateinit var yuvToGray: YuvToGray
|
||||
|
||||
private var decoding = false
|
||||
private var decodingThread: Thread? = null
|
||||
@ -72,9 +68,7 @@ class CameraFragment : Fragment() {
|
||||
vibrator = activity.getSystemService(
|
||||
Context.VIBRATOR_SERVICE) as Vibrator
|
||||
|
||||
yuvToBitmap = YuvToBitmap(context)
|
||||
rotator = Rotator(context)
|
||||
inverter = Inverter(context)
|
||||
yuvToGray = YuvToGray(context)
|
||||
|
||||
cameraView = (activity as MainActivity).cameraView
|
||||
cameraView.setOnCameraListener(object : CameraView.OnCameraListener {
|
||||
@ -109,9 +103,7 @@ class CameraFragment : Fragment() {
|
||||
|
||||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
yuvToBitmap.destroy()
|
||||
rotator.destroy()
|
||||
inverter.destroy()
|
||||
yuvToGray.destroy()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@ -196,14 +188,8 @@ class CameraFragment : Fragment() {
|
||||
|
||||
private fun decodeFrame(): Result? {
|
||||
frameData ?: return null
|
||||
var bitmap = yuvToBitmap.convert(frameData!!, frameWidth, frameHeight)
|
||||
bitmap = rotator.convert(bitmap, frameOrientation)
|
||||
odd = odd xor true
|
||||
if (odd) {
|
||||
// invert every other frame to also read inverted barcodes
|
||||
bitmap = inverter.convert(bitmap)
|
||||
}
|
||||
return zxing.decodeBitmap(bitmap)
|
||||
return zxing.decodeBitmap(yuvToGray.convert(
|
||||
frameData!!, frameWidth, frameHeight, frameOrientation))
|
||||
}
|
||||
|
||||
private fun found(result: Result) {
|
||||
|
@ -1,41 +0,0 @@
|
||||
package de.markusfisch.android.binaryeye.rs
|
||||
|
||||
import de.markusfisch.android.binaryeye.renderscript.ScriptC_invert
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.support.v8.renderscript.Allocation
|
||||
import android.support.v8.renderscript.RenderScript
|
||||
|
||||
class Inverter(context: Context) {
|
||||
private val rs: RenderScript = RenderScript.create(context)
|
||||
private val inverterScript: ScriptC_invert = ScriptC_invert(rs)
|
||||
|
||||
private var alloc: Allocation? = null
|
||||
private var dest: Bitmap? = null
|
||||
|
||||
fun destroy() {
|
||||
alloc?.destroy()
|
||||
alloc = null
|
||||
dest?.recycle()
|
||||
dest = null
|
||||
inverterScript.destroy()
|
||||
rs.destroy()
|
||||
}
|
||||
|
||||
fun convert(bitmap: Bitmap): Bitmap {
|
||||
if (dest == null) {
|
||||
dest = bitmap.copy(bitmap.getConfig(), true)
|
||||
alloc = Allocation.createFromBitmap(
|
||||
rs,
|
||||
dest,
|
||||
Allocation.MipmapControl.MIPMAP_NONE,
|
||||
Allocation.USAGE_SCRIPT)
|
||||
}
|
||||
|
||||
inverterScript.forEach_invert(alloc, alloc)
|
||||
alloc?.copyTo(dest)
|
||||
|
||||
return dest!!
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package de.markusfisch.android.binaryeye.rs
|
||||
|
||||
import de.markusfisch.android.binaryeye.renderscript.ScriptC_rotator
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.support.v8.renderscript.Allocation
|
||||
import android.support.v8.renderscript.RenderScript
|
||||
|
||||
class Rotator(context: Context) {
|
||||
private val rs: RenderScript = RenderScript.create(context)
|
||||
private val rotatorScript: ScriptC_rotator = ScriptC_rotator(rs)
|
||||
|
||||
private var sourceAlloc: Allocation? = null
|
||||
private var destAlloc: Allocation? = null
|
||||
private var dest: Bitmap? = null
|
||||
|
||||
fun destroy() {
|
||||
sourceAlloc?.destroy()
|
||||
sourceAlloc = null
|
||||
destAlloc?.destroy()
|
||||
destAlloc = null
|
||||
dest?.recycle()
|
||||
dest = null
|
||||
rotatorScript.destroy()
|
||||
rs.destroy()
|
||||
}
|
||||
|
||||
fun convert(bitmap: Bitmap, frameOrientation: Int): Bitmap {
|
||||
var orientation = frameOrientation
|
||||
|
||||
orientation = orientation % 360 / 90
|
||||
if (orientation == 0) {
|
||||
return bitmap
|
||||
}
|
||||
|
||||
if (dest == null) {
|
||||
var width = bitmap.width
|
||||
var height = bitmap.height
|
||||
|
||||
sourceAlloc = Allocation.createFromBitmap(
|
||||
rs,
|
||||
bitmap,
|
||||
Allocation.MipmapControl.MIPMAP_NONE,
|
||||
Allocation.USAGE_SCRIPT)
|
||||
rotatorScript._inImage = sourceAlloc
|
||||
rotatorScript._inWidth = width
|
||||
rotatorScript._inHeight = height
|
||||
|
||||
when (orientation) {
|
||||
1, 3 -> {
|
||||
val tmp = width
|
||||
width = height
|
||||
height = tmp
|
||||
}
|
||||
}
|
||||
|
||||
dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
destAlloc = Allocation.createFromBitmap(
|
||||
rs,
|
||||
dest,
|
||||
Allocation.MipmapControl.MIPMAP_NONE,
|
||||
Allocation.USAGE_SCRIPT)
|
||||
} else {
|
||||
sourceAlloc?.copyFrom(bitmap)
|
||||
}
|
||||
|
||||
when (orientation) {
|
||||
1 -> rotatorScript.forEach_rotate90(destAlloc, destAlloc)
|
||||
2 -> rotatorScript.forEach_rotate180(destAlloc, destAlloc)
|
||||
3 -> rotatorScript.forEach_rotate270(destAlloc, destAlloc)
|
||||
}
|
||||
destAlloc?.copyTo(dest)
|
||||
|
||||
return dest!!
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
package de.markusfisch.android.binaryeye.rs
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.support.v8.renderscript.Allocation
|
||||
import android.support.v8.renderscript.Element
|
||||
import android.support.v8.renderscript.RenderScript
|
||||
import android.support.v8.renderscript.ScriptIntrinsicYuvToRGB
|
||||
import android.support.v8.renderscript.Type
|
||||
|
||||
class YuvToBitmap(context: Context) {
|
||||
private val rs: RenderScript = RenderScript.create(context)
|
||||
|
||||
private var yuvType: Type? = null
|
||||
private var rgbaType: Type? = null
|
||||
private var yuvAllocation: Allocation? = null
|
||||
private var rgbaAllocation: Allocation? = null
|
||||
private var yuvToRgbaScript: ScriptIntrinsicYuvToRGB? = null
|
||||
private var dest: Bitmap? = null
|
||||
|
||||
fun destroy() {
|
||||
yuvToRgbaScript?.destroy()
|
||||
yuvToRgbaScript = null
|
||||
yuvType?.destroy()
|
||||
yuvType = null
|
||||
rgbaType?.destroy()
|
||||
rgbaType = null
|
||||
yuvAllocation?.destroy()
|
||||
yuvAllocation = null
|
||||
rgbaAllocation?.destroy()
|
||||
rgbaAllocation = null
|
||||
dest?.recycle()
|
||||
dest = null
|
||||
rs.destroy()
|
||||
}
|
||||
|
||||
fun convert(data: ByteArray, width: Int, height: Int): Bitmap {
|
||||
if (dest == null) {
|
||||
yuvType = Type.createX(rs, Element.U8(rs), data.size)
|
||||
yuvType?.let {
|
||||
yuvAllocation = Allocation.createTyped(rs, yuvType,
|
||||
Allocation.USAGE_SCRIPT)
|
||||
}
|
||||
|
||||
rgbaType = Type.createXY(rs, Element.RGBA_8888(rs), width, height)
|
||||
rgbaType?.let {
|
||||
rgbaAllocation = Allocation.createTyped(rs, rgbaType)
|
||||
}
|
||||
|
||||
yuvToRgbaScript = ScriptIntrinsicYuvToRGB.create(rs,
|
||||
Element.U8_4(rs))
|
||||
yuvToRgbaScript?.setInput(yuvAllocation)
|
||||
|
||||
dest = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
|
||||
}
|
||||
|
||||
yuvAllocation?.copyFrom(data)
|
||||
yuvToRgbaScript?.forEach(rgbaAllocation)
|
||||
rgbaAllocation?.copyTo(dest)
|
||||
|
||||
return dest!!
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package de.markusfisch.android.binaryeye.rs
|
||||
|
||||
import de.markusfisch.android.binaryeye.renderscript.ScriptC_rotator
|
||||
import de.markusfisch.android.binaryeye.renderscript.ScriptC_yuv2gray
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Bitmap
|
||||
import android.support.v8.renderscript.Allocation
|
||||
import android.support.v8.renderscript.Element
|
||||
import android.support.v8.renderscript.RenderScript
|
||||
import android.support.v8.renderscript.Type
|
||||
|
||||
class YuvToGray(context: Context) {
|
||||
private val rs: RenderScript = RenderScript.create(context)
|
||||
private val rotatorScript: ScriptC_rotator = ScriptC_rotator(rs)
|
||||
private val yuv2grayScript: ScriptC_yuv2gray = ScriptC_yuv2gray(rs)
|
||||
|
||||
private var yuvType: Type? = null
|
||||
private var rgbaType: Type? = null
|
||||
private var yuvAlloc: Allocation? = null
|
||||
private var rgbaAlloc: Allocation? = null
|
||||
private var destAlloc: Allocation? = null
|
||||
private var dest: Bitmap? = null
|
||||
|
||||
fun destroy() {
|
||||
yuvType?.destroy()
|
||||
yuvType = null
|
||||
rgbaType?.destroy()
|
||||
rgbaType = null
|
||||
yuvAlloc?.destroy()
|
||||
yuvAlloc = null
|
||||
rgbaAlloc?.destroy()
|
||||
rgbaAlloc = null
|
||||
destAlloc?.destroy()
|
||||
destAlloc = null
|
||||
dest?.recycle()
|
||||
dest = null
|
||||
rotatorScript.destroy()
|
||||
yuv2grayScript.destroy()
|
||||
rs.destroy()
|
||||
}
|
||||
|
||||
fun convert(
|
||||
data: ByteArray,
|
||||
width: Int,
|
||||
height: Int,
|
||||
orientation: Int): Bitmap {
|
||||
if (dest == null) {
|
||||
yuvType = Type.createXY(rs, Element.U8(rs), width, height * 3 / 2)
|
||||
yuvAlloc = Allocation.createTyped(rs, yuvType,
|
||||
Allocation.USAGE_SCRIPT)
|
||||
rgbaType = Type.createXY(rs, Element.RGBA_8888(rs), width, height)
|
||||
rgbaAlloc = Allocation.createTyped(rs, rgbaType,
|
||||
Allocation.USAGE_SCRIPT)
|
||||
|
||||
var w = width
|
||||
var h = height
|
||||
when (orientation) {
|
||||
90, 270 -> {
|
||||
val tmp = w
|
||||
w = h
|
||||
h = tmp
|
||||
}
|
||||
}
|
||||
|
||||
dest = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
|
||||
destAlloc = Allocation.createFromBitmap(
|
||||
rs,
|
||||
dest,
|
||||
Allocation.MipmapControl.MIPMAP_NONE,
|
||||
Allocation.USAGE_SCRIPT)
|
||||
}
|
||||
|
||||
yuvAlloc?.copyFrom(data)
|
||||
yuv2grayScript._inYUV = yuvAlloc
|
||||
// width/height are uint_32 but Kotlin wants toLong()
|
||||
yuv2grayScript._inWidth = width.toLong()
|
||||
yuv2grayScript._inHeight = height.toLong()
|
||||
yuv2grayScript.forEach_yuv2gray(rgbaAlloc)
|
||||
|
||||
rotatorScript._inImage = rgbaAlloc
|
||||
rotatorScript._inWidth = width
|
||||
rotatorScript._inHeight = height
|
||||
|
||||
when (orientation) {
|
||||
0 -> destAlloc?.copyFrom(rgbaAlloc)
|
||||
90 -> rotatorScript.forEach_rotate90(destAlloc, destAlloc)
|
||||
180 -> rotatorScript.forEach_rotate180(destAlloc, destAlloc)
|
||||
270 -> rotatorScript.forEach_rotate270(destAlloc, destAlloc)
|
||||
}
|
||||
|
||||
destAlloc?.copyTo(dest)
|
||||
|
||||
return dest!!
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#pragma version(1)
|
||||
#pragma rs java_package_name(de.markusfisch.android.binaryeye.renderscript)
|
||||
|
||||
uchar4 RS_KERNEL invert(uchar4 in, uint32_t x, uint32_t y) {
|
||||
uchar4 out = in;
|
||||
out.r = 255 - in.r;
|
||||
out.g = 255 - in.g;
|
||||
out.b = 255 - in.b;
|
||||
return out;
|
||||
}
|
17
app/src/main/rs/yuv2gray.rs
Normal file
17
app/src/main/rs/yuv2gray.rs
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma version(1)
|
||||
#pragma rs java_package_name(de.markusfisch.android.binaryeye.renderscript)
|
||||
#pragma rs_fp_relaxed
|
||||
|
||||
rs_allocation inYUV;
|
||||
uint32_t inWidth;
|
||||
uint32_t inHeight;
|
||||
|
||||
uchar4 RS_KERNEL yuv2gray(uint32_t x, uint32_t y) {
|
||||
uchar Y = rsGetElementAt_uchar(inYUV, x, y);
|
||||
uchar4 out;
|
||||
out.r = Y;
|
||||
out.g = Y;
|
||||
out.b = Y;
|
||||
out.a = 255;
|
||||
return out;
|
||||
}
|
Loading…
Reference in New Issue
Block a user