GDAL: cannot create and write a zip file with vsiz

2019-08-31 02:19发布

I'm trying to write a GeoTIFF to zip file with GDAL library and its virtual filesystem driver vsizip. Alas, it gives me an error:

ERROR 1: Random access not supported for writable file in /vsizip
ERROR 4: Attempt to create new tiff file `/vsizip/D:\Projects\oy_vey.zip\my.tif'
 failed: No such file or directory

How can I cope with it?

P.S. Here's my code:

#include "stdafx.h"
#include "MainWnd.h"
#include <QtWidgets/QApplication>

#include <gdal.h>
#include <gdal_priv.h>
#include <gdal_frmts.h>
#include <ogr_spatialref.h>

int main(int argc, char *argv[])
{
    //QApplication a(argc, argv);
    //MainWnd w;
    //w.show();
    //return a.exec();

    GDALRegister_GTiff();

    int numLatPx = 480;
    int numLonPx = 640;

    double northDeg = 3;
    double southDeg = 0;
    double westDeg = 0;
    double eastDeg = 4;


    double latStep = (northDeg - southDeg) / numLatPx;
    double lonStep = (eastDeg - westDeg) / numLonPx;


    GDALDriver* poDriver;
    char** papszMetadata;

    GDALDriverManager* driverManager = GetGDALDriverManager();
    poDriver = driverManager->GetDriverByName("GTiff");
    if (poDriver == NULL)
    {
        qDebug() << "GEOTIFF DRIVER NULL!!!";
        exit(1);
    }
    //it's okay so far...

    GDALDataset* poDstDS;

    double adfGeoTransform[6];
    adfGeoTransform[0] = westDeg; /* top left x */
    adfGeoTransform[1] = lonStep; /* w-e pixel resolution */
    adfGeoTransform[2] = 0; /* 0 */
    adfGeoTransform[3] = northDeg; /* top left y */
    adfGeoTransform[4] = 0; /* 0 */
    adfGeoTransform[5] = -latStep;/* n-s pixel resolution (negative value) */

    char** papszOptions = NULL;

    poDstDS = poDriver->Create("/vsizip/D:\\Projects\\oy_vey.zip\\my.tif", numLonPx, numLatPx, 1, GDT_Int16, papszOptions);
    // poDstDS will give NULL

    OGRSpatialReference oSRS;
    char *pszSRS_WKT = NULL;
    GDALRasterBand* poBand;

    poDstDS->SetGeoTransform(adfGeoTransform);
    //oSRS.importFromEPSG(4284); // PULKOVO 1942
    oSRS.exportToWkt(&pszSRS_WKT);

    poDstDS->SetProjection(pszSRS_WKT);
    CPLFree(pszSRS_WKT);
    poBand = poDstDS->GetRasterBand(1);

    GInt16* abyRaster = new GInt16[numLatPx * numLonPx];

    abyRaster[10000] = 0;
    abyRaster[10001] = 1;

    poBand->RasterIO(GF_Write, 0, 0, numLonPx, numLatPx, abyRaster, numLonPx, numLatPx, GDT_Int16, 0, 0);

    double minVal, maxVal, meanVal, stdDevVal;
    poBand->ComputeStatistics(false, &minVal, &maxVal, &meanVal, &stdDevVal, NULL, NULL);
    poBand->SetStatistics(minVal, maxVal, meanVal, stdDevVal);
    poBand->SetColorInterpretation(GCI_GrayIndex);


    /* Once we're done, close properly the dataset */
    GDALClose((GDALDatasetH)poDstDS);



    qDebug() << "^_^" << endl;
    return 0;
}

标签: zip gdal
1条回答
神经病院院长
2楼-- · 2019-08-31 03:05

GTiff driver Create() will attempt to open the dataset in read / write mode, which is not supported by the vsizip virtual filesystem.

As a workaround, you can do the following:

  1. Create a temp TIFF file
  2. Use the CopyFiles method with vsizip syntax
  3. Delete the temp file

Here is the how I changed your code (I'm on Linux so you should adjust the file path to use it on Windows).

int main(int argc, char *argv[])
{
    //QApplication a(argc, argv);
    //MainWnd w;
    //w.show();
    //return a.exec();

    GDALAllRegister();

    int numLatPx = 480;
    int numLonPx = 640;

    double northDeg = 3;
    double southDeg = 0;
    double westDeg = 0;
    double eastDeg = 4;


    double latStep = (northDeg - southDeg) / numLatPx;
    double lonStep = (eastDeg - westDeg) / numLonPx;


    GDALDriver* poDriver;
    char** papszMetadata;

    GDALDriverManager* driverManager = GetGDALDriverManager();
    poDriver = driverManager->GetDriverByName("GTiff");
    if (poDriver == NULL)
    {
        qDebug() << "GEOTIFF DRIVER NULL!!!";
        exit(1);
    }
    //it's okay so far...

    GDALDataset* poDstDS;

    double adfGeoTransform[6];
    adfGeoTransform[0] = westDeg; /* top left x */
    adfGeoTransform[1] = lonStep; /* w-e pixel resolution */
    adfGeoTransform[2] = 0; /* 0 */
    adfGeoTransform[3] = northDeg; /* top left y */
    adfGeoTransform[4] = 0; /* 0 */
    adfGeoTransform[5] = -latStep;/* n-s pixel resolution (negative value) */

    char** papszOptions = NULL;

    poDstDS = poDriver->Create("/home/me/my.tif", numLonPx, numLatPx, 1, GDT_Int16, papszOptions);
    // poDstDS will give NULL

    OGRSpatialReference oSRS;
    char *pszSRS_WKT = NULL;
    GDALRasterBand* poBand;

    poDstDS->SetGeoTransform(adfGeoTransform);
    //oSRS.importFromEPSG(4284); // PULKOVO 1942
    oSRS.exportToWkt(&pszSRS_WKT);

    poDstDS->SetProjection(pszSRS_WKT);
    CPLFree(pszSRS_WKT);
    poBand = poDstDS->GetRasterBand(1);

    GInt16* abyRaster = new GInt16[numLatPx * numLonPx];

    abyRaster[10000] = 0;
    abyRaster[10001] = 1;

    poBand->RasterIO(GF_Write, 0, 0, numLonPx, numLatPx, abyRaster, numLonPx, numLatPx, GDT_Int16, 0, 0);

    double minVal, maxVal, meanVal, stdDevVal;
    poBand->ComputeStatistics(false, &minVal, &maxVal, &meanVal, &stdDevVal, NULL, NULL);
    poBand->SetStatistics(minVal, maxVal, meanVal, stdDevVal);
    poBand->SetColorInterpretation(GCI_GrayIndex);


    /* Once we're done, close properly the dataset */
   GDALClose((GDALDatasetH)poDstDS);


   poDriver->CopyFiles("/vsizip//home/me/test.zip/my.tif", "/home/me/my.tif");


    qDebug() << "^_^" << endl;
    return 0;
}
查看更多
登录 后发表回答