void TestRoundTrip(const char* strName, std::vector<BYTE>& rgbyteRaw, Size size, int cbit, int ccomp) { std::vector<BYTE> rgbyteCompressed(size.cx *size.cy * ccomp * cbit / 4); std::vector<BYTE> rgbyteOut(size.cx * size.cy * ((cbit + 7) / 8) * ccomp); double dblstart = getTime(); JlsParameters info = JlsParameters(); info.components = ccomp; info.bitspersample = cbit; info.height = size.cy; info.width = size.cx; if (ccomp == 4) { info.ilv = ILV_LINE; } else if (ccomp == 3) { info.ilv = ILV_LINE; info.colorTransform = COLORXFORM_HP1; } size_t compressedLength; JLS_ERROR err = JpegLsEncode(&rgbyteCompressed[0], rgbyteCompressed.size(), &compressedLength, &rgbyteRaw[0], rgbyteOut.size(), &info); assert(err == OK); double dwtimeEncodeComplete = getTime(); err = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), &rgbyteCompressed[0], int(compressedLength), NULL); assert(err == OK); double bitspersample = compressedLength * 8 * 1.0 / (ccomp *size.cy * size.cx); double dwtimeDecodeComplete = getTime(); std::cout << "RoundTrip test for: " << strName << "\n\r"; double decodeTime = dwtimeDecodeComplete - dwtimeEncodeComplete; double symbolRate = (ccomp *size.cy * size.cx)/(1000.0 * decodeTime); printf("Size:%4ldx%4ld Encode:%7.2f Decode:%7.2f Bps:%5.2f Decode rate:%5.1f M/s \n\r", size.cx, size.cy, dwtimeEncodeComplete - dblstart, dwtimeDecodeComplete - dwtimeEncodeComplete, bitspersample, symbolRate); BYTE* pbyteOut = &rgbyteOut[0]; for (size_t i = 0; i < rgbyteOut.size(); ++i) { if (rgbyteRaw[i] != pbyteOut[i]) { assert(false); break; } } }
GDALDataset * JPEGLSDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS, int bStrict, char ** papszOptions, GDALProgressFunc /*pfnProgress*/, void * /*pProgressData*/ ) { int nBands = poSrcDS->GetRasterCount(); int nXSize = poSrcDS->GetRasterXSize(); int nYSize = poSrcDS->GetRasterYSize(); /* -------------------------------------------------------------------- */ /* Some some rudimentary checks */ /* -------------------------------------------------------------------- */ if( nBands != 1 && nBands != 3 && nBands != 4 ) { CPLError( CE_Failure, CPLE_NotSupported, "JPGLS driver doesn't support %d bands. Must be 1 (grey), " "3 (RGB) or 4 bands.\n", nBands ); return NULL; } if (nBands == 1 && poSrcDS->GetRasterBand(1)->GetColorTable() != NULL) { CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, "JPGLS driver ignores color table. " "The source raster band will be considered as grey level.\n" "Consider using color table expansion (-expand option in gdal_translate)\n"); if (bStrict) return NULL; } GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType(); if( eDT != GDT_Byte && eDT != GDT_Int16 ) { CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported, "JPGLS driver doesn't support data type %s", GDALGetDataTypeName( poSrcDS->GetRasterBand(1)->GetRasterDataType()) ); if (bStrict) return NULL; } int nWordSize = GDALGetDataTypeSize(eDT) / 8; int nUncompressedSize = nXSize * nYSize * nBands * nWordSize; // FIXME? bug in charls-1.0beta ?. I needed a "+ something" to // avoid errors on byte.tif. int nCompressedSize = nUncompressedSize + 256; GByte* pabyDataCompressed = (GByte*)VSI_MALLOC_VERBOSE(nCompressedSize); GByte* pabyDataUncompressed = (GByte*)VSI_MALLOC_VERBOSE(nUncompressedSize); if (pabyDataCompressed == NULL || pabyDataUncompressed == NULL) { VSIFree(pabyDataCompressed); VSIFree(pabyDataUncompressed); return NULL; } CPLErr eErr; eErr = poSrcDS->RasterIO(GF_Read, 0, 0, nXSize, nYSize, pabyDataUncompressed, nXSize, nYSize, eDT, nBands, NULL, nBands * nWordSize, nBands * nWordSize * nXSize, nWordSize, NULL); if (eErr != CE_None) { VSIFree(pabyDataCompressed); VSIFree(pabyDataUncompressed); return NULL; } size_t nWritten = 0; JlsParameters sParams; memset(&sParams, 0, sizeof(sParams)); sParams.width = nXSize; sParams.height = nYSize; sParams.bitspersample = (eDT == GDT_Byte) ? 8 : 16; sParams.ilv = ILV_NONE; const char* pszINTERLEAVE = CSLFetchNameValue( papszOptions, "INTERLEAVE" ); if (pszINTERLEAVE) { if (EQUAL(pszINTERLEAVE, "PIXEL")) sParams.ilv = ILV_SAMPLE; else if (EQUAL(pszINTERLEAVE, "LINE")) sParams.ilv = ILV_LINE; else if (EQUAL(pszINTERLEAVE, "BAND")) sParams.ilv = ILV_NONE; else { CPLError(CE_Warning, CPLE_NotSupported, "Unsupported value for INTERLEAVE : %s. Defaulting to BAND", pszINTERLEAVE); } } const char* pszLOSSFACTOR = CSLFetchNameValue( papszOptions, "LOSS_FACTOR" ); if (pszLOSSFACTOR) { int nLOSSFACTOR = atoi(pszLOSSFACTOR); if (nLOSSFACTOR >= 0) sParams.allowedlossyerror = nLOSSFACTOR; } const char* pszNBITS = poSrcDS->GetRasterBand(1)->GetMetadataItem( "NBITS", "IMAGE_STRUCTURE" ); if (pszNBITS != NULL) { int nBits = atoi(pszNBITS); if (nBits != 8 && nBits != 16) sParams.bitspersample = nBits; } sParams.components = nBands; JLS_ERROR eError = JpegLsEncode(pabyDataCompressed, nCompressedSize, &nWritten, pabyDataUncompressed, nUncompressedSize, &sParams); VSIFree(pabyDataUncompressed); pabyDataUncompressed = NULL; if (eError != OK) { CPLError(CE_Failure, CPLE_AppDefined, "Compression of data failed : %s", JPEGLSGetErrorAsString(eError)); VSIFree(pabyDataCompressed); return NULL; } VSILFILE* fp = VSIFOpenL(pszFilename, "wb"); if (fp == NULL) { VSIFree(pabyDataCompressed); return NULL; } VSIFWriteL(pabyDataCompressed, 1, nWritten, fp); VSIFree(pabyDataCompressed); VSIFCloseL(fp); /* -------------------------------------------------------------------- */ /* Re-open dataset, and copy any auxiliary pam information. */ /* -------------------------------------------------------------------- */ JPEGLSDataset *poDS = (JPEGLSDataset *) GDALOpen( pszFilename, GA_ReadOnly ); if( poDS ) poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT ); return poDS; }