Working with PanoSalado on Mac OS X Leopard

Axel T. Schreiner, Computer Science, RIT
Last modified 6/25/09.

Get FLEX.
Download version 3.3 of the Flex SDK and unpack the archive in some directory which will be called FLEX below.
Get PANO.
Download the Feb/10/2009 version of the PanoSalado Source and unpack the archive in some directory which will be called PANO below.
Get SWFOBJ.
Download version 2.2 of <swfobject> and unpack the archive in some directory which will be called SWFOBJ below.
Repair.
In a Terminal window, execute the following commands to move some icons to the location where they are expected and to remove a watermark button from the user interface which does not seem to have an implementation:
  $ cd PANO
  $ mv graphics commercial/flexinterfaces/elements
  $ sed 14d layout_7.mxml > tmp && mv tmp layout_7.mxml 
Compile.
In a Terminal window, execute the following commands to produce files which Adobe's Flash Player (but not Shockwave Player) can execute:
  $ cd PANO
  $ FLEX/bin/mxmlc ModuleLoader.as
  $ FLEX/bin/mxmlc PanoSalado.as
  $ FLEX/bin/mxmlc layout_7.mxml
  $ FLEX/bin/mxmlc css_minimini_BR_styl.css 
Create RUNTIME.
In a Terminal window, execute the following commands to create and populate a new directory which will be called RUNTIME below and which can be shared by all panoramas:
  $ mkdir RUNTIME
  $ cd PANO
  $ cp ModuleLoader.swf PanoSalado.swf layout_7.swf css_minimini_BR_styl.swf RUNTIME
  $ cd SWFOBJ
  $ cp expressInstall.swf swfobject.js RUNTIME 
Create a web page to host a panorama.
If you want to understand the following code you need to consult the documentation of <swfobject> or deploy one of their code generators. The following code uses the static method of embedding a panorama. Variable information is indicated in color; note that most of it must be specified twice.
  <html>
    <head>
      <title> Static Example </title>
      <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1' />
      <script type='text/javascript' src='RUNTIME/swfobject.js'></script>
      <script type='text/javascript'>
        swfobject.registerObject('panorama', '9.0.0', 'RUNTIME/expressInstall.swf');
      </script>
    </head>
    <body style='margin: 0px; padding: 0px'>
      <div>
        <object classid='clsid:D27CDB6E-AE6D-11cf-96B8-444553540000'
                width='100%' height='100%' id='panorama' align='middle'>
          <param name='movie' value='RUNTIME/ModuleLoader.swf' />
          <param name='allowfullscreen' value='true' />
          <param name='flashvars' value='xml=index.xml' />
          <!--[if !IE]>-->
          <object type='application/x-shockwave-flash' width='100%' height='100%'
                  align='middle' data='RUNTIME/ModuleLoader.swf'>
            <param name='allowfullscreen' value='true' />
            <param name='flashvars' value='xml=index.xml' />
          <!--<![endif]-->
            <a href='http://www.adobe.com/go/getflashplayer'>
              You need to get Adobe Flash Player.
            </a>
          <!--[if !IE]>-->
          </object>
          <!--<![endif]-->
        </object>
      </div>
    </body>
  </html> 
The following, equivalent code uses the dynamic method of embedding a panorama which is slightly less efficient but does not duplicate information:
  <html>
    <head>
      <title> Dynamic Example </title>
      <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1' />
      <script type='text/javascript' src='RUNTIME/swfobject.js'></script>
      <script type='text/javascript'>
        var flashvars = { xml: 'index.xml' };
        var params = { allowfullscreen: 'true' };
        var attributes = { align: 'middle' };
        swfobject.embedSWF('RUNTIME/ModuleLoader.swf', 'panorama', '100%', '100%', '9.0.0',
          'RUNTIME/expressInstall.swf', flashvars, params, attributes);
      </script>
    </head>
    <body style='margin: 0px; padding: 0px'>
      <div id='panorama'>
        <a href='http://www.adobe.com/go/getflashplayer'>
          You need to get Adobe Flash Player.
        </a>
      </div>
    </body>
  </html> 
Select and configure a panorama.
If you want to understand the following code you need to consult the file PANO/XML Schema.txt or deploy SpinControl:VR Demo. The following code must be in the file index.xml referenced in the web page created in the previous step. Only this code is specific to a particular panorama:
<PanoSalado>
  <layer id='Interface' url='RUNTIME/layout_7.swf' depth='1'>
    <style url='RUNTIME/css_minimini_BR_styl.swf'/>
  </layer>
  <layer id='PanoSalado' url='RUNTIME/PanoSalado.swf' depth='0'>
    <spaces
      onStart='loadSpace:panorama'
      autorotator='false'
    >
      <space id='panorama' interactive='false'
          cameraPan='100' cameraTilt='0'
          cameraFocus='150' cameraZoom='10' cameraMinimumZoom='7.3' cameraMaximumZoom='20'
      >
        <cylinder autoFOV='true'>
          <file>cylinder.jpg</file>
        </cylinder>
      </space>
    </spaces>
  </layer>
