Skip to content

Commit 389a159

Browse files
committed
修复某些情况下会崩溃的问题
1 parent 4d4ddb6 commit 389a159

4 files changed

Lines changed: 284 additions & 82 deletions

File tree

czxing/src/main/cpp/ImageScheduler.cpp

Lines changed: 69 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,29 @@
77
#include <src/BinaryBitmap.h>
88
#include "ImageScheduler.h"
99
#include "JNIUtils.h"
10+
#include <thread>
11+
#include <chrono>
12+
13+
#define DEFAULT_MIN_LIGHT 70;
1014

1115
ImageScheduler::ImageScheduler(JNIEnv *env, MultiFormatReader *_reader,
1216
JavaCallHelper *javaCallHelper) {
1317
this->env = env;
1418
this->reader = _reader;
1519
this->javaCallHelper = javaCallHelper;
1620
qrCodeRecognizer = new QRCodeRecognizer();
21+
stopProcessing.store(false);
22+
isProcessing.store(false);
1723
}
1824

1925
ImageScheduler::~ImageScheduler() {
2026
DELETE(env);
2127
DELETE(reader);
2228
DELETE(javaCallHelper);
2329
DELETE(qrCodeRecognizer);
24-
25-
delete &frameData;
30+
frameQueue.clear();
2631
delete &isProcessing;
32+
delete &stopProcessing;
2733
delete &cameraLight;
2834
delete &prepareThread;
2935
}
@@ -34,37 +40,56 @@ void *prepareMethod(void *arg) {
3440
return nullptr;
3541
}
3642

43+
void releaseFrameData(FrameData &frameData) {
44+
delete &frameData;
45+
}
46+
3747
void ImageScheduler::prepare() {
48+
frameQueue.setReleaseHandle(releaseFrameData);
3849
pthread_create(&prepareThread, nullptr, prepareMethod, this);
3950
}
4051

