玻璃-慢速摄像头\ FileObserver通知-XE12-使用ACTION_IMAGE_CAPTURE [英] Glass - Slow camera \ FileObserver notification - XE12 - using ACTION_IMAGE_CAPTURE

查看:53
本文介绍了玻璃-慢速摄像头\ FileObserver通知-XE12-使用ACTION_IMAGE_CAPTURE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我基本上已经实现了新的XE12 \ GDK2 cameramanager示例代码,以在应用程序启动时捕获图像.但是,到FileObserver回调的通知需要3到30秒的时间来获取创建映像文件的通知.使用默认的拍照"应用程序拍照可以正常工作,因此我不认为这是操作系统\更新问题. 我的应用程序的行为类似于: -拍照 -点击接受 等待3到30秒 -获取回调,然后使用捕获的图像更新imageview.

I have basically implemented the new XE12\GDK2 cameramanager sample code to capture an image on application start. However, the notification to the FileObserver callback takes anywhere from 3 to 30 seconds to get the notification of the image file creation. Taking a picture using the default 'Take a Picture' app works just fine so I dont thin it is an OS\update issue. My app's behavior is like: - Take the picture - Tap to accept Wait 3 to 30 seconds - Get the callback and the imageview is updated with the captured image.

我认为我没有修改GDK 2.0相机教程中提供的示例代码的一行.所以想知道我在想什么.

I dont think I have modified a single line of the sample code provided in the GDK 2.0 camera tutorial. So wondering what I am missing.

我已附上以下代码的相关部分.任何提示\指针都表示赞赏.

I have attached the relevant section of the code below. Any tips\pointers highly appreciated.

@Override
protected void onStart() {
    super.onStart();
     Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
       // String path = Environment.getExternalStorageDirectory().getPath();

        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE);
        }       
}


private void processPictureWhenReady(final String picturePath) {

        final File pictureFile = new File(picturePath);

           if (pictureFile.exists()) {
           // The picture is ready; process it. Takes 3-30 seconds to get here!
               try {

                Bitmap imageBitmap = BitmapFactory.decodeFile(picturePath);
                int w = imageBitmap.getWidth();
                int h = imageBitmap.getHeight();       

         Bitmap bm2 = Bitmap.createScaledBitmap(imageBitmap, w/2, h/2, true);

                imageBitmap = bm2.copy(bm2.getConfig(), true);
                //m_ImageView.setImageBitmap(bm2);


               } catch (Exception e) {
                   Log.e("Exc", e.getMessage()); 
               }

            } else {
                tm = System.currentTimeMillis();
                // The file does not exist yet. Before starting the file observer, you
                // can update your UI to let the user know that the application is
                // waiting for the picture (for example, by displaying the thumbnail
                // image and a progress indicator).

                final File parentDirectory = pictureFile.getParentFile();
                FileObserver observer = new FileObserver(parentDirectory.getPath()) {
                    // Protect against additional pending events after CLOSE_WRITE is
                    // handled.
                    private boolean isFileWritten;

                    @Override
                    public void onEvent(int event, String path) {
                        if (!isFileWritten) {
                            // For safety, make sure that the file that was created in
                            // the directory is actually the one that we're expecting.
                            File affectedFile = new File(parentDirectory, path);
                            isFileWritten = (event == FileObserver.CLOSE_WRITE
                                    && affectedFile.equals(pictureFile));

                            if (isFileWritten) {
                                stopWatching();

                                // Now that the file is ready, recursively call
                                // processPictureWhenReady again (on the UI thread).
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        processPictureWhenReady(picturePath);
                                    }
                                });
                            }
                        }
                    }
                };
                observer.startWatching();

            }
    }

推荐答案

回答我自己的问题-尽管我得到了詹妮·墨菲(Jenny Murphy)和约翰·费格(John Feig)的澄清:-).希望它可以帮助其他人.

Answering my own question - though I got the clarifications from Jenny Murphy and John Feig :-). Hopefully it helps others.

首先,为什么使用GDK指南中的示例代码进行图像捕获如此缓慢: 这是预期的行为. Glass摄影机的意图(ACTION_IMAGE_CAPTURE)对捕获的图像执行大量专有的后处理-自动HDR等,这需要时间.通过仅显示预览图像(可立即使用),在拍摄照片"命令中巧妙地掩盖了这一点.作为证明,请尝试查找您刚刚在时间轴中拍摄的图像.几秒钟后您将看不到它(根据我的经验,平均大约是8秒钟.). 坦白说,除非您能仅获取预览图像,否则在大多数应用程序中,摄像头的意图可能不是很有用.

