~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to frmts/kmlsuperoverlay/kmlsuperoverlaydataset.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/******************************************************************************
 
2
 * $Id$
 
3
 *
 
4
 * Project:  KmlSuperOverlay
 
5
 * Purpose:  Implements write support for KML superoverlay - KMZ.
 
6
 * Author:   Harsh Govind, harsh.govind@spadac.com
 
7
 *
 
8
 ******************************************************************************
 
9
 * Copyright (c) 2010, SPADAC Inc. <harsh.govind@spadac.com>
 
10
 *
 
11
 * Permission is hereby granted, free of charge, to any person obtaining a
 
12
 * copy of this software and associated documentation files (the "Software"),
 
13
 * to deal in the Software without restriction, including without limitation
 
14
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
15
 * and/or sell copies of the Software, and to permit persons to whom the
 
16
 * Software is furnished to do so, subject to the following conditions:
 
17
 *
 
18
 * The above copyright notice and this permission notice shall be included
 
19
 * in all copies or substantial portions of the Software.
 
20
 *
 
21
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
22
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
23
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 
24
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
25
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 
26
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 
27
 * DEALINGS IN THE SOFTWARE.
 
28
 ****************************************************************************/
 
29
 
 
30
#include "kmlsuperoverlaydataset.h"
 
31
 
 
32
#include <cmath>   /* fabs */
 
33
#include <cstring> /* strdup */
 
34
#include <iostream>
 
35
#include <sstream>
 
36
#include <math.h>
 
37
#include <algorithm>
 
38
#include <fstream>
 
39
 
 
40
#include "cpl_error.h"
 
41
#include "cpl_string.h"
 
42
#include "cpl_conv.h"
 
43
#include "cpl_vsi.h"
 
44
#include "ogr_spatialref.h"
 
45
 
 
46
using namespace std;
 
47
 
 
48
/************************************************************************/
 
49
/*                           GenerateTiles()                            */
 
50
/************************************************************************/
 
51
void GenerateTiles(std::string filename, 
 
52
                   int zoom, int rxsize, 
 
53
                   int rysize, int ix, int iy, 
 
54
                   int rx, int ry, int dxsize, 
 
55
                   int dysize, int bands,
 
56
                   GDALDataset* poSrcDs,
 
57
                   GDALDriver* poOutputTileDriver, 
 
58
                   GDALDriver* poMemDriver,
 
59
                   bool isJpegDriver)
 
60
{
 
61
    GDALDataset* poTmpDataset = NULL;
 
62
    GDALRasterBand* alphaBand = NULL;
 
63
   
 
64
    GByte* pafScanline = new GByte[dxsize];
 
65
    bool* hadnoData = new bool[dxsize];
 
66
 
 
67
    if (isJpegDriver && bands == 4)
 
68
        bands = 3;
 
69
   
 
70
    poTmpDataset = poMemDriver->Create("", dxsize, dysize, bands, GDT_Byte, NULL);
 
71
   
 
72
    if (isJpegDriver == false)//Jpeg dataset only has one or three bands
 
73
    {
 
74
        if (bands < 4)//add transparency to files with one band or three bands
 
75
        {
 
76
            poTmpDataset->AddBand(GDT_Byte);
 
77
            alphaBand = poTmpDataset->GetRasterBand(poTmpDataset->GetRasterCount());
 
78
        }
 
79
    }
 
80
 
 
81
    int rowOffset = rysize/dysize;
 
82
    int loopCount = rysize/rowOffset;
 
83
    for (int row = 0; row < loopCount; row++)
 
84
    {
 
85
        if (isJpegDriver == false)
 
86
        {
 
87
            for (int i = 0; i < dxsize; i++)
 
88
            {
 
89
                hadnoData[i] = false;
 
90
            }
 
91
        }
 
92
 
 
93
        for (int band = 1; band <= bands; band++)
 
94
        {
 
95
            GDALRasterBand* poBand = poSrcDs->GetRasterBand(band);
 
96
 
 
97
            int hasNoData = 0;
 
98
            bool isSigned = false;
 
99
            double noDataValue = poBand->GetNoDataValue(&hasNoData);
 
100
            const char* pixelType = poBand->GetMetadataItem("PIXELTYPE", "IMAGE_STRUCTURE");
 
101
            if (pixelType)
 
102
            {
 
103
                if (strcmp(pixelType, "SIGNEDBYTE") == 0)
 
104
                {
 
105
                    isSigned = true; 
 
106
                }
 
107
            }
 
108
 
 
109
            GDALRasterBand* poBandtmp = NULL;
 
110
            if (poTmpDataset)
 
111
            {
 
112
                poBandtmp = poTmpDataset->GetRasterBand(band);
 
113
            }
 
114
 
 
115
            int yOffset = ry + row * rowOffset;
 
116
            bool bReadFailed = false;
 
117
            if (poBand)
 
118
            {
 
119
                CPLErr errTest = 
 
120
                    poBand->RasterIO( GF_Read, rx, yOffset, rxsize, rowOffset, pafScanline, dxsize, 1, GDT_Byte, 0, 0);
 
121
 
 
122
                if ( errTest == CE_Failure )
 
123
                {
 
124
                    hasNoData = 1;
 
125
                    bReadFailed = true;
 
126
                }
 
127
            }
 
128
 
 
129
 
 
130
            //fill the true or false for hadnoData array if the source data has nodata value
 
131
            if (isJpegDriver == false)
 
132
            {
 
133
                if (hasNoData == 1)
 
134
                {
 
135
                    for (int j = 0; j < dxsize; j++)
 
136
                    {
 
137
                        double v = pafScanline[j];
 
138
                        double tmpv = v;
 
139
                        if (isSigned)
 
140
                        {
 
141
                            tmpv -= 128;
 
142
                        }
 
143
                        if (tmpv == noDataValue || bReadFailed == true)
 
144
                        {
 
145
                            hadnoData[j] = true;
 
146
                        }
 
147
                    }
 
148
                }
 
149
            }
 
150
 
 
151
            if (poBandtmp && bReadFailed == false)
 
152
            {
 
153
                poBandtmp->RasterIO(GF_Write, 0, row, dxsize, 1, pafScanline, dxsize, 1, GDT_Byte, 
 
154
                                    0, 0);
 
155
            }
 
156
        } 
 
157
 
 
158
        //fill the values for alpha band
 
159
        if (isJpegDriver == false)
 
160
        {
 
161
            if (alphaBand)
 
162
            {
 
163
                for (int i = 0; i < dxsize; i++)
 
164
                {
 
165
                    if (hadnoData[i] == true)
 
166
                    {
 
167
                        pafScanline[i] = 0;
 
168
                    }
 
169
                    else
 
170
                    {
 
171
                        pafScanline[i] = 255;
 
172
                    }
 
173
                }    
 
174
 
 
175
                alphaBand->RasterIO(GF_Write, 0, row, dxsize, 1, pafScanline, dxsize, 1, GDT_Byte, 
 
176
                                    0, 0);
 
177
            }
 
178
        }
 
179
    }
 
180
 
 
181
    delete [] pafScanline;
 
182
    delete [] hadnoData;
 
183
 
 
184
    GDALDataset* outDs = poOutputTileDriver->CreateCopy(filename.c_str(), poTmpDataset, FALSE, NULL, NULL, NULL);
 
185
 
 
186
    GDALClose(poTmpDataset);
 
187
    if (outDs)
 
188
        GDALClose(outDs);
 
189
}
 