4152
void ImageScheduler::start() {
42-
stopProcessing = false;
53+
stopProcessing.store(false);
54+
isProcessing.store(false);
55+
frameQueue.setWork(1);
4356

4457
while (true) {
45-
if (stopProcessing) {
58+
if (stopProcessing.load()) {
4659
break;
4760
}
48-
if (isProcessing) {
61+
62+
if (isProcessing.load()) {
63+
std::this_thread::sleep_for(chrono::milliseconds(100));
4964
continue;
5065
}
51-
preTreatMat();
66+
67+
FrameData frameData;
68+
int ret = frameQueue.deQueue(frameData);
69+
if (ret) {
70+
isProcessing.store(true);
71+
preTreatMat(frameData);
72+
isProcessing.store(false);
73+
}
5274
}
5375
}
5476

5577
void ImageScheduler::stop() {
56-
stopProcessing = true;
78+
isProcessing.store(false);
79+
stopProcessing.store(true);
80+
frameQueue.setWork(0);
81+
frameQueue.clear();
5782
}
5883

5984
void
6085
ImageScheduler::process(jbyte *bytes, int left, int top, int cropWidth, int cropHeight,
6186
int rowWidth,
6287
int rowHeight) {
63-
if (isProcessing) {
88+
if (isProcessing.load()) {
6489
return;
6590
}
6691

67-
frameData.bytes = bytes;
92+
FrameData frameData;
6893
frameData.left = left;
6994
frameData.top = top;
7095
frameData.cropWidth = cropWidth;
@@ -78,60 +103,51 @@ ImageScheduler::process(jbyte *bytes, int left, int top, int cropWidth, int crop
78103
}
79104
frameData.rowWidth = rowWidth;
80105
frameData.rowHeight = rowHeight;
106+
frameData.bytes = bytes;
81107

108+
frameQueue.enQueue(frameData);
109+
// LOGE("frame data size : %d", frameQueue.size());
82110
}
83111

84112
/**
85113
* 预处理二进制数据
86114
*/
87-
void ImageScheduler::preTreatMat() {
88-
if (isProcessing) {
89-
return;
90-
}
91-
isProcessing = true;
92-
93-
if (frameData.bytes == nullptr) {
94-
isProcessing = false;
115+
void ImageScheduler::preTreatMat(const FrameData &frameData) {
116+
if (&frameData == nullptr) {
95117
return;
96118
}
97119

98-
// 分析亮度,如果亮度过低,不进行处理
99-
LOGE("111111111111111");
100-
analysisBrightness(frameData);
101-
LOGE("222222222222222");
102-
103-
if (cameraLight < 150) {
104-
isProcessing = false;
105-
return;
106-
}
107-
LOGE("33333333333333333");
120+
LOGE("start preTreatMat...");
108121

109122
Mat src(frameData.rowHeight + frameData.rowHeight / 2,
110123
frameData.rowWidth, CV_8UC1,
111124
frameData.bytes);
112125

113-
cvtColor(src, src, COLOR_YUV2RGBA_NV21);
126+
Mat gray;
127+
cvtColor(src, gray, COLOR_YUV2GRAY_NV21);
114128

115129
if (frameData.left != 0) {
116-
src = src(Rect(frameData.left, frameData.top, frameData.cropWidth, frameData.cropHeight));
130+
gray = gray(Rect(frameData.left, frameData.top, frameData.cropWidth, frameData.cropHeight));
117131
}
118132

119-
Mat gray;
120-
cvtColor(src, gray, COLOR_RGBA2GRAY);
121-
122-
LOGE("start decode...");
133+
// 分析亮度,如果亮度过低,不进行处理
134+
analysisBrightness(gray);
135+
if (cameraLight < 40) {
136+
return;
137+
}
123138
decodeGrayPixels(gray);
124139
}
125140

126141
void ImageScheduler::decodeGrayPixels(const Mat &gray) {
142+
LOGE("start GrayPixels...");
143+
127144
Mat mat;
128145
rotate(gray, mat, ROTATE_90_CLOCKWISE);
129146

130147
Result result = decodePixels(mat);
131148

132149
if (result.isValid()) {
133150
javaCallHelper->onResult(result);
134-
isProcessing = false;
135151
}
136152
// else if (result.isNeedScale()) {
137153
// LOGE("is need scale image...");
@@ -153,7 +169,6 @@ void ImageScheduler::decodeGrayPixels(const Mat &gray) {
153169
//
154170
// if (result.isValid()) {
155171
// javaCallHelper->onResult(result);
156-
// isProcessing = false;
157172
// } else {
158173
// decodeThresholdPixels(gray);
159174
// }
@@ -164,11 +179,13 @@ void ImageScheduler::decodeGrayPixels(const Mat &gray) {
164179
}
165180

166181
void ImageScheduler::decodeThresholdPixels(const Mat &gray) {
182+
LOGE("start ThresholdPixels...");
183+
167184
Mat mat;
168185
rotate(gray, mat, ROTATE_180);
169186

170187
// 提升亮度
171-
if (cameraLight < 180) {
188+
if (cameraLight < 80) {
172189
mat.convertTo(mat, -1, 1.0, 30);
173190
}
174191

@@ -177,13 +194,14 @@ void ImageScheduler::decodeThresholdPixels(const Mat &gray) {
177194
Result result = decodePixels(mat);
178195
if (result.isValid()) {
179196
javaCallHelper->onResult(result);
180-
isProcessing = false;
181197
} else {
182198
decodeAdaptivePixels(gray);
183199
}
184200
}
185201

186202
void ImageScheduler::decodeAdaptivePixels(const Mat &gray) {
203+
LOGE("start AdaptivePixels...");
204+
187205
Mat mat;
188206
rotate(gray, mat, ROTATE_90_COUNTERCLOCKWISE);
189207

@@ -197,17 +215,18 @@ void ImageScheduler::decodeAdaptivePixels(const Mat &gray) {
197215
Result result = decodePixels(lightMat);
198216
if (result.isValid()) {
199217
javaCallHelper->onResult(result);
200-
isProcessing = false;
201-
} else {
202-
recognizerQrCode(gray);
203218
}
219+
// } else {
220+
// recognizerQrCode(gray);
221+
// }
204222
}
205223

206224
void ImageScheduler::recognizerQrCode(const Mat &mat) {
225+
LOGE("start recognizerQrCode...");
226+
207227
cv::Rect rect;
208228
qrCodeRecognizer->processData(mat, &rect);
209229
if (rect.empty()) {
210-
isProcessing = false;
211230
return;
212231
}
213232

@@ -224,7 +243,9 @@ void ImageScheduler::recognizerQrCode(const Mat &mat) {
224243
result.setResultPoints(std::move(points));
225244

226245
javaCallHelper->onResult(result);
227-
isProcessing = false;
246+
247+
LOGE("end recognizerQrCode...");
248+
228249
}
229250

230251
Result ImageScheduler::decodePixels(Mat mat) {
@@ -260,33 +281,15 @@ Result ImageScheduler::decodePixels(Mat mat) {
260281
return Result(DecodeStatus::NotFound);
261282
}
262283

263-
bool ImageScheduler::analysisBrightness(const FrameData frameData) {
264-
// LOGE("start analysisBrightness...");
265-
266-
// 像素点的总亮度
267-
unsigned long pixelLightCount = 0L;
268-
269-
// 采集步长,因为没有必要每个像素点都采集,可以跨一段采集一个,减少计算负担,必须大于等于1。
270-
int step = 2;
271-
// 像素点的总数
272-
int pixelCount = frameData.cropWidth * frameData.cropHeight / step;
273-
274-
int bottom = frameData.top + frameData.cropHeight;
275-
int right = frameData.left + frameData.cropWidth;
276-
int rowWidth = frameData.rowWidth;
277-
int srcIndex = 0;
278-
for (int i = frameData.left; i < right; ++i) {
279-
srcIndex = (bottom - 1) * rowWidth + i;
280-
for (int j = 0; j < frameData.cropHeight; j += step, srcIndex -= rowWidth) {
281-
pixelLightCount += frameData.bytes[srcIndex] & 0xFFL;
282-
}
283-
}
284+
bool ImageScheduler::analysisBrightness(const Mat& gray) {
285+
LOGE("start analysisBrightness...");
284286

285287
// 平均亮度
286-
cameraLight = pixelLightCount / (pixelCount / step);
287-
// LOGE("平均亮度 %ld", cameraLight);
288+
Scalar scalar = mean(gray);
289+
cameraLight = scalar.val[0];
290+
LOGE("平均亮度 %lf", cameraLight);
288291
// 判断在时间范围 AMBIENT_BRIGHTNESS_WAIT_SCAN_TIME * lightSize 内是不是亮度过暗
289-
bool isDark = cameraLight < 160;
292+
bool isDark = cameraLight < DEFAULT_MIN_LIGHT;
290293
javaCallHelper->onBrightness(isDark);
291294

292295
return isDark;

czxing/src/main/cpp/ImageScheduler.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "Result.h"
1414
#include "JavaCallHelper.h"
1515
#include "QRCodeRecognizer.h"
16+
#include "safe_queue.h"
1617

1718
using namespace cv;
1819
using namespace ZXing;
@@ -43,26 +44,25 @@ class ImageScheduler {
4344

4445
void stop();
4546

46-
void preTreatMat();
47+
void preTreatMat(const FrameData& frameData);
4748

4849
void decodeGrayPixels(const Mat& gray);
4950

5051
void decodeThresholdPixels(const Mat& gray);
5152

5253
void decodeAdaptivePixels(const Mat& gray);
5354

54-
FrameData frameData{};
55-
5655
Result readBitmap(jobject bitmap, int left, int top, int width,int height);
5756

5857
private:
5958
JNIEnv *env;
6059
MultiFormatReader *reader;
6160
JavaCallHelper *javaCallHelper;
62-
bool isProcessing = false;
63-
bool stopProcessing = false;
64-
long cameraLight{};
61+
std::atomic<bool> isProcessing{};
62+
std::atomic<bool> stopProcessing{};
63+
double cameraLight{};
6564
QRCodeRecognizer *qrCodeRecognizer;
65+
SafeQueue<FrameData> frameQueue;
6666

6767
pthread_t prepareThread{};
6868

@@ -72,7 +72,7 @@ class ImageScheduler {
7272

7373
Result *analyzeResult();
7474

75-
bool analysisBrightness(const FrameData frameData);
75+
bool analysisBrightness(const Mat& gray);
7676

7777
};
7878

czxing/src/main/cpp/JNIUtils.h

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,44 @@
2424
#include <opencv2/core/types.hpp>
2525

2626
#define ZX_LOG_TAG "ZXing"
27+
//#define DEBUG
2728

2829
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, ZX_LOG_TAG, __VA_ARGS__)
2930
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, ZX_LOG_TAG, __VA_ARGS__)
3031
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, ZX_LOG_TAG, __VA_ARGS__)
31-
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, ZX_LOG_TAG, __VA_ARGS__)
32+
33+
#ifdef DEBUG
34+
#define LOGE(...) \
35+
__android_log_print(ANDROID_LOG_ERROR, ZX_LOG_TAG, __VA_ARGS__)
36+
#else
37+
#define LOGE(...) \
38+
{}
39+
#endif
40+
3241
#define DELETE(obj) if(obj){ delete obj; obj = 0; }
3342

3443
namespace ZXing {
35-
class BinaryBitmap;
44+
class BinaryBitmap;
3645
}
3746

3847
// Create BinaryBitmap from Android's Bitmap
39-
std::shared_ptr<ZXing::BinaryBitmap> BinaryBitmapFromJavaBitmap(JNIEnv* env, jobject bitmap, int cropLeft, int cropTop, int cropWidth, int cropHeight);
40-
std::shared_ptr<ZXing::BinaryBitmap> BinaryBitmapFromBytesC4(JNIEnv* env, void *rgbScale, int cropLeft, int cropTop, int cropWidth, int cropHeight);
41-
std::shared_ptr<ZXing::BinaryBitmap> BinaryBitmapFromBytesC1(void *grayScale, int cropLeft, int cropTop, int cropWidth, int cropHeight);
42-
std::string UnicodeToANSI(const std::wstring & wstr);
48+
std::shared_ptr<ZXing::BinaryBitmap>
49+
BinaryBitmapFromJavaBitmap(JNIEnv *env, jobject bitmap, int cropLeft, int cropTop, int cropWidth,
50+
int cropHeight);
51+
52+
std::shared_ptr<ZXing::BinaryBitmap>
53+
BinaryBitmapFromBytesC4(JNIEnv *env, void *rgbScale, int cropLeft, int cropTop, int cropWidth,
54+
int cropHeight);
55+
56+
std::shared_ptr<ZXing::BinaryBitmap>
57+
BinaryBitmapFromBytesC1(void *grayScale, int cropLeft, int cropTop, int cropWidth, int cropHeight);
58+
59+
std::string UnicodeToANSI(const std::wstring &wstr);
60+
4361
std::wstring ANSIToUnicode(const std::string &src);
44-
void ThrowJavaException(JNIEnv* env, const char* message);
45-
jstring ToJavaString(JNIEnv* env, const std::wstring& str);
46-
jfloatArray ToJavaArray(JNIEnv* env, const std::vector<ZXing::ResultPoint>& vector);
62+
63+
void ThrowJavaException(JNIEnv *env, const char *message);
64+
65+
jstring ToJavaString(JNIEnv *env, const std::wstring &str);
66+
67+
jfloatArray ToJavaArray(JNIEnv *env, const std::vector<ZXing::ResultPoint> &vector);

0 commit comments

Comments
 (0)