2012-05-10 8 views
9

मैं आपकी क्या अपेक्षाएं हैं:
* अपने ही PictureActivity का उपयोग कर एक तस्वीर ले लो और EXIF ​​(geotags) डेटा
* जोड़ें: का उपयोग कर SurfaceHolder.Callback को लागू करने और Cameraलिखें/जियोटैग JPEGs (EXIF डेटा) एंड्रॉयड में

क्या काम नहीं कर रहा:
EXIF ​​जीपीएस डेटा

मैं क्या कोशिश की है जोड़ना: ExifInterface का उपयोग
और मैन्युअल Camera.Parameters की स्थापना (दोनों जीपीएस मेटा डेटा स्थापित करने के लिए विशिष्ट तरीकों के साथ और params.set(String, Value) का उपयोग करके)। (हाँ, मैं जीपीएस डेटा आयात करने के लिए फ़्लिकर निर्धारित किया है - अन्य चित्रों अच्छा काम)

मैं FlickrJ का उपयोग कर फ़्लिकर के चित्र अपलोड कर रहा हूँ, लेकिन इस उपकरण भी कहते हैं वहाँ EXIF ​​में कोई जीपीएस डेटा है: http://regex.info/exif.cgi

मुझे क्या याद आ रही है?

(Android 2.2, एचटीसी डिजायर)

संपादित करें:
- कैमरा Geotag photos: On
पर सेट है - मैं हार्डकोडेड डमी जीपीएस पदों

यहाँ के साथ की कोशिश की है मैन्युअल रूप से स्थापित करने के मापदंडों के लिए कोड है (दोनों के साथ और पहली जीपीएस डेटा को हटाए बिना की कोशिश की, और के रूप में 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); 
} 

उसके

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

यहाँ sdcard के लिए JPEG फ़ाइल लिखने के लिए कोड है:: ई ExifInterface उपयोग करने के लिए कोड है

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

इसके अलावा से छवि लेखन की कोशिश की एक Bitmap (काम नहीं किया)

मूल छवियों च को देखते हुए:, प्लस एक और यहाँ सवाल का उपयोग कर एक FileOutputStream काम किया

उत्तर

10

मिले समस्या लिख ​​रिपोर्ट रोम एसडीकार्ड ने दिखाया:

  1. यदि EXIFInterface का उपयोग किया जाता है तो छवियों में EXIF ​​GPS डेटा होता है। हालांकि, जीपीएस डेटा गलत था (नीचे देखें) - शायद यही कारण है कि फ़्लिकर इसे नहीं दिखाएगा।

  2. कैमरा पैरामीटर के माध्यम से जीपीएस निर्देशांक सेट करने वाली विधि का उपयोग करना EXIF ​​GPS डेटा नहीं लिखता है (यह डमी हार्डकोडेड निर्देशांक का उपयोग कर रहा था, मैंने वास्तविक जीपीएस फिक्स के साथ परीक्षण नहीं किया है)। मैंने और क्यों नहीं देखा है यह क्यों है।

EXIFInterface के लिए एंड्रॉयड एपीआई this documentation है:

सार्वजनिक स्थिर अंतिम स्ट्रिंग TAG_GPS_LONGITUDE
के बाद से: एपीआई स्तर 5
स्ट्रिंग। प्रारूप "num1/denom1, num2/denom2, num3/denom3" है।
लगातार मूल्य: "GPSLongitude"

अपने मूल कोड के साथ समस्या यह है कि मैं जीपीएस गुजर रहा था दशमलव डिग्री में निर्देशांक है - निर्देशांक आप एक स्थान वस्तु पर getLatitude/getLogitude कॉल करने से मिलता दशमलव डिग्री में है । EXIFInterface डिग्री मिनट सेकेंड में निर्देशांक की अपेक्षा करता है और फिर राशन के रूप में लिखा जाता है (यह EXIF ​​विनिर्देश का हिस्सा है)। जीपीएस समन्वय प्रारूप और रूपांतरण here पर अधिक।

Here एक अन्य प्रश्न/उत्तर है जो बताता है कि दशमलव डिग्री से डिग्री मिनट सेकेंड में कैसे परिवर्तित किया जाए।

इस कोड का प्रयोग, जीपीएस निर्देशांक EXIF ​​में सही ढंग से लिखा जाता है और फ्लिकर डेटा आयात करने में कोई समस्या नहीं:

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

नोट: डिग्री का उपयोग करते समय मिनट सेकंड आप भी जीपीएस संदर्भ विशेषताएं (निर्धारित करने की आवश्यकता एन, एस, ई, डब्ल्यू)।

+1

नकारात्मक अक्षांश के लिए और देशांतर कोड ऊपर सकारात्मक की बजाय नकारात्मक मूल्यों सांकेतिक शब्दों में बदलना होगा। उदाहरण के लिए (-40.00, -73.00) +40 डिग्री दक्षिण की बजाय दक्षिण -40 डिग्री अक्षांश दक्षिण के रूप में एन्कोड किया जाएगा। -73 को +73 डिग्री रेखांश पश्चिम की बजाय -73 डिग्री रेखांश पश्चिम के रूप में एन्कोड किया जाएगा)। – Theo