190
 
 
191
/************************************************************************/
 
192
/*                          GenerateRootKml()                           */
 
193
/************************************************************************/
 
194
 
 
195
static
 
196
int  GenerateRootKml(const char* filename, 
 
197
                     const char* kmlfilename,
 
198
                     double north, 
 
199
                     double south, 
 
200
                     double east, 
 
201
                     double west, 
 
202
                     int tilesize)
 
203
{
 
204
    VSILFILE* fp = VSIFOpenL(filename, "wb");
 
205
    if (fp == NULL)
 
206
    {
 
207
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot create %s",
 
208
                 filename);
 
209
        return FALSE;
 
210
    }
 
211
    int minlodpixels = tilesize/2;
 
212
 
 
213
    const char* tmpfilename = CPLGetBasename(kmlfilename);
 
214
    // If we haven't writen any features yet, output the layer's schema
 
215
    VSIFPrintfL(fp, "<kml xmlns=\"http://earth.google.com/kml/2.1\">\n");
 
216
    VSIFPrintfL(fp, "\t<Document>\n");
 
217
    VSIFPrintfL(fp, "\t\t<name>%s</name>\n", tmpfilename);
 
218
    VSIFPrintfL(fp, "\t\t<description></description>\n");
 
219
    VSIFPrintfL(fp, "\t\t<Style>\n");
 
220
    VSIFPrintfL(fp, "\t\t\t<ListStyle id=\"hideChildren\">\n");
 
221
    VSIFPrintfL(fp, "\t\t\t\t<listItemType>checkHideChildren</listItemType>\n");
 
222
    VSIFPrintfL(fp, "\t\t\t</ListStyle>\n");
 
223
    VSIFPrintfL(fp, "\t\t</Style>\n");
 
224
    VSIFPrintfL(fp, "\t\t<Region>\n \t\t<LatLonAltBox>\n");
 
225
    VSIFPrintfL(fp, "\t\t\t\t<north>%f</north>\n", north);
 
226
    VSIFPrintfL(fp, "\t\t\t\t<south>%f</south>\n", south);
 
227
    VSIFPrintfL(fp, "\t\t\t\t<east>%f</east>\n", east);
 
228
    VSIFPrintfL(fp, "\t\t\t\t<west>%f</west>\n", west);
 
229
    VSIFPrintfL(fp, "\t\t\t</LatLonAltBox>\n");
 
230
    VSIFPrintfL(fp, "\t\t</Region>\n");
 
231
    VSIFPrintfL(fp, "\t\t<NetworkLink>\n");
 
232
    VSIFPrintfL(fp, "\t\t\t<open>1</open>\n");
 
233
    VSIFPrintfL(fp, "\t\t\t<Region>\n");
 
234
    VSIFPrintfL(fp, "\t\t\t\t<Lod>\n");
 
235
    VSIFPrintfL(fp, "\t\t\t\t\t<minLodPixels>%d</minLodPixels>\n", minlodpixels);
 
