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

« back to all changes in this revision

Viewing changes to .pc/epsilon/frmts/epsilon/epsilondataset.cpp

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

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/******************************************************************************
2
 
 * $Id: epsilondataset.cpp 17975 2009-11-08 20:51:31Z rouault $
3
 
 *
4
 
 * Project:  GDAL Epsilon driver
5
 
 * Purpose:  Implement GDAL Epsilon support using Epsilon library
6
 
 * Author:   Even Rouault, <even dot rouault at mines dash paris dot org>
7
 
 *
8
 
 **********************************************************************
9
 
 * Copyright (c) 2009, Even Rouault, <even dot rouault at mines dash paris dot org>
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 "epsilon.h"
31
 
#include "gdal_pam.h"
32
 
 
33
 
CPL_CVSID("$Id: epsilondataset.cpp 17975 2009-11-08 20:51:31Z rouault $");
34
 
 
35
 
#define RASTERLITE_WAVELET_HEADER "StartWaveletsImage$$"
36
 
#define RASTERLITE_WAVELET_FOOTER "$$EndWaveletsImage"
37
 
 
38
 
#define BLOCK_DATA_MAX_SIZE MAX(EPS_MAX_GRAYSCALE_BUF, EPS_MAX_TRUECOLOR_BUF)
39
 
 
40
 
class EpsilonRasterBand;
41
 
 
42
 
typedef struct
43
 
{
44
 
    int x;
45
 
    int y;
46
 
    int w;
47
 
    int h;
48
 
    vsi_l_offset offset;
49
 
} BlockDesc;
50
 
 
51
 
 
52
 
/************************************************************************/
53
 
/* ==================================================================== */
54
 
/*                              EpsilonDataset                          */
55
 
/* ==================================================================== */
56
 
/************************************************************************/
57
 
 
58
 
class EpsilonDataset : public GDALPamDataset
59
 
{
60
 
    friend class EpsilonRasterBand;
61
 
 
62
 
    FILE*    fp;
63
 
    vsi_l_offset nFileOff;
64
 
    
65
 
    GByte*   pabyFileBuf;
66
 
    int      nFileBufMaxSize;
67
 
    int      nFileBufCurSize;
68
 
    int      nFileBufOffset;
69
 
    int      bEOF;
70
 
    int      bError;
71
 
    
72
 
    GByte*   pabyBlockData;
73
 
    int      nBlockDataSize;
74
 
    vsi_l_offset nStartBlockFileOff;
75
 
    
76
 
    int      bRegularTiling;
77
 
    
78
 
    int        nBlocks;
79
 
    BlockDesc* pasBlocks;
80
 
    
81
 
    int      nBufferedBlock;
82
 
    GByte*   pabyRGBData;
83
 
    
84
 
    void     Seek(vsi_l_offset nPos);
85
 
    int      GetNextByte();
86
 
    int      GetNextBlockData();
87
 
    int      ScanBlocks(int *pnBands);
88
 
 
89
 
  public:
90
 
                 EpsilonDataset();
91
 
    virtual     ~EpsilonDataset();
92
 
    
93
 
    static GDALDataset *Open( GDALOpenInfo * );
94
 
    static int          Identify( GDALOpenInfo * );
95
 
};
96
 
 
97
 
/************************************************************************/
98
 
/* ==================================================================== */
99
 
/*                            EpsilonRasterBand                         */
100
 
/* ==================================================================== */
101
 
/************************************************************************/
102
 
 
103
 
class EpsilonRasterBand : public GDALPamRasterBand
104
 
{
105
 
  public:
106
 
                            EpsilonRasterBand(EpsilonDataset* poDS, int nBand);
107
 
                 
108
 
    virtual CPLErr          IReadBlock( int, int, void * );
109
 
    virtual GDALColorInterp GetColorInterpretation();
110
 
};
111
 
 
112
 
/************************************************************************/
113
 
/*                         EpsilonDataset()                             */
114
 
/************************************************************************/
115
 
 
116
 
EpsilonDataset::EpsilonDataset()
117
 
{
118
 
    fp = NULL;
119
 
    nFileOff = 0;
120
 
    
121
 
    pabyFileBuf = NULL;
122
 
    nFileBufMaxSize = 0;
123
 
    nFileBufCurSize = 0;
124
 
    nFileBufOffset = 0;
125
 
    bEOF = FALSE;
126
 
    bError = FALSE;
127
 
    
128
 
    pabyBlockData = NULL;
129
 
    nBlockDataSize = 0;
130
 
    nStartBlockFileOff = 0;
131
 
    
132
 
    bRegularTiling = FALSE;
133
 
    
134
 
    nBlocks = 0;
135
 
    pasBlocks = NULL;
136
 
    
137
 
    nBufferedBlock = -1;
138
 
    pabyRGBData = NULL;
139
 
}
140
 
 
141
 
/************************************************************************/
142
 
/*                         ~EpsilonDataset()                            */
143
 
/************************************************************************/
144
 
 
145
 
EpsilonDataset::~EpsilonDataset()
146
 
{
147
 
    if (fp)
148
 
        VSIFCloseL(fp);
149
 
    VSIFree(pabyFileBuf);
150
 
    VSIFree(pasBlocks);
151
 
    CPLFree(pabyRGBData);
152
 
}
153
 
 
154
 
/************************************************************************/
155
 
/*                       EpsilonRasterBand()                            */
156
 
/************************************************************************/
157
 
 
158
 
EpsilonRasterBand::EpsilonRasterBand(EpsilonDataset* poDS, int nBand)
159
 
