diff --git a/modules/imgproc/doc/filtering.rst b/modules/imgproc/doc/filtering.rst
index 845e35bce..819514b08 100644
--- a/modules/imgproc/doc/filtering.rst
+++ b/modules/imgproc/doc/filtering.rst
@@ -1332,7 +1332,7 @@ pyrMeanShiftFiltering
---------------------
Performs initial step of meanshift segmentation of an image.
-.. ocv:function: void pyrMeanShiftFiltering( InputArray src, OutputArray dst, double sp, double sr, int maxLevel=1, TermCriteria termcrit=TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS,5,1) )
+.. ocv:function:: void pyrMeanShiftFiltering( InputArray src, OutputArray dst, double sp, double sr, int maxLevel=1, TermCriteria termcrit=TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS,5,1) )
.. ocv:pyfunction:: cv2.pyrMeanShiftFiltering(src, sp, sr[, dst[, maxLevel[, termcrit]]]) -> dst
diff --git a/modules/java/gen_java.py b/modules/java/gen_java.py
index ad7331478..3d3cd00c6 100644
--- a/modules/java/gen_java.py
+++ b/modules/java/gen_java.py
@@ -176,7 +176,7 @@ type_dict = {
}
-setManualFunctions=set(['minMaxLoc'])
+setManualFunctions=set(['minMaxLoc', 'getTextSize'])
class ConstInfo(object):
def __init__(self, cname, name, val):
@@ -420,7 +420,14 @@ class JavaWrapperGenerator(object):
return minMaxLoc(src, null);
}
private static native double[] n_minMaxLocManual(long src_nativeObj, long mask_nativeObj);
-
+
+ //javadoc:getTextSize(text, fontFace, fontScale, thickness, baseLine)
+ public static Size getTextSize(String text, int fontFace, double fontScale, int thickness, int[] baseLine) {
+ assert(baseLine == null || baseLine.length == 1);
+ Size retVal = new Size(n_getTextSize(text, fontFace, fontScale, thickness, baseLine));
+ return retVal;
+ }
+ private static native double[] n_getTextSize(String text, int fontFace, double fontScale, int thickness, int[] baseLine);
""" )
@@ -558,7 +565,62 @@ JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_n_1minMaxLocManual
LOGD("core::n_1minMaxLoc() catched unknown exception (...)");
#endif // DEBUG
jclass je = env->FindClass("java/lang/Exception");
- env->ThrowNew(je, "Unknown exception in JNI code {$module::$fname()}");
+ env->ThrowNew(je, "Unknown exception in JNI code {core::minMaxLoc()}");
+ return NULL;
+ }
+}
+
+JNIEXPORT jdoubleArray JNICALL Java_org_opencv_core_n_1getTextSize
+ (JNIEnv* env, jclass cls, jstring text, jint fontFace, jdouble fontScale, jint thickness, jintArray baseLine)
+{
+ try {
+#ifdef DEBUG
+ LOGD("core::n_1getTextSize()");
+#endif // DEBUG
+
+ jdoubleArray result;
+ result = env->NewDoubleArray(2);
+ if (result == NULL) {
+ return NULL; /* out of memory error thrown */
+ }
+
+ const char* utf_text = env->GetStringUTFChars(text, 0);
+ std::string n_text( utf_text ? utf_text : "" );
+ env->ReleaseStringUTFChars(text, utf_text);
+
+ int _baseLine;
+ int* pbaseLine = 0;
+
+ if (baseLine != NULL)
+ pbaseLine = &_baseLine;
+
+ cv::Size rsize = cv::getTextSize(n_text, (int)fontFace, (double)fontScale, (int)thickness, pbaseLine);
+
+ jdouble fill[2];
+ fill[0]=rsize.width;
+ fill[1]=rsize.height;
+
+ env->SetDoubleArrayRegion(result, 0, 2, fill);
+
+ if (baseLine != NULL)
+ env->SetIntArrayRegion(baseLine, 0, 1, pbaseLine);
+
+ return result;
+
+ } catch(cv::Exception e) {
+#ifdef DEBUG
+ LOGD("core::n_1getTextSize() catched cv::Exception: %s", e.what());
+#endif // DEBUG
+ jclass je = env->FindClass("org/opencv/CvException");
+ if(!je) je = env->FindClass("java/lang/Exception");
+ env->ThrowNew(je, e.what());
+ return NULL;
+ } catch (...) {
+#ifdef DEBUG
+ LOGD("core::n_1getTextSize() catched unknown exception (...)");
+#endif // DEBUG
+ jclass je = env->FindClass("java/lang/Exception");
+ env->ThrowNew(je, "Unknown exception in JNI code {core::getTextSize()}");
return NULL;
}
}
diff --git a/samples/android/15-puzzle/.classpath b/samples/android/15-puzzle/.classpath
new file mode 100644
index 000000000..87ce3fa5d
--- /dev/null
+++ b/samples/android/15-puzzle/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/samples/android/15-puzzle/.project b/samples/android/15-puzzle/.project
new file mode 100644
index 000000000..415bed257
--- /dev/null
+++ b/samples/android/15-puzzle/.project
@@ -0,0 +1,40 @@
+
+
+ 15-puzzle
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
+
+ OpenCV-2.3.1_src
+ 2
+ _android_OpenCV_2_3_1_df28900a/src
+
+
+
diff --git a/samples/android/15-puzzle/.settings/org.eclipse.jdt.core.prefs b/samples/android/15-puzzle/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 000000000..d99578433
--- /dev/null
+++ b/samples/android/15-puzzle/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,5 @@
+#Wed Jun 29 04:36:40 MSD 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/samples/android/15-puzzle/AndroidManifest.xml b/samples/android/15-puzzle/AndroidManifest.xml
new file mode 100644
index 000000000..30003c1f9
--- /dev/null
+++ b/samples/android/15-puzzle/AndroidManifest.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/android/15-puzzle/default.properties b/samples/android/15-puzzle/default.properties
new file mode 100644
index 000000000..fb3ea1f7b
--- /dev/null
+++ b/samples/android/15-puzzle/default.properties
@@ -0,0 +1,3 @@
+android.library.reference.1=../../../android/build
+# Project target.
+target=android-8
diff --git a/samples/android/15-puzzle/res/drawable/icon.png b/samples/android/15-puzzle/res/drawable/icon.png
new file mode 100644
index 000000000..4e828bafd
Binary files /dev/null and b/samples/android/15-puzzle/res/drawable/icon.png differ
diff --git a/samples/android/15-puzzle/res/values/strings.xml b/samples/android/15-puzzle/res/values/strings.xml
new file mode 100644
index 000000000..99e731588
--- /dev/null
+++ b/samples/android/15-puzzle/res/values/strings.xml
@@ -0,0 +1,4 @@
+
+
+ 15-puzzle
+
diff --git a/samples/android/15-puzzle/src/org/opencv/samples/puzzle15/SampleViewBase.java b/samples/android/15-puzzle/src/org/opencv/samples/puzzle15/SampleViewBase.java
new file mode 100644
index 000000000..b85325e33
--- /dev/null
+++ b/samples/android/15-puzzle/src/org/opencv/samples/puzzle15/SampleViewBase.java
@@ -0,0 +1,108 @@
+package org.opencv.samples.puzzle15;
+
+import java.util.List;
+
+import org.opencv.*;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.util.Log;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+public abstract class SampleViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
+ private static final String TAG = "Sample::SurfaceView";
+
+ private SurfaceHolder mHolder;
+ private VideoCapture mCamera;
+
+ public SampleViewBase(Context context) {
+ super(context);
+ mHolder = getHolder();
+ mHolder.addCallback(this);
+ Log.i(TAG, "Instantiated new " + this.getClass());
+ }
+
+ public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
+ Log.i(TAG, "surfaceCreated");
+ synchronized (this) {
+ if (mCamera != null && mCamera.isOpened()) {
+ Log.i(TAG, "before mCamera.getSupportedPreviewSizes()");
+ List sizes = mCamera.getSupportedPreviewSizes();
+ Log.i(TAG, "after mCamera.getSupportedPreviewSizes()");
+ int mFrameWidth = width;
+ int mFrameHeight = height;
+
+ // selecting optimal camera preview size
+ {
+ double minDiff = Double.MAX_VALUE;
+ for (Size size : sizes) {
+ if (Math.abs(size.height - height) < minDiff) {
+ mFrameWidth = (int) size.width;
+ mFrameHeight = (int) size.height;
+ minDiff = Math.abs(size.height - height);
+ }
+ }
+ }
+
+ mCamera.set(highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth);
+ mCamera.set(highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight);
+ }
+ }
+ }
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ Log.i(TAG, "surfaceCreated");
+ mCamera = new VideoCapture(highgui.CV_CAP_ANDROID);
+ if (mCamera.isOpened()) {
+ (new Thread(this)).start();
+ } else {
+ mCamera.release();
+ mCamera = null;
+ Log.e(TAG, "Failed to open native camera");
+ }
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ Log.i(TAG, "surfaceDestroyed");
+ if (mCamera != null) {
+ synchronized (this) {
+ mCamera.release();
+ mCamera = null;
+ }
+ }
+ }
+
+ protected abstract Bitmap processFrame(VideoCapture capture);
+
+ public void run() {
+ Log.i(TAG, "Starting processing thread");
+ while (true) {
+ Bitmap bmp = null;
+
+ synchronized (this) {
+ if (mCamera == null)
+ break;
+
+ if (!mCamera.grab()) {
+ Log.e(TAG, "mCamera.grab() failed");
+ break;
+ }
+
+ bmp = processFrame(mCamera);
+ }
+
+ if (bmp != null) {
+ Canvas canvas = mHolder.lockCanvas();
+ if (canvas != null) {
+ canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, (canvas.getHeight() - bmp.getHeight()) / 2, null);
+ mHolder.unlockCanvasAndPost(canvas);
+ }
+ bmp.recycle();
+ }
+ }
+
+ Log.i(TAG, "Finishing processing thread");
+ }
+}
\ No newline at end of file
diff --git a/samples/android/15-puzzle/src/org/opencv/samples/puzzle15/puzzle15Activity.java b/samples/android/15-puzzle/src/org/opencv/samples/puzzle15/puzzle15Activity.java
new file mode 100644
index 000000000..2444f5755
--- /dev/null
+++ b/samples/android/15-puzzle/src/org/opencv/samples/puzzle15/puzzle15Activity.java
@@ -0,0 +1,50 @@
+package org.opencv.samples.puzzle15;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.Window;
+
+public class puzzle15Activity extends Activity {
+ private static final String TAG = "Sample::Activity";
+
+ private MenuItem mItemNewGame;
+ private MenuItem mItemToggleNumbers;
+ private puzzle15View mView;
+
+ public puzzle15Activity() {
+ Log.i(TAG, "Instantiated new " + this.getClass());
+ }
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ mView = new puzzle15View(this);
+ setContentView(mView);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ Log.i(TAG, "onCreateOptionsMenu");
+ mItemNewGame = menu.add("Start new game");
+ mItemToggleNumbers = menu.add("Show/hide tile numbers");
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ Log.i(TAG, "Menu Item selected " + item);
+ if (item == mItemNewGame) {
+ synchronized (mView) {
+ mView.startNewGame();
+ }
+ } else if (item == mItemToggleNumbers)
+ mView.tolggleTileNumbers();
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/samples/android/15-puzzle/src/org/opencv/samples/puzzle15/puzzle15View.java b/samples/android/15-puzzle/src/org/opencv/samples/puzzle15/puzzle15View.java
new file mode 100644
index 000000000..1f6abbc27
--- /dev/null
+++ b/samples/android/15-puzzle/src/org/opencv/samples/puzzle15/puzzle15View.java
@@ -0,0 +1,221 @@
+package org.opencv.samples.puzzle15;
+
+import org.opencv.*;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.view.MotionEvent;
+import android.view.SurfaceHolder;
+import android.view.View;
+import android.view.View.OnTouchListener;
+
+public class puzzle15View extends SampleViewBase implements OnTouchListener {
+ private Mat mRgba;
+ private Mat mRgba15;
+ private Mat[] mCells;
+ private Mat[] mCells15;
+ private int[] mIndexses;
+ private int[] mTextWidths;
+ private int[] mTextHeights;
+ private boolean mShowTileNumbers = true;
+
+ int gridSize = 4;
+ int gridArea = gridSize * gridSize;
+ int gridEmptyIdx = gridArea - 1;
+
+ public puzzle15View(Context context) {
+ super(context);
+ setOnTouchListener(this);
+
+ mTextWidths = new int[gridArea];
+ mTextHeights = new int[gridArea];
+ for (int i = 0; i < gridArea; i++) {
+ Size s = core.getTextSize(Integer.toString(i + 1), 3/* CV_FONT_HERSHEY_COMPLEX */, 1, 2, null);
+ mTextHeights[i] = (int) s.height;
+ mTextWidths[i] = (int) s.width;
+ }
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
+ super.surfaceChanged(_holder, format, width, height);
+ synchronized (this) {
+ // initialize Mat before usage
+ mRgba = new Mat();
+ }
+ }
+
+ public static void shuffle(int[] array) {
+ for (int i = array.length; i > 1; i--) {
+ int temp = array[i - 1];
+ int randIx = (int) (Math.random() * i);
+ array[i - 1] = array[randIx];
+ array[randIx] = temp;
+ }
+ }
+
+ public boolean isPuzzleSolvable() {
+ if (gridSize != 4)
+ return true;
+
+ int sum = 0;
+ for (int i = 0; i < gridArea; i++) {
+ if (mIndexses[i] == gridEmptyIdx)
+ sum += (i / gridSize) + 1;
+ else {
+ int smaller = 0;
+ for (int j = i + 1; j < gridArea; j++) {
+ if (mIndexses[j] < mIndexses[i])
+ smaller++;
+ }
+ sum += smaller;
+ }
+ }
+
+ return sum % 2 == 0;
+ }
+
+ private void createPuzzle(int cols, int rows) {
+ mCells = new Mat[gridArea];
+ mCells15 = new Mat[gridArea];
+
+ mRgba15 = new Mat(rows, cols, mRgba.type());
+ mIndexses = new int[gridArea];
+
+ for (int i = 0; i < gridSize; i++) {
+ for (int j = 0; j < gridSize; j++) {
+ int k = i * gridSize + j;
+ mIndexses[k] = k;
+ mCells[k] = mRgba.submat(i * rows / gridSize, (i + 1) * rows / gridSize, j * cols / gridSize, (j + 1) * cols / gridSize);
+ mCells15[k] = mRgba15.submat(i * rows / gridSize, (i + 1) * rows / gridSize, j * cols / gridSize, (j + 1) * cols / gridSize);
+ }
+ }
+
+ startNewGame();
+ }
+
+ public void startNewGame() {
+ do {
+ shuffle(mIndexses);
+ } while (!isPuzzleSolvable());
+ }
+
+ public void tolggleTileNumbers() {
+ mShowTileNumbers = !mShowTileNumbers;
+ }
+
+ @Override
+ protected Bitmap processFrame(VideoCapture capture) {
+ capture.retrieve(mRgba, highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
+ int cols = mRgba.cols();
+ int rows = mRgba.rows();
+
+ if (mCells == null)
+ createPuzzle(cols, rows);
+
+ // copy shuffled tiles
+ for (int i = 0; i < gridArea; i++) {
+ int idx = mIndexses[i];
+ if (idx == gridEmptyIdx)
+ mCells15[i].setTo(new Scalar(0x33, 0x33, 0x33, 0xFF));
+ else {
+ mCells[idx].copyTo(mCells15[i]);
+ if (mShowTileNumbers) {
+ core.putText(mCells15[i], Integer.toString(1 + idx), new Point((cols / gridSize - mTextWidths[idx]) / 2,
+ (rows / gridSize + mTextHeights[idx]) / 2), 3/* CV_FONT_HERSHEY_COMPLEX */, 1, new Scalar(255, 0, 0, 255), 2);
+ }
+ }
+ }
+
+ drawGrid(cols, rows);
+
+ Bitmap bmp = Bitmap.createBitmap(cols, rows, Bitmap.Config.ARGB_8888);
+ if (android.MatToBitmap(mRgba15, bmp))
+ return bmp;
+
+ bmp.recycle();
+ return null;
+ }
+
+ private void drawGrid(int cols, int rows) {
+ for (int i = 1; i < gridSize; i++) {
+ core.line(mRgba15, new Point(0, i * rows / gridSize), new Point(cols, i * rows / gridSize), new Scalar(0, 255, 0, 255), 3);
+ core.line(mRgba15, new Point(i * cols / gridSize, 0), new Point(i * cols / gridSize, rows), new Scalar(0, 255, 0, 255), 3);
+ }
+ }
+
+ @Override
+ public void run() {
+ super.run();
+
+ synchronized (this) {
+ // Explicitly deallocate Mats
+ if (mCells != null) {
+ for (Mat m : mCells)
+ m.dispose();
+ }
+ if (mCells15 != null) {
+ for (Mat m : mCells15)
+ m.dispose();
+ }
+ if (mRgba != null)
+ mRgba.dispose();
+ if (mRgba15 != null)
+ mRgba15.dispose();
+
+ mRgba = null;
+ mRgba15 = null;
+ mCells = null;
+ mCells15 = null;
+ mIndexses = null;
+ }
+ }
+
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ int cols = mRgba.cols();
+ int rows = mRgba.rows();
+ float xoffset = (getWidth() - cols) / 2;
+ float yoffset = (getHeight() - rows) / 2;
+
+ float x = event.getX() - xoffset;
+ float y = event.getY() - yoffset;
+
+ int row = (int) Math.floor(y * gridSize / rows);
+ int col = (int) Math.floor(x * gridSize / cols);
+
+ if (row < 0 || row >= gridSize || col < 0 || col >= gridSize)
+ return false;
+
+ int idx = row * gridSize + col;
+ int idxtoswap = -1;
+
+ // left
+ if (idxtoswap < 0 && col > 0)
+ if (mIndexses[idx - 1] == gridEmptyIdx)
+ idxtoswap = idx - 1;
+ // right
+ if (idxtoswap < 0 && col < gridSize - 1)
+ if (mIndexses[idx + 1] == gridEmptyIdx)
+ idxtoswap = idx + 1;
+ // top
+ if (idxtoswap < 0 && row > 0)
+ if (mIndexses[idx - gridSize] == gridEmptyIdx)
+ idxtoswap = idx - gridSize;
+ // bottom
+ if (idxtoswap < 0 && row < gridSize - 1)
+ if (mIndexses[idx + gridSize] == gridEmptyIdx)
+ idxtoswap = idx + gridSize;
+
+ // swap
+ if (idxtoswap >= 0) {
+ synchronized (this) {
+ int touched = mIndexses[idx];
+ mIndexses[idx] = mIndexses[idxtoswap];
+ mIndexses[idxtoswap] = touched;
+ }
+ }
+
+ return false;// don't need subsequent touch events
+ }
+}
diff --git a/samples/android/tutorial-2-opencvcamera/src/org/opencv/samples/tutorial2/SampleViewBase.java b/samples/android/tutorial-2-opencvcamera/src/org/opencv/samples/tutorial2/SampleViewBase.java
index 2f5c03ae3..472584453 100644
--- a/samples/android/tutorial-2-opencvcamera/src/org/opencv/samples/tutorial2/SampleViewBase.java
+++ b/samples/android/tutorial-2-opencvcamera/src/org/opencv/samples/tutorial2/SampleViewBase.java
@@ -16,7 +16,6 @@ public abstract class SampleViewBase extends SurfaceView implements SurfaceHolde
private SurfaceHolder mHolder;
private VideoCapture mCamera;
- private boolean mThreadRun;
public SampleViewBase(Context context) {
super(context);
@@ -27,27 +26,29 @@ public abstract class SampleViewBase extends SurfaceView implements SurfaceHolde
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
Log.i(TAG, "surfaceCreated");
- if (mCamera != null && mCamera.isOpened()) {
- Log.i(TAG, "before mCamera.getSupportedPreviewSizes()");
- List sizes = mCamera.getSupportedPreviewSizes();
- Log.i(TAG, "after mCamera.getSupportedPreviewSizes()");
- int mFrameWidth = width;
- int mFrameHeight = height;
+ synchronized (this) {
+ if (mCamera != null && mCamera.isOpened()) {
+ Log.i(TAG, "before mCamera.getSupportedPreviewSizes()");
+ List sizes = mCamera.getSupportedPreviewSizes();
+ Log.i(TAG, "after mCamera.getSupportedPreviewSizes()");
+ int mFrameWidth = width;
+ int mFrameHeight = height;
- // selecting optimal camera preview size
- {
- double minDiff = Double.MAX_VALUE;
- for (Size size : sizes) {
- if (Math.abs(size.height - height) < minDiff) {
- mFrameWidth = (int) size.width;
- mFrameHeight = (int) size.height;
- minDiff = Math.abs(size.height - height);
+ // selecting optimal camera preview size
+ {
+ double minDiff = Double.MAX_VALUE;
+ for (Size size : sizes) {
+ if (Math.abs(size.height - height) < minDiff) {
+ mFrameWidth = (int) size.width;
+ mFrameHeight = (int) size.height;
+ minDiff = Math.abs(size.height - height);
+ }
}
}
- }
- mCamera.set(highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth);
- mCamera.set(highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight);
+ mCamera.set(highgui.CV_CAP_PROP_FRAME_WIDTH, mFrameWidth);
+ mCamera.set(highgui.CV_CAP_PROP_FRAME_HEIGHT, mFrameHeight);
+ }
}
}
@@ -65,7 +66,6 @@ public abstract class SampleViewBase extends SurfaceView implements SurfaceHolde
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i(TAG, "surfaceDestroyed");
- mThreadRun = false;
if (mCamera != null) {
synchronized (this) {
mCamera.release();
@@ -77,17 +77,19 @@ public abstract class SampleViewBase extends SurfaceView implements SurfaceHolde
protected abstract Bitmap processFrame(VideoCapture capture);
public void run() {
- mThreadRun = true;
Log.i(TAG, "Starting processing thread");
- while (mThreadRun) {
+ while (true) {
Bitmap bmp = null;
- if (!mCamera.grab()) {
- Log.e(TAG, "mCamera.grab() failed");
- break;
- }
-
synchronized (this) {
+ if (mCamera == null)
+ break;
+
+ if (!mCamera.grab()) {
+ Log.e(TAG, "mCamera.grab() failed");
+ break;
+ }
+
bmp = processFrame(mCamera);
}
@@ -100,5 +102,7 @@ public abstract class SampleViewBase extends SurfaceView implements SurfaceHolde
bmp.recycle();
}
}
+
+ Log.i(TAG, "Finishing processing thread");
}
}
\ No newline at end of file