236
    VSIFPrintfL(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
 
237
    VSIFPrintfL(fp, "\t\t\t\t</Lod>\n");
 
238
    VSIFPrintfL(fp, "\t\t\t\t<LatLonAltBox>\n");
 
239
    VSIFPrintfL(fp, "\t\t\t\t\t<north>%f</north>\n", north);
 
240
    VSIFPrintfL(fp, "\t\t\t\t\t<south>%f</south>\n", south);
 
241
    VSIFPrintfL(fp, "\t\t\t\t\t<east>%f</east>\n", east);
 
242
    VSIFPrintfL(fp, "\t\t\t\t\t<west>%f</west>\n", west);
 
243
    VSIFPrintfL(fp, "\t\t\t\t</LatLonAltBox>\n");
 
244
    VSIFPrintfL(fp, "\t\t\t</Region>\n");
 
245
    VSIFPrintfL(fp, "\t\t\t<Link>\n");
 
246
    VSIFPrintfL(fp, "\t\t\t\t<href>0/0/0.kml</href>\n");
 
247
    VSIFPrintfL(fp, "\t\t\t\t<viewRefreshMode>onRegion</viewRefreshMode>\n");
 
248
    VSIFPrintfL(fp, "\t\t\t</Link>\n");
 
249
    VSIFPrintfL(fp, "\t\t</NetworkLink>\n");
 
250
    VSIFPrintfL(fp, "\t</Document>\n");
 
251
    VSIFPrintfL(fp, "</kml>\n");
 
252
 
 
253
    VSIFCloseL(fp);
 
254
    return TRUE;
 
255
}
 
256
 
 
257
/************************************************************************/
 
258
/*                          GenerateChildKml()                          */
 
259
/************************************************************************/
 
260
 
 
261
static
 
262
int  GenerateChildKml(std::string filename, 
 
263
                      int zoom, int ix, int iy, 
 
264
                      double zoomxpixel, double zoomypixel, int dxsize, int dysize, 
 
265
                      double south, double west, int xsize, 
 
266
                      int ysize, int maxzoom, 
 
267
                      OGRCoordinateTransformation * poTransform,
 
268
                      std::string fileExt)
 
269
{
 
270
    double tnorth = south + zoomypixel *((iy + 1)*dysize);
 
271
    double tsouth = south + zoomypixel *(iy*dysize);
 
272
    double teast = west + zoomxpixel*((ix+1)*dxsize);
 
273
    double twest = west + zoomxpixel*ix*dxsize;
 
274
 
 
275
    double upperleftT = twest;
 
276
    double lowerleftT = twest;
 
277
 
 
278
    double rightbottomT = tsouth;
 
279
    double leftbottomT = tsouth;
 
280
 
 
281
    double lefttopT = tnorth;
 
282
    double righttopT = tnorth;
 
283
 
 
284
    double lowerrightT = teast;
 
285
    double upperrightT = teast;
 
286
 
 
287
    if (poTransform)
 
288
    {
 
289
        poTransform->Transform(1, &twest, &tsouth);
 
290
        poTransform->Transform(1, &teast, &tnorth);
 
291
 
 
292
        poTransform->Transform(1, &upperleftT, &lefttopT);
 
293
        poTransform->Transform(1, &upperrightT, &righttopT);
 
294
        poTransform->Transform(1, &lowerrightT, &rightbottomT);
 
295
        poTransform->Transform(1, &lowerleftT, &leftbottomT);
 
296
    }
 
297
 
 
298
    std::vector<int> xchildren;
 
299
    std::vector<int> ychildern;
 
300
 
 
301
    int maxLodPix = -1;
 
302
    if ( zoom < maxzoom )
 
303
    {
 
304
        double zareasize = pow(2.0, (maxzoom - zoom - 1))*dxsize;
 
305
        double zareasize1 = pow(2.0, (maxzoom - zoom - 1))*dysize;
 
306
        xchildren.push_back(ix*2);
 
307
        int tmp = ix*2 + 1;
 
308
        int tmp1 = (int)ceil(xsize / zareasize);
 
309
        if (tmp < tmp1)
 
310
        {
 
311
            xchildren.push_back(ix*2+1);
 
312
        }
 
313
        ychildern.push_back(iy*2);
 
314
        tmp = iy*2 + 1;
 
315
        tmp1 = (int)ceil(ysize / zareasize1);
 
316
        if (tmp < tmp1)
 
317
        {
 
318
            ychildern.push_back(iy*2+1);
 
319
        }     
 
320
        maxLodPix = 2048;
 
321
    }
 
322
 
 
323
    VSILFILE* fp = VSIFOpenL(filename.c_str(), "wb");
 
324
    if (fp == NULL)
 
325
    {
 
326
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot create %s",
 
327
                 filename.c_str());
 
328
        return FALSE;
 
329
    }
 
330
 
 
331
    VSIFPrintfL(fp, "<kml xmlns=\"http://earth.google.com/kml/2.1\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\">\n");
 
332
    VSIFPrintfL(fp, "\t<Document>\n");
 
333
    VSIFPrintfL(fp, "\t\t<name>%d/%d/%d.kml</name>\n", zoom, ix, iy);
 
334
    VSIFPrintfL(fp, "\t\t<Style>\n");
 
335
    VSIFPrintfL(fp, "\t\t\t<ListStyle id=\"hideChildren\">\n");
 
336
    VSIFPrintfL(fp, "\t\t\t\t<listItemType>checkHideChildren</listItemType>\n");
 
337
    VSIFPrintfL(fp, "\t\t\t</ListStyle>\n");
 
338
    VSIFPrintfL(fp, "\t\t</Style>\n");
 
339
    VSIFPrintfL(fp, "\t\t<Region>\n");
 
340
    VSIFPrintfL(fp, "\t\t\t<Lod>\n");
 
