简体   繁体   English

Android Camera2 API和EXIF

[英]Android camera2 api and exif

I am experimenting with the camera2 api and I have made an app that can take an a photo from the camera. 我正在尝试使用camera2 api并且制作了可以从相机拍摄照片的应用程序。 Now I want to add exif data to the captured image. 现在,我想将exif数据添加到捕获的图像中。 I have a question on where or how to put the exif information . 我对在哪里或如何放置exif information有疑问。

Should I create an Exif interface in the onCaptureCompleted() function or what is the best way to do it? 我应该在onCaptureCompleted()函数中创建Exif接口还是最好的方法?

final CameraCaptureSession.CaptureCallback captureListener = new CameraCaptureSession.CaptureCallback() {

    @Override
    public void onCaptureCompleted(CameraCaptureSession session,
                                   CaptureRequest request, TotalCaptureResult result) {

        super.onCaptureCompleted(session, request, result);
        Toast.makeText(MainActivity.this, "Saved:"+file, Toast.LENGTH_SHORT).show();


        ExifInterface exifTags = null;
        try {
            exifTags = new ExifInterface(file.getCanonicalPath());

            exifTags.setAttribute(ExifInterface.TAG_GPS_LATITUDE, Double.toString(cur_lat));
            exifTags.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, Double.toString(cur_long));

            exifTags.saveAttributes();

        } catch (IOException e) {
            e.printStackTrace();
        }
        //System.out.println(file.getCanonicalPath());
        System.out.println("Exif Test: " + Double.toString(cur_lat) + " " + Double.toString(cur_lat));

    }

};

When I do this I get an error: 当我这样做时,我得到一个错误:

"ImageReader_JNI﹕ Unable to acquire a lockedBuffer, very likely client tries to lock more than maxImages buffers" “ ImageReader_JNI:无法获取lockedBuffer,很可能客户端尝试锁定的对象超过了maxImages的缓冲区”

What is the best way to do this? 做这个的最好方式是什么? Any suggestion would be very helpful. 任何建议都将非常有帮助。

What image format you try to capture? 您尝试捕获什么图像格式? If JPEG, then all Exif tags are should be already written in image. 如果为JPEG,则所有Exif标签都应已写入图像中。 The result image is delivered in OnImageAvailableListener.onImageAvailable(), not in CameraCaptureSession. 结果图像通过OnImageAvailableListener.onImageAvailable()而不是CameraCaptureSession中传递。 onCaptureCompleted(). onCaptureCompleted()。 Try to add your custom tags in onImageAvailable method. 尝试在onImageAvailable方法中添加自定义标签。

EDIT: 编辑:

@Override
    public void onImageAvailable(ImageReader reader) {
        Log.e("TAG", System.currentTimeMillis() + "");
        Image mImage = reader.acquireNextImage();
        ByteBuffer buffer = mImage.getPlanes()[0].getBuffer();
        byte[] bytes = new byte[buffer.remaining()];
        buffer.get(bytes);
        FileOutputStream output = null;
        try {
            output = new FileOutputStream(mFile);
            output.write(bytes);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            mImage.close();
            if (null != output) {
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        try {
            ExifInterface exif = new ExifInterface(mFile.getAbsolutePath());
            exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, "10");
            exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, "10");
            exif.saveAttributes();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

hi you can save Exif to image on Imageavaliable like this 嗨,您可以像这样将Exif保存到Imageavaliable上的图像

this on image avaliable : 在图像上可用:

 @Override
    public void onImageAvailable(ImageReader reader) {
        try {
            if (latitude == null || longitude == null){
                imageview.setVisibility(View.GONE);
                /*deleteImage(file.getPath());*/





                Toast.makeText(ShotActivity_camera2API.this,"Waiting.. try to get location result.",Toast.LENGTH_LONG).show();
                //get location
                myLocation.getLocation(ShotActivity_camera2API.this,locationResult);
                return;
            }else {

                File dir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM), "Image Project");
                if (!dir.exists())
                    dir.mkdir();

                file = new File(dir, currentDate + ".jpg");
                Image image = reader.acquireNextImage();
                ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                byte[] bytes = new byte[buffer.remaining()];
                buffer.get(bytes);


                try {
                    saveMetaData(file);
                } catch (IOException e) {
                    e.printStackTrace();
                }


                saveImageFile(bytes);
                /*mBackgroundHandler.post(new ImageSaver(reader.acquireLatestImage(),file));*/


                //close image to fix crash second time capture
                image.close();

            }
        } catch (Exception e) {
            e.printStackTrace();
        } /*catch (IOException e) {
            e.printStackTrace();
        }*/
    }

this method to save Exiv : 这种保存Exiv的方法:

private void saveMetaData(File file) throws IOException {
    ExifInterface exif = new ExifInterface(file.getCanonicalPath());
    Log.e(TAG,""+file.getAbsolutePath());
    //add Latitude to metadata
    exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, gpsParse.convert(latitude));
    exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, gpsParse.latitudeRef(latitude));
    exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, gpsParse.convert(longitude));
    exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, gpsParse.longitudeRef(longitude));
    exif.saveAttributes();
    Log.i(TAG, "" + latitude + "," + longitude);
    Log.i(TAG, "" + gpsParse.convert(latitude) + "," + gpsParse.longitudeRef(longitude));
    Log.i(TAG, "" + gpsParse.latitudeRef(latitude) + "," + gpsParse.longitudeRef(longitude));
}

and this my GPS parse latitude longitude to Exif : 这是我的GPS将纬度经度解析为Exif:

package com.example.PT107.task107_imagesqilte.Helper;

public class gpsParse { private static StringBuilder sb = new StringBuilder(20); 公共类gpsParse {私有静态StringBuilder sb = new StringBuilder(20);

/**
 * returns ref for latitude which is S or N.
 * @param latitude
 * @return S or N
 */
public static String latitudeRef(double latitude) {
    return latitude<0.0d?"S":"N";
}


public static String longitudeRef(double longitude) {
    return longitude<0.0d?"W":"E";
}

/**
 * convert latitude into DMS (degree minute second) format. For instance<br/>
 * -79.948862 becomes<br/>
 *  79/1,56/1,55903/1000<br/>
 * It works for latitude and longitude<br/>
 * @param latitude could be longitude.
 * @return
 */
synchronized public static final String convert(double latitude) {
    latitude=Math.abs(latitude);
    int degree = (int) latitude;
    latitude *= 60;
    latitude -= (degree * 60.0d);
    int minute = (int) latitude;
    latitude *= 60;
    latitude -= (minute * 60.0d);
    int second = (int) (latitude*1000.0d);

    sb.setLength(0);
    sb.append(degree);
    sb.append("/1,");
    sb.append(minute);
    sb.append("/1,");
    sb.append(second);
    sb.append("/1000,");
    return sb.toString();
}

} }

i hope this help someone :) 我希望这可以帮助某人:)

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

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