{
160
 
    this->poDS = poDS;
161
 
    this->nBand = nBand;
162
 
    this->eDataType = GDT_Byte;
163
 
    this->nBlockXSize = poDS->pasBlocks[0].w;
164
 
    this->nBlockYSize = poDS->pasBlocks[0].h;
165
 
}
166
 
 
167
 
/************************************************************************/
168
 
/*                   GetColorInterpretation()                           */
169
 
/************************************************************************/
170
 
 
171
 
GDALColorInterp EpsilonRasterBand::GetColorInterpretation()
172
 
{
173
 
    EpsilonDataset* poGDS = (EpsilonDataset*) poDS;
174
 
    if (poGDS->nBands == 1)
175
 
    {
176
 
        return GCI_GrayIndex;
177
 
    }
178
 
    else
179
 
    {
180
 
        if (nBand == 1)
181
 
            return GCI_RedBand;
182
 
        else if (nBand == 2)
183
 
            return GCI_GreenBand;
184
 
        else
185
 
            return GCI_BlueBand;
186
 
    }
187
 
}
188
 
 
189
 
/************************************************************************/
190
 
/*                           IReadBlock()                               */
191
 
/************************************************************************/
192
 
 
193
 
CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
194
 
                                      int nBlockYOff, void * pImage)
195
 
{
196
 
    EpsilonDataset* poGDS = (EpsilonDataset*) poDS;
197
 
    
198
 
    //CPLDebug("EPSILON", "IReadBlock(nBand=%d,nBlockXOff=%d,nBlockYOff=%d)",
199
 
    //         nBand, nBlockXOff, nBlockYOff);
200
 
 
201
 
    int nBlocksPerRow = (poGDS->nRasterXSize + nBlockXSize - 1) / nBlockXSize;
202
 
    int nBlock = nBlockXOff + nBlockYOff * nBlocksPerRow;
203
 
    
204
 
    BlockDesc* psDesc = &poGDS->pasBlocks[nBlock];
205
 
#ifdef DEBUG
206
 
    int nBlocksPerColumn = (poGDS->nRasterYSize + nBlockYSize - 1) / nBlockYSize;
207
 
    CPLAssert(psDesc->x == nBlockXOff * nBlockXSize);
208
 
    CPLAssert(psDesc->y == nBlockYOff * nBlockYSize);
209
 
    CPLAssert(psDesc->w == (nBlockXOff < nBlocksPerRow - 1) ?
210
 
                                nBlockXSize : poGDS->nRasterXSize - psDesc->x);
211
 
    CPLAssert(psDesc->h == (nBlockYOff < nBlocksPerColumn - 1) ?
212
 
                                nBlockYSize : poGDS->nRasterYSize - psDesc->y);
213
 
#endif
214
 
 
215
 
    poGDS->Seek(psDesc->offset);
216
 
        
217
 
    if (!poGDS->GetNextBlockData())
218
 
    {
219
 
        memset(pImage, 0, nBlockXSize * nBlockYSize);
220
 
        return CE_Failure;
221
 
    }
222
 
    
223
 
    eps_block_header hdr;
224
 
    if (eps_read_block_header (poGDS->pabyBlockData,
225
 
                               poGDS->nBlockDataSize, &hdr) != EPS_OK)
226
 
    {
227
 
        CPLError(CE_Warning, CPLE_AppDefined, "cannot read block header");
228
 
        memset(pImage, 0, nBlockXSize * nBlockYSize);
229
 
        return CE_Failure;
230
 
    }
231
 
 
232
 
    if (hdr.chk_flag == EPS_BAD_CRC ||
233
 
        hdr.crc_flag == EPS_BAD_CRC)
234
 
    {
235
 
        CPLError(CE_Warning, CPLE_AppDefined, "bad CRC");
236
 
        memset(pImage, 0, nBlockXSize * nBlockYSize);
237
 
        return CE_Failure;
238
 
    }
239
 
    
240
 
    int w = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.w : hdr.tc.w;
241
 
    int h = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.h : hdr.tc.h;
242
 
    int i;
243
 
 
244
 
    if (poGDS->nBands == 1)
245
 
    {
246
 
        unsigned char ** pTempData =
247
 
            (unsigned char **) CPLMalloc(h * sizeof(unsigned char*));        
248
 
        for(i=0;i<h;i++)
249
 
            pTempData[i] = ((GByte*)pImage) + i * nBlockXSize;
250
 
 
251
 
        if (w != nBlockXSize || h != nBlockYSize)
252
 
            memset(pImage, 0, nBlockXSize * nBlockYSize);
253
 
 
254
 
        if (eps_decode_grayscale_block (pTempData,
255
 
                                        poGDS->pabyBlockData, &hdr) != EPS_OK)
256
 
        {
257
 
            CPLFree(pTempData);
258
 
            memset(pImage, 0, nBlockXSize * nBlockYSize);
259
 
            return CE_Failure;
260
 
        }
261
 
        CPLFree(pTempData);
262
 
    }
263
 
    else
264
 
    {
265
 
        if (poGDS->pabyRGBData == NULL)
266
 
        {
267
 
            poGDS->pabyRGBData =
268
 
                            (GByte*) VSIMalloc3(nBlockXSize, nBlockYSize, 3);
269
 
            if (poGDS->pabyRGBData == NULL)
270
 
            {
271
 
                memset(pImage, 0, nBlockXSize * nBlockYSize);
272
 
                return CE_Failure;
273
 
            }
274
 
        }
275
 
            
276
 
        if (poGDS->nBufferedBlock == nBlock)
277
 
        {
278
 
            memcpy(pImage,
279
 
                   poGDS->pabyRGBData + (nBand - 1) * nBlockXSize * nBlockYSize,
280
 
                   nBlockXSize * nBlockYSize);
281
 
            return CE_None;
282
 
        }
283
 
    
284
 
        unsigned char ** pTempData[3];
285
 
        int iBand;
286
 
        for(iBand=0;iBand<3;iBand++)
287
 
        {
288
 
            pTempData[iBand] =
289
 
                (unsigned char **) CPLMalloc(h * sizeof(unsigned char*));
290
 
            for(i=0;i<h;i++)
291
 
                pTempData[iBand][i] = poGDS->pabyRGBData +
292
 
                    iBand * nBlockXSize * nBlockYSize + i * nBlockXSize;
293
 
        }
294
 
    
295
 
        if (w != nBlockXSize || h != nBlockYSize)
296
 
            memset(poGDS->pabyRGBData, 0, 3 * nBlockXSize * nBlockYSize);
297
 
            
298
 
        if (eps_decode_truecolor_block (pTempData[0], pTempData[1], pTempData[2],
299
 
                                        poGDS->pabyBlockData, &hdr) != EPS_OK)
300
 
        {
301
 
            for(iBand=0;iBand<poGDS->nBands;iBand++)
302
 
                CPLFree(pTempData[iBand]);
303
 
            memset(pImage, 0, nBlockXSize * nBlockYSize);
304
 
            return CE_Failure;
305
 
        }
306
 
        
307
 
        for(iBand=0;iBand<poGDS->nBands;iBand++)
308
 
            CPLFree(pTempData[iBand]);
309
 
            
310
 
        poGDS->nBufferedBlock = nBlock;
311
 
        memcpy(pImage,
312
 
               poGDS->pabyRGBData + (nBand - 1) * nBlockXSize * nBlockYSize,
313
 
               nBlockXSize * nBlockYSize);
314
 
                   
315
 
        if (nBand == 1)
316
 
        {
317
 
            int iOtherBand;
318
 
            for(iOtherBand=2;iOtherBand<=poGDS->nBands;iOtherBand++)
319
 
            {
320
 
                GDALRasterBlock *poBlock;
321
 
 
322
 
                poBlock = poGDS->GetRasterBand(iOtherBand)->
323
 
                    GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
324
 
                if (poBlock == NULL)
325
 
                    break;
326
 
                    
327
 
                GByte* pabySrcBlock = (GByte *) poBlock->GetDataRef();
328
 
                if( pabySrcBlock == NULL )
329
 
                {
330
 
                    poBlock->DropLock();
331
 
                    break;
332
 
                }
333
 
 
334
 
                memcpy(pabySrcBlock,
335
 
                       poGDS->pabyRGBData + (iOtherBand - 1) * nBlockXSize * nBlockYSize,
336
 
                       nBlockXSize * nBlockYSize);
337
 
 
338
 
                poBlock->DropLock();
339
 
            }
340
 
        }
341
 
    }
342
 
    
343
 
    return CE_None;
344
 
}
345
 
 
346
 