341
    VSIFPrintfL(fp, "\t\t\t\t<minLodPixels>%d</minLodPixels>\n", 128);
 
342
    VSIFPrintfL(fp, "\t\t\t\t<maxLodPixels>%d</maxLodPixels>\n", maxLodPix);
 
343
    VSIFPrintfL(fp, "\t\t\t</Lod>\n");
 
344
    VSIFPrintfL(fp, "\t\t\t<LatLonAltBox>\n");
 
345
    VSIFPrintfL(fp, "\t\t\t\t<north>%f</north>\n", tnorth);
 
346
    VSIFPrintfL(fp, "\t\t\t\t<south>%f</south>\n", tsouth);
 
347
    VSIFPrintfL(fp, "\t\t\t\t<east>%f</east>\n", teast);
 
348
    VSIFPrintfL(fp, "\t\t\t\t<west>%f</west>\n", twest);
 
349
    VSIFPrintfL(fp, "\t\t\t</LatLonAltBox>\n");
 
350
    VSIFPrintfL(fp, "\t\t</Region>\n");
 
351
    VSIFPrintfL(fp, "\t\t<GroundOverlay>\n");
 
352
    VSIFPrintfL(fp, "\t\t\t<drawOrder>%d</drawOrder>\n", zoom);
 
353
    VSIFPrintfL(fp, "\t\t\t<Icon>\n");
 
354
    VSIFPrintfL(fp, "\t\t\t\t<href>%d%s</href>\n", iy, fileExt.c_str());
 
355
    VSIFPrintfL(fp, "\t\t\t</Icon>\n");
 
356
    VSIFPrintfL(fp, "\t\t\t<gx:LatLonQuad>\n");
 
357
    VSIFPrintfL(fp, "\t\t\t\t<coordinates>\n");
 
358
    VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", lowerleftT, leftbottomT);
 
359
    VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", lowerrightT, rightbottomT);
 
360
    VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", upperrightT, righttopT);
 
361
    VSIFPrintfL(fp, "\t\t\t\t\t%f,%f,0\n", upperleftT, lefttopT);
 
362
    VSIFPrintfL(fp, "\t\t\t\t</coordinates>\n");
 
363
    VSIFPrintfL(fp, "\t\t\t</gx:LatLonQuad>\n");
 
364
    VSIFPrintfL(fp, "\t\t</GroundOverlay>\n");
 
365
 
 
366
    for (unsigned int i = 0; i < xchildren.size(); i++)
 
367
    {
 
368
        int cx = xchildren[i];
 
369
        for (unsigned int j = 0; j < ychildern.size(); j++)
 
370
        {
 
371
            int cy = ychildern[j];
 
372
 
 
373
            double cnorth = south + zoomypixel/2 *((cy + 1)*dysize);
 
374
            double csouth = south + zoomypixel/2 *(cy*dysize);
 
375
            double ceast = west + zoomxpixel/2*((cx+1)*dxsize);
 
376
            double cwest = west + zoomxpixel/2*cx*dxsize;
 
377
 
 
378
            if (poTransform)
 
379
            {
 
380
                poTransform->Transform(1, &cwest, &csouth);
 
381
                poTransform->Transform(1, &ceast, &cnorth);
 
382
            }
 
383
 
 
384
            VSIFPrintfL(fp, "\t\t<NetworkLink>\n");
 
385
            VSIFPrintfL(fp, "\t\t\t<name>%d/%d/%d%s</name>\n", zoom+1, cx, cy, fileExt.c_str());
 
386
            VSIFPrintfL(fp, "\t\t\t<Region>\n");
 
387
            VSIFPrintfL(fp, "\t\t\t\t<Lod>\n");
 
388
            VSIFPrintfL(fp, "\t\t\t\t\t<minLodPixels>128</minLodPixels>\n");
 
389
            VSIFPrintfL(fp, "\t\t\t\t\t<maxLodPixels>-1</maxLodPixels>\n");
 
390
            VSIFPrintfL(fp, "\t\t\t\t</Lod>\n");
 
391
            VSIFPrintfL(fp, "\t\t\t\t<LatLonAltBox>\n");
 
392
            VSIFPrintfL(fp, "\t\t\t\t\t<north>%f</north>\n", cnorth);
 
393
            VSIFPrintfL(fp, "\t\t\t\t\t<south>%f</south>\n", csouth);
 
394
            VSIFPrintfL(fp, "\t\t\t\t\t<east>%f</east>\n", ceast);
 
395
            VSIFPrintfL(fp, "\t\t\t\t\t<west>%f</west>\n", cwest);
 
396
            VSIFPrintfL(fp, "\t\t\t\t</LatLonAltBox>\n");
 
397
            VSIFPrintfL(fp, "\t\t\t</Region>\n");
 
398
            VSIFPrintfL(fp, "\t\t\t<Link>\n");
 
399
            VSIFPrintfL(fp, "\t\t\t\t<href>../../%d/%d/%d.kml</href>\n", zoom+1, cx, cy);
 
400
            VSIFPrintfL(fp, "\t\t\t\t<viewRefreshMode>onRegion</viewRefreshMode>\n");
 
401
            VSIFPrintfL(fp, "\t\t\t\t<viewFormat/>\n");
 
402
            VSIFPrintfL(fp, "\t\t\t</Link>\n");
 
403
            VSIFPrintfL(fp, "\t\t</NetworkLink>\n");
 
404
        }
 
405
    }
 
