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

Generated by: LCOV version 1.7