51
// we believe it is ok to use setjmp() in this situation.
53
# pragma warning(disable:4611)
51
56
#if defined(JPEG_DUAL_MODE_8_12) && !defined(JPGDataset)
52
57
GDALDataset* JPEGDataset12Open(GDALOpenInfo* poOpenInfo);
54
JPEGCreateCopy12( const char * pszFilename, GDALDataset *poSrcDS,
55
int bStrict, char ** papszOptions,
56
GDALProgressFunc pfnProgress, void * pProgressData );
58
GDALDataset* JPEGDataset12CreateCopy( const char * pszFilename,
60
int bStrict, char ** papszOptions,
61
GDALProgressFunc pfnProgress,
62
void * pProgressData );
60
66
void GDALRegister_JPEG(void);
63
void jpeg_vsiio_src (j_decompress_ptr cinfo, FILE * infile);
64
void jpeg_vsiio_dest (j_compress_ptr cinfo, FILE * outfile);
69
void jpeg_vsiio_src (j_decompress_ptr cinfo, VSILFILE * infile);
70
void jpeg_vsiio_dest (j_compress_ptr cinfo, VSILFILE * outfile);
67
73
* Do we want to do special processing suitable for when JSAMPLE is a
158
172
virtual const char *GetMetadataItem( const char * pszName,
159
173
const char * pszDomain = "" );
175
virtual char **GetFileList(void);
162
177
static GDALDataset *Open( GDALOpenInfo * );
163
178
static int Identify( GDALOpenInfo * );
179
static GDALDataset* CreateCopy( const char * pszFilename,
180
GDALDataset *poSrcDS,
181
int bStrict, char ** papszOptions,
182
GDALProgressFunc pfnProgress,
183
void * pProgressData );
165
185
static void ErrorExit(j_common_ptr cinfo);
254
274
/************************************************************************/
275
/* ReadXMPMetadata() */
276
/************************************************************************/
278
/* See §2.1.3 of http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/xmp/pdfs/XMPSpecificationPart3.pdf */
280
void JPGDataset::ReadXMPMetadata()
282
if (bHasReadXMPMetadata)
285
/* Save current position to avoid disturbing JPEG stream decoding */
286
vsi_l_offset nCurOffset = VSIFTellL(fpImage);
288
/* -------------------------------------------------------------------- */
289
/* Search for APP1 chunk. */
290
/* -------------------------------------------------------------------- */
291
GByte abyChunkHeader[2+2+29];
293
int bFoundXMP = TRUE;
297
if( VSIFSeekL( fpImage, nChunkLoc, SEEK_SET ) != 0 )
300
if( VSIFReadL( abyChunkHeader, sizeof(abyChunkHeader), 1, fpImage ) != 1 )
303
if( abyChunkHeader[0] != 0xFF
304
|| (abyChunkHeader[1] & 0xf0) != 0xe0 )
305
break; // Not an APP chunk.
307
if( abyChunkHeader[1] == 0xe1
308
&& strncmp((const char *) abyChunkHeader + 4,"http://ns.adobe.com/xap/1.0/",28) == 0 )
314
nChunkLoc += 2 + abyChunkHeader[2] * 256 + abyChunkHeader[3];
319
int nXMPLength = abyChunkHeader[2] * 256 + abyChunkHeader[3];
320
if (nXMPLength > 2 + 29)
322
char* pszXMP = (char*)VSIMalloc(nXMPLength - 2 - 29 + 1);
325
if (VSIFReadL( pszXMP, nXMPLength - 2 - 29, 1, fpImage ) == 1)
327
pszXMP[nXMPLength - 2 - 29] = '\0';
329
/* Avoid setting the PAM dirty bit just for that */
330
int nOldPamFlags = nPamFlags;
333
apszMDList[0] = pszXMP;
334
apszMDList[1] = NULL;
335
SetMetadata(apszMDList, "xml:XMP");
337
nPamFlags = nOldPamFlags;
344
VSIFSeekL( fpImage, nCurOffset, SEEK_SET );
346
bHasReadXMPMetadata = TRUE;
349
/************************************************************************/
255
350
/* GetMetadata() */
256
351
/************************************************************************/
257
352
char **JPGDataset::GetMetadata( const char * pszDomain )
259
356
if (eAccess == GA_ReadOnly && !bHasReadEXIFMetadata &&
260
357
(pszDomain == NULL || EQUAL(pszDomain, "")))
261
358
ReadEXIFMetadata();
359
if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
360
(pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
262
362
return GDALPamDataset::GetMetadata(pszDomain);
268
368
const char *JPGDataset::GetMetadataItem( const char * pszName,
269
369
const char * pszDomain )
271
373
if (eAccess == GA_ReadOnly && !bHasReadEXIFMetadata &&
272
374
(pszDomain == NULL || EQUAL(pszDomain, "")) &&
273
375
pszName != NULL && EQUALN(pszName, "EXIF_", 5))
274
376
ReadEXIFMetadata();
377
if (eAccess == GA_ReadOnly && !bHasReadXMPMetadata &&
378
(pszDomain != NULL && EQUAL(pszDomain, "xml:XMP")))
275
380
return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
1492
1633
/************************************************************************/
1634
/* JPEGDatasetIsJPEGLS() */
1635
/************************************************************************/
1637
static int JPEGDatasetIsJPEGLS( GDALOpenInfo * poOpenInfo )
1640
GByte *pabyHeader = poOpenInfo->pabyHeader;
1641
int nHeaderBytes = poOpenInfo->nHeaderBytes;
1643
if( nHeaderBytes < 10 )
1646
if( pabyHeader[0] != 0xff
1647
|| pabyHeader[1] != 0xd8 )
1651
for (;nOffset + 4 < nHeaderBytes;)
1653
if (pabyHeader[nOffset] != 0xFF)
1656
int nMarker = pabyHeader[nOffset + 1];
1657
if (nMarker == 0xF7 /* JPEG Extension 7, JPEG-LS */)
1659
if (nMarker == 0xF8 /* JPEG Extension 8, JPEG-LS Extension */)
1661
if (nMarker == 0xC3 /* Start of Frame 3 */)
1663
if (nMarker == 0xC7 /* Start of Frame 7 */)
1665
if (nMarker == 0xCB /* Start of Frame 11 */)
1667
if (nMarker == 0xCF /* Start of Frame 15 */)
1670
nOffset += 2 + pabyHeader[nOffset + 2] * 256 + pabyHeader[nOffset + 3];
1676
/************************************************************************/
1493
1677
/* Identify() */
1494
1678
/************************************************************************/
1611
1799
/* -------------------------------------------------------------------- */
1800
/* Open the file using the large file api. */
1801
/* -------------------------------------------------------------------- */
1802
VSILFILE* fpImage = VSIFOpenL( real_filename, "rb" );
1804
if( fpImage == NULL )
1806
CPLError( CE_Failure, CPLE_OpenFailed,
1807
"VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp",
1812
/* -------------------------------------------------------------------- */
1612
1813
/* Create a corresponding GDALDataset. */
1613
1814
/* -------------------------------------------------------------------- */
1614
1815
JPGDataset *poDS;
1616
1817
poDS = new JPGDataset();
1617
1818
poDS->nQLevel = nQLevel;
1619
/* -------------------------------------------------------------------- */
1620
/* Open the file using the large file api. */
1621
/* -------------------------------------------------------------------- */
1622
poDS->fpImage = VSIFOpenL( real_filename, "rb" );
1624
if( poDS->fpImage == NULL )
1626
CPLError( CE_Failure, CPLE_OpenFailed,
1627
"VSIFOpenL(%s) failed unexpectedly in jpgdataset.cpp",
1819
poDS->fpImage = fpImage;
1633
1821
/* -------------------------------------------------------------------- */
1634
1822
/* Move to the start of jpeg data. */
1781
1970
poDS->SetDescription( poOpenInfo->pszFilename );
1783
1972
if( !bIsSubfile )
1973
poDS->TryLoadXML( poOpenInfo->papszSiblingFiles );
1786
1975
poDS->nPamFlags |= GPF_NOSAVE;
1788
1977
/* -------------------------------------------------------------------- */
1789
1978
/* Open overviews. */
1790
1979
/* -------------------------------------------------------------------- */
1791
poDS->oOvManager.Initialize( poDS, real_filename );
1793
/* -------------------------------------------------------------------- */
1794
/* Check for world file. */
1795
/* -------------------------------------------------------------------- */
1798
poDS->bGeoTransformValid =
1799
GDALReadWorldFile( poOpenInfo->pszFilename, NULL,
1800
poDS->adfGeoTransform )
1801
|| GDALReadWorldFile( poOpenInfo->pszFilename, ".jpw",
1802
poDS->adfGeoTransform )
1803
|| GDALReadWorldFile( poOpenInfo->pszFilename, ".wld",
1804
poDS->adfGeoTransform );
1806
if( !poDS->bGeoTransformValid )
1809
GDALReadTabFile( poOpenInfo->pszFilename, poDS->adfGeoTransform,
1810
&poDS->pszProjection,
1811
&poDS->nGCPCount, &poDS->pasGCPList );
1813
if( bTabFileOK && poDS->nGCPCount == 0 )
1814
poDS->bGeoTransformValid = TRUE;
1980
poDS->oOvManager.Initialize( poDS, real_filename, poOpenInfo->papszSiblingFiles );
1982
poDS->bIsSubfile = bIsSubfile;
1821
1987
/************************************************************************/
1988
/* LoadWorldFileOrTab() */
1989
/************************************************************************/
1991
void JPGDataset::LoadWorldFileOrTab()
1995
if (bHasTriedLoadWorldFileOrTab)
1997
bHasTriedLoadWorldFileOrTab = TRUE;
1999
char* pszWldFilename = NULL;
2001
/* TIROS3 JPEG files have a .wld extension, so don't look for .wld as */
2002
/* as worldfile ! */
2003
int bEndsWithWld = strlen(GetDescription()) > 4 &&
2004
EQUAL( GetDescription() + strlen(GetDescription()) - 4, ".wld");
2005
bGeoTransformValid =
2006
GDALReadWorldFile2( GetDescription(), NULL,
2008
oOvManager.GetSiblingFiles(), &pszWldFilename )
2009
|| GDALReadWorldFile2( GetDescription(), ".jpw",
2011
oOvManager.GetSiblingFiles(), &pszWldFilename )
2012
|| ( !bEndsWithWld && GDALReadWorldFile2( GetDescription(), ".wld",
2014
oOvManager.GetSiblingFiles(), &pszWldFilename ));
2016
if( !bGeoTransformValid )
2019
GDALReadTabFile2( GetDescription(), adfGeoTransform,
2021
&nGCPCount, &pasGCPList,
2022
oOvManager.GetSiblingFiles(), &pszWldFilename );
2024
if( bTabFileOK && nGCPCount == 0 )
2025
bGeoTransformValid = TRUE;
2030
osWldFilename = pszWldFilename;
2031
CPLFree(pszWldFilename);
2035
/************************************************************************/
2037
/************************************************************************/
2039
char **JPGDataset::GetFileList()
2042
char **papszFileList = GDALPamDataset::GetFileList();
2044
LoadWorldFileOrTab();
2046
if (osWldFilename.size() != 0 &&
2047
CSLFindString(papszFileList, osWldFilename) == -1)
2049
papszFileList = CSLAddString( papszFileList, osWldFilename );
2052
return papszFileList;
2055
/************************************************************************/
1822
2056
/* CheckForMask() */
1823
2057
/************************************************************************/
1977
2216
int nBitBufSize = nYSize * ((nXSize+7)/8);
1979
2218
GByte *pabyBitBuf, *pabyMaskLine;
2219
CPLErr eErr = CE_None;
1981
2221
/* -------------------------------------------------------------------- */
1982
2222
/* Allocate uncompressed bit buffer. */
1983
2223
/* -------------------------------------------------------------------- */
1984
pabyBitBuf = (GByte *) CPLCalloc(1,nBitBufSize);
2224
pabyBitBuf = (GByte *) VSICalloc(1,nBitBufSize);
1986
pabyMaskLine = (GByte *) CPLMalloc(nXSize);
2226
pabyMaskLine = (GByte *) VSIMalloc(nXSize);
2227
if (pabyBitBuf == NULL || pabyMaskLine == NULL)
2229
CPLError( CE_Failure, CPLE_OutOfMemory, "Out of memory");
1988
2233
/* -------------------------------------------------------------------- */
1989
2234
/* Set bit buffer from mask band, scanline by scanline. */
1990
2235
/* -------------------------------------------------------------------- */
1991
CPLErr eErr = CE_None;
1993
for( iY = 0; iY < nYSize; iY++ )
2237
for( iY = 0; eErr == CE_None && iY < nYSize; iY++ )
1995
2239
eErr = poMask->RasterIO( GF_Read, 0, iY, nXSize, 1,
1996
2240
pabyMaskLine, nXSize, 1, GDT_Byte, 0, 0 );
2084
2336
/************************************************************************/
2085
/* JPEGCreateCopy() */
2086
2338
/************************************************************************/
2089
JPEGCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
2090
int bStrict, char ** papszOptions,
2091
GDALProgressFunc pfnProgress, void * pProgressData )
2341
JPGDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
2342
int bStrict, char ** papszOptions,
2343
GDALProgressFunc pfnProgress, void * pProgressData )
2094
2346
int nBands = poSrcDS->GetRasterCount();
2353
2605
/* -------------------------------------------------------------------- */
2354
2606
/* Re-open dataset, and copy any auxilary pam information. */
2355
2607
/* -------------------------------------------------------------------- */
2356
JPGDataset *poDS = (JPGDataset *) GDALOpen( pszFilename, GA_ReadOnly );
2608
GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly);
2610
/* If outputing to stdout, we can't reopen it, so we'll return */
2611
/* a fake dataset to make the caller happy */
2612
CPLPushErrorHandler(CPLQuietErrorHandler);
2613
JPGDataset *poDS = (JPGDataset*) JPGDataset::Open( &oOpenInfo );
2614
CPLPopErrorHandler();
2359
2617
poDS->CloneInfo( poSrcDS, nCloneFlags );
2623
JPGDataset* poJPG_DS = new JPGDataset();
2624
poJPG_DS->nRasterXSize = nXSize;
2625
poJPG_DS->nRasterYSize = nYSize;
2626
for(int i=0;i<nBands;i++)
2627
poJPG_DS->SetBand( i+1, new JPGRasterBand( poJPG_DS, i+1) );
2364
2631
/************************************************************************/