406
 
 
407
    VSIFPrintfL(fp, "\t</Document>\n");
 
408
    VSIFPrintfL(fp, "</kml>\n");
 
409
    VSIFCloseL(fp);
 
410
    
 
411
    return TRUE;
 
412
}
 
413
 
 
414
/************************************************************************/
 
415
/*                           zipWithMinizip()                           */
 
416
/************************************************************************/
 
417
bool zipWithMinizip(std::vector<std::string> srcFiles, std::string srcDirectory, std::string targetFile)
 
418
{
 
419
    void  *zipfile = CPLCreateZip(targetFile.c_str(), NULL);
 
420
    if (!zipfile)
 
421
    {
 
422
        CPLError( CE_Failure, CPLE_FileIO,
 
423
                  "Unable to open target zip file.." );
 
424
        return false;
 
425
    }
 
426
 
 
427
    std::vector <std::string>::iterator v1_Iter;
 
428
    for(v1_Iter = srcFiles.begin(); v1_Iter != srcFiles.end(); v1_Iter++)
 
429
    {
 
430
        std::string fileRead = *v1_Iter;
 
431
 
 
432
        // Find relative path and open new file with zip file
 
433
        std::string relativeFileReadPath = fileRead;
 
434
        int remNumChars = srcDirectory.size();
 
435
        if(remNumChars > 0)
 
436
        {
 
437
            int f = fileRead.find(srcDirectory);
 
438
            if( f >= 0 )
 
439
            {
 
440
                relativeFileReadPath.erase(f, remNumChars + 1); // 1 added for backslash at the end
 
441
            }      
 
442
        }
 
443
 
 
444
        std::basic_string<char>::iterator iter1;
 
445
        for (iter1 = relativeFileReadPath.begin(); iter1 != relativeFileReadPath.end(); iter1++)
 
446
        {
 
447
            int f = relativeFileReadPath.find("\\");
 
448
            if (f >= 0)
 
449
            {
 
450
                relativeFileReadPath.replace(f, 1, "/");
 
451
            }
 
452
            else
 
453
            {
 
454
                break;
 
455
            }
 
456
        }
 
457
        if (CPLCreateFileInZip(zipfile, relativeFileReadPath.c_str(), NULL) != CE_None)
 
458
        {
 
459
            CPLError( CE_Failure, CPLE_FileIO,
 
460
                      "Unable to create file within the zip file.." );
 
461
            return false;
 
462
        }
 
463
 
 
464
        // Read source file and write to zip file
 
465
        VSILFILE* fp = VSIFOpenL(fileRead.c_str(), "rb");
 
466
        if (fp == NULL)
 
467
        {
 
468
            CPLError( CE_Failure, CPLE_FileIO,
 
469
                      "Could not open source file.." );
 
470
            return false;
 
471
        }
 
472
 
 
473
        // Read file in buffer
 
474
        std::string fileData;
 
475
        const unsigned int bufSize = 1024;
 
476
        char buf[bufSize];
 
477
        int nRead;
 
478
        while((nRead = VSIFReadL(buf, 1, bufSize, fp)) != 0)
 
479
        {
 
480
            if ( CPLWriteFileInZip(zipfile, buf, nRead) != CE_None )
 
481
            {
 
482
                CPLError( CE_Failure, CPLE_FileIO,
 
483
                        "Could not write to file within zip file.." );
 
484
                CPLCloseFileInZip(zipfile);
 
485
                CPLCloseZip(zipfile);
 
486
                VSIFCloseL(fp);
 
487
                return false;
 
488
            }
 
489
        }
 
490
 
 
491
        VSIFCloseL(fp);
 
492
 
 
493
        // Close one src file zipped completely
 
494
        if ( CPLCloseFileInZip(zipfile) != CE_None )
 
495
        {
 
496
            CPLError( CE_Failure, CPLE_FileIO,
 
497
                      "Could not close file written within zip file.." );
 
498
            CPLCloseZip(zipfile);
 
499
            return false;
 
500
        }
 
501
    }
 
502
 
 
503
    CPLCloseZip(zipfile);
 
504
 
 
505
    return true;
 
506
}
 
507
 
 
508
/************************************************************************/
 
509
/*                       KmlSuperOverlayDataset()                       */
 
510
/************************************************************************/
 
511
 
 
512
KmlSuperOverlayDataset::KmlSuperOverlayDataset()
 
513
 
 
514
{
 
515
    bGeoTransformSet = FALSE;
 
516
}
 
517
 
 
518
/************************************************************************/
 
519
/*                      ~KmlSuperOverlayDataset()                       */
 
520
/************************************************************************/
 
521
 
 
522
KmlSuperOverlayDataset::~KmlSuperOverlayDataset()
 
523
   
 
524
{
 
525
    FlushCache();
 
526
}
 
527
 
 
528
/************************************************************************/
 
529
/*                          GetProjectionRef()                          */
 
530
/************************************************************************/
 
531
 
 
532
const char *KmlSuperOverlayDataset::GetProjectionRef()
 
533
   
 
534
{
 
535
    return SRS_WKT_WGS84;
 
536
}
 
537
 
 
538
/************************************************************************/
 
539
/*                   KMLSuperOverlayRecursiveUnlink()                   */
 
540
/************************************************************************/
 
541
 
 
542
static void KMLSuperOverlayRecursiveUnlink( const char *pszName )
 