/************************************************************************/
347
 
/*                              Seek()                                  */
348
 
/************************************************************************/
349
 
 
350
 
void EpsilonDataset::Seek(vsi_l_offset nPos)
351
 
{
352
 
    bEOF = FALSE;
353
 
    VSIFSeekL(fp, nPos, SEEK_SET);
354
 
    nFileBufOffset = 0;
355
 
    nFileBufCurSize = 0;
356
 
    nFileOff = nPos;
357
 
}
358
 
 
359
 
/************************************************************************/
360
 
/*                          GetNextByte()                               */
361
 
/************************************************************************/
362
 
 
363
 
#define BUFFER_CHUNK    16384
364
 
 
365
 
int EpsilonDataset::GetNextByte()
366
 
{
367
 
    if (nFileBufOffset < nFileBufCurSize)
368
 
    {
369
 
        nFileOff ++;
370
 
        return pabyFileBuf[nFileBufOffset ++];
371
 
    }
372
 
        
373
 
    if (bError || bEOF)
374
 
        return -1;
375
 
 
376
 
    if (nFileBufCurSize + BUFFER_CHUNK > nFileBufMaxSize)
377
 
    {
378
 
        GByte* pabyFileBufNew =
379
 
            (GByte*)VSIRealloc(pabyFileBuf, nFileBufCurSize + BUFFER_CHUNK);
380
 
        if (pabyFileBufNew == NULL)
381
 
        {
382
 
            bError = TRUE;
383
 
            return -1;
384
 
        }
385
 
        pabyFileBuf = pabyFileBufNew;
386
 
        nFileBufMaxSize = nFileBufCurSize + BUFFER_CHUNK;
387
 
    }
388
 
    int nBytesRead =
389
 
        (int)VSIFReadL(pabyFileBuf + nFileBufCurSize, 1, BUFFER_CHUNK, fp);
390
 
    nFileBufCurSize += nBytesRead;
391
 
    if (nBytesRead < BUFFER_CHUNK)
392
 
        bEOF = TRUE;
393
 
    if (nBytesRead == 0)
394
 
        return -1;
395
 
    
396
 
    nFileOff ++;
397
 
    return pabyFileBuf[nFileBufOffset ++];
398
 
}
399
 
 
400
 
/************************************************************************/
401
 
/*                     GetNextBlockData()                               */
402
 
/************************************************************************/
403
 
 
404
 
#define MAX_SIZE_BEFORE_BLOCK_MARKER        100
405
 
 
406
 
int EpsilonDataset::GetNextBlockData()
407
 
