1 : /******************************************************************************
2 : * $Id: openjpegdataset.cpp 19740 2010-05-18 19:38:17Z 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 : /* Necessary for opj_setup_decoder() */
31 : #define USE_OPJ_DEPRECATED
32 : #include <openjpeg.h>
33 :
34 : #include "gdal_pam.h"
35 : #include "cpl_string.h"
36 : #include "gdaljp2metadata.h"
37 :
38 : CPL_CVSID("$Id: openjpegdataset.cpp 19740 2010-05-18 19:38:17Z rouault $");
39 :
40 : /************************************************************************/
41 : /* JP2OpenJPEGDataset_ErrorCallback() */
42 : /************************************************************************/
43 :
44 6 : static void JP2OpenJPEGDataset_ErrorCallback(const char *pszMsg, void *unused)
45 : {
46 6 : CPLError(CE_Failure, CPLE_AppDefined, "%s", pszMsg);
47 6 : }
48 :
49 : /************************************************************************/
50 : /* JP2OpenJPEGDataset_WarningCallback() */
51 : /************************************************************************/
52 :
53 0 : static void JP2OpenJPEGDataset_WarningCallback(const char *pszMsg, void *unused)
54 : {
55 0 : CPLError(CE_Warning, CPLE_AppDefined, "%s", pszMsg);
56 0 : }
57 :
58 : /************************************************************************/
59 : /* JP2OpenJPEGDataset_InfoCallback() */
60 : /************************************************************************/
61 :
62 23 : static void JP2OpenJPEGDataset_InfoCallback(const char *pszMsg, void *unused)
63 : {
64 23 : CPLDebug("OPENJPEG", "info: %s", pszMsg);
65 23 : }
66 :
67 : /************************************************************************/
68 : /* JP2OpenJPEGDataset_Read() */
69 : /************************************************************************/
70 :
71 : static OPJ_UINT32 JP2OpenJPEGDataset_Read(void* pBuffer, OPJ_UINT32 nBytes,
72 1452 : void *pUserData)
73 : {
74 1452 : int nRet = VSIFReadL(pBuffer, 1, nBytes, (FILE*)pUserData);
75 : #ifdef DEBUG
76 1452 : CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Read(%d) = %d", nBytes, nRet);
77 : #endif
78 1452 : if (nRet == 0)
79 21 : nRet = -1;
80 1452 : return nRet;
81 : }
82 :
83 : /************************************************************************/
84 : /* JP2OpenJPEGDataset_Write() */
85 : /************************************************************************/
86 :
87 : static OPJ_UINT32 JP2OpenJPEGDataset_Write(void* pBuffer, OPJ_UINT32 nBytes,
88 2 : void *pUserData)
89 : {
90 2 : int nRet = VSIFWriteL(pBuffer, 1, nBytes, (FILE*)pUserData);
91 : #ifdef DEBUG
92 2 : CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Write(%d) = %d", nBytes, nRet);
93 : #endif
94 2 : return nRet;
95 : }
96 :
97 : /************************************************************************/
98 : /* JP2OpenJPEGDataset_Seek() */
99 : /************************************************************************/
100 :
101 0 : static bool JP2OpenJPEGDataset_Seek(OPJ_SIZE_T nBytes, void * pUserData)
102 : {
103 : #ifdef DEBUG
104 0 : CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Seek(%d)", nBytes);
105 : #endif
106 0 : return VSIFSeekL((FILE*)pUserData, nBytes, SEEK_SET) == 0;
107 : }
108 :
109 : /************************************************************************/
110 : /* JP2OpenJPEGDataset_Skip() */
111 : /************************************************************************/
112 :
113 1215 : static OPJ_SIZE_T JP2OpenJPEGDataset_Skip(OPJ_SIZE_T nBytes, void * pUserData)
114 : {
115 1215 : int nOffset = VSIFTellL((FILE*)pUserData) + nBytes;
116 : #ifdef DEBUG
117 1215 : CPLDebug("OPENJPEG", "JP2OpenJPEGDataset_Skip(%d -> %d)", nBytes, nOffset);
118 : #endif
119 1215 : if (nOffset < 0)
120 0 : return -1;
121 1215 : VSIFSeekL((FILE*)pUserData, nOffset, SEEK_SET);
122 1215 : return nBytes;
123 : }
124 :
125 : /************************************************************************/
126 : /* ==================================================================== */
127 : /* JP2OpenJPEGDataset */
128 : /* ==================================================================== */
129 : /************************************************************************/
130 :
131 : class JP2OpenJPEGDataset : public GDALPamDataset
132 : {
133 : friend class JP2OpenJPEGRasterBand;
134 :
135 : FILE *fp; /* Large FILE API */
136 :
137 : char *pszProjection;
138 : int bGeoTransformValid;
139 : double adfGeoTransform[6];
140 : int nGCPCount;
141 : GDAL_GCP *pasGCPList;
142 :
143 : OPJ_CODEC_FORMAT eCodecFormat;
144 : OPJ_COLOR_SPACE eColorSpace;
145 :
146 : int bLoadingOtherBands;
147 : int bIs420;
148 :
149 : public:
150 : JP2OpenJPEGDataset();
151 : ~JP2OpenJPEGDataset();
152 :
153 : static int Identify( GDALOpenInfo * poOpenInfo );
154 : static GDALDataset *Open( GDALOpenInfo * );
155 : static GDALDataset *CreateCopy( const char * pszFilename,
156 : GDALDataset *poSrcDS,
157 : int bStrict, char ** papszOptions,
158 : GDALProgressFunc pfnProgress,
159 : void * pProgressData );
160 : CPLErr GetGeoTransform( double* );
161 : virtual const char *GetProjectionRef(void);
162 : virtual int GetGCPCount();
163 : virtual const char *GetGCPProjection();
164 : virtual const GDAL_GCP *GetGCPs();
165 : };
166 :
167 : /************************************************************************/
168 : /* ==================================================================== */
169 : /* JP2OpenJPEGRasterBand */
170 : /* ==================================================================== */
171 : /************************************************************************/
172 :
173 : class JP2OpenJPEGRasterBand : public GDALPamRasterBand
174 : {
175 : friend class JP2OpenJPEGDataset;
176 :
177 : public:
178 :
179 : JP2OpenJPEGRasterBand( JP2OpenJPEGDataset * poDS, int nBand,
180 : GDALDataType eDataType,
181 : int nBlockXSize, int nBlockYSize);
182 : ~JP2OpenJPEGRasterBand();
183 :
184 : virtual CPLErr IReadBlock( int, int, void * );
185 : virtual GDALColorInterp GetColorInterpretation();
186 : };
187 :
188 :
189 : /************************************************************************/
190 : /* JP2OpenJPEGRasterBand() */
191 : /************************************************************************/
192 :
193 : JP2OpenJPEGRasterBand::JP2OpenJPEGRasterBand( JP2OpenJPEGDataset *poDS, int nBand,
194 : GDALDataType eDataType,
195 38 : int nBlockXSize, int nBlockYSize)
196 :
197 : {
198 38 : this->poDS = poDS;
199 38 : this->nBand = nBand;
200 38 : this->eDataType = eDataType;
201 38 : this->nBlockXSize = nBlockXSize;
202 38 : this->nBlockYSize = nBlockYSize;
203 38 : }
204 :
205 : /************************************************************************/
206 : /* ~JP2OpenJPEGRasterBand() */
207 : /************************************************************************/
208 :
209 38 : JP2OpenJPEGRasterBand::~JP2OpenJPEGRasterBand()
210 : {
211 38 : }
212 :
213 : /************************************************************************/
214 : /* CopySrcToDst() */
215 : /************************************************************************/
216 :
217 921600 : static CPL_INLINE GByte CLAMP_0_255(int val)
218 : {
219 921600 : if (val < 0)
220 2052 : return 0;
221 919548 : else if (val > 255)
222 2016 : return 255;
223 : else
224 917532 : return val;
225 : }
226 :
227 : static void CopySrcToDst(int nWidthToRead, int nHeightToRead,
228 : GByte* pTempBuffer,
229 : int nBlockXSize, int nBlockYSize, int nDataTypeSize,
230 179 : void* pImage, int nBand, int bIs420)
231 : {
232 : int i, j;
233 179 : if (bIs420)
234 : {
235 3 : GByte* pSrc = (GByte*)pTempBuffer;
236 3 : GByte* pDst = (GByte*)pImage;
237 1923 : for(j=0;j<nHeightToRead;j++)
238 : {
239 923520 : for(i=0;i<nWidthToRead;i++)
240 : {
241 921600 : int Y = pSrc[j * nWidthToRead + i];
242 921600 : int Cb = pSrc[nHeightToRead * nWidthToRead + ((j/2) * (nWidthToRead/2) + i/2) ];
243 921600 : int Cr = pSrc[5 * nHeightToRead * nWidthToRead / 4 + ((j/2) * (nWidthToRead/2) + i/2) ];
244 921600 : if (nBand == 1)
245 307200 : pDst[j * nBlockXSize + i] = CLAMP_0_255(Y + 1.402 * (Cr - 128));
246 614400 : else if (nBand == 2)
247 307200 : pDst[j * nBlockXSize + i] = CLAMP_0_255(Y - 0.34414 * (Cb - 128) - 0.71414 * (Cr - 128));
248 : else
249 307200 : pDst[j * nBlockXSize + i] = CLAMP_0_255(Y + 1.772 * (Cb - 128));
250 : }
251 : }
252 : }
253 : else
254 : {
255 66992 : for(j=0;j<nHeightToRead;j++)
256 : {
257 : memcpy(((GByte*)pImage) + j*nBlockXSize * nDataTypeSize,
258 : pTempBuffer + (j*nWidthToRead + (nBand-1) * nHeightToRead * nWidthToRead) * nDataTypeSize,
259 66816 : nWidthToRead * nDataTypeSize);
260 : }
261 : }
262 179 : }
263 :
264 : /************************************************************************/
265 : /* IReadBlock() */
266 : /************************************************************************/
267 :
268 : CPLErr JP2OpenJPEGRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
269 69 : void * pImage )
270 : {
271 69 : JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
272 69 : opj_codec_t* pCodec = NULL;
273 69 : int nDataTypeSize = (GDALGetDataTypeSize(eDataType) / 8);
274 :
275 : CPLDebug("OPENJPEG", "xoff=%d yoff=%d band=%d",
276 69 : nBlockXOff, nBlockYOff, nBand);
277 :
278 69 : int nWidthToRead = MIN(nBlockXSize, poGDS->nRasterXSize - nBlockXOff * nBlockXSize);
279 69 : int nHeightToRead = MIN(nBlockYSize, poGDS->nRasterYSize - nBlockYOff * nBlockYSize);
280 69 : if (nWidthToRead != nBlockXSize || nHeightToRead != nBlockYSize)
281 : {
282 18 : memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
283 : }
284 :
285 : /* FIXME ? Well, this is pretty inefficient as for each block we recreate */
286 : /* a new decoding session. But currently there's no way to call opj_set_decode_area() */
287 : /* twice on the same codec instance... */
288 :
289 69 : pCodec = opj_create_decompress(poGDS->eCodecFormat);
290 :
291 69 : opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
292 69 : opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback,NULL);
293 69 : opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
294 :
295 : opj_dparameters_t parameters;
296 69 : opj_set_default_decoder_parameters(¶meters);
297 :
298 69 : if (! opj_setup_decoder(pCodec,¶meters))
299 : {
300 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_setup_decoder() failed");
301 0 : opj_destroy_codec(pCodec);
302 0 : return CE_Failure;
303 : }
304 :
305 : /* Reseek to file beginning */
306 69 : VSIFSeekL(poGDS->fp, 0, SEEK_SET);
307 :
308 : opj_stream_t * pStream;
309 69 : pStream = opj_stream_create(1024, TRUE); // Default 1MB is way too big for some datasets
310 69 : opj_stream_set_read_function(pStream, JP2OpenJPEGDataset_Read);
311 69 : opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
312 69 : opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
313 69 : opj_stream_set_user_data(pStream, poGDS->fp);
314 :
315 69 : opj_image_t * psImage = NULL;
316 : OPJ_INT32 nX0,nY0;
317 : OPJ_UINT32 nTileW,nTileH,nTilesX,nTilesY;
318 69 : if(!opj_read_header(pCodec, &psImage, &nX0, &nY0, &nTileW, &nTileH,
319 : &nTilesX, &nTilesY, pStream))
320 : {
321 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
322 0 : opj_destroy_codec(pCodec);
323 0 : opj_stream_destroy(pStream);
324 0 : return CE_Failure;
325 : }
326 :
327 69 : if (!opj_set_decode_area(pCodec,
328 : nBlockXOff * nBlockXSize,
329 : nBlockYOff * nBlockYSize,
330 : nBlockXOff * nBlockXSize + nWidthToRead,
331 : nBlockYOff * nBlockYSize + nHeightToRead))
332 : {
333 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_set_decode_area() failed");
334 0 : opj_destroy_codec(pCodec);
335 0 : opj_stream_destroy(pStream);
336 0 : opj_image_destroy(psImage);
337 0 : return CE_Failure;
338 : }
339 :
340 : bool bDataToUncompress;
341 : OPJ_UINT32 nTileIndex,nCompCount;
342 : OPJ_INT32 nTileX0,nTileY0,nTileX1,nTileY1;
343 : OPJ_UINT32 nRequiredSize;
344 :
345 : int nAllocatedSize;
346 69 : if (poGDS->bIs420)
347 1 : nAllocatedSize = 3 * nWidthToRead * nHeightToRead * nDataTypeSize / 2;
348 : else
349 68 : nAllocatedSize = poGDS->nBands * nWidthToRead * nHeightToRead * nDataTypeSize;
350 69 : OPJ_BYTE *pTempBuffer = (OPJ_BYTE *)VSIMalloc(nAllocatedSize);
351 69 : if (pTempBuffer == NULL)
352 : {
353 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot allocate temp buffer");
354 0 : opj_destroy_codec(pCodec);
355 0 : opj_stream_destroy(pStream);
356 0 : opj_image_destroy(psImage);
357 0 : return CE_Failure;
358 : }
359 :
360 138 : do
361 : {
362 138 : if (!opj_read_tile_header(pCodec, &nTileIndex, &nRequiredSize,
363 : &nTileX0, &nTileY0, &nTileX1, &nTileY1,
364 : &nCompCount, &bDataToUncompress, pStream))
365 : {
366 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_read_tile_header() failed");
367 0 : CPLFree(pTempBuffer);
368 0 : opj_destroy_codec(pCodec);
369 0 : opj_stream_destroy(pStream);
370 0 : opj_image_destroy(psImage);
371 0 : return CE_Failure;
372 : }
373 :
374 : /* A few sanity checks */
375 138 : if (nTileX0 != nBlockXOff * nBlockXSize ||
376 : nTileY0 != nBlockYOff * nBlockYSize ||
377 : nTileX1 != nBlockXOff * nBlockXSize + nWidthToRead ||
378 : nTileY1 != nBlockYOff * nBlockYSize + nHeightToRead ||
379 : (int)nRequiredSize != nAllocatedSize ||
380 : (int)nCompCount != poGDS->nBands)
381 : {
382 : CPLDebug("OPENJPEG",
383 : "bDataToUncompress=%d nTileIndex=%d nRequiredSize=%d nCompCount=%d",
384 0 : bDataToUncompress, nTileIndex, nRequiredSize, nCompCount);
385 : CPLDebug("OPENJPEG",
386 : "nTileX0=%d nTileY0=%d nTileX1=%d nTileY1=%d",
387 0 : nTileX0, nTileY0, nTileX1, nTileY1);
388 : CPLError(CE_Failure, CPLE_AppDefined,
389 0 : "opj_read_tile_header() returned unexpected parameters");
390 0 : CPLFree(pTempBuffer);
391 0 : opj_destroy_codec(pCodec);
392 0 : opj_stream_destroy(pStream);
393 0 : opj_image_destroy(psImage);
394 0 : return CE_Failure;
395 : }
396 :
397 138 : if (bDataToUncompress)
398 : {
399 69 : if (!opj_decode_tile_data(pCodec,nTileIndex,pTempBuffer,
400 : nRequiredSize,pStream))
401 : {
402 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_decode_tile_data() failed");
403 0 : CPLFree(pTempBuffer);
404 0 : opj_destroy_codec(pCodec);
405 0 : opj_stream_destroy(pStream);
406 0 : opj_image_destroy(psImage);
407 0 : return CE_Failure;
408 : }
409 : }
410 : } while(bDataToUncompress);
411 :
412 : CopySrcToDst(nWidthToRead, nHeightToRead, pTempBuffer,
413 : nBlockXSize, nBlockYSize, nDataTypeSize, pImage,
414 69 : nBand, poGDS->bIs420);
415 :
416 : /* Let's cache other bands */
417 69 : if( poGDS->nBands != 1 && !poGDS->bLoadingOtherBands)
418 : {
419 : int iOtherBand;
420 :
421 55 : poGDS->bLoadingOtherBands = TRUE;
422 :
423 220 : for( iOtherBand = 1; iOtherBand <= poGDS->nBands; iOtherBand++ )
424 : {
425 165 : if( iOtherBand == nBand )
426 55 : continue;
427 :
428 : GDALRasterBlock *poBlock;
429 :
430 : poBlock = poGDS->GetRasterBand(iOtherBand)->
431 110 : GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
432 110 : if (poBlock == NULL)
433 : {
434 0 : break;
435 : }
436 :
437 110 : void* pData = poBlock->GetDataRef();
438 110 : if (pData)
439 : {
440 : CopySrcToDst(nWidthToRead, nHeightToRead, pTempBuffer,
441 : nBlockXSize, nBlockYSize, nDataTypeSize, pData,
442 110 : iOtherBand, poGDS->bIs420);
443 : }
444 :
445 110 : poBlock->DropLock();
446 : }
447 :
448 55 : poGDS->bLoadingOtherBands = FALSE;
449 : }
450 :
451 69 : CPLFree(pTempBuffer);
452 :
453 69 : opj_end_decompress(pCodec,pStream);
454 69 : opj_stream_destroy(pStream);
455 69 : opj_destroy_codec(pCodec);
456 69 : opj_image_destroy(psImage);
457 :
458 69 : return CE_None;
459 : }
460 :
461 : /************************************************************************/
462 : /* GetColorInterpretation() */
463 : /************************************************************************/
464 :
465 3 : GDALColorInterp JP2OpenJPEGRasterBand::GetColorInterpretation()
466 : {
467 3 : JP2OpenJPEGDataset *poGDS = (JP2OpenJPEGDataset *) poDS;
468 :
469 3 : if (poGDS->eColorSpace == CLRSPC_GRAY)
470 0 : return GCI_GrayIndex;
471 3 : else if (poGDS->nBands == 3 || poGDS->nBands == 4)
472 : {
473 0 : switch(nBand)
474 : {
475 : case 1:
476 0 : return GCI_RedBand;
477 : case 2:
478 0 : return GCI_GreenBand;
479 : case 3:
480 0 : return GCI_BlueBand;
481 : case 4:
482 0 : return GCI_AlphaBand;
483 : default:
484 0 : return GCI_Undefined;
485 : }
486 : }
487 :
488 3 : return GCI_Undefined;
489 : }
490 :
491 : /************************************************************************/
492 : /* ==================================================================== */
493 : /* JP2OpenJPEGDataset */
494 : /* ==================================================================== */
495 : /************************************************************************/
496 :
497 : /************************************************************************/
498 : /* JP2OpenJPEGDataset() */
499 : /************************************************************************/
500 :
501 24 : JP2OpenJPEGDataset::JP2OpenJPEGDataset()
502 : {
503 24 : fp = NULL;
504 24 : nBands = 0;
505 24 : pszProjection = CPLStrdup("");
506 24 : nGCPCount = 0;
507 24 : pasGCPList = NULL;
508 24 : bGeoTransformValid = FALSE;
509 24 : adfGeoTransform[0] = 0.0;
510 24 : adfGeoTransform[1] = 1.0;
511 24 : adfGeoTransform[2] = 0.0;
512 24 : adfGeoTransform[3] = 0.0;
513 24 : adfGeoTransform[4] = 0.0;
514 24 : adfGeoTransform[5] = 1.0;
515 24 : bLoadingOtherBands = FALSE;
516 24 : eCodecFormat = CODEC_UNKNOWN;
517 24 : eColorSpace = CLRSPC_UNKNOWN;
518 24 : bIs420 = FALSE;
519 24 : }
520 :
521 : /************************************************************************/
522 : /* ~JP2OpenJPEGDataset() */
523 : /************************************************************************/
524 :
525 24 : JP2OpenJPEGDataset::~JP2OpenJPEGDataset()
526 :
527 : {
528 24 : FlushCache();
529 :
530 24 : if ( pszProjection )
531 24 : CPLFree( pszProjection );
532 24 : if( nGCPCount > 0 )
533 : {
534 2 : GDALDeinitGCPs( nGCPCount, pasGCPList );
535 2 : CPLFree( pasGCPList );
536 : }
537 24 : if( fp != NULL )
538 24 : VSIFCloseL( fp );
539 24 : }
540 :
541 : /************************************************************************/
542 : /* GetProjectionRef() */
543 : /************************************************************************/
544 :
545 9 : const char *JP2OpenJPEGDataset::GetProjectionRef()
546 :
547 : {
548 9 : return( pszProjection );
549 : }
550 :
551 : /************************************************************************/
552 : /* GetGeoTransform() */
553 : /************************************************************************/
554 :
555 7 : CPLErr JP2OpenJPEGDataset::GetGeoTransform( double * padfTransform )
556 : {
557 7 : if( bGeoTransformValid )
558 : {
559 5 : memcpy( padfTransform, adfGeoTransform, sizeof(adfGeoTransform[0]) * 6 );
560 5 : return CE_None;
561 : }
562 : else
563 2 : return CE_Failure;
564 : }
565 :
566 : /************************************************************************/
567 : /* GetGCPCount() */
568 : /************************************************************************/
569 :
570 3 : int JP2OpenJPEGDataset::GetGCPCount()
571 :
572 : {
573 3 : return nGCPCount;
574 : }
575 :
576 : /************************************************************************/
577 : /* GetGCPProjection() */
578 : /************************************************************************/
579 :
580 1 : const char *JP2OpenJPEGDataset::GetGCPProjection()
581 :
582 : {
583 1 : if( nGCPCount > 0 )
584 1 : return pszProjection;
585 : else
586 0 : return "";
587 : }
588 :
589 : /************************************************************************/
590 : /* GetGCP() */
591 : /************************************************************************/
592 :
593 1 : const GDAL_GCP *JP2OpenJPEGDataset::GetGCPs()
594 :
595 : {
596 1 : return pasGCPList;
597 : }
598 :
599 : /************************************************************************/
600 : /* Identify() */
601 : /************************************************************************/
602 :
603 9812 : int JP2OpenJPEGDataset::Identify( GDALOpenInfo * poOpenInfo )
604 :
605 : {
606 : static const unsigned char jpc_header[] = {0xff,0x4f};
607 : static const unsigned char jp2_box_jp[] = {0x6a,0x50,0x20,0x20}; /* 'jP ' */
608 :
609 9812 : if( poOpenInfo->nHeaderBytes >= 16
610 : && (memcmp( poOpenInfo->pabyHeader, jpc_header,
611 : sizeof(jpc_header) ) == 0
612 : || memcmp( poOpenInfo->pabyHeader + 4, jp2_box_jp,
613 : sizeof(jp2_box_jp) ) == 0
614 : ) )
615 25 : return TRUE;
616 :
617 : else
618 9787 : return FALSE;
619 : }
620 : /************************************************************************/
621 : /* Open() */
622 : /************************************************************************/
623 :
624 1579 : GDALDataset *JP2OpenJPEGDataset::Open( GDALOpenInfo * poOpenInfo )
625 :
626 : {
627 1579 : if (!Identify(poOpenInfo))
628 1555 : return NULL;
629 :
630 24 : FILE* fp = VSIFOpenL(poOpenInfo->pszFilename, "rb");
631 24 : if (!fp)
632 0 : return NULL;
633 :
634 : OPJ_CODEC_FORMAT eCodecFormat;
635 :
636 : /* Detect which codec to use : J2K or JP2 ? */
637 : static const unsigned char jpc_header[] = {0xff,0x4f};
638 24 : if (memcmp( poOpenInfo->pabyHeader, jpc_header,
639 : sizeof(jpc_header) ) == 0)
640 13 : eCodecFormat = CODEC_J2K;
641 : else
642 11 : eCodecFormat = CODEC_JP2;
643 :
644 24 : opj_codec_t* pCodec = opj_create_decompress(eCodecFormat);
645 :
646 24 : opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
647 24 : opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback,NULL);
648 24 : opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
649 :
650 : opj_dparameters_t parameters;
651 24 : opj_set_default_decoder_parameters(¶meters);
652 :
653 24 : if (! opj_setup_decoder(pCodec,¶meters))
654 : {
655 0 : VSIFCloseL(fp);
656 0 : return NULL;
657 : }
658 :
659 : opj_stream_t * pStream;
660 24 : pStream = opj_stream_create(1024, TRUE); // Default 1MB is way too big for some datasets
661 24 : opj_stream_set_read_function(pStream, JP2OpenJPEGDataset_Read);
662 24 : opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
663 24 : opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
664 24 : opj_stream_set_user_data(pStream, fp);
665 :
666 24 : opj_image_t * psImage = NULL;
667 : OPJ_INT32 nX0,nY0;
668 : OPJ_UINT32 nTileW,nTileH,nTilesX,nTilesY;
669 24 : if(!opj_read_header(pCodec, &psImage, &nX0, &nY0, &nTileW, &nTileH,
670 : &nTilesX, &nTilesY, pStream))
671 : {
672 0 : CPLError(CE_Failure, CPLE_AppDefined, "opj_read_header() failed");
673 0 : opj_destroy_codec(pCodec);
674 0 : opj_stream_destroy(pStream);
675 0 : opj_image_destroy(psImage);
676 0 : VSIFCloseL(fp);
677 0 : return NULL;
678 : }
679 :
680 24 : if (psImage == NULL)
681 : {
682 0 : opj_destroy_codec(pCodec);
683 0 : opj_stream_destroy(pStream);
684 0 : opj_image_destroy(psImage);
685 0 : VSIFCloseL(fp);
686 0 : return NULL;
687 : }
688 :
689 : #ifdef DEBUG
690 : int i;
691 24 : CPLDebug("OPENJPEG", "nX0 = %d", nX0);
692 24 : CPLDebug("OPENJPEG", "nY0 = %d", nY0);
693 24 : CPLDebug("OPENJPEG", "nTileW = %d", nTileW);
694 24 : CPLDebug("OPENJPEG", "nTileH = %d", nTileH);
695 24 : CPLDebug("OPENJPEG", "psImage->x0 = %d", psImage->x0);
696 24 : CPLDebug("OPENJPEG", "psImage->y0 = %d", psImage->y0);
697 24 : CPLDebug("OPENJPEG", "psImage->x1 = %d", psImage->x1);
698 24 : CPLDebug("OPENJPEG", "psImage->y1 = %d", psImage->y1);
699 24 : CPLDebug("OPENJPEG", "psImage->numcomps = %d", psImage->numcomps);
700 24 : CPLDebug("OPENJPEG", "psImage->color_space = %d", psImage->color_space);
701 62 : for(i=0;i<(int)psImage->numcomps;i++)
702 : {
703 38 : CPLDebug("OPENJPEG", "psImage->comps[%d].dx = %d", i, psImage->comps[i].dx);
704 38 : CPLDebug("OPENJPEG", "psImage->comps[%d].dy = %d", i, psImage->comps[i].dy);
705 38 : CPLDebug("OPENJPEG", "psImage->comps[%d].x0 = %d", i, psImage->comps[i].x0);
706 38 : CPLDebug("OPENJPEG", "psImage->comps[%d].y0 = %d", i, psImage->comps[i].y0);
707 38 : CPLDebug("OPENJPEG", "psImage->comps[%d].w = %d", i, psImage->comps[i].w);
708 38 : CPLDebug("OPENJPEG", "psImage->comps[%d].h = %d", i, psImage->comps[i].h);
709 38 : CPLDebug("OPENJPEG", "psImage->comps[%d].factor = %d", i, psImage->comps[i].factor);
710 38 : CPLDebug("OPENJPEG", "psImage->comps[%d].prec = %d", i, psImage->comps[i].prec);
711 38 : CPLDebug("OPENJPEG", "psImage->comps[%d].sgnd = %d", i, psImage->comps[i].sgnd);
712 : }
713 : #endif
714 :
715 24 : if (psImage->x1 - psImage->x0 <= 0 ||
716 : psImage->y1 - psImage->y0 <= 0 ||
717 : psImage->numcomps == 0 ||
718 : (int)psImage->comps[0].w != psImage->x1 - psImage->x0 ||
719 : (int)psImage->comps[0].h != psImage->y1 - psImage->y0)
720 : {
721 0 : opj_destroy_codec(pCodec);
722 0 : opj_stream_destroy(pStream);
723 0 : opj_image_destroy(psImage);
724 0 : VSIFCloseL(fp);
725 0 : return NULL;
726 : }
727 :
728 24 : GDALDataType eDataType = GDT_Byte;
729 24 : if (psImage->comps[0].prec > 16)
730 : {
731 0 : if (psImage->comps[0].sgnd)
732 0 : eDataType = GDT_Int32;
733 : else
734 0 : eDataType = GDT_UInt32;
735 : }
736 24 : else if (psImage->comps[0].prec > 8)
737 : {
738 7 : if (psImage->comps[0].sgnd)
739 5 : eDataType = GDT_Int16;
740 : else
741 2 : eDataType = GDT_UInt16;
742 : }
743 :
744 : int bIs420 = (psImage->color_space != CLRSPC_SRGB &&
745 : eDataType == GDT_Byte &&
746 : psImage->numcomps == 3 &&
747 : psImage->comps[1].w == psImage->comps[0].w / 2 &&
748 : psImage->comps[1].h == psImage->comps[0].h / 2 &&
749 : psImage->comps[2].w == psImage->comps[0].w / 2 &&
750 24 : psImage->comps[2].h == psImage->comps[0].h / 2);
751 :
752 24 : if (bIs420)
753 : {
754 1 : CPLDebug("OPENJPEG", "420 format");
755 : }
756 : else
757 : {
758 : int iBand;
759 35 : for(iBand = 2; iBand <= (int)psImage->numcomps; iBand ++)
760 : {
761 12 : if (psImage->comps[iBand-1].w != psImage->comps[0].w ||
762 : psImage->comps[iBand-1].h != psImage->comps[0].h ||
763 : psImage->comps[iBand-1].prec != psImage->comps[0].prec)
764 : {
765 0 : opj_destroy_codec(pCodec);
766 0 : opj_stream_destroy(pStream);
767 0 : opj_image_destroy(psImage);
768 0 : VSIFCloseL(fp);
769 0 : return NULL;
770 : }
771 : }
772 : }
773 :
774 :
775 : /* -------------------------------------------------------------------- */
776 : /* Create a corresponding GDALDataset. */
777 : /* -------------------------------------------------------------------- */
778 : JP2OpenJPEGDataset *poDS;
779 : int iBand;
780 :
781 24 : poDS = new JP2OpenJPEGDataset();
782 24 : poDS->eCodecFormat = eCodecFormat;
783 24 : poDS->eColorSpace = psImage->color_space;
784 24 : poDS->nRasterXSize = psImage->x1 - psImage->x0;
785 24 : poDS->nRasterYSize = psImage->y1 - psImage->y0;
786 24 : poDS->nBands = psImage->numcomps;
787 24 : poDS->fp = fp;
788 24 : poDS->bIs420 = bIs420;
789 :
790 24 : opj_end_decompress(pCodec,pStream);
791 24 : opj_stream_destroy(pStream);
792 24 : opj_destroy_codec(pCodec);
793 24 : opj_image_destroy(psImage);
794 :
795 : /* -------------------------------------------------------------------- */
796 : /* Create band information objects. */
797 : /* -------------------------------------------------------------------- */
798 124 : for( iBand = 1; iBand <= poDS->nBands; iBand++ )
799 : {
800 : poDS->SetBand( iBand, new JP2OpenJPEGRasterBand( poDS, iBand, eDataType,
801 38 : nTileW, nTileH) );
802 : }
803 :
804 : /* -------------------------------------------------------------------- */
805 : /* More metadata. */
806 : /* -------------------------------------------------------------------- */
807 24 : if( poDS->nBands > 1 )
808 : {
809 7 : poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );
810 : }
811 :
812 : /* -------------------------------------------------------------------- */
813 : /* Check for georeferencing information. */
814 : /* -------------------------------------------------------------------- */
815 24 : GDALJP2Metadata oJP2Geo;
816 :
817 24 : if( oJP2Geo.ReadAndParse( poOpenInfo->pszFilename ) )
818 : {
819 9 : if ( poDS->pszProjection )
820 9 : CPLFree( poDS->pszProjection );
821 9 : poDS->pszProjection = CPLStrdup(oJP2Geo.pszProjection);
822 9 : poDS->bGeoTransformValid = oJP2Geo.bHaveGeoTransform;
823 : memcpy( poDS->adfGeoTransform, oJP2Geo.adfGeoTransform,
824 9 : sizeof(double) * 6 );
825 9 : poDS->nGCPCount = oJP2Geo.nGCPCount;
826 : poDS->pasGCPList =
827 9 : GDALDuplicateGCPs( oJP2Geo.nGCPCount, oJP2Geo.pasGCPList );
828 : }
829 :
830 : /* -------------------------------------------------------------------- */
831 : /* Initialize any PAM information. */
832 : /* -------------------------------------------------------------------- */
833 24 : poDS->SetDescription( poOpenInfo->pszFilename );
834 24 : poDS->TryLoadXML();
835 :
836 : /* -------------------------------------------------------------------- */
837 : /* Check for overviews. */
838 : /* -------------------------------------------------------------------- */
839 24 : poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );
840 :
841 24 : return( poDS );
842 : }
843 :
844 : /************************************************************************/
845 : /* CreateCopy() */
846 : /************************************************************************/
847 :
848 : GDALDataset * JP2OpenJPEGDataset::CreateCopy( const char * pszFilename,
849 : GDALDataset *poSrcDS,
850 : int bStrict, char ** papszOptions,
851 : GDALProgressFunc pfnProgress,
852 18 : void * pProgressData )
853 :
854 : {
855 18 : int nBands = poSrcDS->GetRasterCount();
856 18 : int nXSize = poSrcDS->GetRasterXSize();
857 18 : int nYSize = poSrcDS->GetRasterYSize();
858 :
859 18 : if( nBands != 1 && nBands != 3 )
860 : {
861 : CPLError( CE_Failure, CPLE_NotSupported,
862 4 : "Unable to export files with %d bands.", nBands );
863 4 : return NULL;
864 : }
865 :
866 14 : if (poSrcDS->GetRasterBand(1)->GetColorTable() != NULL)
867 : {
868 : CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
869 : "JP2OpenJPEG driver ignores color table. "
870 : "The source raster band will be considered as grey level.\n"
871 0 : "Consider using color table expansion (-expand option in gdal_translate)\n");
872 0 : if (bStrict)
873 0 : return NULL;
874 : }
875 :
876 14 : GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
877 14 : int nDataTypeSize = (GDALGetDataTypeSize(eDataType) / 8);
878 14 : if (eDataType != GDT_Byte && eDataType != GDT_Int16 && eDataType != GDT_UInt16
879 : && eDataType != GDT_Int32 && eDataType != GDT_UInt32)
880 : {
881 : CPLError( CE_Failure, CPLE_NotSupported,
882 6 : "JP2OpenJPEG driver only supports creating Byte, GDT_Int16, GDT_UInt16, GDT_Int32, GDT_UInt32");
883 6 : return NULL;
884 : }
885 :
886 : /* -------------------------------------------------------------------- */
887 : /* Analyze creation options. */
888 : /* -------------------------------------------------------------------- */
889 8 : OPJ_CODEC_FORMAT eCodecFormat = CODEC_J2K;
890 8 : const char* pszCodec = CSLFetchNameValueDef(papszOptions, "CODEC", NULL);
891 8 : if (pszCodec)
892 : {
893 0 : if (EQUAL(pszCodec, "JP2"))
894 0 : eCodecFormat = CODEC_JP2;
895 0 : else if (EQUAL(pszCodec, "J2K"))
896 0 : eCodecFormat = CODEC_J2K;
897 : else
898 : {
899 : CPLError(CE_Warning, CPLE_NotSupported,
900 : "Unsupported value for CODEC : %s. Defaulting to J2K",
901 0 : pszCodec);
902 : }
903 : }
904 : else
905 : {
906 8 : if (strlen(pszFilename) > 4 &&
907 : EQUAL(pszFilename + strlen(pszFilename) - 4, ".JP2"))
908 : {
909 0 : eCodecFormat = CODEC_JP2;
910 : }
911 : }
912 :
913 : int nBlockXSize =
914 8 : atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "1024"));
915 : int nBlockYSize =
916 8 : atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "1024"));
917 8 : if (nBlockXSize < 32 || nBlockYSize < 32)
918 : {
919 0 : CPLError(CE_Failure, CPLE_NotSupported, "Invalid block size");
920 0 : return NULL;
921 : }
922 :
923 8 : if (nXSize < nBlockXSize)
924 8 : nBlockXSize = nXSize;
925 8 : if (nYSize < nBlockYSize)
926 8 : nBlockYSize = nYSize;
927 :
928 8 : OPJ_PROG_ORDER eProgOrder = LRCP;
929 : const char* pszPROGORDER =
930 8 : CSLFetchNameValueDef(papszOptions, "PROGRESSION", "LRCP");
931 8 : if (EQUAL(pszPROGORDER, "LRCP"))
932 8 : eProgOrder = LRCP;
933 0 : else if (EQUAL(pszPROGORDER, "RLCP"))
934 0 : eProgOrder = RLCP;
935 0 : else if (EQUAL(pszPROGORDER, "RPCL"))
936 0 : eProgOrder = RPCL;
937 0 : else if (EQUAL(pszPROGORDER, "PCRL"))
938 0 : eProgOrder = PCRL;
939 0 : else if (EQUAL(pszPROGORDER, "CPRL"))
940 0 : eProgOrder = CPRL;
941 : else
942 : {
943 : CPLError(CE_Warning, CPLE_NotSupported,
944 : "Unsupported value for PROGRESSION : %s. Defaulting to LRCP",
945 0 : pszPROGORDER);
946 : }
947 :
948 : int bIsIrreversible =
949 8 : ! (CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "REVERSIBLE", "NO")));
950 :
951 8 : double dfRate = 100. / 25;
952 8 : const char* pszQuality = CSLFetchNameValueDef(papszOptions, "QUALITY", NULL);
953 8 : if (pszQuality)
954 : {
955 2 : double dfQuality = atof(pszQuality);
956 4 : if (dfQuality > 0 && dfQuality <= 100)
957 : {
958 2 : dfRate = 100 / dfQuality;
959 : }
960 : else
961 : {
962 : CPLError(CE_Warning, CPLE_NotSupported,
963 : "Unsupported value for QUALITY : %s. Defaulting to 25",
964 0 : pszQuality);
965 : }
966 : }
967 :
968 8 : int nNumResolutions = 6;
969 8 : const char* pszResolutions = CSLFetchNameValueDef(papszOptions, "RESOLUTIONS", NULL);
970 8 : if (pszResolutions)
971 : {
972 1 : nNumResolutions = atoi(pszResolutions);
973 1 : if (nNumResolutions < 1 || nNumResolutions > 7)
974 : {
975 0 : nNumResolutions = 6;
976 : CPLError(CE_Warning, CPLE_NotSupported,
977 : "Unsupported value for RESOLUTIONS : %s. Defaulting to 6",
978 0 : pszResolutions);
979 : }
980 : }
981 :
982 8 : int bSOP = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SOP", "FALSE"));
983 8 : int bEPH = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "EPH", "FALSE"));
984 :
985 : int bResample = nBands == 3 && eDataType == GDT_Byte &&
986 8 : CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "YCBCR420", "FALSE"));
987 8 : if (bResample && !((nXSize % 2) == 0 && (nYSize % 2) == 0 && (nBlockXSize % 2) == 0 && (nBlockYSize % 2) == 0))
988 : {
989 : CPLError(CE_Warning, CPLE_NotSupported,
990 0 : "YCBCR420 unsupported when image size and/or tile size are not multiple of 2");
991 0 : bResample = FALSE;
992 : }
993 :
994 : /* -------------------------------------------------------------------- */
995 : /* Setup encoder */
996 : /* -------------------------------------------------------------------- */
997 :
998 : opj_cparameters_t parameters;
999 8 : opj_set_default_encoder_parameters(¶meters);
1000 8 : if (bSOP)
1001 0 : parameters.csty |= 0x02;
1002 8 : if (bEPH)
1003 0 : parameters.csty |= 0x04;
1004 8 : parameters.cp_disto_alloc = 1;
1005 8 : parameters.tcp_numlayers = 1;
1006 8 : parameters.tcp_rates[0] = dfRate;
1007 8 : parameters.cp_tx0 = 0;
1008 8 : parameters.cp_ty0 = 0;
1009 8 : parameters.tile_size_on = TRUE;
1010 8 : parameters.cp_tdx = nBlockXSize;
1011 8 : parameters.cp_tdy = nBlockYSize;
1012 8 : parameters.irreversible = bIsIrreversible;
1013 8 : parameters.numresolution = nNumResolutions;
1014 8 : parameters.prog_order = eProgOrder;
1015 :
1016 : opj_image_cmptparm_t* pasBandParams =
1017 8 : (opj_image_cmptparm_t*)CPLMalloc(nBands * sizeof(opj_image_cmptparm_t));
1018 : int iBand;
1019 18 : for(iBand=0;iBand<nBands;iBand++)
1020 : {
1021 10 : pasBandParams[iBand].x0 = 0;
1022 10 : pasBandParams[iBand].y0 = 0;
1023 10 : if (bResample && iBand > 0)
1024 : {
1025 0 : pasBandParams[iBand].dx = 2;
1026 0 : pasBandParams[iBand].dy = 2;
1027 0 : pasBandParams[iBand].w = nXSize / 2;
1028 0 : pasBandParams[iBand].h = nYSize / 2;
1029 : }
1030 : else
1031 : {
1032 10 : pasBandParams[iBand].dx = 1;
1033 10 : pasBandParams[iBand].dy = 1;
1034 10 : pasBandParams[iBand].w = nXSize;
1035 10 : pasBandParams[iBand].h = nYSize;
1036 : }
1037 10 : pasBandParams[iBand].sgnd = (eDataType == GDT_Int16 || eDataType == GDT_Int32);
1038 10 : pasBandParams[iBand].prec = 8 * nDataTypeSize;
1039 : }
1040 :
1041 8 : opj_codec_t* pCodec = opj_create_compress(eCodecFormat);
1042 8 : if (pCodec == NULL)
1043 : {
1044 : CPLError(CE_Failure, CPLE_AppDefined,
1045 0 : "opj_create_compress() failed");
1046 0 : CPLFree(pasBandParams);
1047 0 : return NULL;
1048 : }
1049 :
1050 8 : opj_set_info_handler(pCodec, JP2OpenJPEGDataset_InfoCallback,NULL);
1051 8 : opj_set_warning_handler(pCodec, JP2OpenJPEGDataset_WarningCallback,NULL);
1052 8 : opj_set_error_handler(pCodec, JP2OpenJPEGDataset_ErrorCallback,NULL);
1053 :
1054 8 : OPJ_COLOR_SPACE eColorSpace = (bResample) ? CLRSPC_SYCC : (nBands == 3) ? CLRSPC_SRGB : CLRSPC_GRAY;
1055 : opj_image_t* psImage = opj_image_tile_create(nBands,pasBandParams,
1056 8 : eColorSpace);
1057 8 : CPLFree(pasBandParams);
1058 8 : pasBandParams = NULL;
1059 8 : if (psImage == NULL)
1060 : {
1061 : CPLError(CE_Failure, CPLE_AppDefined,
1062 0 : "opj_image_tile_create() failed");
1063 0 : opj_destroy_codec(pCodec);
1064 0 : return NULL;
1065 : }
1066 :
1067 8 : psImage->x0 = 0;
1068 8 : psImage->y0 = 0;
1069 8 : psImage->x1 = nXSize;
1070 8 : psImage->y1 = nYSize;
1071 8 : psImage->color_space = eColorSpace;
1072 8 : psImage->numcomps = nBands;
1073 :
1074 8 : if (!opj_setup_encoder(pCodec,¶meters,psImage))
1075 : {
1076 : CPLError(CE_Failure, CPLE_AppDefined,
1077 0 : "opj_setup_encoder() failed");
1078 0 : opj_image_destroy(psImage);
1079 0 : opj_destroy_codec(pCodec);
1080 0 : return NULL;
1081 : }
1082 :
1083 : /* -------------------------------------------------------------------- */
1084 : /* Create the dataset. */
1085 : /* -------------------------------------------------------------------- */
1086 :
1087 8 : const char* pszAccess = EQUALN(pszFilename, "/vsisubfile/", 12) ? "r+b" : "w+b";
1088 8 : FILE* fp = VSIFOpenL(pszFilename, pszAccess);
1089 8 : if (fp == NULL)
1090 : {
1091 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot create file");
1092 0 : opj_image_destroy(psImage);
1093 0 : opj_destroy_codec(pCodec);
1094 0 : return NULL;
1095 : }
1096 :
1097 : opj_stream_t * pStream;
1098 8 : pStream = opj_stream_create(1024*1024, FALSE);
1099 8 : opj_stream_set_write_function(pStream, JP2OpenJPEGDataset_Write);
1100 8 : opj_stream_set_seek_function(pStream, JP2OpenJPEGDataset_Seek);
1101 8 : opj_stream_set_skip_function(pStream, JP2OpenJPEGDataset_Skip);
1102 8 : opj_stream_set_user_data(pStream, fp);
1103 :
1104 8 : if (!opj_start_compress(pCodec,psImage,pStream))
1105 : {
1106 : CPLError(CE_Failure, CPLE_AppDefined,
1107 6 : "opj_start_compress() failed");
1108 6 : opj_stream_destroy(pStream);
1109 6 : opj_image_destroy(psImage);
1110 6 : opj_destroy_codec(pCodec);
1111 6 : VSIFCloseL(fp);
1112 6 : return NULL;
1113 : }
1114 :
1115 2 : int nTilesX = (nXSize + nBlockXSize - 1) / nBlockXSize;
1116 2 : int nTilesY = (nYSize + nBlockYSize - 1) / nBlockYSize;
1117 :
1118 : GByte* pTempBuffer =(GByte*)VSIMalloc(nBlockXSize * nBlockYSize *
1119 2 : nBands * nDataTypeSize);
1120 2 : if (pTempBuffer == NULL)
1121 : {
1122 0 : opj_stream_destroy(pStream);
1123 0 : opj_image_destroy(psImage);
1124 0 : opj_destroy_codec(pCodec);
1125 0 : VSIFCloseL(fp);
1126 0 : return NULL;
1127 : }
1128 :
1129 2 : GByte* pYUV420Buffer = NULL;
1130 2 : if (bResample)
1131 : {
1132 0 : pYUV420Buffer =(GByte*)VSIMalloc(3 * nBlockXSize * nBlockYSize / 2);
1133 0 : if (pYUV420Buffer == NULL)
1134 : {
1135 0 : opj_stream_destroy(pStream);
1136 0 : opj_image_destroy(psImage);
1137 0 : opj_destroy_codec(pCodec);
1138 0 : CPLFree(pTempBuffer);
1139 0 : VSIFCloseL(fp);
1140 0 : return NULL;
1141 : }
1142 : }
1143 :
1144 : /* -------------------------------------------------------------------- */
1145 : /* Iterate over the tiles */
1146 : /* -------------------------------------------------------------------- */
1147 2 : pfnProgress( 0.0, NULL, pProgressData );
1148 :
1149 2 : CPLErr eErr = CE_None;
1150 : int nBlockXOff, nBlockYOff;
1151 2 : int iTile = 0;
1152 4 : for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nTilesY;nBlockYOff++)
1153 : {
1154 4 : for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nTilesX;nBlockXOff++)
1155 : {
1156 2 : int nWidthToRead = MIN(nBlockXSize, nXSize - nBlockXOff * nBlockXSize);
1157 2 : int nHeightToRead = MIN(nBlockYSize, nYSize - nBlockYOff * nBlockYSize);
1158 : eErr = poSrcDS->RasterIO(GF_Read,
1159 : nBlockXOff * nBlockXSize,
1160 : nBlockYOff * nBlockYSize,
1161 : nWidthToRead, nHeightToRead,
1162 : pTempBuffer, nWidthToRead, nHeightToRead,
1163 : eDataType,
1164 : nBands, NULL,
1165 2 : 0,0,0);
1166 2 : if (eErr == CE_None)
1167 : {
1168 2 : if (bResample)
1169 : {
1170 : int j, i;
1171 0 : for(j=0;j<nHeightToRead;j++)
1172 : {
1173 0 : for(i=0;i<nWidthToRead;i++)
1174 : {
1175 0 : int R = pTempBuffer[j*nWidthToRead+i];
1176 0 : int G = pTempBuffer[nHeightToRead*nWidthToRead + j*nWidthToRead+i];
1177 0 : int B = pTempBuffer[2*nHeightToRead*nWidthToRead + j*nWidthToRead+i];
1178 0 : int Y = 0.299 * R + 0.587 * G + 0.114 * B;
1179 0 : int Cb = CLAMP_0_255(-0.1687 * R - 0.3313 * G + 0.5 * B + 128);
1180 0 : int Cr = CLAMP_0_255(0.5 * R - 0.4187 * G - 0.0813 * B + 128);
1181 0 : pYUV420Buffer[j*nWidthToRead+i] = Y;
1182 0 : pYUV420Buffer[nHeightToRead * nWidthToRead + ((j/2) * ((nWidthToRead)/2) + i/2) ] = Cb;
1183 0 : pYUV420Buffer[5 * nHeightToRead * nWidthToRead / 4 + ((j/2) * ((nWidthToRead)/2) + i/2) ] = Cr;
1184 : }
1185 : }
1186 :
1187 0 : if (!opj_write_tile(pCodec,
1188 : iTile,
1189 : pYUV420Buffer,
1190 : 3 * nWidthToRead * nHeightToRead / 2,
1191 : pStream))
1192 : {
1193 : CPLError(CE_Failure, CPLE_AppDefined,
1194 0 : "opj_write_tile() failed");
1195 0 : eErr = CE_Failure;
1196 : }
1197 : }
1198 : else
1199 : {
1200 2 : if (!opj_write_tile(pCodec,
1201 : iTile,
1202 : pTempBuffer,
1203 : nWidthToRead * nHeightToRead * nBands * nDataTypeSize,
1204 : pStream))
1205 : {
1206 : CPLError(CE_Failure, CPLE_AppDefined,
1207 0 : "opj_write_tile() failed");
1208 0 : eErr = CE_Failure;
1209 : }
1210 : }
1211 : }
1212 :
1213 2 : if( !pfnProgress( (iTile + 1) * 1.0 / (nTilesX * nTilesY), NULL, pProgressData ) )
1214 0 : eErr = CE_Failure;
1215 :
1216 2 : iTile ++;
1217 : }
1218 : }
1219 :
1220 2 : VSIFree(pTempBuffer);
1221 2 : VSIFree(pYUV420Buffer);
1222 :
1223 2 : if (eErr != CE_None)
1224 : {
1225 0 : opj_stream_destroy(pStream);
1226 0 : opj_image_destroy(psImage);
1227 0 : opj_destroy_codec(pCodec);
1228 0 : VSIFCloseL(fp);
1229 0 : return NULL;
1230 : }
1231 :
1232 2 : if (!opj_end_compress(pCodec,pStream))
1233 : {
1234 : CPLError(CE_Failure, CPLE_AppDefined,
1235 0 : "opj_end_compress() failed");
1236 0 : opj_stream_destroy(pStream);
1237 0 : opj_image_destroy(psImage);
1238 0 : opj_destroy_codec(pCodec);
1239 0 : VSIFCloseL(fp);
1240 0 : return NULL;
1241 : }
1242 :
1243 2 : opj_stream_destroy(pStream);
1244 2 : opj_image_destroy(psImage);
1245 2 : opj_destroy_codec(pCodec);
1246 2 : VSIFCloseL(fp);
1247 :
1248 : /* -------------------------------------------------------------------- */
1249 : /* Re-open dataset, and copy any auxilary pam information. */
1250 : /* -------------------------------------------------------------------- */
1251 2 : GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
1252 2 : JP2OpenJPEGDataset *poDS = (JP2OpenJPEGDataset*) JP2OpenJPEGDataset::Open(&oOpenInfo);
1253 :
1254 2 : if( poDS )
1255 2 : poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
1256 :
1257 2 : return poDS;
1258 : }
1259 :
1260 : /************************************************************************/
1261 : /* GDALRegister_JP2OpenJPEG() */
1262 : /************************************************************************/
1263 :
1264 409 : void GDALRegister_JP2OpenJPEG()
1265 :
1266 : {
1267 : GDALDriver *poDriver;
1268 :
1269 409 : if (! GDAL_CHECK_VERSION("JP2OpenJPEG driver"))
1270 0 : return;
1271 :
1272 409 : if( GDALGetDriverByName( "JP2OpenJPEG" ) == NULL )
1273 : {
1274 392 : poDriver = new GDALDriver();
1275 :
1276 392 : poDriver->SetDescription( "JP2OpenJPEG" );
1277 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1278 392 : "JPEG-2000 driver based on OpenJPEG library" );
1279 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1280 392 : "frmt_jp2openjpeg.html" );
1281 392 : poDriver->SetMetadataItem( GDAL_DMD_MIMETYPE, "image/jp2" );
1282 392 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "jp2" );
1283 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
1284 392 : "Byte Int16 UInt16 Int32 UInt32" );
1285 :
1286 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
1287 : "<CreationOptionList>"
1288 : " <Option name='CODEC' type='string-select' default='according to file extension. If unknown, default to J2K'>"
1289 : " <Value>JP2</Value>"
1290 : " <Value>J2K</Value>"
1291 : " </Option>"
1292 : " <Option name='QUALITY' type='float' description='Quality. 0-100' default=25/>"
1293 : " <Option name='REVERSIBLE' type='boolean' description='True if the compression is reversible' default='false'/>"
1294 : " <Option name='RESOLUTIONS' type='int' description='Number of resolutions. 1-7' default=6/>"
1295 : " <Option name='BLOCKXSIZE' type='int' description='Tile Width' default=1024/>"
1296 : " <Option name='BLOCKYSIZE' type='int' description='Tile Height' default=1024/>"
1297 : " <Option name='PROGRESSION' type='string-select' default='LRCP'>"
1298 : " <Value>LRCP</Value>"
1299 : " <Value>RLCP</Value>"
1300 : " <Value>RPCL</Value>"
1301 : " <Value>PCRL</Value>"
1302 : " <Value>CPRL</Value>"
1303 : " </Option>"
1304 : " <Option name='SOP' type='boolean' description='True to insert SOP markers' default='false'/>"
1305 : " <Option name='EPH' type='boolean' description='True to insert EPH markers' default='false'/>"
1306 : " <Option name='YCBCR420' type='boolean' description='if RGB must be resampled to YCbCr 4:2:0' default='false'/>"
1307 392 : "</CreationOptionList>" );
1308 :
1309 392 : poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
1310 :
1311 392 : poDriver->pfnIdentify = JP2OpenJPEGDataset::Identify;
1312 392 : poDriver->pfnOpen = JP2OpenJPEGDataset::Open;
1313 392 : poDriver->pfnCreateCopy = JP2OpenJPEGDataset::CreateCopy;
1314 :
1315 392 : GetGDALDriverManager()->RegisterDriver( poDriver );
1316 : }
1317 : }
1318 :
|