</PanoSalado> 
The Interface layer contains buttons to control the panorama; without the buttons the panorama can still be moved with the mouse or arrow keys and zoomed with the shift and command keys.

The PanoSalado layer is mandatory. It must contain spaces with onStart loading a space containing a panorama which can take many forms. Initial values for pan, tilt, and zoom should be specified; they control what is seen initially. Focus and zoom interact; SpinControl is helpful to determine suitable values interactively for a (default) focus of 100. Tilt and zoom interact, too: given larger zoom values (i.e., more magnification) more tilting is possible without leaving the scene if the panorama was acquired as a single stripe.

The panorama can use several media formats, in particular, a single file for a cylinder or six files for the faces of a cube. To accommodate Flash cylinder.jpg should not exceed 8000x4000 pixels and a cube face should be limited to 4000x4000 pixels. A cylinder is particularly convenient because it can be produced directly by many stitching programs and because the interaction between tilt and zoom is managed automatically if autoFOV is asserted.

More examples are available by searching for all versions at the PanoSalado download site. They are particularly instructive because they contain previews and several different media formats.

Preview
There are many (undocumented) ways to move from one panorama to another. For example, if the closing tag </spaces> above is replaced by the following code
      <space id='loading' interactive='false'
             cameraPan='-15' cameraTilt='0' cameraZoom='1'
             transition="tweenXML:global.tween"
             onTransitionEnd="loadSpace:panorama; removeLastSpace"
      >
        <cylinder>
          <file>loading.png</file>
        </cylinder>
      </space>
    </spaces>
    <tweens>
      <tween id="global.tween"
             target="currentSpace.viewport"
             property="alpha" direction="from" endValue="0" time="1.5"
             easeClass="Expo" easeFunction="easeInOut" onComplete="onTransitionEnd"/>
    </tweens> 
and if the first loadSpace is changed to reference loading rather than panorama then the file loading.png is shown prior to the actual panorama in cylinder.jpg. The first file can be much smaller to load faster if the quality and size are reduced, or if the file just contains a text message.
Modifications
You can change the sources, recompile the modules, and copy them back to RUNTIME to tailor them to your liking. For example, you can remove the word SpinControl from the context menu of Flash Player (which appears if you control-click a panorama) on line 189 in the file PANO/commercial/flexinterfaces/elements/PanoSaladoApplication.as. If you do, you need to recompile and copy layout_7.swf as described above.

You can insert your own icons and move and restyle the toolbar by editing (or replacing) the file PANO/css_minimini_BR_styl.css, compiling, and copying css_minimini_BR_styl.swf as described above. The visible icons are defined beginning in line 490, the toolbar is styled beginning in line 340. For example, Icons Etc is a good place to find free icons.

Troubleshooting
One should specify a DOCTYPE to distinguish which version of HTML is in use. Unfortunately, most of the tested browsers do not render the panorama if there is a DOCTYPE and height is specified as a percentage.

If the web page is opened in a browser which supports Flash it will take some time to load the panorama.

If you load the page from the file system, you may have to 'trust' the directory by connecting to the security settings for the Flash Player.

Even version 10 of the Shockwave player cannot render Flash files which require version 9 and above. An old plugin /Library/Internet Plug-Ins/NP-PPC-Dir-Shockwave should be removed (it would only work with a PowerPC-based browser anyhow) and a current Flash Player must be installed.

Google's Chrome does not officially support Flash Player; however, if a current version of Flash Player is installed or reinstalled Flash content can be viewed.

Compatibility
The following browsers have been tested under Mac OS X version 10.5.7, both, with static and dynamic embedding of the panorama:
Browser Version

Camino 1.6.8
2.0.b3
Firefox 3.0.11
Flock 2.0.3
Mozilla 1.7.13
Navigator 9.0.0.6
OmniWeb 5.9.2
Opera 9.64
RealPlayer 11.0.1
Safari 4.0.1
Seamonkey 1.1.17
The following browsers have been tested under Windows XP, both, with static and dynamic embedding of the panorama:
Browser Version

Chrome 2.0.172.33
Firefox 3.0.11
Internet Explorer 8.0.6001.18702
Safari 4.0
Camino version 1 requires an event to redraw Flash content in the browser window when terminating full-screen mode; this has been fixed in version 2 (beta).