543
 
 
544
{
 
545
    char **papszFileList;
 
546
    int i;
 
547
 
 
548
    papszFileList = CPLReadDir( pszName );
 
549
 
 
550
    for( i = 0; papszFileList != NULL && papszFileList[i] != NULL; i++ )
 
551
    {
 
552
        VSIStatBufL  sStatBuf;
 
553
 
 
554
        if( EQUAL(papszFileList[i],".") || EQUAL(papszFileList[i],"..") )
 
555
            continue;
 
556
 
 
557
        CPLString osFullFilename =
 
558
                 CPLFormFilename( pszName, papszFileList[i], NULL );
 
559
 
 
560
        VSIStatL( osFullFilename, &sStatBuf );
 
561
 
 
562
        if( VSI_ISREG( sStatBuf.st_mode ) )
 
563
        {
 
564
            VSIUnlink( osFullFilename );
 
565
        }
 
566
        else if( VSI_ISDIR( sStatBuf.st_mode ) )
 
567
        {
 
568
            KMLSuperOverlayRecursiveUnlink( osFullFilename );
 
569
        }
 
570
    }
 
571
 
 
572
    CSLDestroy( papszFileList );
 
573
 
 
574
    VSIRmdir( pszName );
 
575
}
 
576
 
 
577
/************************************************************************/
 
578
/*                           CreateCopy()                               */
 
579
/************************************************************************/
 
580
 
 
581
GDALDataset *KmlSuperOverlayDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
 
582
                                                 int bStrict, char ** papszOptions, GDALProgressFunc pfnProgress, void * pProgressData)
 
