1 : /******************************************************************************
2 : * $Id: openjpegdataset.cpp 25264 2012-11-29 06:57:39Z rouault $
3 : *
4 : * Project: JPEG2000 driver based on OpenJPEG library
5 : * Purpose: JPEG2000 driver based on OpenJPEG library
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2010, 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 : /* This file is to be used with openjpeg 2.0 */
31 :
32 : #include <stdio.h> /* openjpeg.h needs FILE* */
33 : #include <openjpeg-2.0/openjpeg.h>
34 : #include <vector>
35 :
36 : #include "gdal_pam.h"
37 : #include "cpl_string.h"
38 : #include "gdaljp2metadata.h"
39 : #include "cpl_multiproc.h"
40 : #include "cpl_atomic_ops.h"
41 :
42 : CPL_CVSID("$Id: openjpegdataset.cpp 25264 2012-11-29 06:57:39Z rouault $");
43 :
44 : /************************************************************************/
45 : /* JP2OpenJPEGDataset_ErrorCallback() */
46 : /************************************************************************/
47 :
48 6 : static void JP2OpenJPEGDataset_ErrorCallback(const char *pszMsg, void *unused)
49 : {
50 6 : CPLError(CE_Failure, CPLE_AppDefined, "%s", pszMsg);
51 6 : }
52 :
53 : /************************************************************************/
54 : /* JP2OpenJPEGDataset_WarningCallback() */
55 : /************************************************************************/
56 :
57 14 : static void JP2OpenJPEGDataset_WarningCallback(const char *pszMsg, void *unused)
58 : {
59 14 : if( strcmp(pszMsg, "JP2 box which are after the codestream will not be read by this function.\n") != 0 )
60 0 : CPLError(CE_Warning, CPLE_AppDefined, "%s", pszMsg);
61 14 : }
62 :
63 : /************************************************************************/
64 : /* JP2OpenJPEGDataset_InfoCallback() */
65 : /************************************************************************/
66 :
67 437 : static void JP2OpenJPEGDataset_InfoCallback(const char *pszMsg, void *unused)
68 : {
69 437 : char* pszMsgTmp = CPLStrdup(pszMsg);
70 438 : int nLen = (int)strlen(pszMsgTmp);
71 1385 : while( nLen > 0 && pszMsgTmp[nLen-1] == '\n' )
72 : {
73 509 : pszMsgTmp[nLen-1] = '\0';
74 509 : nLen --;
75 : }
76 438 : CPLDebug("OPENJPEG", "info: %s", pszMsgTmp);
77 438 : CPLFree(pszMsgTmp);
78 438 : }
79 :
80 : /************************************************************************/
81 : /* JP2OpenJPEGDataset_Read() */
82 : /************************************************************************/
83 :
84 883 : static OPJ_SIZE_T JP2OpenJPEGDataset_Read(void* pBuffer, OPJ_SIZE_T nBytes,
85 : void *pUserData)
86 : {
87 883 : int nRet = VSIFReadL(pBuffer, 1, nBytes, (VSILFILE*)pUserData);
88 : #ifdef DEBUG_IO
89 : CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Read(%d) = %d", (int)nBytes, nRet);
90 : #endif
91 885 : if (nRet == 0)
92 14 : nRet = -1;
93 885 : return nRet;
94 : }
95 :
96 : /************************************************************************/
97 : /* JP2OpenJPEGDataset_Write() */
98 : /************************************************************************/
99 :
100 10 : static OPJ_SIZE_T JP2OpenJPEGDataset_Write(void* pBuffer, OPJ_SIZE_T nBytes,
101 : void *pUserData)
102 : {
103 10 : int nRet = VSIFWriteL(pBuffer, 1, nBytes, (VSILFILE*)pUserData);
104 : #ifdef DEBUG_IO
105 : CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Write(%d) = %d", (int)nBytes, nRet);
106 : #endif
107 10 : return nRet;
108 : }
109 :
110 : /************************************************************************/
111 : /* JP2OpenJPEGDataset_Seek() */
112 : /************************************************************************/
113 :
114 77 : static OPJ_BOOL JP2OpenJPEGDataset_Seek(OPJ_OFF_T nBytes, void * pUserData)
115 : {
116 : #ifdef DEBUG_IO
117 : CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Seek(%d)", (int)nBytes);
118 : #endif
119 77 : return VSIFSeekL((VSILFILE*)pUserData, nBytes, SEEK_SET) == 0;
120 : }
121 :
122 : /************************************************************************/
123 : /* JP2OpenJPEGDataset_Skip() */
124 : /************************************************************************/
125 :
126 633 : static OPJ_OFF_T JP2OpenJPEGDataset_Skip(OPJ_OFF_T nBytes, void * pUserData)
127 : {
128 633 : vsi_l_offset nOffset = VSIFTellL((VSILFILE*)pUserData);
129 630 : nOffset += nBytes;
130 : #ifdef DEBUG_IO
131 : CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Skip(%d -> " CPL_FRMT_GUIB ")",
132 : (int)nBytes, (GUIntBig)nOffset);
133 : #endif
134 630 : VSIFSeekL((VSILFILE*)pUserData, nOffset, SEEK_SET);
135 633 : return nBytes;
136 : }
137 :
138 : /************************************************************************/
139 : /* ==================================================================== */
140 : /* JP2OpenJPEGDataset */
141 : /* ==================================================================== */
142 : /************************************************************************/
143 :
144 : class JP2OpenJPEGRasterBand;
145 :
146 : class JP2OpenJPEGDataset : public GDALPamDataset
147 : {
148 : friend class JP2OpenJPEGRasterBand;
149 :
150 : VSILFILE *fp; /* Large FILE API */
151 :
152 : char *pszProjection;
153 : int bGeoTransformValid;
154 : double adfGeoTransform[6];
155 : int nGCPCount;
156 : GDAL_GCP *pasGCPList;
157 :
158 : OPJ_CODEC_FORMAT eCodecFormat;
159 : OPJ_COLOR_SPACE eColorSpace;
160 :
161 : int bIs420;
162 :
163 : int iLevel;
164 : int nOverviewCount;
165 : JP2OpenJPEGDataset** papoOverviewDS;
166 : int bUseSetDecodeArea;
167 :
168 : int nThreads;
169 : int GetNumThreads();
170 : int bEnoughMemoryToLoadOtherBands;
171 :
172 : protected:
173 : virtual int CloseDependentDatasets();
174 :
175 : public:
176 : JP2OpenJPEGDataset();
177 : ~JP2OpenJPEGDataset();
178 :
179 : static int Identify( GDALOpenInfo * poOpenInfo );
180 : static GDALDataset *Open( GDALOpenInfo * );
181 : static GDALDataset *CreateCopy( const char * pszFilename,
182 : GDALDataset *poSrcDS,
183 : int bStrict, char ** papszOptions,
184 : GDALProgressFunc pfnProgress,
185 : void * pProgressData );
186 : CPLErr GetGeoTransform( double* );
187 : virtual const char *GetProjectionRef(void);
188 : virtual int GetGCPCount();
189 : virtual const char *GetGCPProjection();
190 : virtual const GDAL_GCP *GetGCPs();
191 :
192 : virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
193 : int nXOff, int nYOff, int nXSize, int nYSize,
194 : void * pData, int nBufXSize, int nBufYSize,
195 : GDALDataType eBufType,
196 : int nBandCount, int *panBandMap,
197 : int nPixelSpace, int nLineSpace, int nBandSpace);
198 :
199 : static void WriteBox(VSILFILE* fp, GDALJP2Box* poBox);
200 :
201 : CPLErr ReadBlock( int nBand, VSILFILE* fp,
202 : int nBlockXOff, int nBlockYOff, void * pImage,
203 : int nBandCount, int *panBandMap );
204 :
205 : int PreloadBlocks( JP2OpenJPEGRasterBand* poBand,
206 : int nXOff, int nYOff, int nXSize, int nYSize,
207 : int nBandCount, int *panBandMap );
208 : };
209 :
210 : /************************************************************************/
211 : /* ==================================================================== */
212 : /* JP2OpenJPEGRasterBand */
213 : /* ==================================================================== */
214 : /************************************************************************/
215 :
216 : class JP2OpenJPEGRasterBand : public GDALPamRasterBand
217 : {
218 : friend class JP2OpenJPEGDataset;
219 :
220 : public:
221 :
222 : JP2OpenJPEGRasterBand( JP2OpenJPEGDataset * poDS, int nBand,
223 : GDALDataType eDataType, int nBits,
224 : int nBlockXSize, int nBlockYSize);
225 : ~JP2OpenJPEGRasterBand();
226 :
227 : virtual CPLErr IReadBlock( int, int, void * );
228 : virtual CPLErr IRasterIO( GDALRWFlag eRWFlag,
229 : int nXOff, int nYOff, int nXSize, int nYSize,
230 : void * pData, int nBufXSize, int nBufYSize,
231 : GDALDataType eBufType,
232 : int nPixelSpace, int nLineSpace );
233 :
234 : virtual GDALColorInterp GetColorInterpretation();
235 :
236 : virtual int GetOverviewCount();
237 : virtual GDALRasterBand* GetOverview(int iOvrLevel);
238 :
239 8 : virtual int HasArbitraryOverviews() { return TRUE; }
240 : };
241 :
242 :
243 : /************************************************************************/
244 : /* JP2OpenJPEGRasterBand() */
245 : /************************************************************************/
246 :
247 122 : JP2OpenJPEGRasterBand::JP2OpenJPEGRasterBand( JP2OpenJPEGDataset *poDS, int nBand,
248 : GDALDataType eDataType, int nBits,
249 122 : int nBlockXSize, int nBlockYSize)
250 :
251 : {
252 122 : this->poDS = poDS;
253 122 : this->nBand = nBand;
254 122 : this->eDataType = eDataType;
255 122 : this->nBlockXSize = nBlockXSize;
256 122 : this->nBlockYSize = nBlockYSize;
257 :
258 122 : if( (nBits % 8) != 0 )
259 : SetMetadataItem("NBITS",
260 : CPLString().Printf("%d",nBits),
261 24 : "IMAGE_STRUCTURE" );
262 122 : }
263 :
264 : /************************************************************************/
265 : /* ~JP2OpenJPEGRasterBand() */
266 : /************************************************************************/
267 :
268 122 : JP2OpenJPEGRasterBand::~JP2OpenJPEGRasterBand()
269 : {
270 122 : }
271 :
272 : /************************************************************************/
273 : /* CLAMP_0_255() */
274 : /************************************************************************/
275 :
276 921600 : static CPL_INLINE GByte CLAMP_0_255(int val)
277 : {
278 921600 : if (val < 0)
279 1383 : return 0;
280 920217 : else if (val > 255)
281 1778 : return 255;
282 : else
283 918439 : return (GByte)val;
284 : }
285 :
286 : /************************************************************************/
287 : /* IReadBlock() */
288 : /************************************************************************/
289 :
290 21 : CPLErr JP2OpenJPEGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
291 : void * pImage )
292 : {
293 21 : JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
294 21 : if ( poGDS->bEnoughMemoryToLoadOtherBands )
295 : return poGDS->ReadBlock(nBand, poGDS->fp, nBlockXOff, nBlockYOff, pImage,
296 21 : poGDS->nBands, NULL);
297 : else
298 : return poGDS->ReadBlock(nBand, poGDS->fp, nBlockXOff, nBlockYOff, pImage,
299 0 : 1, &nBand);
300 : }
301 :
302 : /************************************************************************/
303 : /* IRasterIO() */
304 : /************************************************************************/
305 :
306 10694 : CPLErr JP2OpenJPEGRasterBand::IRasterIO( GDALRWFlag eRWFlag,
307 : int nXOff, int nYOff, int nXSize, int nYSize,
308 : void * pData, int nBufXSize, int nBufYSize,
309 : GDALDataType eBufType,
310 : int nPixelSpace, int nLineSpace )
311 : {
312 10694 : JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
313 :
314 10694 : if( eRWFlag != GF_Read )
315 0 : return CE_Failure;
316 :
317 : /* ==================================================================== */
318 : /* Do we have overviews that would be appropriate to satisfy */
319 : /* this request? */
320 : /* ==================================================================== */
321 10694 : if( (nBufXSize < nXSize || nBufYSize < nYSize)
322 0 : && GetOverviewCount() > 0 && eRWFlag == GF_Read )
323 : {
324 : int nOverview;
325 :
326 : nOverview =
327 : GDALBandGetBestOverviewLevel(this, nXOff, nYOff, nXSize, nYSize,
328 0 : nBufXSize, nBufYSize);
329 0 : if (nOverview >= 0)
330 : {
331 0 : GDALRasterBand* poOverviewBand = GetOverview(nOverview);
332 0 : if (poOverviewBand == NULL)
333 0 : return CE_Failure;
334 :
335 : return poOverviewBand->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
336 : pData, nBufXSize, nBufYSize, eBufType,
337 0 : nPixelSpace, nLineSpace );
338 : }
339 : }
340 :
341 10694 : poGDS->bEnoughMemoryToLoadOtherBands = poGDS->PreloadBlocks(this, nXOff, nYOff, nXSize, nYSize, 0, NULL);
342 :
343 : CPLErr eErr = GDALPamRasterBand::IRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
344 : pData, nBufXSize, nBufYSize, eBufType,
345 10694 : nPixelSpace, nLineSpace );
346 :
347 10694 : poGDS->bEnoughMemoryToLoadOtherBands = TRUE;
348 10694 : return eErr;
349 : }
350 :
351 : /************************************************************************/
352 : /* GetNumThreads() */
353 : /************************************************************************/
354 :
355 10695 : int JP2OpenJPEGDataset::GetNumThreads()
356 : {
357 10695 : if( nThreads >= 1 )
358 10674 : return nThreads;
359 :
360 21 : const char* pszThreads = CPLGetConfigOption("GDAL_NUM_THREADS", "ALL_CPUS");
361 21 : if (EQUAL(pszThreads, "ALL_CPUS"))
362 21 : nThreads = CPLGetNumCPUs();
363 : else
364 0 : nThreads = atoi(pszThreads);
365 21 : if (nThreads > 128)
366 0 : nThreads = 128;
367 21 : if (nThreads <= 0)
368 0 : nThreads = 1;
369 21 : return nThreads;
370 : }
371 :
372 : /************************************************************************/
373 : /* JP2OpenJPEGReadBlockInThread() */
374 : /************************************************************************/
375 :
376 : class JobStruct
377 22 : {
378 : public:
379 :
380 : JP2OpenJPEGDataset* poGDS;
381 : int nBand;
382 : std::vector< std::pair<int, int> > oPairs;
383 : volatile int nCurPair;
384 : int nBandCount;
385 : int *panBandMap;
386 : };
387 :
388 41 : static void JP2OpenJPEGReadBlockInThread(void* userdata)
389 : {
390 : int nPair;
391 41 : JobStruct* poJob = (JobStruct*) userdata;
392 41 : JP2OpenJPEGDataset* poGDS = poJob->poGDS;
393 41 : int nBand = poJob->nBand;
394 41 : int nPairs = (int)poJob->oPairs.size();
395 41 : int nBandCount = poJob->nBandCount;
396 41 : int* panBandMap = poJob->panBandMap;
397 41 : VSILFILE* fp = VSIFOpenL(poGDS->GetDescription(), "rb");
398 41 : if( fp == NULL )
399 : {
400 0 : CPLDebug("OPENJPEG", "Cannot open %s", poGDS->GetDescription());
401 0 : return;
402 : }
403 :
404 132 : while( (nPair = CPLAtomicInc(&(poJob->nCurPair))) < nPairs )
405 : {
406 50 : int nBlockXOff = poJob->oPairs[nPair].first;
407 50 : int nBlockYOff = poJob->oPairs[nPair].second;
408 : GDALRasterBlock* poBlock = poGDS->GetRasterBand(nBand)->
409 50 : GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
410 50 : if (poBlock == NULL)
411 0 : break;
412 :
413 50 : void* pDstBuffer = poBlock->GetDataRef();
414 50 : if (!pDstBuffer)
415 : {
416 0 : poBlock->DropLock();
417 0 : break;
418 : }
419 :
420 : poGDS->ReadBlock(nBand, fp, nBlockXOff, nBlockYOff, pDstBuffer,
421 50 : nBandCount, panBandMap);
422 :
423 50 : poBlock->DropLock();
424 : }
425 :
426 41 : VSIFCloseL(fp);
427 : }
428 :
429 : /************************************************************************/
430 : /* PreloadBlocks() */
431 : /************************************************************************/
432 :
433 10695 : int JP2OpenJPEGDataset::PreloadBlocks(JP2OpenJPEGRasterBand* poBand,
434 : int nXOff, int nYOff, int nXSize, int nYSize,
435 : int nBandCount, int *panBandMap)
436 : {
437 10695 : int bRet = TRUE;
438 10695 : int nXStart = nXOff / poBand->nBlockXSize;
439 10695 : int nXEnd = (nXOff + nXSize - 1) / poBand->nBlockXSize;
440 10695 : int nYStart = nYOff / poBand->nBlockYSize;
441 10695 : int nYEnd = (nYOff + nYSize - 1) / poBand->nBlockYSize;
442 : GIntBig nReqMem = (GIntBig)(nXEnd - nXStart + 1) * (nYEnd - nYStart + 1) *
443 10695 : poBand->nBlockXSize * poBand->nBlockYSize * (GDALGetDataTypeSize(poBand->eDataType) / 8);
444 :
445 10695 : int nMaxThreads = GetNumThreads();
446 10695 : if( !bUseSetDecodeArea && nMaxThreads > 1 )
447 : {
448 10695 : if( nReqMem > GDALGetCacheMax64() / (nBandCount == 0 ? 1 : nBandCount) )
449 0 : return FALSE;
450 :
451 10695 : int nBlocksToLoad = 0;
452 10695 : std::vector< std::pair<int,int> > oPairs;
453 36943 : for(int nBlockXOff = nXStart; nBlockXOff <= nXEnd; ++nBlockXOff)
454 : {
455 52500 : for(int nBlockYOff = nYStart; nBlockYOff <= nYEnd; ++nBlockYOff)
456 : {
457 26252 : GDALRasterBlock* poBlock = poBand->TryGetLockedBlockRef(nBlockXOff,nBlockYOff);
458 26252 : if (poBlock != NULL)
459 : {
460 26184 : poBlock->DropLock();
461 26184 : continue;
462 : }
463 68 : oPairs.push_back( std::pair<int,int>(nBlockXOff, nBlockYOff) );
464 68 : nBlocksToLoad ++;
465 : }
466 : }
467 :
468 10695 : if( nBlocksToLoad > 1 )
469 : {
470 11 : int nThreads = MIN(nBlocksToLoad, nMaxThreads);
471 11 : void** pahThreads = (void**) CPLMalloc( sizeof(void*) * nThreads );
472 : int i;
473 :
474 11 : CPLDebug("OPENJPEG", "%d blocks to load", nBlocksToLoad);
475 :
476 11 : JobStruct oJob;
477 11 : oJob.poGDS = this;
478 11 : oJob.nBand = poBand->GetBand();
479 11 : oJob.oPairs = oPairs;
480 11 : oJob.nCurPair = -1;
481 11 : if( nBandCount > 0 )
482 : {
483 0 : oJob.nBandCount = nBandCount;
484 0 : oJob.panBandMap = panBandMap;
485 : }
486 : else
487 : {
488 11 : if( nReqMem <= GDALGetCacheMax64() / nBands )
489 : {
490 11 : oJob.nBandCount = nBands;
491 11 : oJob.panBandMap = NULL;
492 : }
493 : else
494 : {
495 0 : bRet = FALSE;
496 0 : oJob.nBandCount = 1;
497 0 : oJob.panBandMap = &oJob.nBand;
498 : }
499 : }
500 :
501 52 : for(i=0;i<nThreads;i++)
502 41 : pahThreads[i] = CPLCreateJoinableThread(JP2OpenJPEGReadBlockInThread, &oJob);
503 52 : for(i=0;i<nThreads;i++)
504 41 : CPLJoinThread( pahThreads[i] );
505 11 : CPLFree(pahThreads);
506 10695 : }
507 : }
508 :
509 10695 : return bRet;
510 : }
511 :
512 : /************************************************************************/
513 : /* IRasterIO() */
514 : /************************************************************************/
515 :
516 1 : CPLErr JP2OpenJPEGDataset::IRasterIO( GDALRWFlag eRWFlag,
517 : int nXOff, int nYOff, int nXSize, int nYSize,
518 : void * pData, int nBufXSize, int nBufYSize,
519 : GDALDataType eBufType,
520 : int nBandCount, int *panBandMap,
521 : int nPixelSpace, int nLineSpace, int nBandSpace)
522 : {
523 1 : if( eRWFlag != GF_Read )
524 0 : return CE_Failure;
525 :
526 1 : if( nBandCount < 1 )
527 0 : return CE_Failure;
528 :
529 1 : JP2OpenJPEGRasterBand* poBand = (JP2OpenJPEGRasterBand*) GetRasterBand(panBandMap[0]);
530 :
531 : /* ==================================================================== */
532 : /* Do we have overviews that would be appropriate to satisfy */
533 : /* this request? */
534 : /* ==================================================================== */
535 :
536 1 : if( (nBufXSize < nXSize || nBufYSize < nYSize)
537 0 : && poBand->GetOverviewCount() > 0 && eRWFlag == GF_Read )
538 : {
539 : int nOverview;
540 :
541 : nOverview =
542 : GDALBandGetBestOverviewLevel(poBand, nXOff, nYOff, nXSize, nYSize,
543 0 : nBufXSize, nBufYSize);
544 0 : if (nOverview >= 0)
545 : {
546 0 : return papoOverviewDS[nOverview]->RasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize,
547 : pData, nBufXSize, nBufYSize, eBufType,
548 : nBandCount, panBandMap,
549 0 : nPixelSpace, nLineSpace, nBandSpace );
550 : }
551 : }
552 :
553 1 : bEnoughMemoryToLoadOtherBands = PreloadBlocks(poBand, nXOff, nYOff, nXSize, nYSize, nBandCount, panBandMap);
554 :
555 : CPLErr eErr = GDALPamDataset::IRasterIO( eRWFlag,
556 : nXOff, nYOff, nXSize, nYSize,
557 : pData, nBufXSize, nBufYSize,
558 : eBufType,
559 : nBandCount, panBandMap,
560 1 : nPixelSpace, nLineSpace, nBandSpace );
561 :
562 1 : bEnoughMemoryToLoadOtherBands = TRUE;
563 1 : return eErr;
564 : }
565 :
566 : /************************************************************************/
567 : /* ReadBlock() */
568 : /************************************************************************/
569 :
570 71 : CPLErr JP2OpenJPEGDataset::ReadBlock( int nBand, VSILFILE* fp,
571 : int nBlockXOff, int nBlockYOff, void * pImage,
572 : int nBandCount, int* panBandMap )
573 : {
574 71 : CPLErr eErr = CE_None;
575 : opj_codec_t* pCodec;
576 : opj_stream_t * pStream;
577 : opj_image_t * psImage;
578 :
579 71 : JP2OpenJPEGRasterBand* poBand = (JP2OpenJPEGRasterBand*) GetRasterBand(nBand);
580 71 : int nBlockXSize = poBand->nBlockXSize;
581 71 : int nBlockYSize = poBand->nBlockYSize;
582 71 : GDALDataType eDataType = poBand->eDataType;
583 :
584 71 : int nDataTypeSize = (GDALGetDataTypeSize(eDataType) / 8);
585 :
586 71 : int nTileNumber = nBlockXOff + nBlockYOff * poBand->nBlocksPerRow;
587 71 : int nWidthToRead = MIN(nBlockXSize, nRasterXSize - nBlockXOff * nBlockXSize);
588 71 : int nHeightToRead = MIN(nBlockYSize, nRasterYSize - nBlockYOff * nBlockYSize);
589 :
590 71 : pCodec = opj_create_decompress(eCodecFormat);
591 :
592 71 : opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
593 71 : opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback, NULL);
594 71 : opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
595 :
596 : opj_dparameters_t parameters;
597 71 : opj_set_default_decoder_parameters(¶meters);
598 :
599 71 : if (! opj_setup_decoder(pCodec,¶meters))
600 : {
601 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_setup_decoder() failed");
602 0 : return CE_Failure;
603 : }
604 :
605 71 : pStream = opj_stream_create(1024, TRUE); // Default 1MB is way too big for some datasets
606 :
607 71 : VSIFSeekL(fp, 0, SEEK_END);
608 71 : opj_stream_set_user_data_length(pStream, VSIFTellL(fp));
609 : /* Reseek to file beginning */
610 71 : VSIFSeekL(fp, 0, SEEK_SET);
611 :
612 71 : opj_stream_set_read_function(pStream, JP2OpenJPEGDataset_Read);
613 71 : opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
614 71 : opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
615 71 : opj_stream_set_user_data(pStream, fp);
616 :
617 71 : if(!opj_read_header(pStream,pCodec,&psImage))
618 : {
619 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
620 0 : return CE_Failure;
621 : }
622 :
623 71 : if (!opj_set_decoded_resolution_factor( pCodec, iLevel ))
624 : {
625 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_set_decoded_resolution_factor() failed");
626 0 : eErr = CE_Failure;
627 0 : goto end;
628 : }
629 :
630 71 : if (bUseSetDecodeArea)
631 : {
632 0 : if (!opj_set_decode_area(pCodec,psImage,
633 : nBlockXOff*nBlockXSize,nBlockYOff*nBlockYSize,
634 : (nBlockXOff+1)*nBlockXSize,(nBlockYOff+1)*nBlockYSize))
635 : {
636 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_set_decode_area() failed");
637 0 : eErr = CE_Failure;
638 0 : goto end;
639 : }
640 0 : if (!opj_decode(pCodec,pStream, psImage))
641 : {
642 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_decode() failed");
643 0 : eErr = CE_Failure;
644 0 : goto end;
645 : }
646 : }
647 : else
648 : {
649 71 : if (!opj_get_decoded_tile( pCodec, pStream, psImage, nTileNumber ))
650 : {
651 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_get_decoded_tile() failed");
652 0 : eErr = CE_Failure;
653 0 : goto end;
654 : }
655 : }
656 :
657 255 : for(int xBand = 0; xBand < nBandCount; xBand ++)
658 : {
659 : void* pDstBuffer;
660 184 : GDALRasterBlock *poBlock = NULL;
661 184 : int iBand = (panBandMap) ? panBandMap[xBand] : xBand + 1;
662 :
663 184 : if (iBand == nBand)
664 71 : pDstBuffer = pImage;
665 : else
666 : {
667 : poBlock = ((JP2OpenJPEGRasterBand*)GetRasterBand(iBand))->
668 113 : TryGetLockedBlockRef(nBlockXOff,nBlockYOff);
669 113 : if (poBlock != NULL)
670 : {
671 0 : poBlock->DropLock();
672 0 : continue;
673 : }
674 :
675 : poBlock = GetRasterBand(iBand)->
676 113 : GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
677 113 : if (poBlock == NULL)
678 : {
679 0 : continue;
680 : }
681 :
682 113 : pDstBuffer = poBlock->GetDataRef();
683 113 : if (!pDstBuffer)
684 : {
685 0 : poBlock->DropLock();
686 0 : continue;
687 : }
688 : }
689 :
690 184 : if (bIs420)
691 : {
692 3 : CPLAssert((int)psImage->comps[0].w >= nWidthToRead);
693 3 : CPLAssert((int)psImage->comps[0].h >= nHeightToRead);
694 3 : CPLAssert(psImage->comps[1].w == (psImage->comps[0].w + 1) / 2);
695 3 : CPLAssert(psImage->comps[1].h == (psImage->comps[0].h + 1) / 2);
696 3 : CPLAssert(psImage->comps[2].w == (psImage->comps[0].w + 1) / 2);
697 3 : CPLAssert(psImage->comps[2].h == (psImage->comps[0].h + 1) / 2);
698 :
699 3 : OPJ_INT32* pSrcY = psImage->comps[0].data;
700 3 : OPJ_INT32* pSrcCb = psImage->comps[1].data;
701 3 : OPJ_INT32* pSrcCr = psImage->comps[2].data;
702 3 : GByte* pDst = (GByte*)pDstBuffer;
703 1923 : for(int j=0;j<nHeightToRead;j++)
704 : {
705 923520 : for(int i=0;i<nWidthToRead;i++)
706 : {
707 921600 : int Y = pSrcY[j * psImage->comps[0].w + i];
708 921600 : int Cb = pSrcCb[(j/2) * psImage->comps[1].w + (i/2)];
709 921600 : int Cr = pSrcCr[(j/2) * psImage->comps[2].w + (i/2)];
710 921600 : if (iBand == 1)
711 307200 : pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.402 * (Cr - 128)));
712 614400 : else if (iBand == 2)
713 307200 : pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128)));
714 : else
715 307200 : pDst[j * nBlockXSize + i] = CLAMP_0_255((int)(Y + 1.772 * (Cb - 128)));
716 : }
717 : }
718 : }
719 : else
720 : {
721 181 : CPLAssert((int)psImage->comps[iBand-1].w >= nWidthToRead);
722 181 : CPLAssert((int)psImage->comps[iBand-1].h >= nHeightToRead);
723 :
724 459 : if ((int)psImage->comps[iBand-1].w == nBlockXSize &&
725 151 : (int)psImage->comps[iBand-1].h == nBlockYSize)
726 : {
727 127 : GDALCopyWords(psImage->comps[iBand-1].data, GDT_Int32, 4,
728 254 : pDstBuffer, eDataType, nDataTypeSize, nBlockXSize * nBlockYSize);
729 : }
730 : else
731 : {
732 12292 : for(int j=0;j<nHeightToRead;j++)
733 : {
734 24476 : GDALCopyWords(psImage->comps[iBand-1].data + j * psImage->comps[iBand-1].w, GDT_Int32, 4,
735 : (GByte*)pDstBuffer + j * nBlockXSize * nDataTypeSize, eDataType, nDataTypeSize,
736 36714 : nWidthToRead);
737 : }
738 : }
739 : }
740 :
741 184 : if (poBlock != NULL)
742 113 : poBlock->DropLock();
743 : }
744 :
745 : end:
746 71 : opj_end_decompress(pCodec,pStream);
747 71 : opj_stream_destroy(pStream);
748 71 : opj_destroy_codec(pCodec);
749 71 : opj_image_destroy(psImage);
750 :
751 71 : return eErr;
752 : }
753 :
754 :
755 : /************************************************************************/
756 : /* GetOverviewCount() */
757 : /************************************************************************/
758 :
759 24 : int JP2OpenJPEGRasterBand::GetOverviewCount()
760 : {
761 24 : JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
762 24 : return poGDS->nOverviewCount;
763 : }
764 :
765 : /************************************************************************/
766 : /* GetOverview() */
767 : /************************************************************************/
768 :
769 8 : GDALRasterBand* JP2OpenJPEGRasterBand::GetOverview(int iOvrLevel)
770 : {
771 8 : JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
772 8 : if (iOvrLevel < 0 || iOvrLevel >= poGDS->nOverviewCount)
773 0 : return NULL;
774 :
775 8 : return poGDS->papoOverviewDS[iOvrLevel]->GetRasterBand(nBand);
776 : }
777 :
778 : /************************************************************************/
779 : /* GetColorInterpretation() */
780 : /************************************************************************/
781 :
782 27 : GDALColorInterp JP2OpenJPEGRasterBand::GetColorInterpretation()
783 : {
784 27 : JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
785 :
786 27 : if (poGDS->eColorSpace == OPJ_CLRSPC_GRAY)
787 0 : return GCI_GrayIndex;
788 27 : else if (poGDS->nBands == 3 || poGDS->nBands == 4)
789 : {
790 22 : switch(nBand)
791 : {
792 : case 1:
793 4 : return GCI_RedBand;
794 : case 2:
795 4 : return GCI_GreenBand;
796 : case 3:
797 4 : return GCI_BlueBand;
798 : case 4:
799 10 : return GCI_AlphaBand;
800 : default:
801 0 : return GCI_Undefined;
802 : }
803 : }
804 :
805 5 : return GCI_Undefined;
806 : }
807 :
808 : /************************************************************************/
809 : /* ==================================================================== */
810 : /* JP2OpenJPEGDataset */
811 : /* ==================================================================== */
812 : /************************************************************************/
813 :
814 : /************************************************************************/
815 : /* JP2OpenJPEGDataset() */
816 : /************************************************************************/
817 :
818 54 : JP2OpenJPEGDataset::JP2OpenJPEGDataset()
819 : {
820 54 : fp = NULL;
821 54 : nBands = 0;
822 54 : pszProjection = CPLStrdup("");
823 54 : nGCPCount = 0;
824 54 : pasGCPList = NULL;
825 54 : bGeoTransformValid = FALSE;
826 54 : adfGeoTransform[0] = 0.0;
827 54 : adfGeoTransform[1] = 1.0;
828 54 : adfGeoTransform[2] = 0.0;
829 54 : adfGeoTransform[3] = 0.0;
830 54 : adfGeoTransform[4] = 0.0;
831 54 : adfGeoTransform[5] = 1.0;
832 54 : eCodecFormat = OPJ_CODEC_UNKNOWN;
833 54 : eColorSpace = OPJ_CLRSPC_UNKNOWN;
834 54 : bIs420 = FALSE;
835 54 : iLevel = 0;
836 54 : nOverviewCount = 0;
837 54 : papoOverviewDS = NULL;
838 54 : bUseSetDecodeArea = FALSE;
839 54 : nThreads = -1;
840 54 : bEnoughMemoryToLoadOtherBands = TRUE;
841 54 : }
842 :
843 : /************************************************************************/
844 : /* ~JP2OpenJPEGDataset() */
845 : /************************************************************************/
846 :
847 54 : JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
848 :
849 : {
850 54 : FlushCache();
851 :
852 54 : if ( pszProjection )
853 54 : CPLFree( pszProjection );
854 54 : if( nGCPCount > 0 )
855 : {
856 2 : GDALDeinitGCPs( nGCPCount, pasGCPList );
857 2 : CPLFree( pasGCPList );
858 : }
859 54 : if( fp != NULL )
860 54 : VSIFCloseL( fp );
861 :
862 54 : CloseDependentDatasets();
863 54 : }
864 :
865 : /************************************************************************/
866 : /* CloseDependentDatasets() */
867 : /************************************************************************/
868 :
869 54 : int JP2OpenJPEGDataset::CloseDependentDatasets()
870 : {
871 54 : int bRet = GDALPamDataset::CloseDependentDatasets();
872 54 : if ( papoOverviewDS )
873 : {
874 33 : for( int i = 0; i < nOverviewCount; i++ )
875 22 : delete papoOverviewDS[i];
876 11 : CPLFree( papoOverviewDS );
877 11 : papoOverviewDS = NULL;
878 11 : bRet = TRUE;
879 : }
880 54 : return bRet;
881 : }
882 :
883 :
884 : /************************************************************************/
885 : /* GetProjectionRef() */
886 : /************************************************************************/
887 :
888 23 : const char *JP2OpenJPEGDataset::GetProjectionRef()
889 :
890 : {
891 23 : if ( pszProjection && pszProjection[0] != 0 )
892 19 : return( pszProjection );
893 : else
894 4 : return GDALPamDataset::GetProjectionRef();
895 : }
896 :
897 : /************************************************************************/
898 : /* GetGeoTransform() */
899 : /************************************************************************/
900 :
901 28 : CPLErr JP2OpenJPEGDataset::GetGeoTransform( double * padfTransform )
902 : {
903 28 : if( bGeoTransformValid )
904 : {
905 26 : memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform[0]) * 6 );
906 26 : return CE_None;
907 : }
908 : else
909 2 : return GDALPamDataset::GetGeoTransform(padfTransform);
910 : }
911 :
912 : /************************************************************************/
913 : /* GetGCPCount() */
914 : /************************************************************************/
915 :
916 6 : int JP2OpenJPEGDataset::GetGCPCount()
917 :
918 : {
919 6 : if( nGCPCount > 0 )
920 1 : return nGCPCount;
921 : else
922 5 : return GDALPamDataset::GetGCPCount();
923 : }
924 :
925 : /************************************************************************/
926 : /* GetGCPProjection() */
927 : /************************************************************************/
928 :
929 1 : const char *JP2OpenJPEGDataset::GetGCPProjection()
930 :
931 : {
932 1 : if( nGCPCount > 0 )
933 1 : return pszProjection;
934 : else
935 0 : return GDALPamDataset::GetGCPProjection();
936 : }
937 :
938 : /************************************************************************/
939 : /* GetGCP() */
940 : /************************************************************************/
941 :
942 1 : const GDAL_GCP *JP2OpenJPEGDataset::GetGCPs()
943 :
944 : {
945 1 : if( nGCPCount > 0 )
946 1 : return pasGCPList;
947 : else
948 0 : return GDALPamDataset::GetGCPs();
949 : }
950 :
951 : /************************************************************************/
952 : /* Identify() */
953 : /************************************************************************/
954 :
955 12011 : int JP2OpenJPEGDataset::Identify( GDALOpenInfo * poOpenInfo )
956 :
957 : {
958 : static const unsigned char jpc_header[] = {0xff,0x4f};
959 : static const unsigned char jp2_box_jp[] = {0x6a,0x50,0x20,0x20}; /* 'jP ' */
960 :
961 12011 : if( poOpenInfo->nHeaderBytes >= 16
962 : && (memcmp( poOpenInfo->pabyHeader, jpc_header,
963 : sizeof(jpc_header) ) == 0
964 : || memcmp( poOpenInfo->pabyHeader + 4, jp2_box_jp,
965 : sizeof(jp2_box_jp) ) == 0
966 : ) )
967 32 : return TRUE;
968 :
969 : else
970 11979 : return FALSE;
971 : }
972 : /************************************************************************/
973 : /* Open() */
974 : /************************************************************************/
975 :
976 1950 : GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
977 :
978 : {
979 1950 : if (!Identify(poOpenInfo))
980 1918 : return NULL;
981 :
982 32 : VSILFILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
983 32 : if (!fp)
984 0 : return NULL;
985 :
986 : OPJ_CODEC_FORMAT eCodecFormat;
987 :
988 : /* Detect which codec to use : J2K or JP2 ? */
989 : static const unsigned char jpc_header[] = {0xff,0x4f};
990 32 : if (memcmp( poOpenInfo->pabyHeader, jpc_header,
991 : sizeof(jpc_header) ) == 0)
992 10 : eCodecFormat = OPJ_CODEC_J2K;
993 : else
994 22 : eCodecFormat = OPJ_CODEC_JP2;
995 :
996 : opj_codec_t* pCodec;
997 :
998 32 : pCodec = opj_create_decompress(eCodecFormat);
999 :
1000 32 : opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
1001 32 : opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback, NULL);
1002 32 : opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
1003 :
1004 : opj_dparameters_t parameters;
1005 32 : opj_set_default_decoder_parameters(¶meters);
1006 :
1007 32 : if (! opj_setup_decoder(pCodec,¶meters))
1008 : {
1009 0 : VSIFCloseL(fp);
1010 0 : return NULL;
1011 : }
1012 :
1013 : opj_stream_t * pStream;
1014 32 : pStream = opj_stream_create(1024, TRUE); // Default 1MB is way too big for some datasets
1015 :
1016 32 : VSIFSeekL(fp, 0, SEEK_END);
1017 32 : opj_stream_set_user_data_length(pStream, VSIFTellL(fp));
1018 : /* Reseek to file beginning */
1019 32 : VSIFSeekL(fp, 0, SEEK_SET);
1020 :
1021 32 : opj_stream_set_read_function(pStream, JP2OpenJPEGDataset_Read);
1022 32 : opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
1023 32 : opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
1024 32 : opj_stream_set_user_data(pStream, fp);
1025 :
1026 32 : opj_image_t * psImage = NULL;
1027 : OPJ_INT32 nX0,nY0;
1028 : OPJ_UINT32 nTileW,nTileH,nTilesX,nTilesY;
1029 32 : if(!opj_read_header(pStream,pCodec,&psImage))
1030 : {
1031 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
1032 0 : opj_destroy_codec(pCodec);
1033 0 : opj_stream_destroy(pStream);
1034 0 : opj_image_destroy(psImage);
1035 0 : VSIFCloseL(fp);
1036 0 : return NULL;
1037 : }
1038 :
1039 32 : opj_codestream_info_v2_t* pCodeStreamInfo = opj_get_cstr_info(pCodec);
1040 32 : nX0 = pCodeStreamInfo->tx0;
1041 32 : nY0 = pCodeStreamInfo->ty0;
1042 32 : nTileW = pCodeStreamInfo->tdx;
1043 32 : nTileH = pCodeStreamInfo->tdy;
1044 32 : nTilesX = pCodeStreamInfo->tw;
1045 32 : nTilesY = pCodeStreamInfo->th;
1046 32 : int numResolutions = pCodeStreamInfo->m_default_tile_info.tccp_info[0].numresolutions;
1047 32 : opj_destroy_cstr_info(&pCodeStreamInfo);
1048 :
1049 32 : if (psImage == NULL)
1050 : {
1051 0 : opj_destroy_codec(pCodec);
1052 0 : opj_stream_destroy(pStream);
1053 0 : opj_image_destroy(psImage);
1054 0 : VSIFCloseL(fp);
1055 0 : return NULL;
1056 : }
1057 :
1058 : #ifdef DEBUG
1059 : int i;
1060 32 : CPLDebug("OPENJPEG", "nX0 = %d", nX0);
1061 32 : CPLDebug("OPENJPEG", "nY0 = %d", nY0);
1062 32 : CPLDebug("OPENJPEG", "nTileW = %d", nTileW);
1063 32 : CPLDebug("OPENJPEG", "nTileH = %d", nTileH);
1064 32 : CPLDebug("OPENJPEG", "psImage->x0 = %d", psImage->x0);
1065 32 : CPLDebug("OPENJPEG", "psImage->y0 = %d", psImage->y0);
1066 32 : CPLDebug("OPENJPEG", "psImage->x1 = %d", psImage->x1);
1067 32 : CPLDebug("OPENJPEG", "psImage->y1 = %d", psImage->y1);
1068 32 : CPLDebug("OPENJPEG", "psImage->numcomps = %d", psImage->numcomps);
1069 32 : CPLDebug("OPENJPEG", "psImage->color_space = %d", psImage->color_space);
1070 32 : CPLDebug("OPENJPEG", "numResolutions = %d", numResolutions);
1071 87 : for(i=0;i<(int)psImage->numcomps;i++)
1072 : {
1073 55 : CPLDebug("OPENJPEG", "psImage->comps[%d].dx = %d", i, psImage->comps[i].dx);
1074 55 : CPLDebug("OPENJPEG", "psImage->comps[%d].dy = %d", i, psImage->comps[i].dy);
1075 55 : CPLDebug("OPENJPEG", "psImage->comps[%d].x0 = %d", i, psImage->comps[i].x0);
1076 55 : CPLDebug("OPENJPEG", "psImage->comps[%d].y0 = %d", i, psImage->comps[i].y0);
1077 55 : CPLDebug("OPENJPEG", "psImage->comps[%d].w = %d", i, psImage->comps[i].w);
1078 55 : CPLDebug("OPENJPEG", "psImage->comps[%d].h = %d", i, psImage->comps[i].h);
1079 55 : CPLDebug("OPENJPEG", "psImage->comps[%d].resno_decoded = %d", i, psImage->comps[i].resno_decoded);
1080 55 : CPLDebug("OPENJPEG", "psImage->comps[%d].factor = %d", i, psImage->comps[i].factor);
1081 55 : CPLDebug("OPENJPEG", "psImage->comps[%d].prec = %d", i, psImage->comps[i].prec);
1082 55 : CPLDebug("OPENJPEG", "psImage->comps[%d].sgnd = %d", i, psImage->comps[i].sgnd);
1083 : }
1084 : #endif
1085 :
1086 96 : if (psImage->x1 <= psImage->x0 ||
1087 : psImage->y1 <= psImage->y0 ||
1088 : psImage->numcomps == 0 ||
1089 32 : psImage->comps[0].w != psImage->x1 - psImage->x0 ||
1090 32 : psImage->comps[0].h != psImage->y1 - psImage->y0)
1091 : {
1092 0 : CPLDebug("OPENJPEG", "Unable to handle that image (1)");
1093 0 : opj_destroy_codec(pCodec);
1094 0 : opj_stream_destroy(pStream);
1095 0 : opj_image_destroy(psImage);
1096 0 : VSIFCloseL(fp);
1097 0 : return NULL;
1098 : }
1099 :
1100 32 : GDALDataType eDataType = GDT_Byte;
1101 32 : if (psImage->comps[0].prec > 16)
1102 : {
1103 0 : if (psImage->comps[0].sgnd)
1104 0 : eDataType = GDT_Int32;
1105 : else
1106 0 : eDataType = GDT_UInt32;
1107 : }
1108 32 : else if (psImage->comps[0].prec > 8)
1109 : {
1110 10 : if (psImage->comps[0].sgnd)
1111 5 : eDataType = GDT_Int16;
1112 : else
1113 5 : eDataType = GDT_UInt16;
1114 : }
1115 :
1116 : int bIs420 = (psImage->color_space != OPJ_CLRSPC_SRGB &&
1117 : eDataType == GDT_Byte &&
1118 : psImage->numcomps == 3 &&
1119 14 : psImage->comps[1].w == psImage->comps[0].w / 2 &&
1120 2 : psImage->comps[1].h == psImage->comps[0].h / 2 &&
1121 2 : psImage->comps[2].w == psImage->comps[0].w / 2 &&
1122 50 : psImage->comps[2].h == psImage->comps[0].h / 2);
1123 :
1124 32 : if (bIs420)
1125 : {
1126 1 : CPLDebug("OPENJPEG", "420 format");
1127 : }
1128 : else
1129 : {
1130 : int iBand;
1131 52 : for(iBand = 2; iBand <= (int)psImage->numcomps; iBand ++)
1132 : {
1133 63 : if( psImage->comps[iBand-1].w != psImage->comps[0].w ||
1134 42 : psImage->comps[iBand-1].h != psImage->comps[0].h )
1135 : {
1136 0 : CPLDebug("OPENJPEG", "Unable to handle that image (2)");
1137 0 : opj_destroy_codec(pCodec);
1138 0 : opj_stream_destroy(pStream);
1139 0 : opj_image_destroy(psImage);
1140 0 : VSIFCloseL(fp);
1141 0 : return NULL;
1142 : }
1143 : }
1144 : }
1145 :
1146 :
1147 : /* -------------------------------------------------------------------- */
1148 : /* Create a corresponding GDALDataset. */
1149 : /* -------------------------------------------------------------------- */
1150 : JP2OpenJPEGDataset *poDS;
1151 : int iBand;
1152 :
1153 32 : poDS = new JP2OpenJPEGDataset();
1154 32 : poDS->eCodecFormat = eCodecFormat;
1155 32 : poDS->eColorSpace = psImage->color_space;
1156 32 : poDS->nRasterXSize = psImage->x1 - psImage->x0;
1157 32 : poDS->nRasterYSize = psImage->y1 - psImage->y0;
1158 32 : poDS->nBands = psImage->numcomps;
1159 32 : poDS->fp = fp;
1160 32 : poDS->bIs420 = bIs420;
1161 :
1162 : poDS->bUseSetDecodeArea =
1163 : (poDS->nRasterXSize == (int)nTileW &&
1164 : poDS->nRasterYSize == (int)nTileH &&
1165 : (poDS->nRasterXSize > 1024 ||
1166 62 : poDS->nRasterYSize > 1024));
1167 :
1168 32 : if (poDS->bUseSetDecodeArea)
1169 : {
1170 0 : if (nTileW > 1024) nTileW = 1024;
1171 0 : if (nTileH > 1024) nTileH = 1024;
1172 : }
1173 :
1174 : /* -------------------------------------------------------------------- */
1175 : /* Create band information objects. */
1176 : /* -------------------------------------------------------------------- */
1177 174 : for( iBand = 1; iBand <= poDS->nBands; iBand++ )
1178 : {
1179 : poDS->SetBand( iBand, new JP2OpenJPEGRasterBand( poDS, iBand, eDataType,
1180 55 : psImage->comps[iBand-1].prec,
1181 110 : nTileW, nTileH) );
1182 : }
1183 :
1184 : /* -------------------------------------------------------------------- */
1185 : /* Create overview datasets. */
1186 : /* -------------------------------------------------------------------- */
1187 32 : int nW = poDS->nRasterXSize;
1188 32 : int nH = poDS->nRasterYSize;
1189 86 : while (poDS->nOverviewCount+1 < numResolutions &&
1190 : (nW > 256 || nH > 256) &&
1191 : (poDS->bUseSetDecodeArea || ((nTileW % 2) == 0 && (nTileH % 2) == 0)))
1192 : {
1193 22 : nW /= 2;
1194 22 : nH /= 2;
1195 :
1196 22 : VSILFILE* fpOvr = VSIFOpenL(poOpenInfo->pszFilename, "rb");
1197 22 : if (!fpOvr)
1198 0 : break;
1199 :
1200 : poDS->papoOverviewDS = (JP2OpenJPEGDataset**) CPLRealloc(
1201 : poDS->papoOverviewDS,
1202 22 : (poDS->nOverviewCount + 1) * sizeof(JP2OpenJPEGDataset*));
1203 22 : JP2OpenJPEGDataset* poODS = new JP2OpenJPEGDataset();
1204 22 : poODS->SetDescription( poOpenInfo->pszFilename );
1205 22 : poODS->iLevel = poDS->nOverviewCount + 1;
1206 22 : poODS->bUseSetDecodeArea = poDS->bUseSetDecodeArea;
1207 22 : if (!poDS->bUseSetDecodeArea)
1208 : {
1209 22 : nTileW /= 2;
1210 22 : nTileH /= 2;
1211 : }
1212 : else
1213 : {
1214 0 : if (nW < (int)nTileW || nH < (int)nTileH)
1215 : {
1216 0 : nTileW = nW;
1217 0 : nTileH = nH;
1218 0 : poODS->bUseSetDecodeArea = FALSE;
1219 : }
1220 : }
1221 :
1222 22 : poODS->eCodecFormat = poDS->eCodecFormat;
1223 22 : poODS->eColorSpace = poDS->eColorSpace;
1224 22 : poODS->nRasterXSize = nW;
1225 22 : poODS->nRasterYSize = nH;
1226 22 : poODS->nBands = poDS->nBands;
1227 22 : poODS->fp = fpOvr;
1228 22 : poODS->bIs420 = bIs420;
1229 178 : for( iBand = 1; iBand <= poDS->nBands; iBand++ )
1230 : {
1231 : poODS->SetBand( iBand, new JP2OpenJPEGRasterBand( poODS, iBand, eDataType,
1232 67 : psImage->comps[iBand-1].prec,
1233 134 : nTileW, nTileH ) );
1234 : }
1235 :
1236 22 : poDS->papoOverviewDS[poDS->nOverviewCount ++] = poODS;
1237 :
1238 : }
1239 :
1240 32 : opj_destroy_codec(pCodec);
1241 32 : opj_stream_destroy(pStream);
1242 32 : opj_image_destroy(psImage);
1243 32 : pCodec = NULL;
1244 32 : pStream = NULL;
1245 32 : psImage = NULL;
1246 :
1247 : /* -------------------------------------------------------------------- */
1248 : /* More metadata. */
1249 : /* -------------------------------------------------------------------- */
1250 32 : if( poDS->nBands > 1 )
1251 : {
1252 10 : poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
1253 : }
1254 :
1255 : /* -------------------------------------------------------------------- */
1256 : /* Check for georeferencing information. */
1257 : /* -------------------------------------------------------------------- */
1258 32 : GDALJP2Metadata oJP2Geo;
1259 :
1260 32 : if( oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
1261 : {
1262 20 : if ( poDS->pszProjection )
1263 20 : CPLFree( poDS->pszProjection );
1264 20 : poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
1265 20 : poDS->bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
1266 : memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform,
1267 20 : sizeof(double) * 6 );
1268 20 : poDS->nGCPCount = oJP2Geo.nGCPCount;
1269 : poDS->pasGCPList =
1270 20 : GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
1271 : }
1272 :
1273 32 : if (oJP2Geo.pszXMPMetadata)
1274 : {
1275 : char *apszMDList[2];
1276 1 : apszMDList[0] = (char *) oJP2Geo.pszXMPMetadata;
1277 1 : apszMDList[1] = NULL;
1278 1 : poDS->SetMetadata(apszMDList, "xml:XMP");
1279 : }
1280 :
1281 : /* -------------------------------------------------------------------- */
1282 : /* Do we have other misc metadata? */
1283 : /* -------------------------------------------------------------------- */
1284 32 : if( oJP2Geo.papszMetadata != NULL )
1285 : {
1286 4 : char **papszMD = CSLDuplicate(poDS->GDALPamDataset::GetMetadata());
1287 :
1288 4 : papszMD = CSLMerge( papszMD, oJP2Geo.papszMetadata );
1289 4 : poDS->GDALPamDataset::SetMetadata( papszMD );
1290 :
1291 4 : CSLDestroy( papszMD );
1292 : }
1293 :
1294 : /* -------------------------------------------------------------------- */
1295 : /* Check for world file. */
1296 : /* -------------------------------------------------------------------- */
1297 32 : if( !poDS->bGeoTransformValid )
1298 : {
1299 : poDS->bGeoTransformValid |=
1300 : GDALReadWorldFile2( poOpenInfo->pszFilename, NULL,
1301 : poDS->adfGeoTransform,
1302 : poOpenInfo->papszSiblingFiles, NULL )
1303 : || GDALReadWorldFile2( poOpenInfo->pszFilename, ".wld",
1304 : poDS->adfGeoTransform,
1305 14 : poOpenInfo->papszSiblingFiles, NULL );
1306 : }
1307 :
1308 : /* -------------------------------------------------------------------- */
1309 : /* Initialize any PAM information. */
1310 : /* -------------------------------------------------------------------- */
1311 32 : poDS->SetDescription( poOpenInfo->pszFilename );
1312 32 : poDS->TryLoadXML();
1313 :
1314 : /* -------------------------------------------------------------------- */
1315 : /* Check for overviews. */
1316 : /* -------------------------------------------------------------------- */
1317 : //poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
1318 :
1319 32 : return( poDS );
1320 : }
1321 :
1322 : /************************************************************************/
1323 : /* WriteBox() */
1324 : /************************************************************************/
1325 :
1326 6 : void JP2OpenJPEGDataset::WriteBox(VSILFILE* fp, GDALJP2Box* poBox)
1327 : {
1328 : GUInt32 nLBox;
1329 : GUInt32 nTBox;
1330 :
1331 6 : nLBox = (int) poBox->GetDataLength() + 8;
1332 6 : nLBox = CPL_MSBWORD32( nLBox );
1333 :
1334 6 : memcpy(&nTBox, poBox->GetType(), 4);
1335 :
1336 6 : VSIFWriteL( &nLBox, 4, 1, fp );
1337 6 : VSIFWriteL( &nTBox, 4, 1, fp );
1338 6 : VSIFWriteL(poBox->GetWritableData(), 1, (int) poBox->GetDataLength(), fp);
1339 6 : }
1340 :
1341 : /************************************************************************/
1342 : /* CreateCopy() */
1343 : /************************************************************************/
1344 :
1345 22 : GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
1346 : GDALDataset *poSrcDS,
1347 : int bStrict, char ** papszOptions,
1348 : GDALProgressFunc pfnProgress,
1349 : void * pProgressData )
1350 :
1351 : {
1352 22 : int nBands = poSrcDS->GetRasterCount();
1353 22 : int nXSize = poSrcDS->GetRasterXSize();
1354 22 : int nYSize = poSrcDS->GetRasterYSize();
1355 :
1356 22 : if( nBands != 1 && nBands != 3 )
1357 : {
1358 : CPLError( CE_Failure, CPLE_NotSupported,
1359 4 : "Unable to export files with %d bands.", nBands );
1360 4 : return NULL;
1361 : }
1362 :
1363 18 : if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
1364 : {
1365 : CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
1366 : "JP2OpenJPEG driver ignores color table. "
1367 : "The source raster band will be considered as grey level.\n"
1368 0 : "Consider using color table expansion (-expand option in gdal_translate)\n");
1369 0 : if (bStrict)
1370 0 : return NULL;
1371 : }
1372 :
1373 18 : GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
1374 18 : int nDataTypeSize = (GDALGetDataTypeSize(eDataType) / 8);
1375 18 : if (eDataType != GDT_Byte && eDataType != GDT_Int16 && eDataType != GDT_UInt16
1376 : && eDataType != GDT_Int32 && eDataType != GDT_UInt32)
1377 : {
1378 : CPLError( CE_Failure, CPLE_NotSupported,
1379 6 : "JP2OpenJPEG driver only supports creating Byte, GDT_Int16, GDT_UInt16, GDT_Int32, GDT_UInt32");
1380 6 : return NULL;
1381 : }
1382 :
1383 : /* -------------------------------------------------------------------- */
1384 : /* Analyze creation options. */
1385 : /* -------------------------------------------------------------------- */
1386 12 : OPJ_CODEC_FORMAT eCodecFormat = OPJ_CODEC_J2K;
1387 12 : const char* pszCodec = CSLFetchNameValueDef(papszOptions, "CODEC", NULL);
1388 12 : if (pszCodec)
1389 : {
1390 1 : if (EQUAL(pszCodec, "JP2"))
1391 0 : eCodecFormat = OPJ_CODEC_JP2;
1392 1 : else if (EQUAL(pszCodec, "J2K"))
1393 1 : eCodecFormat = OPJ_CODEC_J2K;
1394 : else
1395 : {
1396 : CPLError(CE_Warning, CPLE_NotSupported,
1397 : "Unsupported value for CODEC : %s. Defaulting to J2K",
1398 0 : pszCodec);
1399 : }
1400 : }
1401 : else
1402 : {
1403 11 : if (strlen(pszFilename) > 4 &&
1404 : EQUAL(pszFilename + strlen(pszFilename) - 4, ".JP2"))
1405 : {
1406 3 : eCodecFormat = OPJ_CODEC_JP2;
1407 : }
1408 : }
1409 :
1410 : int nBlockXSize =
1411 12 : atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "1024"));
1412 : int nBlockYSize =
1413 12 : atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "1024"));
1414 12 : if (nBlockXSize < 32 || nBlockYSize < 32)
1415 : {
1416 0 : CPLError(CE_Failure, CPLE_NotSupported, "Invalid block size");
1417 0 : return NULL;
1418 : }
1419 :
1420 12 : if (nXSize < nBlockXSize)
1421 10 : nBlockXSize = nXSize;
1422 12 : if (nYSize < nBlockYSize)
1423 10 : nBlockYSize = nYSize;
1424 :
1425 12 : OPJ_PROG_ORDER eProgOrder = OPJ_LRCP;
1426 : const char* pszPROGORDER =
1427 12 : CSLFetchNameValueDef(papszOptions, "PROGRESSION", "LRCP");
1428 12 : if (EQUAL(pszPROGORDER, "LRCP"))
1429 12 : eProgOrder = OPJ_LRCP;
1430 0 : else if (EQUAL(pszPROGORDER, "RLCP"))
1431 0 : eProgOrder = OPJ_RLCP;
1432 0 : else if (EQUAL(pszPROGORDER, "RPCL"))
1433 0 : eProgOrder = OPJ_RPCL;
1434 0 : else if (EQUAL(pszPROGORDER, "PCRL"))
1435 0 : eProgOrder = OPJ_PCRL;
1436 0 : else if (EQUAL(pszPROGORDER, "CPRL"))
1437 0 : eProgOrder = OPJ_CPRL;
1438 : else
1439 : {
1440 : CPLError(CE_Warning, CPLE_NotSupported,
1441 : "Unsupported value for PROGRESSION : %s. Defaulting to LRCP",
1442 0 : pszPROGORDER);
1443 : }
1444 :
1445 : int bIsIrreversible =
1446 12 : ! (CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "REVERSIBLE", "NO")));
1447 :
1448 12 : double dfRate = 100. / 25;
1449 12 : const char* pszQuality = CSLFetchNameValueDef(papszOptions, "QUALITY", NULL);
1450 12 : if (pszQuality)
1451 : {
1452 3 : double dfQuality = atof(pszQuality);
1453 6 : if (dfQuality > 0 && dfQuality <= 100)
1454 : {
1455 3 : dfRate = 100 / dfQuality;
1456 : }
1457 : else
1458 : {
1459 : CPLError(CE_Warning, CPLE_NotSupported,
1460 : "Unsupported value for QUALITY : %s. Defaulting to 25",
1461 0 : pszQuality);
1462 : }
1463 : }
1464 :
1465 12 : int nNumResolutions = 6;
1466 12 : const char* pszResolutions = CSLFetchNameValueDef(papszOptions, "RESOLUTIONS", NULL);
1467 12 : if (pszResolutions)
1468 : {
1469 1 : nNumResolutions = atoi(pszResolutions);
1470 1 : if (nNumResolutions < 1 || nNumResolutions > 7)
1471 : {
1472 0 : nNumResolutions = 6;
1473 : CPLError(CE_Warning, CPLE_NotSupported,
1474 : "Unsupported value for RESOLUTIONS : %s. Defaulting to 6",
1475 0 : pszResolutions);
1476 : }
1477 : }
1478 :
1479 12 : int bSOP = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SOP", "FALSE"));
1480 12 : int bEPH = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "EPH", "FALSE"));
1481 :
1482 : int bResample = nBands == 3 && eDataType == GDT_Byte &&
1483 12 : CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "YCBCR420", "FALSE"));
1484 12 : if (bResample && !((nXSize % 2) == 0 && (nYSize % 2) == 0 && (nBlockXSize % 2) == 0 && (nBlockYSize % 2) == 0))
1485 : {
1486 : CPLError(CE_Warning, CPLE_NotSupported,
1487 0 : "YCBCR420 unsupported when image size and/or tile size are not multiple of 2");
1488 0 : bResample = FALSE;
1489 : }
1490 :
1491 : /* -------------------------------------------------------------------- */
1492 : /* Setup encoder */
1493 : /* -------------------------------------------------------------------- */
1494 :
1495 : opj_cparameters_t parameters;
1496 12 : opj_set_default_encoder_parameters(¶meters);
1497 12 : if (bSOP)
1498 0 : parameters.csty |= 0x02;
1499 12 : if (bEPH)
1500 0 : parameters.csty |= 0x04;
1501 12 : parameters.cp_disto_alloc = 1;
1502 12 : parameters.tcp_numlayers = 1;
1503 12 : parameters.tcp_rates[0] = (float) dfRate;
1504 12 : parameters.cp_tx0 = 0;
1505 12 : parameters.cp_ty0 = 0;
1506 12 : parameters.tile_size_on = TRUE;
1507 12 : parameters.cp_tdx = nBlockXSize;
1508 12 : parameters.cp_tdy = nBlockYSize;
1509 12 : parameters.irreversible = bIsIrreversible;
1510 12 : parameters.numresolution = nNumResolutions;
1511 12 : parameters.prog_order = eProgOrder;
1512 :
1513 : opj_image_cmptparm_t* pasBandParams =
1514 12 : (opj_image_cmptparm_t*)CPLMalloc(nBands * sizeof(opj_image_cmptparm_t));
1515 : int iBand;
1516 26 : for(iBand=0;iBand<nBands;iBand++)
1517 : {
1518 14 : pasBandParams[iBand].x0 = 0;
1519 14 : pasBandParams[iBand].y0 = 0;
1520 14 : if (bResample && iBand > 0)
1521 : {
1522 0 : pasBandParams[iBand].dx = 2;
1523 0 : pasBandParams[iBand].dy = 2;
1524 0 : pasBandParams[iBand].w = nXSize / 2;
1525 0 : pasBandParams[iBand].h = nYSize / 2;
1526 : }
1527 : else
1528 : {
1529 14 : pasBandParams[iBand].dx = 1;
1530 14 : pasBandParams[iBand].dy = 1;
1531 14 : pasBandParams[iBand].w = nXSize;
1532 14 : pasBandParams[iBand].h = nYSize;
1533 : }
1534 14 : pasBandParams[iBand].sgnd = (eDataType == GDT_Int16 || eDataType == GDT_Int32);
1535 14 : pasBandParams[iBand].prec = 8 * nDataTypeSize;
1536 : }
1537 :
1538 12 : opj_codec_t* pCodec = opj_create_compress(eCodecFormat);
1539 12 : if (pCodec == NULL)
1540 : {
1541 : CPLError(CE_Failure, CPLE_AppDefined,
1542 0 : "opj_create_compress() failed");
1543 0 : CPLFree(pasBandParams);
1544 0 : return NULL;
1545 : }
1546 :
1547 12 : opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
1548 12 : opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback,NULL);
1549 12 : opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
1550 :
1551 12 : OPJ_COLOR_SPACE eColorSpace = (bResample) ? OPJ_CLRSPC_SYCC : (nBands == 3) ? OPJ_CLRSPC_SRGB : OPJ_CLRSPC_GRAY;
1552 :
1553 : opj_image_t* psImage = opj_image_tile_create(nBands,pasBandParams,
1554 12 : eColorSpace);
1555 :
1556 :
1557 12 : CPLFree(pasBandParams);
1558 12 : pasBandParams = NULL;
1559 12 : if (psImage == NULL)
1560 : {
1561 : CPLError(CE_Failure, CPLE_AppDefined,
1562 0 : "opj_image_tile_create() failed");
1563 0 : opj_destroy_codec(pCodec);
1564 0 : return NULL;
1565 : }
1566 :
1567 12 : psImage->x0 = 0;
1568 12 : psImage->y0 = 0;
1569 12 : psImage->x1 = nXSize;
1570 12 : psImage->y1 = nYSize;
1571 12 : psImage->color_space = eColorSpace;
1572 12 : psImage->numcomps = nBands;
1573 :
1574 12 : if (!opj_setup_encoder(pCodec,¶meters,psImage))
1575 : {
1576 : CPLError(CE_Failure, CPLE_AppDefined,
1577 0 : "opj_setup_encoder() failed");
1578 0 : opj_image_destroy(psImage);
1579 0 : opj_destroy_codec(pCodec);
1580 0 : return NULL;
1581 : }
1582 :
1583 : /* -------------------------------------------------------------------- */
1584 : /* Create the dataset. */
1585 : /* -------------------------------------------------------------------- */
1586 :
1587 12 : const char* pszAccess = EQUALN(pszFilename, "/vsisubfile/", 12) ? "r+b" : "w+b";
1588 12 : VSILFILE* fp = VSIFOpenL(pszFilename, pszAccess);
1589 12 : if (fp == NULL)
1590 : {
1591 2 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot create file");
1592 2 : opj_image_destroy(psImage);
1593 2 : opj_destroy_codec(pCodec);
1594 2 : return NULL;
1595 : }
1596 :
1597 : opj_stream_t * pStream;
1598 10 : pStream = opj_stream_create(1024*1024, FALSE);
1599 10 : opj_stream_set_write_function(pStream, JP2OpenJPEGDataset_Write);
1600 10 : opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
1601 10 : opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
1602 10 : opj_stream_set_user_data(pStream, fp);
1603 :
1604 10 : if (!opj_start_compress(pCodec,psImage,pStream))
1605 : {
1606 : CPLError(CE_Failure, CPLE_AppDefined,
1607 6 : "opj_start_compress() failed");
1608 6 : opj_stream_destroy(pStream);
1609 6 : opj_image_destroy(psImage);
1610 6 : opj_destroy_codec(pCodec);
1611 6 : VSIFCloseL(fp);
1612 6 : return NULL;
1613 : }
1614 :
1615 4 : int nTilesX = (nXSize + nBlockXSize - 1) / nBlockXSize;
1616 4 : int nTilesY = (nYSize + nBlockYSize - 1) / nBlockYSize;
1617 :
1618 : GByte* pTempBuffer =(GByte*)VSIMalloc(nBlockXSize * nBlockYSize *
1619 4 : nBands * nDataTypeSize);
1620 4 : if (pTempBuffer == NULL)
1621 : {
1622 0 : opj_stream_destroy(pStream);
1623 0 : opj_image_destroy(psImage);
1624 0 : opj_destroy_codec(pCodec);
1625 0 : VSIFCloseL(fp);
1626 0 : return NULL;
1627 : }
1628 :
1629 4 : GByte* pYUV420Buffer = NULL;
1630 4 : if (bResample)
1631 : {
1632 0 : pYUV420Buffer =(GByte*)VSIMalloc(3 * nBlockXSize * nBlockYSize / 2);
1633 0 : if (pYUV420Buffer == NULL)
1634 : {
1635 0 : opj_stream_destroy(pStream);
1636 0 : opj_image_destroy(psImage);
1637 0 : opj_destroy_codec(pCodec);
1638 0 : CPLFree(pTempBuffer);
1639 0 : VSIFCloseL(fp);
1640 0 : return NULL;
1641 : }
1642 : }
1643 :
1644 : /* -------------------------------------------------------------------- */
1645 : /* Setup GML and GeoTIFF information. */
1646 : /* -------------------------------------------------------------------- */
1647 4 : GDALJP2Metadata oJP2MD;
1648 :
1649 4 : int bWriteExtraBoxes = FALSE;
1650 4 : if( eCodecFormat == OPJ_CODEC_JP2 &&
1651 : (CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) ||
1652 : CSLFetchBoolean( papszOptions, "GeoJP2", TRUE )) )
1653 : {
1654 2 : const char* pszWKT = poSrcDS->GetProjectionRef();
1655 2 : if( pszWKT != NULL && pszWKT[0] != '\0' )
1656 : {
1657 2 : bWriteExtraBoxes = TRUE;
1658 2 : oJP2MD.SetProjection( pszWKT );
1659 : }
1660 : double adfGeoTransform[6];
1661 2 : if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None )
1662 : {
1663 2 : bWriteExtraBoxes = TRUE;
1664 2 : oJP2MD.SetGeoTransform( adfGeoTransform );
1665 : }
1666 : }
1667 :
1668 : #define PIXELS_PER_INCH 2
1669 : #define PIXELS_PER_CM 3
1670 :
1671 : // Resolution
1672 4 : double dfXRes = 0, dfYRes = 0;
1673 4 : int nResUnit = 0;
1674 11 : if( eCodecFormat == OPJ_CODEC_JP2
1675 3 : && poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION") != NULL
1676 2 : && poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION") != NULL
1677 2 : && poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT") != NULL )
1678 : {
1679 : dfXRes =
1680 2 : CPLAtof(poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION"));
1681 : dfYRes =
1682 2 : CPLAtof(poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION"));
1683 2 : nResUnit = atoi(poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT"));
1684 :
1685 2 : if( nResUnit == PIXELS_PER_INCH )
1686 : {
1687 : // convert pixels per inch to pixels per cm.
1688 0 : dfXRes = dfXRes * 39.37 / 100.0;
1689 0 : dfYRes = dfYRes * 39.37 / 100.0;
1690 0 : nResUnit = PIXELS_PER_CM;
1691 : }
1692 :
1693 2 : if( nResUnit == PIXELS_PER_CM &&
1694 : dfXRes > 0 && dfYRes > 0 &&
1695 : dfXRes < 65535 && dfYRes < 65535 )
1696 : {
1697 2 : bWriteExtraBoxes = TRUE;
1698 : }
1699 : }
1700 :
1701 : /* The file pointer should have been set 8 bytes after the */
1702 : /* last written bytes, because openjpeg has reserved it */
1703 : /* for the jp2c header, but still not written. */
1704 4 : vsi_l_offset nPosOriginalJP2C = 0;
1705 4 : vsi_l_offset nPosRealJP2C = 0;
1706 : GByte abyBackupWhatShouldHaveBeenTheJP2CBoxHeader[8];
1707 :
1708 4 : if( bWriteExtraBoxes )
1709 : {
1710 2 : nPosOriginalJP2C = VSIFTellL(fp) - 8;
1711 :
1712 : char szBoxName[4+1];
1713 2 : int nLBoxJP2H = 0;
1714 :
1715 : /* If we must write a Res/Resd box, */
1716 : /* read the box header at offset 32 */
1717 2 : if ( nResUnit == PIXELS_PER_CM )
1718 : {
1719 2 : VSIFSeekL(fp, 32, SEEK_SET);
1720 2 : VSIFReadL(&nLBoxJP2H, 1, 4, fp);
1721 2 : nLBoxJP2H = CPL_MSBWORD32( nLBoxJP2H );
1722 2 : VSIFReadL(szBoxName, 1, 4, fp);
1723 2 : szBoxName[4] = '\0';
1724 : }
1725 :
1726 2 : VSIFSeekL(fp, nPosOriginalJP2C, SEEK_SET);
1727 :
1728 : /* And check that it is the jp2h box before */
1729 : /* writing the res box */
1730 2 : if ( nResUnit == PIXELS_PER_CM && EQUAL(szBoxName, "jp2h") )
1731 : {
1732 : /* Format a resd box and embed it inside a res box */
1733 2 : GDALJP2Box oResd;
1734 2 : oResd.SetType("resd");
1735 : GByte aby[10];
1736 :
1737 2 : int nYDenom = 1;
1738 20 : while (nYDenom < 32767 && dfYRes < 32767)
1739 : {
1740 16 : dfYRes *= 2;
1741 16 : nYDenom *= 2;
1742 : }
1743 2 : int nXDenom = 1;
1744 18 : while (nXDenom < 32767 && dfXRes < 32767)
1745 : {
1746 14 : dfXRes *= 2;
1747 14 : nXDenom *= 2;
1748 : }
1749 :
1750 2 : aby[0] = (GByte) (((int)dfYRes) / 256);
1751 2 : aby[1] = ((int)dfYRes) % 256;
1752 2 : aby[2] = (GByte) (nYDenom / 256);
1753 2 : aby[3] = nYDenom % 256;
1754 2 : aby[4] = (GByte) (((int)dfXRes) / 256);
1755 2 : aby[5] = ((int)dfXRes) % 256;
1756 2 : aby[6] = (GByte) (nXDenom / 256);
1757 2 : aby[7] = nXDenom % 256;
1758 2 : aby[8] = 2;
1759 2 : aby[9] = 2;
1760 2 : oResd.SetWritableData(10, aby);
1761 2 : GDALJP2Box* poResd = &oResd;
1762 2 : GDALJP2Box* poRes = GDALJP2Box::CreateAsocBox( 1, &poResd );
1763 2 : poRes->SetType("res ");
1764 :
1765 : /* Now let's extend the jp2c box header so that the */
1766 : /* res box becomes a sub-box of it */
1767 2 : nLBoxJP2H += (int)poRes->GetDataLength() + 8;
1768 2 : nLBoxJP2H = CPL_MSBWORD32( nLBoxJP2H );
1769 2 : VSIFSeekL(fp, 32, SEEK_SET);
1770 2 : VSIFWriteL(&nLBoxJP2H, 1, 4, fp);
1771 :
1772 : /* Write the box at the end of the file */
1773 2 : VSIFSeekL(fp, nPosOriginalJP2C, SEEK_SET);
1774 2 : WriteBox(fp, poRes);
1775 :
1776 2 : delete poRes;
1777 : }
1778 :
1779 2 : if( CSLFetchBoolean( papszOptions, "GMLJP2", TRUE ) )
1780 : {
1781 2 : GDALJP2Box* poBox = oJP2MD.CreateGMLJP2(nXSize,nYSize);
1782 2 : WriteBox(fp, poBox);
1783 2 : delete poBox;
1784 : }
1785 2 : if( CSLFetchBoolean( papszOptions, "GeoJP2", TRUE ) )
1786 : {
1787 2 : GDALJP2Box* poBox = oJP2MD.CreateJP2GeoTIFF();
1788 2 : WriteBox(fp, poBox);
1789 2 : delete poBox;
1790 : }
1791 :
1792 2 : nPosRealJP2C = VSIFTellL(fp);
1793 :
1794 : /* Backup the res, GMLJP2 or GeoJP2 box header */
1795 : /* that will be overwritten by opj_end_compress() */
1796 2 : VSIFSeekL(fp, nPosOriginalJP2C, SEEK_SET);
1797 2 : VSIFReadL(abyBackupWhatShouldHaveBeenTheJP2CBoxHeader, 1, 8, fp);
1798 :
1799 2 : VSIFSeekL(fp, nPosRealJP2C + 8, SEEK_SET);
1800 : }
1801 :
1802 : /* -------------------------------------------------------------------- */
1803 : /* Iterate over the tiles */
1804 : /* -------------------------------------------------------------------- */
1805 4 : pfnProgress( 0.0, NULL, pProgressData );
1806 :
1807 4 : CPLErr eErr = CE_None;
1808 : int nBlockXOff, nBlockYOff;
1809 4 : int iTile = 0;
1810 8 : for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nTilesY;nBlockYOff++)
1811 : {
1812 8 : for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nTilesX;nBlockXOff++)
1813 : {
1814 4 : int nWidthToRead = MIN(nBlockXSize, nXSize - nBlockXOff * nBlockXSize);
1815 4 : int nHeightToRead = MIN(nBlockYSize, nYSize - nBlockYOff * nBlockYSize);
1816 : eErr = poSrcDS->RasterIO(GF_Read,
1817 : nBlockXOff * nBlockXSize,
1818 : nBlockYOff * nBlockYSize,
1819 : nWidthToRead, nHeightToRead,
1820 : pTempBuffer, nWidthToRead, nHeightToRead,
1821 : eDataType,
1822 : nBands, NULL,
1823 4 : 0,0,0);
1824 4 : if (eErr == CE_None)
1825 : {
1826 4 : if (bResample)
1827 : {
1828 : int j, i;
1829 0 : for(j=0;j<nHeightToRead;j++)
1830 : {
1831 0 : for(i=0;i<nWidthToRead;i++)
1832 : {
1833 0 : int R = pTempBuffer[j*nWidthToRead+i];
1834 0 : int G = pTempBuffer[nHeightToRead*nWidthToRead + j*nWidthToRead+i];
1835 0 : int B = pTempBuffer[2*nHeightToRead*nWidthToRead + j*nWidthToRead+i];
1836 0 : int Y = (int) (0.299 * R + 0.587 * G + 0.114 * B);
1837 0 : int Cb = CLAMP_0_255((int) (-0.1687 * R - 0.3313 * G + 0.5 * B + 128));
1838 0 : int Cr = CLAMP_0_255((int) (0.5 * R - 0.4187 * G - 0.0813 * B + 128));
1839 0 : pYUV420Buffer[j*nWidthToRead+i] = (GByte) Y;
1840 0 : pYUV420Buffer[nHeightToRead * nWidthToRead + ((j/2) * ((nWidthToRead)/2) + i/2) ] = (GByte) Cb;
1841 0 : pYUV420Buffer[5 * nHeightToRead * nWidthToRead / 4 + ((j/2) * ((nWidthToRead)/2) + i/2) ] = (GByte) Cr;
1842 : }
1843 : }
1844 :
1845 0 : if (!opj_write_tile(pCodec,
1846 : iTile,
1847 : pYUV420Buffer,
1848 : 3 * nWidthToRead * nHeightToRead / 2,
1849 : pStream))
1850 : {
1851 : CPLError(CE_Failure, CPLE_AppDefined,
1852 0 : "opj_write_tile() failed");
1853 0 : eErr = CE_Failure;
1854 : }
1855 : }
1856 : else
1857 : {
1858 4 : if (!opj_write_tile(pCodec,
1859 : iTile,
1860 : pTempBuffer,
1861 : nWidthToRead * nHeightToRead * nBands * nDataTypeSize,
1862 : pStream))
1863 : {
1864 : CPLError(CE_Failure, CPLE_AppDefined,
1865 0 : "opj_write_tile() failed");
1866 0 : eErr = CE_Failure;
1867 : }
1868 : }
1869 : }
1870 :
1871 4 : if( !pfnProgress( (iTile + 1) * 1.0 / (nTilesX * nTilesY), NULL, pProgressData ) )
1872 0 : eErr = CE_Failure;
1873 :
1874 4 : iTile ++;
1875 : }
1876 : }
1877 :
1878 4 : VSIFree(pTempBuffer);
1879 4 : VSIFree(pYUV420Buffer);
1880 :
1881 4 : if (eErr != CE_None)
1882 : {
1883 0 : opj_stream_destroy(pStream);
1884 0 : opj_image_destroy(psImage);
1885 0 : opj_destroy_codec(pCodec);
1886 0 : VSIFCloseL(fp);
1887 0 : return NULL;
1888 : }
1889 :
1890 4 : if (!opj_end_compress(pCodec,pStream))
1891 : {
1892 : CPLError(CE_Failure, CPLE_AppDefined,
1893 0 : "opj_end_compress() failed");
1894 0 : opj_stream_destroy(pStream);
1895 0 : opj_image_destroy(psImage);
1896 0 : opj_destroy_codec(pCodec);
1897 0 : VSIFCloseL(fp);
1898 0 : return NULL;
1899 : }
1900 :
1901 4 : opj_stream_destroy(pStream);
1902 4 : opj_image_destroy(psImage);
1903 4 : opj_destroy_codec(pCodec);
1904 :
1905 : /* Move the jp2c box header at its real position */
1906 : /* and restore the res, GMLJP2 or GeoJP2 box header that */
1907 : /* has been overwritten */
1908 4 : if( bWriteExtraBoxes )
1909 : {
1910 : GByte abyJP2CHeader[8];
1911 :
1912 2 : VSIFSeekL(fp, nPosOriginalJP2C, SEEK_SET);
1913 2 : VSIFReadL(abyJP2CHeader, 1, 8, fp);
1914 :
1915 2 : VSIFSeekL(fp, nPosOriginalJP2C, SEEK_SET);
1916 2 : VSIFWriteL(abyBackupWhatShouldHaveBeenTheJP2CBoxHeader, 1, 8, fp);
1917 :
1918 2 : VSIFSeekL(fp, nPosRealJP2C, SEEK_SET);
1919 2 : VSIFWriteL(abyJP2CHeader, 1, 8, fp);
1920 : }
1921 :
1922 4 : VSIFCloseL(fp);
1923 : /* -------------------------------------------------------------------- */
1924 : /* Re-open dataset, and copy any auxilary pam information. */
1925 : /* -------------------------------------------------------------------- */
1926 :
1927 4 : GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
1928 4 : JP2OpenJPEGDataset *poDS = (JP2OpenJPEGDataset*) JP2OpenJPEGDataset::Open(&oOpenInfo);
1929 :
1930 4 : if( poDS )
1931 4 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
1932 :
1933 4 : return poDS;
1934 : }
1935 :
1936 : /************************************************************************/
1937 : /* GDALRegister_JP2OpenJPEG() */
1938 : /************************************************************************/
1939 :
1940 582 : void GDALRegister_JP2OpenJPEG()
1941 :
1942 : {
1943 : GDALDriver *poDriver;
1944 :
1945 582 : if (! GDAL_CHECK_VERSION("JP2OpenJPEG driver"))
1946 0 : return;
1947 :
1948 582 : if( GDALGetDriverByName( "JP2OpenJPEG" ) == NULL )
1949 : {
1950 561 : poDriver = new GDALDriver();
1951 :
1952 561 : poDriver->SetDescription( "JP2OpenJPEG" );
1953 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1954 561 : "JPEG-2000 driver based on OpenJPEG library" );
1955 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1956 561 : "frmt_jp2openjpeg.html" );
1957 561 : poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
1958 561 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
1959 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
1960 561 : "Byte Int16 UInt16 Int32 UInt32" );
1961 :
1962 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
1963 : "<CreationOptionList>"
1964 : " <Option name='CODEC' type='string-select' default='according to file extension. If unknown, default to J2K'>"
1965 : " <Value>JP2</Value>"
1966 : " <Value>J2K</Value>"
1967 : " </Option>"
1968 : " <Option name='GeoJP2' type='boolean' description='defaults to ON'/>"
1969 : " <Option name='GMLJP2' type='boolean' description='defaults to ON'/>"
1970 : " <Option name='QUALITY' type='float' description='Quality. 0-100' default='25'/>"
1971 : " <Option name='REVERSIBLE' type='boolean' description='True if the compression is reversible' default='false'/>"
1972 : " <Option name='RESOLUTIONS' type='int' description='Number of resolutions. 1-7' default='6'/>"
1973 : " <Option name='BLOCKXSIZE' type='int' description='Tile Width' default='1024'/>"
1974 : " <Option name='BLOCKYSIZE' type='int' description='Tile Height' default='1024'/>"
1975 : " <Option name='PROGRESSION' type='string-select' default='LRCP'>"
1976 : " <Value>LRCP</Value>"
1977 : " <Value>RLCP</Value>"
1978 : " <Value>RPCL</Value>"
1979 : " <Value>PCRL</Value>"
1980 : " <Value>CPRL</Value>"
1981 : " </Option>"
1982 : " <Option name='SOP' type='boolean' description='True to insert SOP markers' default='false'/>"
1983 : " <Option name='EPH' type='boolean' description='True to insert EPH markers' default='false'/>"
1984 : " <Option name='YCBCR420' type='boolean' description='if RGB must be resampled to YCbCr 4:2:0' default='false'/>"
1985 561 : "</CreationOptionList>" );
1986 :
1987 561 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1988 :
1989 561 : poDriver->pfnIdentify = JP2OpenJPEGDataset::Identify;
1990 561 : poDriver->pfnOpen = JP2OpenJPEGDataset::Open;
1991 561 : poDriver->pfnCreateCopy = JP2OpenJPEGDataset::CreateCopy;
1992 :
1993 561 : GetGDALDriverManager()->RegisterDriver( poDriver );
1994 : }
1995 : }
1996 :
|