1 : /******************************************************************************
2 : * $Id: dataset.cpp 24237 2012-04-14 15:06:21Z 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 14 : const char *pszUserAgent = CPLGetXMLValue(config, "UserAgent", "");
352 14 : if (pszUserAgent[0] != '\0')
353 0 : m_osUserAgent = pszUserAgent;
354 :
355 14 : const char *pszReferer = CPLGetXMLValue(config, "Referer", "");
356 14 : if (pszReferer[0] != '\0')
357 0 : m_osReferer = pszReferer;
358 :
359 14 : if (ret == CE_None) {
360 14 : const char *pszHttpZeroBlockCodes = CPLGetXMLValue(config, "ZeroBlockHttpCodes", "");
361 14 : if(pszHttpZeroBlockCodes == '\0') {
362 0 : m_http_zeroblock_codes.push_back(204);
363 : } else {
364 14 : char **kv = CSLTokenizeString2(pszHttpZeroBlockCodes,",",CSLT_HONOURSTRINGS);
365 14 : int nCount = CSLCount(kv);
366 14 : for(int i=0; i<nCount; i++) {
367 0 : int code = atoi(kv[i]);
368 0 : if(code <= 0) {
369 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockHttpCodes \"%s\", comma separated HTTP response codes expected.",
370 0 : kv[i]);
371 0 : ret = CE_Failure;
372 0 : break;
373 : }
374 0 : m_http_zeroblock_codes.push_back(code);
375 : }
376 14 : CSLDestroy(kv);
377 : }
378 : }
379 :
380 14 : if (ret == CE_None) {
381 14 : const char *pszZeroExceptions = CPLGetXMLValue(config, "ZeroBlockOnServerException", "");
382 14 : if(pszZeroExceptions[0] != '\0') {
383 0 : m_zeroblock_on_serverexceptions = StrToBool(pszZeroExceptions);
384 0 : if (m_zeroblock_on_serverexceptions == -1) {
385 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ZeroBlockOnServerException \"%s\", true/false expected.",
386 0 : pszZeroExceptions);
387 0 : ret = CE_Failure;
388 : }
389 : }
390 : }
391 :
392 14 : if (ret == CE_None) {
393 14 : const char *max_conn = CPLGetXMLValue(config, "MaxConnections", "");
394 14 : if (max_conn[0] != '\0') {
395 0 : m_http_max_conn = atoi(max_conn);
396 : } else {
397 14 : m_http_max_conn = 2;
398 : }
399 : }
400 14 : if (ret == CE_None) {
401 14 : const char *timeout = CPLGetXMLValue(config, "Timeout", "");
402 14 : if (timeout[0] != '\0') {
403 0 : m_http_timeout = atoi(timeout);
404 : } else {
405 14 : m_http_timeout = 300;
406 : }
407 : }
408 14 : if (ret == CE_None) {
409 14 : const char *offline_mode = CPLGetXMLValue(config, "OfflineMode", "");
410 14 : if (offline_mode[0] != '\0') {
411 0 : const int offline_mode_bool = StrToBool(offline_mode);
412 0 : if (offline_mode_bool == -1) {
413 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of OfflineMode, true / false expected.");
414 0 : ret = CE_Failure;
415 : } else {
416 0 : m_offline_mode = offline_mode_bool;
417 : }
418 : } else {
419 14 : m_offline_mode = 0;
420 : }
421 : }
422 :
423 14 : if (ret == CE_None) {
424 14 : const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
425 14 : if (advise_read[0] != '\0') {
426 0 : const int advise_read_bool = StrToBool(advise_read);
427 0 : if (advise_read_bool == -1) {
428 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of AdviseRead, true / false expected.");
429 0 : ret = CE_Failure;
430 : } else {
431 0 : m_use_advise_read = advise_read_bool;
432 : }
433 : } else {
434 14 : m_use_advise_read = 0;
435 : }
436 : }
437 :
438 14 : if (ret == CE_None) {
439 14 : const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
440 14 : if (m_use_advise_read) {
441 0 : if (verify_advise_read[0] != '\0') {
442 0 : const int verify_advise_read_bool = StrToBool(verify_advise_read);
443 0 : if (verify_advise_read_bool == -1) {
444 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of VerifyAdviseRead, true / false expected.");
445 0 : ret = CE_Failure;
446 : } else {
447 0 : m_verify_advise_read = verify_advise_read_bool;
448 : }
449 : } else {
450 0 : m_verify_advise_read = 1;
451 : }
452 : }
453 : }
454 :
455 : // Let the local configuration override the minidriver supplied projection
456 :
457 14 : if (ret == CE_None) {
458 14 : const char *proj = CPLGetXMLValue(config, "Projection", "");
459 14 : if (proj[0] != '\0') {
460 8 : m_projection = ProjToWKT(proj);
461 8 : if (m_projection.size() == 0) {
462 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Bad projection specified.");
463 0 : ret = CE_Failure;
464 : }
465 : }
466 : }
467 :
468 : // Same for Min, Max and NoData, defined per band or per dataset
469 : // If they are set as null strings, they clear the server declared values
470 14 : if (ret == CE_None) {
471 : // Data values are attributes, they include NoData Min and Max
472 : // TODO: document those options
473 14 : if (0!=CPLGetXMLNode(config,"DataValues")) {
474 0 : const char *nodata=CPLGetXMLValue(config,"DataValues.NoData",NULL);
475 0 : if (nodata!=NULL) WMSSetNoDataValue(nodata);
476 0 : const char *min=CPLGetXMLValue(config,"DataValues.min",NULL);
477 0 : if (min!=NULL) WMSSetMinValue(min);
478 0 : const char *max=CPLGetXMLValue(config,"DataValues.max",NULL);
479 0 : if (max!=NULL) WMSSetMaxValue(max);
480 : }
481 : }
482 :
483 14 : if (ret == CE_None) {
484 14 : CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
485 14 : if (cache_node != NULL) {
486 4 : m_cache = new GDALWMSCache();
487 4 : if (m_cache->Initialize(cache_node) != CE_None) {
488 0 : delete m_cache;
489 0 : m_cache = NULL;
490 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize cache.");
491 0 : ret = CE_Failure;
492 : }
493 : }
494 : }
495 :
496 14 : if (ret == CE_None) {
497 14 : const int v = StrToBool(CPLGetXMLValue(config, "UnsafeSSL", "false"));
498 14 : if (v == -1) {
499 0 : CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of UnsafeSSL: true or false expected.");
500 0 : ret = CE_Failure;
501 : } else {
502 14 : m_unsafeSsl = v;
503 : }
504 : }
505 :
506 14 : if (ret == CE_None) {
507 : /* If we dont have projection already set ask mini-driver. */
508 14 : if (!m_projection.size()) {
509 6 : const char *proj = m_mini_driver->GetProjectionInWKT();
510 6 : if (proj != NULL) {
511 6 : m_projection = proj;
512 : }
513 : }
514 : }
515 :
516 14 : return ret;
517 : }
518 :
519 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) {
520 : CPLErr ret;
521 :
522 1 : if (rw != GF_Read) return CE_Failure;
523 1 : if (buffer == NULL) return CE_Failure;
524 1 : if ((sx == 0) || (sy == 0) || (bsx == 0) || (bsy == 0) || (band_count == 0)) return CE_None;
525 :
526 1 : m_hint.m_x0 = x0;
527 1 : m_hint.m_y0 = y0;
528 1 : m_hint.m_sx = sx;
529 1 : m_hint.m_sy = sy;
530 1 : m_hint.m_overview = -1;
531 1 : m_hint.m_valid = true;
532 : // 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);
533 1 : ret = GDALDataset::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, band_count, band_map, pixel_space, line_space, band_space);
534 1 : m_hint.m_valid = false;
535 :
536 1 : return ret;
537 : }
538 :
539 2 : const char *GDALWMSDataset::GetProjectionRef() {
540 2 : return m_projection.c_str();
541 : }
542 :
543 0 : CPLErr GDALWMSDataset::SetProjection(const char *proj) {
544 0 : return CE_Failure;
545 : }
546 :
547 7 : CPLErr GDALWMSDataset::GetGeoTransform(double *gt) {
548 7 : gt[0] = m_data_window.m_x0;
549 7 : gt[1] = (m_data_window.m_x1 - m_data_window.m_x0) / static_cast<double>(m_data_window.m_sx);
550 7 : gt[2] = 0.0;
551 7 : gt[3] = m_data_window.m_y0;
552 7 : gt[4] = 0.0;
553 7 : gt[5] = (m_data_window.m_y1 - m_data_window.m_y0) / static_cast<double>(m_data_window.m_sy);
554 7 : return CE_None;
555 : }
556 :
557 0 : CPLErr GDALWMSDataset::SetGeoTransform(double *gt) {
558 0 : return CE_Failure;
559 : }
560 :
561 6 : const GDALWMSDataWindow *GDALWMSDataset::WMSGetDataWindow() const {
562 6 : return &m_data_window;
563 : }
564 :
565 3 : void GDALWMSDataset::WMSSetBlockSize(int x, int y) {
566 3 : m_block_size_x=x;
567 3 : m_block_size_y=y;
568 3 : }
569 :
570 3 : void GDALWMSDataset::WMSSetRasterSize(int x, int y) {
571 3 : nRasterXSize=x;
572 3 : nRasterYSize=y;
573 3 : }
574 :
575 3 : void GDALWMSDataset::WMSSetBandsCount(int count) {
576 3 : nBands=count;
577 3 : }
578 :
579 3 : void GDALWMSDataset::WMSSetClamp(bool flag=true) {
580 3 : m_clamp_requests=flag;
581 3 : }
582 :
583 3 : void GDALWMSDataset::WMSSetDataType(GDALDataType type) {
584 3 : m_data_type=type;
585 3 : }
586 :
587 3 : void GDALWMSDataset::WMSSetDataWindow(GDALWMSDataWindow &window) {
588 3 : m_data_window=window;
589 3 : }
590 :
591 1 : void GDALWMSDataset::WMSSetDefaultBlockSize(int x, int y) {
592 1 : m_default_block_size_x=x;
593 1 : m_default_block_size_y=y;
594 1 : }
595 :
596 1 : void GDALWMSDataset::WMSSetDefaultDataWindowCoordinates(double x0, double y0, double x1, double y1)
597 : {
598 1 : m_default_data_window.m_x0 = x0;
599 1 : m_default_data_window.m_y0 = y0;
600 1 : m_default_data_window.m_x1 = x1;
601 1 : m_default_data_window.m_y1 = y1;
602 1 : }
603 :
604 0 : void GDALWMSDataset::WMSSetDefaultTileCount(int tilecountx, int tilecounty)
605 : {
606 0 : m_default_tile_count_x = tilecountx;
607 0 : m_default_tile_count_y = tilecounty;
608 0 : }
609 :
610 1 : void GDALWMSDataset::WMSSetDefaultTileLevel(int tlevel)
611 : {
612 1 : m_default_data_window.m_tlevel = tlevel;
613 1 : }
614 :
615 1 : void GDALWMSDataset::WMSSetDefaultOverviewCount(int overview_count)
616 : {
617 1 : m_default_overview_count = overview_count;
618 1 : }
619 :
620 1 : void GDALWMSDataset::WMSSetNeedsDataWindow(int flag)
621 : {
622 1 : m_bNeedsDataWindow = flag;
623 1 : }
624 :
625 2 : static void list2vec(std::vector<double> &v,const char *pszList)
626 : {
627 2 : if ((pszList==NULL)||(pszList[0]==0)) return;
628 : char **papszTokens=CSLTokenizeString2(pszList," \t\n\r",
629 2 : CSLT_STRIPLEADSPACES|CSLT_STRIPENDSPACES);
630 2 : v.clear();
631 4 : for (int i=0;i<CSLCount(papszTokens);i++)
632 2 : v.push_back(CPLStrtod(papszTokens[i],NULL));
633 2 : CSLDestroy(papszTokens);
634 : }
635 :
636 0 : void GDALWMSDataset::WMSSetNoDataValue(const char * pszNoData)
637 : {
638 0 : list2vec(vNoData,pszNoData);
639 0 : }
640 :
641 1 : void GDALWMSDataset::WMSSetMinValue(const char * pszMin)
642 : {
643 1 : list2vec(vMin,pszMin);
644 1 : }
645 :
646 1 : void GDALWMSDataset::WMSSetMaxValue(const char * pszMax)
647 : {
648 1 : list2vec(vMax,pszMax);
649 1 : }
650 :
651 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) {
652 : // printf("AdviseRead(%d, %d, %d, %d)\n", x0, y0, sx, sy);
653 0 : if (m_offline_mode || !m_use_advise_read) return CE_None;
654 0 : if (m_cache == NULL) return CE_Failure;
655 :
656 0 : GDALRasterBand *band = GetRasterBand(1);
657 0 : if (band == NULL) return CE_Failure;
658 0 : return band->AdviseRead(x0, y0, sx, sy, bsx, bsy, bdt, options);
659 : }
660 :
661 1 : const char *GDALWMSDataset::GetMetadataItem( const char * pszName,
662 : const char * pszDomain )
663 : {
664 1 : if( pszName != NULL && EQUAL(pszName, "XML") &&
665 : pszDomain != NULL && EQUAL(pszDomain, "WMS") )
666 : {
667 1 : return (m_osXML.size()) ? m_osXML.c_str() : NULL;
668 : }
669 :
670 0 : return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
671 : }
|