1
/******************************************************************************
2
* $Id: epsilondataset.cpp 17975 2009-11-08 20:51:31Z rouault $
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>
8
**********************************************************************
9
* Copyright (c) 2009, Even Rouault, <even dot rouault at mines dash paris dot org>
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:
18
* The above copyright notice and this permission notice shall be included
19
* in all copies or substantial portions of the Software.
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
****************************************************************************/
33
CPL_CVSID("$Id: epsilondataset.cpp 17975 2009-11-08 20:51:31Z rouault $");
35
#define RASTERLITE_WAVELET_HEADER "StartWaveletsImage$$"
36
#define RASTERLITE_WAVELET_FOOTER "$$EndWaveletsImage"
38
#define BLOCK_DATA_MAX_SIZE MAX(EPS_MAX_GRAYSCALE_BUF, EPS_MAX_TRUECOLOR_BUF)
40
class EpsilonRasterBand;
52
/************************************************************************/
53
/* ==================================================================== */
55
/* ==================================================================== */
56
/************************************************************************/
58
class EpsilonDataset : public GDALPamDataset
60
friend class EpsilonRasterBand;
63
vsi_l_offset nFileOff;
74
vsi_l_offset nStartBlockFileOff;
84
void Seek(vsi_l_offset nPos);
86
int GetNextBlockData();
87
int ScanBlocks(int *pnBands);
91
virtual ~EpsilonDataset();
93
static GDALDataset *Open( GDALOpenInfo * );
94
static int Identify( GDALOpenInfo * );
97
/************************************************************************/
98
/* ==================================================================== */
99
/* EpsilonRasterBand */
100
/* ==================================================================== */
101
/************************************************************************/
103
class EpsilonRasterBand : public GDALPamRasterBand
106
EpsilonRasterBand(EpsilonDataset* poDS, int nBand);
108
virtual CPLErr IReadBlock( int, int, void * );
109
virtual GDALColorInterp GetColorInterpretation();
112
/************************************************************************/
113
/* EpsilonDataset() */
114
/************************************************************************/
116
EpsilonDataset::EpsilonDataset()
128
pabyBlockData = NULL;
130
nStartBlockFileOff = 0;
132
bRegularTiling = FALSE;
141
/************************************************************************/
142
/* ~EpsilonDataset() */
143
/************************************************************************/
145
EpsilonDataset::~EpsilonDataset()
149
VSIFree(pabyFileBuf);
151
CPLFree(pabyRGBData);
154
/************************************************************************/
155
/* EpsilonRasterBand() */
156
/************************************************************************/
158
EpsilonRasterBand::EpsilonRasterBand(EpsilonDataset* poDS, int nBand)
162
this->eDataType = GDT_Byte;
163
this->nBlockXSize = poDS->pasBlocks[0].w;
164
this->nBlockYSize = poDS->pasBlocks[0].h;
167
/************************************************************************/
168
/* GetColorInterpretation() */
169
/************************************************************************/
171
GDALColorInterp EpsilonRasterBand::GetColorInterpretation()
173
EpsilonDataset* poGDS = (EpsilonDataset*) poDS;
174
if (poGDS->nBands == 1)
176
return GCI_GrayIndex;
183
return GCI_GreenBand;
189
/************************************************************************/
191
/************************************************************************/
193
CPLErr EpsilonRasterBand::IReadBlock( int nBlockXOff,
194
int nBlockYOff, void * pImage)
196
EpsilonDataset* poGDS = (EpsilonDataset*) poDS;
198
//CPLDebug("EPSILON", "IReadBlock(nBand=%d,nBlockXOff=%d,nBlockYOff=%d)",
199
// nBand, nBlockXOff, nBlockYOff);
201
int nBlocksPerRow = (poGDS->nRasterXSize + nBlockXSize - 1) / nBlockXSize;
202
int nBlock = nBlockXOff + nBlockYOff * nBlocksPerRow;
204
BlockDesc* psDesc = &poGDS->pasBlocks[nBlock];
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);
215
poGDS->Seek(psDesc->offset);
217
if (!poGDS->GetNextBlockData())
219
memset(pImage, 0, nBlockXSize * nBlockYSize);
223
eps_block_header hdr;
224
if (eps_read_block_header (poGDS->pabyBlockData,
225
poGDS->nBlockDataSize, &hdr) != EPS_OK)
227
CPLError(CE_Warning, CPLE_AppDefined, "cannot read block header");
228
memset(pImage, 0, nBlockXSize * nBlockYSize);
232
if (hdr.chk_flag == EPS_BAD_CRC ||
233
hdr.crc_flag == EPS_BAD_CRC)
235
CPLError(CE_Warning, CPLE_AppDefined, "bad CRC");
236
memset(pImage, 0, nBlockXSize * nBlockYSize);
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;
244
if (poGDS->nBands == 1)
246
unsigned char ** pTempData =
247
(unsigned char **) CPLMalloc(h * sizeof(unsigned char*));
249
pTempData[i] = ((GByte*)pImage) + i * nBlockXSize;
251
if (w != nBlockXSize || h != nBlockYSize)
252
memset(pImage, 0, nBlockXSize * nBlockYSize);
254
if (eps_decode_grayscale_block (pTempData,
255
poGDS->pabyBlockData, &hdr) != EPS_OK)
258
memset(pImage, 0, nBlockXSize * nBlockYSize);
265
if (poGDS->pabyRGBData == NULL)
268
(GByte*) VSIMalloc3(nBlockXSize, nBlockYSize, 3);
269
if (poGDS->pabyRGBData == NULL)
271
memset(pImage, 0, nBlockXSize * nBlockYSize);
276
if (poGDS->nBufferedBlock == nBlock)
279
poGDS->pabyRGBData + (nBand - 1) * nBlockXSize * nBlockYSize,
280
nBlockXSize * nBlockYSize);
284
unsigned char ** pTempData[3];
286
for(iBand=0;iBand<3;iBand++)
289
(unsigned char **) CPLMalloc(h * sizeof(unsigned char*));
291
pTempData[iBand][i] = poGDS->pabyRGBData +
292
iBand * nBlockXSize * nBlockYSize + i * nBlockXSize;
295
if (w != nBlockXSize || h != nBlockYSize)
296
memset(poGDS->pabyRGBData, 0, 3 * nBlockXSize * nBlockYSize);
298
if (eps_decode_truecolor_block (pTempData[0], pTempData[1], pTempData[2],
299
poGDS->pabyBlockData, &hdr) != EPS_OK)
301
for(iBand=0;iBand<poGDS->nBands;iBand++)
302
CPLFree(pTempData[iBand]);
303
memset(pImage, 0, nBlockXSize * nBlockYSize);
307
for(iBand=0;iBand<poGDS->nBands;iBand++)
308
CPLFree(pTempData[iBand]);
310
poGDS->nBufferedBlock = nBlock;
312
poGDS->pabyRGBData + (nBand - 1) * nBlockXSize * nBlockYSize,
313
nBlockXSize * nBlockYSize);
318
for(iOtherBand=2;iOtherBand<=poGDS->nBands;iOtherBand++)
320
GDALRasterBlock *poBlock;
322
poBlock = poGDS->GetRasterBand(iOtherBand)->
323
GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
327
GByte* pabySrcBlock = (GByte *) poBlock->GetDataRef();
328
if( pabySrcBlock == NULL )
335
poGDS->pabyRGBData + (iOtherBand - 1) * nBlockXSize * nBlockYSize,
336
nBlockXSize * nBlockYSize);
346
/************************************************************************/
348
/************************************************************************/
350
void EpsilonDataset::Seek(vsi_l_offset nPos)
353
VSIFSeekL(fp, nPos, SEEK_SET);
359
/************************************************************************/
361
/************************************************************************/
363
#define BUFFER_CHUNK 16384
365
int EpsilonDataset::GetNextByte()
367
if (nFileBufOffset < nFileBufCurSize)
370
return pabyFileBuf[nFileBufOffset ++];
376
if (nFileBufCurSize + BUFFER_CHUNK > nFileBufMaxSize)
378
GByte* pabyFileBufNew =
379
(GByte*)VSIRealloc(pabyFileBuf, nFileBufCurSize + BUFFER_CHUNK);
380
if (pabyFileBufNew == NULL)
385
pabyFileBuf = pabyFileBufNew;
386
nFileBufMaxSize = nFileBufCurSize + BUFFER_CHUNK;
389
(int)VSIFReadL(pabyFileBuf + nFileBufCurSize, 1, BUFFER_CHUNK, fp);
390
nFileBufCurSize += nBytesRead;
391
if (nBytesRead < BUFFER_CHUNK)
397
return pabyFileBuf[nFileBufOffset ++];
400
/************************************************************************/
401
/* GetNextBlockData() */
402
/************************************************************************/
404
#define MAX_SIZE_BEFORE_BLOCK_MARKER 100
406
int EpsilonDataset::GetNextBlockData()
408
int nStartBlockBufOffset = 0;
409
pabyBlockData = NULL;
412
while (nFileBufOffset < MAX_SIZE_BEFORE_BLOCK_MARKER)
414
int chNextByte = GetNextByte();
418
if (chNextByte != EPS_MARKER)
420
nStartBlockFileOff = nFileOff - 1;
421
nStartBlockBufOffset = nFileBufOffset - 1;
426
if (nFileBufOffset == MAX_SIZE_BEFORE_BLOCK_MARKER)
429
while (nFileBufOffset < BLOCK_DATA_MAX_SIZE)
431
int chNextByte = GetNextByte();
435
if (chNextByte == EPS_MARKER)
437
pabyBlockData = pabyFileBuf + nStartBlockBufOffset;
444
pabyBlockData = pabyFileBuf + nStartBlockBufOffset;
448
/************************************************************************/
450
/************************************************************************/
452
int EpsilonDataset::ScanBlocks(int* pnBands)
464
bRegularTiling = TRUE;
466
eps_block_header hdr;
469
Seek(nStartBlockFileOff + nBlockDataSize);
471
if (!GetNextBlockData())
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)
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)
494
if (eps_read_block_header (pabyBlockData,
495
nBlockDataSize, &hdr) != EPS_OK)
497
CPLError(CE_Warning, CPLE_AppDefined, "cannot read block header");
501
if (hdr.chk_flag == EPS_BAD_CRC ||
502
hdr.crc_flag == EPS_BAD_CRC)
504
CPLError(CE_Warning, CPLE_AppDefined, "bad CRC");
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;
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);
518
int nNewBands = (hdr.block_type == EPS_GRAYSCALE_BLOCK) ? 1 : 3;
519
if (nRasterXSize == 0)
521
if (W <= 0 || H <= 0)
529
*pnBands = nNewBands;
532
if (nRasterXSize != W || nRasterYSize != H || *pnBands != nNewBands ||
533
x < 0 || y < 0 || x + w > W || y + h > H)
535
CPLError(CE_Failure, CPLE_AppDefined, "Bad block characteristics");
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;
556
if (w > nTileW || h > nTileH)
557
bRegularTiling = FALSE;
560
bRegularTiling = FALSE;
562
if (y != nExpectedY || nTileH != h)
565
bRegularTiling = FALSE;
571
bRegularTiling = FALSE;
575
nExpectedY += nTileW;
579
nExpectedX += nTileW;
581
//if (!bRegularTiling)
582
// CPLDebug("EPSILON", "not regular tiling!");
589
/************************************************************************/
591
/************************************************************************/
593
int EpsilonDataset::Identify(GDALOpenInfo* poOpenInfo)
595
int nRasterliteWaveletHeaderLen = strlen(RASTERLITE_WAVELET_HEADER);
596
if (poOpenInfo->nHeaderBytes > nRasterliteWaveletHeaderLen + 1 &&
597
EQUALN((const char*)poOpenInfo->pabyHeader,
598
RASTERLITE_WAVELET_HEADER, nRasterliteWaveletHeaderLen))
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)))
613
/************************************************************************/
615
/************************************************************************/
617
GDALDataset* EpsilonDataset::Open(GDALOpenInfo* poOpenInfo)
619
if (!Identify(poOpenInfo))
622
if( poOpenInfo->eAccess == GA_Update )
624
CPLError( CE_Failure, CPLE_NotSupported,
625
"The EPSILON driver does not support update access to existing"
630
FILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
634
EpsilonDataset* poDS = new EpsilonDataset();
637
poDS->nRasterXSize = 0;
638
poDS->nRasterYSize = 0;
641
if (!poDS->ScanBlocks(&nBandsToAdd))
647
if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ||
648
!GDALCheckBandCount(nBandsToAdd, FALSE))
653
if (!poDS->bRegularTiling)
655
CPLError( CE_Failure, CPLE_NotSupported,
656
"The EPSILON driver does not support reading "
657
"not regularly blocked files.\n" );
663
for(i=1;i<=nBandsToAdd;i++)
664
poDS->SetBand(i, new EpsilonRasterBand(poDS, i));
667
poDS->SetMetadataItem("INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE");
673
/************************************************************************/
674
/* EpsilonDatasetCreateCopy () */
675
/************************************************************************/
678
EpsilonDatasetCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
679
int bStrict, char ** papszOptions,
680
GDALProgressFunc pfnProgress, void * pProgressData )
682
int nBands = poSrcDS->GetRasterCount();
683
if ((nBands != 1 && nBands != 3) ||
684
(nBands > 0 && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL))
686
CPLError(CE_Failure, CPLE_NotSupported,
687
"The EPSILON driver only supports 1 band (grayscale) "
688
"or 3 band (RGB) data");
692
/* -------------------------------------------------------------------- */
693
/* Fetch and check creation options */
694
/* -------------------------------------------------------------------- */
697
atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
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))
705
CPLError(CE_Failure, CPLE_NotSupported,
706
"Block size must be a power of 2 between 32 et 1024");
710
const char* pszFilter =
711
CSLFetchNameValueDef(papszOptions, "FILTER", "daub97lift");
712
char** papszFBID = eps_get_fb_info(EPS_FB_ID);
713
char** papszFBIDIter = papszFBID;
716
while(papszFBIDIter && *papszFBIDIter && !bFound)
718
if (strcmp(*papszFBIDIter, pszFilter) == 0)
724
eps_free_fb_info(papszFBID);
727
CPLError(CE_Failure, CPLE_NotSupported, "FILTER='%s' not supported",
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;
740
CPLError(CE_Failure, CPLE_NotSupported, "MODE='%s' not supported",
745
char** papszFBType = eps_get_fb_info(EPS_FB_TYPE);
746
int bIsBiOrthogonal = EQUAL(papszFBType[nIndexFB], "biorthogonal");
747
eps_free_fb_info(papszFBType);
749
if (eMode == EPS_MODE_OTLPF && !bIsBiOrthogonal)
751
CPLError(CE_Failure, CPLE_NotSupported,
752
"MODE=OTLPF can only be used with biorthogonal filters. "
753
"Use MODE=NORMAL instead");
757
int bRasterliteOutput =
758
CSLTestBoolean(CSLFetchNameValueDef(papszOptions,
759
"RASTERLITE_OUTPUT", "NO"));
761
int nYRatio = EPS_Y_RT;
762
int nCbRatio = EPS_Cb_RT;
763
int nCrRatio = EPS_Cr_RT;
766
if (CSLTestBoolean(CSLFetchNameValueDef(papszOptions,
767
"RGB_RESAMPLE", "YES")))
768
eResample = EPS_RESAMPLE_420;
770
eResample = EPS_RESAMPLE_444;
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;
779
/* -------------------------------------------------------------------- */
781
/* -------------------------------------------------------------------- */
783
FILE* fp = VSIFOpenL(pszFilename, "wb");
787
/* -------------------------------------------------------------------- */
788
/* Compute number of blocks, block size, etc... */
789
/* -------------------------------------------------------------------- */
791
int nXSize = poSrcDS->GetRasterXSize();
792
int nYSize = poSrcDS->GetRasterYSize();
793
if (eMode == EPS_MODE_OTLPF)
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);
805
nTargetBlockSize = MAX (nTargetBlockSize, EPS_MIN_GRAYSCALE_BUF + 1);
807
nTargetBlockSize = MAX (nTargetBlockSize, EPS_MIN_TRUECOLOR_BUF + 1);
809
/* -------------------------------------------------------------------- */
810
/* Allocate work buffers */
811
/* -------------------------------------------------------------------- */
813
GByte* pabyBuffer = (GByte*)VSIMalloc3(nBlockXSize, nBlockYSize, nBands);
814
if (pabyBuffer == NULL)
820
GByte* pabyOutBuf = (GByte*)VSIMalloc(nTargetBlockSize);
821
if (pabyOutBuf == NULL)
828
GByte** apapbyRawBuffer[3];
830
for(i=0;i<nBands;i++)
832
apapbyRawBuffer[i] = (GByte**) VSIMalloc(sizeof(GByte*) * nBlockYSize);
833
for(j=0;j<nBlockYSize;j++)
835
apapbyRawBuffer[i][j] =
836
pabyBuffer + (i * nBlockXSize + j) * nBlockYSize;
840
if (bRasterliteOutput)
842
const char* pszHeader = RASTERLITE_WAVELET_HEADER;
843
VSIFWriteL(pszHeader, 1, strlen(pszHeader) + 1, fp);
846
/* -------------------------------------------------------------------- */
847
/* Iterate over blocks */
848
/* -------------------------------------------------------------------- */
850
int nBlockXOff, nBlockYOff;
851
CPLErr eErr = CE_None;
853
eErr == CE_None && nBlockYOff < nYBlocks; nBlockYOff ++)
856
eErr == CE_None && nBlockXOff < nXBlocks; nBlockXOff ++)
858
int bMustMemset = FALSE;
859
int nReqXSize = nBlockXSize, nReqYSize = nBlockYSize;
860
if ((nBlockXOff+1) * nBlockXSize > nXSize)
863
nReqXSize = nXSize - nBlockXOff * nBlockXSize;
865
if ((nBlockYOff+1) * nBlockYSize > nYSize)
868
nReqYSize = nYSize - nBlockYOff * nBlockYSize;
871
memset(pabyBuffer, 0, nBands * nBlockXSize * nBlockYSize);
873
eErr = poSrcDS->RasterIO(GF_Read,
874
nBlockXOff * nBlockXSize,
875
nBlockYOff * nBlockYSize,
876
nReqXSize, nReqYSize,
878
nReqXSize, nReqYSize,
879
GDT_Byte, nBands, NULL,
882
nBlockXSize * nBlockYSize);
884
int nOutBufSize = nTargetBlockSize;
885
if (eErr == CE_None && nBands == 1)
887
if (EPS_OK != eps_encode_grayscale_block(apapbyRawBuffer[0],
889
nReqXSize, nReqYSize,
890
nBlockXOff * nBlockXSize,
891
nBlockYOff * nBlockYSize,
892
pabyOutBuf, &nOutBufSize,
893
(char*) pszFilter, eMode))
895
CPLError(CE_Failure, CPLE_AppDefined,
896
"Error occured when encoding block (%d, %d)",
897
nBlockXOff, nBlockYOff);
901
else if (eErr == CE_None)
903
if (EPS_OK != eps_encode_truecolor_block(
908
nReqXSize, nReqYSize,
909
nBlockXOff * nBlockXSize,
910
nBlockYOff * nBlockYSize,
912
pabyOutBuf, &nOutBufSize,
913
nYRatio, nCbRatio, nCrRatio,
914
(char*) pszFilter, eMode))
916
CPLError(CE_Failure, CPLE_AppDefined,
917
"Error occured when encoding block (%d, %d)",
918
nBlockXOff, nBlockYOff);
925
if ((int)VSIFWriteL(pabyOutBuf, 1, nOutBufSize, fp) !=
929
char chEPSMarker = EPS_MARKER;
930
VSIFWriteL(&chEPSMarker, 1, 1, fp);
932
if (pfnProgress && !pfnProgress(
933
1.0 * (nBlockYOff * nXBlocks + nBlockXOff + 1) / nBlocks,
934
NULL, pProgressData))
942
if (bRasterliteOutput)
944
const char* pszFooter = RASTERLITE_WAVELET_FOOTER;
945
VSIFWriteL(pszFooter, 1, strlen(pszFooter) + 1, fp);
948
/* -------------------------------------------------------------------- */
949
/* Cleanup work buffers */
950
/* -------------------------------------------------------------------- */
952
for(i=0;i<nBands;i++)
954
VSIFree(apapbyRawBuffer[i]);
965
/* -------------------------------------------------------------------- */
966
/* Reopen the dataset, unless asked for not (Rasterlite optim) */
967
/* -------------------------------------------------------------------- */
968
return (GDALDataset*) GDALOpen(pszFilename, GA_ReadOnly);
971
/************************************************************************/
972
/* GDALRegister_EPSILON() */
973
/************************************************************************/
975
void GDALRegister_EPSILON()
978
GDALDriver *poDriver;
980
if (! GDAL_CHECK_VERSION("EPSILON driver"))
983
if( GDALGetDriverByName( "EPSILON" ) == NULL )
985
poDriver = new GDALDriver();
987
poDriver->SetDescription( "EPSILON" );
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,
997
char** papszFBID = eps_get_fb_info(EPS_FB_ID);
998
char** papszFBIDIter = papszFBID;
999
while(papszFBIDIter && *papszFBIDIter)
1001
osMethods += " <Value>";
1002
osMethods += *papszFBIDIter;
1003
osMethods += "</Value>\n";
1006
eps_free_fb_info(papszFBID);
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'>"
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>"
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() );
1025
poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
1026
osOptionList.c_str() );
1028
poDriver->pfnOpen = EpsilonDataset::Open;
1029
poDriver->pfnIdentify = EpsilonDataset::Identify;
1030
poDriver->pfnCreateCopy = EpsilonDatasetCreateCopy;
1032
poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1034
GetGDALDriverManager()->RegisterDriver( poDriver );