Click here to see your recently viewed pages and most viewed pages.
Hide

Photo Sphere XMP Metadata

The panorama namespace described here contains properties that provide information regarding the creation and rendering of a panorama image, such as those created by the Photo Sphere feature in the Android 4.2 camera. The metadata should be serialized and embedded inside the panorama image as described by the Adobe XMP standard (see references at the end of this page).

The namespace URI is http://ns.google.com/photos/1.0/panorama/

Metadata Properties Explained

The diagram and table below show the panorama properties. For developers writing this metadata, please be sure to follow the Euler angle conventions later in this document. For developers editing and viewing panoramas, please be sure to verify and update the metadata accordingly as described later in this document.

Name Type Required Default value
(viewer assumed)
Property description Action required if image is modified
GPano:UsePanoramaViewer Boolean No True Whether to show this image in a panorama viewer rather than as a normal flat image. This may be specified based on user preferences or by the stitching software. The application displaying or ingesting the image may choose to ignore this. scale/crop:
No change. An application may decide to switch this to False if the field of view falls below a certain value.
GPano:CaptureSoftware String No n/a If capture was done using an application on a mobile device, such as an Android phone, the name of the application that was used (such as “Photo Sphere”). This should be left blank if source images were captured manually, such as by using a DSLR on a tripod. n/a
GPano:StitchingSoftware String No n/a The software that was used to create the final panorama. This may sometimes be the same value as that of  GPano:CaptureSoftware. n/a
GPano:ProjectionType Open Choice of Text Yes

equirectangular

Projection type used in the image file. Google products currently support the value equirectangular. scale/crop: No change.
GPano:PoseHeadingDegrees Real No, but is required for display on Google Maps n/a Compass heading, measured in degrees, for the center the image. Value must be >= 0 and < 360. scale/crop: No change.
GPano:PosePitchDegrees Real No 0 Pitch, measured in degrees, for the center in the image. Value must be >= -90 and <= 90. scale/crop: No change.
GPano:PoseRollDegrees Real No 0 Roll, measured in degrees, of the image where level with the horizon is 0. Value must be > -180 and <= 180. scale/crop: No change.
GPano:InitialViewHeadingDegrees Integer No 0 The heading angle of the initial view in degrees. scale/crop: No change.
GPano:InitialViewPitchDegrees Integer No 0 The pitch angle of the initial view in degrees. scale/crop: No change.
GPano:InitialViewRollDegrees Integer No 0 The roll angle of the initial view in degrees. scale/crop: No change.
GPano:InitialHorizontalFOVDegrees Real No n/a The initial horizontal field of view that the viewer should display (in degrees). This is similar to a zoom level. n/a
GPano:FirstPhotoDate Date No n/a Date and time for the first image created in the panorama. scale/crop: No change.
GPano:LastPhotoDate Date No n/a Date and time for the last image created in the panorama. scale/crop: No change.
GPano:SourcePhotosCount Integer No n/a Number of source images used to create the panorama scale/crop: No change.
GPano:ExposureLockUsed Boolean No n/a When individual source photographs were captured, whether or not the camera’s exposure setting was locked. n/a
GPano:CroppedAreaImageWidthPixels Integer Yes n/a Original width in pixels of the image (equal to the actual image’s width for unedited images). scale/crop: This property needs to be updated to reflect the new size of the image.
GPano:CroppedAreaImageHeightPixels Integer Yes n/a Original height in pixels of the image (equal to the actual image’s height for unedited images). scale/crop: This property needs to be updated to reflect the new size of the image.
GPano:FullPanoWidthPixels Integer Yes n/a Original full panorama width from which the image was cropped. Or, if only a partial panorama was captured, this specifies the width of what the full panorama would have been. crop: No change.
scale: This properly needs to be scaled accordingly.
GPano:FullPanoHeightPixels Integer Yes n/a Original full panorama height from which the image was cropped. Or, if only a partial panorama was captured, this specifies the height of what the full panorama would have been. crop: No change.
scale: This properly needs to be scaled accordingly.
GPano:CroppedAreaLeftPixels Integer Yes n/a Column where the left edge of the image was cropped from the full sized panorama. crop: If the left crop of the image is changed, this value must be updated.
scale: This properly needs to be scaled accordingly.
GPano:CroppedAreaTopPixels Integer Yes n/a Row where the top edge of the image was cropped from the full sized panorama. crop: If the top crop of the image is changed, this value must be updated.
scale: This properly needs to be scaled accordingly.
GPano:InitialCameraDolly Real No 0 This optional parameter moves the virtual camera position along the line of sight, away from the center of the photo sphere. A rear surface position is represented by the value -1.0, while a front surface position is represented by 1.0. For normal viewing, this parameter should be set to 0. n/a

Example for a Full Spherical Panorama

Non-programmers can add the metadata example below to their existing full spherical panoramas (360 degrees x 180 degrees) with only small modifications. This can be done in image editing products, such as Adobe Photoshop.

  1. change any occurrences of 4000 and 2000 to match the corresponding width and height of your image in pixels
  2. update PoseHeadingDegrees if you want Google Maps to be able to show your panorama; otherwise, you may optionally remove this parameter
  3. update or remove optional parameters (as listed above)

<rdf:Description rdf:about="" xmlns:GPano="http://ns.google.com/photos/1.0/panorama/">
    <GPano:UsePanoramaViewer>True</GPano:UsePanoramaViewer>
    <GPano:CaptureSoftware>Photo Sphere</GPano:CaptureSoftware>
    <GPano:StitchingSoftware>Photo Sphere</GPano:StitchingSoftware>
    <GPano:ProjectionType>equirectangular</GPano:ProjectionType>
    <GPano:PoseHeadingDegrees>350.0</GPano:PoseHeadingDegrees>
    <GPano:InitialViewHeadingDegrees>90.0</GPano:InitialViewHeadingDegrees>
    <GPano:InitialViewPitchDegrees>0.0</GPano:InitialViewPitchDegrees>
    <GPano:InitialViewRollDegrees>0.0</GPano:InitialViewRollDegrees>
    <GPano:InitialHorizontalFOVDegrees>75.0</GPano:InitialHorizontalFOVDegrees>
    <GPano:CroppedAreaLeftPixels>0</GPano:CroppedAreaLeftPixels>
    <GPano:CroppedAreaTopPixels>0</GPano:CroppedAreaTopPixels>
    <GPano:CroppedAreaImageWidthPixels>4000</GPano:CroppedAreaImageWidthPixels>
    <GPano:CroppedAreaImageHeightPixels>2000</GPano:CroppedAreaImageHeightPixels>
    <GPano:FullPanoWidthPixels>4000</GPano:FullPanoWidthPixels>
    <GPano:FullPanoHeightPixels>2000</GPano:FullPanoHeightPixels>
    <GPano:FirstPhotoDate>2012-11-07T21:03:13.465Z</GPano:FirstPhotoDate>
    <GPano:LastPhotoDate>2012-11-07T21:04:10.897Z</GPano:LastPhotoDate>
    <GPano:SourcePhotosCount>50</GPano:SourcePhotosCount>
    <GPano:ExposureLockUsed>False</GPano:ExposureLockUsed>
</rdf:Description>

Example for a Partial Spherical Panorama

