Get your own customer support community

Recent activity

Subscribe to this feed
  • question

    Christian replied on August 22, 2009 16:21 to the question "How to Use OpenZoom for Images on GigaPan.org?" in OpenZoom:

    Christian
    Daniel,

    I had to put that together quickly for a demo, but I planned to submit a patch before it went to the production stage ... then I got diverted to other projects and never went back to it.

    So it looks like the 0.4.2 descriptor allows the custom URL out of the box, so Michael ought to be all set. The directory structure should be the same whether it's on your own server or GigaPan's.
  • question

    Christian replied on August 22, 2009 16:00 to the question "How to Use OpenZoom for Images on GigaPan.org?" in OpenZoom:

    Christian
    Ok, basically what I'm doing is allowing you to feed a URL, width and height:


    var descriptor:GigaPanUrlDescriptor = new GigaPanUrlDescriptor("http://mars.asu.edu/~cyates/moeur_south.data", 111180, 13481)


    You can look at http://mars.asu.edu/~cyates/moeur_sou... and see that it's just the directory structure that the GigaPan stitcher software creates.

    The revised class is as follows:


    /**
    * Support for GigaPan panoramas not hosted at gigapan.org
    *
    * Replaces id param with a URL param
    *
    * We are replacing the org.openzoom.flash.descriptors.gigapan
    * package because method extension will not work in this case,
    * as several methods are defined as private.
    *
    */

    package edu.asu.mars.gigapan
    {

    import flash.utils.Dictionary;

    import org.openzoom.flash.descriptors.IMultiScaleImageDescriptor;
    import org.openzoom.flash.descriptors.IMultiScaleImageLevel;
    import org.openzoom.flash.descriptors.MultiScaleImageDescriptorBase;
    import org.openzoom.flash.descriptors.MultiScaleImageLevel;
    import org.openzoom.flash.utils.math.clamp;

    /**
    * Descriptor for the GigaPan.org project panoramas.
    * Copyright GigaPan.org, http://gigapan.org/
    */
    public class GigaPanUrlDescriptor extends MultiScaleImageDescriptorBase
    implements IMultiScaleImageDescriptor
    {
    //--------------------------------------------------------------------------
    //
    // Class constants
    //
    //--------------------------------------------------------------------------

    private static const DEFAULT_BASE_LEVEL:uint = 8
    private static const DEFAULT_TILE_SIZE:uint = 256

    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
    * Constructor.
    */
    public function GigaPanUrlDescriptor(url:String, width:uint, height:uint)
    {
    this.url = url

    _width = width
    _height = height
    _numLevels = computeNumLevels(width, height)

    _tileWidth = DEFAULT_TILE_SIZE
    _tileHeight = DEFAULT_TILE_SIZE

    _type = "image/jpeg"

    levels = computeLevels(width, height, DEFAULT_TILE_SIZE, numLevels)
    }

    //--------------------------------------------------------------------------
    //
    // Variables
    //
    //--------------------------------------------------------------------------

    private var url:String
    private var extension:String = ".jpg"
    private var levels:Dictionary

    //--------------------------------------------------------------------------
    //
    // Methods: IMultiScaleImageDescriptor
    //
    //--------------------------------------------------------------------------

    /**
    * @inheritDoc
    */
    public function getTileURL(level:int, column:uint, row:uint):String
    {
    var url:String = url + "/tiles"
    var name:String = "r"
    var z:int = level
    var bit:int = (1 << z) >> 1
    var x:int = column
    var y:int = row

    while (bit > 0)
    {
    name += String((x & bit ? 1 : 0) + (y & bit ? 2 : 0))
    bit = bit >> 1
    }

    var i:int = 0
    while (i < name.length - 3)
    {
    url = url + "/" + name.substr(i, 3)
    i = i + 3
    }

    var tileURL:String = [url, "/", name, extension].join("")
    return tileURL
    }

    /**
    * @inheritDoc
    */
    public function getLevelAt(index:int):IMultiScaleImageLevel
    {
    return IMultiScaleImageLevel(levels[index])
    }

    /**
    * @inheritDoc
    */
    public function getMinLevelForSize(width:Number, height:Number):IMultiScaleImageLevel
    {
    var maxDimension:uint = Math.max(width, height)
    var level:uint = Math.ceil(Math.log(maxDimension) / Math.LN2)
    var actualLevel:uint = level - DEFAULT_BASE_LEVEL
    var index:int = clamp(actualLevel, 0, numLevels - 1)

    return IMultiScaleImageLevel(getLevelAt(index)).clone()
    }

    /**
    * @inheritDoc
    */
    public function clone():IMultiScaleImageDescriptor
    {
    return new GigaPanUrlDescriptor(url, width, height)
    }

    //--------------------------------------------------------------------------
    //
    // Methods: Debug
    //
    //--------------------------------------------------------------------------

    /**
    * @inheritDoc
    */
    override public function toString():String
    {
    return "[GigaPanUrlDescriptor]" + "\n" + super.toString()
    }

    //--------------------------------------------------------------------------
    //
    // Methods: Internal
    //
    //--------------------------------------------------------------------------

    /**
    * @private
    */
    private function computeNumLevels(width:uint, height:uint):uint
    {
    var maxDimension:uint = Math.max(width, height)
    var actualLevels:uint = Math.ceil(Math.log(maxDimension) / Math.LN2)
    var numLevels:uint = Math.max(0, actualLevels - DEFAULT_BASE_LEVEL + 1)
    return numLevels
    }

    /**
    * @private
    */
    private function computeLevels(originalWidth:uint, originalHeight:uint,
    tileSize:uint, numLevels:int):Dictionary
    {
    var levels:Dictionary = new Dictionary()

    var width:uint = originalWidth
    var height:uint = originalHeight

    for (var index:int = numLevels - 1; index >= 0; index--)
    {
    levels[index] = new MultiScaleImageLevel(this, index, width, height,
    Math.ceil(width / tileWidth),
    Math.ceil(height / tileHeight))
    width = Math.ceil(width / 2)
    height = Math.ceil(height / 2)
    }

    return levels
    }
    }

    }
  • question

    Christian replied on August 22, 2009 15:55 to the question "How to Use OpenZoom for Images on GigaPan.org?" in OpenZoom:

    Christian
    Michael,

    You can use Gigapan's tiling software to stitch and tile your raw images into a pyramidized structure. You can then host those tiles on your own web server.

    IIRC, I had to duplicate the GigapanDescriptor class file rather than extending it, because the variables and methods I had to manipulate were private, but it's a relatively simple change to make, and then you can feed the top level URI of your gigapan structure to OpenZoom and it just works.

    Here's a demo using local gigapan tiles:
    http://www.mars.asu.edu/~cyates/zoome...

    I'll dig up the source code and post it. I'll warn you that it's not using the most recent code from SVN, so Daniel may have already made improvements.
  • question

    Christian replied on June 30, 2009 22:25 to the question "How Do I Prevent Loading of Very Small Deep Zoom Tiles?" in OpenZoom:

    Christian
    Awesome. Setting RenderingMode.FAST did the trick. On one particular image setting it to SMOOTH downloads 48 image slices, while FAST downloads 9.

    For most of our images, the change in "smoothness" of the zoom isn't very noticeable, and I (and I'm guessing our users) would prefer the increase in performance and reliability of the servers.

    When the neo branch is closer to production I'll have to revisit this.

    Thanks again Daniel.

    -c
  • question

    Christian asked a question in OpenZoom on June 30, 2009 18:10:

    Christian
    How Do I Prevent Loading of Very Small Deep Zoom Tiles?
    Daniel,

    I've noticed that when using DeepZoom derived descriptors that Openzoom loads many seemingly unnecessary image levels at resolutions far smaller than the viewport dimensions -- the 1x1, 2x2, etc. pixel versions from the DZI pyramid.

    This seems odd to me, but would be more of a curiosity if it weren't creating a big impact on certain aspects of our product. When we try to scale a 25,000 x 330,000 pixel image down to 1x2 or something, even with the magic of JPEG2000, my on-the-fly tile cutter chokes.

    My custom descriptor, which implements IMultiScaleImageBase, implements the getMinLevelForSize method.

    getMinLevelForSize returns the right level for the viewport, but lower levels are also queried. This uses bandwidth in all situations (I noticed the same behavior in your NYTimes inline image replacement demo), but also chokes my build process. It would seem that getMinLevelForSize ought to be setting the floor for the MultiScaleImageLevel to return.

    My temporary hack may be to disable the image cutter when both requested dimensions are < 10px and return a blank image... but it would be nicer to know if there's a way to stop the client code from requesting these seemingly unneeded levels.

    Thanks again!

    -christian
  • question

    Christian replied on June 20, 2009 16:24 to the question "How to Use OpenZoom for Images on GigaPan.org?" in OpenZoom:

    Christian
    There is a Gigapan descriptor available. You probably need to download the latest OpenZoom SDK from SVN, as I don't think it's in the preview SWC that Daniel published.

    I can verify that the Gigapan descriptor works well, and if you have the need to access Gigapan tile sets on your own server (as opposed to Gigapan's), the descriptor class can easily be extended to do so.
  • praise

    Christian replied on June 10, 2009 23:07 to the praise "OpenZoom on Mars" in OpenZoom:

    Christian
    Thanks very much for your assistance Daniel!

    I think I've got both problems fixed now. I updated my embed code, and then discovered I'd deployed an outdated version of the swf, which was missing a fix I'd made to prevent over-zooming, which I think was causing the null pointer error.

    Thanks again!

    -c
  • praise

    Christian replied on June 10, 2009 22:13 to the praise "OpenZoom on Mars" in OpenZoom:

    Christian
    Yeah, I've noticed both problems. I'm not sure why the mouse wheel won't work, as I've got the ExternalMouseWheel class included and I'm calling it on initialization of the Flex app. It also works fine from the Flex debugger, but not when it's put into the web page.

    The other issue I think may be a race condition, as I'm not able to consistently trigger the bug.

    The Mars Image Explorer is a system that is intended to encompass all images taken by various spacecraft orbiting mars, dating back to Viking forward to the current missions - Mars Express, Mars Odyssey and Mars Reconnaissance Orbiter.

    The system as it stands now lets you search and browse through a million or so images from eight instruments that flew aboard various spacecraft. The front end is Drupal and jQuery, while the backend is in Java (for metadata) and Python (for image processing).

    I built the Drupal, jQuery and Python stuff, while a colleague manages the Java stuff, which also powers our JMARS desktop GIS application.

    My next step will be to integrate our mapping services (displaying global and regional maps), and to re-implement the front end in Flex.

    The whole thing is modular and configurable, so we also use the software to display data from Earth: http://earth.asu.edu/

    The Mars Space Flight Facility at Arizona State University manages the THEMIS instrument aboard Mars Odyssey and authors a variety of software tools and web applications used by scientists studying Mars, Earth, and the Moon (and probably other planets and planetoids in the future).

    -c
  • praise

    Christian gave praise in OpenZoom on June 10, 2009 03:45:

    Christian
    OpenZoom on Mars
    Daniel,

    As promised, here are some examples of a custom Openzoom descriptor and JPEG2000 tile server in use:

    Images containing the "Face on Mars"

    From the Context (CTX) Camera onboard the Mars Reconnaissance Orbiter:
    http://viewer.mars.asu.edu/planetview...

    And a higher resolution view from the HiRISE camera on MRO:
    http://viewer.mars.asu.edu/planetview...

    These pages (well, the CTX pages anyway) are linked directly from Google Earth's Mars layer. Eventually we'll enable other instruments in our Mars Image Explorer with Openzoom. I've got a number of other interesting plans for it too.

    -christian
  • question

    A comment on the question "How Do I Use OpenZoom with djatoka?" in OpenZoom:

    Christian
    Ryan,

    It wasn't so much that djatoka's performance was bad, it was that it wasn't any better than what we were already working on in most cases. In some cases, it lagged behind. Specifically, when subsetting and scaling large portions of large images (say 4000x32000 of a 5000x54000 pixel image) took 2-3x longer than our existing solution. Smaller subsections fared better, and were sometimes faster to return.

    A colleague had already set up a subsetting server using Java for use by our JMARS application, calling the gdal_translate binary from FWTools, which implements the Kakadu libraries in C. It was pretty simple for me to create something similar but more generic in Python. It's not nearly as full-featured as Djatoka.

    The other issue was the portability - I did manage to finally get djatoka running under Glassfish, our production app server, but it required extra domain-wide JVM variables to do so.

    We were using the getRegion syntax but for some of our needs we needed to use the scale parameter as well - I noticed though that if given percentage rather than pixel values it wouldn't cache output images.

    We were really hoping for a JNI solution, but it appears that the Kakadu JNI just isn't up to snuff, as you're the second group that's tried it and reverted back to system calls to external binaries. – Christian, on June 09, 2009 13:38
  • question

    Christian replied on June 09, 2009 04:59 to the question "How Do I Use OpenZoom with djatoka?" in OpenZoom:

    Christian
    Daniel,

    To tell you the truth, I ended up abandoning Djatoka, as its performance wasn't up to the level we needed and it was difficult to deploy in our environment. I did however use the experience to build a similar JPEG2000 subsetting service in Python, and to create a custom OpenZoom descriptor for it.

    I've been handling the metadata issue on the server side for now, but I'll take a look at your improved Djatoka descriptor code and see if that would be a better way to handle my custom descriptor as well.

    Once our service is up (in a couple of days, most likely), I'll send you a link.

    -christian
  • question

    Christian replied on May 21, 2009 00:53 to the question "How Do I Use OpenZoom with djatoka?" in OpenZoom:

    Christian
    No problem! I've attempted to add a static constructor method, but I keep banging my head on the asynchronous return of data from the djatoka metadata service.

    Do you have any examples where data is retrieved remotely i.e. xml describing a deepzoom pyramid? Your examples included in the SDK all have the image description XML hard-coded into the MXML.

    As for the level mapping - I'm assuming that if we use the dwtLevels data from metadata service, that should give the correct # of levels for that particular image, regardless of how it was processed. This assumption has not been tested adequately, as my current sample size is two.

    I have a number of JP2 images that have been processed with different tools (kdu_convert, GDAL, JasPer, etc.) so as soon as I figure out the remoting issue, I'll tackle some testing to verify my assumption.

    -christian
  • question

    Christian replied on May 21, 2009 00:19 to the question "How Do I Use OpenZoom with djatoka?" in OpenZoom:

    Christian
    Well, it appears I'm too much of an AS3 noob to figure out how to do this.

    Retrieving and parsing the metadata is easy enough, but I can't figure out how to set up the chain of events such that the metadata is retrieved before the DjatokaDescriptor constructor is executed.
  • question

    Christian replied on May 18, 2009 20:33 to the question "How Do I Use OpenZoom with djatoka?" in OpenZoom:

    Christian
    Problem seems to be related to the DEFAULT_BASE_LEVEL. Even though that is set correctly for the LANL example images, it doesn't work correctly.

    I was unaware of the metadata service from Djatoka, and now that I am, I'm going to see if I can just refactor the DjatokaDescriptor class to query it instead, so I can get the dimensions and zoom levels directly from the service. That way it'll still work even if the image has some strange level encoding like the demo Mars image I'm using.

    I'll post a patch if I get this fixed up.

    -c
  • question

    Christian asked a question in OpenZoom on May 18, 2009 17:06:

    Christian
    How Do I Use OpenZoom with djatoka?
    Daniel, I'm trying to get your Djatoka descriptor to work, but I'm running into issues. I'm using the latest flex code from the svn repo.

    What I'm seeing is incorrect tiling at low zoom levels, or when zoom=1. When I zoom all the way the maximum for an image, tiling is correct.

    Do you have any examples of usage, so I can make sure I'm not just doing something stupid?

    Here's the Openzoom example:
    http://mars.asu.edu/~cyates/djatokade...

    And here's the same image with the Djatoka viewer:
    http://african.lanl.gov/adore-djatoka...

    Both of these are using the same Dkatoka service and image.

    Here's my code:


    var descriptor:DjatokaDescriptor = new DjatokaDescriptor("http://african.lanl.gov/adore-djatoka/resolver", "http://mars.asu.edu/~cyates/P01_001337_1945_XN_14N065W.jp2", 5056, 11264);


    I've tested the rest of the code with the Gigapan and other descriptors, and it works fine, so I'm fairly sure I'm having an issue with the Djatoka descriptor.

    Same code example with a slightly refactored Gigapan descriptor:
    http://mars.asu.edu/~cyates/zoomer/Zo...

    Thanks Daniel!

    -christian
  • question

    Christian replied on April 29, 2009 16:32 to the question "How Do I Calculate the Maximum Zoom?" in OpenZoom:

    Christian
    What I ended up doing was setting the maximum property of the slider to the maxScale calculated with the method from your examples. For now, I'm setting the minimum property to zero - in actuality, minScale is slightly more than zero, but since I'm setting a minimum zoom constraint also, the image never zooms out past zoom = 1.

    Since the minScale != 0, there is a slight flicker in the slider handle from it moving from 0 to 0.0x when the the viewport is zoomed all the way out via the mouse wheel, but this isn't terribly noticeable, and good enough to get a demo out the door until I can come up with a more accurate solution.
  • question

    Christian replied on April 29, 2009 16:10 to the question "How Do I Calculate the Maximum Zoom?" in OpenZoom:

    Christian
    Thanks Daniel! This is very helpful. I was not thinking of zoom being a relative property. Using the viewport scale instead achieves what I need.

    Great work by the way!

    -christian
  • question

    Christian asked a question in OpenZoom on April 29, 2009 00:58:

    Christian
    How Do I Calculate the Maximum Zoom?
    I'm working on implementing a MultiScaleImage viewer in Flex. I've read through the API docs, but am I missing a function that will calculate the maximum (i.e. 1:1 pixel) zoom for the image?

    I've tried using the method shown on your site at http://gasi.ch/blog/inside-deep-zoom-2/, but the zoom level I calculate is much lower than the maximum that can be achieved with the mouse wheel.

    I'm working with an image that is 111180 x 13481, which calculates out to a maximum level of 17 using your function, but I can actually zoom into the image up to a level of 33.59, based on setting a scaleconstraint.

    My goal is to calculate the maximum zoom possible for an image and set this as the maximum for an HSilder

    Thanks!

    -chris