Recent activity
Subscribe to this feed
Christian replied on August 22, 2009 16:21 to the question "How to Use OpenZoom for Images on GigaPan.org?" in OpenZoom:
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.
Christian replied on August 22, 2009 16:00 to the question "How to Use OpenZoom for Images on GigaPan.org?" in OpenZoom:
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
}
}
}
Christian replied on August 22, 2009 15:55 to the question "How to Use OpenZoom for Images on GigaPan.org?" in OpenZoom:
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.
Christian replied on June 30, 2009 22:25 to the question "How Do I Prevent Loading of Very Small Deep Zoom Tiles?" in OpenZoom:
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
Christian asked a question in OpenZoom on June 30, 2009 18:10:
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
Christian replied on June 20, 2009 16:24 to the question "How to Use OpenZoom for Images on GigaPan.org?" in OpenZoom:
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.
Christian replied on June 10, 2009 23:07 to the praise "OpenZoom on Mars" in OpenZoom:
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
Christian replied on June 10, 2009 22:13 to the praise "OpenZoom on Mars" in OpenZoom:
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
Christian gave praise in OpenZoom on June 10, 2009 03:45:
OpenZoom on MarsDaniel,
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
A comment on the question "How Do I Use OpenZoom with djatoka?" in OpenZoom:
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
Christian replied on June 09, 2009 04:59 to the question "How Do I Use OpenZoom with djatoka?" in OpenZoom:
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
Christian replied on May 21, 2009 00:53 to the question "How Do I Use OpenZoom with djatoka?" in OpenZoom:
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
Christian replied on May 21, 2009 00:19 to the question "How Do I Use OpenZoom with djatoka?" in OpenZoom:
Christian replied on May 18, 2009 20:33 to the question "How Do I Use OpenZoom with djatoka?" in OpenZoom:
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
Christian asked a question in OpenZoom on May 18, 2009 17:06:
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
Christian replied on April 29, 2009 16:32 to the question "How Do I Calculate the Maximum Zoom?" in OpenZoom:
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.
Christian replied on April 29, 2009 16:10 to the question "How Do I Calculate the Maximum Zoom?" in OpenZoom:
Christian asked a question in OpenZoom on April 29, 2009 00:58:
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
Loading Profile...
