I’m trying the openCV sample on Android. When I’m trying to save a bmp file to my SDcard every thread using following code:
String filePath = "/sdcard"; // some times it may be only /sdcard not /mnt/sdcard
filePath += "newFileName.jpg";
try {
bmp.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File(filePath)));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.i(TAG, "IOException Occurred!!!");
}
The log always shows up “IOException Occurred” and no file have been saved on SDcard.
The full class code is below
public abstract class SampleCvViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
private static final String TAG = "Sample::SurfaceView";
private SurfaceHolder mHolder;
private VideoCapture mCamera;
private FpsMeter mFps;
public SampleCvViewBase(Context context) {
super(context);
mHolder = getHolder();
mHolder.addCallback(this);
mFps = new FpsMeter();
Log.i(TAG, "Instantiated new " + this.getClass());
}
public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {//called immediately after the structural change of surface
Log.i(TAG, "surfaceCreated");
synchronized (this) {
if (mCamera != null && mCamera.isOpened()) {
Log.i(TAG, "before mCamera.getSupportedPreviewSizes()");
List<Size> 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(); //new thread
} 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) throws IOException;
public void run() {
Log.i(TAG, "Starting processing thread"); //send out log notice
mFps.init(); //instance of Fps meter
while (true) {
Bitmap bmp = null;
synchronized (this) {
if (mCamera == null) //instance of video capture
break;
if (!mCamera.grab()) {
Log.e(TAG, "mCamera.grab() failed");
break;
}
try {
bmp = processFrame(mCamera);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mFps.measure();
}
if (bmp != null) {
Canvas canvas = mHolder.lockCanvas();
if (canvas != null) {
canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth()) / 2, (canvas.getHeight() - bmp.getHeight()) / 2, null);
mFps.draw(canvas, (canvas.getWidth() - bmp.getWidth()) / 2, 0);
mHolder.unlockCanvasAndPost(canvas);
}
String filePath = "/sdcard"; // some times it may be only /sdcard not /mnt/sdcard
filePath += "newFileName.jpg";
try {
bmp.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(new File(filePath)));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Log.i(TAG, "IOExcpetion Occurred!!!");
}
}
Here is what I’ve got in DDMS:
03-07 08:58:11.639: W/TextLayoutCache(986): computeValuesWithHarfbuzz -- need to force to single run
03-07 08:58:11.709: W/System.err(986): java.io.FileNotFoundException: /sdcardnewFileName.jpg: open failed: EROFS (Read-only file system)
03-07 08:58:11.769: W/System.err(986): at libcore.io.IoBridge.open(IoBridge.java:406)
03-07 08:58:11.769: W/System.err(986): at java.io.FileOutputStream.<init>(FileOutputStream.java:88)
03-07 08:58:11.809: W/System.err(986): at java.io.FileOutputStream.<init>(FileOutputStream.java:73)
03-07 08:58:11.829: W/System.err(986): at org.opencv.samples.fd.SampleCvViewBase.run(SampleCvViewBase.java:125)
03-07 08:58:11.829: W/System.err(986): at org.opencv.samples.fd.FdView.run(FdView.java:107)
03-07 08:58:11.829: W/System.err(986): at java.lang.Thread.run(Thread.java:856)
03-07 08:58:11.829: W/System.err(986): Caused by: libcore.io.ErrnoException: open failed: EROFS (Read-only file system)
03-07 08:58:11.859: W/System.err(986): at libcore.io.Posix.open(Native Method)
03-07 08:58:11.859: W/System.err(986): at libcore.io.BlockGuardOs.open(BlockGuardOs.java:98)
03-07 08:58:11.889: W/System.err(986): at libcore.io.IoBridge.open(IoBridge.java:390)
03-07 08:58:11.889: W/System.err(986): ... 5 more
03-07 08:58:11.919: I/Sample::SurfaceView(986): IOExcpetion Occurred!!!
03-07 08:58:12.489: D/dalvikvm(986): GC_FOR_ALLOC freed 1209K, 14% free 9902K/11399K, paused 29ms
03-07 08:58:12.489: I/dalvikvm-heap(986): Grow heap (frag case) to 10.925MB for 1228816-byte allocation
03-07 08:58:12.619: D/dalvikvm(986): GC_CONCURRENT freed <1K, 3% free 11102K/11399K, paused 3ms+45ms
I’m trying to save one bmp image as soon as the detection has completed once. Can anyone help me?Thank you
You are trying to write into the filesystem root because you missed a forward slash in your file path: You use
/sdcardnewFileName.jpginstead of/sdcard/newFileName.jpg.But you got no permission to write there, so you get an exception.
Also: Please don’t hardcode the path to the SD-card like this at all. Instead use
Environment.getExternalStorageDirectory(). Some devices mount the card on a different path or have flash memory instead. This method always returns the correct path. If you don’t do this, you will run into problems when using your app across multiple devices.