To the first point - why is image capture using the sample code from the GDK guide so slow: This is the expected behavior. The Glass camera intent (ACTION_IMAGE_CAPTURE) performs a ton of proprietary post-processing on the captured image - auto-HDR etc which takes time. This is cleverly disguised in the 'Take a picture' command by only displaying the preview image (which is available immediately.). As proof, try to find the image you just took in your time-line. You will not see it for several seconds (around 8 seconds on average in my experience.). Frankly, unless you are ok just grabbing the preview image, the camera intent may not be very useful in most apps.

解决方案是直接使用默认Android API来使用Camera.为了方便起见,我粘贴了这段代码的片段.如果对您中的大多数人来说是基本的话,请原谅.许多代码是从 John Feig在GitHub上的GIFCamera玻璃器皿复制的

The solution is to use the Camera directly using default Android APIs. For convenience, I have pasted a snippet of this code. Please excuse if it is kind of basic for many of you. A lot of the code is copied from John Feig's GIFCamera glassware on GitHub

activity_main布局包含一个名为Preview的SurfaceView

<SurfaceView
    android:id="@+id/preview"
    android:layout_width="500dp"
    android:layout_height="500dp"       
    android:layout_alignParentTop="true"
    android:layout_marginTop="20dp"
     />

MainActivity.java

public class MainActivity extends Activity implements PhotoCallback {
public byte[] m_jpg = null;
Camera cam = null;      
SurfaceHolder m_sh;

 private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {

        @Override
        public void surfaceCreated(SurfaceHolder hldr) {
            m_sh = hldr;                
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {               
            myCapHandler2(); //Start Camera Preview etc.
        }
    };

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);         
    setContentView(R.layout.activity_main);     
    SurfaceView preview = (SurfaceView) findViewById(R.id.preview);     
    preview.getHolder().addCallback(mSurfaceHolderCallback);
}

public void myCapHandler2() {
        //open camera
        try {           
        cam = Camera.open(0);

        Camera.Parameters params = cam.getParameters();
        List<Size> sizes = params.getSupportedPreviewSizes();
        params.setJpegQuality(90);          
        params.setPreviewFpsRange(30000, 30000);            
        params.setPictureSize(sizes.get(1).width, sizes.get(1).height);
        params.setPreviewSize(sizes.get(1).width, sizes.get(1).height);
        cam.setParameters(params);

         try {
                 cam.setPreviewDisplay(m_sh);
                } 
                catch (IOException e) {
                    e.printStackTrace();
            }

            // Important: Call startPreview() to start updating the preview
            // surface. Preview must be started before you can take a picture.
         cam.startPreview();

         cam.takePicture(null, null,
                    new PhotoHandler(this));

        } catch (Exception e) {

            if (null != cam) { 
                cam.stopPreview(); 
                cam.release();
                }
            }
    }   

@Override
public void pictureTaken(byte[] jpg) {
    m_jpg = jpg;

    //Picture captured - release the camera for other apps
    cam.stopPreview();
    cam.release();      
}

@Override
public void onPause() {
    if (null != cam) { 
        cam.stopPreview(); 
        cam.release();
        }
}

@Override
public void onDestroy() {
if (null != cam) { 
    cam.stopPreview(); 
    cam.release();
    }
 }
}

PhotoHandler.java

import android.hardware.Camera;
import android.os.AsyncTask;



public class PhotoHandler implements Camera.PictureCallback {


private PhotoCallback photoCallback;

public PhotoHandler(PhotoCallback photoCallback) {
    super();
    this.photoCallback = photoCallback;
}

@Override
public void onPictureTaken(byte[] data, Camera camera) {

    new ProcessCapturedImage().execute(data);
}

private class ProcessCapturedImage extends AsyncTask<byte[], Void, byte[]> {

      @Override
      protected byte[] doInBackground(byte[]... params) {           

          if (null == params || null == params[0])
              return null;

          return params[0];

      }

    @Override
    protected void onPostExecute(byte[] params) {
        photoCallback.pictureTaken(params);
    }
}

}

PhotoCallback.java

public interface PhotoCallback {
public void pictureTaken(byte[] jpg);
}

最好用相机玻璃器皿.

这篇关于玻璃-慢速摄像头\ FileObserver通知-XE12-使用ACTION_IMAGE_CAPTURE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