简体   繁体   English

从线程将bmp图像保存到SD卡

[英]Saving an bmp image to SD card from thread

I'm trying the openCV sample on Android. 我正在尝试在Android上使用openCV示例。 When I'm trying to save a bmp file to my SDcard every thread using following code: 当我尝试使用以下代码将bmp文件保存到我的SD卡时,每个线程:

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. 日志始终显示“ IOException Occurred”,并且没有文件保存在SD卡上。

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: 这是我在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. 一旦检测完成,我正在尝试保存一张bmp图像。 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.jpg instead of /sdcard/newFileName.jpg . 您正在尝试写入文件系统根目录,因为您在文件路径中错过了正斜杠:您使用/sdcardnewFileName.jpg而不是/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. 另外:请完全不要这样硬编码SD卡的路径。 Instead use Environment.getExternalStorageDirectory() . 而是使用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. 如果不这样做,则在跨多个设备使用应用程序时会遇到问题。

1/ you lack a slash in your path. 1 /您的道路上没有斜线。

2/ that is not the proper way of finding the sdcard path and creating a file on it: http://developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory%28%29 2 /这不是查找sdcard路径并在其上创建文件的正确方法: http : //developer.android.com/reference/android/os/Environment.html#getExternalStorageDirectory%28%29

File root = Environment.getExternalStorageDirectory();
File imgFile = new File(root, "newFileName.jpg");
FileOutputStream fos = new FileOutputStream(imgFile);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM