写/地理标记JPEG文件(EXIF数据)的Andr​​oid标记、地理、文件、数据

2023-09-12 08:53:29 作者:凉了时光病了心

我想要做的: 拍照用我自己的PictureActivity *,并添加EXIF(地理标记)的数据 *:实施 SurfaceHolder.Callback 和使用摄像机

What I want to do: Take a picture using my own PictureActivity* and add EXIF (geotags) data *: Implementing SurfaceHolder.Callbackand using Camera

什么是不工作: 添加EXIF GPS数据。

What is not working: Adding the EXIF GPS data

我已经试过: 使用 ExifInterface 和手动设置 Camera.Parameters (均与设置GPS的元数据,以及使用的具体方法 params.set(字符串,值))。

What I've tried: Using the ExifInterface and manually setting Camera.Parameters (both with the specific methods for setting GPS meta-data and by using params.set(String, Value)).

我用FlickrJ(是的,我给自己定的Flickr导入GPS数据 - 其他的图片做工精细)上传图片到Flickr,但是这个工具还表示,没有在EXIF没有GPS数据:的 http://regex.info/exif.cgi

I'm uploading the pictures to Flickr using FlickrJ (yes, I've set Flickr to import GPS data -- other pictures work fine), however this tool also says there is no GPS data in the EXIF: http://regex.info/exif.cgi

我在想什么?

(Android 2.2系统,HTC Desire的)

(Android 2.2, HTC Desire)

编辑: - 将相机设置为地理标记照片: - 我已经试过用硬codeD虚拟GPS位置

- The camera is set to Geotag photos: On - I've tried with hardcoded dummy GPS positions

下面是code手动设置参数(有和没有首先去除GPS数据用尽全力,并与提到还设置(字符串,值) ):

Here is the code for manually setting parameters (tried both with and without first removing the GPS data, and as mentioned also with set(String, Value)):

@Override
public void surfaceCreated(SurfaceHolder holder) {
    mCamera = Camera.open();    

    Camera.Parameters p = mCamera.getParameters();
    p.setPreviewSize(p.getPreviewSize().width, p.getPreviewSize().height);
    Log.e("PictureActivity", "EXIF: "+AGlanceLocationListener.getLatitude());
    p.removeGpsData();
    p.setGpsLatitude( AGlanceLocationListener.getLatitude() );
    p.setGpsLongitude( AGlanceLocationListener.getLongitude() );
    p.setGpsAltitude( AGlanceLocationListener.getAltitude() );
    p.setGpsTimestamp( AGlanceLocationListener.getTime() );
    mCamera.setParameters(p);
}

下面是$ C $下使用 ExifInterface

Here is the code for using the ExifInterface:

//Save EXIF location data to JPEG
ExifInterface exif;
try {
    exif = new ExifInterface("/sdcard/DCIM/"+filename+".jpeg");
    exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE,
        String.valueOf(AGlanceLocationListener.getLatitude()));

    exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, 
        String.valueOf(AGlanceLocationListener.getLongitude()));

    exif.saveAttributes();

} catch (IOException e) {
    Log.e("PictureActivity", e.getLocalizedMessage());
}

下面是code编写的JPEG文件到SD卡:

Here is the code for writing the JPEG file to the SDCARD:

Camera.PictureCallback jpegCallback = new Camera.PictureCallback() {
    public void onPictureTaken(byte[] imageData, Camera c) 
    {
        //      Bitmap pic = BitmapFactory.decodeByteArray(imageData, 0, imageData.length);

        String day = String.valueOf(Calendar.getInstance().getTime().getDay());
        String hour = String.valueOf(Calendar.getInstance().getTime().getHours());
        String minute = String.valueOf(Calendar.getInstance().getTime().getMinutes());
        String second = String.valueOf(Calendar.getInstance().getTime().getSeconds());

        filename = "Billede"+day+hour+minute+second;

        try {
            FileOutputStream fos = new FileOutputStream(new File("/sdcard/DCIM/"+filename+".jpeg"));
            fos.write(imageData);
            fos.flush();
            fos.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        if(imageData != null){
            Intent mIntent = new Intent();
            setResult(0,mIntent);
            PictureActivity.this.showDialog(0);
        }
    }
};

也试过写从位图(没有工作)的形象,再加上另外一个问题在这里报告使用写的FileOutputStream 工作

Also tried writing the image from a Bitmap (didn't work), plus another question here report writing using a FileOutputStream worked

推荐答案

发现问题:

纵观原始图像从SD卡显示:

Looking at the original images from the SDCARD showed:

图像包含EXIF GPS数据,如果EXIFInterface使用。该GPS数据,但是,错了(见下文) - 这可能就是为什么Flickr的不会表现出来。

The images contained EXIF GPS data if the EXIFInterface is used. The GPS data, however, was wrong (see below) -- which probably is why Flickr won't show it.

使用那台GPS坐标通过摄像头的参数不写EXIF GPS数据的方法(这是使用虚拟硬盘codeD的坐标,我还没有与实际的GPS定位测试)。我没有看过更进这是为什么。

Using the method that sets GPS coordinates through the camera parameters do NOT write EXIF GPS data (this was using dummy hardcoded coordinates, I haven't tested with an actual GPS fix). I haven't looked more into why this is.

有关EXIFInterface Android的API有this文档:

The Android API for EXIFInterface has this documentation:

公共静态最后弦乐TAG_GPS_LONGITUDE   自:API级别5   串。格式为NUM1 / denom1,NUM2 / denom2,NUM3 / denom3。   常数值:GPSLongitude

public static final String TAG_GPS_LONGITUDE Since: API Level 5 String. Format is "num1/denom1,num2/denom2,num3/denom3". Constant Value: "GPSLongitude"

与我原来的code的问题是,我是路过的GPS坐标在十进制度 - 你从一个位置对象调用getLatitude / getLogitude得到的坐标是十进制度。该EXIFInterface预计,度分秒,然后写成有理数的坐标(这是EXIF规范的一部分)。更多关于GPS坐标格式和转换这里。

The problem with my original code is that I was passing the GPS coordinates in Decimal Degrees -- the coordinates you get from calling getLatitude/getLogitude on a Location object is in Decimal Degrees. The EXIFInterface expects the coordinates in Degrees Minutes Seconds and then written as rationals (this is part of the EXIF specification). More on GPS coordinate formats and conversion here.

Here是另外一个问题/回答,解释如何从十进制度转换为度分秒。

Here is another question/answer that explains how to convert from Decimal Degrees to Degrees Minutes Seconds.

使用这个code,GPS坐标获取的EXIF正确地写入和Flickr都没有问题导入数据:

Using this code, the GPS coordinates gets written correctly in the EXIF and Flickr have no problem importing the data:

ExifInterface exif;

double latitude = AGlanceLocationListener.getLatitude();
double longitude = AGlanceLocationListener.getLongitude();

try {
    exif = new ExifInterface("/sdcard/DCIM/"+filename+".jpeg");
    int num1Lat = (int)Math.floor(latitude);
    int num2Lat = (int)Math.floor((latitude - num1Lat) * 60);
    double num3Lat = (latitude - ((double)num1Lat+((double)num2Lat/60))) * 3600000;

    int num1Lon = (int)Math.floor(longitude);
    int num2Lon = (int)Math.floor((longitude - num1Lon) * 60);
    double num3Lon = (longitude - ((double)num1Lon+((double)num2Lon/60))) * 3600000;

    exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, num1Lat+"/1,"+num2Lat+"/1,"+num3Lat+"/1000");
    exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, num1Lon+"/1,"+num2Lon+"/1,"+num3Lon+"/1000");


    if (latitude > 0) {
        exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, "N"); 
    } else {
        exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, "S");
    }

    if (longitude > 0) {
        exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, "E");    
    } else {
    exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, "W");
    }

    exif.saveAttributes();

} catch (IOException e) {
    Log.e("PictureActivity", e.getLocalizedMessage());
}   

请注意:当使用度分秒还需要设置GPS的参考属性(N,S,E,W)

Note: When using Degrees Minutes Seconds you also need to set the GPS reference attributes (N, S, E, W).

 
精彩推荐
图片推荐