moleculeone
moleculeone

Reputation: 221

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. Now I want to add exif data to the captured image. I have a question on where or how to put the exif information.

Should I create an Exif interface in the onCaptureCompleted() function or what is the best way to do it?

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"

What is the best way to do this? Any suggestion would be very helpful.

Upvotes: 2

Views: 5049

Answers (2)

Yudi karma
Yudi karma

Reputation: 324

hi you can save Exif to image on Imageavaliable like this

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 :

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 :

package com.example.PT107.task107_imagesqilte.Helper;

public class gpsParse { private static 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 :)

Upvotes: 0

Maxim Metelskiy
Maxim Metelskiy

Reputation: 1389

What image format you try to capture? If JPEG, then all Exif tags are should be already written in image. The result image is delivered in OnImageAvailableListener.onImageAvailable(), not in CameraCaptureSession. onCaptureCompleted(). Try to add your custom tags in onImageAvailable method.

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

    }

Upvotes: 2

Related Questions