1 : /******************************************************************************
2 : * $Id: dataset.cpp 25776 2013-03-20 20:46:48Z rouault $
3 : *
4 : * Project: WMS Client Driver
5 : * Purpose: Implementation of Dataset and RasterBand classes for WMS
6 : * and other similar services.
7 : * Author: Adam Nowacki, nowak@xpam.de
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2007, Adam Nowacki
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************
30 : *
31 : * dataset.cpp:
32 : * Initialization of the GDALWMSdriver, parsing the XML configuration file,
33 : * instantiation of the minidrivers and accessors used by minidrivers
34 : *
35 : ***************************************************************************/
36 :
37 :
38 : #include "stdinc.h"
39 :
40 14 : GDALWMSDataset::GDALWMSDataset() {
41 14 : m_mini_driver = 0;
42 14 : m_cache = 0;
43 14 : m_hint.m_valid = false;
44 14 : m_data_type = GDT_Byte;
45 14 : m_clamp_requests = true;
46 14 : m_unsafeSsl = false;
47 14 : m_data_window.m_sx = -1;
48 14 : nBands = 0;
49 14 : m_default_block_size_x = 1024;
50 14 : m_default_block_size_y = 1024;
51 14 : m_bNeedsDataWindow = TRUE;
52 14 : m_default_tile_count_x = 1;
53 14 : m_default_tile_count_y = 1;
54 14 : m_default_overview_count = -1;
55 14 : m_zeroblock_on_serverexceptions = 0;
56 14 : m_poColorTable = NULL;
57 14 : }
58 :
59 14 : GDALWMSDataset::~GDALWMSDataset() {
60 14 : if (m_mini_driver) delete m_mini_driver;
61 14 : if (m_cache) delete m_cache;
62 14 : if (m_poColorTable) delete m_poColorTable;
63 14 : }
64 :
65 14 : CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
66 14 : CPLErr ret = CE_None;
67 :
68 14 : char* pszXML = CPLSerializeXMLTree( config );
69 14 : if (pszXML)
70 : {
71 14 : m_osXML = pszXML;
72 14 : CPLFree(pszXML);
73 : }
74 :
75 : // Initialize the minidriver, which can set parameters for the dataset using member functions
76 14 : CPLXMLNode *service_node = CPLGetXMLNode(config, "Service");
77 14 : if (service_node != NULL)
78 : {
79 14 : const CPLString service_name = CPLGetXMLValue(service_node, "name", "");
80 14 : if (!service_name.empty())
81 : {
82 14 : GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
83 14 : GDALWMSMiniDriverFactory *const mdf = mdm->Find(service_name);
84 14 : if (mdf != NULL)
85 : {
86 14 : m_mini_driver = mdf->New();
87 14 : m_mini_driver->m_parent_dataset = this;
88 14 : if (m_mini_driver->Initialize(service_node) == CE_None)
89 : {
90 14 : m_mini_driver_caps.m_capabilities_version = -1;
91 14 : m_mini_driver->GetCapabilities(&m_mini_driver_caps);
92 14 : if (m_mini_driver_caps.m_capabilities_version == -1)
93 : {
94 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Internal error, mini-driver capabilities version not set.");
95 0 : ret = CE_Failure;
96 : }
97 : }
98 : else
99 : {
100 0 : delete m_mini_driver;
101 0 : m_mini_driver = NULL;
102 :
103 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize minidriver.");
104 0 : ret = CE_Failure;
105 : }
106 : }
107 : else
108 : {
109 : CPLError(CE_Failure, CPLE_AppDefined,
110 0 : "GDALWMS: No mini-driver registered for '%s'.", service_name.c_str());
111 0 : ret = CE_Failure;
112 : }
113 : }
114 : else
115 : {
116 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
117 0 : ret = CE_Failure;
118 14 : }
119 : }
120 : else
121 : {
122 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
123 0 : ret = CE_Failure;
124 : }
125 :
126 :
127 : /*
128 : Parameters that could be set by minidriver already, based on server side information.
129 : If the size is set, minidriver has done this already
130 : A "server" side minidriver needs to set at least:
131 : - Blocksize (x and y)
132 : - Clamp flag (defaults to true)
133 : - DataWindow
134 : - Band Count
135 : - Data Type
136 : It should also initialize and register the bands and overviews.
137 : */
138 :
139 14 : if (m_data_window.m_sx<1)
140 : {
141 11 : int nOverviews = 0;
142 :
143 11 : if (ret == CE_None)
144 : {
145 11 : m_block_size_x = atoi(CPLGetXMLValue(config, "BlockSizeX", CPLString().Printf("%d", m_default_block_size_x)));
146 22 : m_block_size_y = atoi(CPLGetXMLValue(config, "BlockSizeY", CPLString().Printf("%d", m_default_block_size_y)));
147 22 : if (m_block_size_x <= 0 || m_block_size_y <= 0)
148 : {
149 0 : CPLError( CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value in BlockSizeX or BlockSizeY" );
150 0 : ret = CE_Failure;
151 : }
152 : }
153 :
154 11 : if (ret == CE_None)
155 : {
156 11 : m_clamp_requests = StrToBool(CPLGetXMLValue(config, "ClampRequests", "true"));
157 11 : if (m_clamp_requests<0)
158 : {
159 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ClampRequests, true/false expected.");
160 0 : ret = CE_Failure;
161 : }
162 : }
163 :
164 11 : if (ret == CE_None)
165 : {
166 11 : CPLXMLNode *data_window_node = CPLGetXMLNode(config, "DataWindow");
167 11 : if (data_window_node == NULL && m_bNeedsDataWindow)
168 : {
169 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow missing.");
170 0 : ret = CE_Failure;
171 : }
172 : else
173 : {
174 11 : CPLString osDefaultX0, osDefaultX1, osDefaultY0, osDefaultY1;
175 11 : CPLString osDefaultTileCountX, osDefaultTileCountY, osDefaultTileLevel;
176 11 : CPLString osDefaultOverviewCount;
177 11 : osDefaultX0.Printf("%.8f", m_default_data_window.m_x0);
178 11 : osDefaultX1.Printf("%.8f", m_default_data_window.m_x1);
179 11 : osDefaultY0.Printf("%.8f", m_default_data_window.m_y0);
180 11 : osDefaultY1.Printf("%.8f", m_default_data_window.m_y1);
181 11 : osDefaultTileCountX.Printf("%d", m_default_tile_count_x);
182 11 : osDefaultTileCountY.Printf("%d", m_default_tile_count_y);
183 11 : if (m_default_data_window.m_tlevel >= 0)
184 1 : osDefaultTileLevel.Printf("%d", m_default_data_window.m_tlevel);
185 11 : if (m_default_overview_count >= 0)
186 1 : osDefaultOverviewCount.Printf("%d", m_default_overview_count);
187 11 : const char *overview_count = CPLGetXMLValue(config, "OverviewCount", osDefaultOverviewCount);
188 11 : const char *ulx = CPLGetXMLValue(data_window_node, "UpperLeftX", osDefaultX0);
189 11 : const char *uly = CPLGetXMLValue(data_window_node, "UpperLeftY", osDefaultY0);
190 11 : const char *lrx = CPLGetXMLValue(data_window_node, "LowerRightX", osDefaultX1);
191 11 : const char *lry = CPLGetXMLValue(data_window_node, "LowerRightY", osDefaultY1);
192 11 : const char *sx = CPLGetXMLValue(data_window_node, "SizeX", "");
193 11 : const char *sy = CPLGetXMLValue(data_window_node, "SizeY", "");
194 11 : const char *tx = CPLGetXMLValue(data_window_node, "TileX", "0");
195 11 : const char *ty = CPLGetXMLValue(data_window_node, "TileY", "0");
196 11 : const char *tlevel = CPLGetXMLValue(data_window_node, "TileLevel", osDefaultTileLevel);
197 11 : const char *str_tile_count_x = CPLGetXMLValue(data_window_node, "TileCountX", osDefaultTileCountX);
198 11 : const char *str_tile_count_y = CPLGetXMLValue(data_window_node, "TileCountY", osDefaultTileCountY);
199 11 : const char *y_origin = CPLGetXMLValue(data_window_node, "YOrigin", "default");
200 :
201 11 : if (ret == CE_None)
202 : {
203 22 : if ((ulx[0] != '\0') && (uly[0] != '\0') && (lrx[0] != '\0') && (lry[0] != '\0'))
204 : {
205 11 : m_data_window.m_x0 = atof(ulx);
206 11 : m_data_window.m_y0 = atof(uly);
207 11 : m_data_window.m_x1 = atof(lrx);
208 11 : m_data_window.m_y1 = atof(lry);
209 : }
210 : else
211 : {
212 : CPLError(CE_Failure, CPLE_AppDefined,
213 0 : "GDALWMS: Mandatory elements of DataWindow missing: UpperLeftX, UpperLeftY, LowerRightX, LowerRightY.");
214 0 : ret = CE_Failure;
215 : }
216 : }
217 :
218 11 : m_data_window.m_tlevel = atoi(tlevel);
219 :
220 11 : if (ret == CE_None)
221 : {
222 16 : if ((sx[0] != '\0') && (sy[0] != '\0'))
223 : {
224 5 : m_data_window.m_sx = atoi(sx);
225 5 : m_data_window.m_sy = atoi(sy);
226 : }
227 12 : else if ((tlevel[0] != '\0') && (str_tile_count_x[0] != '\0') && (str_tile_count_y[0] != '\0'))
228 : {
229 6 : int tile_count_x = atoi(str_tile_count_x);
230 6 : int tile_count_y = atoi(str_tile_count_y);
231 6 : m_data_window.m_sx = tile_count_x * m_block_size_x * (1 << m_data_window.m_tlevel);
232 6 : m_data_window.m_sy = tile_count_y * m_block_size_y * (1 << m_data_window.m_tlevel);
233 : }
234 : else
235 : {
236 : CPLError(CE_Failure, CPLE_AppDefined,
237 0 : "GDALWMS: Mandatory elements of DataWindow missing: SizeX, SizeY.");
238 0 : ret = CE_Failure;
239 : }
240 : }
241 11 : if (ret == CE_None)
242 : {
243 22 : if ((tx[0] != '\0') && (ty[0] != '\0'))
244 : {
245 11 : m_data_window.m_tx = atoi(tx);
246 11 : m_data_window.m_ty = atoi(ty);
247 : }
248 : else
249 : {
250 : CPLError(CE_Failure, CPLE_AppDefined,
251 0 : "GDALWMS: Mandatory elements of DataWindow missing: TileX, TileY.");
252 0 : ret = CE_Failure;
253 : }
254 : }
255 :
256 11 : if (ret == CE_None)
257 : {
258 11 : if (overview_count[0] != '\0')
259 : {
260 4 : nOverviews = atoi(overview_count);
261 : }
262 7 : else if (tlevel[0] != '\0')
263 : {
264 6 : nOverviews = m_data_window.m_tlevel;
265 : }
266 : else
267 : {
268 1 : const int min_overview_size = MAX(32, MIN(m_block_size_x, m_block_size_y));
269 : double a = log(static_cast<double>(MIN(m_data_window.m_sx, m_data_window.m_sy))) / log(2.0)
270 1 : - log(static_cast<double>(min_overview_size)) / log(2.0);
271 1 : nOverviews = MAX(0, MIN(static_cast<int>(ceil(a)), 32));
272 : }
273 : }
274 11 : if (ret == CE_None)
275 : {
276 11 : CPLString y_origin_str = y_origin;
277 11 : if (y_origin_str == "top") {
278 2 : m_data_window.m_y_origin = GDALWMSDataWindow::TOP;
279 9 : } else if (y_origin_str == "bottom") {
280 0 : m_data_window.m_y_origin = GDALWMSDataWindow::BOTTOM;
281 9 : } else if (y_origin_str == "default") {
282 9 : m_data_window.m_y_origin = GDALWMSDataWindow::DEFAULT;
283 : } else {
284 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow YOrigin must be set to "
285 0 : "one of 'default', 'top', or 'bottom', not '%s'.", y_origin_str.c_str());
286 0 : ret = CE_Failure;
287 11 : }
288 11 : }
289 : }
290 : }
291 :
292 11 : if (ret == CE_None)
293 : {
294 11 : if (nBands<1)
295 11 : nBands=atoi(CPLGetXMLValue(config,"BandsCount","3"));
296 11 : if (nBands<1)
297 : {
298 : CPLError(CE_Failure, CPLE_AppDefined,
299 0 : "GDALWMS: Bad number of bands.");
300 0 : ret = CE_Failure;
301 : }
302 : }
303 :
304 11 : if (ret == CE_None)
305 : {
306 11 : const char *data_type = CPLGetXMLValue(config, "DataType", "Byte");
307 11 : m_data_type = GDALGetDataTypeByName( data_type );
308 11 : if ( m_data_type == GDT_Unknown || m_data_type >= GDT_TypeCount )
309 : {
310 : CPLError( CE_Failure, CPLE_AppDefined,
311 0 : "GDALWMS: Invalid value in DataType. Data type \"%s\" is not supported.", data_type );
312 0 : ret = CE_Failure;
313 : }
314 : }
315 :
316 : // Initialize the bands and the overviews. Assumes overviews are powers of two
317 11 : if (ret == CE_None)
318 : {
319 11 : nRasterXSize = m_data_window.m_sx;
320 11 : nRasterYSize = m_data_window.m_sy;
321 :
322 11 : if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) ||
323 : !GDALCheckBandCount(nBands, TRUE))
324 : {
325 0 : return CE_Failure;
326 : }
327 :
328 : GDALColorInterp default_color_interp[4][4] = {
329 : { GCI_GrayIndex, GCI_Undefined, GCI_Undefined, GCI_Undefined },
330 : { GCI_GrayIndex, GCI_AlphaBand, GCI_Undefined, GCI_Undefined },
331 : { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_Undefined },
332 : { GCI_RedBand, GCI_GreenBand, GCI_BlueBand, GCI_AlphaBand }
333 11 : };
334 44 : for (int i = 0; i < nBands; ++i)
335 : {
336 33 : GDALColorInterp color_interp = (nBands <= 4 && i <= 3 ? default_color_interp[nBands - 1][i] : GCI_Undefined);
337 33 : GDALWMSRasterBand *band = new GDALWMSRasterBand(this, i, 1.0);
338 33 : band->m_color_interp = color_interp;
339 33 : SetBand(i + 1, band);
340 33 : double scale = 0.5;
341 630 : for (int j = 0; j < nOverviews; ++j)
342 : {
343 597 : band->AddOverview(scale);
344 597 : band->m_color_interp = color_interp;
345 597 : scale *= 0.5;
346 : }
347 : }
348 : }
349 : }
350 :
351 : // UserPwd
352 14 : const char *pszUserPwd = CPLGetXMLValue(config, "UserPwd", "");
353 14 : if (pszUserPwd[0] != '\0')
354 0 : m_osUserPwd = pszUserPwd;
355 :
356 14 : const char *pszUserAgent = CPLGetXMLValue(config, "UserAgent", "");
357 14 : if (pszUserAgent[0] != '\0')
358 0 : m_osUserAgent = pszUserAgent;
359 :
360 14 : const char *pszReferer = CPLGetXMLValue(config, "Referer", "");
361 14 : if (pszReferer[0] != '\0')
362 0 : m_osReferer = pszReferer;
363 :
364 14 : if (ret == CE_None) {
365 14 : const char *pszHttpZeroBlockCodes = CPLGetXMLValue(config, "ZeroBlockHttpCodes", "");
366 14 : if(pszHttpZeroBlockCodes == '\0') {
367 0 : m_http_zeroblock_codes.push_back(204);
368 : } else {
369 14 : char **kv = CSLTokenizeString2(pszHttpZeroBlockCodes,",",CSLT_HONOURSTRINGS);
370 14 : int nCount = CSLCount(kv);
371 14 : for(int i=0; i<nCount; i++) {
372 0 : int code = atoi(kv[i]);
373 0 : if(code <= 0) {
374 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockHttpCodes \"%s\", comma separated HTTP response codes expected.",
375 0 : kv[i]);
376 0 : ret = CE_Failure;
377 0 : break;
378 : }
379 0 : m_http_zeroblock_codes.push_back(code);
380 : }
381 14 : CSLDestroy(kv);
382 : }
383 : }
384 :
385 14 : if (ret == CE_None) {
386 14 : const char *pszZeroExceptions = CPLGetXMLValue(config, "ZeroBlockOnServerException", "");
387 14 : if(pszZeroExceptions[0] != '\0') {
388 0 : m_zeroblock_on_serverexceptions = StrToBool(pszZeroExceptions);
389 0 : if (m_zeroblock_on_serverexceptions == -1) {
390 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockOnServerException \"%s\", true/false expected.",
391 0 : pszZeroExceptions);
392 0 : ret = CE_Failure;
393 : }
394 : }
395 : }
396 :
397 14 : if (ret == CE_None) {
398 14 : const char *max_conn = CPLGetXMLValue(config, "MaxConnections", "");
399 14 : if (max_conn[0] != '\0') {
400 0 : m_http_max_conn = atoi(max_conn);
401 : } else {
402 14 : m_http_max_conn = 2;
403 : }
404 : }
405 14 : if (ret == CE_None) {
406 14 : const char *timeout = CPLGetXMLValue(config, "Timeout", "");
407 14 : if (timeout[0] != '\0') {
408 0 : m_http_timeout = atoi(timeout);
409 : } else {
410 14 : m_http_timeout = 300;
411 : }
412 : }
413 14 : if (ret == CE_None) {
414 14 : const char *offline_mode = CPLGetXMLValue(config, "OfflineMode", "");
415 14 : if (offline_mode[0] != '\0') {
416 0 : const int offline_mode_bool = StrToBool(offline_mode);
417 0 : if (offline_mode_bool == -1) {
418 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of OfflineMode, true / false expected.");
419 0 : ret = CE_Failure;
420 : } else {
421 0 : m_offline_mode = offline_mode_bool;
422 : }
423 : } else {
424 14 : m_offline_mode = 0;
425 : }
426 : }
427 :
428 14 : if (ret == CE_None) {
429 14 : const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
430 14 : if (advise_read[0] != '\0') {
431 0 : const int advise_read_bool = StrToBool(advise_read);
432 0 : if (advise_read_bool == -1) {
433 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of AdviseRead, true / false expected.");
434 0 : ret = CE_Failure;
435 : } else {
436 0 : m_use_advise_read = advise_read_bool;
437 : }
438 : } else {
439 14 : m_use_advise_read = 0;
440 : }
441 : }
442 :
443 14 : if (ret == CE_None) {
444 14 : const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
445 14 : if (m_use_advise_read) {
446 0 : if (verify_advise_read[0] != '\0') {
447 0 : const int verify_advise_read_bool = StrToBool(verify_advise_read);
448 0 : if (verify_advise_read_bool == -1) {
449 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of VerifyAdviseRead, true / false expected.");
450 0 : ret = CE_Failure;
451 : } else {
452 0 : m_verify_advise_read = verify_advise_read_bool;
453 : }
454 : } else {
455 0 : m_verify_advise_read = 1;
456 : }
457 : }
458 : }
459 :
460 : // Let the local configuration override the minidriver supplied projection
461 :
462 14 : if (ret == CE_None) {
463 14 : const char *proj = CPLGetXMLValue(config, "Projection", "");
464 14 : if (proj[0] != '\0') {
465 8 : m_projection = ProjToWKT(proj);
466 8 : if (m_projection.size() == 0) {
467 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Bad projection specified.");
468 0 : ret = CE_Failure;
469 : }
470 : }
471 : }
472 :
473 : // Same for Min, Max and NoData, defined per band or per dataset
474 : // If they are set as null strings, they clear the server declared values
475 14 : if (ret == CE_None) {
476 : // Data values are attributes, they include NoData Min and Max
477 : // TODO: document those options
478 14 : if (0!=CPLGetXMLNode(config,"DataValues")) {
479 0 : const char *nodata=CPLGetXMLValue(config,"DataValues.NoData",NULL);
480 0 : if (nodata!=NULL) WMSSetNoDataValue(nodata);
481 0 : const char *min=CPLGetXMLValue(config,"DataValues.min",NULL);
482 0 : if (min!=NULL) WMSSetMinValue(min);
483 0 : const char *max=CPLGetXMLValue(config,"DataValues.max",NULL);
484 0 : if (max!=NULL) WMSSetMaxValue(max);
485 : }
486 : }
487 :
488 14 : if (ret == CE_None) {
489 14 : CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
490 14 : if (cache_node != NULL) {
491 4 : m_cache = new GDALWMSCache();
492 4 : if (m_cache->Initialize(cache_node) != CE_None) {
493 0 : delete m_cache;
494 0 : m_cache = NULL;
495 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize cache.");
496 0 : ret = CE_Failure;
497 : }
498 : }
499 : }
500 :
501 14 : if (ret == CE_None) {
502 14 : const int v = StrToBool(CPLGetXMLValue(config, "UnsafeSSL", "false"));
503 14 : if (v == -1) {
504 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of UnsafeSSL: true or false expected.");
505 0 : ret = CE_Failure;
506 : } else {
507 14 : m_unsafeSsl = v;
508 : }
509 : }
510 :
511 14 : if (ret == CE_None) {
512 : /* If we dont have projection already set ask mini-driver. */
513 14 : if (!m_projection.size()) {
514 6 : const char *proj = m_mini_driver->GetProjectionInWKT();
515 6 : if (proj != NULL) {
516 6 : m_projection = proj;
517 : }
518 : }
519 : }
520 :
521 14 : return ret;
522 : }
523 :
524 1 : CPLErr GDALWMSDataset::IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy, void *buffer, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, int pixel_space, int line_space, int band_space) {
525 : CPLErr ret;
526 :
527 1 : if (rw != GF_Read) return CE_Failure;
528 1 : if (buffer == NULL) return CE_Failure;
529 1 : if ((sx == 0) || (sy == 0) || (bsx == 0) || (bsy == 0) || (band_count == 0)) return CE_None;
530 :
531 1 : m_hint.m_x0 = x0;
532 1 : m_hint.m_y0 = y0;
533 1 : m_hint.m_sx = sx;
534 1 : m_hint.m_sy = sy;
535 1 : m_hint.m_overview = -1;
536 1 : m_hint.m_valid = true;
537 : // printf("[%p] GDALWMSDataset::IRasterIO(x0: %d, y0: %d, sx: %d, sy: %d, bsx: %d, bsy: %d, band_count: %d, band_map: %p)\n", this, x0, y0, sx, sy, bsx, bsy, band_count, band_map);
538 1 : ret = GDALDataset::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, band_count, band_map, pixel_space, line_space, band_space);
539 1 : m_hint.m_valid = false;
540 :
541 1 : return ret;
542 : }
543 :
544 2 : const char *GDALWMSDataset::GetProjectionRef() {
545 2 : return m_projection.c_str();
546 : }
547 :
548 0 : CPLErr GDALWMSDataset::SetProjection(const char *proj) {
549 0 : return CE_Failure;
550 : }
551 :
552 3 : CPLErr GDALWMSDataset::GetGeoTransform(double *gt) {
553 3 : gt[0] = m_data_window.m_x0;
554 3 : gt[1] = (m_data_window.m_x1 - m_data_window.m_x0) / static_cast<double>(m_data_window.m_sx);
555 3 : gt[2] = 0.0;
556 3 : gt[3] = m_data_window.m_y0;
557 3 : gt[4] = 0.0;
558 3 : gt[5] = (m_data_window.m_y1 - m_data_window.m_y0) / static_cast<double>(m_data_window.m_sy);
559 3 : return CE_None;
560 : }
561 :
562 0 : CPLErr GDALWMSDataset::SetGeoTransform(double *gt) {
563 0 : return CE_Failure;
564 : }
565 :
566 6 : const GDALWMSDataWindow *GDALWMSDataset::WMSGetDataWindow() const {
567 6 : return &m_data_window;
568 : }
569 :
570 3 : void GDALWMSDataset::WMSSetBlockSize(int x, int y) {
571 3 : m_block_size_x=x;
572 3 : m_block_size_y=y;
573 3 : }
574 :
575 3 : void GDALWMSDataset::WMSSetRasterSize(int x, int y) {
576 3 : nRasterXSize=x;
577 3 : nRasterYSize=y;
578 3 : }
579 :
580 3 : void GDALWMSDataset::WMSSetBandsCount(int count) {
581 3 : nBands=count;
582 3 : }
583 :
584 3 : void GDALWMSDataset::WMSSetClamp(bool flag=true) {
585 3 : m_clamp_requests=flag;
586 3 : }
587 :
588 3 : void GDALWMSDataset::WMSSetDataType(GDALDataType type) {
589 3 : m_data_type=type;
590 3 : }
591 :
592 3 : void GDALWMSDataset::WMSSetDataWindow(GDALWMSDataWindow &window) {
593 3 : m_data_window=window;
594 3 : }
595 :
596 1 : void GDALWMSDataset::WMSSetDefaultBlockSize(int x, int y) {
597 1 : m_default_block_size_x=x;
598 1 : m_default_block_size_y=y;
599 1 : }
600 :
601 1 : void GDALWMSDataset::WMSSetDefaultDataWindowCoordinates(double x0, double y0, double x1, double y1)
602 : {
603 1 : m_default_data_window.m_x0 = x0;
604 1 : m_default_data_window.m_y0 = y0;
605 1 : m_default_data_window.m_x1 = x1;
606 1 : m_default_data_window.m_y1 = y1;
607 1 : }
608 :
609 0 : void GDALWMSDataset::WMSSetDefaultTileCount(int tilecountx, int tilecounty)
610 : {
611 0 : m_default_tile_count_x = tilecountx;
612 0 : m_default_tile_count_y = tilecounty;
613 0 : }
614 :
615 1 : void GDALWMSDataset::WMSSetDefaultTileLevel(int tlevel)
616 : {
617 1 : m_default_data_window.m_tlevel = tlevel;
618 1 : }
619 :
620 1 : void GDALWMSDataset::WMSSetDefaultOverviewCount(int overview_count)
621 : {
622 1 : m_default_overview_count = overview_count;
623 1 : }
624 :
625 1 : void GDALWMSDataset::WMSSetNeedsDataWindow(int flag)
626 : {
627 1 : m_bNeedsDataWindow = flag;
628 1 : }
629 :
630 2 : static void list2vec(std::vector<double> &v,const char *pszList)
631 : {
632 2 : if ((pszList==NULL)||(pszList[0]==0)) return;
633 : char **papszTokens=CSLTokenizeString2(pszList," \t\n\r",
634 2 : CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
635 2 : v.clear();
636 4 : for (int i=0;i<CSLCount(papszTokens);i++)
637 2 : v.push_back(CPLStrtod(papszTokens[i],NULL));
638 2 : CSLDestroy(papszTokens);
639 : }
640 :
641 0 : void GDALWMSDataset::WMSSetNoDataValue(const char * pszNoData)
642 : {
643 0 : list2vec(vNoData,pszNoData);
644 0 : }
645 :
646 1 : void GDALWMSDataset::WMSSetMinValue(const char * pszMin)
647 : {
648 1 : list2vec(vMin,pszMin);
649 1 : }
650 :
651 1 : void GDALWMSDataset::WMSSetMaxValue(const char * pszMax)
652 : {
653 1 : list2vec(vMax,pszMax);
654 1 : }
655 :
656 0 : CPLErr GDALWMSDataset::AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, char **options) {
657 : // printf("AdviseRead(%d, %d, %d, %d)\n", x0, y0, sx, sy);
658 0 : if (m_offline_mode || !m_use_advise_read) return CE_None;
659 0 : if (m_cache == NULL) return CE_Failure;
660 :
661 0 : GDALRasterBand *band = GetRasterBand(1);
662 0 : if (band == NULL) return CE_Failure;
663 0 : return band->AdviseRead(x0, y0, sx, sy, bsx, bsy, bdt, options);
664 : }
665 :
666 1 : const char *GDALWMSDataset::GetMetadataItem( const char * pszName,
667 : const char * pszDomain )
668 : {
669 1 : if( pszName != NULL && EQUAL(pszName, "XML") &&
670 : pszDomain != NULL && EQUAL(pszDomain, "WMS") )
671 : {
672 1 : return (m_osXML.size()) ? m_osXML.c_str() : NULL;
673 : }
674 :
675 0 : return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
676 : }
|