LCOV - code coverage report
Current view: directory - frmts/kmlsuperoverlay - kmlsuperoverlaydataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 457 336 73.5 %
Date: 2011-12-18 Functions: 18 12 66.7 %

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

Generated by: LCOV version 1.7