{
408
 
    int nStartBlockBufOffset = 0;
409
 
    pabyBlockData = NULL;
410
 
    nBlockDataSize = 0;
411
 
    
412
 
    while (nFileBufOffset < MAX_SIZE_BEFORE_BLOCK_MARKER)
413
 
    {
414
 
        int chNextByte = GetNextByte();
415
 
        if (chNextByte < 0)
416
 
            return FALSE;
417
 
        
418
 
        if (chNextByte != EPS_MARKER)
419
 
        {
420
 
            nStartBlockFileOff = nFileOff - 1;
421
 
            nStartBlockBufOffset = nFileBufOffset - 1;
422
 
            nBlockDataSize = 1;
423
 
            break;
424
 
        }
425
 
    }
426
 
    if (nFileBufOffset == MAX_SIZE_BEFORE_BLOCK_MARKER)
427
 
        return FALSE;
428
 
        
429
 
    while (nFileBufOffset < BLOCK_DATA_MAX_SIZE)
430
 
    {
431
 
        int chNextByte = GetNextByte();
432
 
        if (chNextByte < 0)
433
 
            break;
434
 
 
435
 
        if (chNextByte == EPS_MARKER)
436
 
        {
437
 
            pabyBlockData = pabyFileBuf + nStartBlockBufOffset;
438
 
            return TRUE;
439
 
        }
440
 
            
441
 
        nBlockDataSize ++;
442
 
    }
443
 
    
444
 
    pabyBlockData = pabyFileBuf + nStartBlockBufOffset;
445
 
    return TRUE;
446
 
}
447
 
 
448
 
/************************************************************************/
449
 
/*                           ScanBlocks()                               */
450
 
/************************************************************************/
451
 
 
452
 
int EpsilonDataset::ScanBlocks(int* pnBands)
453
 
{
454
 
    int bRet = FALSE;
455
 
 
456
 
    int nExpectedX = 0;
457
 
    int nExpectedY = 0;
458
 
 
459
 
    int nTileW = -1;
460
 
    int nTileH = -1;
461
 
    
462
 
    *pnBands = 0;
463
 
 
464
 
    bRegularTiling = TRUE;
465
 
    
466
 
    eps_block_header hdr;
467
 
    while(TRUE)
468
 
    {
469
 
        Seek(nStartBlockFileOff + nBlockDataSize);
470
 
        
471
 
        if (!GetNextBlockData())
472
 
        {
473
 
            break;
474
 
        }
475
 
        
476
 
        /* Ignore rasterlite wavelet header */
477
 
        int nRasterliteWaveletHeaderLen = strlen(RASTERLITE_WAVELET_HEADER);
478
 
        if (nBlockDataSize >= nRasterliteWaveletHeaderLen &&
479
 
            memcmp(pabyBlockData, RASTERLITE_WAVELET_HEADER,
480
 
                   nRasterliteWaveletHeaderLen) == 0)
481
 
        {
482
 
            continue;
483
 
        }
484
 
        
485
 
        /* Stop at rasterlite wavelet footer */
486
 
        int nRasterlineWaveletFooterLen = strlen(RASTERLITE_WAVELET_FOOTER);
487
 
        if (nBlockDataSize >= nRasterlineWaveletFooterLen &&
488
 
            memcmp(pabyBlockData, RASTERLITE_WAVELET_FOOTER,
489
 
                   nRasterlineWaveletFooterLen) == 0)
490
 
        {
491
 
            break;
492
 
        }
493
 
        
494
 
        if (eps_read_block_header (pabyBlockData,
495
 
                                   nBlockDataSize, &hdr) != EPS_OK)
496
 
        {
497
 
            CPLError(CE_Warning, CPLE_AppDefined, "cannot read block header");
498
 
            continue;
499
 
        }
500
 
 
501
 
        if (hdr.chk_flag == EPS_BAD_CRC ||
502
 
            hdr.crc_flag == EPS_BAD_CRC)
503
 
        {
504
 
            CPLError(CE_Warning, CPLE_AppDefined, "bad CRC");
505
 
            continue;
506
 
        }
507
 
        
508
 
        int W = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.W : hdr.tc.W;
509
 
        int H = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.H : hdr.tc.H;
510
 
        int x = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.x : hdr.tc.x;
511
 
        int y = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.y : hdr.tc.y;
512
 
        int w = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.w : hdr.tc.w;
513
 
        int h = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? hdr.gs.h : hdr.tc.h;
514
 
 
515
 
        //CPLDebug("EPSILON", "W=%d,H=%d,x=%d,y=%d,w=%d,h=%d,offset=" CPL_FRMT_GUIB,
516
 
        //                    W, H, x, y, w, h, nStartBlockFileOff);
517
 
        
518
 
        int nNewBands = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? 1 : 3;
519
 
        if (nRasterXSize == 0)
520
 
        {
521
 
            if (W <= 0 || H <= 0)
522
 
            {
523
 
                break;
524
 
            }
525
 
            
526
 
            bRet = TRUE;
527
 
            nRasterXSize = W;
528
 
            nRasterYSize = H;
529
 
            *pnBands = nNewBands;
530
 
        }
531
 
        
532
 
        if (nRasterXSize != W || nRasterYSize != H || *pnBands != nNewBands ||
533
 
            x < 0 || y < 0 || x + w > W || y + h > H)
534
 
        {
535
 
            CPLError(CE_Failure, CPLE_AppDefined, "Bad block characteristics");
536
 
            bRet = FALSE;
537
 
            break;
538
 
        }
539
 
        
540
 
        nBlocks++;
541
 
        pasBlocks = (BlockDesc*)VSIRealloc(pasBlocks, sizeof(BlockDesc) * nBlocks);
542
 
        pasBlocks[nBlocks-1].x = x;
543
 
        pasBlocks[nBlocks-1].y = y;
544
 
        pasBlocks[nBlocks-1].w = w;
545
 
        pasBlocks[nBlocks-1].h = h;
546
 
        pasBlocks[nBlocks-1].offset = nStartBlockFileOff;
547
 
        
548
 
        if (bRegularTiling)
549
 
        {
550
 
            if (nTileW < 0)
551
 
            {
552
 
                nTileW = w;
553
 
                nTileH = h;
554
 
            }
555
 
            
556
 
            if (w > nTileW || h > nTileH)
557
 
                bRegularTiling = FALSE;
558
 
            
559
 
            if (x != nExpectedX)
560
 
                bRegularTiling = FALSE;
561
 
 
562
 
            if (y != nExpectedY || nTileH != h)
563
 
            {
564
 
                if (y + h != H)
565
 
                    bRegularTiling = FALSE;
566
 
            }
567
 
            
568
 
            if (nTileW != w)
569
 
            {
570
 
                if (x + w != W)
571
 
                    bRegularTiling = FALSE;
572
 
                else
573
 
                {
574
 
                    nExpectedX = 0;
575
 
                    nExpectedY += nTileW;
576
 
                }
577
 
            }
578
 
            else
579
 
                nExpectedX += nTileW;
580
 
            
581
 
            //if (!bRegularTiling)
582
 
            //    CPLDebug("EPSILON", "not regular tiling!");
583
 
        }
584
 
    } 
585
 
 
586
 
    return bRet;
587
 
}
588
 
 
589
 
