Skip to content

Commit c4eb697

Browse files
committed
feat(android): moving BarCodeScanning logic to ScanArea
1 parent e9af04a commit c4eb697

File tree

3 files changed

+110
-139
lines changed

3 files changed

+110
-139
lines changed

android/src/main/java/org/reactnative/camera/RNCameraView.java

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.reactnative.barcodedetector.RNBarcodeDetector;
2020
import org.reactnative.camera.tasks.*;
2121
import org.reactnative.camera.utils.RNFileUtils;
22+
import org.reactnative.camera.utils.ScanArea;
2223
import org.reactnative.facedetector.RNFaceDetector;
2324

2425
import java.io.File;
@@ -73,6 +74,7 @@ public class RNCameraView extends CameraView implements LifecycleEventListener,
7374
private float mScanAreaHeight = 0.0f;
7475
private int mCameraViewWidth = 0;
7576
private int mCameraViewHeight = 0;
77+
private ScanArea mScanArea = new ScanArea(mLimitScanArea, 0, 0, mScanAreaX, mScanAreaY, mScanAreaWidth, mScanAreaHeight, mCameraViewWidth, mCameraViewHeight, 0.0f);
7678

7779
public RNCameraView(ThemedReactContext themedReactContext) {
7880
super(themedReactContext, true);
@@ -159,7 +161,8 @@ public void onFramePreview(CameraView cameraView, byte[] data, int width, int he
159161
if (willCallBarCodeTask) {
160162
barCodeScannerTaskLock = true;
161163
BarCodeScannerAsyncTaskDelegate delegate = (BarCodeScannerAsyncTaskDelegate) cameraView;
162-
new BarCodeScannerAsyncTask(delegate, mMultiFormatReader, data, width, height, mLimitScanArea, mScanAreaX, mScanAreaY, mScanAreaWidth, mScanAreaHeight, mCameraViewWidth, mCameraViewHeight, getAspectRatio().toFloat()).execute();
164+
ScanArea mScanArea = new ScanArea(mLimitScanArea, width, height, mScanAreaX, mScanAreaY, mScanAreaWidth, mScanAreaHeight, mCameraViewWidth, mCameraViewHeight, getAspectRatio().toFloat());
165+
new BarCodeScannerAsyncTask(delegate, mMultiFormatReader, data, mScanArea).execute();
163166
}
164167

165168
if (willCallFaceTask) {
@@ -358,15 +361,16 @@ public void onBarCodeScanningTaskCompleted() {
358361

359362
// Limit Scan Area
360363
public void setRectOfInterest(float x, float y, float width, float height) {
361-
this.mLimitScanArea = true;
362-
this.mScanAreaX = x;
363-
this.mScanAreaY = y;
364-
this.mScanAreaWidth = width;
365-
this.mScanAreaHeight = height;
366-
}
367-
public void setCameraViewDimensions(int width, int height) {
368-
this.mCameraViewWidth = width;
369-
this.mCameraViewHeight = height;
364+
mScanArea.setLimitScanArea(true);
365+
mScanArea.setScanAreaX(x);
366+
mScanArea.setScanAreaY(y);
367+
mScanArea.setScanAreaWidth(width);
368+
mScanArea.setScanAreaHeight(height);
369+
}
370+
371+
public void setCameraViewDimensions(int width, int height) {
372+
mScanArea.setCameraWidth(width);
373+
mScanArea.setCameraHeight(height);
370374
}
371375

372376
/**

android/src/main/java/org/reactnative/camera/tasks/BarCodeScannerAsyncTask.java

Lines changed: 32 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -6,51 +6,29 @@
66
import com.google.zxing.PlanarYUVLuminanceSource;
77
import com.google.zxing.Result;
88
import com.google.zxing.common.HybridBinarizer;
9+
import org.reactnative.camera.utils.ScanArea;
10+
import android.util.Log;
911

1012
public class BarCodeScannerAsyncTask extends android.os.AsyncTask<Void, Void, Result> {
1113
private byte[] mImageData;
1214
private int mWidth;
1315
private int mHeight;
1416
private BarCodeScannerAsyncTaskDelegate mDelegate;
1517
private final MultiFormatReader mMultiFormatReader;
16-
private boolean mLimitScanArea;
17-
private float mScanAreaX;
18-
private float mScanAreaY;
19-
private float mScanAreaWidth;
20-
private float mScanAreaHeight;
21-
private int mCameraViewWidth;
22-
private int mCameraViewHeight;
23-
private float mRatio;
18+
private ScanArea mScanArea;
2419

25-
// note(sjchmiela): From my short research it's ok to ignore rotation of the image.
2620
public BarCodeScannerAsyncTask(
2721
BarCodeScannerAsyncTaskDelegate delegate,
2822
MultiFormatReader multiFormatReader,
2923
byte[] imageData,
30-
int width,
31-
int height,
32-
boolean limitScanArea,
33-
float scanAreaX,
34-
float scanAreaY,
35-
float scanAreaWidth,
36-
float scanAreaHeight,
37-
int cameraViewWidth,
38-
int cameraViewHeight,
39-
float ratio
24+
ScanArea scanArea
4025
) {
41-
mImageData = imageData;
42-
mWidth = width;
43-
mHeight = height;
26+
mScanArea = scanArea;
27+
mWidth = mScanArea.getWidth();
28+
mHeight = mScanArea.getHeight();
29+
mImageData = rotateImage(imageData,mWidth, mHeight);
4430
mDelegate = delegate;
4531
mMultiFormatReader = multiFormatReader;
46-
mLimitScanArea = limitScanArea;
47-
mScanAreaX = scanAreaX;
48-
mScanAreaY = scanAreaY;
49-
mScanAreaWidth = scanAreaWidth;
50-
mScanAreaHeight = scanAreaHeight;
51-
mCameraViewWidth = cameraViewWidth;
52-
mCameraViewHeight = cameraViewHeight;
53-
mRatio = ratio;
5432
}
5533

5634
@Override
@@ -60,81 +38,38 @@ protected Result doInBackground(Void... ignored) {
6038
}
6139

6240
Result result = null;
63-
/**
64-
* mCameraViewWidth and mCameraViewHeight are obtained from portait orientation
65-
* mWidth and mHeight are measured with landscape orientation with Home button to the right
66-
* adjustedCamViewWidth is the adjusted width fromt the Aspect ratio setting
67-
*/
68-
int adjustedCamViewWidth = (int) (mCameraViewHeight / mRatio);
69-
float adjustedScanY = (((adjustedCamViewWidth - mCameraViewWidth) / 2) + (mScanAreaY * mCameraViewWidth)) / adjustedCamViewWidth;
70-
71-
int left = (int) (mScanAreaX * mWidth);
72-
int top = (int) (adjustedScanY * mHeight);
73-
int scanWidth = (int) (mScanAreaWidth * mWidth);
74-
int scanHeight = (int) (((mScanAreaHeight * mCameraViewWidth) / adjustedCamViewWidth) * mHeight);
75-
41+
boolean mLimitScanArea = mScanArea.getLimitScanArea();
42+
int scanWidth = mScanArea.getScanWidth();
43+
int scanHeight = mScanArea.getScanHeight();
44+
int left = mScanArea.getLeft();
45+
int top = mScanArea.getTop();
46+
if (!mLimitScanArea) {
47+
left = 0;
48+
top = 0;
49+
scanWidth = mWidth;
50+
scanHeight = mHeight;
51+
}
52+
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(
53+
mImageData,
54+
mHeight,
55+
mWidth,
56+
mHeight - scanHeight - top,
57+
left,
58+
scanHeight,
59+
scanWidth,
60+
false
61+
);
62+
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
7663
try {
77-
BinaryBitmap bitmap = generateBitmapFromImageData(
78-
mImageData,
79-
mWidth,
80-
mHeight,
81-
false,
82-
left,
83-
top,
84-
scanWidth,
85-
scanHeight
86-
);
8764
result = mMultiFormatReader.decodeWithState(bitmap);
8865
} catch (NotFoundException e) {
89-
BinaryBitmap bitmap = generateBitmapFromImageData(
90-
rotateImage(mImageData,mWidth, mHeight),
91-
mHeight,
92-
mWidth,
93-
false,
94-
mHeight - scanHeight - top,
95-
left,
96-
scanHeight,
97-
scanWidth
98-
);
99-
try {
100-
result = mMultiFormatReader.decodeWithState(bitmap);
101-
} catch (NotFoundException e1) {
102-
BinaryBitmap invertedBitmap = generateBitmapFromImageData(
103-
mImageData,
104-
mWidth,
105-
mHeight,
106-
true,
107-
mWidth - scanWidth - left,
108-
mHeight - scanHeight - top,
109-
scanWidth,
110-
scanHeight
111-
);
112-
try {
113-
result = mMultiFormatReader.decodeWithState(invertedBitmap);
114-
} catch (NotFoundException e2) {
115-
BinaryBitmap invertedRotatedBitmap = generateBitmapFromImageData(
116-
rotateImage(mImageData,mWidth, mHeight),
117-
mHeight,
118-
mWidth,
119-
true,
120-
top,
121-
mWidth - scanWidth - left,
122-
scanHeight,
123-
scanWidth
124-
);
125-
try {
126-
result = mMultiFormatReader.decodeWithState(invertedRotatedBitmap);
127-
} catch (NotFoundException e3) {
128-
//no barcode Found
129-
}
130-
}
131-
}
66+
Log.w("CAMERA_1::", "BarCodeScannerAsyncTask doInBackground throws: ", e);
13267
} catch (Throwable t) {
13368
t.printStackTrace();
13469
}
135-
13670
return result;
13771
}
72+
13873
private byte[] rotateImage(byte[]imageData,int width, int height) {
13974
byte[] rotated = new byte[imageData.length];
14075
for (int y = 0; y < height; y++) {
@@ -152,36 +87,4 @@ protected void onPostExecute(Result result) {
15287
}
15388
mDelegate.onBarCodeScanningTaskCompleted();
15489
}
155-
156-
private BinaryBitmap generateBitmapFromImageData(byte[] imageData, int width, int height, boolean inverse, int left, int top, int sWidth, int sHeight) {
157-
PlanarYUVLuminanceSource source;
158-
if (mLimitScanArea) {
159-
source = new PlanarYUVLuminanceSource(
160-
imageData, // byte[] yuvData
161-
width, // int dataWidth
162-
height, // int dataHeight
163-
left, // int left
164-
top, // int top
165-
sWidth, // int width
166-
sHeight, // int height
167-
false // boolean reverseHorizontal
168-
);
169-
} else {
170-
source = new PlanarYUVLuminanceSource(
171-
imageData, // byte[] yuvData
172-
width, // int dataWidth
173-
height, // int dataHeight
174-
0, // int left
175-
0, // int top
176-
width, // int width
177-
height, // int height
178-
false // boolean reverseHorizontal
179-
);
180-
}
181-
if (inverse) {
182-
return new BinaryBitmap(new HybridBinarizer(source.invert()));
183-
} else {
184-
return new BinaryBitmap(new HybridBinarizer(source));
185-
}
186-
}
18790
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.reactnative.camera.utils;
2+
3+
public class ScanArea {
4+
private Float scanX, scanY, scanAreaWidth, scanAreaHeight, ratio, adjustedScanY;
5+
private Integer width, height, cameraWidth, cameraHeight, left, top, scanWidth, scanHeight;
6+
private Boolean limitScanArea;
7+
8+
public ScanArea(
9+
Boolean limitScanArea,
10+
Integer width,
11+
Integer height,
12+
Float scanX,
13+
Float scanY,
14+
Float scanAreaWidth,
15+
Float scanAreaHeight,
16+
Integer cameraWidth,
17+
Integer cameraHeight,
18+
Float ratio
19+
) {
20+
// TODO: Group all parameters in size, coordinates, area, camera ..
21+
this.limitScanArea = limitScanArea;
22+
this.width = width;
23+
this.height = height;
24+
this.scanX = scanX;
25+
this.scanY = scanY;
26+
this.scanAreaHeight = scanAreaHeight;
27+
this.scanAreaWidth = scanAreaWidth;
28+
this.cameraWidth = cameraWidth;
29+
this.cameraHeight = cameraHeight;
30+
Integer aspectRatio = (int) (cameraHeight / ratio);
31+
Float widthMargin = (float) (aspectRatio - cameraWidth) / 2;
32+
Float computedArea = this.scanY * cameraWidth;
33+
this.adjustedScanY = (widthMargin + computedArea) / aspectRatio;
34+
this.left = (int) (scanX * width);
35+
this.top = (int) (this.adjustedScanY * height);
36+
this.scanWidth = (int) (scanAreaWidth * width);
37+
Float area = scanAreaHeight * cameraWidth;
38+
this.scanHeight = (int) ((area / aspectRatio) * height);
39+
}
40+
41+
// TODO: Metaprogramming loop to remove getters/setters
42+
public void setLimitScanArea(Boolean value) { this.limitScanArea = value; }
43+
public void setScanAreaX(Float value) { this.scanX = value; }
44+
public void setScanAreaY(Float value) { this.scanY = value; }
45+
public void setScanAreaWidth(Float value) { this.scanAreaWidth = value; }
46+
public void setScanAreaHeight(Float value) { this.scanAreaHeight = value; }
47+
public void setCameraWidth(Integer value) { this.cameraWidth = value; }
48+
public void setCameraHeight(Integer value) { this.cameraHeight = value; }
49+
50+
public Boolean getLimitScanArea() { return this.limitScanArea; }
51+
public Float getAdjustedScanY() { return this.adjustedScanY; }
52+
public Integer getLeft() { return this.left; }
53+
public Integer getTop() { return this.top; }
54+
public Float getScanAreaWidth() { return this.scanAreaWidth; }
55+
public Float getScanAreaHeight() { return this.scanAreaHeight; }
56+
public Integer getScanWidth() { return this.scanWidth; }
57+
public Integer getScanHeight() { return this.scanHeight; }
58+
public Integer getWidth() { return this.width; }
59+
public Integer getHeight() { return this.height; }
60+
public Float getScanX() { return this.scanX; }
61+
public Float getScanY() { return this.scanY; }
62+
public Integer getCameraWidth() { return this.cameraWidth; }
63+
public Integer getCameraHeight() { return this.cameraHeight; }
64+
}

0 commit comments

Comments
 (0)