-
Notifications
You must be signed in to change notification settings - Fork 0
Home
A friend recently saw a picture posted on Facebook by a friend and wanted to find out where that picture was taken. The picture was of someone in a park and he could not pinpoint exactly which park it was, but had a general idea. He asked me if there was a way for him to see the location of the photo on a map.
Before you can determine the location of a photo, the photo has to be geotagged. Geotagged basically means that the longitude and latitude of the photo has been stored in the photo metadata. The metadata is the invisible part of the photo called EXIF data. Depending on the camera, EXIF data will store the current state of the camera when the photo was taken including date and time, shutter speeds, focal lengths, flash, lens type, location data, etc.
Of course, the only way you’ll see where a picture was taken is if the camera is GPS enabled. If you have a camera that doesn’t have any type of GPS option, then there won’t be any location data in the EXIF data. This is true of most SLR cameras. However, if the photo was taken with a smartphone and location services are enabled, then the GPS coordinates of the phone will be captured when you snap a picture.
We need to install a gem to read EXIF data from a given image. We shall use the exifr
gem. You can read the details of the "exifr gem"
$ gem install exifr
You can run $ bundle install
which will do this for you, as per the Gemfile
.
# exifmap_sinatra.rb
require 'sinatra'
require 'exifr'
not_found do
erb :'404'
end
error do
'Sorry there was a nasty error - ' + env['sinatra.error'].name
end
get '/' do
erb :index
end
post '/show' do
begin
if params[:photo]
photo = EXIFR::JPEG.new(params[:photo][:tempfile])
lat = photo.gps.latitude
lng = photo.gps.longitude
defaults = {:zoom => 5, :size => [600, 300], :maptype => 'roadmap'}
@photo_map = "http://maps.googleapis.com/maps/api/staticmap?sensor=false&zoom=#{defaults[:zoom]}&size=#{defaults[:size][0]}x#{defaults[:size][1]}&maptype=#{defaults[:maptype]}¢er=#{lat},#{lng}&markers=color:blue%7Clabel:I%7C#{lat},#{lng}"
erb :show
end
rescue NoMethodError
halt erb(:nomethod)
end
end
The Google Static Maps API lets you embed a Google Maps image on your web page without requiring JavaScript or any dynamic page loading. The Google Static Map service creates your map based on URL parameters sent through a standard HTTP request and returns the map as an image you can display on your web page.
We create the string photo_map
based on the above API, as follows:
- The base URL is
http://maps.googleapis.com/maps/api/staticmap?sensor=false
where applications that determine the user's location via a sensor must passsensor=true
within the Static Maps API request URL. If your application does not use a sensor, passsensor=false
. Thesensor
parameter is required.
The additional parameters used in photo_map
are:
-
zoom
(required) defines the zoom level of the map, which determines the magnification level of the map. This parameter takes a numerical value corresponding to the zoom level of the region desired. Zoom levels between 0 (the lowest zoom level, in which the entire world can be seen on one map) to 21+ (down to individual buildings) are possible within the default roadmap maps view. -
size
(required) defines the rectangular dimensions of the map image. This parameter takes a string of the form {horizontal_value}x{vertical_value}. For example, 600x300 defines a map 600 pixels wide by 300 pixels high. -
maptype
(optional) defines the type of map to construct. There are several possible maptype values, includingroadmap
,satellite
,hybrid
, andterrain
. -
center
(required) defines the center of the map, equidistant from all edges of the map. This parameter takes a location as either a comma-separated {latitude,longitude} pair (e.g. "40.714728,-73.998672") or a string address (e.g. "city hall, new york, ny") identifying a unique location on the face of the earth. -
markers
(optional) define one or more markers to attach to the image at specified locations. This parameter takes a single marker definition with parameters separated by the pipe character (| or %7C).
The markers
parameter takes set of value assignments (marker descriptors) of the following format:
markers=markerStyles|markerLocation1| markerLocation2|...
etc.
The set of markerStyles is declared at the beginning of the markers
declaration and consists of zero or more style descriptors separated by the pipe character (|), followed by a set of one or more locations also separated by the pipe character (|).
The marker style descriptors contain the following key/value assignments:
-
size
: (optional) specifies the size of marker from the set {tiny, mid, small}. If no size parameter is set, the marker will appear in its default (normal) size. -
color
: (optional) specifies a 24-bit color (example: color=0xFFFFCC) or a predefined color from the set {black, brown, green, purple, yellow, blue, gray, orange, red, white}. -
label
: (optional) specifies a single uppercase alphanumeric character from the set {A-Z, 0-9}.
Each marker descriptor must contain a set of one or more locations defining where to place the marker on the map. These locations may be either specified as latitude/longitude values or as addresses.
source "http://rubygems.org"
gem 'sinatra'
gem 'exifr'
require './exifmap_sinatra'
run Sinatra::Application
web: bundle exec ruby exifmap_sinatra.rb -p $PORT
GPS Location and Map from Photo
===============================
Brief Description
-----------------
This is a introductory level project wherein we build a Sinatra app that extracts the geo data, namely latitude and longitude, from a given photo and then shows the location where the photo was snapped, on a map.
References
----------
The Google Static Maps API - https://developers.google.com/maps/documentation/staticmaps/
exifr gem - https://rubygems.org/gems/exifr
Wiki
----
Here we explain the logic of the Sinatra app that we have built -
<form action="/show" method="post" enctype="multipart/form-data">
Select a photo: <input type="file" name = "photo" id="photo" /><br />
<input type="submit" value="Upload" />
</form>
<div>
<h2>Your photo was snapped here!</h2>
<img src=<%= @photo_map %> alt="Photo location" />
<p><a href="/">Back</a></p>
</div>
<div id="footer">
<p><b>A Fun Sinatra App for accessing photo location and displaying the location map by RubyLearning 18 Aug. 2013</b>.</p>
</div>
<div>
<h1>A Sinatra app to display location where photo was snapped</h1>
<p>I'm sorry but the "The Sinatra app to access Photo Location Service is not accessible from the folder you typed in.</p>
<p>The correct URL is: <a href="http://localhost:4567/">http://localhost:4567/</a></p>
<p><a href="/">Back</a></p>
</div>
<div id="footer">
<p><b>A Fun Sinatra App for displaying location where a photo was snapped by RubyLearning 18 Aug. 2013</b>.</p>
</div>
<div>
<h1>A Sinatra app to display location where photo was snapped</h1>
<p>I'm sorry but the photo you uploaded has no location data.</p>
<p><a href="/">Back</a></p>
</div>
<div id="footer">
<p><b>A Fun Sinatra App for displaying location where a photo was snapped by RubyLearning 18 Aug. 2013</b>.</p>
</div>
Finally, our app displays the map in a new browser window.