/************************************************************************/
590
 
/*                             Identify()                               */
591
 
/************************************************************************/
592
 
 
593
 
int EpsilonDataset::Identify(GDALOpenInfo* poOpenInfo)
594
 
{
595
 
    int nRasterliteWaveletHeaderLen = strlen(RASTERLITE_WAVELET_HEADER);
596
 
    if (poOpenInfo->nHeaderBytes > nRasterliteWaveletHeaderLen + 1 &&
597
 
          EQUALN((const char*)poOpenInfo->pabyHeader,
598
 
                 RASTERLITE_WAVELET_HEADER, nRasterliteWaveletHeaderLen))
599
 
    {
600
 
        return TRUE;
601
 
    }
602
 
    
603
 
    if (poOpenInfo->nHeaderBytes > EPS_MIN_GRAYSCALE_BUF &&
604
 
        (EQUALN((const char*)poOpenInfo->pabyHeader, "type=gs", 7) ||
605
 
         EQUALN((const char*)poOpenInfo->pabyHeader, "type=tc", 7)))
606
 
    {
607
 
        return TRUE;
608
 
    }
609
 
    
610
 
    return FALSE;
611
 
}
612
 
 
613
 
/************************************************************************/
614
 
/*                                Open()                                */
615
 
/************************************************************************/
616
 
 
617
 
GDALDataset* EpsilonDataset::Open(GDALOpenInfo* poOpenInfo)
618
 
{
619
 
    if (!Identify(poOpenInfo))
620
 
        return NULL;
621
 
 
622
 
    if( poOpenInfo->eAccess == GA_Update )
623
 
    {
624
 
        CPLError( CE_Failure, CPLE_NotSupported, 
625
 
                  "The EPSILON driver does not support update access to existing"
626
 
                  " files.\n" );
627
 
        return NULL;
628
 
    }
629
 
 
630
 
    FILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
631
 
    if (fp == NULL)
632
 
        return NULL;
633
 
    
634
 
    EpsilonDataset* poDS = new EpsilonDataset();
635
 
    poDS->fp = fp;
636
 
    
637
 
    poDS->nRasterXSize = 0;
638
 
    poDS->nRasterYSize = 0;
639
 
    
640
 
    int nBandsToAdd = 0;
641
 
    if (!poDS->ScanBlocks(&nBandsToAdd))
642
 
    {
643
 
        delete poDS;
644
 
        return NULL;
645
 
    }
646
 
    
647
 
    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
648
 
        !GDALCheckBandCount(nBandsToAdd, FALSE))
649
 
    {
650
 
        delete poDS;
651
 
        return NULL;
652
 
    }
653
 
    if (!poDS->bRegularTiling)
654
 
    {
655
 
        CPLError( CE_Failure, CPLE_NotSupported, 
656
 
                  "The EPSILON driver does not support reading "
657
 
                  "not regularly blocked files.\n" );
658
 
        delete poDS;
659
 
        return NULL;
660
 
    }
661
 
    
662
 
    int i;
663
 
    for(i=1;i<=nBandsToAdd;i++)
664
 
        poDS->SetBand(i, new EpsilonRasterBand(poDS, i));
665
 
        
666
 
    if (nBandsToAdd > 1)
667
 
        poDS->SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
668
 
    
669
 
    return poDS;
670
 
}
671
 
 
672
 
 
673
 
/************************************************************************/
674
 
/*                  EpsilonDatasetCreateCopy ()                         */
675
 
/************************************************************************/
676
 
 
677
 
GDALDataset *
678
 
EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
679
 
                       int bStrict, char ** papszOptions, 
680
 
                       GDALProgressFunc pfnProgress, void * pProgressData )
681
 