<rdf:Description rdf:about="" xmlns:GPano="http://ns.google.com/photos/1.0/panorama/">
    <GPano:UsePanoramaViewer>True</GPano:UsePanoramaViewer>
    <GPano:CaptureSoftware>Photo Sphere</GPano:CaptureSoftware>
    <GPano:StitchingSoftware>Photo Sphere</GPano:StitchingSoftware>
    <GPano:ProjectionType>equirectangular</GPano:ProjectionType>
    <GPano:PoseHeadingDegrees>350.0</GPano:PoseHeadingDegrees>
    <GPano:InitialViewHeadingDegrees>90.0</GPano:InitialViewHeadingDegrees>
    <GPano:InitialViewPitchDegrees>0.0</GPano:InitialViewPitchDegrees>
    <GPano:InitialViewRollDegrees>0.0</GPano:InitialViewRollDegrees>
    <GPano:InitialHorizontalFOVDegrees>75.0</GPano:InitialHorizontalFOVDegrees>
    <GPano:CroppedAreaLeftPixels>90</GPano:CroppedAreaLeftPixels>
    <GPano:CroppedAreaTopPixels>128</GPano:CroppedAreaTopPixels>
    <GPano:CroppedAreaImageWidthPixels>2300</GPano:CroppedAreaImageWidthPixels>
    <GPano:CroppedAreaImageHeightPixels>1042</GPano:CroppedAreaImageHeightPixels>
    <GPano:FullPanoWidthPixels>4000</GPano:FullPanoWidthPixels>
    <GPano:FullPanoHeightPixels>2000</GPano:FullPanoHeightPixels>
    <GPano:FirstPhotoDate>2012-11-07T21:03:13.465Z</GPano:FirstPhotoDate>
    <GPano:LastPhotoDate>2012-11-07T21:04:10.897Z</GPano:LastPhotoDate>
    <GPano:SourcePhotosCount>50</GPano:SourcePhotosCount>
    <GPano:ExposureLockUsed>False</GPano:ExposureLockUsed>
</rdf:Description>

Robustness to Image Editing

To be robust, programs that display panoramas in a viewer should check if the original panorama has been scaled by an application without updating the metadata. This can be done in the following steps:

  1. ensure that CroppedAreaImageWidthPixels tag is equal to the actual image width
  2. ensure that CroppedAreaImageHeightPixels tag is equal to the actual image height
  3. if step 1 or 2 fails, check if the aspect ratio of the image has been preserved
  4. if step 3 fails, do not display the image as a panorama as it has been transformed in an incompatible manner that will introduce bad distortions
  5. if step 3 passes, the aspect ratio is equivalent and all of the following associated tag values should be scaled to fit the new image size:
    CroppedAreaImageWidthPixels, CroppedAreaImageHeightPixels, FullPanoWidthPixels, FullPanoHeightPixels, CroppedAreaLeftPixels, CroppedAreaRightPixels.

Overview of Euler Angles

The orientation of the panorama in the world frame is defined by Euler angles. Euler angles can be defined in many ways. To be correct, a program must strictly follow the proper Euler angle conventions described here:

The position above the earth’s surface defines a fixed "local frame" XYZ, where Z is up and orthogonal to the earth’s surface, X is true east, and Y is true north. The orientation is defined relative to this fixed "local frame", and the Euler angles are rotations around these fixed XYZ axes.  Pose orientation is therefore undefined at the poles. This means that a panorama with angles (0, 0, 0) will be oriented such that the center pixel faces due north with the equator of the panorama parallel with the earth’s surface.

The Euler angles provide a mapping from points in the (rotated) "panorama frame" to points in the (fixed) "local frame":
 
A rotation matrix is constructed from the Euler angles as follows (it is important to preserve this ordering):

R = R_Z(-heading) * R_X(pitch) * R_Y(roll)

where: R_*(t) is a right-handed rotation around the named axis:

    R_Z(angle) = [ cos(angle), -sin(angle),  0
                   sin(angle),  cos(angle),  0
                   0,       0,  1 ]
 
    R_X(angle) = [ 1,       0,      0,
                   0,  cos(angle), -sin(angle),
                   0,  sin(angle),  cos(angle) ]
 
    R_Y(angle) = [ cos(angle),  0,  sin(angle),
                   0,  1,       0,
                   -sin(angle),  0,  cos(angle) ]

and where: Z = Up, X = East, Y = North.

It is important to preserve this ordering:

R = R_Z(-heading) * R_X(pitch) * R_Y(roll)

as rotations are not commutative.

Note that the heading angle is the same as a standard compass heading.

References

Adobe XMP standard: http://www.adobe.com/devnet/xmp.html