Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions src/android/src/gmvScanner/BarcodeCaptureActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,36 @@ public void onClick(View view) {
.show();
}

/* Used in testing.
private void requestFilesPermission() {
Log.w(TAG, "Files permission is not granted. Requesting permission");

final String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};

if (!ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
ActivityCompat.requestPermissions(this, permissions, 3);
return;
}

final Activity thisActivity = this;

View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View view) {
ActivityCompat.requestPermissions(thisActivity, permissions,
3);
}
};

findViewById(getResources().getIdentifier("topLayout", "id", getPackageName())).setOnClickListener(listener);
Snackbar.make(mGraphicOverlay, getResources().getIdentifier("permission_camera_rationale", "string", getPackageName()),
Snackbar.LENGTH_INDEFINITE)
.setAction(getResources().getIdentifier("ok", "string", getPackageName()), listener)
.show();
}*/


@Override
public boolean onTouchEvent(MotionEvent e) {
boolean b = scaleGestureDetector.onTouchEvent(e);
Expand Down Expand Up @@ -244,6 +274,7 @@ private void createCameraSource(boolean autoFocus, boolean useFlash) {
// Creates and starts the camera. Note that this uses a higher resolution in comparison
// to other detection examples to enable the barcode detector to detect small barcodes
// at long distances.

CameraSource.Builder builder = new CameraSource.Builder(getApplicationContext(), barcodeDetector)
.setFacing(CameraSource.CAMERA_FACING_BACK)
.setRequestedPreviewSize(1600, 1024)
Expand All @@ -258,6 +289,9 @@ private void createCameraSource(boolean autoFocus, boolean useFlash) {
mCameraSource = builder
.setFlashMode(useFlash ? Camera.Parameters.FLASH_MODE_TORCH : null)
.build();

mCameraSource.ViewFinderWidth = ViewFinderWidth;
mCameraSource.ViewFinderHeight = ViewFinderHeight;
}

/**
Expand Down Expand Up @@ -339,9 +373,9 @@ public void onClick(DialogInterface dialog, int id) {
};

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Camera permission required")
builder.setTitle("Multitracker sample")
.setMessage(getResources().getIdentifier("no_camera_permission", "string", getPackageName()))
.setPositiveButton(getResources().getIdentifier("ok", "string", getPackageName()), listener)
.setPositiveButton(getResources().getIdentifier("listener", "string", getPackageName()), listener)
.show();
}

Expand Down
143 changes: 140 additions & 3 deletions src/android/src/gmvScanner/ui/camera/CameraSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,41 @@
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.graphics.Matrix;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.os.Build;
import android.os.Environment;
import android.os.SystemClock;
import android.renderscript.Allocation;
import android.renderscript.Element;
import android.renderscript.RenderScript;
import android.renderscript.ScriptIntrinsic;
import android.renderscript.ScriptIntrinsicYuvToRGB;
import android.renderscript.Type;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresPermission;
import android.support.annotation.StringDef;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.WindowManager;

import com.google.android.gms.common.images.Size;
import com.google.android.gms.vision.Detector;
import com.google.android.gms.vision.Frame;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.Thread.State;
import java.lang.annotation.Retention;
Expand All @@ -47,6 +63,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

// Note: This requires Google Play Services 8.1 or higher, due to using indirect byte buffers for
// storing images.
Expand Down Expand Up @@ -119,6 +136,11 @@ public class CameraSource {

// Guarded by mCameraLock
private Camera mCamera;
public int viewWidth;
public int viewHeight;

public double ViewFinderWidth = .5;
public double ViewFinderHeight = .7;

private int mFacing = CAMERA_FACING_BACK;

Expand All @@ -130,6 +152,8 @@ public class CameraSource {

private Size mPreviewSize;

private List<Camera.Area> mFocusAreas;

// These values may be requested by the caller. Due to hardware limitations, we may need to
// select close, but not exactly the same values for these.
private float mRequestedFps = 30.0f;
Expand Down Expand Up @@ -209,6 +233,11 @@ public Builder setFlashMode(@FlashMode String mode) {
return this;
}

public Builder setFocusAreas(List<Camera.Area> focusAreas) {
mCameraSource.mFocusAreas = focusAreas;
return this;
}

/**
* Sets the desired width and height of the camera frames in pixels. If the exact desired
* values are not available options, the best matching available options are selected.
Expand Down Expand Up @@ -797,6 +826,7 @@ private Camera createCamera() {

// setting mFlashMode to the one set in the params
mFlashMode = parameters.getFlashMode();
parameters.setFocusAreas(mFocusAreas);

camera.setParameters(parameters);

Expand Down Expand Up @@ -1086,6 +1116,7 @@ private class FrameProcessingRunnable implements Runnable {
private long mPendingTimeMillis;
private int mPendingFrameId = 0;
private ByteBuffer mPendingFrameData;
private Bitmap mPendingFrameBitmap;

FrameProcessingRunnable(Detector<?> detector) {
mDetector = detector;
Expand Down Expand Up @@ -1136,12 +1167,60 @@ void setNextFrame(byte[] data, Camera camera) {
mPendingTimeMillis = SystemClock.elapsedRealtime() - mStartTimeMillis;
mPendingFrameId++;
mPendingFrameData = mBytesToByteBuffer.get(data);

mPendingFrameBitmap = Bitmap.createBitmap(mPreviewSize.getWidth(), mPreviewSize.getHeight(), Bitmap.Config.ARGB_8888);
Allocation bmData = renderScriptNV21ToRGBA888(
mContext,
mPreviewSize.getWidth(),
mPreviewSize.getHeight(),
data);
bmData.copyTo(mPendingFrameBitmap);
// Notify the processor thread if it is waiting on the next frame (see below).
mLock.notifyAll();
}
}


public Allocation renderScriptNV21ToRGBA888(Context context, int width, int height, byte[] nv21) {
RenderScript rs = RenderScript.create(context);
ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));

Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(nv21.length);
Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);

Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);

in.copyFrom(nv21);

yuvToRgbIntrinsic.setInput(in);
yuvToRgbIntrinsic.forEach(out);
return out;
}

private String saveToInternalStorage(Bitmap bitmapImage){
ContextWrapper cw = new ContextWrapper(mContext);
// path to /data/data/yourapp/app_data/imageDir
File directory = cw.getDir("imageDir", Context.MODE_WORLD_READABLE);
// Create imageDir
File mypath=new File(directory,"profile.jpg");

FileOutputStream fos = null;
try {
fos = new FileOutputStream(mypath);
// Use the compress method on the BitMap object to write image to the OutputStream
bitmapImage.compress(Bitmap.CompressFormat.PNG, 100, fos);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return directory.getAbsolutePath();
}

/**
* As long as the processing thread is active, this executes detection on frames
* continuously. The next pending frame is either immediately available or hasn't been
Expand Down Expand Up @@ -1182,9 +1261,66 @@ public void run() {
return;
}

// Extract the viewfinder portion of the preview.

float origFrameWidth = (float) mPreviewSize.getWidth();
float origFrameHeight = (float) mPreviewSize.getHeight();
if (origFrameHeight < origFrameWidth) {
origFrameWidth = (float) mPreviewSize.getHeight();
origFrameHeight = (float) mPreviewSize.getWidth();
}

float ratio = origFrameHeight / viewHeight;
if (ratio > origFrameWidth/viewWidth) {
ratio = origFrameWidth/viewWidth;
}

int newViewWidth = (int) (viewWidth * ratio);
int newViewHeight = (int) (viewHeight * ratio);

int viewFinderWidth = (int) (newViewWidth * ViewFinderWidth);
int viewFinderHeight = (int) (newViewHeight * ViewFinderHeight);

int x = (int) (origFrameWidth/2 - viewFinderWidth/2);
int y = (int) (origFrameHeight/2 - viewFinderHeight/2);

Matrix matrix = new Matrix();

matrix.postRotate(90);

mPendingFrameBitmap = Bitmap.createBitmap(mPendingFrameBitmap, 0, 0, mPendingFrameBitmap.getWidth(), mPendingFrameBitmap.getHeight(), matrix, true);
Log.d(TAG, (origFrameWidth/viewHeight) + "viewWidth:" + viewWidth + " viewHeight:" + viewHeight + " r:" + ratio + " x:" + x + " y:" + y + " w:" + viewFinderWidth + " h:"+viewFinderHeight + " w1:" + origFrameWidth + " h1:" +origFrameHeight);
Bitmap resizedBitmap = Bitmap.createBitmap(mPendingFrameBitmap, x,y,viewFinderWidth, viewFinderHeight);

/* For debugging the cropping of the frame.
String root = Environment.getExternalStorageDirectory().toString();
File myDir = new File(root + "/req_images");
myDir.mkdirs();
Random generator = new Random();
int n = 10000;
n = generator.nextInt(n);
String fname = "Image-" + n + ".jpg";
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fname);
Log.i(TAG, "" + file);
if (file.exists())
file.delete();
try {
FileOutputStream out = new FileOutputStream(file);
resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
out.flush();
out.close();
} catch (Exception e) {
e.printStackTrace();
}

if (true) {
return;
} //*/

outputFrame = new Frame.Builder()
.setImageData(mPendingFrameData, mPreviewSize.getWidth(),
mPreviewSize.getHeight(), ImageFormat.NV21)
.setBitmap(resizedBitmap)
/*.setImageData(mPendingFrameData, mPreviewSize.getWidth(),
mPreviewSize.getHeight(), ImageFormat.NV21) //*/
.setId(mPendingFrameId)
.setTimestampMillis(mPendingTimeMillis)
.setRotation(mRotation)
Expand All @@ -1195,6 +1331,7 @@ public void run() {
// recycled back to the camera before we are done using that data.
data = mPendingFrameData;
mPendingFrameData = null;
mPendingFrameBitmap = null;
}

// The code below needs to run outside of synchronization, because this will allow
Expand Down
9 changes: 6 additions & 3 deletions src/android/src/gmvScanner/ui/camera/CameraSourcePreview.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,18 @@ public void surfaceChanged(SurfaceHolder holder, int format, int width, int heig
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int width = 320;
int height = 240;

final int layoutWidth = right - left;
final int layoutHeight = bottom - top;

if (mCameraSource != null) {
Size size = mCameraSource.getPreviewSize();
if (size != null) {
width = size.getWidth();
height = size.getHeight();
}
mCameraSource.viewWidth = layoutWidth;
mCameraSource.viewHeight = layoutHeight;
}

// Swap width and height sizes when in portrait, since it will be rotated 90 degrees
Expand All @@ -191,9 +197,6 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto
height = tmp;
}

final int layoutWidth = right - left;
final int layoutHeight = bottom - top;

// Computes height and width for potentially doing fit width.

int childHeight = layoutHeight;
Expand Down