{
682
 
    int nBands = poSrcDS->GetRasterCount();
683
 
    if ((nBands != 1 && nBands != 3) ||
684
 
        (nBands > 0 && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL))
685
 
    {
686
 
        CPLError(CE_Failure, CPLE_NotSupported,
687
 
                 "The EPSILON driver only supports 1 band (grayscale) "
688
 
                 "or 3 band (RGB) data");
689
 
        return NULL;
690
 
    }
691
 
    
692
 
/* -------------------------------------------------------------------- */
693
 
/*      Fetch and check creation options                                */
694
 
/* -------------------------------------------------------------------- */
695
 
 
696
 
    int nBlockXSize =
697
 
        atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
698
 
    int nBlockYSize =
699
 
        atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
700
 
    if ((nBlockXSize != 32 && nBlockXSize != 64 && nBlockXSize != 128 &&
701
 
         nBlockXSize != 256 && nBlockXSize != 512 && nBlockXSize != 1024) ||
702
 
        (nBlockYSize != 32 && nBlockYSize != 64 && nBlockYSize != 128 &&
703
 
         nBlockYSize != 256 && nBlockYSize != 512 && nBlockYSize != 1024))
704
 
    {
705
 
        CPLError(CE_Failure, CPLE_NotSupported,
706
 
                "Block size must be a power of 2 between 32 et 1024");
707
 
        return NULL;
708
 
    }         
709
 
    
710
 
    const char* pszFilter =
711
 
        CSLFetchNameValueDef(papszOptions, "FILTER", "daub97lift");
712
 
    char** papszFBID = eps_get_fb_info(EPS_FB_ID);
713
 
    char** papszFBIDIter = papszFBID;
714
 
    int bFound = FALSE;
715
 
    int nIndexFB = 0;
716
 
    while(papszFBIDIter && *papszFBIDIter && !bFound)
717
 
    {
718
 
        if (strcmp(*papszFBIDIter, pszFilter) == 0)
719
 
            bFound = TRUE;
720
 
        else
721
 
            nIndexFB ++;
722
 
        papszFBIDIter ++;
723
 
    }
724
 
    eps_free_fb_info(papszFBID);
725
 
    if (!bFound)
726
 
    {
727
 
        CPLError(CE_Failure, CPLE_NotSupported, "FILTER='%s' not supported",
728
 
                 pszFilter);
729
 
        return NULL;
730
 
    }
731
 
    
732
 
    int eMode = EPS_MODE_OTLPF;
733
 
    const char* pszMode = CSLFetchNameValueDef(papszOptions, "MODE", "OTLPF");
734
 
    if (EQUAL(pszMode, "NORMAL"))
735
 
        eMode = EPS_MODE_NORMAL;
736
 
    else if (EQUAL(pszMode, "OTLPF"))
737
 
        eMode = EPS_MODE_OTLPF;
738
 
    else
739
 
    {
740
 
        CPLError(CE_Failure, CPLE_NotSupported, "MODE='%s' not supported",
741
 
                 pszMode);
742
 
        return NULL;
743
 
    }
744
 
    
745
 
    char** papszFBType = eps_get_fb_info(EPS_FB_TYPE);
746
 
    int bIsBiOrthogonal = EQUAL(papszFBType[nIndexFB], "biorthogonal");
747
 
    eps_free_fb_info(papszFBType);
748
 
    
749
 
    if (eMode == EPS_MODE_OTLPF && !bIsBiOrthogonal)
750
 
    {
751
 
        CPLError(CE_Failure, CPLE_NotSupported,
752
 
                 "MODE=OTLPF can only be used with biorthogonal filters. "
753
 
                 "Use MODE=NORMAL instead");
754
 
        return NULL;
755
 
    }    
756
 
    
757
 
    int bRasterliteOutput =
758
 
        CSLTestBoolean(CSLFetchNameValueDef(papszOptions,
759
 
                                            "RASTERLITE_OUTPUT", "NO"));
760
 
             
761
 
    int nYRatio = EPS_Y_RT;
762
 
    int nCbRatio = EPS_Cb_RT;
763
 
    int nCrRatio = EPS_Cr_RT;
764
 
    
765
 
    int eResample;
766
 
    if (CSLTestBoolean(CSLFetchNameValueDef(papszOptions,
767
 
                                            "RGB_RESAMPLE", "YES")))
768
 
        eResample = EPS_RESAMPLE_420;
769
 
    else
770
 
        eResample = EPS_RESAMPLE_444;
771
 
    
772
 
    const char* pszTarget = CSLFetchNameValueDef(papszOptions, "TARGET", "96");
773
 
    double dfReductionFactor = 1 - atof(pszTarget) / 100;
774
 
    if (dfReductionFactor > 1)
775
 
        dfReductionFactor = 1;
776
 
    else if (dfReductionFactor < 0)
777
 
        dfReductionFactor = 0;
778
 
    
779
 
/* -------------------------------------------------------------------- */
780
 
/*      Open file                                                       */
781
 
/* -------------------------------------------------------------------- */
782
 
 
783
 
    FILE* fp = VSIFOpenL(pszFilename, "wb");
784
 
    if (fp == NULL)
785
 
        return NULL;
786
 
 
787
 
/* -------------------------------------------------------------------- */
788
 
/*      Compute number of blocks, block size, etc...                    */
789
 
/* -------------------------------------------------------------------- */
790
 
 
791
 
    int nXSize = poSrcDS->GetRasterXSize();
792
 
    int nYSize = poSrcDS->GetRasterYSize();
793
 
    if (eMode == EPS_MODE_OTLPF)
794
 
    {
795
 
        nBlockXSize ++;
796
 
        nBlockYSize ++;
797
 
    }
798
 
    int nXBlocks = (nXSize + nBlockXSize - 1) / nBlockXSize;
799
 
    int nYBlocks = (nYSize + nBlockYSize - 1) / nBlockYSize;
800
 
    int nBlocks = nXBlocks * nYBlocks;
801
 
    int nUncompressedFileSize = nXSize * nYSize * nBands;
802
 
    int nUncompressedBlockSize = nUncompressedFileSize / nBlocks;
803
 
    int nTargetBlockSize = (int) (dfReductionFactor * nUncompressedBlockSize);
804
 
    if (nBands == 1)
805
 
        nTargetBlockSize = MAX (nTargetBlockSize, EPS_MIN_GRAYSCALE_BUF + 1);
806
 
    else
807
 
        nTargetBlockSize = MAX (nTargetBlockSize, EPS_MIN_TRUECOLOR_BUF + 1);
808
 
 
809
 
/* -------------------------------------------------------------------- */
810
 
/*      Allocate work buffers                                           */
811
 
/* -------------------------------------------------------------------- */
812
 
 
813
 
    GByte* pabyBuffer = (GByte*)VSIMalloc3(nBlockXSize, nBlockYSize, nBands);
814
 
    if (pabyBuffer == NULL)
815
 
    {
816
 
        VSIFCloseL(fp);
817
 
        return NULL;
818
 
    }
819
 
    
820
 
    GByte* pabyOutBuf = (GByte*)VSIMalloc(nTargetBlockSize);
821
 
    if (pabyOutBuf == NULL)
822
 
    {
823
 
        VSIFree(pabyBuffer);
824
 
        VSIFCloseL(fp);
825
 
        return NULL;
826
 
    }
827
 
    
828
 
    GByte** apapbyRawBuffer[3];
829
 
    int i, j;
830
 
    for(i=0;i<nBands;i++)
831
 
    {
832
 
        apapbyRawBuffer[i] = (GByte**) VSIMalloc(sizeof(GByte*) * nBlockYSize);
833
 
        for(j=0;j<nBlockYSize;j++)
834
 
        {
835
 
            apapbyRawBuffer[i][j] =
836
 
                            pabyBuffer + (i * nBlockXSize + j) * nBlockYSize;
837
 
        }
838
 
    }
839
 
    
840
 
    if (bRasterliteOutput)
841
 
    {
842
 
        const char* pszHeader = RASTERLITE_WAVELET_HEADER;
843
 
        VSIFWriteL(pszHeader, 1, strlen(pszHeader) + 1, fp);
844
 
    }
845
 
 
846
 
/* -------------------------------------------------------------------- */
847
 
/*      Iterate over blocks                                             */
848
 
/* -------------------------------------------------------------------- */
849
 
 
850
 
    int nBlockXOff, nBlockYOff;
851
 
    CPLErr eErr = CE_None;
852
 
    for(nBlockYOff = 0;
853
 
        eErr == CE_None && nBlockYOff < nYBlocks; nBlockYOff ++)
854
 
    {
855
 
        for(nBlockXOff = 0;
856
 
            eErr == CE_None && nBlockXOff < nXBlocks; nBlockXOff ++)
857
 
        {
858
 
            int bMustMemset = FALSE;
859
 
            int nReqXSize = nBlockXSize, nReqYSize = nBlockYSize;
860
 
            if ((nBlockXOff+1) * nBlockXSize > nXSize)
861
 
            {
862
 
                bMustMemset = TRUE;
863
 
                nReqXSize = nXSize - nBlockXOff * nBlockXSize;
864
 
            }
865
 
            if ((nBlockYOff+1) * nBlockYSize > nYSize)
866
 
            {
867
 
                bMustMemset = TRUE;
868
 
                nReqYSize = nYSize - nBlockYOff * nBlockYSize;
869
 
            }
870
 
            if (bMustMemset)
871
 
                memset(pabyBuffer, 0, nBands * nBlockXSize * nBlockYSize);
872
 
            
873
 
            eErr = poSrcDS->RasterIO(GF_Read,
874
 
                              nBlockXOff * nBlockXSize,
875
 
                              nBlockYOff * nBlockYSize,
876
 
                              nReqXSize, nReqYSize,
877
 
                              pabyBuffer,
878
 
                              nReqXSize, nReqYSize,
879
 
                              GDT_Byte, nBands, NULL,
880
 
                              1,
881
 
                              nBlockXSize,
882
 
                              nBlockXSize * nBlockYSize);
883
 
            
884
 
            int nOutBufSize = nTargetBlockSize;
885
 
            if (eErr == CE_None && nBands == 1)
886
 
            {
887
 
                if (EPS_OK != eps_encode_grayscale_block(apapbyRawBuffer[0],
888
 
                                           nXSize, nYSize,
889
 
                                           nReqXSize, nReqYSize,
890
 
                                           nBlockXOff * nBlockXSize,
891
 
                                           nBlockYOff * nBlockYSize,
892
 
                                           pabyOutBuf, &nOutBufSize,
893
 
                                           (char*) pszFilter, eMode))
894
 
                {
895
 
                    CPLError(CE_Failure, CPLE_AppDefined,
896
 
                             "Error occured when encoding block (%d, %d)",
897
 
                             nBlockXOff, nBlockYOff);
898
 
                    eErr = CE_Failure;
899
 
                }
900
 
            }
901
 
            else if (eErr == CE_None)
902
 
            {
903
 
                if (EPS_OK != eps_encode_truecolor_block(
904
 
                                           apapbyRawBuffer[0],
905
 
                                           apapbyRawBuffer[1],
906
 
                                           apapbyRawBuffer[2],
907
 
                                           nXSize, nYSize,
908
 
                                           nReqXSize, nReqYSize,
909
 
                                           nBlockXOff * nBlockXSize,
910
 
                                           nBlockYOff * nBlockYSize,
911
 
                                           eResample,
912
 
                                           pabyOutBuf, &nOutBufSize,
913
 
                                           nYRatio, nCbRatio, nCrRatio,
914
 
                                           (char*) pszFilter, eMode))
915
 
                {
916
 
                    CPLError(CE_Failure, CPLE_AppDefined,
917
 
                             "Error occured when encoding block (%d, %d)",
918
 
                             nBlockXOff, nBlockYOff);
919
 
                    eErr = CE_Failure;
920
 
                }
921
 
            }
922
 
            
923
 
            if (eErr == CE_None)
924
 
            {
925
 
                if ((int)VSIFWriteL(pabyOutBuf, 1, nOutBufSize, fp) !=
926
 
                                                                nOutBufSize)
927
 
                    eErr = CE_Failure;
928
 
 
929
 
                char chEPSMarker = EPS_MARKER;
930
 
                VSIFWriteL(&chEPSMarker, 1, 1, fp);
931
 
                
932
 
                if (pfnProgress && !pfnProgress(
933
 
                      1.0 * (nBlockYOff * nXBlocks + nBlockXOff + 1) / nBlocks,
934
 
                      NULL, pProgressData))
935
 
                {
936
 
                    eErr = CE_Failure;
937
 
                }
938
 
            }
939
 
        }
940
 
    }
941
 
    
942
 
    if (bRasterliteOutput)
943
 
    {
944
 
        const char* pszFooter = RASTERLITE_WAVELET_FOOTER;
945
 
        VSIFWriteL(pszFooter, 1, strlen(pszFooter) + 1, fp);
946
 
    }
947
 
 
948
 
/* -------------------------------------------------------------------- */
949
 
/*      Cleanup work buffers                                            */
950
 
/* -------------------------------------------------------------------- */
951
 
    
952
 
    for(i=0;i<nBands;i++)
953
 
    {
954
 
        VSIFree(apapbyRawBuffer[i]);
955
 
    }
956
 
    
957
 
    VSIFree(pabyOutBuf);
958
 
    VSIFree(pabyBuffer);
959
 
        
960
 
    VSIFCloseL(fp);
961
 
    
962
 
    if (eErr != CE_None)
963
 
        return NULL;
964
 
 
965
 
/* -------------------------------------------------------------------- */
966
 
/*      Reopen the dataset, unless asked for not (Rasterlite optim)     */
967
 
/* -------------------------------------------------------------------- */
968
 
    return (GDALDataset*) GDALOpen(pszFilename, GA_ReadOnly);
969
 
}
970
 
 
971
 
