mirror of
https://github.com/markusfisch/BinaryEye.git
synced 2024-09-20 03:52:16 +02:00
Route raw YUV data to ZXing
And don't convert it into a Bitmap just to read the pixels back from it.
This commit is contained in:
parent
05a206384c
commit
64e1d722d5
@ -362,15 +362,18 @@ class CameraActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun decodeFrame(): Result? {
|
||||
val dat = frameData
|
||||
dat ?: return null
|
||||
return zxing.decodeBitmap(
|
||||
preprocessor.convert(
|
||||
dat,
|
||||
frameWidth,
|
||||
frameHeight,
|
||||
frameOrientation
|
||||
)
|
||||
val yuvData = frameData
|
||||
yuvData ?: return null
|
||||
preprocessor.convert(
|
||||
yuvData,
|
||||
frameWidth,
|
||||
frameHeight,
|
||||
frameOrientation
|
||||
)
|
||||
return zxing.decode(
|
||||
yuvData,
|
||||
frameWidth,
|
||||
frameHeight
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
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
|
||||
@ -13,31 +11,23 @@ import android.support.v8.renderscript.Type
|
||||
class Preprocessor(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 destType: Type? = null
|
||||
private var destAlloc: Allocation? = null
|
||||
private var dest: Bitmap? = null
|
||||
private var odd = true
|
||||
|
||||
fun destroy() {
|
||||
yuvType?.destroy()
|
||||
yuvType = null
|
||||
rgbaType?.destroy()
|
||||
rgbaType = null
|
||||
yuvAlloc?.destroy()
|
||||
yuvAlloc = null
|
||||
rgbaAlloc?.destroy()
|
||||
rgbaAlloc = null
|
||||
destType?.destroy()
|
||||
destType = null
|
||||
yuvAlloc?.destroy()
|
||||
destAlloc?.destroy()
|
||||
destAlloc = null
|
||||
dest?.recycle()
|
||||
dest = null
|
||||
rotatorScript.destroy()
|
||||
yuv2grayScript.destroy()
|
||||
rs.destroy()
|
||||
}
|
||||
|
||||
@ -46,67 +36,56 @@ class Preprocessor(context: Context) {
|
||||
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
|
||||
) {
|
||||
if (orientation == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
if (yuvAlloc == null) {
|
||||
yuvType = Type.createXY(
|
||||
rs,
|
||||
Element.U8(rs),
|
||||
width,
|
||||
height * 3 / 2
|
||||
)
|
||||
rgbaType = Type.createXY(rs, Element.RGBA_8888(rs), width, height)
|
||||
rgbaAlloc = Allocation.createTyped(
|
||||
rs, rgbaType,
|
||||
yuvAlloc = Allocation.createTyped(
|
||||
rs,
|
||||
yuvType,
|
||||
Allocation.USAGE_SCRIPT
|
||||
)
|
||||
|
||||
var w = width
|
||||
var h = height
|
||||
when (orientation) {
|
||||
90, 270 -> {
|
||||
val tmp = w
|
||||
w = h
|
||||
h = tmp
|
||||
}
|
||||
if (orientation == 90 || orientation == 270) {
|
||||
val tmp = w
|
||||
w = h
|
||||
h = tmp
|
||||
}
|
||||
|
||||
dest = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
|
||||
destAlloc = Allocation.createFromBitmap(
|
||||
destType = Type.createXY(
|
||||
rs,
|
||||
dest,
|
||||
Allocation.MipmapControl.MIPMAP_NONE,
|
||||
Element.U8(rs),
|
||||
w,
|
||||
h
|
||||
)
|
||||
destAlloc = Allocation.createTyped(
|
||||
rs,
|
||||
destType,
|
||||
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()
|
||||
|
||||
// invert every second frame to also read inverted barcodes
|
||||
if (odd) {
|
||||
yuv2grayScript.forEach_yuv2gray(rgbaAlloc)
|
||||
} else {
|
||||
yuv2grayScript.forEach_yuv2inverted(rgbaAlloc)
|
||||
}
|
||||
odd = odd xor true
|
||||
|
||||
rotatorScript._inImage = rgbaAlloc
|
||||
rotatorScript._inImage = yuvAlloc
|
||||
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)
|
||||
|
||||
// since Bitmap.createBitmap() can't return null,
|
||||
// dest cannot be null here either
|
||||
return dest!!
|
||||
destAlloc?.copyTo(data)
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ import com.google.zxing.DecodeHintType
|
||||
import com.google.zxing.LuminanceSource
|
||||
import com.google.zxing.MultiFormatReader
|
||||
import com.google.zxing.MultiFormatWriter
|
||||
import com.google.zxing.PlanarYUVLuminanceSource
|
||||
import com.google.zxing.ReaderException
|
||||
import com.google.zxing.Result
|
||||
import com.google.zxing.RGBLuminanceSource
|
||||
import com.google.zxing.common.HybridBinarizer
|
||||
|
||||
import android.graphics.Bitmap
|
||||
@ -20,6 +20,8 @@ import java.util.EnumSet
|
||||
class Zxing {
|
||||
private val multiFormatReader: MultiFormatReader = MultiFormatReader()
|
||||
|
||||
private var odd = false
|
||||
|
||||
init {
|
||||
val decodeFormats = EnumSet.noneOf<BarcodeFormat>(
|
||||
BarcodeFormat::class.java
|
||||
@ -54,16 +56,32 @@ class Zxing {
|
||||
multiFormatReader.setHints(hints)
|
||||
}
|
||||
|
||||
fun decodeBitmap(bitmap: Bitmap): Result? {
|
||||
val width = bitmap.width
|
||||
val height = bitmap.height
|
||||
val data = IntArray(width * height)
|
||||
bitmap.getPixels(data, 0, width, 0, 0, width, height)
|
||||
return decodeLuminanceSource(RGBLuminanceSource(width, height, data))
|
||||
fun decode(yuvData: ByteArray, width: Int, height: Int): Result? {
|
||||
return decodeLuminanceSource(
|
||||
PlanarYUVLuminanceSource(
|
||||
yuvData,
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
0,
|
||||
width,
|
||||
height,
|
||||
false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun decodeLuminanceSource(source: LuminanceSource): Result? {
|
||||
val bitmap = BinaryBitmap(HybridBinarizer(source))
|
||||
val bitmap = BinaryBitmap(
|
||||
HybridBinarizer(
|
||||
if (odd) {
|
||||
source
|
||||
} else {
|
||||
source.invert()
|
||||
}
|
||||
)
|
||||
)
|
||||
odd = odd xor true
|
||||
return try {
|
||||
multiFormatReader.decodeWithState(bitmap)
|
||||
} catch (e: ReaderException) {
|
||||
|
@ -5,20 +5,20 @@ rs_allocation inImage;
|
||||
int inWidth;
|
||||
int inHeight;
|
||||
|
||||
uchar4 RS_KERNEL rotate90(uchar4 in, uint32_t x, uint32_t y) {
|
||||
const uchar4 *out = rsGetElementAt(inImage, y, inHeight - 1 - x);
|
||||
uchar RS_KERNEL rotate90(uchar in, uint32_t x, uint32_t y) {
|
||||
const uchar *out = rsGetElementAt(inImage, y, inHeight - 1 - x);
|
||||
return *out;
|
||||
}
|
||||
|
||||
uchar4 RS_KERNEL rotate180(uchar4 in, uint32_t x, uint32_t y) {
|
||||
const uchar4 *out = rsGetElementAt(
|
||||
uchar RS_KERNEL rotate180(uchar in, uint32_t x, uint32_t y) {
|
||||
const uchar *out = rsGetElementAt(
|
||||
inImage,
|
||||
inWidth - 1 - x,
|
||||
inHeight - 1 - y);
|
||||
return *out;
|
||||
}
|
||||
|
||||
uchar4 RS_KERNEL rotate270(uchar4 in, uint32_t x, uint32_t y) {
|
||||
const uchar4 *out = rsGetElementAt(inImage, inWidth - 1 - y, x);
|
||||
uchar RS_KERNEL rotate270(uchar in, uint32_t x, uint32_t y) {
|
||||
const uchar *out = rsGetElementAt(inImage, inWidth - 1 - y, x);
|
||||
return *out;
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
#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;
|
||||
}
|
||||
|
||||
uchar4 RS_KERNEL yuv2inverted(uint32_t x, uint32_t y) {
|
||||
uchar Y = 255 - 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