mlte.de

Partial Panorama with Pannellum

In order to use Pannellum with a partial panorama you need to set the haov, vaov, and vOffset parameters. This is demonstrated in the official example. But how to get these parameters?

In my case I generated the partial panorama with my Android Smartphone and Google's Camera app. So the JPEG contained all the needed information already in its Photo Sphere XMP metadata. These metadata where autimatically extracted and everything worked fine.

Unfortunately these metadata get lost if you edit the picture and they become outdated if you resize the picture. While the pannellum options haov, vaov, and vOffset are independent of the image resolution, the XMP metadata are based on the image size. Fortunaly one can find the conversion of XMP metadata to the Pannellum initialization options in the Pannellum source code:

// Set up viewer using GPano XMP data
if (specifiedPhotoSphereExcludes.indexOf('haov') < 0)
  config.haov = xmp.croppedWidth / xmp.fullWidth * 360;
if (specifiedPhotoSphereExcludes.indexOf('vaov') < 0)
  config.vaov = xmp.croppedHeight / xmp.fullHeight * 180;
if (specifiedPhotoSphereExcludes.indexOf('vOffset') < 0)
  config.vOffset = ((xmp.topPixels + xmp.croppedHeight / 2) / xmp.fullHeight - 0.5) * -180;

To get the XMP metadata one can use ImageMagick:

convert panorama.jpg panorama.xmp

I got something like this

...
<rdf:Description
GPano:CroppedAreaImageHeightPixels="1932"
GPano:CroppedAreaImageWidthPixels="14848"
GPano:CroppedAreaLeftPixels="0"
GPano:CroppedAreaTopPixels="2350"
GPano:FirstPhotoDate="2017-08-19T12:12:29.667Z"
GPano:FullPanoHeightPixels="7424"
GPano:FullPanoWidthPixels="14848"
GPano:LargestValidInteriorRectHeight="1932"
GPano:LargestValidInteriorRectLeft="0"
GPano:LargestValidInteriorRectTop="0"
GPano:LargestValidInteriorRectWidth="14848"
GPano:LastPhotoDate="2017-08-19T12:13:05.11Z"
GPano:PoseHeadingDegrees="54.0"
GPano:ProjectionType="equirectangular"
GPano:SourcePhotosCount="16"
GPano:UsePanoramaViewer="True"
rdf:about=""
xmlns:GPano="http://ns.google.com/photos/1.0/panorama/"/>
...

and converted it according to the formulas given above to the following options for Panellum:

pannellum.viewer('panorama', {
  "type": "equirectangular",
  "panorama": "panorama.jpg",
  "haov": 360,
  "vaov": 46.8426724138,
  "vOffset": 9.60129310345
});