/************************************************************************/
972
 
/*                     GDALRegister_EPSILON()                           */
973
 
/************************************************************************/
974
 
 
975
 
void GDALRegister_EPSILON()
976
 
 
977
 
{
978
 
    GDALDriver  *poDriver;
979
 
    
980
 
    if (! GDAL_CHECK_VERSION("EPSILON driver"))
981
 
        return;
982
 
 
983
 
    if( GDALGetDriverByName( "EPSILON" ) == NULL )
984
 
    {
985
 
        poDriver = new GDALDriver();
986
 
        
987
 
        poDriver->SetDescription( "EPSILON" );
988
 
        
989
 
        poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
990
 
                                   "Epsilon wavelets" );
991
 
        poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
992
 
                                   "frmt_epsilon.html" );
993
 
        poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
994
 
                                   "Byte" );
995
 
 
996
 
        CPLString osMethods;
997
 
        char** papszFBID = eps_get_fb_info(EPS_FB_ID);
998
 
        char** papszFBIDIter = papszFBID;
999
 
        while(papszFBIDIter && *papszFBIDIter)
1000
 
        {
1001
 
            osMethods += "       <Value>";
1002
 
            osMethods += *papszFBIDIter;
1003
 
            osMethods += "</Value>\n";
1004
 
            papszFBIDIter ++;
1005
 
        }
