Opened 17 years ago
Closed 17 years ago
#1983 closed defect (fixed)
WCS Server does not return data at the correct resolution
Reported by: | Owned by: | warmerdam | |
---|---|---|---|
Priority: | high | Milestone: | |
Component: | WCS Server | Version: | 4.10 |
Severity: | normal | Keywords: | |
Cc: |
Description (last modified by )
If starting with a 30 arcsec (0.00833333 degrees) data set in a mapserver WCS, when I make a WCS request using resx=0.00833333 and resy=0.00833333 the output image returned by mapserver does not register correctly and gdalinfo returns Pixel Size = (0.00836820,-0.00836820). The new pixel size can vary slightly based on the bounding box of the request. The main point is that the output image (we are using geotiff) is not the same resolution as the request. Example: http://www.ngdc.noaa.gov/eog/maps/test5.php?SERVICE=WCS&REQUEST=GetCoverage&Coverage=vis_mosaic&STYLES=&CRS=EPSG:4326&BBOX=-125,30,-115,40&resx=0.00833333&resy=0.00833333&Format=geotiff the data comes back as 0.00834028,-0.00834028 instead of 0.00833333,-0.00833333 (the native resolution of the data is 0.00833333,-0.00833333). Additionally the given bounding box actually covers an area 1201px by 1201px in the data. However, the returned image is 1200px by 1200px. If compared to the original data one can see that mapserver has resampled the returned image to fit the area which is 1201 by 1201 into an image that is 1200 by 1200, which explains the change in the resolution. It seems to me that this may not be the the desired behaviour for WCS. I would expect to get my data back at the same resolution requested.
Attachments (1)
Change History (23)
comment:2 by , 17 years ago
Sorry about that, here is the mapfile from the example in the first post. Also, the data is still quite large (410M) zipped so I put it on our ftp site (ftp://ftp.ngdc.noaa.gov/DMSP/ms/test_data.tgz). If anyone would prefer to have it on the bugzilla server or would prefer a subset on the bugzilla server let me know. :::::::::::::::::::::::::::::::::::::::::::: NAME DMSP-Test STATUS ON SIZE 864 312 EXTENT -180 -65 180 65 UNITS dd SHAPEPATH "/mnt/anchor1/eogmaps/data/" IMAGECOLOR 255 255 255 WEB IMAGEPATH "/mnt/anchor1/eogmaps/www/html/tmp/" IMAGEURL "/tmp/" METADATA "wms_title" "DMSP Demo Server" ##required "wms_onlineresource" "http://eogmaps.ngdc.noaa.gov/cgi-bin/mapserv.exe?" ##required "wms_srs" "EPSG:4326" ##recommended END END PROJECTION "init=epsg:4326" ##required END OUTPUTFORMAT NAME GEOTIFF DRIVER "GDAL/GTiff" MIMETYPE "image/tiff" IMAGEMODE "BYTE" EXTENSION "tif" END LAYER NAME "vis_mosaic" METADATA wcs_description "F152003 11 28 mosaic" wcs_name "mosaic" wcs_label "vis_mosaic" ows_srs "EPSG:4326" ows_extent "-180 -65 180 65" wcs_resolution "0.00833333 -0.00833333" wcs_bandcount "1" wcs_formats "GEOTIFF" wcs_nativeformat "8-bit GeoTIF" wcs_rangeset_name "vis_mosaic" wcs_rangeset_label "vis" wcs_rangeset_axes "bands" wcs_bands_rangeitem "_bands" wcs_bands_name "bands" wcs_bands_semantic "http://www.ngdc.noaa.gov/dmsp/" wcs_bands_refSys "European Petroleum Survey Group (EPSG)" wcs_bands_label "F152003" wcs_bands_values "VIS" END STATUS off DUMP true DATA "F1520061123.nt.d.OIS.vis.mos" TYPE raster PROJECTION "init=epsg:4326" END END LAYER NAME "tir_mosaic" METADATA wcs_description "F152003 11 28 mosaic" wcs_name "mosaic" wcs_label "tir_mosaic" ows_srs "EPSG:4326" ows_extent "-180 -65 180 65" wcs_resolution "0.00833333 -0.00833333" wcs_bandcount "1" wcs_formats "GEOTIFF" wcs_nativeformat "8-bit GeoTIF" wcs_rangeset_name "tir_mosaic" wcs_rangeset_label "tir" wcs_rangeset_axes "bands" wcs_bands_rangeitem "_bands" wcs_bands_name "bands" wcs_bands_semantic "http://www.ngdc.noaa.gov/dmsp/" wcs_bands_refSys "European Petroleum Survey Group (EPSG)" wcs_bands_label "F152003" wcs_bands_values "TIR" END STATUS off DUMP true DATA "F1520061123.nt.d.OIS.tir.mos" TYPE raster PROJECTION "init=epsg:4326" END END END #Mapfile
comment:3 by , 17 years ago
Starting to look into this. May take all night to download the example image, but once that's here... ;-) Steve
comment:4 by , 17 years ago
So here is some additional information based on work we've been doing. In order to work around this and get back the data at full res (with no resampling) we wrote some php that recalculates the width and height based on the bounding box and the resolution of the data. So we wrote the following two functions: function round_bbox($lat0,$lon0,$lat1,$lon1, $resx, $resy) { $nlat0=round($lat0/$resy)*$resy; $nlat1=round($lat1/$resy)*$resy; $nlon0=round($lon0/$resx)*$resx; $nlon1=round($lon1/$resx)*$resx; parse_str("nlat0={$nlat0}&nlon0={$nlon0}&nlat1={$nlat1}&nlon1={$nlon1} ",$all); return $all; } function get_width_height($lat0,$lon0,$lat1,$lon1,$resx, $resy) { $width = ($lon1-$lon0)/$resx + 1; $height = ($lat1-$lat0)/$resy + 1; parse_str("nwidth={$width}&nheight={$height}",$all); return $all; } We decided that if no widht/height or resx/rey were specified we would calculate width/height based on the bounding box and return the data at full res for the requested area. Then we decided to handle resx/resy being specified by calculating the correct width and height for the specified resolution and return the data for the requested area at the requested resolution. Our last decision was that if width and height were specified we would not do any recaculating. This is all based on a default gridsize of 30 arcseconds in the case of our data. The block of code we are using for this is as follows: $gridsz=1.0/120.0; $resx=$request->getvaluebyname('resx'); $resy=$request->getvaluebyname('resy'); $width=$request->getvaluebyname('width'); $height=$request->getvaluebyname('height'); $service=$request->getvaluebyname('service'); $format=$request->getvaluebyname('format'); /* lon0 lat0 lon1 lat1 */ $bbox=explode(',',$request->getvaluebyname('bbox')); if (($resx == "") && ($resy == "") && ($width == "") && ($height == "") && (preg_match("/^WCS$/i", $service) == 1)){ /*Round the bbox and calculate the new width and height*/ $nbbox=round_bbox($bbox[1],$bbox[0],$bbox[3],$bbox[2], $gridsz, $gridsz); $nwidth_nheight=get_width_height($nbbox["nlat0"], $nbbox["nlon0"], $nbbox["nlat1"], $nbbox["nlon1"], $gridsz, $gridsz); $request->setParameter("bbox","{$nbbox["nlon0"]}, {$nbbox["nlat0"]}, {$nbbox["nlon1"]}, {$nbbox["nlat1"]}"); $request->setParameter("width","{$nwidth_nheight["nwidth"]}"); $request->setParameter("height","{$nwidth_nheight["nheight"]}"); }elseif (($resx != "") && ($resy != "") && ($width == "") && ($height == "") && (preg_match("/^WCS$/i", $service) == 1)){ /*Round the bbox and caculate the new width and height based on the requested resolution*/ $nbbox=round_bbox($bbox[1],$bbox[0],$bbox[3],$bbox[2], $resx, $resy); $nwidth_nheight=get_width_height($nbbox["nlat0"], $nbbox["nlon0"], $nbbox["nlat1"], $nbbox["nlon1"], $resx, $resy); $request->setParameter("bbox","{$nbbox["nlon0"]}, {$nbbox["nlat0"]}, {$nbbox["nlon1"]}, {$nbbox["nlat1"]}"); $request->setParameter("width","{$nwidth_nheight["nwidth"]}"); $request->setParameter("height","{$nwidth_nheight["nheight"]}"); } Thought it might help to see a work around that seemed to solve the issue we were having. I'd be happy to discuss this in more detail if anyone thinks it could be helpful.
comment:5 by , 17 years ago
Do I read this as there is not a problem with the WCS code? Rather that the client needs to do appropriate computational work (based on service metadata) before requesting imagery. Steve
comment:6 by , 17 years ago
As it stands the if one made a request for data with a native resolution of 30 arcsec using resx=0.00833333 and resy=0.00833333 the returned image would in fact not be at that resolution. Mapserver seems to resample the data due to a minor miscalculation in the width and height (it seems to only be off by one pixel in either direction and in our tests has been very predictable thus we were able to get around it in php) that corespond to the bounding box. This suggests an error in the code to me as it does not behave as I would expect. I would expect the request to return th edata at the resolution requested. Any thoughts?
comment:7 by , 17 years ago
I played around with this one tonite. Seems to me like the problem is in the msDrawRasterLow function (or lower) someplace. The requested extent, resolution and computed height/width remain stable and correct all the way through that call. They way the WCS code works is that the WCS params are used to configure the mapfile used to drive the service. This ammounts to setting the EXTENT and SIZE parameters in this case. Those values seem to be just fine. I can create a test case outside of the WCS code with Ben's mapfile by changing: SIZE 1200 1200 EXTENT -125 30 -115 40 and running shp2img (I'll post my version). The output tiff is the right size but has different EXTENT and resolution values. The msAdjustExtent function likes the values above and doesn't have to modify them (as expected). This doesn't look to be a WCS problem . Ideas? Steve
comment:8 by , 17 years ago
Component: | WCS Server → GDAL Support |
---|
Changing component to GDAL... Steve
comment:9 by , 17 years ago
Steve, How are you getting the extent of the GeoTIFF? Map file extents are based on the center of the top left pixel to the center of the bottom right pixel. But gdalinfo reports are the top left corner of the top left pixel to the bottom right corner of the bottom right pixel. Is this accounted for? I also *think* that the WCS extent has the same interpretation as gdalinfo, and would need to be adjusted before used as a mapfile extent. Is this accounted for?
comment:10 by , 17 years ago
Note that I may be too quick to point to the raster code. I would have expected msAdjustExtent to compute the resolution gdalinfo reports. That's not the case. I've got a feeling the raster code is using a different cell model than other spots resulting in this off-by-one error. See MS_CELLSIZE in map.h. Perusing mapdrawgdal.c I see some coordinate computations for lr x/y that add .5 pixels. Which seems to be compensating for a center cell pixel model. The comments in map.h indicate we switched to a UL pixel model to match WMS. Steve
comment:11 by , 17 years ago
Geez, this gets confusing. As I look at msAdjustExtent it sure looks to me like an "extent" matches the definitions described in the OGC WMS specs. That is, those values represent the outside edges of the pixels on the corners. (section 6.5.6 in the WMS 1.1.1 spec). I went back to the 4.6 code and it's been that way for a good while. Steve
comment:12 by , 17 years ago
Component: | GDAL Support → WCS Server |
---|
Ok, more testing. The WMS support certainly assumes a center pixel model and if I adjust the incoming BBOX for WCS by 1/2 the resolution (supplied or computed) then I get the right output. Frank, if a BBOX is not supplied then the code defaults to the extent of the dataset (using msOWSGetLayerExtent). What pixel model does that extent use? Has is already been adjusted for MapServer? Back to the WCS component. I'm still concerned msAdjustExtent is off-by-one. Steve
comment:13 by , 17 years ago
Hi all- FYI we have had some interesting problems with tiled geotiffs that seem likely to be related to this problem as well. I haven't been able to test it enough to say absolutely it is the same problem, but it seems likely. Basically when using a tiled tiff (physical tiles, not internal) the returned image (using WCS) has systematic shifts at the tile boundaries. Thought there was a chance this information might help track down the issue if it is indeed related. Happy to discuss this more it it anyone thinks it might help.
comment:14 by , 17 years ago
Cc: | added |
---|
comment:15 by , 17 years ago
Ben: I committed a fix to CVS HEAD that addresses the differences in how MapServer and OWS extents are interpreted. I also fixed another problem that perhaps could be related to your last comment, again in CVS HEAD. Any chance you can test things on your end and report back? Steve
comment:16 by , 17 years ago
I'm at a conference all week, but I will try and get the updated components up next week and see what happens. Thanks.
comment:17 by , 17 years ago
Ben: Any chance you'll get a chance to try the 5.0 CVS version soon? No hurry, just want to make sure I get this resolved. Steve
comment:18 by , 17 years ago
Steve: Trying out the 5.0 cvs version is pretty high on my to do list, but January was pretty hectic. This issue is pretty important to what we are doing here so I also want to see it resolved. I will try to get this running as soon as I can and report back. Thanks for your help on this.
comment:19 by , 17 years ago
So I grabbed a copy of mapserver from cvs, here is the mapserv -v info for reference: MapServer version 4.99 OUTPUT=GIF OUTPUT=PNG OUTPUT=JPEG OUTPUT=WBMP OUTPUT=SVG SUPPORTS=PROJ SUPPORTS=FREETYPE SUPPORTS=WMS_SERVER SUPPORTS=WMS_CLIENT SUPPORTS=WFS_SERVER SUPPORTS=WFS_CLIENT SUPPORTS=WCS_SERVER SUPPORTS=GEOS INPUT=EPPL7 INPUT=POSTGIS INPUT=OGR INPUT=GDAL INPUT=SHAPEFILE So far I have only done a few tests, but it seems to be returning the correct resolution now. I am planning to fire some more requests at it to try and be sure it works in more than just the few cases I've tried thus far. So far so good though. I've made a few requests with resx=0.00833333&resy=0.00833333 and every response has been an image with Pixel Size = (0.00833333,-0.00833333). I'll try to post any further results as soon as possible. By the way, it does not seem to fix our issue with physical (not internal) tiles being mosaicked incorrectly. I'll have to look at this some more to see if maybe we are doing something bad when we make out tiles. Any chance something similar could be happening somewhere else in the code that causes a similar issue for tiles?
comment:20 by , 17 years ago
We need to look at the tiling problem more closely then. I'm not sure I understand the issue (haven't thought about it lately). Thanks for checking on this and let me know how other tests go. Steve
comment:21 by , 17 years ago
Hi all- Sorry for the long delay on getting back to this. The newer version does seem to fix the resolution issue as I said before. However, I finally noticed one other problem. If this should be filed as a new bug let me know. I think it may be part of the same issue though. Given a file with the following coordinates: Corner Coordinates: Upper Left (-180.0041667, 65.0041667) (180d 0'15.00"W, 65d 0'15.00"N) Lower Left (-180.0041667, -65.0041147) (180d 0'15.00"W, 65d 0'14.81"S) Upper Right ( 180.0040227, 65.0041667) (180d 0'14.48"E, 65d 0'15.00"N) Lower Right ( 180.0040227, -65.0041147) (180d 0'14.48"E, 65d 0'14.81"S)
When I make a request for the file via WCS I get back the expected resolution and file size, however, the header information is changed to be exactly what I said in the WCS bbox. THis means that the header info is not correct for the downloaded file.
For example, I would expect a request for a bbox=-180,0,-100,65 to return an upper left of -180.0041667, 65.0041667 for this image. Instead it returns -180.0000000, 65.0000000.
I would also expect a request for a bbox=-96.1234567,20,-90,31.1234567 to return an upper left something like -96.0042, -31.0042 rather than -96.1234557,31.1234557.
Unfortunately I don;t have the newer version running on a public server yet, but I would be happy to provide data, mapfiles, set up (if someone has a server I can log into), and/or answers to questions to help work this out.
Let me know if this makes sense or not and if there are questions or anything else I can do to track this down. Also, as I mentioned if this should be filed as a new bug let me know. Thanks.
comment:22 by , 17 years ago
Description: | modified (diff) |
---|---|
Resolution: | → fixed |
Status: | assigned → closed |
Ben,
This should be addressed seperately from this ticket, so I'll close this one.
I'm not exactly sure that what you describe is a bug in MapServer. My understanding is that mapserver is expected to resample available data into a raster with the size and extents requested regardless of the extent or resolution of the source data.
But we can pursue that elsewhere.