583
{
 
584
    bool isKmz = false;
 
585
 
 
586
    int bands = poSrcDS->GetRasterCount();
 
587
    if (bands != 1 && bands != 3 && bands != 4)
 
588
        return NULL;
 
589
   
 
590
    //correct the file and get the directory
 
591
    char* output_dir = NULL;
 
592
    if (pszFilename == NULL)
 
593
    {
 
594
        output_dir = CPLGetCurrentDir();
 
595
        pszFilename = CPLFormFilename(output_dir, "doc", "kml");
 
596
    }
 
597
    else
 
598
    {
 
599
        const char* extension = CPLGetExtension(pszFilename);
 
600
        if (!EQUAL(extension,"kml") && !EQUAL(extension,"kmz"))
 
601
        {
 
602
            CPLError( CE_Failure, CPLE_None,
 
603
                      "File extension should be kml or kmz." );
 
604
            return NULL;
 
605
        }
 
606
        if (EQUAL(extension,"kmz"))
 
607
        {
 
608
            isKmz = true;
 
609
        }
 
610
    
 
611
        output_dir = CPLStrdup(CPLGetPath(pszFilename));
 
612
        if (strcmp(output_dir, "") == 0)
 
613
        {
 
614
            CPLFree(output_dir);
 
615
            output_dir = CPLGetCurrentDir();
 
616
        }
 
617
    }
 
618
    CPLString outDir = output_dir;
 
619
    CPLFree(output_dir);
 
620
    output_dir = NULL;
 
621
 
 
622
    KmlSuperOverlayDataset *poDsDummy = new KmlSuperOverlayDataset();
 
623
 
 
624
    if (isKmz)
 
625
    {
 
626
        outDir = CPLFormFilename(outDir, CPLSPrintf("kmlsuperoverlaytmp_%p", poDsDummy) , NULL);
 
627
        if (VSIMkdir(outDir, 0755) != 0)
 
628
        {
 
629
            CPLError( CE_Failure, CPLE_None,
 
630
                    "Cannot create %s", outDir.c_str() );
 
631
            delete poDsDummy;
 
632
            return NULL;
 
633
        }
 
634
    }
 
635
 
 
636
    GDALDriver* poOutputTileDriver = NULL;
 
637
    bool isJpegDriver = true;
 
638
 
 
639
    const char* pszFormat = CSLFetchNameValueDef(papszOptions, "FORMAT", "JPEG");
 
640
    if (EQUAL(pszFormat, "PNG"))
 
641
    {
 
642
        isJpegDriver = false;
 
643
    }
 
644
 
 
645
    GDALDriver* poMemDriver = GetGDALDriverManager()->GetDriverByName("MEM");
 
646
    poOutputTileDriver = GetGDALDriverManager()->GetDriverByName(pszFormat);
 
647
 
 
648
    if( poMemDriver == NULL || poOutputTileDriver == NULL)
 
649
    {
 
650
        CPLError( CE_Failure, CPLE_None,
 
651
                  "Image export driver was not found.." );
 
652
        delete poDsDummy;
 
653
        if (isKmz)
 
654
            KMLSuperOverlayRecursiveUnlink(outDir);
 
655
        return NULL;
 
656
    }
 
657
 
 
658
    int xsize = poSrcDS->GetRasterXSize();
 
659
    int ysize = poSrcDS->GetRasterYSize();
 
660
 
 
661
    double north = 0.0;
 
662
    double south = 0.0;
 
663
    double east = 0.0;
 
664
    double west = 0.0;
 
665
 
 
666
    double      adfGeoTransform[6];
 
667
 
 
668
    if( poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None )
 
669
    {
 
670
        north = adfGeoTransform[3];
 
671
        south = adfGeoTransform[3] + adfGeoTransform[5]*ysize;
 
672
        east = adfGeoTransform[0] + adfGeoTransform[1]*xsize;
 
673
        west = adfGeoTransform[0];
 
674
    }
 
675
 
 
676
    OGRCoordinateTransformation * poTransform = NULL;
 
677
    if (poSrcDS->GetProjectionRef() != NULL)
 
678
    {
 
679
        OGRSpatialReference poDsUTM;
 
680
     
 
681
        char* projStr = (char*)poSrcDS->GetProjectionRef();
 
682
     
 
683
        if (poDsUTM.importFromWkt(&projStr) == OGRERR_NONE)
 
684
        {
 
685
            if (poDsUTM.IsProjected())
 
686
            {
 
687
                OGRSpatialReference poLatLong;
 
688
                poLatLong.SetWellKnownGeogCS( "WGS84" );
 
689
           
 
690
                poTransform = OGRCreateCoordinateTransformation( &poDsUTM, &poLatLong );
 
691
                if( poTransform != NULL )
 
692
                {
 
693
                    poTransform->Transform(1, &west, &south);
 
694
                    poTransform->Transform(1, &east, &north);
 
695
                }
 
696
            }
 
697
        }
 
698
    }
 
699
 
 
700
    //Zoom levels of the pyramid.
 
701
    int maxzoom;
 
702
    int tilexsize;
 
703
    int tileysize;
 
704
    // Let the longer side determine the max zoom level and x/y tilesizes.
 
705
    if ( xsize >= ysize )
 
706
    {
 
707
        double dtilexsize = xsize;
 
708
        while (dtilexsize > 400) //calculate x tile size
 
709
        {
 
710
            dtilexsize = dtilexsize/2;
 
711
        }
 
712
 
 
713
        maxzoom   = static_cast<int>(log( (double)xsize / dtilexsize ) / log(2.0));
 
714
        tilexsize = (int)dtilexsize;
 
715
        tileysize = (int)( (double)(dtilexsize * ysize) / xsize );
 
716
    }
 
717
    else
 
718
    {
 
719
        double dtileysize = ysize;
 
720
        while (dtileysize > 400) //calculate y tile size
 
721
        {
 
722
            dtileysize = dtileysize/2;
 
723
        }
 
724
 
 
725
        maxzoom   = static_cast<int>(log( (double)ysize / dtileysize ) / log(2.0));
 
726
        tileysize = (int)dtileysize;
 
727
        tilexsize = (int)( (double)(dtileysize * xsize) / ysize );
 
728
    }
 
729
    maxzoom = 0;
 
730
 
 
731
    std::vector<double> zoomxpixels;
 
732
    std::vector<double> zoomypixels;
 
733
    for (int zoom = 0; zoom < maxzoom + 1; zoom++)
 
734
    {
 
735
        zoomxpixels.push_back(adfGeoTransform[1] * pow(2.0, (maxzoom - zoom)));
 
736
        // zoomypixels.push_back(abs(adfGeoTransform[5]) * pow(2.0, (maxzoom - zoom)));
 
737
        zoomypixels.push_back(fabs(adfGeoTransform[5]) * pow(2.0, (maxzoom - zoom)));
 
738
    }
 
739
 
 
740
    std::string tmpFileName; 
 
741
    std::vector<std::string> fileVector;
 
742
    int nRet;
 
743
    if (isKmz)
 
744
    {
 
745
        tmpFileName = CPLFormFilename(outDir, "tmp.kml", NULL);
 
746
        nRet = GenerateRootKml(tmpFileName.c_str(), pszFilename, north, south, east, west, (int)tilexsize);
 
747
        fileVector.push_back(tmpFileName);
 
748
    }
 
749
    else
 
750
    {
 
751
        nRet = GenerateRootKml(pszFilename, pszFilename, north, south, east, west, (int)tilexsize);
 
752
    }
 
753
    
 
754
    if (nRet == FALSE)
 
755
    {
 
756
        OGRCoordinateTransformation::DestroyCT( poTransform );
 
757
        delete poDsDummy;
 
758
        if (isKmz)
 
759
            KMLSuperOverlayRecursiveUnlink(outDir);
 
760
        return NULL;
 
761
    }
 
762
 
 
763
    for (int zoom = maxzoom; zoom >= 0; --zoom)
 
764
    {
 
765
        int rmaxxsize = static_cast<int>(pow(2.0, (maxzoom-zoom)) * tilexsize);
 
766
        int rmaxysize = static_cast<int>(pow(2.0, (maxzoom-zoom)) * tileysize);
 
767
 
 
768
        int xloop = (int)xsize/rmaxxsize;
 
769
        int yloop = (int)ysize/rmaxysize;
 
770
 
 
771
        xloop = xloop>0 ? xloop : 1;
 
772
        yloop = yloop>0 ? yloop : 1;
 
773
        for (int ix = 0; ix < xloop; ix++)
 
774
        {
 
775
            int rxsize = (int)(rmaxxsize);
 
776
            int rx = (int)(ix * rmaxxsize);
 
777
 
 
778
            for (int iy = 0; iy < yloop; iy++)
 
779
            {
 
780
                int rysize = (int)(rmaxysize);
 
781
                int ry = (int)(ysize - (iy * rmaxysize)) - rysize;
 
782
 
 
783
                int dxsize = (int)(rxsize/rmaxxsize * tilexsize);
 
784
                int dysize = (int)(rysize/rmaxysize * tileysize);
 
785
 
 
786
                std::stringstream zoomStr;
 
787
                std::stringstream ixStr;
 
788
                std::stringstream iyStr;
 
789
 
 
790
                zoomStr << zoom;
 
791
                ixStr << ix;
 
792
                iyStr << iy;
 
793
 
 
794
                std::string zoomDir = outDir;
 
795
                zoomDir+= "/" + zoomStr.str();
 
796
                VSIMkdir(zoomDir.c_str(), 0775);
 
797
        
 
798
 
 
799
                zoomDir = zoomDir + "/" + ixStr.str();
 
800
                VSIMkdir(zoomDir.c_str(), 0775);
 
801
 
 
802
                std::string fileExt = ".jpg";
 
803
                if (isJpegDriver == false)
 
804
                {
 
805
                    fileExt = ".png";
 
806
                }
 
807
                std::string filename = zoomDir + "/" + iyStr.str() + fileExt;
 
808
                if (isKmz)
 
809
                {
 
810
                    fileVector.push_back(filename);
 
811
                }
 
812
 
 
813
                GenerateTiles(filename, zoom, rxsize, rysize, ix, iy, rx, ry, dxsize, 
 
814
                              dysize, bands, poSrcDS, poOutputTileDriver, poMemDriver, isJpegDriver);
 
815
                std::string childKmlfile = zoomDir + "/" + iyStr.str() + ".kml";
 
816
                if (isKmz)
 
817
                {
 
818
                    fileVector.push_back(childKmlfile);
 
819
                }
 
820
 
 
821
                double tmpSouth = adfGeoTransform[3] + adfGeoTransform[5]*ysize;
 
822
                double zoomxpix = zoomxpixels[zoom];
 
823
                double zoomypix = zoomypixels[zoom];
 
824
                if (zoomxpix == 0)
 
825
                {
 
826
                    zoomxpix = 1;
 
827
                }
 
828
 
 
829
                if (zoomypix == 0)
 
830
                {
 
831
                    zoomypix = 1;
 
832
                }
 
833
 
 
834
                GenerateChildKml(childKmlfile, zoom, ix, iy, zoomxpix, zoomypix, 
 
835
                                 dxsize, dysize, tmpSouth, adfGeoTransform[0], xsize, ysize, maxzoom, poTransform, fileExt);
 
836
            }
 
837
        }
 
838
    }
 
839
 
 
840
    OGRCoordinateTransformation::DestroyCT( poTransform );
 
841
    poTransform = NULL;
 
842
    
 
843
    if (isKmz)
 
844
    {
 
845
        std::string outputfile = pszFilename;
 
846
        bool zipDone = true;
 
847
        if (zipWithMinizip(fileVector, outDir, outputfile) == false)
 
848
        {
 
849
            CPLError( CE_Failure, CPLE_FileIO,
 
850
                      "Unable to do zip.." );
 
851
            zipDone = false;
 
852
        }
 
853
 
 
854
        KMLSuperOverlayRecursiveUnlink(outDir);
 
855
 
 
856
        if (zipDone == false)
 
857
        {
 
858
            delete poDsDummy;
 
859
            return NULL;
 
860
        }
 
861
    }
 
862
 
 
863
    return poDsDummy;
 
864
}
 
