Android 相机 2 api 和 exif

Android camera2 api and exif

我正在试验 camera2 api 并且我制作了一个可以从相机拍摄照片的应用程序。现在我想将 exif 数据添加到捕获的图像中。我对 exif information 放在哪里或如何放有疑问。

我应该在 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));

    }

};

执行此操作时出现错误:

"ImageReader_JNI﹕ Unable to acquire a lockedBuffer, very likely client tries to lock more than maxImages buffers"

最好的方法是什么?任何建议都会很有帮助。

您尝试捕获什么图像格式?如果是 JPEG,那么所有的 Exif 标签都应该已经写在图像中了。 结果图像在 OnImageAvailableListener.onImageAvailable() 中传递,而不是在 CameraCaptureSession 中传递。 onCaptureCompleted()。 尝试在 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();
        }

    }

您好,您可以像这样将 Exif 保存到 Imageavaliable 上的图像

此图片可用:

 @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();
        }*/
    }

此方法保存 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));
}

这是我的 GPS 将经纬度解析为 Exif:

package com.example.PT107.task107_imagesqilte.Helper;

public class 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();
}

}

我希望这对某人有所帮助:)