1006
 
        eps_free_fb_info(papszFBID);
1007
 
        
1008
 
        CPLString osOptionList;
1009
 
        osOptionList.Printf(
1010
 
"<CreationOptionList>"
1011
 
"   <Option name='TARGET' type='int' description='target size reduction as a percentage of the original (0-100)' default='75'/>"
1012
 
"   <Option name='FILTER' type='string-select' description='Filter ID' default='daub97lift'>"
1013
 
"%s"
1014
 
"   </Option>"
1015
 
"   <Option name='BLOCKXSIZE' type='int' description='Tile Width. Between 32 and 1024' default=256/>"
1016
 
"   <Option name='BLOCKYSIZE' type='int' description='Tile Height. Between 32 and 1024' default=256/>"
1017
 
"   <Option name='MODE' type='string-select' default='OTLPF'>"
1018
 
"       <Value>NORMAL</Value>"
1019
 
"       <Value>OTLPF</Value>"
1020
 
"   </Option>"
1021
 
"   <Option name='RGB_RESAMPLE' type='boolean' description='if RGB must be resampled to 4:2:0' default='YES'/>"
1022
 
"   <Option name='RASTERLITE_OUTPUT' type='boolean' description='if Rasterlite header and footers must be inserted' default='FALSE'/>"
1023
 
"</CreationOptionList>", osMethods.c_str()  );
1024
 
 
1025
 
        poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
1026
 
                                   osOptionList.c_str() );
1027
 
                            
1028
 
        poDriver->pfnOpen = EpsilonDataset::Open;
1029
 
        poDriver->pfnIdentify = EpsilonDataset::Identify;
1030
 
        poDriver->pfnCreateCopy = EpsilonDatasetCreateCopy;
1031
 
        
1032
 
        poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1033
 
 
1034
 
        GetGDALDriverManager()->RegisterDriver( poDriver );
1035
 
    }
1036
 
}