+1

आम तौर पर इसे सही उत्तर नहीं माना जाना चाहिए, क्योंकि कोड त्रुटिपूर्ण है (गणित। फ्लोर इश्यू आदि ...) – seanpj

12

दुर्भाग्य से, यह केवल गोलार्ध के एक चौथाई पर काम करता है। ग्रीनविच के पूर्व और भूमध्य रेखा के उत्तर। इस तरह मैंने अनुमान लगाया कि आपको वहां रहना चाहिए :)। आपका 'Math.floor' सभी नकारात्मक मानों को गलत बना देगा (जैसे -105 में -106)। यहां एक ही बात है, जो अमेरिका में भी काम करनी चाहिए।

public void loc2Exif(String flNm, Location loc) { 
    try { 
    ExifInterface ef = new ExifInterface(flNm); 
    ef.setAttribute(ExifInterface.TAG_GPS_LATITUDE, dec2DMS(loc.getLatitude())); 
    ef.setAttribute(ExifInterface.TAG_GPS_LONGITUDE,dec2DMS(loc.getLongitude())); 
    if (loc.getLatitude() > 0) 
     ef.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, "N"); 
    else    
     ef.setAttribute(ExifInterface.TAG_GPS_LATITUDE_REF, "S"); 
    if (loc.getLongitude()>0) 
     ef.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, "E");  
    else    
     ef.setAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF, "W"); 
    ef.saveAttributes(); 
    } catch (IOException e) {}   
} 
//----------------------------------------------------------------------------------- 
String dec2DMS(double coord) { 
    coord = coord > 0 ? coord : -coord; // -105.9876543 -> 105.9876543 
    String sOut = Integer.toString((int)coord) + "/1,"; // 105/1, 
    coord = (coord % 1) * 60;   // .987654321 * 60 = 59.259258 
    sOut = sOut + Integer.toString((int)coord) + "/1,"; // 105/1,59/1, 
    coord = (coord % 1) * 60000;    // .259258 * 60000 = 15555 
    sOut = sOut + Integer.toString((int)coord) + "/1000"; // 105/1,59/1,15555/1000 
    return sOut; 
} 

... और एक बार आप मिल गया मुझे शुरू कर दिया, यहां रिवर्स

public Location exif2Loc(String flNm) { 
    String sLat = "", sLatR = "", sLon = "", sLonR = ""; 
    try { 
    ExifInterface ef = new ExifInterface(flNm); 
    sLat = ef.getAttribute(ExifInterface.TAG_GPS_LATITUDE); 
    sLon = ef.getAttribute(ExifInterface.TAG_GPS_LONGITUDE); 
    sLatR = ef.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF); 
    sLonR = ef.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF); 
    } catch (IOException e) {return null;} 

    double lat = dms2Dbl(sLat); 
    if (lat > 180.0) return null; 
    double lon = dms2Dbl(sLon); 
    if (lon > 180.0) return null; 

    lat = sLatR.contains("S") ? -lat : lat; 
    lon = sLonR.contains("W") ? -lon : lon; 

    Location loc = new Location("exif"); 
    loc.setLatitude(lat); 
    loc.setLongitude(lon); 
    return loc; 
} 
//------------------------------------------------------------------------- 
double dms2Dbl(String sDMS){ 
    double dRV = 999.0; 
    try { 
    String[] DMSs = sDMS.split(",", 3); 
    String s[] = DMSs[0].split("/", 2); 
    dRV = (new Double(s[0])/new Double(s[1])); 
    s = DMSs[1].split("/", 2); 
    dRV += ((new Double(s[0])/new Double(s[1]))/60); 
    s = DMSs[2].split("/", 2); 
    dRV += ((new Double(s[0])/new Double(s[1]))/3600); 
    } catch (Exception e) {} 
    return dRV; 
} 

है ... और एक दिन, मैं बहुत कोड देख लिखने के लिए शुरू करेंगे। मुबारक जियोटैगिंग, शॉन

3

यह समाधान नकारात्मक और सकारात्मक अक्षांश/एलएनजी मूल्यों के लिए पूरा करेगी:

static public boolean setGeoTag(File image, LatLng geoTag) { 
    if (geoTag != null) { 
     try { 
      ExifInterface exif = new ExifInterface(
        image.getAbsolutePath()); 

      double latitude = Math.abs(geoTag.latitude); 
      double longitude = Math.abs(geoTag.longitude); 

      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; 

      String lat = num1Lat + "/1," + num2Lat + "/1," + num3Lat + "/1000"; 
      String lon = num1Lon + "/1," + num2Lon + "/1," + num3Lon + "/1000"; 

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

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

      exif.setAttribute(ExifInterface.TAG_GPS_LATITUDE, lat); 
      exif.setAttribute(ExifInterface.TAG_GPS_LONGITUDE, lon); 

      exif.saveAttributes(); 

     } catch (IOException e) { 
      e.printStackTrace(); 
      return false; 
     } 
    } else { 
     return false; 
    } 
    return true; 
} 
संबंधित मुद्दे