865
 
 
866
/************************************************************************/
 
867
/*                                Open()                                */
 
868
/************************************************************************/
 
869
 
 
870
GDALDataset *KmlSuperOverlayDataset::Open(GDALOpenInfo *)
 
871
 
 
872
{
 
873
    return NULL;
 
874
}
 
875
 
 
876
/************************************************************************/
 
877
/*                    KmlSuperOverlayDatasetDelete()                    */
 
878
/************************************************************************/
 
879
 
 
880
static CPLErr KmlSuperOverlayDatasetDelete(const char* fileName)
 
881
{
 
882
    /* Null implementation, so that people can Delete("MEM:::") */
 
883
    return CE_None;
 
884
}
 
885
 
 
886
/************************************************************************/
 
887
/*                    GDALRegister_KMLSUPEROVERLAY()                    */
 
888
/************************************************************************/
 
889
 
 
890
void GDALRegister_KMLSUPEROVERLAY()
 
891
   
 
892
{
 
893
    GDALDriver  *poDriver;
 
894
   
 
895
    if( GDALGetDriverByName( "KMLSUPEROVERLAY" ) == NULL )
 
896
    {
 
897
        poDriver = new GDALDriver();
 
898
      
 
899
        poDriver->SetDescription( "KMLSUPEROVERLAY" );
 
900
        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
 
901
                                   "Kml Super Overlay" );
 
902
        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
 
903
                                   "Byte Int16 UInt16 Int32 UInt32 Float32 Float64 CInt16 CInt32 CFloat32 CFloat64" );
 
904
 
 
905
        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
 
906
"<CreationOptionList>"
 
907
"   <Option name='FORMAT' type='string-select' default='JPEG' description='Force of the tiles'>"
 
908
"       <Value>PNG</Value>"
 
909
"       <Value>JPEG</Value>"
 
910
"   </Option>"
 
911
"</CreationOptionList>" );
 
912
 
 
913
        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
 
914
 
 
915
        poDriver->pfnOpen = KmlSuperOverlayDataset::Open;
 
916
        poDriver->pfnCreateCopy = KmlSuperOverlayDataset::CreateCopy;
 
917
        poDriver->pfnDelete = KmlSuperOverlayDatasetDelete;
 
918
      
 
919
        GetGDALDriverManager()->RegisterDriver( poDriver );
 
920
    }
 
921
}
 
922