#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include //nullptr #include #include static ossimTrace traceDebug("ossim::TiffHandlerState"); static const ossimGeoTiffCoordTransformsLut COORD_TRANS_LUT; static const ossimGeoTiffDatumLut DATUM_LUT; const ossimString ossim::TiffHandlerState::m_typeName = "ossim::TiffHandlerState"; ossim::TiffHandlerState::TiffHandlerState() { } ossim::TiffHandlerState::~TiffHandlerState() { } const ossimString& ossim::TiffHandlerState::getTypeName()const { return m_typeName; } const ossimString& ossim::TiffHandlerState::getStaticTypeName() { return m_typeName; } void ossim::TiffHandlerState::addValue(const ossimString& key, const ossimString& value) { m_tags.add(key.c_str(), value.c_str()); } bool ossim::TiffHandlerState::getValue(ossimString& value, const ossim_uint32 directory, const ossimString& key)const { return getValue(value, "tiff.image"+ossimString::toString(directory)+"."+key); } bool ossim::TiffHandlerState::getValue(ossimString& value, const ossimString& key)const { bool result = false; const char* v = m_tags.find(key.c_str()); if(v) { result = true; value = v; } return result; } bool ossim::TiffHandlerState::exists(ossim_uint32 directory, const ossimString& key)const { return exists("tiff.image"+ ossimString::toString(directory)+ "."+key); } bool ossim::TiffHandlerState::exists(const ossimString& key)const { return (m_tags.find(key)!= 0); } bool ossim::TiffHandlerState::checkBool(ossim_uint32 directory, const ossimString& key)const { return checkBool("tiff.image"+ossimString::toString(directory)+"."+key); } bool ossim::TiffHandlerState::checkBool(const ossimString& key)const { bool result = false; const char* value = m_tags.find(key); if(value) { result = ossimString(value).toBool(); } return result; } bool ossim::TiffHandlerState::loadDefaults(const ossimFilename& file, ossim_uint32 entry) { bool result = ImageHandlerState::loadDefaults(file, entry); if(result) { std::shared_ptr tiffStream = ossim::StreamFactoryRegistry::instance()->createIstream(file); if(tiffStream) { std::shared_ptr streamAdaptor = std::make_shared(tiffStream, file.c_str()); TIFF* tiffPtr = XTIFFClientOpen(file.c_str(), "rm", (thandle_t)streamAdaptor.get(), ossim::TiffIStreamAdaptor::tiffRead, ossim::TiffIStreamAdaptor::tiffWrite, ossim::TiffIStreamAdaptor::tiffSeek, ossim::TiffIStreamAdaptor::tiffClose, ossim::TiffIStreamAdaptor::tiffSize, ossim::TiffIStreamAdaptor::tiffMap, ossim::TiffIStreamAdaptor::tiffUnmap); if(tiffPtr) { loadDefaults(tiffPtr); result = true; XTIFFClose(tiffPtr); tiffPtr = 0; } } } return result; } void ossim::TiffHandlerState::loadDefaults(TIFF* tiffPtr) { ossim_int64 currentDirectory = TIFFCurrentDirectory(tiffPtr); TIFFSetDirectory(tiffPtr, 0); ossim_int32 numberOfDirectories = TIFFNumberOfDirectories(tiffPtr); addValue("number_of_directories", ossimString::toString(numberOfDirectories)); ossim_int32 idx=0; for(;idx < numberOfDirectories;++idx) { if (!TIFFSetDirectory(tiffPtr, idx)) { break; } else { loadDirectory(tiffPtr, idx); } } TIFFSetDirectory(tiffPtr, currentDirectory); } void ossim::TiffHandlerState::loadDefaults(std::shared_ptr &str, const std::string &connectionString) { setConnectionString(connectionString); ossim_int64 offset = str->tellg(); ossimTiffInfo info; std::ostringstream out; str->seekg(0); if(info.open(str, connectionString)) { std::vector prefixValues; ossim_int32 nValues=0; info.print(out); m_tags.parseString(out.str()); m_tags.getSortedList(prefixValues, "tiff.image"); nValues = prefixValues.size(); addValue("tiff.number_of_directories", ossimString::toString(nValues)); // ossim_uint32 idx = 0; //ossim_int64 h = getImageLength(0); //ossim_int64 w = getImageWidth(0); ossim_int64 tw = getTileWidth(0); ossim_int64 th = getTileLength(0); //bool isTiled = (th&&tw&& ((tw < w) && (th < h))); bool isTiled = (tw>0 && th>0); // Can be a single tile (no strip info) for (auto key : prefixValues) { if(isTiled) { addValue(key + ".is_tiled", "true"); } else { addValue(key+".is_tiled", "false"); } } } // std::cout << "______________________________________________\n" // << m_tags // << "_______________________________________________\n"; str->clear(); str->seekg(offset); } void ossim::TiffHandlerState::loadCurrentDirectory(TIFF* tiffPtr) { if(tiffPtr) { loadDirectory(tiffPtr, TIFFCurrentDirectory(tiffPtr)); } } void ossim::TiffHandlerState::loadDirectory(TIFF* tiffPtr, ossim_uint32 directory) { ossim_uint32 imageWidth=0; ossim_uint32 imageLength=0; // ossim_int32 readMethod=0; ossim_uint16 planarConfig=0; ossim_uint16 photometric=0; ossim_uint32 rowsPerStrip=0; ossim_uint32 imageTileWidth=0; ossim_uint32 imageTileLength=0; // ossim_uint32 imageDirectoryList=0; ossim_int32 compressionType=0; ossim_uint32 subFileType=0; ossim_uint16 bitsPerSample=0; ossim_uint16 samplesPerPixel=0; ossim_uint16 sampleFormatUnit=0; ossim_float64 sampleValue=0; ossim_uint16 sampleUintValue = 0; ossim_int32 numberOfDirectories = TIFFNumberOfDirectories(tiffPtr); addValue("number_of_directories", ossimString::toString(numberOfDirectories)); if(TIFFCurrentDirectory(tiffPtr) != directory) { if(!TIFFSetDirectory(tiffPtr, directory)) { return; } } ossimString dirPrefix = "tiff.image"+ossimString::toString(directory)+"."; if(TIFFGetField(tiffPtr, TIFFTAG_COMPRESSION, &compressionType)) { addValue(dirPrefix+"compression", ossimString::toString(compressionType)); } if( TIFFGetField(tiffPtr, TIFFTAG_BITSPERSAMPLE, &bitsPerSample) ) { addValue(dirPrefix+"bits_per_sample", ossimString::toString(bitsPerSample)); } if( TIFFGetField(tiffPtr, TIFFTAG_SAMPLESPERPIXEL, &samplesPerPixel ) ) { addValue(dirPrefix+"samples_per_pixel", ossimString::toString(samplesPerPixel)); } if ( TIFFGetField( tiffPtr, TIFFTAG_SAMPLEFORMAT, &sampleFormatUnit ) ) { addValue(dirPrefix+"sample_format", ossimString::toString(sampleFormatUnit)); } if (TIFFGetField(tiffPtr, TIFFTAG_SMAXSAMPLEVALUE, &sampleValue ) ) { addValue(dirPrefix+"max_sample_value", ossimString::toString(sampleValue)); } else { if(TIFFGetField( tiffPtr, TIFFTAG_MAXSAMPLEVALUE, &sampleUintValue)) { addValue(dirPrefix+"max_sample_value", ossimString::toString(sampleUintValue)); } } if ( TIFFGetField( tiffPtr, TIFFTAG_SMINSAMPLEVALUE, &sampleValue ) ) { addValue(dirPrefix+"min_sample_value", ossimString::toString(sampleValue)); } else { if(TIFFGetField( tiffPtr, TIFFTAG_MINSAMPLEVALUE, &sampleUintValue)) { addValue(dirPrefix+"min_sample_value", ossimString::toString(sampleUintValue)); } } // lines: if ( TIFFGetField( tiffPtr, TIFFTAG_IMAGELENGTH, &imageLength ) ) { addValue(dirPrefix+"image_length", ossimString::toString(imageLength)); } // samples: if ( TIFFGetField( tiffPtr, TIFFTAG_IMAGEWIDTH, &imageWidth ) ) { addValue(dirPrefix+"image_width", ossimString::toString(imageWidth)); } if (TIFFGetField(tiffPtr, TIFFTAG_SUBFILETYPE , &subFileType ) ) { addValue(dirPrefix+"sub_file_type", ossimString::toString(subFileType)); } if( TIFFGetField( tiffPtr, TIFFTAG_PLANARCONFIG, &planarConfig ) ) { addValue(dirPrefix+"planar_configuration", ossimString::toString(planarConfig)); } if( TIFFGetField( tiffPtr, TIFFTAG_PHOTOMETRIC, &photometric ) ) { addValue(dirPrefix + "photo_interpretation", ossimString::toString(photometric)); } // Check for palette. ossim_uint16* red; ossim_uint16* green; ossim_uint16* blue; if(TIFFGetField(tiffPtr, TIFFTAG_COLORMAP, &red, &green, &blue)) { if(bitsPerSample) { saveColorMap(dirPrefix, red, green, blue, 1<UOMAngle)); } if (!exists(dirPrefix + "linear_units")) { loadedGeotiff = true; addValue(dirPrefix + "linear_units", ossimString::toString(defs->UOMLength)); } if (!exists(dirPrefix + "datum_code")) { loadedGeotiff = true; addValue(dirPrefix + "datum_code", ossimString::toString(defs->Datum)); } if (!exists(dirPrefix + "pcs_code")) { loadedGeotiff = true; addValue(dirPrefix + "pcs_code", ossimString::toString(defs->PCS)); } if (!exists(dirPrefix + "gcs_code")) { loadedGeotiff = true; addValue(dirPrefix + "gcs_code", ossimString::toString(defs->GCS)); } if (!exists(dirPrefix + "model_type")) { loadedGeotiff = true; addValue(dirPrefix + "model_type", ossimString::toString(defs->Model)); } GTIFFreeDefn(defs); } #endif addValue(dirPrefix+"is_geotiff", ossimString::toString(loadedGeotiff)); GTIFFree(gtif); } bool ossim::TiffHandlerState::isDigitalGlobe() const { ossimString value; bool result = false; if(getValue(value, "tiff.is_digital_globe")) { result = value.toBool(); } return result; } bool ossim::TiffHandlerState::isReduced(ossim_uint32 directory)const { // return getSubFileType(directory) & FILETYPE_REDUCEDIMAGE; return getSubFileType(directory) == FILETYPE_REDUCEDIMAGE; } bool ossim::TiffHandlerState::isMask(ossim_uint32 directory)const { //--- // NOTE: // sub_file_type of 5(bit mask) from cloud optimized geotiff(COG) sample // is not in tiff.h yet. Not sure if it's standard yet. drb - 20211109 //--- // return getSubFileType(directory) & FILETYPE_MASK; ossim_int32 sub_file_type = getSubFileType(directory); return (sub_file_type == FILETYPE_MASK) || (sub_file_type == 5); } bool ossim::TiffHandlerState::isPage(ossim_uint32 directory)const { // return getSubFileType(directory) & FILETYPE_PAGE; return getSubFileType(directory) == FILETYPE_PAGE; } bool ossim::TiffHandlerState::isTiled(ossim_uint32 directory)const { return checkBool(directory, "is_tiled"); } void ossim::TiffHandlerState::convertArrayToStringList(ossimString& result, double* doubleArray, ossim_int32 doubleArraySize)const { ossim_int32 idx = 0; result = ""; if(doubleArray && (doubleArraySize > 0)) { // ossim_int32 precision = 20; std::ostringstream doubleArrayStream; doubleArrayStream << "("; for(idx = 0; idx < doubleArraySize-1;++idx) { doubleArrayStream << ossimString::toString(doubleArray[idx],20) << ","; } doubleArrayStream << ossimString::toString(doubleArray[idx],20) << ")"; result = doubleArrayStream.str(); } } ossim_int32 ossim::TiffHandlerState::getModelType(ossim_int32 directory)const { ossimString tempStr; ossim_int32 result = 0; if (!getValue(tempStr, directory, "model_type")) { tempStr = "unknown"; } if (tempStr == "geographic") { result = ModelTypeGeographic; } else if (tempStr == "projected") { result = ModelTypeProjected; } else if (tempStr == "geocentric") { result = ModelTypeGeocentric; } return result; } ossim_int32 ossim::TiffHandlerState::getAngularUnits(ossim_int32 directory)const { return getInt32Value("angular_units", directory); } ossim_int32 ossim::TiffHandlerState::getLinearUnits(ossim_int32 directory)const { return getInt32Value("linear_units", directory); } ossim_int32 ossim::TiffHandlerState::getDatumCode(ossim_int32 directory)const { return getInt32Value("datum_code", directory); } ossim_int32 ossim::TiffHandlerState::getPcsCode(ossim_int32 directory)const { return getInt32Value("pcs_code", directory); } ossim_int32 ossim::TiffHandlerState::getGcsCode(ossim_int32 directory)const { return getInt32Value("gcs_code", directory); } ossim_int32 ossim::TiffHandlerState::getInt32Value(const ossimString& key, ossim_int32 directory)const { ossimString tempStr; if(getValue(tempStr, directory, key)) { return tempStr.toInt32(); } return ossimGeoTiff::UNDEFINED; } ossim_float64 ossim::TiffHandlerState::getDoubleValue(const ossimString& key, ossim_int32 directory)const { ossimString tempStr; if(getValue(tempStr, directory, key)) { return tempStr.toDouble(); } return ossim::nan(); } ossim_float64 ossim::TiffHandlerState::getOriginLat(ossim_int32 directory)const { return getDoubleValue("origin_lat", directory); } ossim_float64 ossim::TiffHandlerState::getOriginLon(ossim_int32 directory)const { return getDoubleValue("origin_lon", directory); } ossim_float64 ossim::TiffHandlerState::getStandardParallel1(ossim_int32 directory)const { return getDoubleValue("std_parallel_1", directory); } ossim_float64 ossim::TiffHandlerState::getStandardParallel2(ossim_int32 directory)const { return getDoubleValue("std_parallel_2", directory); } ossim_float64 ossim::TiffHandlerState::getFalseEasting(ossim_int32 directory)const { return getDoubleValue("false_easting", directory); } ossim_float64 ossim::TiffHandlerState::getFalseNorthing(ossim_int32 directory)const { return getDoubleValue("false_northing", directory); } ossim_float64 ossim::TiffHandlerState::getScaleFactor(ossim_int32 directory)const { return getDoubleValue("scale_factor", directory); } ossim_int32 ossim::TiffHandlerState::getCompressionType(ossim_int32 directory) const { ossim_int32 result = 0; ossimString tempValue; if (getValue(tempValue, directory, "compression")) { result = tempValue.toInt32(); } return result; } ossim_uint16 ossim::TiffHandlerState::getBitsPerSample(ossim_int32 directory) const { ossim_uint16 result = 8; ossimString tempValue; if (getValue(tempValue, directory, "bits_per_sample")) { result = tempValue.toUInt16(); } return result; } ossim_uint16 ossim::TiffHandlerState::getSamplesPerPixel(ossim_int32 directory) const { ossim_uint16 result = 0; ossimString tempValue; if (getValue(tempValue, directory, "samples_per_pixel")) { result = tempValue.toUInt16(); } return result; } ossim_uint16 ossim::TiffHandlerState::getSampleFormat(ossim_int32 directory) const { ossim_uint16 result = 1; ossimString tempValue; if (getValue(tempValue, directory, "sample_format")) { result = tempValue.toUInt16(); } return result; } bool ossim::TiffHandlerState::getMinSampleValue(ossim_float64 &minSampleValue, ossim_int32 directory)const { bool result = false; ossimString tempValue; if (getValue(tempValue, directory, "min_sample_value")) { minSampleValue = tempValue.toFloat64(); result = true; } else if (getValue(tempValue, directory, "smin_sample_value")) { minSampleValue = tempValue.toFloat64(); result = true; } return result; } bool ossim::TiffHandlerState::getMaxSampleValue(ossim_float64 &maxSampleValue, ossim_int32 directory)const { bool result = false; ossimString tempValue; if (getValue(tempValue, directory, "max_sample_value")) { maxSampleValue = tempValue.toFloat64(); result = true; } else if (getValue(tempValue, directory, "smax_sample_value")) { maxSampleValue = tempValue.toFloat64(); result = true; } return result; } ossim_uint32 ossim::TiffHandlerState::getRowsPerStrip(ossim_int32 directory) const { ossim_uint32 result = 0; ossimString tempValue; if(getValue(tempValue, directory, "rows_per_strip")) { result = tempValue.toUInt32(); } return result; } bool ossim::TiffHandlerState::hasColorMap(ossim_int32 directory)const { return exists(directory, "colormap"); } #if 0 /* Overloaded methods for int32 dir not called in core. */ bool ossim::TiffHandlerState::isReduced(ossim_int32 directory) const { return getSubFileType(directory) == FILETYPE_REDUCEDIMAGE; } bool ossim::TiffHandlerState::isPage(ossim_int32 directory) const { return getSubFileType(directory) == FILETYPE_PAGE; } bool ossim::TiffHandlerState::isMask(ossim_int32 directory) const { return getSubFileType(directory) == FILETYPE_MASK; } #endif ossim_int32 ossim::TiffHandlerState::getSubFileType(ossim_int32 directory) const { ossim_int32 result = 0; ossimString tempValue; if (getValue(tempValue, directory, "sub_file_type")) { result = tempValue.toInt32(); } return result; } ossim_uint32 ossim::TiffHandlerState::getNumberOfDirectories() const { ossim_uint32 result = 0; ossimString tempValue; if(getValue(tempValue, "tiff.number_of_directories")) { result = tempValue.toUInt32(); } return result; } bool ossim::TiffHandlerState::getColorMap(std::vector &red, std::vector &green, std::vector &blue, ossim_int32 directory) const { ossimString tempStr; red.clear(); green.clear(); blue.clear(); bool result = false; if (getValue(tempStr, directory, "colormap")) { std::vector values; ossim::toSimpleVector(values, "("+tempStr.substitute(" ", ",", true)+")"); ossim_uint32 offset = 0; if(values.size() == 768) { offset = 256; } else if (values.size() == 196608) { offset = 65536; } if(offset) { ossim_uint16 *valuesPtr = &values.front(); red = std::vector(valuesPtr, (valuesPtr + offset)); valuesPtr += offset; green = std::vector(valuesPtr, (valuesPtr + offset)); valuesPtr += offset; blue = std::vector(valuesPtr, (valuesPtr + offset)); result = true; } } return result; } ossim_int32 ossim::TiffHandlerState::getPlanarConfig(ossim_int32 directory) const { ossimString tempStr; ossim_int32 result = 0; if (getValue(tempStr, directory, "planar_configuration")) { if (tempStr.contains("separate")) { result = PLANARCONFIG_SEPARATE; } else if(tempStr.contains("contig")) { result = PLANARCONFIG_CONTIG; } } return result; } ossim_int32 ossim::TiffHandlerState::getRasterType(ossim_int32 directory) const { ossimString tempStr; ossimPixelType result = OSSIM_PIXEL_IS_POINT; if (getValue(tempStr, directory, "raster_type")) { if (tempStr.contains("area")) { result = OSSIM_PIXEL_IS_AREA; } } return result; } ossim_int32 ossim::TiffHandlerState::getPhotoInterpretation(ossim_int32 directory) const { ossimString tempStr; ossim_int32 result = 0; if (getValue(tempStr, directory, "photo_interpretation")) { if (tempStr.contains("MINISWHITE")) { result = PHOTOMETRIC_MINISWHITE; } else if (tempStr.contains("MINISBLACK")) { result = PHOTOMETRIC_MINISBLACK; } else if (tempStr.contains("RGB")) { result = PHOTOMETRIC_RGB; } else if (tempStr.contains("PALETTE")) { result = PHOTOMETRIC_PALETTE; } else if (tempStr.contains("MASK")) { result = PHOTOMETRIC_MASK; } else if (tempStr.contains("SEPARATED")) { result = PHOTOMETRIC_SEPARATED; } else if (tempStr.contains("YCBCR")) { result = PHOTOMETRIC_YCBCR; } else if (tempStr.contains("CIELAB")) { result = PHOTOMETRIC_CIELAB; } else if (tempStr.contains("ICCLAB")) { result = PHOTOMETRIC_ICCLAB; } else if (tempStr.contains("ITULAB")) { result = PHOTOMETRIC_ITULAB; } else if (tempStr.contains("LOGL")) { result = PHOTOMETRIC_LOGL; } else if (tempStr.contains("LOGLUV")) { result = PHOTOMETRIC_LOGLUV; } } return result; } ossim_int64 ossim::TiffHandlerState::getTileLength(ossim_int32 directory) const { ossimString tempStr; ossim_int64 result = 0; if (getValue(tempStr, directory, "tile_length")) { result = tempStr.toInt64(); } return result; } ossim_int64 ossim::TiffHandlerState::getImageLength(ossim_int32 directory) const { ossimString tempStr; ossim_int64 result = 0; if (getValue(tempStr, directory, "image_length")) { result = tempStr.toInt64(); } return result; } ossim_int64 ossim::TiffHandlerState::getTileWidth(ossim_int32 directory) const { ossimString tempStr; ossim_int64 result = 0; if (getValue(tempStr, directory, "tile_width")) { result = tempStr.toInt64(); } return result; } ossim_int64 ossim::TiffHandlerState::getImageWidth(ossim_int32 directory) const { ossimString tempStr; ossim_int64 result = 0; if (getValue(tempStr, directory, "image_width")) { result = tempStr.toInt64(); } return result; } bool ossim::TiffHandlerState::getDoubleArray(std::vector& result, ossim_int32 directory, const ossimString& key)const { ossimString tempStr; if(getValue(tempStr, directory, key)) { if(!tempStr.empty()) { tempStr=tempStr.substitute(" ", ",", true); if(!toSimpleVector(result, "("+tempStr+")")) { result.clear(); } tempStr=""; } } return !result.empty(); } bool ossim::TiffHandlerState::getGeoDoubleParams(std::vector& result, ossim_int32 directory)const { return getDoubleArray(result, directory, "geo_double_params"); } bool ossim::TiffHandlerState::getGeoPixelScale(std::vector& result, ossim_int32 directory)const { return getDoubleArray(result, directory, "model_pixel_scale"); } bool ossim::TiffHandlerState::getGeoTiePoints(std::vector& result, ossim_int32 directory)const { return getDoubleArray(result, directory, "model_tie_point"); } bool ossim::TiffHandlerState::getImageModelTransform (std::vector& result, ossim_int32 directory)const { return getDoubleArray(result, directory, "model_transform"); } bool ossim::TiffHandlerState::getCitation(ossimString &citation, ossim_int32 directory) const { bool result = true; if (!getValue(citation, directory, "citation")) { result = false; } return result; } bool ossim::TiffHandlerState::getCopyright(ossimString ©right, ossim_int32 directory) const { bool result = true; if (!getValue(copyright, directory, "copyright")) { result = false; } return result; } bool ossim::TiffHandlerState::load(const ossimKeywordlist& kwl, const ossimString& prefix) { bool result = ossim::ImageHandlerState::load(kwl, prefix); m_tags.clear(); kwl.extractKeysThatMatch(m_tags, "^("+prefix+"dir[0-9]+)"); if(!prefix.empty()) { m_tags.stripPrefixFromAll("^("+prefix+")"); } ossimString numberOfDirectories = kwl.find(prefix, "number_of_directories"); if(!numberOfDirectories.empty()) m_tags.add("number_of_directories", numberOfDirectories, true); return result; } bool ossim::TiffHandlerState::save(ossimKeywordlist& kwl, const ossimString& prefix)const { bool result = ossim::ImageHandlerState::save(kwl, prefix); kwl.add(prefix.c_str(), m_tags); return result; }