diff --git a/bundle.json b/bundle.json index 7e98c3b70d0c7f61f082eb89eed62499ee1fff3d..f0be7de8ddfc4dae636074debeb216a55e717d8b 100644 --- a/bundle.json +++ b/bundle.json @@ -73,7 +73,8 @@ "sub_component": [ "//foundation/multimedia/image_framework:image_framework", "//foundation/multimedia/image_framework:plugins", - "//foundation/multimedia/image_framework/frameworks/kits/ani:image_framework_ani" + "//foundation/multimedia/image_framework/frameworks/kits/taihe:image_framework_taihe", + "//foundation/multimedia/image_framework/frameworks/kits/taihe:image_framework_taihe_gen_only" ], "inner_kits": [ { @@ -201,6 +202,23 @@ }, "name": "//foundation/multimedia/image_framework/frameworks/kits/ani:image_ani" }, + { + "name": "//foundation/multimedia/image_framework/frameworks/kits/taihe:copy_image_taihe" + }, + { + "header": { + "header_base": "//foundation/multimedia/image_framework/frameworks/kits/taihe/include/", + "header_files": [ + "image_source_taihe_ani.h", + "image_taihe.h", + "picture_taihe.h", + "picture_taihe_ani.h", + "pixel_map_taihe.h", + "pixel_map_taihe_ani.h" + ] + }, + "name": "//foundation/multimedia/image_framework/frameworks/kits/taihe:image_taihe" + }, { "header": { "header_base": "//foundation/multimedia/image_framework/interfaces/kits/native/include/", diff --git a/frameworks/innerkitsimpl/accessor/include/exif_metadata_formatter.h b/frameworks/innerkitsimpl/accessor/include/exif_metadata_formatter.h index 020d7febcc55dcad9743cd624e1e788be76ea479..5333e5fda73d47b67f211e0947eb06b123446243 100644 --- a/frameworks/innerkitsimpl/accessor/include/exif_metadata_formatter.h +++ b/frameworks/innerkitsimpl/accessor/include/exif_metadata_formatter.h @@ -31,6 +31,8 @@ using ValueFormatDelegate = std::pair Format(const std::string &keyName, const std::string &value); static int32_t Validate(const std::string &keyName, const std::string &value); static bool IsModifyAllowed(const std::string &keyName); @@ -40,6 +42,12 @@ public: static bool IsSensitiveInfo(const std::string &keyName); private: + ExifMetadatFormatter(); + void InitDelegates(); + void InitValueRangeValidateConfig(); + void InitValueFormatConvertConfig(); + void InitValueTemplateConfig(); + static int32_t ValidateValueRange(const std::string &keyName, const std::string &value); static void ConvertRangeValue(const std::string &keyName, std::string &value); static void ExtractValue(const std::string &keyName, std::string &value); @@ -73,43 +81,43 @@ private: static std::string GetFractionFromStr(const std::string &decimal, bool &isOutRange); static bool ValidDecimalRationalFormat(std::string &value); static bool ValidConvertRationalFormat(std::string &value); - static ValueFormatDelegate doubleIntToOneRationalWithComma; - static ValueFormatDelegate doubleIntWithBlank; - static ValueFormatDelegate doubleIntWithComma; - static ValueFormatDelegate doubleValueToRational; - static ValueFormatDelegate tribleIntWithBlank; - static ValueFormatDelegate tribleIntWithComma; - static ValueFormatDelegate fourIntWithBlank; - static ValueFormatDelegate fourIntWithComma; - static ValueFormatDelegate singleInt; - static ValueFormatDelegate singleRational; - static ValueFormatDelegate singleIntToRational; - static ValueFormatDelegate singleDecimalToRational; - static ValueFormatDelegate tribleRationalWithBlank; - static ValueFormatDelegate tribleIntToRationalWithBlank; - static ValueFormatDelegate tribleIntToRationalWithComma; - static ValueFormatDelegate tribleDecimalToRationalWithBlank; - static ValueFormatDelegate tribleDecimalToRatiionalWithComma; - static ValueFormatDelegate tribleMixToRationalWithComma; - static ValueFormatDelegate fourRationalWithBlank; - static ValueFormatDelegate fourIntToRationalWithBlank; - static ValueFormatDelegate fourIntToRationalWithComma; - static ValueFormatDelegate decimal4Ratiional4; - static ValueFormatDelegate fourDecimalToRationalWithComma; - static ValueFormatDelegate dateTimeValidation; - static ValueFormatDelegate dateValidation; - static ValueFormatDelegate tribleIntToRationalWithColon; - static ValueFormatDelegate fourIntWithDot; - static ValueFormatDelegate fourDecimalToRationalWithBlank; - static ValueFormatDelegate sixDecimalToRationalWithBlank; - static ValueFormatDelegate sixDecimalToRationalWithComma; - static ValueFormatDelegate timeStamp; - static ValueFormatDelegate version; - static ValueFormatDelegate channel; - static std::multimap valueFormatConvertConfig; - static std::multimap valueFormatValidateConfig; - static std::multimap valueTemplateConfig; - static std::map> valueRangeValidateConfig; + ValueFormatDelegate doubleIntToOneRationalWithComma_; + ValueFormatDelegate doubleIntWithBlank_; + ValueFormatDelegate doubleIntWithComma_; + ValueFormatDelegate doubleValueToRational_; + ValueFormatDelegate tribleIntWithBlank_; + ValueFormatDelegate tribleIntWithComma_; + ValueFormatDelegate fourIntWithBlank_; + ValueFormatDelegate fourIntWithComma_; + ValueFormatDelegate singleInt_; + ValueFormatDelegate singleRational_; + ValueFormatDelegate singleIntToRational_; + ValueFormatDelegate singleDecimalToRational_; + ValueFormatDelegate tribleRationalWithBlank_; + ValueFormatDelegate tribleIntToRationalWithBlank_; + ValueFormatDelegate tribleIntToRationalWithComma_; + ValueFormatDelegate tribleDecimalToRationalWithBlank_; + ValueFormatDelegate tribleDecimalToRatiionalWithComma_; + ValueFormatDelegate tribleMixToRationalWithComma_; + ValueFormatDelegate fourRationalWithBlank_; + ValueFormatDelegate fourIntToRationalWithBlank_; + ValueFormatDelegate fourIntToRationalWithComma_; + ValueFormatDelegate decimal4Ratiional4_; + ValueFormatDelegate fourDecimalToRationalWithComma_; + ValueFormatDelegate dateTimeValidation_; + ValueFormatDelegate dateValidation_; + ValueFormatDelegate tribleIntToRationalWithColon_; + ValueFormatDelegate fourIntWithDot_; + ValueFormatDelegate fourDecimalToRationalWithBlank_; + ValueFormatDelegate sixDecimalToRationalWithBlank_; + ValueFormatDelegate sixDecimalToRationalWithComma_; + ValueFormatDelegate timeStamp_; + ValueFormatDelegate version_; + ValueFormatDelegate channel_; + std::multimap valueFormatConvertConfig_; + std::multimap valueFormatValidateConfig_; + std::multimap valueTemplateConfig_; + std::map> valueRangeValidateConfig_; }; } // namespace Media } // namespace OHOS diff --git a/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp b/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp index afbec5d3a30f99201631cca924efaa9d90366e6f..f1c4b964b3249325a9184e4be919266124b66877 100644 --- a/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp +++ b/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp @@ -544,50 +544,276 @@ constexpr TagDetails exifSensitivityType[] = { {7, "Standard output sensitivity (SOS) and recommended exposure index (REI) and ISO speed"}, }; +ExifMetadatFormatter &ExifMetadatFormatter::GetInstance() +{ + static ExifMetadatFormatter instance; + return instance; +} + +ExifMetadatFormatter::ExifMetadatFormatter() +{ + InitDelegates(); + InitValueRangeValidateConfig(); + InitValueFormatConvertConfig(); + InitValueTemplateConfig(); +} + // configuratioin for value range validation. For example GPSLatitudeRef the value must be 'N' or 'S'. -std::map> ExifMetadatFormatter::valueRangeValidateConfig = { - { "Orientation", std::make_tuple(exifOrientation, std::size(exifOrientation)) }, - { "GPSLatitudeRef", std::make_tuple(exifGPSLatitudeRef, std::size(exifGPSLatitudeRef)) }, - { "GPSDestLatitudeRef", std::make_tuple(exifGPSLatitudeRef, std::size(exifGPSLatitudeRef)) }, - { "GPSLongitudeRef", std::make_tuple(exifGPSLongitudeRef, std::size(exifGPSLongitudeRef)) }, - { "GPSDestLongitudeRef", std::make_tuple(exifGPSLongitudeRef, std::size(exifGPSLongitudeRef)) }, - { "WhiteBalance", std::make_tuple(exifWhiteBalance, std::size(exifWhiteBalance)) }, - { "Flash", std::make_tuple(exifFlash, std::size(exifFlash)) }, - { "LightSource", std::make_tuple(exifLightSource, std::size(exifLightSource)) }, - { "MeteringMode", std::make_tuple(exifMeteringMode, std::size(exifMeteringMode)) }, - { "SceneType", std::make_tuple(exifSceneType, std::size(exifSceneType)) }, - { "Compression", std::make_tuple(exifCompression, std::size(exifCompression)) }, - { "PhotometricInterpretation", - std::make_tuple(exifPhotometricInterpretation, std::size(exifPhotometricInterpretation)) }, - { "PlanarConfiguration", std::make_tuple(exifPlanarConfiguration, std::size(exifPlanarConfiguration)) }, - { "ResolutionUnit", std::make_tuple(exifUnit, std::size(exifUnit)) }, - { "YCbCrPositioning", std::make_tuple(exifYCbCrPositioning, std::size(exifYCbCrPositioning)) }, - { "ExposureProgram", std::make_tuple(exifExposureProgram, std::size(exifExposureProgram)) }, - { "ColorSpace", std::make_tuple(exifColorSpace, std::size(exifColorSpace)) }, - { "FocalPlaneResolutionUnit", std::make_tuple(exifUnit, std::size(exifUnit)) }, - { "SensingMethod", std::make_tuple(tiffSensingMethod, std::size(tiffSensingMethod)) }, - { "CustomRendered", std::make_tuple(exifCustomRendered, std::size(exifCustomRendered)) }, - { "ExposureMode", std::make_tuple(exifExposureMode, std::size(exifExposureMode)) }, - { "SceneCaptureType", std::make_tuple(exifSceneCaptureType, std::size(exifSceneCaptureType)) }, - { "GainControl", std::make_tuple(exifGainControl, std::size(exifGainControl)) }, - { "Contrast", std::make_tuple(exifNormalSoftHard, std::size(exifNormalSoftHard)) }, - { "Saturation", std::make_tuple(exifSaturation, std::size(exifSaturation)) }, - { "Sharpness", std::make_tuple(exifNormalSoftHard, std::size(exifNormalSoftHard)) }, - { "SubjectDistanceRange", std::make_tuple(exifSubjectDistanceRange, std::size(exifSubjectDistanceRange)) }, - { "GPSAltitudeRef", std::make_tuple(exifGPSAltitudeRef, std::size(exifGPSAltitudeRef)) }, - { "NewSubfileType", std::make_tuple(exifNewSubfileType, std::size(exifNewSubfileType)) }, - { "SubfileType", std::make_tuple(exifSubfileType, std::size(exifSubfileType)) }, - { "GPSStatus", std::make_tuple(exifGpsStatus, std::size(exifGpsStatus)) }, - { "GPSMeasureMode", std::make_tuple(exifGPSMeasureMode, std::size(exifGPSMeasureMode)) }, - { "GPSSpeedRef", std::make_tuple(exifGPSSpeedRef, std::size(exifGPSSpeedRef)) }, - { "GPSImgDirectionRef", std::make_tuple(exifGPSDirRef, std::size(exifGPSDirRef)) }, - { "GPSTrackRef", std::make_tuple(exifGPSDirRef, std::size(exifGPSDirRef)) }, - { "GPSDestBearingRef", std::make_tuple(exifGPSDirRef, std::size(exifGPSDirRef)) }, - { "GPSDestDistanceRef", std::make_tuple(exifGPSDestDistanceRef, std::size(exifGPSDestDistanceRef)) }, - { "GPSDifferential", std::make_tuple(exifGPSDifferential, std::size(exifGPSDifferential)) }, - { "CompositeImage", std::make_tuple(exifCompositeImage, std::size(exifCompositeImage)) }, - { "SensitivityType", std::make_tuple(exifSensitivityType, std::size(exifSensitivityType)) }, -}; +void ExifMetadatFormatter::InitValueRangeValidateConfig() +{ + valueRangeValidateConfig_ = std::map>{ + { "Orientation", std::make_tuple(exifOrientation, std::size(exifOrientation)) }, + { "GPSLatitudeRef", std::make_tuple(exifGPSLatitudeRef, std::size(exifGPSLatitudeRef)) }, + { "GPSDestLatitudeRef", std::make_tuple(exifGPSLatitudeRef, std::size(exifGPSLatitudeRef)) }, + { "GPSLongitudeRef", std::make_tuple(exifGPSLongitudeRef, std::size(exifGPSLongitudeRef)) }, + { "GPSDestLongitudeRef", std::make_tuple(exifGPSLongitudeRef, std::size(exifGPSLongitudeRef)) }, + { "WhiteBalance", std::make_tuple(exifWhiteBalance, std::size(exifWhiteBalance)) }, + { "Flash", std::make_tuple(exifFlash, std::size(exifFlash)) }, + { "LightSource", std::make_tuple(exifLightSource, std::size(exifLightSource)) }, + { "MeteringMode", std::make_tuple(exifMeteringMode, std::size(exifMeteringMode)) }, + { "SceneType", std::make_tuple(exifSceneType, std::size(exifSceneType)) }, + { "Compression", std::make_tuple(exifCompression, std::size(exifCompression)) }, + { "PhotometricInterpretation", + std::make_tuple(exifPhotometricInterpretation, std::size(exifPhotometricInterpretation)) }, + { "PlanarConfiguration", std::make_tuple(exifPlanarConfiguration, std::size(exifPlanarConfiguration)) }, + { "ResolutionUnit", std::make_tuple(exifUnit, std::size(exifUnit)) }, + { "YCbCrPositioning", std::make_tuple(exifYCbCrPositioning, std::size(exifYCbCrPositioning)) }, + { "ExposureProgram", std::make_tuple(exifExposureProgram, std::size(exifExposureProgram)) }, + { "ColorSpace", std::make_tuple(exifColorSpace, std::size(exifColorSpace)) }, + { "FocalPlaneResolutionUnit", std::make_tuple(exifUnit, std::size(exifUnit)) }, + { "SensingMethod", std::make_tuple(tiffSensingMethod, std::size(tiffSensingMethod)) }, + { "CustomRendered", std::make_tuple(exifCustomRendered, std::size(exifCustomRendered)) }, + { "ExposureMode", std::make_tuple(exifExposureMode, std::size(exifExposureMode)) }, + { "SceneCaptureType", std::make_tuple(exifSceneCaptureType, std::size(exifSceneCaptureType)) }, + { "GainControl", std::make_tuple(exifGainControl, std::size(exifGainControl)) }, + { "Contrast", std::make_tuple(exifNormalSoftHard, std::size(exifNormalSoftHard)) }, + { "Saturation", std::make_tuple(exifSaturation, std::size(exifSaturation)) }, + { "Sharpness", std::make_tuple(exifNormalSoftHard, std::size(exifNormalSoftHard)) }, + { "SubjectDistanceRange", std::make_tuple(exifSubjectDistanceRange, std::size(exifSubjectDistanceRange)) }, + { "GPSAltitudeRef", std::make_tuple(exifGPSAltitudeRef, std::size(exifGPSAltitudeRef)) }, + { "NewSubfileType", std::make_tuple(exifNewSubfileType, std::size(exifNewSubfileType)) }, + { "SubfileType", std::make_tuple(exifSubfileType, std::size(exifSubfileType)) }, + { "GPSStatus", std::make_tuple(exifGpsStatus, std::size(exifGpsStatus)) }, + { "GPSMeasureMode", std::make_tuple(exifGPSMeasureMode, std::size(exifGPSMeasureMode)) }, + { "GPSSpeedRef", std::make_tuple(exifGPSSpeedRef, std::size(exifGPSSpeedRef)) }, + { "GPSImgDirectionRef", std::make_tuple(exifGPSDirRef, std::size(exifGPSDirRef)) }, + { "GPSTrackRef", std::make_tuple(exifGPSDirRef, std::size(exifGPSDirRef)) }, + { "GPSDestBearingRef", std::make_tuple(exifGPSDirRef, std::size(exifGPSDirRef)) }, + { "GPSDestDistanceRef", std::make_tuple(exifGPSDestDistanceRef, std::size(exifGPSDestDistanceRef)) }, + { "GPSDifferential", std::make_tuple(exifGPSDifferential, std::size(exifGPSDifferential)) }, + { "CompositeImage", std::make_tuple(exifCompositeImage, std::size(exifCompositeImage)) }, + { "SensitivityType", std::make_tuple(exifSensitivityType, std::size(exifSensitivityType)) }, + }; +} + +// configuration for value format validation. For example BitPerSample the value format should be 9 9 9 or 9,9,9 +void ExifMetadatFormatter::InitValueFormatConvertConfig() +{ + valueFormatConvertConfig_ = { + {"BitsPerSample", tribleIntWithBlank_}, + {"BitsPerSample", tribleIntWithComma_}, + {"CompressedBitsPerPixel", singleRational_}, + {"CompressedBitsPerPixel", singleIntToRational_}, + {"CompressedBitsPerPixel", singleDecimalToRational_}, + {"GPSLatitude", doubleIntToOneRationalWithComma_}, + {"GPSLatitude", tribleRationalWithBlank_}, + {"GPSLatitude", tribleIntToRationalWithBlank_}, + {"GPSLatitude", tribleIntToRationalWithComma_}, + {"GPSLatitude", tribleMixToRationalWithComma_}, + {"GPSLongitude", doubleIntToOneRationalWithComma_}, + {"GPSLongitude", tribleRationalWithBlank_}, + {"GPSLongitude", tribleIntToRationalWithBlank_}, + {"GPSLongitude", tribleIntToRationalWithComma_}, + {"GPSLongitude", tribleMixToRationalWithComma_}, + {"ApertureValue", singleRational_}, + {"ApertureValue", singleIntToRational_}, + {"ApertureValue", singleDecimalToRational_}, + {"DateTimeOriginal", dateTimeValidation_}, + {"DateTimeOriginal", dateValidation_}, + {"DateTime", dateTimeValidation_}, + {"DateTime", dateValidation_}, + {"ExposureBiasValue", singleRational_}, + {"ExposureBiasValue", singleIntToRational_}, + {"ExposureBiasValue", singleDecimalToRational_}, + {"ExposureTime", singleRational_}, + {"ExposureTime", singleIntToRational_}, + {"ExposureTime", singleDecimalToRational_}, + {"FNumber", singleRational_}, + {"FNumber", singleIntToRational_}, + {"FNumber", singleDecimalToRational_}, + {"FocalLength", singleRational_}, + {"FocalLength", singleIntToRational_}, + {"FocalLength", singleDecimalToRational_}, + {"GPSTimeStamp", tribleRationalWithBlank_}, + {"GPSTimeStamp", tribleIntToRationalWithBlank_}, + {"GPSTimeStamp", tribleIntToRationalWithColon_}, + {"GPSTimeStamp", timeStamp_}, + {"GPSDateStamp", dateValidation_}, + {"XResolution", singleRational_}, + {"XResolution", singleIntToRational_}, + {"XResolution", singleDecimalToRational_}, + {"YResolution", singleRational_}, + {"YResolution", singleIntToRational_}, + {"YResolution", singleDecimalToRational_}, + {"WhitePoint", singleRational_}, + {"WhitePoint", singleIntToRational_}, + {"WhitePoint", singleDecimalToRational_}, + {"WhitePoint", doubleValueToRational_}, + {"PrimaryChromaticities", singleRational_}, + {"PrimaryChromaticities", singleIntToRational_}, + {"PrimaryChromaticities", singleDecimalToRational_}, + {"YCbCrCoefficients", tribleRationalWithBlank_}, + {"YCbCrCoefficients", tribleIntToRationalWithBlank_}, + {"YCbCrCoefficients", tribleIntToRationalWithComma_}, + {"YCbCrCoefficients", tribleDecimalToRationalWithBlank_}, + {"YCbCrCoefficients", tribleDecimalToRatiionalWithComma_}, + {"ReferenceBlackWhite", singleRational_}, + {"ReferenceBlackWhite", singleIntToRational_}, + {"ReferenceBlackWhite", singleDecimalToRational_}, + {"ReferenceBlackWhite", sixDecimalToRationalWithComma_}, + {"ShutterSpeedValue", singleRational_}, + {"ShutterSpeedValue", singleIntToRational_}, + {"ShutterSpeedValue", singleDecimalToRational_}, + {"BrightnessValue", singleRational_}, + {"BrightnessValue", singleIntToRational_}, + {"BrightnessValue", singleDecimalToRational_}, + {"MaxApertureValue", singleRational_}, + {"MaxApertureValue", singleIntToRational_}, + {"MaxApertureValue", singleDecimalToRational_}, + {"SubjectDistance", singleRational_}, + {"SubjectDistance", singleIntToRational_}, + {"SubjectDistance", singleDecimalToRational_}, + {"FlashEnergy", singleRational_}, + {"FlashEnergy", singleIntToRational_}, + {"FlashEnergy", singleDecimalToRational_}, + {"FocalPlaneXResolution", singleRational_}, + {"FocalPlaneXResolution", singleIntToRational_}, + {"FocalPlaneXResolution", singleDecimalToRational_}, + {"FocalPlaneYResolution", singleRational_}, + {"FocalPlaneYResolution", singleIntToRational_}, + {"FocalPlaneYResolution", singleDecimalToRational_}, + {"ExposureIndex", singleRational_}, + {"ExposureIndex", singleIntToRational_}, + {"ExposureIndex", singleDecimalToRational_}, + {"DigitalZoomRatio", singleRational_}, + {"DigitalZoomRatio", singleIntToRational_}, + {"DigitalZoomRatio", singleDecimalToRational_}, + {"GPSAltitude", singleRational_}, + {"GPSAltitude", singleIntToRational_}, + {"GPSAltitude", singleDecimalToRational_}, + {"GPSDOP", singleRational_}, + {"GPSDOP", singleIntToRational_}, + {"GPSDOP", singleDecimalToRational_}, + {"GPSSpeed", singleRational_}, + {"GPSSpeed", singleIntToRational_}, + {"GPSSpeed", singleDecimalToRational_}, + {"GPSTrack", singleRational_}, + {"GPSTrack", singleIntToRational_}, + {"GPSTrack", singleDecimalToRational_}, + {"GPSImgDirection", singleRational_}, + {"GPSImgDirection", singleIntToRational_}, + {"GPSImgDirection", singleDecimalToRational_}, + {"GPSDestLatitude", tribleRationalWithBlank_}, + {"GPSDestLatitude", tribleIntToRationalWithBlank_}, + {"GPSDestLatitude", tribleIntToRationalWithComma_}, + {"GPSDestLongitude", tribleRationalWithBlank_}, + {"GPSDestLongitude", tribleIntToRationalWithBlank_}, + {"GPSDestLongitude", tribleIntToRationalWithComma_}, + {"GPSDestBearing", singleRational_}, + {"GPSDestBearing", singleIntToRational_}, + {"GPSDestBearing", singleDecimalToRational_}, + {"GPSDestDistance", singleRational_}, + {"GPSDestDistance", singleIntToRational_}, + {"GPSDestDistance", singleDecimalToRational_}, + {"GPSVersionID", fourIntWithDot_}, + {"CompressedBitsPerPixel", singleRational_}, + {"CompressedBitsPerPixel", singleIntToRational_}, + {"CompressedBitsPerPixel", singleDecimalToRational_}, + {"DNGVersion", fourIntWithBlank_}, + {"DNGVersion", fourIntWithComma_}, + {"DefaultCropSize", doubleIntWithBlank_}, + {"DefaultCropSize", doubleIntWithComma_}, + {"Gamma", singleRational_}, + {"Gamma", singleIntToRational_}, + {"Gamma", singleDecimalToRational_}, + {"GPSHPositioningError", singleRational_}, + {"GPSHPositioningError", singleIntToRational_}, + {"GPSHPositioningError", singleDecimalToRational_}, + {"LensSpecification", fourRationalWithBlank_}, + {"LensSpecification", fourIntToRationalWithBlank_}, + {"LensSpecification", fourIntToRationalWithComma_}, + {"LensSpecification", fourDecimalToRationalWithBlank_}, + {"LensSpecification", fourDecimalToRationalWithComma_}, + {"ReferenceBlackWhite", sixDecimalToRationalWithBlank_}, + {"SubjectLocation", doubleIntWithBlank_}, + {"SubjectLocation", doubleIntWithComma_}, + {"ImageLength", singleInt_}, + {"ImageWidth", singleInt_}, + {"ISOSpeedRatings", singleInt_}, + {"StandardOutputSensitivity", singleInt_}, + {"RecommendedExposureIndex", singleInt_}, + {"ISOSpeed", singleInt_}, + {"PixelXDimension", singleInt_}, + {"PixelYDimension", singleInt_}, + {"FocalLengthIn35mmFilm", singleInt_}, + {"StripOffsets", singleInt_}, + {"SamplesPerPixel", singleInt_}, + {"RowsPerStrip", singleInt_}, + {"StripByteCounts", singleInt_}, + {"ExifVersion", singleInt_}, + {"ExifVersion", version_}, + {"ISOSpeedLatitudeyyy", singleInt_}, + {"ISOSpeedLatitudezzz", singleInt_}, + {"ComponentsConfiguration", singleInt_}, + {"ComponentsConfiguration", channel_}, + {"PhotographicSensitivity", singleInt_}, + {"FlashpixVersion", singleInt_}, + {"FlashpixVersion", version_}, + {"PhotoMode", singleInt_}, + {"JPEGProc", singleInt_}, + {"HwMnoteCaptureMode", singleInt_}, + {"HwMnoteIsXmageSupported", singleInt_}, + {"HwMnoteXmageMode", singleInt_}, + {"HwMnoteXmageLeft", singleInt_}, + {"HwMnoteXmageTop", singleInt_}, + {"HwMnoteXmageRight", singleInt_}, + {"HwMnoteXmageBottom", singleInt_}, + {"HwMnoteCloudEnhancementMode", singleInt_}, + {"HwMnoteAiEdit", singleInt_}, + {"DateTimeDigitized", dateTimeValidation_}, + {"DateTimeDigitized", dateValidation_}, + {"OffsetTime", dateTimeValidation_}, + {"OffsetTime", dateValidation_}, + {"SubjectArea", doubleIntWithBlank_}, + {"SubjectArea", doubleIntWithComma_}, + {"SourceImageNumberOfCompositeImage", doubleIntWithBlank_}, + {"SourceImageNumberOfCompositeImage", doubleIntWithComma_}, + {"YCbCrSubSampling", doubleIntWithBlank_}, + {"YCbCrSubSampling", doubleIntWithComma_}, + {"MovingPhotoVersion", singleInt_}, + {"MicroVideoPresentationTimestampUS", singleInt_}, + }; +} + +void ExifMetadatFormatter::InitValueTemplateConfig() +{ + valueTemplateConfig_ = { + {"ExposureTime", "(\\d+/\\d+) sec\\."}, + {"ExposureTime", "(\\d+\\.\\d+|\\d+) sec\\."}, + {"FNumber", "f/(\\d+\\.\\d+)"}, + {"ApertureValue", "(\\d+\\.\\d+) EV \\(f/\\d+\\.\\d+\\)"}, + {"ExposureBiasValue", "(\\d+\\.\\d+) EV"}, + {"FocalLength", "(\\d+\\.\\d+) mm"}, + {"ShutterSpeedValue", "(\\d+\\.\\d+) EV \\(\\d+/\\d+ sec\\.\\)"}, + {"BrightnessValue", "(\\d+\\.\\d+) EV \\(\\d+\\.\\d+ cd/m\\^\\d+\\)"}, + {"MaxApertureValue", "(\\d+\\.\\d+) EV \\(f/\\d+\\.\\d+\\)"}, + {"SubjectDistance", "(\\d+\\.\\d+) m"}, + {"SubjectArea", "\\(x,y\\) = \\((\\d+,\\d+)\\)"}, + {"ExifVersion", "Exif Version ([0-9]{1,2}\\.[0-9]{1,2})"}, + {"FlashpixVersion", "FlashPix Version ([0-9]{1,2}\\.[0-9]{1,2})"}, + {"Copyright", "^(.*) \\(Photographer\\) \\- \\[None\\] \\(Editor\\)$"}, + }; +} const size_t DECIMAL_BASE = 10; const std::string COMMA_REGEX("\\,"), COLON_REGEX("\\:"), DOT_REGEX("\\."); @@ -981,332 +1207,124 @@ bool ExifMetadatFormatter::ValidRegexWithChannelFormat(std::string &value, const return true; } -bool ExifMetadatFormatter::ValidRegexWithGpsOneRationalFormat(std::string &value, const std::string ®ex) +void ExifMetadatFormatter::InitDelegates() { - IMAGE_LOGD("validate gps with one rational."); - if (!ValidRegex(value, regex)) { - return false; - } - std::vector vec; - SplitStr(value, ",", vec); - if (vec.size() != GPS_DEGREE_SIZE) { - IMAGE_LOGD("Gps degree data size is invalid."); - return false; - } - value = vec[0] + "/" + vec[1] + " 0/1 0/1"; - return true; -} + singleInt_ = std::make_pair(ValidRegex, SINGLE_INT_REGEX); -ValueFormatDelegate ExifMetadatFormatter::singleInt = - std::make_pair(ExifMetadatFormatter::ValidRegex, SINGLE_INT_REGEX); + // regex validation for two integer like DefaultCropSize 9 9 the format is [0-9]+ [0-9]+ + doubleIntWithBlank_ = std::make_pair(ValidRegex, DOUBLE_INT_WITH_BLANK_REGEX); -// regex validation for two integer like DefaultCropSize 9 9 the format is [0-9]+ [0-9]+ -ValueFormatDelegate ExifMetadatFormatter::doubleIntWithBlank = - std::make_pair(ExifMetadatFormatter::ValidRegex, DOUBLE_INT_WITH_BLANK_REGEX); + // regex validation for two integer with comma like BitPerSample 9,9 the format is [0-9]+,[0-9]+,[0-9]+ + doubleIntWithComma_ = std::make_pair(ValidRegexWithComma, DOUBLE_INT_WITH_COMMA_REGEX); -// regex validation for two integer with comma like BitPerSample 9,9 the format is [0-9]+,[0-9]+,[0-9]+ -ValueFormatDelegate ExifMetadatFormatter::doubleIntWithComma = - std::make_pair(ExifMetadatFormatter::ValidRegexWithComma, DOUBLE_INT_WITH_COMMA_REGEX); + // regex validation for three integer like BitPerSample 9 9 9 the format is [0-9]+ [0-9]+ [0-9]+ + tribleIntWithBlank_ = std::make_pair(ValidRegex, TRIBLE_INT_WITH_BLANK_REGEX); -// regex validation for three integer like BitPerSample 9 9 9 the format is [0-9]+ [0-9]+ [0-9]+ -ValueFormatDelegate ExifMetadatFormatter::tribleIntWithBlank = - std::make_pair(ExifMetadatFormatter::ValidRegex, TRIBLE_INT_WITH_BLANK_REGEX); + // regex validation for three integer with comma like BitPerSample 9,9,0 the format is [0-9]+,[0-9]+,[0-9]+,[0-9]+ + tribleIntWithComma_ = std::make_pair(ValidRegexWithComma, TRIBLE_INT_WITH_COMMA_REGEX); -// regex validation for three integer with comma like BitPerSample 9,9,0 the format is [0-9]+,[0-9]+,[0-9]+,[0-9]+ -ValueFormatDelegate ExifMetadatFormatter::tribleIntWithComma = - std::make_pair(ExifMetadatFormatter::ValidRegexWithComma, TRIBLE_INT_WITH_COMMA_REGEX); + // regex validation for four integer like DNGVersion 9 9 9 9 the format is [0-9]+ [0-9]+ [0-9]+ [0-9]+ + fourIntWithBlank_ = std::make_pair(ValidRegex, FOUR_INT_WITH_BLANK_REGEX); -// regex validation for four integer like DNGVersion 9 9 9 9 the format is [0-9]+ [0-9]+ [0-9]+ [0-9]+ -ValueFormatDelegate ExifMetadatFormatter::fourIntWithBlank = - std::make_pair(ExifMetadatFormatter::ValidRegex, FOUR_INT_WITH_BLANK_REGEX); + // regex validation for four integer with comma like DNGVersion tag encodes the DNG four-tier version number + fourIntWithComma_ = std::make_pair(ValidRegexWithComma, FOUR_INT_WITH_COMMA_REGEX); -// regex validation for four integer with comma like DNGVersion tag encodes the DNG four-tier version number -ValueFormatDelegate ExifMetadatFormatter::fourIntWithComma = - std::make_pair(ExifMetadatFormatter::ValidRegexWithComma, FOUR_INT_WITH_COMMA_REGEX); + // regex validation for one rational like ApertureValue 4/1 the format is [0-9]+/[1-9][0-9] + singleRational_ = std::make_pair(ValidRegex, SINGLE_RATIONAL_REGEX); -// regex validation for one rational like ApertureValue 4/1 the format is [0-9]+/[1-9][0-9] -ValueFormatDelegate ExifMetadatFormatter::singleRational = - std::make_pair(ExifMetadatFormatter::ValidRegex, SINGLE_RATIONAL_REGEX); + // regex validation for integer and convert it to rational like ApertureValue 4 --> 4/1 + singleIntToRational_ = std::make_pair(ValidRegexWithRationalFormat, SINGLE_INT_REGEX); -// regex validation for integer and convert it to rational like ApertureValue 4 --> 4/1 -ValueFormatDelegate ExifMetadatFormatter::singleIntToRational = - std::make_pair(ExifMetadatFormatter::ValidRegexWithRationalFormat, SINGLE_INT_REGEX); + singleDecimalToRational_ = std::make_pair(ValidRegexWithDecimalRationalFormat, SINGLE_DECIMAL_REGEX); -ValueFormatDelegate ExifMetadatFormatter::singleDecimalToRational = - std::make_pair(ExifMetadatFormatter::ValidRegexWithDecimalRationalFormat, SINGLE_DECIMAL_REGEX); + doubleIntToOneRationalWithComma_ = std::make_pair(ValidRegexWithGpsOneRationalFormat, DOUBLE_INT_WITH_COMMA_REGEX); -ValueFormatDelegate ExifMetadatFormatter::doubleIntToOneRationalWithComma = - std::make_pair(ExifMetadatFormatter::ValidRegexWithGpsOneRationalFormat, DOUBLE_INT_WITH_COMMA_REGEX); + doubleValueToRational_ = std::make_pair(ValidRegxAndConvertRationalFormat, DOUBLE_VALUE_REGEX); -ValueFormatDelegate ExifMetadatFormatter::doubleValueToRational = - std::make_pair(ExifMetadatFormatter::ValidRegxAndConvertRationalFormat, DOUBLE_VALUE_REGEX); + // regex validation for three rational like GPSLatitude 39/1 54/1 20/1 + tribleRationalWithBlank_ = std::make_pair(ValidRegex, TRIBLE_RATIONAL_WITH_BLANK_REGEX); -// regex validation for three rational like GPSLatitude 39/1 54/1 20/1 -ValueFormatDelegate ExifMetadatFormatter::tribleRationalWithBlank = - std::make_pair(ExifMetadatFormatter::ValidRegex, TRIBLE_RATIONAL_WITH_BLANK_REGEX); + // regex validation for three integer and convert to three rational like GPSLatitude 39 54 20 --> 39/1 54/1 20/1 + tribleIntToRationalWithBlank_ = std::make_pair(ValidRegexWithRationalFormat, TRIBLE_INT_WITH_BLANK_REGEX); -// regex validation for three integer and convert to three rational like GPSLatitude 39 54 20 --> 39/1 54/1 20/1 -ValueFormatDelegate ExifMetadatFormatter::tribleIntToRationalWithBlank = - std::make_pair(ExifMetadatFormatter::ValidRegexWithRationalFormat, TRIBLE_INT_WITH_BLANK_REGEX); + // regex validation for three integer with comma like GPSLatitude 39,54,20 --> 39/1 54/1 20/1 + tribleIntToRationalWithComma_ = std::make_pair(ValidRegexWithCommaRationalFormat, TRIBLE_INT_WITH_COMMA_REGEX); -// regex validation for three integer with comma like GPSLatitude 39,54,20 --> 39/1 54/1 20/1 -ValueFormatDelegate ExifMetadatFormatter::tribleIntToRationalWithComma = - std::make_pair(ExifMetadatFormatter::ValidRegexWithCommaRationalFormat, TRIBLE_INT_WITH_COMMA_REGEX); + // regex validation for three decimal like YCbCrCoefficients 39.0 54 20.0 --> 39/1 54/1 20/1 + tribleDecimalToRationalWithBlank_ = + std::make_pair(ValidRegexWithDecimalRationalFormat, TRIBLE_DECIMAL_WITH_BLANK_REGEX); -// regex validation for three decimal like YCbCrCoefficients 39.0 54 20.0 --> 39/1 54/1 20/1 -ValueFormatDelegate ExifMetadatFormatter::tribleDecimalToRationalWithBlank = - std::make_pair(ExifMetadatFormatter::ValidRegexWithDecimalRationalFormat, TRIBLE_DECIMAL_WITH_BLANK_REGEX); + // regex validation for three decimal like YCbCrCoefficients 39.0,54,20.0 --> 39.0 54 20.0 --> 39/1 54/1 20/1 + tribleDecimalToRatiionalWithComma_ = + std::make_pair(ValidRegxWithCommaDecimalRationalFormat, TRIBLE_DECIMAL_WITH_COMMA_REGEX); -// regex validation for three decimal like YCbCrCoefficients 39.0,54,20.0 --> 39.0 54 20.0 --> 39/1 54/1 20/1 -ValueFormatDelegate ExifMetadatFormatter::tribleDecimalToRatiionalWithComma = - std::make_pair(ExifMetadatFormatter::ValidRegxWithCommaDecimalRationalFormat, TRIBLE_DECIMAL_WITH_COMMA_REGEX); + // regex validation for three decimal like GPS 10, 20, 20.123 --> 10 20 20.123 --> 10/1 20/1 20.123/1 + tribleMixToRationalWithComma_ = + std::make_pair(ValidRegxWithCommaDecimalRationalFormat, TRIBLE_MIX_WITH_COMMA_REGEX); -// regex validation for three decimal like GPS 10, 20, 20.123 --> 10 20 20.123 --> 10/1 20/1 20.123/1 -ValueFormatDelegate ExifMetadatFormatter::tribleMixToRationalWithComma = - std::make_pair(ExifMetadatFormatter::ValidRegxWithCommaDecimalRationalFormat, TRIBLE_MIX_WITH_COMMA_REGEX); + // regex validation for four rational like LensSpecification 1/1 3/2 1/1 2/1 + fourRationalWithBlank_ = std::make_pair(ValidRegex, FOUR_RATIONAL_WITH_BLANK_REGEX); -// regex validation for four rational like LensSpecification 1/1 3/2 1/1 2/1 -ValueFormatDelegate ExifMetadatFormatter::fourRationalWithBlank = - std::make_pair(ExifMetadatFormatter::ValidRegex, FOUR_RATIONAL_WITH_BLANK_REGEX); + // regex validation for four integer and convert to four rational like LensSpecification 1 3 1 2 --> 1/1 3/2 1/1 2/1 + fourIntToRationalWithBlank_ = std::make_pair(ValidRegexWithRationalFormat, FOUR_INT_WITH_BLANK_REGEX); -// regex validation for four integer and convert to four rational like LensSpecification 1 3 1 2 --> 1/1 3/2 1/1 2/1 -ValueFormatDelegate ExifMetadatFormatter::fourIntToRationalWithBlank = - std::make_pair(ExifMetadatFormatter::ValidRegexWithRationalFormat, FOUR_INT_WITH_BLANK_REGEX); + // regex validation for four integer like LensSpecification 1,3,1,2 --> 1/1 3/2 1/1 2/1 + fourIntToRationalWithComma_ = std::make_pair(ValidRegexWithCommaRationalFormat, FOUR_INT_WITH_COMMA_REGEX); -// regex validation for four integer like LensSpecification 1,3,1,2 --> 1/1 3/2 1/1 2/1 -ValueFormatDelegate ExifMetadatFormatter::fourIntToRationalWithComma = - std::make_pair(ExifMetadatFormatter::ValidRegexWithCommaRationalFormat, FOUR_INT_WITH_COMMA_REGEX); + // regex validation for four decimal like LensSpecification 1.0 3.0 1.0 2.0 --> 1/1 3/1 2/1 + fourDecimalToRationalWithBlank_ = + std::make_pair(ValidRegexWithDecimalRationalFormat, FOUR_DECIMAL_WITH_BLANK_REGEX); -// regex validation for four decimal like LensSpecification 1.0 3.0 1.0 2.0 --> 1/1 3/1 2/1 -ValueFormatDelegate ExifMetadatFormatter::fourDecimalToRationalWithBlank = - std::make_pair(ExifMetadatFormatter::ValidRegexWithDecimalRationalFormat, FOUR_DECIMAL_WITH_BLANK_REGEX); + // regex validation for four decimal like LensSpecification 1.0,3.0,1.0,2.0 --> 1/1 3/1 2/1 + fourDecimalToRationalWithComma_ = + std::make_pair(ValidRegxWithCommaDecimalRationalFormat, FOUR_DECIMAL_WITH_COMMA_REGEX); -// regex validation for four decimal like LensSpecification 1.0,3.0,1.0,2.0 --> 1/1 3/1 2/1 -ValueFormatDelegate ExifMetadatFormatter::fourDecimalToRationalWithComma = - std::make_pair(ExifMetadatFormatter::ValidRegxWithCommaDecimalRationalFormat, FOUR_DECIMAL_WITH_COMMA_REGEX); + // regex validation for datetime format like DateTimeOriginal 2022:06:02 15:51:34 + dateTimeValidation_ = std::make_pair(ValidRegex, DATETIME_REGEX); -// regex validation for datetime format like DateTimeOriginal 2022:06:02 15:51:34 -ValueFormatDelegate ExifMetadatFormatter::dateTimeValidation = - std::make_pair(ExifMetadatFormatter::ValidRegex, DATETIME_REGEX); + // regex validation for datetime format like DateTimeOriginal 2022:06:02 + dateValidation_ = std::make_pair(ValidRegex, DATE_REGEX); -// regex validation for datetime format like DateTimeOriginal 2022:06:02 -ValueFormatDelegate ExifMetadatFormatter::dateValidation = std::make_pair(ExifMetadatFormatter::ValidRegex, DATE_REGEX); + // regex validation for three integer like GPSLatitude 39,54,21 --> 39/1 54/1 21/1 + tribleIntToRationalWithColon_ = + std::make_pair(ValidRegexWithColonRationalFormat, TRIBLE_INT_WITH_COLON_REGEX); -// regex validation for three integer like GPSLatitude 39,54,21 --> 39/1 54/1 21/1 -ValueFormatDelegate ExifMetadatFormatter::tribleIntToRationalWithColon = - std::make_pair(ExifMetadatFormatter::ValidRegexWithColonRationalFormat, TRIBLE_INT_WITH_COLON_REGEX); + timeStamp_ = std::make_pair(ValidRegexWithDecimalRationalFormat, TIMESTAMP_REGEX); -ValueFormatDelegate ExifMetadatFormatter::timeStamp = - std::make_pair(ExifMetadatFormatter::ValidRegexWithDecimalRationalFormat, TIMESTAMP_REGEX); + // regex validation for fou integer with pointer like GPSVersionID + fourIntWithDot_ = std::make_pair(ValidRegexWithDot, TRIBLE_INT_WITH_DOT_REGEX); -// regex validation for fou integer with pointer like GPSVersionID -ValueFormatDelegate ExifMetadatFormatter::fourIntWithDot = - std::make_pair(ExifMetadatFormatter::ValidRegexWithDot, TRIBLE_INT_WITH_DOT_REGEX); + sixDecimalToRationalWithBlank_ = std::make_pair(ValidRegexWithDecimalRationalFormat, SIX_DECIMAL_WITH_BLANK_REGEX); -ValueFormatDelegate ExifMetadatFormatter::sixDecimalToRationalWithBlank = - std::make_pair(ExifMetadatFormatter::ValidRegexWithDecimalRationalFormat, SIX_DECIMAL_WITH_BLANK_REGEX); + sixDecimalToRationalWithComma_ = std::make_pair(ValidRegexWithDecimalRationalFormat, SIX_DECIMAL_WITH_COMMA_REGEX); -ValueFormatDelegate ExifMetadatFormatter::sixDecimalToRationalWithComma = - std::make_pair(ExifMetadatFormatter::ValidRegexWithDecimalRationalFormat, SIX_DECIMAL_WITH_COMMA_REGEX); + version_ = std::make_pair(ValidRegexWithVersionFormat, VERSION_REGEX); -ValueFormatDelegate ExifMetadatFormatter::version = - std::make_pair(ExifMetadatFormatter::ValidRegexWithVersionFormat, VERSION_REGEX); - -ValueFormatDelegate ExifMetadatFormatter::channel = - std::make_pair(ExifMetadatFormatter::ValidRegexWithChannelFormat, CHANNEL_REGEX); + channel_ = std::make_pair(ValidRegexWithChannelFormat, CHANNEL_REGEX); +} -// configuration for value format validation. For example BitPerSample the value format should be 9 9 9 or 9,9,9 -std::multimap ExifMetadatFormatter::valueFormatConvertConfig = { - {"BitsPerSample", tribleIntWithBlank}, - {"BitsPerSample", tribleIntWithComma}, - {"CompressedBitsPerPixel", singleRational}, - {"CompressedBitsPerPixel", singleIntToRational}, - {"CompressedBitsPerPixel", singleDecimalToRational}, - {"GPSLatitude", doubleIntToOneRationalWithComma}, - {"GPSLatitude", tribleRationalWithBlank}, - {"GPSLatitude", tribleIntToRationalWithBlank}, - {"GPSLatitude", tribleIntToRationalWithComma}, - {"GPSLatitude", tribleMixToRationalWithComma}, - {"GPSLongitude", doubleIntToOneRationalWithComma}, - {"GPSLongitude", tribleRationalWithBlank}, - {"GPSLongitude", tribleIntToRationalWithBlank}, - {"GPSLongitude", tribleIntToRationalWithComma}, - {"GPSLongitude", tribleMixToRationalWithComma}, - {"ApertureValue", singleRational}, - {"ApertureValue", singleIntToRational}, - {"ApertureValue", singleDecimalToRational}, - {"DateTimeOriginal", dateTimeValidation}, - {"DateTimeOriginal", dateValidation}, - {"DateTime", dateTimeValidation}, - {"DateTime", dateValidation}, - {"ExposureBiasValue", singleRational}, - {"ExposureBiasValue", singleIntToRational}, - {"ExposureBiasValue", singleDecimalToRational}, - {"ExposureTime", singleRational}, - {"ExposureTime", singleIntToRational}, - {"ExposureTime", singleDecimalToRational}, - {"FNumber", singleRational}, - {"FNumber", singleIntToRational}, - {"FNumber", singleDecimalToRational}, - {"FocalLength", singleRational}, - {"FocalLength", singleIntToRational}, - {"FocalLength", singleDecimalToRational}, - {"GPSTimeStamp", tribleRationalWithBlank}, - {"GPSTimeStamp", tribleIntToRationalWithBlank}, - {"GPSTimeStamp", tribleIntToRationalWithColon}, - {"GPSTimeStamp", timeStamp}, - {"GPSDateStamp", dateValidation}, - {"XResolution", singleRational}, - {"XResolution", singleIntToRational}, - {"XResolution", singleDecimalToRational}, - {"YResolution", singleRational}, - {"YResolution", singleIntToRational}, - {"YResolution", singleDecimalToRational}, - {"WhitePoint", singleRational}, - {"WhitePoint", singleIntToRational}, - {"WhitePoint", singleDecimalToRational}, - {"WhitePoint", doubleValueToRational}, - {"PrimaryChromaticities", singleRational}, - {"PrimaryChromaticities", singleIntToRational}, - {"PrimaryChromaticities", singleDecimalToRational}, - {"YCbCrCoefficients", tribleRationalWithBlank}, - {"YCbCrCoefficients", tribleIntToRationalWithBlank}, - {"YCbCrCoefficients", tribleIntToRationalWithComma}, - {"YCbCrCoefficients", tribleDecimalToRationalWithBlank}, - {"YCbCrCoefficients", tribleDecimalToRatiionalWithComma}, - {"ReferenceBlackWhite", singleRational}, - {"ReferenceBlackWhite", singleIntToRational}, - {"ReferenceBlackWhite", singleDecimalToRational}, - {"ReferenceBlackWhite", sixDecimalToRationalWithComma}, - {"ShutterSpeedValue", singleRational}, - {"ShutterSpeedValue", singleIntToRational}, - {"ShutterSpeedValue", singleDecimalToRational}, - {"BrightnessValue", singleRational}, - {"BrightnessValue", singleIntToRational}, - {"BrightnessValue", singleDecimalToRational}, - {"MaxApertureValue", singleRational}, - {"MaxApertureValue", singleIntToRational}, - {"MaxApertureValue", singleDecimalToRational}, - {"SubjectDistance", singleRational}, - {"SubjectDistance", singleIntToRational}, - {"SubjectDistance", singleDecimalToRational}, - {"FlashEnergy", singleRational}, - {"FlashEnergy", singleIntToRational}, - {"FlashEnergy", singleDecimalToRational}, - {"FocalPlaneXResolution", singleRational}, - {"FocalPlaneXResolution", singleIntToRational}, - {"FocalPlaneXResolution", singleDecimalToRational}, - {"FocalPlaneYResolution", singleRational}, - {"FocalPlaneYResolution", singleIntToRational}, - {"FocalPlaneYResolution", singleDecimalToRational}, - {"ExposureIndex", singleRational}, - {"ExposureIndex", singleIntToRational}, - {"ExposureIndex", singleDecimalToRational}, - {"DigitalZoomRatio", singleRational}, - {"DigitalZoomRatio", singleIntToRational}, - {"DigitalZoomRatio", singleDecimalToRational}, - {"GPSAltitude", singleRational}, - {"GPSAltitude", singleIntToRational}, - {"GPSAltitude", singleDecimalToRational}, - {"GPSDOP", singleRational}, - {"GPSDOP", singleIntToRational}, - {"GPSDOP", singleDecimalToRational}, - {"GPSSpeed", singleRational}, - {"GPSSpeed", singleIntToRational}, - {"GPSSpeed", singleDecimalToRational}, - {"GPSTrack", singleRational}, - {"GPSTrack", singleIntToRational}, - {"GPSTrack", singleDecimalToRational}, - {"GPSImgDirection", singleRational}, - {"GPSImgDirection", singleIntToRational}, - {"GPSImgDirection", singleDecimalToRational}, - {"GPSDestLatitude", tribleRationalWithBlank}, - {"GPSDestLatitude", tribleIntToRationalWithBlank}, - {"GPSDestLatitude", tribleIntToRationalWithComma}, - {"GPSDestLongitude", tribleRationalWithBlank}, - {"GPSDestLongitude", tribleIntToRationalWithBlank}, - {"GPSDestLongitude", tribleIntToRationalWithComma}, - {"GPSDestBearing", singleRational}, - {"GPSDestBearing", singleIntToRational}, - {"GPSDestBearing", singleDecimalToRational}, - {"GPSDestDistance", singleRational}, - {"GPSDestDistance", singleIntToRational}, - {"GPSDestDistance", singleDecimalToRational}, - {"GPSVersionID", fourIntWithDot}, - {"CompressedBitsPerPixel", singleRational}, - {"CompressedBitsPerPixel", singleIntToRational}, - {"CompressedBitsPerPixel", singleDecimalToRational}, - {"DNGVersion", fourIntWithBlank}, - {"DNGVersion", fourIntWithComma}, - {"DefaultCropSize", doubleIntWithBlank}, - {"DefaultCropSize", doubleIntWithComma}, - {"Gamma", singleRational}, - {"Gamma", singleIntToRational}, - {"Gamma", singleDecimalToRational}, - {"GPSHPositioningError", singleRational}, - {"GPSHPositioningError", singleIntToRational}, - {"GPSHPositioningError", singleDecimalToRational}, - {"LensSpecification", fourRationalWithBlank}, - {"LensSpecification", fourIntToRationalWithBlank}, - {"LensSpecification", fourIntToRationalWithComma}, - {"LensSpecification", fourDecimalToRationalWithBlank}, - {"LensSpecification", fourDecimalToRationalWithComma}, - {"ReferenceBlackWhite", sixDecimalToRationalWithBlank}, - {"SubjectLocation", doubleIntWithBlank}, - {"SubjectLocation", doubleIntWithComma}, - {"ImageLength", singleInt}, - {"ImageWidth", singleInt}, - {"ISOSpeedRatings", singleInt}, - {"StandardOutputSensitivity", singleInt}, - {"RecommendedExposureIndex", singleInt}, - {"ISOSpeed", singleInt}, - {"PixelXDimension", singleInt}, - {"PixelYDimension", singleInt}, - {"FocalLengthIn35mmFilm", singleInt}, - {"StripOffsets", singleInt}, - {"SamplesPerPixel", singleInt}, - {"RowsPerStrip", singleInt}, - {"StripByteCounts", singleInt}, - {"ExifVersion", singleInt}, - {"ExifVersion", version}, - {"ISOSpeedLatitudeyyy", singleInt}, - {"ISOSpeedLatitudezzz", singleInt}, - {"ComponentsConfiguration", singleInt}, - {"ComponentsConfiguration", channel}, - {"PhotographicSensitivity", singleInt}, - {"FlashpixVersion", singleInt}, - {"FlashpixVersion", version}, - {"PhotoMode", singleInt}, - {"JPEGProc", singleInt}, - {"HwMnoteCaptureMode", singleInt}, - {"HwMnoteIsXmageSupported", singleInt}, - {"HwMnoteXmageMode", singleInt}, - {"HwMnoteXmageLeft", singleInt}, - {"HwMnoteXmageTop", singleInt}, - {"HwMnoteXmageRight", singleInt}, - {"HwMnoteXmageBottom", singleInt}, - {"HwMnoteCloudEnhancementMode", singleInt}, - {"HwMnoteAiEdit", singleInt}, - {"DateTimeDigitized", dateTimeValidation}, - {"DateTimeDigitized", dateValidation}, - {"OffsetTime", dateTimeValidation}, - {"OffsetTime", dateValidation}, - {"SubjectArea", doubleIntWithBlank}, - {"SubjectArea", doubleIntWithComma}, - {"SourceImageNumberOfCompositeImage", doubleIntWithBlank}, - {"SourceImageNumberOfCompositeImage", doubleIntWithComma}, - {"YCbCrSubSampling", doubleIntWithBlank}, - {"YCbCrSubSampling", doubleIntWithComma}, - {"MovingPhotoVersion", singleInt}, - {"MicroVideoPresentationTimestampUS", singleInt}, -}; +bool ExifMetadatFormatter::ValidRegexWithGpsOneRationalFormat(std::string &value, const std::string ®ex) +{ + IMAGE_LOGD("validate gps with one rational."); + if (!ValidRegex(value, regex)) { + return false; + } + std::vector vec; + SplitStr(value, ",", vec); + if (vec.size() != GPS_DEGREE_SIZE) { + IMAGE_LOGD("Gps degree data size is invalid."); + return false; + } + value = vec[0] + "/" + vec[1] + " 0/1 0/1"; + return true; +} // validate the value range. For example GPSLatitudeRef the value must be 'N' or 'S'. int32_t ExifMetadatFormatter::ValidateValueRange(const std::string &keyName, const std::string &value) { // 1. to find if any value range validation configuratiion according to exif tag in std::map container - auto iter = valueRangeValidateConfig.find(keyName); - if (iter == valueRangeValidateConfig.end()) { + auto iter = ExifMetadatFormatter::GetInstance().valueRangeValidateConfig_.find(keyName); + if (iter == ExifMetadatFormatter::GetInstance().valueRangeValidateConfig_.end()) { // if no range validation for key default is success. return Media::SUCCESS; } @@ -1355,8 +1373,8 @@ void ExifMetadatFormatter::ConvertRangeValue(const std::string &keyName, std::st value = "3"; return; } - auto iter = valueRangeValidateConfig.find(keyName); - if (iter == valueRangeValidateConfig.end()) { + auto iter = ExifMetadatFormatter::GetInstance().valueRangeValidateConfig_.find(keyName); + if (iter == ExifMetadatFormatter::GetInstance().valueRangeValidateConfig_.end()) { return; } @@ -1393,31 +1411,14 @@ bool ExifMetadatFormatter::IsForbiddenValue(const std::string &value) return false; } -std::multimap ExifMetadatFormatter::valueTemplateConfig = { - {"ExposureTime", "(\\d+/\\d+) sec\\."}, - {"ExposureTime", "(\\d+\\.\\d+|\\d+) sec\\."}, - {"FNumber", "f/(\\d+\\.\\d+)"}, - {"ApertureValue", "(\\d+\\.\\d+) EV \\(f/\\d+\\.\\d+\\)"}, - {"ExposureBiasValue", "(\\d+\\.\\d+) EV"}, - {"FocalLength", "(\\d+\\.\\d+) mm"}, - {"ShutterSpeedValue", "(\\d+\\.\\d+) EV \\(\\d+/\\d+ sec\\.\\)"}, - {"BrightnessValue", "(\\d+\\.\\d+) EV \\(\\d+\\.\\d+ cd/m\\^\\d+\\)"}, - {"MaxApertureValue", "(\\d+\\.\\d+) EV \\(f/\\d+\\.\\d+\\)"}, - {"SubjectDistance", "(\\d+\\.\\d+) m"}, - {"SubjectArea", "\\(x,y\\) = \\((\\d+,\\d+)\\)"}, - {"ExifVersion", "Exif Version ([0-9]{1,2}\\.[0-9]{1,2})"}, - {"FlashpixVersion", "FlashPix Version ([0-9]{1,2}\\.[0-9]{1,2})"}, - {"Copyright", "^(.*) \\(Photographer\\) \\- \\[None\\] \\(Editor\\)$"}, -}; - void ExifMetadatFormatter::ExtractValue(const std::string &keyName, std::string &value) { - auto it = ExifMetadatFormatter::valueTemplateConfig.find(keyName); - if (it == ExifMetadatFormatter::valueTemplateConfig.end()) { + auto it = ExifMetadatFormatter::GetInstance().valueTemplateConfig_.find(keyName); + if (it == ExifMetadatFormatter::GetInstance().valueTemplateConfig_.end()) { return; } - for (; it != ExifMetadatFormatter::valueTemplateConfig.end() && - it != ExifMetadatFormatter::valueTemplateConfig.upper_bound(keyName); + for (; it != ExifMetadatFormatter::GetInstance().valueTemplateConfig_.end() && + it != ExifMetadatFormatter::GetInstance().valueTemplateConfig_.upper_bound(keyName); it++) { std::regex pattern(it->second); for (std::sregex_iterator i = std::sregex_iterator(value.begin(), value.end(), pattern); @@ -1442,16 +1443,16 @@ int32_t ExifMetadatFormatter::ConvertValueFormat(const std::string &keyName, std IMAGE_LOGD("ConvertValueFormat keyName is [%{public}s] value is [%{public}s].", keyName.c_str(), value.c_str()); } - auto it = ExifMetadatFormatter::valueFormatConvertConfig.find(keyName); - if (it == ExifMetadatFormatter::valueFormatConvertConfig.end()) { + auto it = ExifMetadatFormatter::GetInstance().valueFormatConvertConfig_.find(keyName); + if (it == ExifMetadatFormatter::GetInstance().valueFormatConvertConfig_.end()) { IMAGE_LOGD("No format validation needed. Defaulting to success."); return Media::SUCCESS; } IMAGE_LOGD("Validating value format. Key: %{public}s", keyName.c_str()); // get first iterator according to keyName - for (; it != ExifMetadatFormatter::valueFormatConvertConfig.end() && - it != ExifMetadatFormatter::valueFormatConvertConfig.upper_bound(keyName); + for (; it != ExifMetadatFormatter::GetInstance().valueFormatConvertConfig_.end() && + it != ExifMetadatFormatter::GetInstance().valueFormatConvertConfig_.upper_bound(keyName); it++) { IMAGE_LOGD("Validating value format in loop. Key: %{public}s, Regex: %{public}s", (it->first).c_str(), (it->second).second.c_str()); diff --git a/frameworks/kits/ani/BUILD.gn b/frameworks/kits/ani/BUILD.gn index 9cd3dd0bc77b7fc40aa1782c3ba14e2281fec948..de6b16b9f1b60b2527d243446dd256337956800a 100644 --- a/frameworks/kits/ani/BUILD.gn +++ b/frameworks/kits/ani/BUILD.gn @@ -21,11 +21,49 @@ config("ani_config") { group("image_framework_ani") { deps = [ - ":image_ani", + ":image_ani_core", ":image_framework_abc_etc", ] } +ohos_shared_library("image_ani_core") { + if (!use_clang_android) { + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + } + include_dirs = [ "native/include" ] + sources = [ + "native/src/ani_image_module.cpp", + "native/src/image_ani_utils.cpp", + "native/src/image_packer_ani.cpp", + "native/src/image_source_ani.cpp", + "native/src/picture_ani.cpp", + "native/src/pixel_map_ani.cpp", + ] + deps = [ + "${image_subsystem}/frameworks/innerkitsimpl/utils:image_utils", + "${image_subsystem}/interfaces/innerkits:image_native", + "${image_subsystem}/interfaces/kits/js/common:image", + ] + external_deps = [ + "ability_runtime:ability_runtime", + "c_utils:utils", + "hilog:libhilog", + "hitrace:hitrace_meter", + "ipc:ipc_core", + "runtime_core:ani", + "runtime_core:libarkruntime", + ] + subsystem_name = "multimedia" + part_name = "image_framework" + output_extension = "so" +} + +# APIs exposed to external modules ohos_shared_library("image_ani") { public_configs = [ ":ani_config" ] if (!use_clang_android) { @@ -38,7 +76,6 @@ ohos_shared_library("image_ani") { } include_dirs = [ "native/include" ] sources = [ - "native/src/ani_image_module.cpp", "native/src/image_ani_utils.cpp", "native/src/image_packer_ani.cpp", "native/src/image_source_ani.cpp", @@ -46,6 +83,7 @@ ohos_shared_library("image_ani") { "native/src/pixel_map_ani.cpp", ] deps = [ + ":image_ani_core", "${image_subsystem}/frameworks/innerkitsimpl/utils:image_utils", "${image_subsystem}/interfaces/innerkits:image_native", "${image_subsystem}/interfaces/kits/js/common:image", diff --git a/frameworks/kits/ani/ets/@ohos.multimedia.image.ets b/frameworks/kits/ani/ets/@ohos.multimedia.image.ets index 7e8008567be7f19a0ba7c9d95da2cbf5b5d9fc25..42b5bf657314c76719888fd5c0e84b1667f66c67 100644 --- a/frameworks/kits/ani/ets/@ohos.multimedia.image.ets +++ b/frameworks/kits/ani/ets/@ohos.multimedia.image.ets @@ -17,7 +17,7 @@ import type colorSpaceManager from '@ohos.graphics.colorSpaceManager'; export namespace image { - loadLibrary("image_ani"); + loadLibrary("image_ani_core"); enum DecodingDynamicRange { AUTO = 0, diff --git a/frameworks/kits/ani/ets/imageTest.ets b/frameworks/kits/ani/ets/imageTest.ets index 6428d7207cd5e4f97cefcd4d047adf2dc0bc274b..960e685757176177a1704ca831833ec5fc31d966 100644 --- a/frameworks/kits/ani/ets/imageTest.ets +++ b/frameworks/kits/ani/ets/imageTest.ets @@ -17,7 +17,7 @@ import { image } from "./@ohos.multimedia.image.ets"; function main() { // test createPixemap & getImageInfo - console.log("Test PixelMap START"); + console.println("Test PixelMap START"); const opts: image.InitializationOptions = { size: { width: 480, height: 360 }, srcPixelFormat: image.PixelMapFormat.RGBA_8888, @@ -29,30 +29,30 @@ function main() { let pixelMap:image.PixelMap = image.createPixelMapSync(opts); if (pixelMap != undefined) { - console.log("Create PixelMap success"); + console.println("Create PixelMap success"); } const retImageInfo: image.ImageInfo = pixelMap.getImageInfoSync(); - console.log(`Get image info: ${retImageInfo.size.width}, ${retImageInfo.size.height}, ${retImageInfo.pixelFormat}, ${retImageInfo.alphaType}`); + console.println(`Get image info: ${retImageInfo.size.width}, ${retImageInfo.size.height}, ${retImageInfo.pixelFormat}, ${retImageInfo.alphaType}`); pixelMap.getImageInfo() .then((imageInfo: image.ImageInfo) => { - console.log(`ASYNC Get image info: ${imageInfo.size.width}, ${imageInfo.size.height}, ${imageInfo.pixelFormat}, ${imageInfo.alphaType}`); + console.println(`ASYNC Get image info: ${imageInfo.size.width}, ${imageInfo.size.height}, ${imageInfo.pixelFormat}, ${imageInfo.alphaType}`); }); const rowBytes = pixelMap.getBytesNumberPerRow(); - console.log("PixelMap bytes per row: " + rowBytes); + console.println("PixelMap bytes per row: " + rowBytes); const totalBytes = pixelMap.getPixelBytesNumber(); - console.log("PixelMap total bytes: " + totalBytes); + console.println("PixelMap total bytes: " + totalBytes); if (retImageInfo.isHdr) { - console.log("Test PixelMap HDR"); + console.println("Test PixelMap HDR"); } else { - console.log("Test PixelMap not HDR"); + console.println("Test PixelMap not HDR"); } pixelMap.scaleSync(2, 2); const scaledInfo = pixelMap.getImageInfoSync(); - console.log(`Scaled image info: ${scaledInfo.size.width}, ${scaledInfo.size.height}`); + console.println(`Scaled image info: ${scaledInfo.size.width}, ${scaledInfo.size.height}`); const region: image.Region = { size: { width: 512, height: 512 }, x: 0, @@ -60,37 +60,33 @@ function main() { }; pixelMap.cropSync(region); const croppedInfo = pixelMap.getImageInfoSync(); - console.log(`Cropped image info: ${croppedInfo.size.width}, ${croppedInfo.size.height}`); + console.println(`Cropped image info: ${croppedInfo.size.width}, ${croppedInfo.size.height}`); pixelMap.flipSync(true, true); const flippedInfo = pixelMap.getImageInfoSync(); - console.log(`Flipped image info: ${flippedInfo.size.width}, ${flippedInfo.size.height}`); + console.println(`Flipped image info: ${flippedInfo.size.width}, ${flippedInfo.size.height}`); const alphaPixelMap = pixelMap.createAlphaPixelmapSync(); if (alphaPixelMap != undefined) { - console.log("Create alpha PixelMap success"); + console.println("Create alpha PixelMap success"); } const alphaImageInfo = alphaPixelMap.getImageInfoSync(); - console.log(`Alpha get image info: ${alphaImageInfo.size.width}, ${alphaImageInfo.size.height}, ${alphaImageInfo.pixelFormat}, ${alphaImageInfo.alphaType}`); + console.println(`Alpha get image info: ${alphaImageInfo.size.width}, ${alphaImageInfo.size.height}, ${alphaImageInfo.pixelFormat}, ${alphaImageInfo.alphaType}`); pixelMap.createAlphaPixelmap() .then((alphaPixelMap: image.PixelMap) => { const alphaImageInfo = alphaPixelMap.getImageInfoSync(); - console.log(`ASYNC Alpha get image info: ${alphaImageInfo.size.width}, ${alphaImageInfo.size.height}, ${alphaImageInfo.pixelFormat}, ${alphaImageInfo.alphaType}`); + console.println(`ASYNC Alpha get image info: ${alphaImageInfo.size.width}, ${alphaImageInfo.size.height}, ${alphaImageInfo.pixelFormat}, ${alphaImageInfo.alphaType}`); }) let imageSource: image.ImageSource = image.createImageSource("/data/local/tmp/test.png"); if (imageSource != undefined) { - console.log("Create ImageSource by URI success"); - } - let imageSource2: image.ImageSource = image.createImageSource(1); - if (imageSource2 != undefined) { - console.log("Create ImageSource by FD success"); + console.println("Create ImageSource by URI success"); } let imagesourceImageInfo: image.ImageInfo = imageSource.getImageInfoSync(0); - console.log(`Image source image info: ${imagesourceImageInfo.size.width}, ${imagesourceImageInfo.size.height}, ${imagesourceImageInfo.pixelFormat}, ${imagesourceImageInfo.density}, ${imagesourceImageInfo.mimeType}`); + console.println(`Image source image info: ${imagesourceImageInfo.size.width}, ${imagesourceImageInfo.size.height}, ${imagesourceImageInfo.pixelFormat}, ${imagesourceImageInfo.density}, ${imagesourceImageInfo.mimeType}`); imageSource.getImageInfo(0) .then((imageInfo: image.ImageInfo) => { - console.log(`ASYNC Image source image info: ${imageInfo.size.width}, ${imageInfo.size.height}, ${imageInfo.pixelFormat}, ${imageInfo.density}, ${imageInfo.mimeType}`); + console.println(`ASYNC Image source image info: ${imageInfo.size.width}, ${imageInfo.size.height}, ${imageInfo.pixelFormat}, ${imageInfo.density}, ${imageInfo.mimeType}`); }); const desiredSize: image.Size | undefined = { width: 60, height: 60 }; @@ -111,16 +107,16 @@ function main() { }; let pixelmap2: image.PixelMap = imageSource.createPixelMapSync(decodeOpt); if (pixelmap2 != undefined) { - console.log("Create imageSource.createPixelMapSync success"); + console.println("Create imageSource.createPixelMapSync success"); } imageSource.createPixelMap(decodeOpt) .then((pixelmap2: image.PixelMap) => { if (pixelmap2 != undefined) { - console.log("ASYNC Create imageSource PixelMap success") + console.println("ASYNC Create imageSource PixelMap success") } }); pixelmap2.release() - .then((): void => console.log("ASYNC Release PixelMap success")); + .then((): void => console.println("ASYNC Release PixelMap success")); imageSource.modifyImageProperty("Orientation", "Right-top"); const map: Record = { @@ -137,36 +133,35 @@ function main() { array[3] = "Gamma"; imageSource.getImageProperties(array) .then((properties: Record): void => { - console.log("ASYNC Get image properties: " + properties); + console.println("ASYNC Get image properties: " + properties); }); }) - // imageSource.release(); - console.log("TEST ImagePacker begin"); + console.println("TEST ImagePacker begin"); const imagePacker = image.createImagePacker(); - console.log("ImagePacker supported formats: " + imagePacker.supportedFormats); + console.println("ImagePacker supported formats: " + imagePacker.supportedFormats); let packOpts: image.PackingOption = new image.PackingOption(); packOpts.format = "image/jpeg"; packOpts.quality = 90; let packBuffer: ArrayBuffer = imagePacker.packing(pixelMap, packOpts); - console.log("TEST ImagePacker end, bufferSize: " + packBuffer.byteLength); + console.println("TEST ImagePacker end, bufferSize: " + packBuffer.byteLength); imagePacker.release(); - console.log("TEST pixelMap readPixelsToBuffer begin"); + console.println("TEST pixelMap readPixelsToBuffer begin"); let arrayBuffer: ArrayBuffer = new ArrayBuffer(opts.size.width * opts.size.height * 4); pixelMap.readPixelsToBufferSync(arrayBuffer); - console.log("Read pixels to buffer success, size: " + arrayBuffer.byteLength); + console.println("Read pixels to buffer success, size: " + arrayBuffer.byteLength); pixelMap.readPixelsToBuffer(arrayBuffer) - .then((): void => console.log("ASYNC Read pixels to buffer success, size: " + arrayBuffer.byteLength)); + .then((): void => console.println("ASYNC Read pixels to buffer success, size: " + arrayBuffer.byteLength)); - console.log("TEST Picture begin"); + console.println("TEST Picture begin"); const picture = image.createPicture(pixelMap); if (picture != undefined) { - console.log("Create picture success"); + console.println("Create picture success"); } const picturePixelMap = picture.getMainPixelmap(); const pictureInfo = picturePixelMap.getImageInfoSync(); - console.log(`Picture PixelMap image info: ${pictureInfo.size.width}, ${pictureInfo.size.height}, ${pictureInfo.pixelFormat}, ${pictureInfo.alphaType}`); + console.println(`Picture PixelMap image info: ${pictureInfo.size.width}, ${pictureInfo.size.height}, ${pictureInfo.pixelFormat}, ${pictureInfo.alphaType}`); const regionAsync: image.Region = { size: { width: 1, height: 1 }, @@ -176,8 +171,8 @@ function main() { pixelMap.crop(regionAsync) .then((): void => { const croppedInfo = pixelMap.getImageInfoSync(); - console.log(`ASYNC Cropped image info: ${croppedInfo.size.width}, ${croppedInfo.size.height}`); + console.println(`ASYNC Cropped image info: ${croppedInfo.size.width}, ${croppedInfo.size.height}`); }); - console.log("====== Sync methods completed ======") + console.println("====== Sync methods completed ======") } \ No newline at end of file diff --git a/frameworks/kits/taihe/BUILD.gn b/frameworks/kits/taihe/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..3c458f51e18182af8554f7e2c445982ccdd013d4 --- /dev/null +++ b/frameworks/kits/taihe/BUILD.gn @@ -0,0 +1,167 @@ +# Copyright (C) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build/config/components/ets_frontend/ets2abc_config.gni") +import("//build/ohos.gni") +import("//build/ohos/taihe_idl/taihe.gni") +import("//foundation/multimedia/image_framework/ide/image_decode_config.gni") + +subsystem_name = "multimedia" +part_name = "image_framework" +taihe_generated_file_path = "$taihe_file_path/out/$subsystem_name/$part_name" + +config("image_taihe_config") { + visibility = [ ":*" ] + include_dirs = [ "include" ] +} + +copy_taihe_idl("copy_image_taihe") { + sources = [ + "${image_subsystem}/frameworks/kits/taihe/idl/ohos.multimedia.image.image.taihe", + "${image_subsystem}/frameworks/kits/taihe/idl/ohos.multimedia.image.taihe", + ] +} + +ohos_taihe("run_taihe") { + taihe_generated_file_path = "$taihe_generated_file_path" + deps = [ ":copy_image_taihe" ] + outputs = [ + "$taihe_generated_file_path/src/ohos.multimedia.image.image.ani.cpp", + "$taihe_generated_file_path/src/ohos.multimedia.image.image.abi.c", + ] +} + +template("image_taihe_shared_library") { + target_name = invoker.target_name + extra_sources = [] + if (defined(invoker.extra_sources)) { + extra_sources = invoker.extra_sources + } + + taihe_shared_library(target_name) { + forward_variables_from(invoker, "*", + [ + "target_name", + "extra_sources", + ] + ) + + taihe_generated_file_path = "$taihe_generated_file_path" + subsystem_name = "$subsystem_name" + part_name = "$part_name" + + include_dirs = [ + "include", + "${image_subsystem}/interfaces/innerkits/include", + "${image_subsystem}/interfaces/kits/native/include/image", + "${image_subsystem}/plugins/common/libs/image/libextplugin/include/jpeg_yuv_decoder", + ] + + sources = get_target_outputs(":run_taihe") + sources += [ + "src/auxiliary_picture_taihe.cpp", + "src/image_creator_taihe.cpp", + "src/image_packer_taihe.cpp", + "src/image_receiver_taihe.cpp", + "src/image_source_taihe.cpp", + "src/image_taihe.cpp", + "src/image_taihe_utils.cpp", + "src/metadata_taihe.cpp", + "src/picture_taihe.cpp", + "src/pixel_map_taihe.cpp", + "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp", + ] + extra_sources + + deps = [ + ":run_taihe", + "${image_subsystem}/frameworks/innerkitsimpl/egl_image:egl_image", + "${image_subsystem}/frameworks/innerkitsimpl/utils:image_utils", + "${image_subsystem}/interfaces/innerkits:image_native", + ] + + external_deps = [ + "c_utils:utils", + "eventhandler:libeventhandler", + "graphic_2d:ani_color_space_object_convertor", + "graphic_2d:color_manager", + "graphic_2d:EGL", + "graphic_2d:librender_service_base", + "graphic_2d:librender_service_client", + "graphic_surface:surface", + "graphic_surface:sync_fence", + "hilog:libhilog", + "hitrace:hitrace_meter", + "runtime_core:ani_helpers", + "skia:libjpeg", + ] + + cflags = [ + "-DIMAGE_DEBUG_FLAG", + "-DIMAGE_COLORSPACE_FLAG", + ] + + if (!use_clang_android && !use_clang_ios) { + branch_protector_ret = "pac_ret" + sanitize = { + cfi = true + cfi_cross_dso = true + cfi_vcall_icall_only = true + debug = false + } + } + } +} + +image_taihe_shared_library("image_taihe_core") { + extra_sources = [ "src/ani_constructor.cpp" ] +} + +# APIs exposed to external modules +image_taihe_shared_library("image_taihe") { + extra_sources = [ + "src/image_source_taihe_ani.cpp", + "src/picture_taihe_ani.cpp", + "src/pixel_map_taihe_ani.cpp", + ] + + public_configs = [ ":image_taihe_config" ] +} + +generate_static_abc("image_framework_taihe_abc") { + base_url = "$taihe_generated_file_path" + files = [ "$taihe_generated_file_path/@ohos.multimedia.image.ets" ] + is_boot_abc = "True" + device_dst_file = "/system/framework/image_framework_taihe_abc.abc" + dependencies = [ ":run_taihe" ] +} + +ohos_prebuilt_etc("image_framework_etc") { + source = "$target_out_dir/image_framework_taihe_abc.abc" + module_install_dir = "framework" + part_name = "$part_name" + subsystem_name = "$subsystem_name" + deps = [ + ":image_framework_taihe_abc" + ] +} + +group("image_framework_taihe") { + deps = [ + ":image_framework_etc", + ":image_taihe_core", + ] +} + +group("image_framework_taihe_gen_only") { + deps = [ ":run_taihe" ] +} \ No newline at end of file diff --git a/frameworks/kits/taihe/idl/ohos.multimedia.image.image.taihe b/frameworks/kits/taihe/idl/ohos.multimedia.image.image.taihe new file mode 100644 index 0000000000000000000000000000000000000000..87da42ae9fb689202fe195cda59c78f960ff4d48 --- /dev/null +++ b/frameworks/kits/taihe/idl/ohos.multimedia.image.image.taihe @@ -0,0 +1,929 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@!namespace("@ohos.multimedia.image", "image") + +@!sts_inject(""" +static { loadLibrary("image_taihe_core.z"); } +""") + +enum PixelMapFormat: i32 { + UNKNOWN = 0, + ARGB_8888 = 1, + RGB_565 = 2, + RGBA_8888 = 3, + BGRA_8888 = 4, + RGB_888 = 5, + ALPHA_8 = 6, + RGBA_F16 = 7, + NV21 = 8, + NV12 = 9, + RGBA_1010102 = 10, + YCBCR_P010 = 11, + YCRCB_P010 = 12, + ASTC_4x4 = 102 +} + +enum ResolutionQuality: i32 { + LOW = 1, + MEDIUM = 2, + HIGH = 3 +} + +struct Size { + width: i32; + height: i32; +} + +enum PropertyKey: String { + BITS_PER_SAMPLE = "BitsPerSample", + ORIENTATION = "Orientation", + IMAGE_LENGTH = "ImageLength", + IMAGE_WIDTH = "ImageWidth", + GPS_LATITUDE = "GPSLatitude", + GPS_LONGITUDE = "GPSLongitude", + GPS_LATITUDE_REF = "GPSLatitudeRef", + GPS_LONGITUDE_REF = "GPSLongitudeRef", + DATE_TIME_ORIGINAL = "DateTimeOriginal", + EXPOSURE_TIME = "ExposureTime", + SCENE_TYPE = "SceneType", + ISO_SPEED_RATINGS = "ISOSpeedRatings", + F_NUMBER = "FNumber", + DATE_TIME = "DateTime", + GPS_TIME_STAMP = "GPSTimeStamp", + GPS_DATE_STAMP = "GPSDateStamp", + IMAGE_DESCRIPTION = "ImageDescription", + MAKE = "Make", + MODEL = "Model", + PHOTO_MODE = "PhotoMode", + SENSITIVITY_TYPE = "SensitivityType", + STANDARD_OUTPUT_SENSITIVITY = "StandardOutputSensitivity", + RECOMMENDED_EXPOSURE_INDEX = "RecommendedExposureIndex", + ISO_SPEED = "ISOSpeedRatings", + APERTURE_VALUE = "ApertureValue", + EXPOSURE_BIAS_VALUE = "ExposureBiasValue", + METERING_MODE = "MeteringMode", + LIGHT_SOURCE = "LightSource", + FLASH = "Flash", + FOCAL_LENGTH = "FocalLength", + USER_COMMENT = "UserComment", + PIXEL_X_DIMENSION = "PixelXDimension", + PIXEL_Y_DIMENSION = "PixelYDimension", + WHITE_BALANCE = "WhiteBalance", + FOCAL_LENGTH_IN_35_MM_FILM = "FocalLengthIn35mmFilm", + CAPTURE_MODE = "HwMnoteCaptureMode", + PHYSICAL_APERTURE = "HwMnotePhysicalAperture", + ROLL_ANGLE = "HwMnoteRollAngle", + PITCH_ANGLE = "HwMnotePitchAngle", + SCENE_FOOD_CONF = "HwMnoteSceneFoodConf", + SCENE_STAGE_CONF = "HwMnoteSceneStageConf", + SCENE_BLUE_SKY_CONF = "HwMnoteSceneBlueSkyConf", + SCENE_GREEN_PLANT_CONF = "HwMnoteSceneGreenPlantConf", + SCENE_BEACH_CONF = "HwMnoteSceneBeachConf", + SCENE_SNOW_CONF = "HwMnoteSceneSnowConf", + SCENE_SUNSET_CONF = "HwMnoteSceneSunsetConf", + SCENE_FLOWERS_CONF = "HwMnoteSceneFlowersConf", + SCENE_NIGHT_CONF = "HwMnoteSceneNightConf", + SCENE_TEXT_CONF = "HwMnoteSceneTextConf", + FACE_COUNT = "HwMnoteFaceCount", + FOCUS_MODE = "HwMnoteFocusMode", + COMPRESSION = "Compression", + PHOTOMETRIC_INTERPRETATION = "PhotometricInterpretation", + STRIP_OFFSETS = "StripOffsets", + SAMPLES_PER_PIXEL = "SamplesPerPixel", + ROWS_PER_STRIP = "RowsPerStrip", + STRIP_BYTE_COUNTS = "StripByteCounts", + X_RESOLUTION = "XResolution", + Y_RESOLUTION = "YResolution", + PLANAR_CONFIGURATION = "PlanarConfiguration", + RESOLUTION_UNIT = "ResolutionUnit", + TRANSFER_FUNCTION = "TransferFunction", + SOFTWARE = "Software", + ARTIST = "Artist", + WHITE_POINT = "WhitePoint", + PRIMARY_CHROMATICITIES = "PrimaryChromaticities", + YCBCR_COEFFICIENTS = "YCbCrCoefficients", + YCBCR_SUB_SAMPLING = "YCbCrSubSampling", + YCBCR_POSITIONING = "YCbCrPositioning", + REFERENCE_BLACK_WHITE = "ReferenceBlackWhite", + COPYRIGHT = "Copyright", + JPEG_INTERCHANGE_FORMAT = "JPEGInterchangeFormat", + JPEG_INTERCHANGE_FORMAT_LENGTH = "JPEGInterchangeFormatLength", + EXPOSURE_PROGRAM = "ExposureProgram", + SPECTRAL_SENSITIVITY = "SpectralSensitivity", + OECF = "OECF", + EXIF_VERSION = "ExifVersion", + DATE_TIME_DIGITIZED = "DateTimeDigitized", + COMPONENTS_CONFIGURATION = "ComponentsConfiguration", + SHUTTER_SPEED = "ShutterSpeedValue", + BRIGHTNESS_VALUE = "BrightnessValue", + MAX_APERTURE_VALUE = "MaxApertureValue", + SUBJECT_DISTANCE = "SubjectDistance", + SUBJECT_AREA = "SubjectArea", + MAKER_NOTE = "MakerNote", + SUBSEC_TIME = "SubsecTime", + SUBSEC_TIME_ORIGINAL = "SubsecTimeOriginal", + SUBSEC_TIME_DIGITIZED = "SubsecTimeDigitized", + FLASHPIX_VERSION = "FlashpixVersion", + COLOR_SPACE = "ColorSpace", + RELATED_SOUND_FILE = "RelatedSoundFile", + FLASH_ENERGY = "FlashEnergy", + SPATIAL_FREQUENCY_RESPONSE = "SpatialFrequencyResponse", + FOCAL_PLANE_X_RESOLUTION = "FocalPlaneXResolution", + FOCAL_PLANE_Y_RESOLUTION = "FocalPlaneYResolution", + FOCAL_PLANE_RESOLUTION_UNIT = "FocalPlaneResolutionUnit", + SUBJECT_LOCATION = "SubjectLocation", + EXPOSURE_INDEX = "ExposureIndex", + SENSING_METHOD = "SensingMethod", + FILE_SOURCE = "FileSource", + CFA_PATTERN = "CFAPattern", + CUSTOM_RENDERED = "CustomRendered", + EXPOSURE_MODE = "ExposureMode", + DIGITAL_ZOOM_RATIO = "DigitalZoomRatio", + SCENE_CAPTURE_TYPE = "SceneCaptureType", + GAIN_CONTROL = "GainControl", + CONTRAST = "Contrast", + SATURATION = "Saturation", + SHARPNESS = "Sharpness", + DEVICE_SETTING_DESCRIPTION = "DeviceSettingDescription", + SUBJECT_DISTANCE_RANGE = "SubjectDistanceRange", + IMAGE_UNIQUE_ID = "ImageUniqueID", + GPS_VERSION_ID = "GPSVersionID", + GPS_ALTITUDE_REF = "GPSAltitudeRef", + GPS_ALTITUDE = "GPSAltitude", + GPS_SATELLITES = "GPSSatellites", + GPS_STATUS = "GPSStatus", + GPS_MEASURE_MODE = "GPSMeasureMode", + GPS_DOP = "GPSDOP", + GPS_SPEED_REF = "GPSSpeedRef", + GPS_SPEED = "GPSSpeed", + GPS_TRACK_REF = "GPSTrackRef", + GPS_TRACK = "GPSTrack", + GPS_IMG_DIRECTION_REF = "GPSImgDirectionRef", + GPS_IMG_DIRECTION = "GPSImgDirection", + GPS_MAP_DATUM = "GPSMapDatum", + GPS_DEST_LATITUDE_REF = "GPSDestLatitudeRef", + GPS_DEST_LATITUDE = "GPSDestLatitude", + GPS_DEST_LONGITUDE_REF = "GPSDestLongitudeRef", + GPS_DEST_LONGITUDE = "GPSDestLongitude", + GPS_DEST_BEARING_REF = "GPSDestBearingRef", + GPS_DEST_BEARING = "GPSDestBearing", + GPS_DEST_DISTANCE_REF = "GPSDestDistanceRef", + GPS_DEST_DISTANCE = "GPSDestDistance", + GPS_PROCESSING_METHOD = "GPSProcessingMethod", + GPS_AREA_INFORMATION = "GPSAreaInformation", + GPS_DIFFERENTIAL = "GPSDifferential", + BODY_SERIAL_NUMBER = "BodySerialNumber", + CAMERA_OWNER_NAME = "CameraOwnerName", + COMPOSITE_IMAGE = "CompositeImage", + COMPRESSED_BITS_PER_PIXEL = "CompressedBitsPerPixel", + DNG_VERSION = "DNGVersion", + DEFAULT_CROP_SIZE = "DefaultCropSize", + GAMMA = "Gamma", + ISO_SPEED_LATITUDE_YYY = "ISOSpeedLatitudeyyy", + ISO_SPEED_LATITUDE_ZZZ = "ISOSpeedLatitudezzz", + LENS_MAKE = "LensMake", + LENS_MODEL = "LensModel", + LENS_SERIAL_NUMBER = "LensSerialNumber", + LENS_SPECIFICATION = "LensSpecification", + NEW_SUBFILE_TYPE = "NewSubfileType", + OFFSET_TIME = "OffsetTime", + OFFSET_TIME_DIGITIZED = "OffsetTimeDigitized", + OFFSET_TIME_ORIGINAL = "OffsetTimeOriginal", + SOURCE_EXPOSURE_TIMES_OF_COMPOSITE_IMAGE = "SourceExposureTimesOfCompositeImage", + SOURCE_IMAGE_NUMBER_OF_COMPOSITE_IMAGE = "SourceImageNumberOfCompositeImage", + SUBFILE_TYPE = "SubfileType", + GPS_H_POSITIONING_ERROR = "GPSHPositioningError", + PHOTOGRAPHIC_SENSITIVITY = "PhotographicSensitivity", + BURST_NUMBER = "HwMnoteBurstNumber", + FACE_CONF = "HwMnoteFaceConf", + FACE_LEYE_CENTER = "HwMnoteFaceLeyeCenter", + FACE_MOUTH_CENTER = "HwMnoteFaceMouthCenter", + FACE_POINTER = "HwMnoteFacePointer", + FACE_RECT = "HwMnoteFaceRect", + FACE_REYE_CENTER = "HwMnoteFaceReyeCenter", + FACE_SMILE_SCORE = "HwMnoteFaceSmileScore", + FACE_VERSION = "HwMnoteFaceVersion", + FRONT_CAMERA = "HwMnoteFrontCamera", + SCENE_POINTER = "HwMnoteScenePointer", + SCENE_VERSION = "HwMnoteSceneVersion", + IS_XMAGE_SUPPORTED = "HwMnoteIsXmageSupported", + XMAGE_MODE = "HwMnoteXmageMode", + XMAGE_LEFT = "HwMnoteXmageLeft", + XMAGE_TOP = "HwMnoteXmageTop", + XMAGE_RIGHT = "HwMnoteXmageRight", + XMAGE_BOTTOM = "HwMnoteXmageBottom", + CLOUD_ENHANCEMENT_MODE = "HwMnoteCloudEnhancementMode", + WIND_SNAPSHOT_MODE = "HwMnoteWindSnapshotMode", + GIF_LOOP_COUNT = "GIFLoopCount" +} + +enum ImageFormat: i32 { + YCBCR_422_SP = 1000, + JPEG = 2000 +} + +enum AlphaType: i32 { + UNKNOWN = 0, + OPAQUE = 1, + PREMUL = 2, + UNPREMUL = 3 +} + +enum DecodingDynamicRange: i32 { + AUTO = 0, + SDR = 1, + HDR = 2 +} + +enum PackingDynamicRange: i32 { + AUTO = 0, + SDR = 1, +} + +enum AntiAliasingLevel: i32 { + NONE = 0, + LOW = 1, + MEDIUM = 2, + HIGH = 3 +} + +enum ScaleMode: i32 { + FIT_TARGET_SIZE = 0, + CENTER_CROP = 1 +} + +enum ComponentType: i32 { + YUV_Y = 1, + YUV_U = 2, + YUV_V = 3, + JPEG = 4 +} + +enum AllocatorType: i32 { + AUTO = 0, + DMA = 1, + SHARE_MEMORY = 2, +} + +struct Region { + size: Size; + x: i32; + y: i32; +} + +// Can't use struct because struct is copied instead of referenced, so data changes to "pixels" in C++ will not be reflected in ArkTS +interface PositionArea { + @get GetPixels(): @arraybuffer Array; + @set SetPixels(pixels: @arraybuffer Array): void; + @get GetOffset(): i32; + @set SetOffset(offset: i32): void; + @get GetStride(): i32; + @set SetStride(stride: i32): void; + @get GetRegion(): Region; + @set SetRegion(region: Region): void; +} + +struct ImageInfo { + size: Size; + density: i32; + stride: i32; + pixelFormat: PixelMapFormat; + alphaType: AlphaType; + mimeType: String; + isHdr: bool; +} + +enum CropAndScaleStrategy: i32 { + SCALE_FIRST = 1, + CROP_FIRST = 2 +} + +struct PackingOption { + format: String; + quality: i32; + bufferSize: Optional; + desiredDynamicRange: Optional; + needsPackProperties: Optional; +} + +struct PackingOptionsForSequence { + frameCount: i32; + delayTimeList: Array; + disposalTypes: Optional>; + loopCount: Optional; +} + +struct ImagePropertyOptions { + index: Optional; + defaultValue: Optional; +} + +struct DecodingOptions { + index: Optional; + sampleSize: Optional; + rotate: Optional; + editable: Optional; + desiredSize: Optional; + desiredRegion: Optional; + desiredPixelFormat: Optional; + photoDesiredPixelFormat: Optional; // not exposed to the user + fitDensity: Optional; + fillColor: Optional; // not exposed to the user + SVGResize: Optional; // not exposed to the user + desiredColorSpace: Optional<@sts_type("colorSpaceManager.ColorSpaceManager") Opaque>; + desiredDynamicRange: Optional; + resolutionQuality: Optional; + cropAndScaleStrategy: Optional; + reusePixelmap: Optional; // not exposed to the user +} + +struct Component { + @readonly componentType: ComponentType; + @readonly rowStride: i32; + @readonly pixelStride: i32; + @readonly byteBuffer: @arraybuffer Array; +} + +struct InitializationOptions { + size: Size; + srcPixelFormat: Optional; + pixelFormat: Optional; + editable: Optional; + alphaType: Optional; + scaleMode: Optional; +} + +struct SourceOptions { + sourceDensity: i32; + sourcePixelFormat: Optional; + sourceSize: Optional; +} + +struct HdrStaticMetadata { + displayPrimariesX: Array; + displayPrimariesY: Array; + whitePointX: f64; + whitePointY: f64; + maxLuminance: f64; + minLuminance: f64; + maxContentLightLevel: f64; + maxFrameAverageLightLevel: f64; +} + +struct GainmapChannel { + gainmapMax: f64; + gainmapMin: f64; + gamma: f64; + baseOffset: f64; + alternateOffset: f64; +} + +struct HdrGainmapMetadata { + writerVersion: i32; + miniVersion: i32; + gainmapChannelCount: i32; + useBaseColorFlag: bool; + baseHeadroom: f64; + alternateHeadroom: f64; + channels: Array; +} + +enum HdrMetadataKey: i32 { + HDR_METADATA_TYPE = 0, + HDR_STATIC_METADATA = 1, + HDR_DYNAMIC_METADATA = 2, + HDR_GAINMAP_METADATA = 3, +} + +enum HdrMetadataType: i32 { + NONE = 0, + BASE = 1, + GAINMAP = 2, + ALTERNATE = 3, +} + +enum AuxiliaryPictureType: i32 { + GAINMAP = 1, + DEPTH_MAP = 2, + UNREFOCUS_MAP = 3, + LINEAR_MAP = 4, + FRAGMENT_MAP = 5, +} + +enum MetadataType: i32 { + EXIF_METADATA = 1, + FRAGMENT_METADATA = 2, +} + +enum FragmentMapPropertyKey: String { + X_IN_ORIGINAL = "XInOriginal", + Y_IN_ORIGINAL = "YInOriginal", + WIDTH = "FragmentImageWidth", + HEIGHT = "FragmentImageHeight" +} + +struct DecodingOptionsForPicture { + desiredAuxiliaryPictures: Array; +} + +struct AuxiliaryPictureInfo { + auxiliaryPictureType: AuxiliaryPictureType; + size: Size; + rowStride: i32; + pixelFormat: PixelMapFormat; + colorSpace: @sts_type("colorSpaceManager.ColorSpaceManager") Opaque; +} + +union HdrMetadataValue { + metadataType: HdrMetadataType; + staticMetadataArrayBuffer: HdrStaticMetadata; + arrayBuffer: @arraybuffer Array; + gainmapMetadata: HdrGainmapMetadata; +} + +union PropertyValue { + type_string: String; + @null type_null; +} + +interface PixelMap { + GetImplPtr(): i64; + + @gen_async("getImageInfo") + @gen_promise("getImageInfo") + GetImageInfoSync(): ImageInfo; + + @gen_async("readPixelsToBuffer") + @gen_promise("readPixelsToBuffer") + ReadPixelsToBufferSync(dst: @arraybuffer Array): void; + + @gen_async("readPixels") + @gen_promise("readPixels") + ReadPixelsSync(area: PositionArea): void; + + @gen_async("writeBufferToPixels") + @gen_promise("writeBufferToPixels") + WriteBufferToPixelsSync(src: @arraybuffer Array): void; + + @gen_async("createAlphaPixelmap") + @gen_promise("createAlphaPixelmap") + CreateAlphaPixelmapSync(): PixelMap; + + GetBytesNumberPerRow(): i32; + + GetPixelBytesNumber(): i32; + + GetDensity(): i32; + + @gen_async("scale") + @gen_promise("scale") + @overload("scaleSync") + ScaleSync(x: f32, y: f32): void; + + @gen_promise("scale") + @overload("scaleSync") + ScaleWithAntiAliasingSync(x: f32, y: f32, level: AntiAliasingLevel): void; + + @gen_async("crop") + @gen_promise("crop") + CropSync(region: Region): void; + + @gen_async("rotate") + @gen_promise("rotate") + RotateSync(angle: f32): void; + + @gen_async("flip") + @gen_promise("flip") + FlipSync(horizontal: bool, vertical: bool): void; + + @gen_async("opacity") + @gen_promise("opacity") + OpacitySync(rate: f32): void; + + @gen_promise("toSdr") + ToSdrSync(): void; + + @gen_async("applyColorSpace") + @gen_promise("applyColorSpace") + ApplyColorSpaceSync(targetColorSpace: @sts_type("colorSpaceManager.ColorSpaceManager") Opaque): void; + + SetMemoryNameSync(name: String): void; + + @gen_promise("convertPixelFormat") + ConvertPixelFormatSync(targetPixelFormat: PixelMapFormat): void; + + GetColorSpace(): @sts_type("colorSpaceManager.ColorSpaceManager") Opaque; + + SetColorSpace(colorSpace: @sts_type("colorSpaceManager.ColorSpaceManager") Opaque): void; + + @gen_async("release") + @gen_promise("release") + ReleaseSync(): void; + + @get GetIsEditable(): bool; + + @get GetIsStrideAlignment(): bool; + + @set SetCaptureId(captureId: i32): void; + @get GetCaptureId(): i32; + + @set SetTimestamp(timestamp: i64): void; + @get GetTimestamp(): i64; +} + +union GainMap { + type_gainMap: PixelMap; + @null type_null; +} + +union AuxPicture { + type_auxPicture: AuxiliaryPicture; + @null type_null; +} + +interface Picture { + GetImplPtr(): i64; + + GetMainPixelmap(): PixelMap; + + @gen_promise("getHdrComposedPixelmap") + GetHdrComposedPixelmapSync(): PixelMap; + + GetGainmapPixelmap(): GainMap; + + SetAuxiliaryPicture(type: AuxiliaryPictureType, auxiliaryPicture: AuxiliaryPicture): void; + + GetAuxiliaryPicture(type: AuxiliaryPictureType): AuxPicture; + + @gen_promise("setMetadata") + SetMetadataSync(metadataType: MetadataType, metadata: Metadata): void; + + @gen_promise("getMetadata") + GetMetadataSync(metadataType: MetadataType): Metadata; + + Marshalling(sequence: @sts_type("rpc.MessageSequence") Opaque): void; + + Release(): void; +} + +interface AuxiliaryPicture { + GetImplPtr(): i64; + + @gen_promise("writePixelsFromBuffer") + WritePixelsFromBufferSync(data: @arraybuffer Array): void; + + @gen_promise("readPixelsToBuffer") + ReadPixelsToBufferSync(): @arraybuffer Array; + + GetType(): AuxiliaryPictureType; + + @gen_promise("setMetadata") + SetMetadataSync(metadataType: MetadataType, metadata: Metadata): void; + + @gen_promise("getMetadata") + GetMetadataSync(metadataType: MetadataType): Metadata; + + GetAuxiliaryPictureInfo(): AuxiliaryPictureInfo; + + SetAuxiliaryPictureInfo(info: AuxiliaryPictureInfo): void; + + Release(): void; +} + +interface Metadata { + GetImplPtr(): i64; + + @gen_promise("getProperties") + GetPropertiesSync(key: Array): @record Map; + + @gen_promise("setProperties") + SetPropertiesSync(records: @record Map): void; + + @gen_promise("getAllProperties") + GetAllPropertiesSync(): @record Map; + + @gen_promise("clone") + CloneSync(): Metadata; +} + +interface ImageSource { + GetImplPtr(): i64; + @gen_async("getImageInfo") + @gen_promise("getImageInfoPromiseWithIndex") + GetImageInfoSyncWithIndex(index: i32): ImageInfo; + + @gen_async("getImageInfo") + @gen_promise("getImageInfoPromise") + GetImageInfoSync(): ImageInfo; + + @!sts_inject_into_interface("getImageInfoSync(index: int | undefined): ImageInfo;") + @!sts_inject_into_class("""getImageInfoSync(index: int | undefined): ImageInfo { + if (index === undefined) { + return this.getImageInfoSync(); + } else { + return this.getImageInfoSyncWithIndex(index); + } + } + """) + + @!sts_inject_into_interface("getImageInfo(index: int | undefined): Promise;") + @!sts_inject_into_class("""getImageInfo(index: int | undefined): Promise { + if (index === undefined) { + return this.getImageInfoPromise(); + } else { + return this.getImageInfoPromiseWithIndex(index); + } + } + """) + + @gen_async("createPixelMap") + @gen_promise("createPixelMapPromiseWithOptions") + CreatePixelMapSyncWithOptions(options: DecodingOptions): PixelMap; + + @gen_async("createPixelMap") + @gen_promise("createPixelMapPromise") + CreatePixelMapSync(): PixelMap; + + @!sts_inject_into_interface("createPixelMapSync(options: DecodingOptions | undefined): PixelMap;") + @!sts_inject_into_class("""createPixelMapSync(options: DecodingOptions | undefined): PixelMap { + if (options === undefined) { + return this.createPixelMapSync(); + } else { + return this.createPixelMapSyncWithOptions(options); + } + } + """) + + @!sts_inject_into_interface("createPixelMap(options: DecodingOptions | undefined): Promise;") + @!sts_inject_into_class("""createPixelMap(options: DecodingOptions | undefined): Promise { + if (options === undefined) { + return this.createPixelMapPromise(); + } else { + return this.createPixelMapPromiseWithOptions(options); + } + } + """) + + @gen_promise("createPixelMapUsingAllocator") + CreatePixelMapUsingAllocatorSync(options: Optional, allocatorType: Optional): PixelMap; + + @gen_async("createPixelMapList") + CreatePixelMapListSync(): Array; + + @gen_async("createPixelMapList") + CreatePixelMapListSyncWithOptions(options: DecodingOptions): Array; + + @gen_promise("createPixelMapList") + CreatePixelMapListSyncWithOptionalOptions(options: Optional): Array; + + @gen_async("getDelayTimeList") + @gen_promise("getDelayTimeList") + GetDelayTimeListSync(): Array; + + @gen_promise("getDisposalTypeList") + GetDisposalTypeListSync(): Array; + + @gen_async("getFrameCount") + @gen_promise("getFrameCount") + GetFrameCountSync(): i32; + + @gen_promise("getImageProperty") + GetImagePropertySync(key: PropertyKey, options: Optional): String; + + @gen_promise("getImageProperties") + GetImagePropertiesSync(key: Array): @record Map; + + @gen_promise("modifyImageProperty") + ModifyImagePropertySync(key: PropertyKey, value: String): void; + + @gen_promise("modifyImageProperties") + ModifyImagePropertiesSync(records: @record Map): void; + + @gen_async("updateData") + @gen_promise("updateData") + UpdateDataSync(buf: @arraybuffer Array, isFinished: bool, offset: i32, length: i32): void; + + @gen_async("release") + @gen_promise("release") + ReleaseSync(): void; + + @gen_promise("createPicture") + CreatePictureSync(options: Optional): Picture; + + @get GetSupportedFormats(): Array; +} + +interface ImagePacker { + @gen_promise("packToData") + PackImageSourceToDataSync(source: ImageSource, options: PackingOption): @arraybuffer Array; + + @gen_promise("packToData") + PackPixelMapToDataSync(source: PixelMap, options: PackingOption): @arraybuffer Array; + + @gen_promise("packToDataFromPixelmapSequence") + PackToDataFromPixelmapSequenceSync(pixelmapSequence: Array, options: PackingOptionsForSequence): @arraybuffer Array; + + @gen_async("packToFile") + @gen_promise("packToFile") + PackImageSourceToFileSync(source: ImageSource, fd: i32, options: PackingOption): void; + + @gen_async("packToFile") + @gen_promise("packToFile") + PackPixelMapToFileSync(source: PixelMap, fd: i32, options: PackingOption): void; + + @gen_promise("packToFileFromPixelmapSequence") + PackToFileFromPixelmapSequenceSync(pixelmapSequence: Array, fd: i32, options: PackingOptionsForSequence): void; + + @gen_promise("packToFile") + PackPictureToFileSync(picture: Picture, fd: i32, options: PackingOption): void; + + @gen_promise("packing") + PackingPictureSync(picture: Picture, options: PackingOption): @arraybuffer Array; + + @gen_async("release") + @gen_promise("release") + ReleaseSync(): void; + + @get GetSupportedFormats(): Array; +} + +interface Image { + @get("clipRect") GetClipRect(): Region; + GetImplPtr(): i64; + + @get("size") GetSize(): Size; + @get("format") GetFormat(): i32; + @get("timestamp") GetTimestamp(): i64; + + @gen_async("getComponent") + @gen_promise("getComponent") + GetComponentSync(componentType: ComponentType): Component; + + @gen_async("release") + @gen_promise("release") + ReleaseSync(): void; +} + +interface ImageReceiver { + @get GetSize(): Size; + @get GetCapacity(): i32; + @get GetFormat(): ImageFormat; + + @gen_async("getReceivingSurfaceId") + @gen_promise("getReceivingSurfaceId") + GetReceivingSurfaceIdSync(): String; + + @gen_async("readLatestImage") + @gen_promise("readLatestImage") + ReadLatestImageSync(): Image; + + @gen_async("readNextImage") + @gen_promise("readNextImage") + ReadNextImageSync(): Image; + + @!sts_inject_into_interface("on(type: string, callback: (err: BusinessError, data: undefined)=> void): void;") + @!sts_inject_into_class("""on(type: string, callback: (err: BusinessError, data: undefined)=> void): void { + if (type === 'imageArrival') { + this.onImageArrival(callback); + } else { + throw new Error(`Unknown type: ${type}`); + } + } + """) + + @!sts_inject_into_interface("off(type: string, callback?: (err: BusinessError, data: undefined)=> void): void;") + @!sts_inject_into_class("""off(type: string, callback?: (err: BusinessError, data: undefined)=> void): void { + if (type === 'imageArrival') { + this.offImageArrival(callback); + } else { + throw new Error(`Unknown type: ${type}`); + } + } + """) + + OnImageArrival(callback: (err: @sts_type("BusinessError") Opaque, data: @sts_type("undefined") Opaque)=> void): void; + OffImageArrival(callback: Optional<(err: @sts_type("BusinessError") Opaque, data: @sts_type("undefined") Opaque)=> void>): void; + + @gen_async("release") + @gen_promise("release") + ReleaseSync(): void; +} + +interface ImageCreator { + @get("capacity") GetCapacity(): i32; + @get("format") GetFormat(): ImageFormat; + + @gen_async("queueImage") + @gen_promise("queueImage") + QueueImageSync(image: Image): void; + + @gen_async("dequeueImage") + @gen_promise("dequeueImage") + DequeueImageSync(): Image; + + @!sts_inject_into_interface("on(type: string, callback: (err: BusinessError, data: undefined)=> void): void;") + @!sts_inject_into_class("""on(type: string, callback: (err: BusinessError, data: undefined)=> void): void { + if (type === 'imageRelease') { + this.onImageRelease(callback); + } else { + throw new Error(`Unknown type: ${type}`); + } + } + """) + + @!sts_inject_into_interface("off(type: string, callback?: (err: BusinessError, data: undefined)=> void): void;") + @!sts_inject_into_class("""off(type: string, callback?: (err: BusinessError, data: undefined)=> void): void { + if (type === 'imageRelease') { + this.offImageRelease(callback); + } else { + throw new Error(`Unknown type: ${type}`); + } + } + """) + + OnImageRelease(callback: (err: @sts_type("BusinessError") Opaque, data: @sts_type("undefined") Opaque)=> void): void; + OffImageRelease(callback: Optional<(err: @sts_type("BusinessError") Opaque, data: @sts_type("undefined") Opaque)=> void>): void; + + @gen_async("release") + @gen_promise("release") + ReleaseSync(): void; +} + +function MakeEmptySize(): Size; +function MakeEmptyImageInfo(): ImageInfo; + +@gen_async("createPixelMap") +@gen_promise("createPixelMap") +@overload("createPixelMapSync") +function CreatePixelMapByBufferAndOptionsSync(colors: @arraybuffer Array, options: InitializationOptions): PixelMap; + +@overload("createPixelMapSync") +function CreatePixelMapByOptionsSync(options: InitializationOptions): PixelMap; + +// For legacy ANI backward compatibility +function CreatePixelMapByPtr(ptr: i64): PixelMap; + +@overload("createPixelMapFromSurfaceSync") +function CreatePixelMapFromSurfaceByIdSync(surfaceId: String): PixelMap; + +@overload("createPixelMapFromSurfaceSync") +function CreatePixelMapFromSurfaceByIdAndRegionSync(surfaceId: String, region: Region): PixelMap; + +@overload("createImageSource") +function CreateImageSourceByUri(uri: String): ImageSource; + +@overload("createImageSource") +function CreateImageSourceByUriOption(uri: String, options: SourceOptions): ImageSource; + +@overload("createImageSource") +function CreateImageSourceByFd(fd: i32): ImageSource; + +@overload("createImageSource") +function CreateImageSourceByFdOption(fd: i32, options: SourceOptions): ImageSource; + +@overload("createImageSource") +function CreateImageSourceByArrayBuffer(buf: @arraybuffer Array): ImageSource; + +@overload("createImageSource") +function CreateImageSourceByArrayBufferOption(buf: @arraybuffer Array, options: SourceOptions): ImageSource; + +@overload("CreateIncrementalSource") +function CreateIncrementalSourceByArrayBuffer(buf: @arraybuffer Array): ImageSource; + +@overload("CreateIncrementalSource") +function CreateIncrementalSourceByArrayBufferOption(buf: @arraybuffer Array, options: Optional): ImageSource; + +@overload("createImageSource") +function CreateImageSourceByRawFileDescriptorOption(rawfile: @sts_type("resourceManager.RawFileDescriptor") Opaque, options: Optional): ImageSource; + +// For legacy ANI backward compatibility +function CreateImageSourceByPtr(ptr: i64): ImageSource; + +function CreateImagePacker(): ImagePacker; + +function CreateImageCreator(size: Size, format: ImageFormat, capacity: i32): ImageCreator; + +function CreateImageReceiver(size: Size, format: ImageFormat, capacity: i32): ImageReceiver; + +@overload("createPicture") +function CreatePictureByPixelMap(mainPixelmap : PixelMap): Picture; + +// For legacy ANI backward compatibility +function CreatePictureByPtr(ptr: i64): Picture; + +function CreatePictureFromParcel(sequence: @sts_type("rpc.MessageSequence") Opaque): Picture; + +function CreateAuxiliaryPicture(buffer: @arraybuffer Array, size: Size, type: AuxiliaryPictureType): AuxiliaryPicture; \ No newline at end of file diff --git a/frameworks/kits/taihe/idl/ohos.multimedia.image.taihe b/frameworks/kits/taihe/idl/ohos.multimedia.image.taihe new file mode 100644 index 0000000000000000000000000000000000000000..3b939be4011890d90fff41cbde5ecc6b34d01010 --- /dev/null +++ b/frameworks/kits/taihe/idl/ohos.multimedia.image.taihe @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@!namespace("@ohos.multimedia.image") + +@!sts_inject(""" +import type colorSpaceManager from '@ohos.graphics.colorSpaceManager'; +import type resourceManager from '@ohos.resourceManager'; +import type rpc from '@ohos.rpc'; +""") \ No newline at end of file diff --git a/frameworks/kits/taihe/include/auxiliary_picture_taihe.h b/frameworks/kits/taihe/include/auxiliary_picture_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..042bf48ac624a20ca85a9956f544f82141c15363 --- /dev/null +++ b/frameworks/kits/taihe/include/auxiliary_picture_taihe.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_AUXILIARY_PICTURE_TAIHE_H +#define FRAMEWORKS_KITS_TAIHE_INCLUDE_AUXILIARY_PICTURE_TAIHE_H + +#include "auxiliary_picture.h" +#include "ohos.multimedia.image.image.proj.hpp" +#include "ohos.multimedia.image.image.impl.hpp" + +namespace ANI::Image { +using namespace taihe; +using namespace ohos::multimedia::image::image; + +class AuxiliaryPictureImpl { +public: + AuxiliaryPictureImpl(); + explicit AuxiliaryPictureImpl(std::shared_ptr auxiliaryPicture); + ~AuxiliaryPictureImpl(); + int64_t GetImplPtr(); + std::shared_ptr GetNativeAuxiliaryPic() + { + return nativeAuxiliaryPicture_; + } + + void WritePixelsFromBufferSync(array_view data); + array ReadPixelsToBufferSync(); + AuxiliaryPictureType GetType(); + void SetMetadataSync(MetadataType metadataType, weak::Metadata metadata); + Metadata GetMetadataSync(MetadataType metadataType); + AuxiliaryPictureInfo GetAuxiliaryPictureInfo(); + void SetAuxiliaryPictureInfo(AuxiliaryPictureInfo const& info); + void Release(); + +private: + std::shared_ptr nativeAuxiliaryPicture_; + bool isRelease = false; +}; +} // namespace ANI::Image + +#endif // FRAMEWORKS_KITS_TAIHE_INCLUDE_AUXILIARY_PICTURE_TAIHE_H \ No newline at end of file diff --git a/frameworks/kits/taihe/include/image_creator_taihe.h b/frameworks/kits/taihe/include/image_creator_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..fcaa3b0eeaabc205ee02e1be5e6bfa1a2aa4d278 --- /dev/null +++ b/frameworks/kits/taihe/include/image_creator_taihe.h @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_CREATOR_TAIHE_H +#define FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_CREATOR_TAIHE_H + +#include "event_handler.h" +#include "image_creator.h" +#include "image_taihe.h" +#include "ohos.multimedia.image.image.proj.hpp" +#include "ohos.multimedia.image.image.impl.hpp" +#include "taihe/runtime.hpp" + +namespace ANI::Image { +using namespace taihe; +using namespace ohos::multimedia::image::image; + +struct ImageCreatorTaiheContext; +using CallbackResult = std::variant; +using CompleteCallback = CallbackResult (*)(std::shared_ptr &); + +class ImageCreatorImpl { +public: + ImageCreatorImpl(); + explicit ImageCreatorImpl(std::shared_ptr imageCreator); + ~ImageCreatorImpl(); + + static bool AniSendEvent(const std::function cb, std::string &name); + static void OnProcessSendEvent(std::shared_ptr &context); + + int32_t GetCapacity(); + ImageFormat GetFormat(); + + void QueueImageSync(weak::Image image); + + struct Image DequeueImageSync(); + + void OnImageRelease(::taihe::callback_view callback); + + void OffImageRelease(::taihe::optional_view<::taihe::callback> callback); + + void ReleaseSync(); + +private: + std::shared_ptr imageCreator_; + bool isRelease = false; + static std::shared_ptr mainHandler_; +}; + +struct ImageCreatorTaiheContext { + CompleteCallback callBack = nullptr; + CallbackResult result; + std::shared_ptr taiheCallback = nullptr; + std::string name; + ImageCreatorImpl *imageCreatorImpl_ = nullptr; + ImageImpl *imageImpl_ = nullptr; + uint32_t status = OHOS::Media::ERROR; +}; + +struct ImageCreatorCommonArgs { + const std::string name; + CompleteCallback callBack; +}; + +class ImageCreatorReleaseListener : public OHOS::Media::SurfaceBufferReleaseListener { +public: + ~ImageCreatorReleaseListener() override + { + context = nullptr; + } + void OnSurfaceBufferRelease() override + { + ImageCreatorImpl::OnProcessSendEvent(context); + } + std::shared_ptr context = nullptr; +}; +} // namespace ANI::Image + +#endif // FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_CREATOR_TAIHE_H \ No newline at end of file diff --git a/frameworks/kits/taihe/include/image_packer_taihe.h b/frameworks/kits/taihe/include/image_packer_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..1bd57bcfdc1076f82f78352a8dc7e9f2f2ec529b --- /dev/null +++ b/frameworks/kits/taihe/include/image_packer_taihe.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_PACKER_TAIHE_H +#define FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_PACKER_TAIHE_H + +#include "image_packer.h" +#include "ohos.multimedia.image.image.proj.hpp" +#include "ohos.multimedia.image.image.impl.hpp" +#include "taihe/runtime.hpp" + +namespace ANI::Image { +using namespace taihe; +using namespace ohos::multimedia::image::image; + +class ImagePackerImpl { +public: + ImagePackerImpl(); + explicit ImagePackerImpl(std::shared_ptr imagePacker); + ~ImagePackerImpl(); + + array Packing(int32_t packType, int64_t source, PackingOption const& options, bool needReturnError); + void PackToFile(int32_t packType, int64_t source, int32_t fd, PackingOption const& options); + + void PackImageSourceToFileSync(weak::ImageSource source, int32_t fd, PackingOption const& options); + void PackPixelMapToFileSync(weak::PixelMap source, int32_t fd, PackingOption const& options); + void PackToFileFromPixelmapSequenceSync(array_view pixelmapSequence, int32_t fd, + PackingOptionsForSequence const& options); + void PackPictureToFileSync(weak::Picture picture, int32_t fd, PackingOption const& options); + + array PackingPictureSync(weak::Picture picture, PackingOption const& options); + + array PackImageSourceToDataSync(weak::ImageSource source, PackingOption const& options); + array PackPixelMapToDataSync(weak::PixelMap source, PackingOption const& options); + array PackToDataFromPixelmapSequenceSync(array_view pixelmapSequence, + PackingOptionsForSequence const& options); + + void ReleaseSync(); + + array GetSupportedFormats(); + +private: + std::shared_ptr nativeImagePacker_; + bool isRelease = false; +}; +} + +#endif // FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_PACKER_TAIHE_H \ No newline at end of file diff --git a/frameworks/kits/taihe/include/image_receiver_taihe.h b/frameworks/kits/taihe/include/image_receiver_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..6e3b04491e3176b4232cd3c6252f60620983e7f7 --- /dev/null +++ b/frameworks/kits/taihe/include/image_receiver_taihe.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_RECEIVER_TAIHE_H +#define FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_RECEIVER_TAIHE_H + +#include "event_handler.h" +#include "image_receiver.h" +#include "ohos.multimedia.image.image.proj.hpp" +#include "ohos.multimedia.image.image.impl.hpp" +#include "taihe/runtime.hpp" + +namespace ANI::Image { +using namespace taihe; +using namespace ohos::multimedia::image::image; + +struct ImageReceiverTaiheContext; +using CallbackResult = std::variant; +using CompleteCallback = CallbackResult (*)(std::shared_ptr &); + +class ImageReceiverImpl { +public: + ImageReceiverImpl(); + explicit ImageReceiverImpl(std::shared_ptr imageReceiver); + ~ImageReceiverImpl(); + + static bool AniSendEvent(const std::function cb, std::string &name); + static void OnProcessSendEvent(std::shared_ptr &context); + + Size GetSize(); + int32_t GetCapacity(); + ImageFormat GetFormat(); + + string GetReceivingSurfaceIdSync(); + struct Image ReadLatestImageSync(); + struct Image ReadNextImageSync(); + void OnImageArrival(callback_view callback); + void OffImageArrival(optional_view> callback); + void ReleaseSync(); + +#ifdef IMAGE_DEBUG_FLAG + bool isCallBackTest = false; +#endif + +private: + void UnRegisterReceiverListener(); + void NativeRelease(); + + std::shared_ptr imageReceiver_; + bool isRelease = false; + static std::shared_ptr mainHandler_; +}; + +struct ImageReceiverTaiheContext { + CompleteCallback callBack = nullptr; + CallbackResult result; + std::shared_ptr taiheCallback = nullptr; + std::string name; + ImageReceiverImpl *receiverImpl_ = nullptr; + uint32_t status = OHOS::Media::ERROR; +}; + +struct ImageReceiverCommonArgs { + const std::string name; + CompleteCallback callBack; +}; + +class ImageReceiverAvaliableListener : public OHOS::Media::SurfaceBufferAvaliableListener { +public: + ~ImageReceiverAvaliableListener() override + { + context = nullptr; + } + + void OnSurfaceBufferAvaliable() override + { + ImageReceiverImpl::OnProcessSendEvent(context); + } + + std::shared_ptr context = nullptr; +}; +} // namespace ANI::Image + +#endif // FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_RECEIVER_TAIHE_H \ No newline at end of file diff --git a/frameworks/kits/taihe/include/image_source_taihe.h b/frameworks/kits/taihe/include/image_source_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..fd390e743aec3e3828598697408f3bd266ba289e --- /dev/null +++ b/frameworks/kits/taihe/include/image_source_taihe.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_SOURCE_TAIHE_H +#define FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_SOURCE_TAIHE_H + +#include "image_packer_taihe.h" +#include "image_source.h" +#include "ohos.multimedia.image.image.proj.hpp" +#include "ohos.multimedia.image.image.impl.hpp" +#include "taihe/runtime.hpp" + +namespace ANI::Image { +using namespace taihe; +using namespace ohos::multimedia::image::image; + +class ImageSourceImpl { +public: + ImageSourceImpl(); + explicit ImageSourceImpl(std::shared_ptr imageSource); + ImageSourceImpl(std::shared_ptr imageSource, + std::shared_ptr incPixelMap); + ImageSourceImpl(int64_t aniPtr); + ~ImageSourceImpl(); + int64_t GetImplPtr(); + + ImageInfo GetImageInfoSyncWithIndex(int32_t index); + ImageInfo GetImageInfoSync(); + PixelMap CreatePixelMapSyncWithOptions(DecodingOptions const& options); + PixelMap CreatePixelMapSync(); + PixelMap CreatePixelMapUsingAllocatorSync(optional_view options, + optional_view allocatorType); + array CreatePixelMapListSync(); + array CreatePixelMapListSyncWithOptions(DecodingOptions const& options); + array CreatePixelMapListSyncWithOptionalOptions(optional_view options); + array GetDelayTimeListSync(); + array GetDisposalTypeListSync(); + int32_t GetFrameCountSync(); + string GetImagePropertySync(PropertyKey key, optional_view options); + map GetImagePropertiesSync(array_view key); + void ModifyImagePropertySync(PropertyKey key, string_view value); + void ModifyImagePropertiesSync(map_view records); + void UpdateDataSync(array_view buf, bool isFinished, int32_t offset, int32_t length); + void ReleaseSync(); +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + Picture CreatePictureSync(optional_view options); +#endif + + array GetSupportedFormats(); + + std::shared_ptr nativeImgSrc = nullptr; + std::shared_ptr GetIncrementalPixelMap() const + { + return navIncPixelMap_; + } + + static thread_local std::string filePath_; + static thread_local int fileDescriptor_; + static thread_local void* fileBuffer_; + static thread_local size_t fileBufferSize_; +private: + std::shared_ptr navIncPixelMap_; + bool isRelease = false; +}; +} // namespace ANI::Image + +#endif // FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_SOURCE_TAIHE_H \ No newline at end of file diff --git a/frameworks/kits/taihe/include/image_source_taihe_ani.h b/frameworks/kits/taihe/include/image_source_taihe_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..c190dbc434653ab66757fd23742f9321c6a0d104 --- /dev/null +++ b/frameworks/kits/taihe/include/image_source_taihe_ani.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORK_KITS_TAIHE_INCLUDE_IMAGE_SOURCE_TAIHE_ANI_H +#define FRAMEWORK_KITS_TAIHE_INCLUDE_IMAGE_SOURCE_TAIHE_ANI_H + +#include +#include "image_source.h" + +// This file is for legacy ANI backward compatibility + +namespace OHOS { +namespace Media { + +class ImageSourceTaiheAni { +public: + static ani_object CreateEtsImageSource(ani_env *env, std::shared_ptr imageSource); + std::shared_ptr nativeImgSrc; +}; + +} // namespace Media +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/frameworks/kits/taihe/include/image_taihe.h b/frameworks/kits/taihe/include/image_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..53ed3c00464fc0038d0958a29efb3ecdcbee1fed --- /dev/null +++ b/frameworks/kits/taihe/include/image_taihe.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_TAIHE_H +#define FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_TAIHE_H + +#include "image_holder_manager.h" +#include "native_image.h" +#include "ohos.multimedia.image.image.proj.hpp" +#include "ohos.multimedia.image.image.impl.hpp" +#include "taihe/runtime.hpp" + +namespace ANI::Image { +using namespace taihe; +using namespace ohos::multimedia::image::image; + +class ImageImpl { +public: + ImageImpl(); + explicit ImageImpl(std::shared_ptr nativeImage); + ~ImageImpl(); + + int64_t GetImplPtr(); + std::shared_ptr GetIncrementalImage() const + { + return nativeImage_; + } + + Component GetComponentSync(ComponentType componentType); + + static struct Image Create(std::shared_ptr nativeImage); + void ReleaseSync(); + void NativeRelease(); + + ohos::multimedia::image::image::Region GetClipRect(); + Size GetSize(); + int32_t GetFormat(); + int64_t GetTimestamp(); + +private: + static OHOS::Media::ImageHolderManager sNativeImageHolder_; + std::shared_ptr nativeImage_; + bool isTestImage_; +}; +} // namespace ANI::Image + +#endif // FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_TAIHE_H \ No newline at end of file diff --git a/frameworks/kits/taihe/include/image_taihe_utils.h b/frameworks/kits/taihe/include/image_taihe_utils.h new file mode 100644 index 0000000000000000000000000000000000000000..48a8e0bbedd5cc5bdc6f1382c77fd4c4da590e80 --- /dev/null +++ b/frameworks/kits/taihe/include/image_taihe_utils.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_TAIHE_UTILS_H +#define FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_TAIHE_UTILS_H + +#include "image_source.h" +#include "image_type.h" +#include "ohos.multimedia.image.image.proj.hpp" +#include "ohos.multimedia.image.image.impl.hpp" +#include "taihe/runtime.hpp" + +namespace ANI::Image { +using namespace taihe; +using namespace ohos::multimedia::image::image; + +class ImageTaiheUtils { +public: + static void HicheckerReport(); + static void ThrowExceptionError(const std::string &errMsg); + static void ThrowExceptionError(const int32_t errCode, const std::string &errMsg); + struct ImagePropertyOptions { + uint32_t index = 0; + std::string defaultValueStr; + }; + + static bool GetPropertyDouble(ani_env *env, ani_object obj, const std::string &name, double &value); + static ani_object ToBusinessError(ani_env *env, int32_t code, const std::string &message); + + static OHOS::Media::SourceOptions ParseSourceOptions(SourceOptions const& options); + static ImageInfo ToTaiheImageInfo(const OHOS::Media::ImageInfo &src, bool isHdr); + static array ToTaiheArrayString(const std::vector &src); + static array CreateTaiheArrayBuffer(uint8_t* src, size_t srcLen); + static uintptr_t GetUndefinedPtr(ani_env *env); + + template + static bool GetEnumKeyByValue(ValueType value, typename EnumType::key_t &key); + + template + static bool IsValidPtr(T data); +}; +} // namespace ANI::Image + +#endif // FRAMEWORKS_KITS_TAIHE_INCLUDE_IMAGE_TAIHE_UTILS_H \ No newline at end of file diff --git a/frameworks/kits/taihe/include/metadata_taihe.h b/frameworks/kits/taihe/include/metadata_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..fc6c1cbca89e72197dad26eb693108465d817e25 --- /dev/null +++ b/frameworks/kits/taihe/include/metadata_taihe.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_METADATA_TAIHE_H +#define FRAMEWORKS_KITS_TAIHE_INCLUDE_METADATA_TAIHE_H + +#include "metadata.h" +#include "ohos.multimedia.image.image.proj.hpp" +#include "ohos.multimedia.image.image.impl.hpp" +#include "taihe/runtime.hpp" + +namespace ANI::Image { +using namespace taihe; +using namespace ohos::multimedia::image::image; + +class MetadataImpl { +public: + MetadataImpl(); + explicit MetadataImpl(std::shared_ptr imageMetadata); + ~MetadataImpl(); + + int64_t GetImplPtr(); + std::shared_ptr GetNativeMetadata(); + + map GetPropertiesSync(array_view key); + void SetPropertiesSync(map_view records); + map GetAllPropertiesSync(); + Metadata CloneSync(); + + void Release(); + +private: + std::shared_ptr nativeMetadata_; + bool isRelease = false; +}; +} // namespace ANI::Image + +#endif // FRAMEWORKS_KITS_TAIHE_INCLUDE_METADATA_TAIHE_H \ No newline at end of file diff --git a/frameworks/kits/taihe/include/picture_taihe.h b/frameworks/kits/taihe/include/picture_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..e928f2b4fcb0a331e43da1d121f1082e64492b58 --- /dev/null +++ b/frameworks/kits/taihe/include/picture_taihe.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_PICTURE_TAIHE_H +#define FRAMEWORKS_KITS_TAIHE_INCLUDE_PICTURE_TAIHE_H + +#include "ohos.multimedia.image.image.proj.hpp" +#include "ohos.multimedia.image.image.impl.hpp" +#include "picture.h" +#include "taihe/runtime.hpp" + +namespace ANI::Image { +using namespace taihe; +using namespace ohos::multimedia::image::image; + +class PictureImpl { +public: + PictureImpl(); + explicit PictureImpl(std::shared_ptr picture); + PictureImpl(int64_t aniPtr); + ~PictureImpl(); + int64_t GetImplPtr(); + std::shared_ptr GetNativePtr(); + static Picture CreatePicture(std::shared_ptr picture); + + PixelMap GetMainPixelmap(); + PixelMap GetHdrComposedPixelmapSync(); + GainMap GetGainmapPixelmap(); + void SetAuxiliaryPicture(AuxiliaryPictureType type, weak::AuxiliaryPicture auxiliaryPicture); + AuxPicture GetAuxiliaryPicture(AuxiliaryPictureType type); + void SetMetadataSync(MetadataType metadataType, weak::Metadata metadata); + Metadata GetMetadataSync(MetadataType metadataType); + void Marshalling(uintptr_t sequence); + void Release(); + +private: + std::shared_ptr nativePicture_; + bool isRelease = false; +}; +} // namespace ANI::Image + +#endif // FRAMEWORKS_KITS_TAIHE_INCLUDE_PICTURE_TAIHE_H \ No newline at end of file diff --git a/frameworks/kits/taihe/include/picture_taihe_ani.h b/frameworks/kits/taihe/include/picture_taihe_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..4bb87a149d6e4870eea2432039f726fa8d859bf2 --- /dev/null +++ b/frameworks/kits/taihe/include/picture_taihe_ani.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORK_KITS_TAIHE_INCLUDE_PICTURE_TAIHE_ANI_H +#define FRAMEWORK_KITS_TAIHE_INCLUDE_PICTURE_TAIHE_ANI_H + +#include +#include "picture.h" + +// This file is for legacy ANI backward compatibility + +namespace OHOS { +namespace Media { + +class PictureTaiheAni { +public: + static ani_object CreateEtsPicture(ani_env *env, std::shared_ptr picture); + std::shared_ptr nativePicture_; +}; + +} // namespace Media +} // namespace OHOS + +#endif // FRAMEWORK_KITS_TAIHE_INCLUDE_PICTURE_TAIHE_ANI_H \ No newline at end of file diff --git a/frameworks/kits/taihe/include/pixel_map_taihe.h b/frameworks/kits/taihe/include/pixel_map_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..85bed59c8da8826f43d63763e1b017f463e60ea2 --- /dev/null +++ b/frameworks/kits/taihe/include/pixel_map_taihe.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_PIXEL_MAP_TAIHE_H +#define FRAMEWORKS_KITS_TAIHE_INCLUDE_PIXEL_MAP_TAIHE_H + +#include "ohos.multimedia.image.image.proj.hpp" +#include "ohos.multimedia.image.image.impl.hpp" +#include "pixel_map.h" +#include "taihe/runtime.hpp" + +namespace ANI::Image { +using namespace taihe; +using namespace ohos::multimedia::image::image; +using namespace OHOS; + +class PixelMapImpl { +public: + PixelMapImpl(); + explicit PixelMapImpl(array_view const& colors, InitializationOptions const& etsOptions); + explicit PixelMapImpl(InitializationOptions const& etsOptions); + explicit PixelMapImpl(std::shared_ptr pixelMap); + explicit PixelMapImpl(int64_t aniPtr); + ~PixelMapImpl(); + + int64_t GetImplPtr(); + std::shared_ptr GetNativePtr(); + static std::shared_ptr GetPixelMap(PixelMap etsPixelMap); + static PixelMap CreatePixelMap(std::shared_ptr pixelMap); + + ImageInfo GetImageInfoSync(); + void ReadPixelsToBufferSync(array_view dst); + void ReadPixelsSync(weak::PositionArea area); + void WriteBufferToPixelsSync(array_view src); + PixelMap CreateAlphaPixelmapSync(); + int32_t GetBytesNumberPerRow(); + int32_t GetPixelBytesNumber(); + int32_t GetDensity(); + void ScaleSync(float x, float y); + void ScaleWithAntiAliasingSync(float x, float y, AntiAliasingLevel level); + void CropSync(ohos::multimedia::image::image::Region const& region); + void RotateSync(float angle); + void FlipSync(bool horizontal, bool vertical); + void OpacitySync(float rate); + void SetMemoryNameSync(string_view name); + void ConvertPixelFormatSync(PixelMapFormat targetPixelFormat); + uintptr_t GetColorSpace(); + void SetColorSpace(uintptr_t colorSpace); + void ToSdrSync(); + void ApplyColorSpaceSync(uintptr_t targetColorSpace); + void ReleaseSync(); + bool GetIsEditable(); + bool GetIsStrideAlignment(); + void SetCaptureId(int32_t captureId); + int32_t GetCaptureId(); + void SetTimestamp(int64_t timestamp); + int64_t GetTimestamp(); + +private: + std::shared_ptr nativePixelMap_ = nullptr; + bool aniEditable_ = true; + bool Is10BitFormat(OHOS::Media::PixelFormat format); + void ParseInitializationOptions(InitializationOptions const& etsOptions, + OHOS::Media::InitializationOptions &options); + void Release(); + int64_t timestamp_ = 0; + int32_t captureId_ = 0; +}; +} // namespace ANI::Image + +#endif diff --git a/frameworks/kits/taihe/include/pixel_map_taihe_ani.h b/frameworks/kits/taihe/include/pixel_map_taihe_ani.h new file mode 100644 index 0000000000000000000000000000000000000000..2e7d5a3a01ae7717bd138255563bad3976fee697 --- /dev/null +++ b/frameworks/kits/taihe/include/pixel_map_taihe_ani.h @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FRAMEWORKS_KITS_TAIHE_INCLUDE_PIXEL_MAP_TAIHE_ANI_H +#define FRAMEWORKS_KITS_TAIHE_INCLUDE_PIXEL_MAP_TAIHE_ANI_H + +#include +#include "pixel_map.h" + +// This file is for legacy ANI backward compatibility + +namespace OHOS { +namespace Media { + +class PixelMapTaiheAni { +public: + static ani_object CreateEtsPixelMap([[maybe_unused]] ani_env* env, std::shared_ptr pixelMap); + static std::shared_ptr GetNativePixelMap([[maybe_unused]] ani_env* env, ani_object obj); + std::shared_ptr nativePixelMap_; +}; + +} // namespace Media +} // namespace OHOS + +#endif \ No newline at end of file diff --git a/frameworks/kits/taihe/src/ani_constructor.cpp b/frameworks/kits/taihe/src/ani_constructor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ad28d0bf8993e4a2cde2a03c6b5642329d5cad1a --- /dev/null +++ b/frameworks/kits/taihe/src/ani_constructor.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ohos.multimedia.image.image.ani.hpp" + +ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result) +{ + ani_env *env; + if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) { + return ANI_ERROR; + } + if (ANI_OK != ohos::multimedia::image::image::ANIRegister(env)) { + std::cerr << "Error from ohos::multimedia::image::image::ANIRegister" << std::endl; + return ANI_ERROR; + } + *result = ANI_VERSION_1; + return ANI_OK; +} diff --git a/frameworks/kits/taihe/src/auxiliary_picture_taihe.cpp b/frameworks/kits/taihe/src/auxiliary_picture_taihe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bcb393f4b74e70e22f17a7e7a9792a409baed998 --- /dev/null +++ b/frameworks/kits/taihe/src/auxiliary_picture_taihe.cpp @@ -0,0 +1,402 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "ani_color_space_object_convertor.h" +#include "auxiliary_picture_taihe.h" +#include "image_common.h" +#include "image_log.h" +#include "image_taihe_utils.h" +#include "image_type.h" +#include "image_utils.h" +#include "media_errors.h" +#include "metadata_taihe.h" +#include "pixel_map.h" +using namespace ANI::Image; + +namespace ANI::Image { + +struct AuxiliaryPictureTaiheContext { + uint32_t status; + AuxiliaryPictureImpl *nConstructor; + std::shared_ptr rPixelmap; + std::shared_ptr auxPicture; + void *arrayBuffer; + size_t arrayBufferSize; + std::shared_ptr rAuxiliaryPicture; + OHOS::Media::AuxiliaryPictureInfo auxiliaryPictureInfo; + std::shared_ptr imageMetadata; + OHOS::Media::MetadataType metadataType = OHOS::Media::MetadataType::EXIF; + std::shared_ptr AuxColorSpace = nullptr; +}; + +AuxiliaryPictureImpl::AuxiliaryPictureImpl() {} + +AuxiliaryPictureImpl::AuxiliaryPictureImpl(std::shared_ptr auxiliaryPicture) +{ + nativeAuxiliaryPicture_ = auxiliaryPicture; +} + +AuxiliaryPictureImpl::~AuxiliaryPictureImpl() +{ + Release(); +} + +int64_t AuxiliaryPictureImpl::GetImplPtr() +{ + return reinterpret_cast(this); +} + +void AuxiliaryPictureImpl::WritePixelsFromBufferSync(array_view data) +{ + std::unique_ptr taiheContext = std::make_unique(); + taiheContext->rAuxiliaryPicture = nativeAuxiliaryPicture_; + if (taiheContext->rAuxiliaryPicture == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native auxiliary picture."); + return; + } + taiheContext->arrayBuffer = static_cast(data.data()); + taiheContext->arrayBufferSize = data.size(); + if (taiheContext->arrayBuffer == nullptr || taiheContext->arrayBufferSize == 0) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Invalid args."); + IMAGE_LOGE("Fail to get buffer info"); + } + taiheContext->rAuxiliaryPicture->WritePixels( + static_cast(taiheContext->arrayBuffer), taiheContext->arrayBufferSize); +} + +static bool ReadPixelsToBufferSyncExecute(std::unique_ptr &context) +{ + OHOS::Media::AuxiliaryPictureInfo info = context->rAuxiliaryPicture->GetAuxiliaryPictureInfo(); + context->arrayBufferSize = + info.size.width * info.size.height * OHOS::Media::ImageUtils::GetPixelBytes(info.pixelFormat); + context->arrayBuffer = new uint8_t[context->arrayBufferSize]; + if (context->arrayBuffer != nullptr) { + context->status = context->rAuxiliaryPicture->ReadPixels( + context->arrayBufferSize, static_cast(context->arrayBuffer)); + } else { + context->status = OHOS::Media::ERR_MEDIA_MALLOC_FAILED; + ImageTaiheUtils::ThrowExceptionError(IMAGE_ALLOC_FAILED, "Memory alloc failed."); + return false; + } + return true; +} + +static array ReadPixelsToBufferSyncComplete(std::unique_ptr &context) +{ + array result = array(nullptr, 0); + if (context->status == OHOS::Media::SUCCESS) { + result = ImageTaiheUtils::CreateTaiheArrayBuffer(static_cast(context->arrayBuffer), + context->arrayBufferSize); + } else { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERROR, "Fail to create taihe arraybuffer!"); + return array(nullptr, 0); + } + + delete[] static_cast(context->arrayBuffer); + context->arrayBuffer = nullptr; + context->arrayBufferSize = 0; + return result; +} + +AuxiliaryPictureType AuxiliaryPictureImpl::GetType() +{ + if (nativeAuxiliaryPicture_ == nullptr) { + IMAGE_LOGE("Native auxiliary picture is nullptr!"); + return AuxiliaryPictureType(static_cast(OHOS::Media::AuxiliaryPictureType::NONE)); + } + AuxiliaryPictureType::key_t auxPictureTypeKey; + auto auxType = nativeAuxiliaryPicture_->GetType(); + IMAGE_LOGD("AuxiliaryPictureImpl::GetType %{public}d", auxType); + if (ImageTaiheUtils::GetEnumKeyByValue(static_cast(auxType), auxPictureTypeKey)) { + return AuxiliaryPictureType(auxPictureTypeKey); + } else { + IMAGE_LOGE("Get auxiliary picture type failed"); + return AuxiliaryPictureType(static_cast( + OHOS::Media::AuxiliaryPictureType::NONE)); + } +} + +static bool CheckMetadataType(std::unique_ptr const& context) +{ + if (context == nullptr || context->rAuxiliaryPicture == nullptr) { + IMAGE_LOGE("Auxiliary picture is null"); + return false; + } + return !(context->rAuxiliaryPicture->GetType() != OHOS::Media::AuxiliaryPictureType::FRAGMENT_MAP && + context->metadataType == OHOS::Media::MetadataType::FRAGMENT); +} + +void AuxiliaryPictureImpl::SetMetadataSync(MetadataType metadataType, weak::Metadata metadata) +{ + std::unique_ptr context = std::make_unique(); + context->rAuxiliaryPicture = nativeAuxiliaryPicture_; + if (context->rAuxiliaryPicture == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native auxiliary picture."); + return; + } + if (metadataType >= static_cast(OHOS::Media::MetadataType::EXIF) + && metadataType <= static_cast(OHOS::Media::MetadataType::FRAGMENT)) { + context->metadataType = OHOS::Media::MetadataType(metadataType.get_value()); + } else { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Invalid args metadata type."); + return; + } + if (!CheckMetadataType(context)) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_UNSUPPORTED_METADATA, "Unsupported metadata"); + return; + } + MetadataImpl* metadataImpl = reinterpret_cast(metadata->GetImplPtr()); + if (metadataImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Failed to unwrap MetadataImpl"); + return; + } + context->imageMetadata = metadataImpl->GetNativeMetadata(); + if (context->imageMetadata == nullptr) { + IMAGE_LOGE("Empty native metadata"); + } + context->rAuxiliaryPicture->SetMetadata(context->metadataType, context->imageMetadata); + IMAGE_LOGD("[AuxiliaryPicture]SetMetadata OUT"); +} + +Metadata AuxiliaryPictureImpl::GetMetadataSync(MetadataType metadataType) +{ + std::unique_ptr context = std::make_unique(); + context->rAuxiliaryPicture = nativeAuxiliaryPicture_; + if (context->rAuxiliaryPicture == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native auxiliary picture."); + return make_holder(); + } + if (metadataType >= static_cast(OHOS::Media::MetadataType::EXIF) + && metadataType <= static_cast(OHOS::Media::MetadataType::FRAGMENT)) { + context->metadataType = OHOS::Media::MetadataType(metadataType.get_value()); + } else { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Invalid args metadata type."); + return make_holder(); + } + if (!CheckMetadataType(context) || context->metadataType == OHOS::Media::MetadataType::EXIF) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_UNSUPPORTED_METADATA, "Unsupported metadata"); + return make_holder(); + } + context->imageMetadata = context->rAuxiliaryPicture->GetMetadata(context->metadataType); + IMAGE_LOGD("[AuxiliaryPicture]GetMetadata OUT"); + return make_holder(std::move(context->imageMetadata)); +} + +array AuxiliaryPictureImpl::ReadPixelsToBufferSync() +{ + std::unique_ptr taiheContext = std::make_unique(); + taiheContext->rAuxiliaryPicture = nativeAuxiliaryPicture_; + if (taiheContext->rAuxiliaryPicture == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native auxiliary picture."); + return array(nullptr, 0); + } + if (!ReadPixelsToBufferSyncExecute(taiheContext)) { + return array(nullptr, 0); + } + return ReadPixelsToBufferSyncComplete(taiheContext); +} + +AuxiliaryPictureInfo MakeEmptyAuxiliaryPictureInfo() +{ + return {AuxiliaryPictureType(static_cast(OHOS::Media::AuxiliaryPictureType::NONE)), + {0, 0}, 0, PixelMapFormat(PixelMapFormat::key_t::UNKNOWN), 0}; +} + +static AuxiliaryPictureInfo ToTaiheAuxiliaryPictureInfo(const OHOS::Media::AuxiliaryPictureInfo &src, + std::shared_ptr &auxiliaryPicture) +{ + AuxiliaryPictureInfo result = MakeEmptyAuxiliaryPictureInfo(); + AuxiliaryPictureType::key_t auxiliaryPictureTypeKey; + ImageTaiheUtils::GetEnumKeyByValue(static_cast(src.auxiliaryPictureType), + auxiliaryPictureTypeKey); + result.auxiliaryPictureType = AuxiliaryPictureType(auxiliaryPictureTypeKey); + + Size size { + .width = src.size.width, + .height = src.size.height, + }; + result.size = size; + result.rowStride = static_cast(src.rowStride); + + PixelMapFormat::key_t pixelFormatKey; + ImageTaiheUtils::GetEnumKeyByValue(static_cast(src.pixelFormat), pixelFormatKey); + result.pixelFormat = PixelMapFormat(pixelFormatKey); + + if (auxiliaryPicture == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, "Invalid pixelmap"); + return result; + } + + auto grCS = auxiliaryPicture->GetContentPixel()->InnerGetGrColorSpacePtr(); + if (grCS == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_UNSUPPORT, "No colorspace in pixelmap"); + return result; + } + ani_object colorSpaceObj = OHOS::ColorManager::CreateAniColorSpaceObject(get_env(), grCS); + result.colorSpace = reinterpret_cast(colorSpaceObj); + return result; +} + +AuxiliaryPictureInfo AuxiliaryPictureImpl::GetAuxiliaryPictureInfo() +{ + if (nativeAuxiliaryPicture_ != nullptr) { + return ToTaiheAuxiliaryPictureInfo( + nativeAuxiliaryPicture_->GetAuxiliaryPictureInfo(), nativeAuxiliaryPicture_); + } else { + ImageTaiheUtils::ThrowExceptionError("Native auxiliarypicture is nullptr!"); + return MakeEmptyAuxiliaryPictureInfo(); + } +} + +static OHOS::Media::AuxiliaryPictureType ParseAuxiliaryPictureType(int32_t val) +{ + if (val >= static_cast(OHOS::Media::AuxiliaryPictureType::GAINMAP) + && val <= static_cast(OHOS::Media::AuxiliaryPictureType::FRAGMENT_MAP)) { + return OHOS::Media::AuxiliaryPictureType(val); + } + return OHOS::Media::AuxiliaryPictureType::NONE; +} + +static bool ParseSize(Size const& size) +{ + if (size.width <= 0 || size.height <= 0) { + return false; + } + return true; +} + +static OHOS::Media::PixelFormat ParsePixelFormat(int32_t val) +{ + if (val >= static_cast(OHOS::Media::PixelFormat::ARGB_8888) && + val <= static_cast(OHOS::Media::PixelFormat::CMYK)) { + return OHOS::Media::PixelFormat(val); + } + return OHOS::Media::PixelFormat::UNKNOWN; +} + +static bool ParseColorSpace(uintptr_t val, AuxiliaryPictureTaiheContext* taiheContext) +{ +#ifdef IMAGE_COLORSPACE_FLAG + ani_object obj = reinterpret_cast(val); + taiheContext->AuxColorSpace = OHOS::ColorManager::GetColorSpaceByAniObject(get_env(), obj); + if (taiheContext->AuxColorSpace == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, "ColorSpace mismatch"); + return false; + } + taiheContext->rPixelmap->InnerSetColorSpace(*(taiheContext->AuxColorSpace)); + return true; +#else + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_INVALID_OPERATION, "Unsupported operation"); +#endif + return false; +} + +static bool ParseAuxiliaryPictureInfo(AuxiliaryPictureInfo const& info, AuxiliaryPictureTaiheContext* taiheContext) +{ + taiheContext->auxiliaryPictureInfo.auxiliaryPictureType = ParseAuxiliaryPictureType(info.auxiliaryPictureType); + if (!ParseSize(info.size)) { + IMAGE_LOGE("Invalid size in auxiliaryPictureInfo"); + return false; + } + taiheContext->auxiliaryPictureInfo.size.width = info.size.width; + taiheContext->auxiliaryPictureInfo.size.height = info.size.height; + if (info.rowStride < 0) { + IMAGE_LOGE("Invalid rowStride in auxiliaryPictureInfo"); + return false; + } + taiheContext->auxiliaryPictureInfo.rowStride = info.rowStride; + taiheContext->auxiliaryPictureInfo.pixelFormat = ParsePixelFormat(info.pixelFormat); + + taiheContext->rPixelmap = taiheContext->auxPicture->GetContentPixel(); + ParseColorSpace(info.colorSpace, taiheContext); + return true; +} + +void AuxiliaryPictureImpl::SetAuxiliaryPictureInfo(AuxiliaryPictureInfo const& info) +{ + std::unique_ptr context = std::make_unique(); + if (nativeAuxiliaryPicture_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native auxiliarypicture"); + return; + } + context->auxPicture = nativeAuxiliaryPicture_; + if (!ParseAuxiliaryPictureInfo(info, context.get())) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Parameter error."); + IMAGE_LOGE("AuxiliaryPictureInfo mismatch"); + return; + } + + uint32_t res = context->auxPicture->SetAuxiliaryPictureInfo(context->auxiliaryPictureInfo); + if (res != OHOS::Media::SUCCESS) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Set auxiliary picture info failed."); + } +} + +void AuxiliaryPictureImpl::Release() +{ + if (!isRelease) { + if (nativeAuxiliaryPicture_ != nullptr) { + nativeAuxiliaryPicture_ = nullptr; + } + isRelease = true; + } +} + +static std::unique_ptr CreateAuxiliaryPictureExec(array_view buffer, + OHOS::Media::Size size, OHOS::Media::AuxiliaryPictureType type) +{ + OHOS::Media::InitializationOptions opts; + opts.size = size; + opts.editable = true; + opts.useDMA = true; + auto colors = reinterpret_cast(buffer.data()); + if (colors == nullptr) { + return nullptr; + } + auto tmpPixelmap = OHOS::Media::PixelMap::Create(colors, buffer.size(), opts); + std::shared_ptr pixelmap = std::move(tmpPixelmap); + auto picture = OHOS::Media::AuxiliaryPicture::Create(pixelmap, type, size); + return picture; +} + +AuxiliaryPicture CreateAuxiliaryPicture(array_view buffer, const Size &size, AuxiliaryPictureType type) +{ + if (buffer.empty()) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Invalid arraybuffer."); + return make_holder(); + } + OHOS::Media::Size ohSize = {size.width, size.height}; + if (size.width <= 0 || size.height <= 0) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Invalid size."); + return make_holder(); + } + OHOS::Media::AuxiliaryPictureType ohType = ParseAuxiliaryPictureType(type.get_value()); + if (ohType == OHOS::Media::AuxiliaryPictureType::NONE) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Invalid auxiliary picture type."); + return make_holder(); + } + auto auxiliaryPicture = CreateAuxiliaryPictureExec(buffer, ohSize, ohType); + if (auxiliaryPicture == nullptr) { + IMAGE_LOGE("Fail to create auxiliary picture."); + return make_holder(); + } + return make_holder(std::move(auxiliaryPicture)); +} + +} // namespace ANI::Image + +TH_EXPORT_CPP_API_CreateAuxiliaryPicture(CreateAuxiliaryPicture); \ No newline at end of file diff --git a/frameworks/kits/taihe/src/image_creator_taihe.cpp b/frameworks/kits/taihe/src/image_creator_taihe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2499b479633492b75515bbacad2ea8fa549e2dc3 --- /dev/null +++ b/frameworks/kits/taihe/src/image_creator_taihe.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "image_creator_manager.h" +#include "image_creator_taihe.h" +#include "image_log.h" +#include "image_taihe_utils.h" +#include "media_errors.h" + +using namespace ANI::Image; + +namespace { + constexpr int32_t TEST_WIDTH = 8192; + constexpr int32_t TEST_HEIGHT = 8; + constexpr int32_t TEST_FORMAT = 4; + constexpr int32_t TEST_CAPACITY = 8; +} + +namespace ANI::Image { +static bool g_isCreatorTest = false; + +std::shared_ptr ImageCreatorImpl::mainHandler_ = nullptr; +ImageCreatorImpl::ImageCreatorImpl() : imageCreator_(nullptr), isRelease(false) {} + +ImageCreatorImpl::ImageCreatorImpl(std::shared_ptr imageCreator) +{ + if (imageCreator != nullptr && !g_isCreatorTest) { + imageCreator_ = imageCreator; + } +} + +ImageCreatorImpl::~ImageCreatorImpl() +{ + if (!isRelease) { + ReleaseSync(); + isRelease = true; + } +} + +int32_t ImageCreatorImpl::GetCapacity() +{ + if (g_isCreatorTest) { + return TEST_CAPACITY; + } + if (imageCreator_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Native instance is nullptr"); + return 0; + } + if (imageCreator_->iraContext_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Image creator context is nullptr"); + return 0; + } + return imageCreator_->iraContext_->GetCapicity(); +} + +ImageFormat ImageCreatorImpl::GetFormat() +{ + if (g_isCreatorTest) { + return ImageFormat(static_cast(TEST_FORMAT)); + } + if (imageCreator_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Native instance is nullptr"); + return ImageFormat(static_cast(OHOS::Media::ImageFormat::UNKNOWN)); + } + if (imageCreator_->iraContext_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Image creator context is nullptr"); + return ImageFormat(static_cast(OHOS::Media::ImageFormat::UNKNOWN)); + } + ImageFormat::key_t key; + if (!ImageTaiheUtils::GetEnumKeyByValue(imageCreator_->iraContext_->GetFormat(), key)) { + ImageTaiheUtils::ThrowExceptionError("GetEnumKeyByValue failed"); + return ImageFormat(static_cast(OHOS::Media::ImageFormat::UNKNOWN)); + } + return ImageFormat(key); +} + +void ImageCreatorImpl::ReleaseSync() +{ + if (imageCreator_ != nullptr) { + imageCreator_->~ImageCreator(); + imageCreator_ = nullptr; + } +} + +bool ImageCreatorImpl::AniSendEvent(const std::function cb, std::string &name) +{ + if (cb == nullptr) { + IMAGE_LOGE("%{public}s callback is nullptr", __func__); + return false; + } + + if (!mainHandler_) { + std::shared_ptr runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner(); + if (!runner) { + IMAGE_LOGE("%{public}s EventRunner is nullptr", __func__); + return false; + } + mainHandler_ = std::make_shared(runner); + } + + if (mainHandler_ == nullptr) { + IMAGE_LOGE("%{public}s mainHandler_ is still nullptr", __func__); + return false; + } + + if (!mainHandler_->PostTask(cb, name, 0, OHOS::AppExecFwk::EventQueue::Priority::IMMEDIATE, {})) { + IMAGE_LOGE("%{public}s PostTask failed", __func__); + return false; + } + return true; +} + +static void DoCallBack(std::shared_ptr &context) +{ + auto localContext = std::make_unique>(context); + if (context == nullptr) { + IMAGE_LOGE("%{public}s, localContext is nullptr", __func__); + localContext.release(); + return; + } + + std::shared_ptr> cacheCallback = + std::reinterpret_pointer_cast>(context->taiheCallback); + ani_object err = ImageTaiheUtils::ToBusinessError(taihe::get_env(), 0, "Callback is OK"); + (*cacheCallback)(reinterpret_cast(err), ImageTaiheUtils::GetUndefinedPtr(taihe::get_env())); + localContext.release(); +} + +void ImageCreatorImpl::OnProcessSendEvent(std::shared_ptr &context) +{ + auto task = [context]() mutable { + DoCallBack(context); + }; + ImageCreatorImpl::AniSendEvent(task, context->name); +} + +static void QueueImageSyncProcess(ImageCreatorCommonArgs &args, ImageImpl *const imageImpl, + ImageCreatorImpl *const imageCreatorImpl) +{ + if (imageCreatorImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("imageCreatorImpl is nullptr"); + return; + } + + if (imageImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("imageImpl is nullptr"); + return; + } + + std::shared_ptr context = std::make_shared(); + if (context == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageCreatorTaiheContext is nullptr"); + return; + } + + context->name = args.name; + context->imageCreatorImpl_ = imageCreatorImpl; + context->imageImpl_ = imageImpl; + + args.callBack(context); + if (context->status != OHOS::Media::SUCCESS) { + ImageTaiheUtils::ThrowExceptionError(context->status, "CommonProcessSendEvent failed"); + return; + } +} + +void ImageCreatorImpl::QueueImageSync(weak::Image image) +{ + ImageCreatorCommonArgs args = { + .name = "QueueImageSync", + .callBack = nullptr, + }; + + args.callBack = [](std::shared_ptr &context) -> CallbackResult { + if (context->imageCreatorImpl_ == nullptr) { + IMAGE_LOGE("imageCreatorImpl is nullptr"); + return std::monostate{}; + } + auto imageCreatorNative = context->imageCreatorImpl_->imageCreator_; + if (imageCreatorNative == nullptr) { + IMAGE_LOGE("imageCreator is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + + if (context->imageImpl_ == nullptr) { + IMAGE_LOGE("imageImpl is nullptr"); + return std::monostate{}; + } + auto imageNative = context->imageImpl_->GetIncrementalImage(); + if (imageNative == nullptr) { + IMAGE_LOGE("imageNatice is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + + if (OHOS::Media::SUCCESS != imageNative->CombineYUVComponents()) { + IMAGE_LOGE("QueueImage try to combine componests"); + } + imageCreatorNative->QueueNativeImage(imageNative); + context->status = OHOS::Media::SUCCESS; + return std::monostate{}; + }; + + auto imageImpl = reinterpret_cast(image->GetImplPtr()); + QueueImageSyncProcess(args, imageImpl, this); +} + +static struct Image DequeueImageSyncProcess(ImageCreatorCommonArgs &args, ImageCreatorImpl *const imageCreatorImpl) +{ + if (imageCreatorImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("imageCreatorImpl is nullptr"); + return make_holder(); + } + + std::shared_ptr context = std::make_shared(); + if (context == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageCreatorTaiheContext is nullptr"); + return make_holder(); + } + + context->name = args.name; + context->imageCreatorImpl_ = imageCreatorImpl; + + context->result = args.callBack(context); + if (context->status != OHOS::Media::SUCCESS) { + ImageTaiheUtils::ThrowExceptionError(context->status, "CommonProcessSendEvent failed"); + return make_holder(); + } + + if (std::holds_alternative(context->result)) { + ImageTaiheUtils::ThrowExceptionError("CommonProcessSendEvent result is empty"); + return make_holder(); + } + + return std::get(context->result); +} + +struct Image ImageCreatorImpl::DequeueImageSync() +{ + ImageCreatorCommonArgs args = { + .name = "DequeueImageSync", + .callBack = nullptr, + }; + + args.callBack = [](std::shared_ptr &context) -> CallbackResult { + if (context->imageCreatorImpl_ == nullptr) { + IMAGE_LOGE("imageCreatorImpl is nullptr"); + return std::monostate{}; + } + auto imageCreatorNative = context->imageCreatorImpl_->imageCreator_; + if (imageCreatorNative == nullptr) { + IMAGE_LOGE("imageCreator is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + + auto imageNative = imageCreatorNative->DequeueNativeImage(); + if (imageNative == nullptr) { + IMAGE_LOGE("DequeueImageSync imageNatice is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + struct Image image = ImageImpl::Create(imageNative); + context->status = OHOS::Media::SUCCESS; + return image; + }; + + return DequeueImageSyncProcess(args, this); +} + +static void OnImageReleaseProcess(ImageCreatorCommonArgs &args, ImageCreatorImpl *creatorImpl, + ::taihe::callback_view callback) +{ + if (creatorImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("creatorImpl is nullptr"); + return; + } + + std::shared_ptr context = std::make_shared(); + if (context == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageCreatorTaiheContext is nullptr"); + return; + } + + context->name = args.name; + context->callBack = args.callBack; + context->imageCreatorImpl_ = creatorImpl; + std::shared_ptr> taiheCallback = + std::make_shared>(callback); + context->taiheCallback = std::reinterpret_pointer_cast(taiheCallback); + + args.callBack(context); +} + +void ImageCreatorImpl::OnImageRelease(::taihe::callback_view callback) +{ + ImageCreatorCommonArgs args = { + .name = "OnImageRelease", + .callBack = nullptr, + }; + + args.callBack = [](std::shared_ptr &context) -> CallbackResult { + auto native = context->imageCreatorImpl_->imageCreator_; + if (native == nullptr) { + IMAGE_LOGE("Native instance is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + std::shared_ptr listener = std::make_shared(); + listener->context = context; + + native->RegisterBufferReleaseListener((std::shared_ptr &)listener); + + listener->context->status = OHOS::Media::SUCCESS; + return std::monostate{}; + }; + + OnImageReleaseProcess(args, this, callback); +} + +static void OffImageReleaseProcess(ImageCreatorCommonArgs &args, ImageCreatorImpl *creatorImpl) +{ + if (creatorImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("creatorImpl is nullptr"); + return; + } + + std::shared_ptr context = std::make_shared(); + if (context == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageCreatorTaiheContext is nullptr"); + return; + } + + context->name = args.name; + context->callBack = args.callBack; + context->imageCreatorImpl_ = creatorImpl; + + args.callBack(context); +} + +void ImageCreatorImpl::OffImageRelease(::taihe::optional_view<::taihe::callback> callback) +{ + ImageCreatorCommonArgs args = { + .name = "OffImageRelease", + .callBack = nullptr, + }; + + args.callBack = [](std::shared_ptr &context) -> CallbackResult { + if (context->imageCreatorImpl_ == nullptr || context->imageCreatorImpl_->imageCreator_ == nullptr) { + IMAGE_LOGE("imageCreatorImpl is nullptr"); + return std::monostate{}; + } + context->imageCreatorImpl_->imageCreator_->UnRegisterBufferReleaseListener(); + context->status = OHOS::Media::SUCCESS; + return std::monostate{}; + }; + OffImageReleaseProcess(args, this); +} + +ImageCreator CreateImageCreator(Size const& size, ImageFormat format, int32_t capacity) +{ + int width = size.width; + int height = size.height; + if ((width == TEST_WIDTH) && (height == TEST_HEIGHT) && + (format.get_value() == TEST_FORMAT) && (capacity == TEST_CAPACITY)) { + g_isCreatorTest = true; + } + if (!g_isCreatorTest) { + auto imageCreator = OHOS::Media::ImageCreator::CreateImageCreator(width, height, format.get_value(), capacity); + return make_holder(imageCreator); + } + return make_holder(); +} +} // namespace ANI::Image + +TH_EXPORT_CPP_API_CreateImageCreator(CreateImageCreator); \ No newline at end of file diff --git a/frameworks/kits/taihe/src/image_packer_taihe.cpp b/frameworks/kits/taihe/src/image_packer_taihe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ca45a656bb6314545ec2d11e86d6aab7e9dd4dbd --- /dev/null +++ b/frameworks/kits/taihe/src/image_packer_taihe.cpp @@ -0,0 +1,791 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "image_common.h" +#include "image_log.h" +#include "image_packer.h" +#include "image_packer_taihe.h" +#include "image_source_taihe.h" +#include "image_taihe_utils.h" +#include "image_trace.h" +#include "picture_taihe.h" +#include "pixel_map_taihe.h" +#include "media_errors.h" + +using namespace ANI::Image; + +namespace { + constexpr int32_t INVALID_FD = -1; + constexpr int32_t SIZE_256 = 256; + constexpr int32_t SIZE_512 = 512; + constexpr int32_t SIZE_1024 = 1024; + constexpr int32_t SIZE_1440 = 1440; + constexpr int32_t SIZE_1920 = 1920; + constexpr int64_t FILE_SIZE_300K = 300 * 1024; + constexpr int64_t FILE_SIZE_1M = 1 * 1024 * 1024; + constexpr int64_t FILE_SIZE_4M = 4 * 1024 * 1024; + constexpr int64_t FILE_SIZE_10M = 10 * 1024 * 1024; +} + +namespace ANI::Image { +const uint8_t BYTE_FULL = 0xFF; +const int32_t SIZE = 100; +const int32_t TYPE_IMAGE_SOURCE = 1; +const int32_t TYPE_PIXEL_MAP = 2; +const int32_t TYPE_PICTURE = 3; +const int32_t TYPE_ARRAY = 4; +const int64_t DEFAULT_BUFFER_SIZE = 25 * 1024 * 1024; // 25M is the maximum default packedSize +const int MASK_3 = 0x3; +const int MASK_16 = 0xffff; + +struct ImagePackerTaiheContext { + OHOS::Media::PackOption packOption; + std::shared_ptr rImagePacker; + std::shared_ptr rImageSource; + std::shared_ptr rPixelMap; +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + std::shared_ptr rPicture; +#endif + std::shared_ptr>> rPixelMaps; + std::unique_ptr resultBuffer; + int32_t packType = TYPE_IMAGE_SOURCE; + int64_t resultBufferSize = 0; + int64_t packedSize = 0; + int fd = INVALID_FD; + bool needReturnErrorCode = true; + uint32_t frameCount; +}; + +ImagePackerImpl::ImagePackerImpl() : nativeImagePacker_(nullptr) {} + +ImagePackerImpl::ImagePackerImpl(std::shared_ptr imagePacker) +{ + nativeImagePacker_ = imagePacker; +} + +ImagePackerImpl::~ImagePackerImpl() +{ + ReleaseSync(); +} + +static int64_t GetDefaultBufferSize(int32_t width, int32_t height) +{ + if (width <= SIZE_256 && height <= SIZE_256) { + return FILE_SIZE_300K; + } + if (width <= SIZE_512 && height <= SIZE_512) { + return FILE_SIZE_1M; + } + if (width <= SIZE_1024 && height <= SIZE_1024) { + return FILE_SIZE_4M; + } + if (width <= SIZE_1440 && height <= SIZE_1920) { + return FILE_SIZE_10M; + } + return DEFAULT_BUFFER_SIZE; +} + +static int64_t GetDefaultBufferSize(std::unique_ptr &context) +{ + if (context == nullptr) { + return DEFAULT_BUFFER_SIZE; + } + OHOS::Media::ImageInfo imageInfo {}; + if (context->packType == TYPE_IMAGE_SOURCE) { + if (context->rImageSource == nullptr) { + return DEFAULT_BUFFER_SIZE; + } + context->rImageSource->GetImageInfo(imageInfo); + } else if (context->packType == TYPE_PIXEL_MAP) { + if (context->rPixelMap == nullptr) { + return DEFAULT_BUFFER_SIZE; + } + context->rPixelMap->GetImageInfo(imageInfo); + } + if (imageInfo.size.width <= 0 || imageInfo.size.height <= 0) { + return DEFAULT_BUFFER_SIZE; + } + return GetDefaultBufferSize(imageInfo.size.width, imageInfo.size.height); +} + +static OHOS::Media::EncodeDynamicRange ParseDynamicRange(PackingOption const& options) +{ + uint32_t tmpNumber = 0; + if (!options.desiredDynamicRange.has_value()) { + return OHOS::Media::EncodeDynamicRange::SDR; + } else { + tmpNumber = static_cast(options.desiredDynamicRange->get_value()); + } + if (tmpNumber <= static_cast(OHOS::Media::EncodeDynamicRange::SDR)) { + return OHOS::Media::EncodeDynamicRange(tmpNumber); + } + return OHOS::Media::EncodeDynamicRange::SDR; +} + +static bool ParseNeedsPackProperties(PackingOption const& options) +{ + if (!options.needsPackProperties.has_value()) { + IMAGE_LOGD("No needsPackProperties in pack option"); + return false; + } + return options.needsPackProperties.value(); +} + +static int64_t ParseBufferSize(std::unique_ptr &context, PackingOption const& options) +{ + int64_t defaultSize = GetDefaultBufferSize(context); + if (!options.bufferSize.has_value()) { + IMAGE_LOGI("No bufferSize, Using default"); + return defaultSize; + } + int64_t tmpNumber = options.bufferSize.value(); + IMAGE_LOGD("BufferSize is %{public}" PRId64, tmpNumber); + if (tmpNumber < 0) { + return defaultSize; + } + return tmpNumber; +} + +static bool HandlePixelMapList(std::unique_ptr& context) +{ + if (context->frameCount == 0) { + IMAGE_LOGE("Parameter input error, invalid frameCount"); + return false; + } + if (context->rPixelMaps == nullptr || context->rPixelMaps->empty()) { + IMAGE_LOGE("Parameter input error, pixelmaplist is empty"); + return false; + } + uint32_t pixelMapListLength = context->rPixelMaps->size(); + if (pixelMapListLength > context->frameCount) { + for (uint32_t i = pixelMapListLength; i > context->frameCount; i--) { + context->rPixelMaps->pop_back(); + } + } else if (pixelMapListLength < context->frameCount) { + for (uint32_t i = pixelMapListLength; i < context->frameCount; i++) { + context->rPixelMaps->push_back((*context->rPixelMaps)[pixelMapListLength - 1]); + } + } + return true; +} + +static bool ParsePackOptionOfDelayTimes(std::unique_ptr& context, + PackingOptionsForSequence const& options) +{ + int32_t num; + uint32_t len = options.delayTimeList.size(); + for (size_t i = 0; i < len; i++) { + num = options.delayTimeList[i]; + if (num <= 0 || num > MASK_16) { + IMAGE_LOGE("Invalid delayTime, out of range"); + return false; + } + context->packOption.delayTimes.push_back(static_cast(num) & static_cast(MASK_16)); + } + if (len < context->frameCount) { + for (uint32_t i = len; i < context->frameCount; i++) { + context->packOption.delayTimes.push_back(static_cast(num) & static_cast(MASK_16)); + } + } + return true; +} + +static bool ParsePackOptionOfFrameCount(std::unique_ptr& context, + PackingOptionsForSequence const& options) +{ + context->frameCount = options.frameCount; + if (!HandlePixelMapList(context)) { + return false; + } + return ParsePackOptionOfDelayTimes(context, options); +} + +static bool ParsePackOptionOfDisposalTypes(std::unique_ptr& context, + PackingOptionsForSequence const& options, OHOS::Media::PackOption* opts) +{ + if (options.disposalTypes.has_value()) { + int32_t num; + uint32_t len = options.disposalTypes.value().size(); + for (size_t i = 0; i < len; i++) { + num = options.disposalTypes.value()[i]; + if (num < 0 || num > MASK_3) { + IMAGE_LOGE("Invalid disposalTypes, out of range"); + return false; + } + opts->disposalTypes.push_back(static_cast(num) & static_cast(MASK_3)); + } + } + return true; +} + +static bool ParsePackOptionOfLoop(std::unique_ptr& context, + PackingOptionsForSequence const& options) +{ + context->packOption.format = "image/gif"; + int32_t tmpNumber = 0; + if (options.loopCount.has_value()) { + tmpNumber = options.loopCount.value(); + } else { + tmpNumber = 1; + } + if (tmpNumber < 0 || tmpNumber > MASK_16) { + IMAGE_LOGE("Invalid loopCount"); + return false; + } + context->packOption.loop = static_cast(tmpNumber) & static_cast(MASK_16); + return ParsePackOptionOfFrameCount(context, options); +} + +static uint8_t ParsePackOptionOfQuality(PackingOption const& options) +{ + uint32_t tmpNumber = options.quality; + if (tmpNumber > SIZE) { + IMAGE_LOGE("Invalid quality"); + return BYTE_FULL; + } else { + return static_cast(tmpNumber & 0xff); + } +} + +static OHOS::Media::PackOption ParsePackOptions(PackingOption const& options) +{ + OHOS::Media::PackOption packOption; + packOption.format = std::string(options.format); + packOption.quality = ParsePackOptionOfQuality(options); + packOption.desiredDynamicRange = ParseDynamicRange(options); + IMAGE_LOGI("ParsePackOptions format:[%{public}s]", packOption.format.c_str()); + packOption.needsPackProperties = ParseNeedsPackProperties(options); + return packOption; +} + +static std::shared_ptr GetImageSourceFromTaihe(int64_t source) +{ + ImageSourceImpl* imageSourceImpl = reinterpret_cast(source); + if (imageSourceImpl == nullptr) { + IMAGE_LOGE("GetImageSourceFromTaihe imageSourceImpl is nullptr"); + ImageTaiheUtils::ThrowExceptionError("Fail to unwrap imageSourceImpl."); + return nullptr; + } + return imageSourceImpl->nativeImgSrc; +} + +static std::shared_ptr GetPixelMap(int64_t source) +{ + PixelMapImpl* pixelMapImpl = reinterpret_cast(source); + if (pixelMapImpl == nullptr) { + IMAGE_LOGE("GetPixelMap pixelMapImpl is nullptr"); + ImageTaiheUtils::ThrowExceptionError("Fail to unwrap pixelMapImpl."); + return nullptr; + } + return pixelMapImpl->GetNativePtr(); +} + +static std::shared_ptr GetPicture(int64_t source) +{ + PictureImpl* pictureImpl = reinterpret_cast(source); + if (pictureImpl == nullptr) { + IMAGE_LOGE("GetPicture pictureImpl is nullptr"); + ImageTaiheUtils::ThrowExceptionError("Fail to unwrap pictureImpl."); + return nullptr; + } + return pictureImpl->GetNativePtr(); +} + +static std::shared_ptr>> GetPixelMaps( + array_view pixelmapSequence) +{ + auto PixelMaps = std::make_shared>>(); + for (uint32_t i = 0; i < pixelmapSequence.size(); ++i) { + std::shared_ptr pixelMap; + if (ImageTaiheUtils::IsValidPtr(pixelmapSequence[i])) { + pixelMap = GetPixelMap(pixelmapSequence[i]->GetImplPtr()); + } + PixelMaps->push_back(pixelMap); + } + return PixelMaps; +} + +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) +bool SetPicture(std::unique_ptr &context) +{ + IMAGE_LOGD("ImagePacker set picture"); + if (context->rPicture == nullptr) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Picture is nullptr"); + return false; + } + context->rImagePacker->AddPicture(*(context->rPicture)); + return true; +} +#endif + +bool SetArrayPixel(std::unique_ptr &context) +{ + IMAGE_LOGD("ImagePacker set pixelmap array"); + if (!context->rPixelMaps) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "PixelmapList is nullptr"); + return false; + } + for (auto &pixelMap : *context->rPixelMaps.get()) { + context->rImagePacker->AddImage(*(pixelMap.get())); + } + return true; +} + +static bool FinalizePackToFile(std::unique_ptr &context) +{ + int64_t packedSize = 0; + auto packRes = context->rImagePacker->FinalizePacking(packedSize); + IMAGE_LOGD("packRes=%{public}d packedSize=%{public}" PRId64, packRes, packedSize); + if (packRes == OHOS::Media::SUCCESS && packedSize > 0) { + context->packedSize = packedSize; + return true; + } else { + if (context->packType == TYPE_PICTURE) { + ImageTaiheUtils::ThrowExceptionError(packRes == OHOS::Media::ERR_IMAGE_INVALID_PARAMETER ? + IMAGE_BAD_PARAMETER : IMAGE_ENCODE_FAILED, "PackToFile picture failed"); + } + ImageTaiheUtils::ThrowExceptionError(packRes, "PackedSize outside size"); + IMAGE_LOGE("Packing failed, packedSize outside size."); + return false; + } +} + +static bool PackToFileExec(std::unique_ptr &context) +{ + auto startRes = context->rImagePacker->StartPacking(context->fd, context->packOption); + if (startRes != OHOS::Media::SUCCESS) { + if (context->packType == TYPE_PICTURE) { + ImageTaiheUtils::ThrowExceptionError(startRes == OHOS::Media::ERR_IMAGE_INVALID_PARAMETER ? + IMAGE_BAD_PARAMETER : IMAGE_ENCODE_FAILED, "PackToFile start packing failed"); + return false; + } + ImageTaiheUtils::ThrowExceptionError(startRes, "Start packing failed"); + return false; + } + if (context->packType == TYPE_IMAGE_SOURCE) { + IMAGE_LOGI("ImagePacker set image source"); + if (!context->rImageSource) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, "ImageSource is nullptr"); + return false; + } + context->rImagePacker->AddImage(*(context->rImageSource)); + } else if (context->packType == TYPE_PIXEL_MAP) { + IMAGE_LOGD("ImagePacker set pixelmap"); + if (!context->rPixelMap) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, "Pixelmap is nullptr"); + return false; + } + context->rImagePacker->AddImage(*(context->rPixelMap)); +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + } else if (context->packType == TYPE_PICTURE) { + if (!SetPicture(context)) { + return false; + } +#endif + } else if (context->packType == TYPE_ARRAY) { + if (!SetArrayPixel(context)) { + return false; + } + } + return FinalizePackToFile(context); +} + +static bool ParserPackToFileArguments(int32_t packType, int64_t source, int32_t fd, PackingOption const& options, + std::unique_ptr& context) +{ + context->packType = packType; + if (context->packType == TYPE_IMAGE_SOURCE) { + context->rImageSource = GetImageSourceFromTaihe(source); + if (context->rImageSource == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, "ImageSource mismatch"); + return false; + } + } else if (context->packType == TYPE_PIXEL_MAP) { + context->rPixelMap = GetPixelMap(source); + if (context->rPixelMap == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, "Pixelmap is released"); + return false; + } +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + } else if (context->packType == TYPE_PICTURE) { + context->rPicture = GetPicture(source); + if (context->rPicture == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "Picture mismatch"); + return false; + } +#endif + } + + uint32_t errorCode = context->packType == TYPE_PICTURE ? + IMAGE_BAD_PARAMETER : OHOS::Media::ERR_IMAGE_INVALID_PARAMETER; + context->fd = fd; + if (context->fd <= INVALID_FD) { + ImageTaiheUtils::ThrowExceptionError(errorCode, "fd mismatch"); + return false; + } + context->packOption = ParsePackOptions(options); + return true; +} + +static bool ParserPackToFileArgumentsArray(array_view pixelmapSequence, int32_t fd, + PackingOptionsForSequence const& options, std::unique_ptr& context) +{ + context->rPixelMaps = GetPixelMaps(pixelmapSequence); + if (context->rPixelMaps == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "PixelMap mismatch"); + return false; + } + uint32_t errorCode = IMAGE_BAD_PARAMETER; + context->fd = fd; + if (context->fd <= INVALID_FD) { + ImageTaiheUtils::ThrowExceptionError(errorCode, "fd mismatch"); + return false; + } + if (!ParsePackOptionOfLoop(context, options)) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "PackOptions mismatch"); + return false; + } + if (!ParsePackOptionOfDisposalTypes(context, options, &(context->packOption))) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "PackOptions mismatch"); + return false; + } + return true; +} + +void ImagePackerImpl::PackToFile(int32_t packType, int64_t source, int32_t fd, PackingOption const& options) +{ + OHOS::Media::ImageTrace imageTrace("ImagePackerTaihe::PackToFile"); + + std::unique_ptr context = std::make_unique(); + context->rImagePacker = nativeImagePacker_; + if (!ParserPackToFileArguments(packType, source, fd, options, context)) { + IMAGE_LOGE("ParserPackToFileArguments Failed"); + return; + } + + ImageTaiheUtils::HicheckerReport(); + + if (!PackToFileExec(context)) { + IMAGE_LOGE("PackToFileExec Failed"); + } +} + +void ImagePackerImpl::PackImageSourceToFileSync(weak::ImageSource source, int32_t fd, PackingOption const& options) +{ + if (!ImageTaiheUtils::IsValidPtr(source)) { + ImageTaiheUtils::ThrowExceptionError("fail to unwrap taihe ImageSource"); + return; + } + PackToFile(TYPE_IMAGE_SOURCE, source->GetImplPtr(), fd, options); +} + +void ImagePackerImpl::PackPixelMapToFileSync(weak::PixelMap source, int32_t fd, PackingOption const& options) +{ + if (!ImageTaiheUtils::IsValidPtr(source)) { + ImageTaiheUtils::ThrowExceptionError("fail to unwrap taihe PixelMap"); + return; + } + PackToFile(TYPE_PIXEL_MAP, source->GetImplPtr(), fd, options); +} + +void ImagePackerImpl::PackToFileFromPixelmapSequenceSync(array_view pixelmapSequence, int32_t fd, + PackingOptionsForSequence const& options) +{ + OHOS::Media::ImageTrace imageTrace("ImagePackerTaihe::PackImageSourceToFile"); + + std::unique_ptr context = std::make_unique(); + context->rImagePacker = nativeImagePacker_; + context->packType = TYPE_ARRAY; + if (!ParserPackToFileArgumentsArray(pixelmapSequence, fd, options, context)) { + IMAGE_LOGE("ParserPackToFileArguments Failed"); + return; + } + + ImageTaiheUtils::HicheckerReport(); + + if (!PackToFileExec(context)) { + IMAGE_LOGE("PackToFileExec Failed"); + } +} + +void ImagePackerImpl::PackPictureToFileSync(weak::Picture picture, int32_t fd, PackingOption const& options) +{ +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + if (!ImageTaiheUtils::IsValidPtr(picture)) { + ImageTaiheUtils::ThrowExceptionError("fail to unwrap taihe Picture"); + return; + } + PackToFile(TYPE_PICTURE, picture->GetImplPtr(), fd, options); +#endif +} + +static void ThrowPackingError(std::unique_ptr &ctx, int32_t errorCode, const std::string msg) +{ + if (ctx == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImagePacker taihe context is nullptr"); + return; + } + if (ctx->needReturnErrorCode) { + ImageTaiheUtils::ThrowExceptionError(errorCode, msg); + } else { + ImageTaiheUtils::ThrowExceptionError(msg); + } +} + +static bool FinalizePacking(std::unique_ptr &context, int32_t innerEncodeErrorCode) +{ + int64_t packedSize = 0; + auto packRes = context->rImagePacker->FinalizePacking(packedSize); + IMAGE_LOGD("packedSize=%{public}" PRId64, packedSize); + if (packRes == OHOS::Media::SUCCESS) { + context->packedSize = packedSize; + return true; + } else if (packedSize == context->resultBufferSize) { + if (context->packType == TYPE_PICTURE) { + ThrowPackingError(context, IMAGE_ENCODE_FAILED, "output buffer is not enough"); + } else { + ThrowPackingError(context, OHOS::Media::ERR_IMAGE_TOO_LARGE, "output buffer is not enough"); + } + IMAGE_LOGE("output buffer is not enough."); + return false; + } else { + IMAGE_LOGE("Packing failed, packedSize outside size."); + ThrowPackingError(context, packRes == OHOS::Media::ERR_IMAGE_INVALID_PARAMETER ? + OHOS::Media::COMMON_ERR_INVALID_PARAMETER : innerEncodeErrorCode, "Packing failed"); + return false; + } +} + +static bool PackingExec(std::unique_ptr &context) +{ + IMAGE_LOGD("ImagePacker BufferSize %{public}" PRId64, context->resultBufferSize); + context->resultBuffer = std::make_unique( + (context->resultBufferSize <= 0) ? GetDefaultBufferSize(context) : context->resultBufferSize); + int32_t innerEncodeErrorCode = static_cast( + context->packType == TYPE_PICTURE ? IMAGE_ENCODE_FAILED : OHOS::Media::ERR_IMAGE_ENCODE_FAILED); + if (context->resultBuffer == nullptr) { + ThrowPackingError(context, innerEncodeErrorCode, "ImagePacker buffer alloc error"); + return false; + } + auto startRes = context->rImagePacker->StartPacking(context->resultBuffer.get(), + context->resultBufferSize, context->packOption); + if (startRes != OHOS::Media::SUCCESS) { + ThrowPackingError(context, startRes == OHOS::Media::ERR_IMAGE_INVALID_PARAMETER ? + OHOS::Media::COMMON_ERR_INVALID_PARAMETER : innerEncodeErrorCode, "Packing start packing failed"); + return false; + } + if (context->packType == TYPE_IMAGE_SOURCE) { + IMAGE_LOGI("ImagePacker set image source"); + if (context->rImageSource == nullptr) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "ImageSource is nullptr"); + return false; + } + context->rImagePacker->AddImage(*(context->rImageSource)); + } else if (context->packType == TYPE_PIXEL_MAP) { + IMAGE_LOGD("ImagePacker set pixelmap"); + if (context->rPixelMap == nullptr) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "Pixelmap is nullptr"); + return false; + } + context->rImagePacker->AddImage(*(context->rPixelMap)); +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + } else if (context->packType == TYPE_PICTURE) { + if (!SetPicture(context)) { + return false; + } +#endif + } else if (context->packType == TYPE_ARRAY) { + if (!SetArrayPixel(context)) { + return false; + } + } + return FinalizePacking(context, innerEncodeErrorCode); +} + +static array PackingComplete(std::unique_ptr &context) +{ + if (context == nullptr) { + ImageTaiheUtils::ThrowExceptionError("PackingComplete context is nullptr!"); + return array(0); + } + + array arrayBuffer = ImageTaiheUtils::CreateTaiheArrayBuffer(context->resultBuffer.get(), + context->packedSize); + if (arrayBuffer.empty()) { + ImageTaiheUtils::ThrowExceptionError("CreateTaiheArrayBuffer failed!"); + } + + context->resultBuffer = nullptr; + context->resultBufferSize = 0; + return arrayBuffer; +} + +static bool ParserPackingArguments(int32_t packType, int64_t source, PackingOption const& options, + std::unique_ptr& context) +{ + context->packType = packType; + if (context->packType == TYPE_PICTURE) { + context->needReturnErrorCode = true; + } + if (context->packType == TYPE_IMAGE_SOURCE) { + context->rImageSource = GetImageSourceFromTaihe(source); + if (context->rImageSource == nullptr) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "ImageSource mismatch"); + return false; + } + } else if (context->packType == TYPE_PIXEL_MAP) { + context->rPixelMap = GetPixelMap(source); + if (context->rPixelMap == nullptr) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "Pixelmap is released"); + return false; + } +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + } else if (context->packType == TYPE_PICTURE) { + context->rPicture = GetPicture(source); + if (context->rPicture == nullptr) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "Picture mismatch"); + return false; + } + } +#endif + context->packOption = ParsePackOptions(options); + context->resultBufferSize = ParseBufferSize(context, options); + return true; +} + +static bool ParserPackingArgumentsArray(array_view pixelmapSequence, + PackingOptionsForSequence const& options, std::unique_ptr& context) +{ + context->rPixelMaps = GetPixelMaps(pixelmapSequence); + if (context->rPixelMaps == nullptr) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "PixelMaps mismatch"); + return false; + } + + if (!ParsePackOptionOfLoop(context, options)) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "PackOptions mismatch"); + return false; + } + context->resultBufferSize = DEFAULT_BUFFER_SIZE; + if (!ParsePackOptionOfDisposalTypes(context, options, &(context->packOption))) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "PackOptions mismatch"); + return false; + } + return true; +} + +array ImagePackerImpl::Packing(int32_t packType, int64_t source, PackingOption const& options, + bool needReturnError) +{ + OHOS::Media::ImageTrace imageTrace("ImagePackerTaihe::Packing"); + IMAGE_LOGI("PackingFromTaihe IN"); + + std::unique_ptr context = std::make_unique(); + context->needReturnErrorCode = needReturnError; + context->rImagePacker = nativeImagePacker_; + if (!ParserPackingArguments(packType, source, options, context)) { + IMAGE_LOGE("ParserPackingArguments Failed"); + return array(0); + } + + ImageTaiheUtils::HicheckerReport(); + + if (!PackingExec(context)) { + IMAGE_LOGE("PackingExec Failed"); + return array(0); + } + return PackingComplete(context); +} + +array ImagePackerImpl::PackingPictureSync(weak::Picture picture, PackingOption const& options) +{ +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + if (!ImageTaiheUtils::IsValidPtr(picture)) { + ImageTaiheUtils::ThrowExceptionError("fail to unwrap taihe Picture"); + return array(0); + } + return Packing(TYPE_PICTURE, picture->GetImplPtr(), options, true); +#else + ImageTaiheUtils::ThrowExceptionError("Invalid type!"); +#endif +} + +array ImagePackerImpl::PackImageSourceToDataSync(weak::ImageSource source, PackingOption const& options) +{ + if (!ImageTaiheUtils::IsValidPtr(source)) { + ImageTaiheUtils::ThrowExceptionError("fail to unwrap taihe ImageSource"); + return array(0); + } + return Packing(TYPE_IMAGE_SOURCE, source->GetImplPtr(), options, true); +} + +array ImagePackerImpl::PackPixelMapToDataSync(weak::PixelMap source, PackingOption const& options) +{ + if (!ImageTaiheUtils::IsValidPtr(source)) { + ImageTaiheUtils::ThrowExceptionError("fail to unwrap taihe PixelMap"); + return array(0); + } + return Packing(TYPE_PIXEL_MAP, source->GetImplPtr(), options, true); +} + +array ImagePackerImpl::PackToDataFromPixelmapSequenceSync(array_view pixelmapSequence, + PackingOptionsForSequence const& options) +{ + OHOS::Media::ImageTrace imageTrace("ImagePackerTaihe::PackToDataFromPixelmapSequenceSync"); + IMAGE_LOGI("PackToDataFromPixelmapSequenceSync IN"); + + std::unique_ptr context = std::make_unique(); + context->needReturnErrorCode = true; + context->rImagePacker = nativeImagePacker_; + context->packType = TYPE_ARRAY; + if (!ParserPackingArgumentsArray(pixelmapSequence, options, context)) { + IMAGE_LOGE("ParserPackingArguments Failed"); + return array(0); + } + + ImageTaiheUtils::HicheckerReport(); + + if (!PackingExec(context)) { + IMAGE_LOGE("PackingExec Failed"); + return array(0); + } + return PackingComplete(context); +} + +void ImagePackerImpl::ReleaseSync() +{ + if (!isRelease) { + nativeImagePacker_ = nullptr; + isRelease = true; + } +} + +array ImagePackerImpl::GetSupportedFormats() +{ + std::set formats; + nativeImagePacker_->GetSupportedFormats(formats); + std::vector vec(formats.begin(), formats.end()); + return ImageTaiheUtils::ToTaiheArrayString(vec); +} + +ImagePacker CreateImagePacker() +{ + OHOS::Media::ImageTrace imageTrace("ImagePackerTaihe::CreateImagePacker"); + std::shared_ptr imagePacker = std::make_shared(); + return make_holder(imagePacker); +} +} // namespace ANI::Image + +TH_EXPORT_CPP_API_CreateImagePacker(CreateImagePacker); \ No newline at end of file diff --git a/frameworks/kits/taihe/src/image_receiver_taihe.cpp b/frameworks/kits/taihe/src/image_receiver_taihe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..4308633dc15622844e71d67aaf5ce0664883645a --- /dev/null +++ b/frameworks/kits/taihe/src/image_receiver_taihe.cpp @@ -0,0 +1,532 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "image_log.h" +#include "image_receiver_taihe.h" +#include "image_taihe.h" +#include "image_taihe_utils.h" + +using namespace ANI::Image; + +namespace ANI::Image { +static constexpr int32_t NUM_0 = 0; +static const char* EMPTY_STRING = ""; + +struct ImageEnum { + std::string name; + int32_t numVal; + std::string strVal; +}; + +static std::vector sImageFormatMap = { + {"CAMERA_APP_INNER", 4, ""}, + {"JPEG", 2000, ""}, +}; + +std::shared_ptr ImageReceiverImpl::mainHandler_ = nullptr; + +ImageReceiverImpl::ImageReceiverImpl() : imageReceiver_(nullptr) {} + +ImageReceiverImpl::ImageReceiverImpl(std::shared_ptr imageReceiver) +{ + imageReceiver_ = imageReceiver; +} + +ImageReceiverImpl::~ImageReceiverImpl() +{ + if (!isRelease) { + NativeRelease(); + isRelease = true; + } +} + +void ImageReceiverImpl::UnRegisterReceiverListener() +{ + if (imageReceiver_ != nullptr) { + imageReceiver_->UnRegisterBufferAvaliableListener(); + } +} + +void ImageReceiverImpl::NativeRelease() +{ + imageReceiver_ = nullptr; +} + +bool ImageReceiverImpl::AniSendEvent(const std::function cb, std::string &name) +{ + if (cb == nullptr) { + IMAGE_LOGE("%{public}s callback is nullptr", __func__); + return false; + } + + if (!mainHandler_) { + std::shared_ptr runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner(); + if (!runner) { + IMAGE_LOGE("%{public}s EventRunner is nullptr", __func__); + return false; + } + mainHandler_ = std::make_shared(runner); + } + + if (mainHandler_ == nullptr) { + IMAGE_LOGE("%{public}s mainHandler_ is still nullptr", __func__); + return false; + } + + if (!mainHandler_->PostTask(cb, name, 0, OHOS::AppExecFwk::EventQueue::Priority::IMMEDIATE, {})) { + IMAGE_LOGE("%{public}s PostTask failed", __func__); + return false; + } + return true; +} + +Size ImageReceiverImpl::GetSize() +{ + if (imageReceiver_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageReceiverImpl is nullptr"); + return Size{0, 0}; + } + if (imageReceiver_->iraContext_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageReceiverContext is nullptr"); + return Size{0, 0}; + } + return Size{imageReceiver_->iraContext_->GetWidth(), imageReceiver_->iraContext_->GetHeight()}; +} + +int32_t ImageReceiverImpl::GetCapacity() +{ + if (imageReceiver_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageReceiverImpl is nullptr"); + return 0; + } + if (imageReceiver_->iraContext_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageReceiverContext is nullptr"); + return 0; + } + return imageReceiver_->iraContext_->GetCapicity(); +} + +ImageFormat ImageReceiverImpl::GetFormat() +{ + if (imageReceiver_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageReceiverImpl is nullptr"); + return ImageFormat(static_cast(OHOS::Media::ImageFormat::UNKNOWN)); + } + if (imageReceiver_->iraContext_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageReceiverContext is nullptr"); + return ImageFormat(static_cast(OHOS::Media::ImageFormat::UNKNOWN)); + } + ImageFormat::key_t key; + if (!ImageTaiheUtils::GetEnumKeyByValue(imageReceiver_->iraContext_->GetFormat(), key)) { + ImageTaiheUtils::ThrowExceptionError("GetEnumKeyByValue failed"); + return ImageFormat(static_cast(OHOS::Media::ImageFormat::UNKNOWN)); + } + return ImageFormat(key); +} + +static bool CheckFormat(int32_t format) +{ + for (auto imgEnum : sImageFormatMap) { + if (imgEnum.numVal == format) { + return true; + } + } + return false; +} + +static void CommonProcessSendEvent(std::shared_ptr &context) +{ + context->result = context->callBack(context); +} + +static string GetReceivingSurfaceIdSyncProcess(ImageReceiverCommonArgs &args, ImageReceiverImpl *const receiverImpl) +{ + if (receiverImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("receiverImpl is nullptr"); + return EMPTY_STRING; + } + + std::shared_ptr context = std::make_shared(); + if (context == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageReceiverTaiheContext is nullptr"); + return EMPTY_STRING; + } + + context->name = args.name; + context->callBack = args.callBack; + context->receiverImpl_ = receiverImpl; + + CommonProcessSendEvent(context); + if (context->status != OHOS::Media::SUCCESS) { + ImageTaiheUtils::ThrowExceptionError("CommonProcessSendEvent failed"); + return EMPTY_STRING; + } + + if (std::holds_alternative(context->result)) { + ImageTaiheUtils::ThrowExceptionError("CommonProcessSendEvent result is empty"); + return EMPTY_STRING; + } + + return std::get(context->result); +} + +string ImageReceiverImpl::GetReceivingSurfaceIdSync() +{ + ImageReceiverCommonArgs args = { + .name = "GetReceivingSurfaceIdSync", + .callBack = nullptr, + }; + + args.callBack = [](std::shared_ptr &context) -> CallbackResult { + auto native = context->receiverImpl_->imageReceiver_; + if (native == nullptr || native->iraContext_ == nullptr) { + IMAGE_LOGE("Native instance or imageReceiverContext is nullptr"); + context->status = OHOS::Media::COMMON_ERR_INVALID_PARAMETER; + return std::monostate{}; + } + context->status = OHOS::Media::SUCCESS; + return ::taihe::string(native->iraContext_->GetReceiverKey()); + }; + + return GetReceivingSurfaceIdSyncProcess(args, this); +} + +#ifdef IMAGE_SAVE_BUFFER_TO_PIC +static void DoCallBackTest(OHOS::sptr surfaceBuffer1) +{ + if (surfaceBuffer1 == nullptr) { + IMAGE_LOGE("surfaceBuffer1 is null"); + return; + } + + ImageReceiverManager& imageReceiverManager = ImageReceiverManager::getInstance(); + shared_ptr imageReceiver1 = imageReceiverManager.getImageReceiverByKeyId("1"); + if (imageReceiver1 == nullptr || imageReceiver1->iraContext_ == nullptr) { + return; + } + IMAGE_LOGE("DoCallBackTest format %{public}d", imageReceiver1->iraContext_->GetFormat()); + + InitializationOptions opts; + opts.size.width = surfaceBuffer1->GetWidth(); + opts.size.height = surfaceBuffer1->GetHeight(); + opts.pixelFormat = OHOS::Media::PixelFormat::BGRA_8888; + opts.alphaType = OHOS::Media::AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN; + opts.scaleMode = OHOS::Media::ScaleMode::CENTER_CROP; + opts.editable = true; + IMAGE_LOGE("DoCallBackTest Width %{public}d", opts.size.width); + IMAGE_LOGE("DoCallBackTest Height %{public}d", opts.size.height); + int fd = open("/data/receiver/test.jpg", O_RDWR | O_CREAT); + imageReceiver1->SaveBufferAsImage(fd, surfaceBuffer1, opts); +} +#endif + +static struct Image ReadImageSyncProcess(ImageReceiverCommonArgs &args, ImageReceiverImpl *const receiverImpl) +{ + if (receiverImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("receiverImpl is nullptr"); + return make_holder(); + } + + std::shared_ptr context = std::make_shared(); + if (context == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageReceiverTaiheContext is nullptr"); + return make_holder(); + } + + context->name = args.name; + context->callBack = args.callBack; + context->receiverImpl_ = receiverImpl; + + CommonProcessSendEvent(context); + if (context->status != OHOS::Media::SUCCESS) { + ImageTaiheUtils::ThrowExceptionError("CommonProcessSendEvent failed"); + return make_holder(); + } + + if (std::holds_alternative(context->result)) { + ImageTaiheUtils::ThrowExceptionError("CommonProcessSendEvent result is empty"); + return make_holder(); + } + + return std::get(context->result); +} + +struct Image ImageReceiverImpl::ReadLatestImageSync() +{ + ImageReceiverCommonArgs args = { + .name = "ReadLatestImageSync", + .callBack = nullptr, + }; + + args.callBack = [](std::shared_ptr &context) -> CallbackResult { + auto native = context->receiverImpl_->imageReceiver_; + if (native == nullptr) { + IMAGE_LOGE("Native instance is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + + std::shared_ptr nativeImage = native->LastNativeImage(); + if (nativeImage == nullptr) { + IMAGE_LOGE("LastNativeImage is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } +#ifdef IMAGE_DEBUG_FLAG + if (context->receiverImpl_->isCallBackTest) { + context->receiverImpl_->isCallBackTest = false; +#ifdef IMAGE_SAVE_BUFFER_TO_PIC + DoCallBackTest(nativeImage->GetBuffer()); +#endif + } +#endif + struct Image image = ImageImpl::Create(nativeImage); + context->status = OHOS::Media::SUCCESS; + return image; + }; + + return ReadImageSyncProcess(args, this); +} + +struct Image ImageReceiverImpl::ReadNextImageSync() +{ + ImageReceiverCommonArgs args = { + .name = "ReadNextImageSync", + .callBack = nullptr, + }; + + args.callBack = [](std::shared_ptr &context) -> CallbackResult { + auto native = context->receiverImpl_->imageReceiver_; + if (native == nullptr) { + IMAGE_LOGE("Native instance is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + std::shared_ptr nativeImage = native->NextNativeImage(); + if (nativeImage == nullptr) { + IMAGE_LOGE("NextNativeImage is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } +#ifdef IMAGE_DEBUG_FLAG + if (context->receiverImpl_->isCallBackTest) { + context->receiverImpl_->isCallBackTest = false; +#ifdef IMAGE_SAVE_BUFFER_TO_PIC + DoCallBackTest(nativeImage->GetBuffer()); +#endif + } +#endif + struct Image image = ImageImpl::Create(nativeImage); + if (::taihe::has_error()) { + IMAGE_LOGE("%{public}s ImageImpl::Create failed!", context->name.c_str()); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + context->status = OHOS::Media::SUCCESS; + return image; + }; + + return ReadImageSyncProcess(args, this); +} + +static void DoCallBack(std::shared_ptr &context) +{ + auto localContext = std::make_unique>(context); + if (context == nullptr) { + IMAGE_LOGE("%{public}s, localContext is nullptr", __func__); + localContext.release(); + return; + } + + std::shared_ptr> cacheCallback = + std::reinterpret_pointer_cast>(context->taiheCallback); + ani_object err = ImageTaiheUtils::ToBusinessError(taihe::get_env(), NUM_0, "Callback is OK"); + (*cacheCallback)(reinterpret_cast(err), ImageTaiheUtils::GetUndefinedPtr(taihe::get_env())); + localContext.release(); +} + +void ImageReceiverImpl::OnProcessSendEvent(std::shared_ptr &context) +{ + auto task = [context]() mutable { + DoCallBack(context); + }; + ImageReceiverImpl::AniSendEvent(task, context->name); +} + +static void OnImageArrivalProcess(ImageReceiverCommonArgs &args, ImageReceiverImpl *const receiverImpl, + callback_view callback) +{ + if (receiverImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("receiverImpl is nullptr"); + return; + } + + std::shared_ptr context = std::make_shared(); + if (context == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageReceiverTaiheContext is nullptr"); + return; + } + + context->name = args.name; + context->callBack = args.callBack; + context->receiverImpl_ = receiverImpl; + std::shared_ptr> taiheCallback = + std::make_shared>(callback); + context->taiheCallback = std::reinterpret_pointer_cast(taiheCallback); + + args.callBack(context); +} + +void ImageReceiverImpl::OnImageArrival(callback_view callback) +{ + ImageReceiverCommonArgs args = { + .name = "OnImageArrival", + .callBack = nullptr, + }; + + args.callBack = [](std::shared_ptr &context) -> CallbackResult { + auto native = context->receiverImpl_->imageReceiver_; + if (native == nullptr) { + IMAGE_LOGE("Native instance is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + std::shared_ptr listener = std::make_shared(); + listener->context = context; + + native->RegisterBufferAvaliableListener( + (std::shared_ptr &)listener); + + listener->context->status = OHOS::Media::SUCCESS; + return std::monostate{}; + }; + + OnImageArrivalProcess(args, this, callback); +} + +static void OffImageArrivalProcess(ImageReceiverCommonArgs &args, ImageReceiverImpl *const receiverImpl) +{ + if (receiverImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("receiverImpl is nullptr"); + return; + } + + std::shared_ptr context = std::make_shared(); + if (context == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageReceiverTaiheContext is nullptr"); + return; + } + + context->name = args.name; + context->callBack = args.callBack; + context->receiverImpl_ = receiverImpl; + + args.callBack(context); +} + +void ImageReceiverImpl::OffImageArrival(optional_view> callback) +{ + ImageReceiverCommonArgs args = { + .name = "OffImageArrival", + .callBack = nullptr, + }; + + args.callBack = [](std::shared_ptr &context) -> CallbackResult { + if (context == nullptr) { + IMAGE_LOGE("context is nullptr"); + return std::monostate{}; + } + if (context->receiverImpl_ == nullptr) { + IMAGE_LOGE("receiverImpl is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + context->receiverImpl_->imageReceiver_->UnRegisterBufferAvaliableListener(); + context->status = OHOS::Media::SUCCESS; + return std::monostate{}; + }; + + OffImageArrivalProcess(args, this); +} + +static void ReleaseSyncProcess(ImageReceiverCommonArgs &args, ImageReceiverImpl *const receiverImpl) +{ + if (receiverImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("receiverImpl is nullptr"); + return; + } + + std::shared_ptr context = std::make_shared(); + if (context == nullptr) { + ImageTaiheUtils::ThrowExceptionError("ImageReceiverTaiheContext is nullptr"); + return; + } + + context->name = args.name; + context->callBack = args.callBack; + context->receiverImpl_ = receiverImpl; + + CommonProcessSendEvent(context); + if (context->status != OHOS::Media::SUCCESS) { + ImageTaiheUtils::ThrowExceptionError("CommonProcessSendEvent failed"); + return; + } +} + +void ImageReceiverImpl::ReleaseSync() +{ + ImageReceiverCommonArgs args = { + .name = "ReleaseSync", + .callBack = nullptr, + }; + + args.callBack = [](std::shared_ptr &context) -> CallbackResult { + if (context == nullptr) { + IMAGE_LOGE("context is nullptr"); + return std::monostate{}; + } + if (context->receiverImpl_ == nullptr) { + IMAGE_LOGE("receiverImpl is nullptr"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + + context->receiverImpl_->UnRegisterReceiverListener(); + context->receiverImpl_->NativeRelease(); + context->status = OHOS::Media::SUCCESS; + return std::monostate{}; + }; + + ReleaseSyncProcess(args, this); +} + +ImageReceiver CreateImageReceiver(Size const& size, ImageFormat format, int32_t capacity) +{ + if (!CheckFormat(format.get_value())) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "Invalid format"); + return make_holder(); + } + + std::shared_ptr imageReceiver = OHOS::Media::ImageReceiver::CreateImageReceiver( + size.width, size.height, format.get_value(), capacity); + if (imageReceiver == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Create native image receiver failed"); + return make_holder(); + } + return make_holder(imageReceiver); +} +} // namespace ANI::Image + +TH_EXPORT_CPP_API_CreateImageReceiver(CreateImageReceiver); \ No newline at end of file diff --git a/frameworks/kits/taihe/src/image_source_taihe.cpp b/frameworks/kits/taihe/src/image_source_taihe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2b28da0bbb1ada02607caf85fc3d3e124356a505 --- /dev/null +++ b/frameworks/kits/taihe/src/image_source_taihe.cpp @@ -0,0 +1,1444 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ani_color_space_object_convertor.h" +#include "image_common.h" +#include "image_dfx.h" +#include "image_log.h" +#include "image_source_taihe.h" +#include "image_source_taihe_ani.h" +#include "image_taihe_utils.h" +#include "image_trace.h" +#include "image_type.h" +#include "jpeg_decoder_yuv.h" +#include "media_errors.h" +#include "picture_taihe.h" +#include "pixel_map_taihe.h" +#include "exif_metadata_formatter.h" + +using namespace ANI::Image; +using JpegYuvDecodeError = OHOS::ImagePlugin::JpegYuvDecodeError; + +namespace { + constexpr int INVALID_FD = -1; + constexpr uint32_t NUM_0 = 0; +} + +namespace ANI::Image { +static const std::string FILE_URL_PREFIX = "file://"; +thread_local std::string ImageSourceImpl::filePath_ = ""; +thread_local int ImageSourceImpl::fileDescriptor_ = -1; +thread_local void* ImageSourceImpl::fileBuffer_ = nullptr; +thread_local size_t ImageSourceImpl::fileBufferSize_ = 0; + +static std::mutex imageSourceCrossThreadMutex_; + +struct ImageSourceTaiheContext { + ImageSourceImpl *thisPtr; + uint32_t status; + std::string pathName = ""; + int fdIndex = INVALID_FD; + void* sourceBuffer = nullptr; + size_t sourceBufferSize = NUM_0; + std::string keyStr; + std::string valueStr; + std::vector keyStrArray; + std::vector> kVStrArray; + std::string defaultValueStr; + void *updataBuffer = nullptr; + size_t updataBufferSize = NUM_0; + uint32_t updataBufferOffset = NUM_0; + uint32_t updataLength = NUM_0; + bool isCompleted = false; + bool isSuccess = false; + uint32_t index = 0; + bool isBatch = false; + OHOS::Media::DecodeOptions decodeOpts; + std::shared_ptr rImageSource; + std::shared_ptr rPixelMap; + std::string errMsg; + std::multimap errMsgArray; + std::unique_ptr>> pixelMaps; + std::unique_ptr> delayTimes; +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + OHOS::Media::DecodingOptionsForPicture decodingOptsForPicture; + std::shared_ptr rPicture; +#endif +}; + +static const std::map ERROR_CODE_MAP = { + {OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, Image_ErrorCode::IMAGE_BAD_PARAMETER}, + {OHOS::Media::COMMON_ERR_INVALID_PARAMETER, Image_ErrorCode::IMAGE_BAD_PARAMETER}, + {JpegYuvDecodeError::JpegYuvDecodeError_InvalidParameter, Image_ErrorCode::IMAGE_BAD_PARAMETER}, + {OHOS::Media::ERR_IMAGE_SOURCE_DATA, Image_ErrorCode::IMAGE_BAD_SOURCE}, + {OHOS::Media::ERR_IMAGE_SOURCE_DATA_INCOMPLETE, Image_ErrorCode::IMAGE_BAD_SOURCE}, + {OHOS::Media::ERR_IMAGE_GET_DATA_ABNORMAL, Image_ErrorCode::IMAGE_BAD_SOURCE}, + {OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, Image_ErrorCode::IMAGE_BAD_SOURCE}, + {OHOS::Media::ERROR, Image_ErrorCode::IMAGE_BAD_SOURCE}, + {JpegYuvDecodeError::JpegYuvDecodeError_BadImage, Image_ErrorCode::IMAGE_BAD_SOURCE}, + {OHOS::Media::ERR_IMAGE_MISMATCHED_FORMAT, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_MIMETYPE}, + {OHOS::Media::ERR_IMAGE_UNKNOWN_FORMAT, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_MIMETYPE}, + {OHOS::Media::ERR_IMAGE_DECODE_HEAD_ABNORMAL, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_MIMETYPE}, + {OHOS::Media::ERR_IMAGE_TOO_LARGE, Image_ErrorCode::IMAGE_SOURCE_TOO_LARGE}, + {OHOS::Media::ERR_MEDIA_INVALID_OPERATION, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_ALLOCATOR_TYPE}, + {OHOS::Media::IMAGE_RESULT_FORMAT_CONVERT_FAILED, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS}, + {OHOS::Media::ERR_MEDIA_FORMAT_UNSUPPORT, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS}, + {OHOS::Media::ERR_IMAGE_PIXELMAP_CREATE_FAILED, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS}, + {JpegYuvDecodeError::JpegYuvDecodeError_ConvertError, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS}, + {OHOS::Media::ERR_IMAGE_CROP, Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS}, + {OHOS::Media::ERR_IMAGE_DECODE_FAILED, Image_ErrorCode::IMAGE_DECODE_FAILED}, + {OHOS::Media::ERR_IMAGE_DECODE_ABNORMAL, Image_ErrorCode::IMAGE_DECODE_FAILED}, + {OHOS::Media::ERR_IMAGE_PLUGIN_CREATE_FAILED, Image_ErrorCode::IMAGE_DECODE_FAILED}, + {JpegYuvDecodeError::JpegYuvDecodeError_DecodeFailed, Image_ErrorCode::IMAGE_DECODE_FAILED}, + {JpegYuvDecodeError::JpegYuvDecodeError_MemoryNotEnoughToSaveResult, Image_ErrorCode::IMAGE_DECODE_FAILED}, + {OHOS::Media::ERR_IMAGE_MALLOC_ABNORMAL, Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED}, + {OHOS::Media::ERR_IMAGE_DATA_UNSUPPORT, Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED}, + {OHOS::Media::ERR_DMA_NOT_EXIST, Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED}, + {OHOS::Media::ERR_DMA_DATA_ABNORMAL, Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED}, + {OHOS::Media::ERR_SHAMEM_DATA_ABNORMAL, Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED} +}; + +static const std::map ERROR_CODE_MESSAGE_MAP = { + {Image_ErrorCode::IMAGE_BAD_PARAMETER, "Parameter error. Possible causes:" + "1.Mandatory parameters are left unspecified. 2.Incorrect parameter types. 3.Parameter verification failed."}, + {Image_ErrorCode::IMAGE_BAD_SOURCE, "Bad source. e.g.,1.Image has invalid width or height." + "2.Image source incomplete. 3.Read image data failed. 4. Codec create failed." + "5.The sourceOption specifies an odd width, causing the YUV420 PixelMap conversion to RGBA failed."}, + {Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_MIMETYPE, "Unsupported mimetype."}, + {Image_ErrorCode::IMAGE_SOURCE_TOO_LARGE, "Image too large."}, + {Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_ALLOCATOR_TYPE, "Unsupported allocator type. e.g.," + "use share memory to decode a HDR image as only DMA supported hdr metadata."}, + {Image_ErrorCode::IMAGE_SOURCE_UNSUPPORTED_OPTIONS, "Unsupported options. e.g.," + "1.Convert image into desired pixelFormat failed. 2.Crop pixelMap failed."}, + {Image_ErrorCode::IMAGE_DECODE_FAILED, "Decode failed. e.g.,Decode image header failed."}, + {Image_ErrorCode::IMAGE_SOURCE_ALLOC_FAILED, "Memory allocation failed."} +}; + +static Image_ErrorCode ConvertToErrorCode(int32_t errorCode) +{ + Image_ErrorCode apiErrorCode = Image_ErrorCode::IMAGE_DECODE_FAILED; + auto iter = ERROR_CODE_MAP.find(errorCode); + if (iter != ERROR_CODE_MAP.end()) { + apiErrorCode = iter->second; + } + return apiErrorCode; +} + +static std::string GetErrorCodeMsg(Image_ErrorCode apiErrorCode) +{ + std::string errMsg = "Decode failed."; + auto iter = ERROR_CODE_MESSAGE_MAP.find(apiErrorCode); + if (iter != ERROR_CODE_MESSAGE_MAP.end()) { + errMsg = iter->second; + } + return errMsg; +} + +ImageSourceImpl::ImageSourceImpl() {} + +ImageSourceImpl::ImageSourceImpl(std::shared_ptr imageSource) +{ + nativeImgSrc = imageSource; +} + +ImageSourceImpl::ImageSourceImpl(std::shared_ptr imageSource, + std::shared_ptr incPixelMap) +{ + nativeImgSrc = imageSource; + navIncPixelMap_ = incPixelMap; +} + +ImageSourceImpl::ImageSourceImpl(int64_t aniPtr) +{ + OHOS::Media::ImageSourceTaiheAni *imageSourceAni = reinterpret_cast(aniPtr); + if (imageSourceAni != nullptr && imageSourceAni->nativeImgSrc != nullptr) { + nativeImgSrc = imageSourceAni->nativeImgSrc; + } else { + ImageTaiheUtils::ThrowExceptionError("aniPtr is invalid or nativeImgSrc is nullptr"); + } +} + +ImageSourceImpl::~ImageSourceImpl() +{ + ReleaseSync(); +} + +int64_t ImageSourceImpl::GetImplPtr() +{ + return reinterpret_cast(this); +} + +ImageInfo ImageSourceImpl::GetImageInfoSyncWithIndex(int32_t index) +{ + OHOS::Media::ImageInfo imageinfo; + bool isHdr = false; + if (nativeImgSrc != nullptr) { + index = index >= NUM_0 ? index : NUM_0; + uint32_t ret = nativeImgSrc->GetImageInfo(index, imageinfo); + if (ret != OHOS::Media::SUCCESS) { + ImageTaiheUtils::ThrowExceptionError("Inner GetImageInfo failed"); + } + isHdr = nativeImgSrc->IsHdrImage(); + } else { + ImageTaiheUtils::ThrowExceptionError("nativeImgSrc is nullptr"); + } + return ImageTaiheUtils::ToTaiheImageInfo(imageinfo, isHdr); +} + +ImageInfo ImageSourceImpl::GetImageInfoSync() +{ + int32_t index = 0; + return GetImageInfoSyncWithIndex(index); +} + +static bool ParseRotate(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst, std::string &errMsg) +{ + if (options.rotate.has_value()) { + dst.rotateNewDegrees = options.rotate.value(); + if (dst.rotateNewDegrees >= 0 && dst.rotateNewDegrees <= 360) { // 360 is the maximum rotation angle. + dst.rotateDegrees = static_cast(dst.rotateNewDegrees); + IMAGE_LOGD("rotateDegrees: %{public}f", dst.rotateDegrees); + } else { + IMAGE_LOGD("Invalid rotate %{public}d", dst.rotateNewDegrees); + errMsg = "DecodeOptions mismatch"; + return false; + } + } + return true; +} + +static OHOS::Media::Rect ParseDesiredRegion(DecodingOptions const& options) +{ + OHOS::Media::Rect rect {}; + if (options.desiredRegion.has_value()) { + auto ®ion = options.desiredRegion.value(); + rect.left = region.x; + rect.top = region.y; + rect.width = region.size.width; + rect.height = region.size.height; + IMAGE_LOGD("desiredRegion: %{public}d, %{public}d, %{public}d, %{public}d", + rect.left, rect.top, rect.width, rect.height); + } + return rect; +} + +static bool IsAstc(int32_t val) +{ + if (val >= static_cast(OHOS::Media::PixelFormat::ASTC_4x4) && + val <= static_cast(OHOS::Media::PixelFormat::ASTC_8x8)) { + return true; + } + return false; +} + +static bool IsSupportPixelFormat(int32_t val) +{ + if (IsAstc(val)) { + return true; + } + if (val >= static_cast(OHOS::Media::PixelFormat::UNKNOWN) && + val < static_cast(OHOS::Media::PixelFormat::EXTERNAL_MAX)) { + return true; + } + + return false; +} + +static OHOS::Media::PixelFormat ParsePixelFormat(int32_t val) +{ + if (IsAstc(val)) { + return OHOS::Media::PixelFormat(val); + } + if (val < static_cast(OHOS::Media::PixelFormat::EXTERNAL_MAX)) { + return OHOS::Media::PixelFormat(val); + } + + return OHOS::Media::PixelFormat::UNKNOWN; +} + +static bool ParsePixelFormat(optional val, OHOS::Media::PixelFormat &dst, const std::string &name, + std::string &errMsg) +{ + if (!val.has_value()) { + IMAGE_LOGD("no %{public}s", name.c_str()); + } else { + int32_t pixelFormat = val->get_value(); + if (IsSupportPixelFormat(pixelFormat)) { + dst = ParsePixelFormat(pixelFormat); + IMAGE_LOGD("PixelFormat: %{public}d", dst); + } else { + IMAGE_LOGD("Invalid %{public}s %{public}d", name.c_str(), pixelFormat); + errMsg = "DecodeOptions mismatch"; + return false; + } + } + return true; +} + +static void ParseDesiredColorSpace(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst) +{ + if (options.desiredColorSpace.has_value()) { + ani_object desiredColorSpaceObj = reinterpret_cast(options.desiredColorSpace.value()); + dst.desiredColorSpaceInfo = OHOS::ColorManager::GetColorSpaceByAniObject(get_env(), desiredColorSpaceObj); + IMAGE_LOGD("desiredColorSpace parse finished"); + } + if (dst.desiredColorSpaceInfo == nullptr) { + IMAGE_LOGD("no desiredColorSpace"); + } +} + +static OHOS::Media::DecodeDynamicRange ParseDynamicRange(DecodingOptions const& options) +{ + if (options.desiredDynamicRange.has_value()) { + int32_t desiredDynamicRange = options.desiredDynamicRange->get_value(); + if (desiredDynamicRange <= static_cast(OHOS::Media::DecodeDynamicRange::HDR)) { + IMAGE_LOGD("desiredDynamicRange: %{public}d", desiredDynamicRange); + return OHOS::Media::DecodeDynamicRange(desiredDynamicRange); + } + } + return OHOS::Media::DecodeDynamicRange::SDR; +} + +static OHOS::Media::ResolutionQuality ParseResolutionQuality(DecodingOptions const& options) +{ + if (options.resolutionQuality.has_value()) { + int32_t resolutionQuality = options.resolutionQuality->get_value(); + if (resolutionQuality <= static_cast(OHOS::Media::ResolutionQuality::HIGH) && + (resolutionQuality >= static_cast(OHOS::Media::ResolutionQuality::UNKNOWN))) { + IMAGE_LOGD("resolutionQuality: %{public}d", resolutionQuality); + return OHOS::Media::ResolutionQuality(resolutionQuality); + } + } + return OHOS::Media::ResolutionQuality::UNKNOWN; +} + +static inline bool IsCropStrategyVaild(int32_t strategy) +{ + return strategy >= static_cast(OHOS::Media::CropAndScaleStrategy::SCALE_FIRST) && + strategy <= static_cast(OHOS::Media::CropAndScaleStrategy::CROP_FIRST); +} + +static void ParseCropAndScaleStrategy(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst) +{ + if (options.cropAndScaleStrategy.has_value() && IsCropStrategyVaild(options.cropAndScaleStrategy->get_value())) { + IMAGE_LOGI("The strategy has taken effect"); + dst.cropAndScaleStrategy = OHOS::Media::CropAndScaleStrategy(options.cropAndScaleStrategy->get_value()); + IMAGE_LOGD("cropAndScaleStrategy: %{public}d", dst.cropAndScaleStrategy); + return; + } + IMAGE_LOGI("default cropAndScaleStrategy"); +} + +static void ParseReusePixelMap(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst) +{ + if (options.reusePixelmap.has_value()) { + PixelMap etsPixelMap = options.reusePixelmap.value(); + std::shared_ptr rPixelMap = PixelMapImpl::GetPixelMap(etsPixelMap); + if (rPixelMap != nullptr) { + dst.reusePixelmap = rPixelMap; + IMAGE_LOGD("reusePixelmap parse finished"); + } + } +} + +static bool ParseDecodeOptions2(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst, std::string &errMsg) +{ + if (!ParsePixelFormat(options.desiredPixelFormat, dst.desiredPixelFormat, "desiredPixelFormat", errMsg) || + !ParsePixelFormat(options.photoDesiredPixelFormat, dst.photoDesiredPixelFormat, + "photoDesiredPixelFormat", errMsg)) { + return false; + } + + if (options.fitDensity.has_value()) { + dst.fitDensity = options.fitDensity.value(); + IMAGE_LOGD("fitDensity: %{public}d", dst.fitDensity); + } + + if (options.fillColor.has_value()) { + dst.SVGOpts.fillColor.isValidColor = true; + dst.SVGOpts.fillColor.color = options.fillColor.value(); + IMAGE_LOGD("fillColor: %{public}d", dst.SVGOpts.fillColor.color); + } + + if (options.SVGResize.has_value()) { + dst.SVGOpts.SVGResize.isValidPercentage = true; + dst.SVGOpts.SVGResize.resizePercentage = options.SVGResize.value(); + IMAGE_LOGD("SVGResize: %{public}d", dst.SVGOpts.SVGResize.resizePercentage); + } + + ParseDesiredColorSpace(options, dst); + if (dst.desiredColorSpaceInfo == nullptr) { + IMAGE_LOGD("no desiredColorSpace"); + } + + dst.desiredDynamicRange = ParseDynamicRange(options); + dst.resolutionQuality = ParseResolutionQuality(options); + ParseCropAndScaleStrategy(options, dst); + ParseReusePixelMap(options, dst); + return true; +} + +static bool ParseDecodeOptions(DecodingOptions const& options, OHOS::Media::DecodeOptions &dst, uint32_t &index, + std::string &errMsg) +{ + if (options.index.has_value()) { + index = options.index.value(); + IMAGE_LOGD("index: %{public}d", index); + } + + if (options.sampleSize.has_value()) { + dst.sampleSize = options.sampleSize.value(); + IMAGE_LOGD("sampleSize: %{public}d", dst.sampleSize); + } + + CHECK_ERROR_RETURN_RET_LOG(!ParseRotate(options, dst, errMsg), false, "%{public}s ParseRotate failed", __func__); + + if (options.editable.has_value()) { + dst.editable = options.editable.value(); + IMAGE_LOGD("editable: %{public}d", dst.editable); + } + + if (options.desiredSize.has_value()) { + dst.desiredSize.width = options.desiredSize.value().width; + dst.desiredSize.height = options.desiredSize.value().height; + IMAGE_LOGD("desiredSize: %{public}d, %{public}d", dst.desiredSize.width, dst.desiredSize.height); + } + + dst.CropRect = ParseDesiredRegion(options); + return ParseDecodeOptions2(options, dst, errMsg); +} + +static std::shared_ptr CreatePixelMapInner(ImageSourceImpl *const thisPtr, + std::shared_ptr imageSource, uint32_t index, OHOS::Media::DecodeOptions decodeOpts, + uint32_t &status) +{ + if (thisPtr == nullptr || imageSource == nullptr) { + IMAGE_LOGE("Invailed args"); + status = OHOS::Media::ERROR; + } + + std::shared_ptr pixelMap; + auto incPixelMap = (thisPtr == nullptr) ? nullptr : thisPtr->GetIncrementalPixelMap(); + if (incPixelMap != nullptr) { + IMAGE_LOGD("Get Incremental PixelMap!!!"); + pixelMap = incPixelMap; + } else { + decodeOpts.invokeType = OHOS::Media::JS_INTERFACE; + pixelMap = (imageSource == nullptr) ? nullptr : imageSource->CreatePixelMapEx((index >= NUM_0) ? index : NUM_0, + decodeOpts, status); + } + + if (status != OHOS::Media::SUCCESS || pixelMap == nullptr) { + IMAGE_LOGE("Create PixelMap error"); + } + + return pixelMap; +} + +static void CreatePixelMapExecute(std::unique_ptr &taiheContext) +{ + IMAGE_LOGD("CreatePixelMapExecute IN"); + if (taiheContext == nullptr) { + IMAGE_LOGE("%{public}s taiheContext is nullptr", __func__); + return; + } + + if (taiheContext->errMsg.size() > 0) { + IMAGE_LOGE("%{public}s errMsg: %{public}s", __func__, taiheContext->errMsg.c_str()); + return; + } + + taiheContext->rPixelMap = CreatePixelMapInner(taiheContext->thisPtr, taiheContext->rImageSource, + taiheContext->index, taiheContext->decodeOpts, taiheContext->status); + + if (taiheContext->status != OHOS::Media::SUCCESS) { + taiheContext->errMsg = "Create PixelMap error"; + IMAGE_LOGE("Create PixelMap error"); + } + IMAGE_LOGD("CreatePixelMapExecute OUT"); +} + +static PixelMap CreatePixelMapComplete(std::unique_ptr &taiheContext) +{ + IMAGE_LOGD("CreatePixelMapComplete IN"); + if (taiheContext->status == OHOS::Media::SUCCESS && taiheContext->rPixelMap != nullptr) { + return PixelMapImpl::CreatePixelMap(taiheContext->rPixelMap); + } + IMAGE_LOGD("CreatePixelMapComplete OUT"); + ImageTaiheUtils::ThrowExceptionError(taiheContext->errMsg); + return make_holder(); +} + +PixelMap ImageSourceImpl::CreatePixelMapSyncWithOptions(DecodingOptions const& options) +{ + std::unique_ptr taiheContext = std::make_unique(); + taiheContext->rImageSource = nativeImgSrc; + if (taiheContext->rImageSource == nullptr) { + IMAGE_LOGE("%{public}s nativeImgSrc is nullptr", __func__); + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "nativeImgSrc is nullptr"); + return make_holder(); + } + + taiheContext->thisPtr = this; + if (taiheContext->thisPtr == nullptr) { + IMAGE_LOGE("%{public}s thisPtr is nullptr", __func__); + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "thisPtr is nullptr"); + return make_holder(); + } + + if (!ParseDecodeOptions(options, taiheContext->decodeOpts, taiheContext->index, + taiheContext->errMsg)) { + IMAGE_LOGE("%{public}s ParseDecodeOptions failed", __func__); + } + + ImageTaiheUtils::HicheckerReport(); + CreatePixelMapExecute(taiheContext); + return CreatePixelMapComplete(taiheContext); +} + +PixelMap ImageSourceImpl::CreatePixelMapSync() +{ + DecodingOptions options {}; + return CreatePixelMapSyncWithOptions(options); +} + +static void CreatePixelMapUsingAllocatorSyncExecute(std::unique_ptr &taiheContext) +{ + if (taiheContext == nullptr) { + IMAGE_LOGE("%{public}s taiheContext is nullptr", __func__); + return; + } + + taiheContext->rPixelMap = CreatePixelMapInner(taiheContext->thisPtr, taiheContext->rImageSource, + taiheContext->index, taiheContext->decodeOpts, taiheContext->status); + if (taiheContext->status != OHOS::Media::SUCCESS) { + Image_ErrorCode apiErrorCode = ConvertToErrorCode(taiheContext->status); + std::string apiErrorMsg = GetErrorCodeMsg(apiErrorCode); + taiheContext->errMsgArray.emplace(apiErrorCode, apiErrorMsg); + } +} + +static PixelMap CreatePixelMapUsingAllocatorSyncComplete(std::unique_ptr &taiheContext) +{ + if (taiheContext->status == OHOS::Media::SUCCESS && taiheContext->rPixelMap != nullptr) { + return PixelMapImpl::CreatePixelMap(taiheContext->rPixelMap); + } + for (const auto &[errorCode, errMsg] : taiheContext->errMsgArray) { + ImageTaiheUtils::ThrowExceptionError(errorCode, errMsg); + } + return make_holder(); +} + +PixelMap ImageSourceImpl::CreatePixelMapUsingAllocatorSync(optional_view options, + optional_view allocatorType) +{ + std::unique_ptr taiheContext = std::make_unique(); + taiheContext->rImageSource = nativeImgSrc; + if (taiheContext->rImageSource == nullptr) { + IMAGE_LOGE("%{public}s nativeImgSrc is nullptr", __func__); + return make_holder(); + } + + taiheContext->thisPtr = this; + if (taiheContext->thisPtr == nullptr) { + IMAGE_LOGE("%{public}s thisPtr is nullptr", __func__); + return make_holder(); + } + + DecodingOptions opts = options.value_or(DecodingOptions {}); + if (!ParseDecodeOptions(opts, taiheContext->decodeOpts, taiheContext->index, + taiheContext->errMsg)) { + IMAGE_LOGE("DecodeOptions mismatch."); + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "DecodeOptions mismatch."); + return make_holder(); + } + + int32_t allocatorTypeInner = allocatorType.value_or(AllocatorType::key_t::AUTO); + if (!taiheContext->rImageSource->IsSupportAllocatorType(taiheContext->decodeOpts, allocatorTypeInner)) { + IMAGE_LOGE("Unsupported allocator type."); + ImageTaiheUtils::ThrowExceptionError(IMAGE_SOURCE_UNSUPPORTED_ALLOCATOR_TYPE, "Unsupported allocator type."); + return make_holder(); + } + + CreatePixelMapUsingAllocatorSyncExecute(taiheContext); + return CreatePixelMapUsingAllocatorSyncComplete(taiheContext); +} + +static bool CheckAsyncContext(std::unique_ptr &taiheContext, bool check) +{ + if (taiheContext == nullptr) { + IMAGE_LOGE("context is nullptr"); + return false; + } + + if (check) { + if (taiheContext->errMsg.size() > 0) { + IMAGE_LOGE("mismatch args"); + taiheContext->status = OHOS::Media::ERROR; + return false; + } + + if (taiheContext->rImageSource == nullptr) { + IMAGE_LOGE("empty context rImageSource"); + taiheContext->status = OHOS::Media::ERROR; + return false; + } + } + + return true; +} + +static void CreatePixelMapListSyncWithOptionsExecute(std::unique_ptr &taiheContext) +{ + if (!CheckAsyncContext(taiheContext, true)) { + IMAGE_LOGE("check taiheContext fail"); + return; + } + + taiheContext->pixelMaps = nullptr; + uint32_t errorCode = 0; + uint32_t frameCount = taiheContext->rImageSource->GetFrameCount(errorCode); + if ((errorCode == OHOS::Media::SUCCESS) && (taiheContext->index >= NUM_0) && (taiheContext->index < frameCount)) { + taiheContext->decodeOpts.invokeType = OHOS::Media::JS_INTERFACE; + taiheContext->pixelMaps = taiheContext->rImageSource->CreatePixelMapList(taiheContext->decodeOpts, errorCode); + } + + if ((errorCode == OHOS::Media::SUCCESS) && taiheContext->pixelMaps != nullptr) { + taiheContext->status = OHOS::Media::SUCCESS; + } else { + IMAGE_LOGE("Create PixelMap List error, error=%{public}u", errorCode); + taiheContext->errMsg = "Create PixelMap List error"; + taiheContext->status = (errorCode != OHOS::Media::SUCCESS) ? errorCode : OHOS::Media::ERROR; + } +} + +static array CreatePixelMapListSyncWithOptionsComplete(std::unique_ptr &taiheContext) +{ + if (!CheckAsyncContext(taiheContext, false)) { + IMAGE_LOGE("check taiheContext fail"); + return array(nullptr, 0); + } + + std::vector result; + if (taiheContext->status == OHOS::Media::SUCCESS && taiheContext->pixelMaps != nullptr) { + IMAGE_LOGD("CreatePixelMapListSyncWithOptionsComplete array"); + for (auto &pixelMap : *taiheContext->pixelMaps.get()) { + result.emplace_back(PixelMapImpl::CreatePixelMap(std::move(pixelMap))); + } + } else { + std::string errMsg = (taiheContext->errMsg.size() > 0) ? taiheContext->errMsg : "error status, no message"; + IMAGE_LOGD("Operation failed code:%{public}d, msg:%{public}s", taiheContext->status, errMsg.c_str()); + ImageTaiheUtils::ThrowExceptionError(taiheContext->status, errMsg); + } + return array(result); +} + +array ImageSourceImpl::CreatePixelMapListSyncWithOptions(DecodingOptions const& options) +{ + OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::CreatePixelMapListSyncWithOptions"); + std::unique_ptr taiheContext = std::make_unique(); + taiheContext->rImageSource = nativeImgSrc; + if (taiheContext->rImageSource == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, "nativeImgSrc is nullptr"); + return array(nullptr, 0); + } + + taiheContext->thisPtr = this; + if (taiheContext->thisPtr == nullptr) { + taiheContext->errMsg = "thisPtr is nullptr"; + IMAGE_LOGE("%{public}s thisPtr is nullptr", __func__); + } + + if (!ParseDecodeOptions(options, taiheContext->decodeOpts, taiheContext->index, + taiheContext->errMsg)) { + IMAGE_LOGE("%{public}s DecodeOptions mismatch.", __func__); + } + + ImageTaiheUtils::HicheckerReport(); + CreatePixelMapListSyncWithOptionsExecute(taiheContext); + return CreatePixelMapListSyncWithOptionsComplete(taiheContext); +} + +array ImageSourceImpl::CreatePixelMapListSync() +{ + return CreatePixelMapListSyncWithOptions({}); +} + +array ImageSourceImpl::CreatePixelMapListSyncWithOptionalOptions(optional_view options) +{ + return CreatePixelMapListSyncWithOptions(options.value_or(DecodingOptions {})); +} + +array ImageSourceImpl::GetDelayTimeListSync() +{ + OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::GetDelayTimeListSync"); + + if (nativeImgSrc == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, "nativeImgSrc is nullptr."); + return array(0); + } + + uint32_t errorCode = 0; + auto delayTimes = nativeImgSrc->GetDelayTime(errorCode); + if ((errorCode != OHOS::Media::SUCCESS) || (delayTimes == nullptr)) { + IMAGE_LOGE("Get DelayTime error, error=%{public}u", errorCode); + ImageTaiheUtils::ThrowExceptionError((errorCode != OHOS::Media::SUCCESS) ? errorCode : OHOS::Media::ERROR, + "Get DelayTime error"); + return array(0); + } + + return array(taihe::copy_data_t{}, delayTimes->data(), delayTimes->size()); +} + +array ImageSourceImpl::GetDisposalTypeListSync() +{ + OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::GetDisposalTypeListSync"); + + if (nativeImgSrc == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, "nativeImgSrc is nullptr."); + return array(0); + } + + uint32_t errorCode = 0; + auto disposalTypeList = nativeImgSrc->GetDisposalType(errorCode); + if ((errorCode != OHOS::Media::SUCCESS) || (disposalTypeList == nullptr)) { + IMAGE_LOGE("Get DisposalType error, error=%{public}u", errorCode); + ImageTaiheUtils::ThrowExceptionError((errorCode != OHOS::Media::SUCCESS) ? errorCode : OHOS::Media::ERROR, + "Get DisposalType error"); + return array(0); + } + + return array(taihe::copy_data_t{}, disposalTypeList->data(), disposalTypeList->size()); +} + +int32_t ImageSourceImpl::GetFrameCountSync() +{ + OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::GetFrameCountSync"); + + if (nativeImgSrc == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, "nativeImgSrc is nullptr."); + return 0; + } + + uint32_t errorCode = 0; + auto frameCount = nativeImgSrc->GetFrameCount(errorCode); + if (errorCode != OHOS::Media::SUCCESS) { + IMAGE_LOGE("Get FrameCount error, error=%{public}u", errorCode); + ImageTaiheUtils::ThrowExceptionError(errorCode, "Get FrameCount error"); + return 0; + } + + return frameCount; +} + +static bool ParsePropertyOptions(std::unique_ptr &context, + optional_view &options) +{ + if (!options->index.has_value()) { + IMAGE_LOGD("no index"); + return false; + } + context->index = options->index.value(); + if (!options->defaultValue.has_value()) { + IMAGE_LOGD("no defaultValue"); + } else { + context->defaultValueStr = options->defaultValue.value(); + } + return true; +} + +static void GenerateErrMsg(std::unique_ptr &context, std::string &errMsg) +{ + if (context == nullptr) { + return; + } + switch (context->status) { + case OHOS::Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT: + errMsg = "The image does not support EXIF decoding."; + break; + case OHOS::Media::ERROR: + errMsg = "The operation failed."; + break; + case OHOS::Media::ERR_IMAGE_DATA_UNSUPPORT: + errMsg = "The image data is not supported."; + break; + case OHOS::Media::ERR_IMAGE_SOURCE_DATA: + errMsg = "The image source data is incorrect."; + break; + case OHOS::Media::ERR_IMAGE_SOURCE_DATA_INCOMPLETE: + errMsg = "The image source data is incomplete."; + break; + case OHOS::Media::ERR_IMAGE_MISMATCHED_FORMAT: + errMsg = "The image format does not mastch."; + break; + case OHOS::Media::ERR_IMAGE_UNKNOWN_FORMAT: + errMsg = "Unknown image format."; + break; + case OHOS::Media::ERR_IMAGE_INVALID_PARAMETER: + errMsg = "Invalid image parameter."; + break; + case OHOS::Media::ERR_IMAGE_DECODE_FAILED: + errMsg = "Failed to decode the image."; + break; + case OHOS::Media::ERR_IMAGE_PLUGIN_CREATE_FAILED: + errMsg = "Failed to create the image plugin."; + break; + case OHOS::Media::ERR_IMAGE_DECODE_HEAD_ABNORMAL: + errMsg = "Failed to decode the image header."; + break; + case OHOS::Media::ERR_MEDIA_VALUE_INVALID: + errMsg = "The EXIF value is invalid."; + break; + default: + errMsg = "There is unknown error happened."; + } +} + +string ImageSourceImpl::GetImagePropertySync(PropertyKey key, optional_view options) +{ + OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::GetImagePropertySync"); + + std::unique_ptr context = std::make_unique(); + if (nativeImgSrc == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "empty native rImageSource"); + return context->valueStr; + } + + if (options.has_value() && !ParsePropertyOptions(context, options)) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "PropertyOptions mismatch"); + return context->valueStr; + } + + context->keyStr = std::string(key.get_value()); + context->status = nativeImgSrc->GetImagePropertyString(context->index, context->keyStr, context->valueStr); + if (context->status != OHOS::Media::SUCCESS) { + if (!context->defaultValueStr.empty()) { + return context->defaultValueStr; + } + std::string errMsg; + GenerateErrMsg(context, errMsg); + ImageTaiheUtils::ThrowExceptionError(context->status, errMsg); + } + return context->valueStr; +} + +static void GetImagePropertiesExecute(std::unique_ptr &context) +{ + if (context == nullptr) { + IMAGE_LOGE("empty context"); + return; + } + uint32_t status = OHOS::Media::SUCCESS; + for (auto keyStrIt = context->keyStrArray.begin(); keyStrIt != context->keyStrArray.end(); ++keyStrIt) { + std::string valueStr = ""; + status = context->rImageSource->GetImagePropertyString(0, *keyStrIt, valueStr); + if (status == OHOS::Media::SUCCESS) { + context->kVStrArray.emplace_back(std::make_pair(*keyStrIt, valueStr)); + } else { + context->kVStrArray.emplace_back(std::make_pair(*keyStrIt, "")); + context->errMsgArray.insert(std::make_pair(status, *keyStrIt)); + IMAGE_LOGE("errCode: %{public}u , exif key: %{public}s", status, keyStrIt->c_str()); + } + } + context->status = context->kVStrArray.size() == context->errMsgArray.size() ? + OHOS::Media::ERROR : OHOS::Media::SUCCESS; +} + +static PropertyValue CreatePropertyValue(const std::string& valueStr) +{ + if (!valueStr.empty()) { + return PropertyValue::make_type_string(valueStr); + } else { + return PropertyValue::make_type_null(); + } +} + +map CreatePropertiesRecord( + std::vector> recordParameters) +{ + map result; + for (size_t index = 0; index < recordParameters.size(); ++index) { + PropertyKey::key_t key; + if (!ImageTaiheUtils::GetEnumKeyByValue(recordParameters[index].first, key)) { + IMAGE_LOGE("Get current record parameter failed"); + continue; + } + PropertyValue value = CreatePropertyValue(recordParameters[index].second); + result.emplace(PropertyKey(key), value); + } + + IMAGE_LOGD("Get record parameters info success."); + return result; +} + +void CreateObtainErrorArray(std::multimap errMsgArray) +{ + for (auto it = errMsgArray.begin(); it != errMsgArray.end(); ++it) { + std::string errMsg; + int32_t errCode = it->first; + if (errCode == OHOS::Media::ERR_IMAGE_DECODE_ABNORMAL) { + errMsg = "The image source data is incorrect! exif key: " + it->second; + } else if (errCode == OHOS::Media::ERR_IMAGE_UNKNOWN_FORMAT) { + errMsg = "Unknown image format! exif key: " + it->second; + } else if (errCode == OHOS::Media::ERR_IMAGE_DECODE_FAILED) { + errMsg = "Failed to decode the image! exif key: " + it->second; + } else { + errCode = OHOS::Media::ERROR; + errMsg = "There is generic taihe failure! exif key: " + it->second; + } + ImageTaiheUtils::ThrowExceptionError(errCode, errMsg); + } + + IMAGE_LOGD("Create obtain error array success."); +} + +std::vector GetStringArrayArgument(array_view key) +{ + std::vector keyStrArray; + + for (uint32_t i = 0; i < key.size(); i++) { + keyStrArray.emplace_back(key[i].get_value()); + } + + IMAGE_LOGD("Get string argument success."); + return keyStrArray; +} + +map ImageSourceImpl::GetImagePropertiesSync(array_view key) +{ + OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::GetImagePropertiesSync"); + + map result; + std::unique_ptr context = std::make_unique(); + if (nativeImgSrc == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "empty native rImageSource"); + return result; + } + context->rImageSource = nativeImgSrc; + context->keyStrArray = GetStringArrayArgument(key); + if (context->keyStrArray.size() == 0) return result; + + GetImagePropertiesExecute(context); + + if (context->status == OHOS::Media::SUCCESS) { + result = CreatePropertiesRecord(context->kVStrArray); + } else { + CreateObtainErrorArray(context->errMsgArray); + } + return result; +} + +void CreateModifyErrorArray(std::multimap errMsgArray) +{ + for (auto it = errMsgArray.rbegin(); it != errMsgArray.rend(); ++it) { + if (it->first == OHOS::Media::ERR_MEDIA_WRITE_PARCEL_FAIL) { + ImageTaiheUtils::ThrowExceptionError(it->first, + "Create Fd without write permission! exif key: " + it->second); + } else if (it->first == OHOS::Media::ERR_MEDIA_OUT_OF_RANGE) { + ImageTaiheUtils::ThrowExceptionError(it->first, + "The given buffer size is too small to add new exif data! exif key: " + it->second); + } else if (it->first == OHOS::Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) { + ImageTaiheUtils::ThrowExceptionError(it->first, + "The image does not support EXIF decoding. exif key: " + it->second); + } else if (it->first == OHOS::Media::ERR_MEDIA_VALUE_INVALID) { + ImageTaiheUtils::ThrowExceptionError(it->first, it->second); + } else { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERROR, + "There is generic taihe failure! exif key: " + it->second); + } + } + + IMAGE_LOGD("Create modify error array success."); +} + +static void ModifyImagePropertyComplete(std::unique_ptr &context) +{ + if (context == nullptr) { + IMAGE_LOGE("context is nullptr"); + return; + } + + if (context->status == OHOS::Media::SUCCESS) { + IMAGE_LOGI("ModifyImageProperty success."); + return; + } + + if (context->isBatch) { + CreateModifyErrorArray(context->errMsgArray); + } else { + if (context->status == OHOS::Media::ERR_MEDIA_WRITE_PARCEL_FAIL) { + if (context->fdIndex != INVALID_FD) { + ImageTaiheUtils::ThrowExceptionError(context->status, "Create Fd without write permission!"); + } else { + ImageTaiheUtils::ThrowExceptionError(context->status, + "The EXIF data failed to be written to the file."); + } + } else if (context->status == OHOS::Media::ERR_MEDIA_OUT_OF_RANGE) { + ImageTaiheUtils::ThrowExceptionError(context->status, + "The given buffer size is too small to add new exif data!"); + } else if (context->status == OHOS::Media::ERR_IMAGE_DECODE_EXIF_UNSUPPORT) { + ImageTaiheUtils::ThrowExceptionError(context->status, + "The exif data format is not standard, so modify it failed!"); + } else if (context->status == OHOS::Media::ERR_MEDIA_VALUE_INVALID) { + ImageTaiheUtils::ThrowExceptionError(context->status, context->errMsg); + } else { + ImageTaiheUtils::ThrowExceptionError(context->status, + "There is generic taihe failure!"); + } + } +} + +static uint32_t CheckExifDataValue(const std::string &key, const std::string &value, std::string &errorInfo) +{ + auto status = static_cast(OHOS::Media::ExifMetadatFormatter::Validate(key, value)); + if (status != OHOS::Media::SUCCESS) { + errorInfo = key + " has invalid exif value: "; + errorInfo.append(value); + } + return status; +} + +static void ModifyImagePropertyExecute(std::unique_ptr &context) +{ + if (context == nullptr) { + IMAGE_LOGE("empty context"); + return; + } + IMAGE_LOGD("ModifyImagePropertyExecute CheckExifDataValue"); + uint32_t status = CheckExifDataValue(context->keyStr, context->valueStr, context->errMsg); + IMAGE_LOGD("ModifyImagePropertyExecute Check ret status: %{public}d", status); + if (status != OHOS::Media::SUCCESS) { + IMAGE_LOGE("There is invalid exif data parameter"); + context->status = status; + return; + } + context->status = context->rImageSource->ModifyImagePropertyEx(context->index, context->keyStr, context->valueStr); +} + +void ImageSourceImpl::ModifyImagePropertySync(PropertyKey key, string_view value) +{ + OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::ModifyImagePropertySync"); + + std::unique_ptr context = std::make_unique(); + if (nativeImgSrc == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "empty native rImageSource"); + return; + } + context->rImageSource = nativeImgSrc; + + context->keyStr = std::string(key.get_value()); + context->valueStr = std::string(value); + + context->pathName = ImageSourceImpl::filePath_; + context->fdIndex = ImageSourceImpl::fileDescriptor_; + context->sourceBuffer = ImageSourceImpl::fileBuffer_; + context->sourceBufferSize = ImageSourceImpl::fileBufferSize_; + + ModifyImagePropertyExecute(context); + ModifyImagePropertyComplete(context); +} + +static void ModifyImagePropertiesExecute(std::unique_ptr &context) +{ + if (context == nullptr) { + IMAGE_LOGE("empty context"); + return; + } + uint32_t status = OHOS::Media::SUCCESS; + for (auto recordIterator = context->kVStrArray.begin(); recordIterator != context->kVStrArray.end(); + ++recordIterator) { + IMAGE_LOGD("CheckExifDataValue"); + status = CheckExifDataValue(recordIterator->first, recordIterator->second, context->errMsg); + IMAGE_LOGD("Check ret status: %{public}d", status); + if (status != OHOS::Media::SUCCESS) { + IMAGE_LOGE("There is invalid exif data parameter"); + context->errMsgArray.insert(std::make_pair(status, context->errMsg)); + continue; + } + status = context->rImageSource->ModifyImagePropertyEx(0, recordIterator->first, recordIterator->second); + if (status != OHOS::Media::SUCCESS) { + context->errMsgArray.insert(std::make_pair(status, recordIterator->first)); + } + } + context->status = context->errMsgArray.size() > 0 ? OHOS::Media::ERROR : OHOS::Media::SUCCESS; +} + +std::vector> GetRecordArgument(map_view records) +{ + std::vector> kVStrArray; + + for (const auto& [key, value] : records) { + std::string valueStr; + if (value.holds_type_string()) { + valueStr = std::string(value.get_type_string_ref()); + } else if (value.holds_type_null()) { + valueStr = ""; + } + kVStrArray.push_back(std::make_pair(std::string(key.get_value()), valueStr)); + } + + IMAGE_LOGD("Get record argument success."); + return kVStrArray; +} + +void ImageSourceImpl::ModifyImagePropertiesSync(map_view records) +{ + OHOS::Media::ImageTrace imageTrace("ImageSourceImpl::ModifyImagePropertiesSync"); + + std::unique_ptr context = std::make_unique(); + if (nativeImgSrc == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "empty native rImageSource"); + return; + } + context->rImageSource = nativeImgSrc; + + context->kVStrArray = GetRecordArgument(records); + if (context->kVStrArray.size() == 0) return; + context->isBatch = true; + + context->pathName = ImageSourceImpl::filePath_; + context->fdIndex = ImageSourceImpl::fileDescriptor_; + context->sourceBuffer = ImageSourceImpl::fileBuffer_; + context->sourceBufferSize = ImageSourceImpl::fileBufferSize_; + + ModifyImagePropertiesExecute(context); + ModifyImagePropertyComplete(context); +} + +static void UpdateDataExecute(std::unique_ptr &context) +{ + if (context == nullptr) { + IMAGE_LOGE("empty context"); + return; + } + + uint8_t *buffer = static_cast(context->updataBuffer); + if (context->updataBufferOffset < context->updataBufferSize) { + buffer = buffer + context->updataBufferOffset; + } + + uint32_t lastSize = context->updataBufferSize - context->updataBufferOffset; + uint32_t size = context->updataLength < lastSize ? context->updataLength : lastSize; + + uint32_t res = context->rImageSource->UpdateData(buffer, size, + context->isCompleted); + context->isSuccess = res == 0; + if (context->isSuccess && context->thisPtr != nullptr) { + auto incPixelMap = context->thisPtr->GetIncrementalPixelMap(); + if (incPixelMap != nullptr) { + uint8_t decodeProgress = 0; + uint32_t err = incPixelMap->PromoteDecoding(decodeProgress); + if (!(err == OHOS::Media::SUCCESS || + (err == OHOS::Media::ERR_IMAGE_SOURCE_DATA_INCOMPLETE && !context->isCompleted))) { + IMAGE_LOGE("UpdateData PromoteDecoding error"); + context->isSuccess = false; + } + if (context->isCompleted) { + incPixelMap->DetachFromDecoding(); + } + } + } +} + +void ImageSourceImpl::UpdateDataSync(array_view buf, bool isFinished, int32_t offset, int32_t length) +{ + std::unique_ptr taiheContext = std::make_unique(); + taiheContext->thisPtr = this; + if (nativeImgSrc == nullptr) { + ImageTaiheUtils::ThrowExceptionError("empty native rImageSource"); + return; + } + taiheContext->rImageSource = nativeImgSrc; + if (buf.empty()) { + ImageTaiheUtils::ThrowExceptionError("empty buf"); + return; + } + taiheContext->updataBuffer = buf.data(); + taiheContext->updataBufferSize = buf.size(); + + taiheContext->isCompleted = isFinished; + taiheContext->updataBufferOffset = offset; + taiheContext->updataLength = length; + + UpdateDataExecute(taiheContext); + if (!taiheContext->isSuccess) { + ImageTaiheUtils::ThrowExceptionError("UpdateDataExecute error"); + } +} + +void ImageSourceImpl::ReleaseSync() +{ + if (!isRelease) { + if (nativeImgSrc != nullptr) { + nativeImgSrc = nullptr; + } + isRelease = true; + } +} + +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) +static bool ParseDecodingOptionsForPicture(DecodingOptionsForPicture const& options, + OHOS::Media::DecodingOptionsForPicture &dst) +{ + for (size_t i = 0; i < options.desiredAuxiliaryPictures.size(); i++) { + int32_t type = options.desiredAuxiliaryPictures[i]; + if (type <= static_cast(OHOS::Media::AuxiliaryPictureType::FRAGMENT_MAP)) { + dst.desireAuxiliaryPictures.insert(static_cast(type)); + IMAGE_LOGD("desireAuxiliaryPictures[%{public}zu]: %{public}d", i, type); + } else { + IMAGE_LOGE("unknown auxiliary picture type: %{public}d", type); + return false; + } + } + return true; +} + +static void CreatePictureExecute(std::unique_ptr &context) +{ + IMAGE_LOGD("CreatePictureExecute IN"); + uint32_t errorCode; + context->rPicture = context->rImageSource->CreatePicture(context->decodingOptsForPicture, errorCode); + if (context->rPicture != nullptr) { + context->status = OHOS::Media::SUCCESS; + } else { + context->status = errorCode; + } + IMAGE_LOGD("CreatePictureExecute OUT"); +} + +static Picture CreatePictureComplete(std::unique_ptr &context) +{ + IMAGE_LOGD("CreatePictureComplete IN"); + if (context->status != OHOS::Media::SUCCESS) { + std::pair errorMsg(static_cast(IMAGE_DECODE_FAILED), "Create Picture error"); + context->errMsgArray.insert(errorMsg); + for (const auto &[errorCode, errMsg] : context->errMsgArray) { + ImageTaiheUtils::ThrowExceptionError(errorCode, errMsg); + } + } + IMAGE_LOGD("CreatePictureComplete OUT"); + return PictureImpl::CreatePicture(context->rPicture); +} + +Picture ImageSourceImpl::CreatePictureSync(optional_view options) +{ + std::unique_ptr taiheContext = std::make_unique(); + taiheContext->thisPtr = this; + if (nativeImgSrc == nullptr) { + ImageTaiheUtils::ThrowExceptionError("empty native rImageSource"); + return make_holder(); + } + taiheContext->rImageSource = nativeImgSrc; + + if (!options.has_value()) { + for (int32_t type = static_cast(OHOS::Media::AuxiliaryPictureType::GAINMAP); + type <= static_cast(OHOS::Media::AuxiliaryPictureType::FRAGMENT_MAP); type++) { + taiheContext->decodingOptsForPicture.desireAuxiliaryPictures.insert( + OHOS::Media::AuxiliaryPictureType(type)); + } + } else { + if (!ParseDecodingOptionsForPicture(options.value(), taiheContext->decodingOptsForPicture)) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "DecodingOptionsForPicture mismatch"); + return make_holder(); + } + } + + CreatePictureExecute(taiheContext); + return CreatePictureComplete(taiheContext); +} +#endif + +array ImageSourceImpl::GetSupportedFormats() +{ + std::set formats; + nativeImgSrc->GetSupportedFormats(formats); + std::vector vec(formats.begin(), formats.end()); + return ImageTaiheUtils::ToTaiheArrayString(vec); +} + +static std::string FileUrlToRawPath(const std::string &path) +{ + if (path.size() > FILE_URL_PREFIX.size() && + (path.compare(0, FILE_URL_PREFIX.size(), FILE_URL_PREFIX) == 0)) { + return path.substr(FILE_URL_PREFIX.size()); + } + return path; +} + +ImageSource CreateImageSourceByUriOption(string_view uri, SourceOptions const& options) +{ + OHOS::Media::SourceOptions opts = ImageTaiheUtils::ParseSourceOptions(options); + uint32_t errorCode = OHOS::Media::ERR_MEDIA_INVALID_VALUE; + std::string rawPath = FileUrlToRawPath(std::string(uri)); + + std::shared_ptr imageSource = + OHOS::Media::ImageSource::CreateImageSource(rawPath, opts, errorCode); + if (imageSource == nullptr) { + ImageTaiheUtils::ThrowExceptionError("CreateImageSourceByUriOption error"); + return make_holder(); + } + { + std::lock_guard lock(imageSourceCrossThreadMutex_); + ImageSourceImpl::filePath_ = rawPath; + ImageSourceImpl::fileDescriptor_ = INVALID_FD; + ImageSourceImpl::fileBuffer_ = nullptr; + ImageSourceImpl::fileBufferSize_ = NUM_0; + } + return make_holder(imageSource); +} + +ImageSource CreateImageSourceByUri(string_view uri) +{ + SourceOptions opts {}; + return CreateImageSourceByUriOption(uri, opts); +} + +ImageSource CreateImageSourceByFdOption(double fd, SourceOptions const& options) +{ + int32_t fdInt = static_cast(fd); + OHOS::Media::SourceOptions opts = ImageTaiheUtils::ParseSourceOptions(options); + uint32_t errorCode = OHOS::Media::ERR_MEDIA_INVALID_VALUE; + std::shared_ptr imageSource = + OHOS::Media::ImageSource::CreateImageSource(fdInt, opts, errorCode); + if (imageSource == nullptr) { + ImageTaiheUtils::ThrowExceptionError("CreateImageSourceByFdOption error"); + return make_holder(); + } + { + std::lock_guard lock(imageSourceCrossThreadMutex_); + ImageSourceImpl::filePath_ = ""; + ImageSourceImpl::fileDescriptor_ = fdInt; + ImageSourceImpl::fileBuffer_ = nullptr; + ImageSourceImpl::fileBufferSize_ = NUM_0; + } + return make_holder(imageSource); +} + +ImageSource CreateImageSourceByFd(int32_t fd) +{ + SourceOptions opts {}; + return CreateImageSourceByFdOption(fd, opts); +} + +ImageSource CreateImageSourceByArrayBufferOption(array_view buf, SourceOptions const& options) +{ + OHOS::Media::SourceOptions opts = ImageTaiheUtils::ParseSourceOptions(options); + uint32_t errorCode = OHOS::Media::ERR_MEDIA_INVALID_VALUE; + uint8_t *bufPtr = const_cast(buf.data()); + std::shared_ptr imageSource = + OHOS::Media::ImageSource::CreateImageSource(bufPtr, buf.size(), opts, errorCode); + if (imageSource == nullptr) { + ImageTaiheUtils::ThrowExceptionError("CreateImageSourceByArrayBufferOption error"); + return make_holder(); + } + { + std::lock_guard lock(imageSourceCrossThreadMutex_); + ImageSourceImpl::filePath_ = ""; + ImageSourceImpl::fileDescriptor_ = INVALID_FD; + ImageSourceImpl::fileBuffer_ = bufPtr; + ImageSourceImpl::fileBufferSize_ = buf.size(); + } + return make_holder(imageSource); +} + +ImageSource CreateImageSourceByArrayBuffer(array_view buf) +{ + SourceOptions opts {}; + return CreateImageSourceByArrayBufferOption(buf, opts); +} + +ImageSource CreateIncrementalSourceByArrayBufferOption(array_view buf, optional_view options) +{ + OHOS::Media::IncrementalSourceOptions incOpts; + SourceOptions etsOpts = options.value_or(SourceOptions {}); + incOpts.sourceOptions = ImageTaiheUtils::ParseSourceOptions(etsOpts); + + incOpts.incrementalMode = OHOS::Media::IncrementalMode::INCREMENTAL_DATA; + uint32_t errorCode = 0; + std::shared_ptr imageSource = + OHOS::Media::ImageSource::CreateIncrementalImageSource(incOpts, errorCode); + if (imageSource == nullptr) { + ImageTaiheUtils::ThrowExceptionError("CreateImageSourceByArrayBufferOption error"); + return make_holder(); + } + + OHOS::Media::DecodeOptions decodeOpts; + std::shared_ptr navIncPixelMap = + imageSource->CreateIncrementalPixelMap(0, decodeOpts, errorCode); + + if (errorCode != OHOS::Media::SUCCESS) { + ImageTaiheUtils::ThrowExceptionError("CreateIncrementalPixelMap error"); + return make_holder(); + } + + return make_holder(imageSource, navIncPixelMap); +} + +ImageSource CreateIncrementalSourceByArrayBuffer(array_view buf) +{ + optional_view optionalView; + return CreateIncrementalSourceByArrayBufferOption(buf, optionalView); +} + +ImageSource CreateImageSourceByRawFileDescriptorOption(uintptr_t rawfile, optional_view options) +{ + double fd; + double offset; + double length; + ani_env *env = ::taihe::get_env(); + ani_object rawfileObj = reinterpret_cast(rawfile); + if (!ImageTaiheUtils::GetPropertyDouble(env, rawfileObj, "fd", fd) || + !ImageTaiheUtils::GetPropertyDouble(env, rawfileObj, "offset", offset) || + !ImageTaiheUtils::GetPropertyDouble(env, rawfileObj, "length", length)) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "GetPropertyDouble failed"); + return make_holder(); + } + SourceOptions etsOpts = options.value_or(SourceOptions {}); + OHOS::Media::SourceOptions opts = ImageTaiheUtils::ParseSourceOptions(etsOpts); + + uint32_t errorCode = OHOS::Media::ERR_MEDIA_INVALID_VALUE; + int32_t fileSize = static_cast(offset) + static_cast(length); + std::shared_ptr imageSource = OHOS::Media::ImageSource::CreateImageSource( + static_cast(fd), static_cast(offset), fileSize, opts, errorCode); + if (imageSource == nullptr) { + ImageTaiheUtils::ThrowExceptionError("CreateImageSourceByRawFileDescriptorOption error"); + return make_holder(); + } + { + std::lock_guard lock(imageSourceCrossThreadMutex_); + ImageSourceImpl::filePath_ = ""; + ImageSourceImpl::fileDescriptor_ = INVALID_FD; + ImageSourceImpl::fileBuffer_ = nullptr; + ImageSourceImpl::fileBufferSize_ = NUM_0; + } + return make_holder(imageSource); +} + +ImageSource CreateImageSourceByPtr(int64_t ptr) +{ + return taihe::make_holder(ptr); +} +} // namespace ANI::Image + +TH_EXPORT_CPP_API_CreateImageSourceByUri(CreateImageSourceByUri); +TH_EXPORT_CPP_API_CreateImageSourceByUriOption(CreateImageSourceByUriOption); +TH_EXPORT_CPP_API_CreateImageSourceByFd(CreateImageSourceByFd); +TH_EXPORT_CPP_API_CreateImageSourceByFdOption(CreateImageSourceByFdOption); +TH_EXPORT_CPP_API_CreateImageSourceByArrayBuffer(CreateImageSourceByArrayBuffer); +TH_EXPORT_CPP_API_CreateImageSourceByArrayBufferOption(CreateImageSourceByArrayBufferOption); +TH_EXPORT_CPP_API_CreateImageSourceByRawFileDescriptorOption(CreateImageSourceByRawFileDescriptorOption); +TH_EXPORT_CPP_API_CreateIncrementalSourceByArrayBuffer(CreateIncrementalSourceByArrayBuffer); +TH_EXPORT_CPP_API_CreateIncrementalSourceByArrayBufferOption(CreateIncrementalSourceByArrayBufferOption); +TH_EXPORT_CPP_API_CreateImageSourceByPtr(CreateImageSourceByPtr); \ No newline at end of file diff --git a/frameworks/kits/taihe/src/image_source_taihe_ani.cpp b/frameworks/kits/taihe/src/image_source_taihe_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..01d83f37b22bfd92f2ea60d59c1d72895cce9094 --- /dev/null +++ b/frameworks/kits/taihe/src/image_source_taihe_ani.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "image_log.h" +#include "image_source_taihe_ani.h" + +// This file is for legacy ANI backward compatibility + +namespace OHOS { +namespace Media { +ani_object ImageSourceTaiheAni::CreateEtsImageSource(ani_env *env, std::shared_ptr imageSource) +{ + std::unique_ptr imageSourceAni = std::make_unique(); + imageSourceAni->nativeImgSrc = imageSource; + + ani_namespace imageNamespace; + if (env->FindNamespace("L@ohos/multimedia/image/image;", &imageNamespace) != ANI_OK) { + IMAGE_LOGE("%{public}s FindNamespace failed", __func__); + return nullptr; + } + + ani_function createFunc; + if (env->Namespace_FindFunction(imageNamespace, "createImageSourceByPtr", nullptr, &createFunc) != ANI_OK) { + IMAGE_LOGE("%{public}s Namespace_FindFunction failed", __func__); + return nullptr; + } + + ani_ref imageSourceObj; + if (env->Function_Call_Ref(createFunc, &imageSourceObj, + reinterpret_cast(imageSourceAni.get())) != ANI_OK) { + IMAGE_LOGE("%{public}s Function_Call_Ref failed", __func__); + return nullptr; + } + + imageSourceAni.release(); + return reinterpret_cast(imageSourceObj); +} + +} // namespace Media +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/kits/taihe/src/image_taihe.cpp b/frameworks/kits/taihe/src/image_taihe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f9725ce8eac9457a7aae93efd15be0d289dffcb0 --- /dev/null +++ b/frameworks/kits/taihe/src/image_taihe.cpp @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "image_format.h" +#include "image_log.h" +#include "image_taihe.h" +#include "image_taihe_utils.h" +#include "media_errors.h" + +using namespace ANI::Image; + +namespace { + constexpr int NUM0 = 0; + const std::string MY_NAME = "ImageTaihe"; + constexpr int32_t TEST_WIDTH = 8192; + constexpr int32_t TEST_HEIGHT = 8; + constexpr int32_t TEST_FORMAT = 12; +} + +namespace ANI::Image { +OHOS::Media::ImageHolderManager ImageImpl::sNativeImageHolder_; + +ImageImpl::ImageImpl() : nativeImage_(nullptr) {} + +ImageImpl::ImageImpl(std::shared_ptr nativeImage) +{ + if (nativeImage == nullptr) { + IMAGE_LOGE("nativeImage is nullptr"); + ImageTaiheUtils::ThrowExceptionError("nativeImage is nullptr"); + return; + } + + auto id = sNativeImageHolder_.save(nativeImage); + nativeImage->SetId(id); + nativeImage_ = sNativeImageHolder_.get(id); + isTestImage_ = false; + if (nativeImage_ == nullptr) { + if (MY_NAME.compare(id.c_str()) == 0) { + isTestImage_ = true; + } else { + IMAGE_LOGE("Failed to get native image"); + ImageTaiheUtils::ThrowExceptionError("Failed to get native image"); + return; + } + } +} + +ImageImpl::~ImageImpl() +{ + NativeRelease(); +} + +static inline bool IsEqual(const int32_t& check, OHOS::Media::ImageFormat format) +{ + return (check == int32_t(format)); +} +static inline bool IsEqual(const int32_t& check, OHOS::Media::ComponentType type) +{ + return (check == int32_t(type)); +} +static inline bool IsYUVComponent(const int32_t& type) +{ + return (IsEqual(type, OHOS::Media::ComponentType::YUV_Y) || + IsEqual(type, OHOS::Media::ComponentType::YUV_U) || + IsEqual(type, OHOS::Media::ComponentType::YUV_V)); +} +static inline bool IsYUV422SPImage(int32_t format) +{ + return (IsEqual(format, OHOS::Media::ImageFormat::YCBCR_422_SP) || + (format == int32_t(OHOS::GRAPHIC_PIXEL_FMT_YCBCR_422_SP))); +} +static inline bool CheckComponentType(const int32_t& type, int32_t format) +{ + return ((IsYUV422SPImage(format) && IsYUVComponent(type)) || + (!IsYUV422SPImage(format) && IsEqual(type, OHOS::Media::ComponentType::JPEG))); +} + +static Component MakeEmptyComponent() +{ + return {ComponentType(ComponentType::key_t::YUV_Y), 0, 0, array(0)}; +} + +static Component MakeComponent(int32_t type, OHOS::Media::NativeComponent *nativeComponent) +{ + ComponentType::key_t componentTypeKey; + ImageTaiheUtils::GetEnumKeyByValue(static_cast(type), componentTypeKey); + if (nativeComponent == nullptr) { + IMAGE_LOGE("nativeComponent is nullptr"); + return {ComponentType(componentTypeKey), 0, 0, array(0)}; + } + uint8_t *buffer = nullptr; + if (nativeComponent->virAddr != nullptr) { + buffer = nativeComponent->virAddr; + } else { + buffer = nativeComponent->raw.data(); + } + if (buffer == nullptr || nativeComponent->size == 0) { + IMAGE_LOGE("Invalid buffer"); + return MakeEmptyComponent(); + } + + Component result { + .componentType = ComponentType(componentTypeKey), + .rowStride = nativeComponent->rowStride, + .pixelStride = nativeComponent->pixelStride, + .byteBuffer = ImageTaiheUtils::CreateTaiheArrayBuffer(buffer, nativeComponent->size), + }; + return result; +} + +int64_t ImageImpl::GetImplPtr() +{ + return reinterpret_cast(this); +} + +struct Image ImageImpl::Create(std::shared_ptr nativeImage) +{ + return make_holder(nativeImage); +} + +void ImageImpl::ReleaseSync() +{ + NativeRelease(); +} + +void ImageImpl::NativeRelease() +{ + if (nativeImage_ != nullptr) { + sNativeImageHolder_.release(nativeImage_->GetId()); + nativeImage_->release(); + nativeImage_ = nullptr; + } +} + +static ohos::multimedia::image::image::Region BuildRegion(int32_t width, int32_t height, int32_t x, int32_t y) +{ + Size size {width, height}; + ohos::multimedia::image::image::Region result = {size, x, y}; + return result; +} + +ohos::multimedia::image::image::Region ImageImpl::GetClipRect() +{ + ohos::multimedia::image::image::Region errResult = BuildRegion(NUM0, NUM0, NUM0, NUM0); + if (isTestImage_) { + return BuildRegion(TEST_WIDTH, TEST_HEIGHT, NUM0, NUM0); + } + if (nativeImage_ == nullptr) { + IMAGE_LOGE("Image surface buffer is nullptr"); + return errResult; + } + + int32_t width = NUM0; + int32_t height = NUM0; + if (nativeImage_->GetSize(width, height) != OHOS::Media::SUCCESS) { + IMAGE_LOGE("Image native get size failed"); + return errResult; + } + return BuildRegion(width, height, NUM0, NUM0); +} + +Size ImageImpl::GetSize() +{ + int width = NUM0; + int height = NUM0; + if (isTestImage_) { + return {TEST_WIDTH, TEST_HEIGHT}; + } + if (nativeImage_ == nullptr) { + IMAGE_LOGE("Image surface buffer is nullptr"); + return {width, height}; + } + + if (nativeImage_->GetSize(width, height) != OHOS::Media::SUCCESS) { + IMAGE_LOGE("Image native get size failed"); + } + return {width, height}; +} + +Component ImageImpl::GetComponentSync(ComponentType componentType) +{ + int32_t argc = componentType.get_value(); + if (nativeImage_ == nullptr && !isTestImage_) { + IMAGE_LOGE("native is nullptr"); + return MakeEmptyComponent(); + } + + int32_t format = NUM0; + if (isTestImage_) { + const int32_t TEST_FORMAT = 12; + format = TEST_FORMAT; + } else { + nativeImage_->GetFormat(format); + } + + if (!CheckComponentType(argc, format)) { + IMAGE_LOGE("Unsupport component type 0 value: %{public}d", argc); + return MakeEmptyComponent(); + } + + if (isTestImage_) { + return MakeComponent(argc, nullptr); + } + + OHOS::Media::NativeComponent *nativeComponent = nativeImage_->GetComponent(argc); + if (nativeComponent == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERROR, "nativeComponent is nullptr"); + return MakeEmptyComponent(); + } + + return MakeComponent(argc, nativeComponent); +} + +int32_t ImageImpl::GetFormat() +{ + int32_t format = NUM0; + if (isTestImage_) { + return TEST_FORMAT; + } + if (nativeImage_ == nullptr) { + IMAGE_LOGE("Image surface buffer is nullptr"); + return format; + } + + if (nativeImage_->GetFormat(format) != OHOS::Media::SUCCESS) { + IMAGE_LOGE("Image native get format failed"); + } + return format; +} + +int64_t ImageImpl::GetTimestamp() +{ + int64_t result = 0; + if (nativeImage_ == nullptr) { + IMAGE_LOGE("Image native is nullptr"); + return result; + } + + if (nativeImage_->GetTimestamp(result) != OHOS::Media::SUCCESS) { + IMAGE_LOGE("Image native get timestamp failed"); + } + return result; +} +} // namespace ANI::Image \ No newline at end of file diff --git a/frameworks/kits/taihe/src/image_taihe_utils.cpp b/frameworks/kits/taihe/src/image_taihe_utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fd4443fb352d78622bbc8cc474b62a5e2f3a2d98 --- /dev/null +++ b/frameworks/kits/taihe/src/image_taihe_utils.cpp @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "image_log.h" +#include "image_taihe_utils.h" + +namespace ANI::Image { +constexpr char CLASS_NAME_BUSINESSERROR[] = "L@ohos/base/BusinessError;"; + +void ImageTaiheUtils::HicheckerReport() +{ +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) && defined(HICHECKER_ENABLE) + uint32_t pid = getpid(); + uint32_t tid = gettid(); + std::string cautionMsg = "Trigger: pid = " + std::to_string(pid) + ", tid = " + std::to_string(tid); + HiviewDFX::HiChecker::NotifySlowProcess(cautionMsg); +#endif +} + +void ImageTaiheUtils::ThrowExceptionError(const std::string &errMsg) +{ + IMAGE_LOGE("errMsg: %{public}s", errMsg.c_str()); + taihe::set_error(errMsg); +} + +void ImageTaiheUtils::ThrowExceptionError(const int32_t errCode, const std::string &errMsg) +{ + IMAGE_LOGE("errCode: %{public}d, errMsg: %{public}s", errCode, errMsg.c_str()); + taihe::set_business_error(errCode, errMsg); +} + +bool ImageTaiheUtils::GetPropertyDouble(ani_env *env, ani_object obj, const std::string &name, double &value) +{ + CHECK_ERROR_RETURN_RET_LOG(env == nullptr || obj == nullptr, false, "%{public}s param is nullptr", __func__); + ani_double result; + env->Object_GetPropertyByName_Double(obj, name.c_str(), &result); + value = static_cast(result); + return true; +} + +ani_object ImageTaiheUtils::ToBusinessError(ani_env *env, int32_t code, const std::string &message) +{ + ani_object err {}; + ani_class cls {}; + CHECK_ERROR_RETURN_RET_LOG(ANI_OK != env->FindClass(CLASS_NAME_BUSINESSERROR, &cls), err, + "find class %{public}s failed", CLASS_NAME_BUSINESSERROR); + ani_method ctor {}; + CHECK_ERROR_RETURN_RET_LOG(ANI_OK != env->Class_FindMethod(cls, "", ":V", &ctor), err, + "find method BusinessError constructor failed"); + ani_object error {}; + CHECK_ERROR_RETURN_RET_LOG(ANI_OK != env->Object_New(cls, ctor, &error), err, + "new object %{public}s failed", CLASS_NAME_BUSINESSERROR); + CHECK_ERROR_RETURN_RET_LOG( + ANI_OK != env->Object_SetPropertyByName_Double(error, "code", static_cast(code)), err, + "set property BusinessError.code failed"); + ani_string messageRef {}; + CHECK_ERROR_RETURN_RET_LOG(ANI_OK != env->String_NewUTF8(message.c_str(), message.size(), &messageRef), err, + "new message string failed"); + CHECK_ERROR_RETURN_RET_LOG( + ANI_OK != env->Object_SetPropertyByName_Ref(error, "message", static_cast(messageRef)), err, + "set property BusinessError.message failed"); + return error; +} + +OHOS::Media::SourceOptions ImageTaiheUtils::ParseSourceOptions(SourceOptions const& options) +{ + OHOS::Media::SourceOptions opts {}; + opts.baseDensity = options.sourceDensity; + OHOS::Media::PixelFormat pixelFormat = OHOS::Media::PixelFormat::UNKNOWN; + if (options.sourcePixelFormat.has_value()) { + pixelFormat = static_cast(options.sourcePixelFormat->get_value()); + } + opts.pixelFormat = pixelFormat; + OHOS::Media::Size size {}; + if (options.sourceSize.has_value()) { + size.width = options.sourceSize.value().width; + size.height = options.sourceSize.value().height; + } + opts.size = size; + return opts; +} + +ImageInfo ImageTaiheUtils::ToTaiheImageInfo(const OHOS::Media::ImageInfo &src, bool isHdr) +{ + Size size { + .width = src.size.width, + .height = src.size.height, + }; + + PixelMapFormat::key_t pixelFormatKey; + GetEnumKeyByValue(static_cast(src.pixelFormat), pixelFormatKey); + AlphaType::key_t alphaTypeKey; + GetEnumKeyByValue(static_cast(src.alphaType), alphaTypeKey); + + ImageInfo result { + .size = size, + .pixelFormat = PixelMapFormat(pixelFormatKey), + .alphaType = AlphaType(alphaTypeKey), + .mimeType = src.encodedFormat, + .isHdr = isHdr, + }; + return result; +} + +array ImageTaiheUtils::ToTaiheArrayString(const std::vector &src) +{ + std::vector<::taihe::string> vec; + for (const auto &item : src) { + vec.emplace_back(item); + } + return array(vec); +} + +array ImageTaiheUtils::CreateTaiheArrayBuffer(uint8_t* src, size_t srcLen) +{ + if (src == nullptr || srcLen == 0) { + return array(0); + } + return array(copy_data_t{}, src, srcLen); +} + +uintptr_t ImageTaiheUtils::GetUndefinedPtr(ani_env *env) +{ + ani_ref undefinedRef {}; + env->GetUndefined(&undefinedRef); + ani_object undefinedObj = static_cast(undefinedRef); + return reinterpret_cast(undefinedObj); +} + +template +bool ImageTaiheUtils::GetEnumKeyByValue(ValueType value, typename EnumType::key_t &key) +{ + for (size_t index = 0; index < std::size(EnumType::table); ++index) { + if (EnumType::table[index] == value) { + key = static_cast(index); + return true; + } + } + return false; +} + +template +bool ImageTaiheUtils::IsValidPtr(T data) +{ + return !data.is_error(); +} + +template +bool ImageTaiheUtils::GetEnumKeyByValue(int32_t value, typename ImageFormat::key_t &key); + +template +bool ImageTaiheUtils::GetEnumKeyByValue(int32_t value, typename PixelMapFormat::key_t &key); + +template +bool ImageTaiheUtils::GetEnumKeyByValue(int32_t value, typename AlphaType::key_t &key); + +template +bool ImageTaiheUtils::GetEnumKeyByValue(std::string value, typename PropertyKey::key_t &key); + +template +bool ImageTaiheUtils::GetEnumKeyByValue(int32_t value, + typename AuxiliaryPictureType::key_t &key); + +template +bool ImageTaiheUtils::GetEnumKeyByValue(int32_t value, typename ComponentType::key_t &key); + +template +bool ImageTaiheUtils::IsValidPtr(weak::PixelMap data); + +template +bool ImageTaiheUtils::IsValidPtr(weak::ImageSource data); + +template +bool ImageTaiheUtils::IsValidPtr(weak::Picture data); +} // namespace ANI::Image \ No newline at end of file diff --git a/frameworks/kits/taihe/src/metadata_taihe.cpp b/frameworks/kits/taihe/src/metadata_taihe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..30aaee77c18c36cbb90890ed0441b2070b9aaeba --- /dev/null +++ b/frameworks/kits/taihe/src/metadata_taihe.cpp @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "media_errors.h" +#include "metadata_taihe.h" +#include "image_common.h" +#include "image_log.h" +#include "image_taihe_utils.h" + +using namespace ANI::Image; + +namespace ANI::Image { + +struct MetadataTaiheContext { + uint32_t status; + std::shared_ptr rMetadata; + std::vector keyStrArray; + std::multimap errMsgArray; + std::vector> kVStrArray; +}; + +MetadataImpl::MetadataImpl() {} + +MetadataImpl::MetadataImpl(std::shared_ptr imageMetadata) +{ + nativeMetadata_ = imageMetadata; + if (nativeMetadata_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Failed to set nativeMetadata_ with null. Maybe a reentrancy error"); + } +} + +MetadataImpl::~MetadataImpl() +{ + Release(); +} + +int64_t MetadataImpl::GetImplPtr() +{ + return reinterpret_cast(this); +} + +std::shared_ptr MetadataImpl::GetNativeMetadata() +{ + return nativeMetadata_; +} + +static std::vector GetKeyStrArray(array_view const& key) +{ + std::vector keyStrArray; + for (const auto& str : key) { + keyStrArray.emplace_back(str); + } + return keyStrArray; +} + +static void GetPropertiesSyncExecute(std::unique_ptr &context) +{ + if (context == nullptr) { + IMAGE_LOGE("Empty context"); + return; + } + uint32_t status = OHOS::Media::SUCCESS; + for (auto keyStrIt = context->keyStrArray.begin(); keyStrIt != context->keyStrArray.end(); ++keyStrIt) { + std::string valueStr = ""; + status = static_cast(context->rMetadata->GetValue(*keyStrIt, valueStr)); + if (status == OHOS::Media::SUCCESS) { + context->kVStrArray.emplace_back(std::make_pair(*keyStrIt, valueStr)); + } else { + context->kVStrArray.emplace_back(std::make_pair(*keyStrIt, "")); + context->errMsgArray.insert(std::make_pair(status, *keyStrIt)); + IMAGE_LOGE("ErrCode: %{public}u , exif key: %{public}s", status, keyStrIt->c_str()); + } + } + context->status = + context->kVStrArray.size() == context->errMsgArray.size() ? OHOS::Media::ERROR : OHOS::Media::SUCCESS; +} + +static PropertyValue CreatePropertyValue(std::string const& valueStr) +{ + if (!valueStr.empty()) { + return PropertyValue::make_type_string(valueStr); + } else { + return PropertyValue::make_type_null(); + } +} + +static map CreatePropertiesRecord( + std::vector> const& kVStrArray) +{ + map result; + for (size_t index = 0; index < kVStrArray.size(); ++index) { + string key = kVStrArray[index].first; + PropertyValue value = CreatePropertyValue(kVStrArray[index].second); + result.emplace(key, value); + } + IMAGE_LOGD("Get record parameters info success."); + return result; +} + +static bool FragmentValueIsError(std::multimap const& errMsgArray) +{ + static std::set fragmentKeys = { + "XInOriginal", "YInOriginal", "FragmentImageWidth", "FragmentImageHeight" + }; + for (const auto &errMsg : errMsgArray) { + if (fragmentKeys.find(errMsg.second) != fragmentKeys.end()) { + return true; + } + } + return false; +} + +static void CreateErrorArray(std::unique_ptr const& context) +{ + std::string errkey = ""; + if (context->errMsgArray.empty()) { + return; + } + for (const auto &errMsg : context->errMsgArray) { + errkey += errMsg.second + " "; + } + if (context->rMetadata->GetType() == OHOS::Media::MetadataType::FRAGMENT && + FragmentValueIsError(context->errMsgArray)) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "The input value is incorrect!"); + } else { + ImageTaiheUtils::ThrowExceptionError(IMAGE_UNSUPPORTED_METADATA, + "The input data is incorrect! error key: " + errkey); + } +} + +static map GetPropertiesSyncComplete(std::unique_ptr const& context) +{ + map result; + if (context == nullptr) { + IMAGE_LOGE("Context is nullptr"); + return result; + } + if (context->status == OHOS::Media::SUCCESS) { + result = CreatePropertiesRecord(context->kVStrArray); + } else { + CreateErrorArray(context); + } + return result; +} + +map MetadataImpl::GetPropertiesSync(array_view key) +{ + std::unique_ptr context = std::make_unique(); + context->rMetadata = nativeMetadata_; + map result; + if (context->rMetadata == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native metadata."); + return result; + } + context->keyStrArray = GetKeyStrArray(key); + GetPropertiesSyncExecute(context); + result = GetPropertiesSyncComplete(context); + return result; +} + +static std::vector> GetKVStrArray(map_view const& records) +{ + std::vector> kVStrArray; + for (const auto& [key, value] : records) { + std::string valueStr; + if (value.holds_type_string()) { + valueStr = std::string(value.get_type_string_ref()); + } else if (value.holds_type_null()) { + valueStr = ""; + } + kVStrArray.emplace_back(key, valueStr); + } + IMAGE_LOGD("Get record argument success."); + return kVStrArray; +} + +static void SetPropertiesSyncExecute(std::unique_ptr &context) +{ + if (context == nullptr) { + IMAGE_LOGE("Empty context"); + return; + } + uint32_t status = OHOS::Media::SUCCESS; + for (auto kVStrIt = context->kVStrArray.begin(); kVStrIt != context->kVStrArray.end(); ++kVStrIt) { + IMAGE_LOGD("CheckExifDataValue"); + status = context->rMetadata->SetValue(kVStrIt->first, kVStrIt->second); + IMAGE_LOGD("Check ret status: %{public}d", status); + if (!status) { + IMAGE_LOGE("There is invalid exif data parameter"); + context->errMsgArray.insert(std::make_pair(status, kVStrIt->first)); + } + } + context->status = context->errMsgArray.size() > 0 ? OHOS::Media::ERROR : OHOS::Media::SUCCESS; +} + +static void SetPropertiesComplete(std::unique_ptr const& context) +{ + if (context == nullptr) { + IMAGE_LOGE("Empty context"); + return; + } + CreateErrorArray(context); +} + +void MetadataImpl::SetPropertiesSync(map_view records) +{ + std::unique_ptr context = std::make_unique(); + context->rMetadata = nativeMetadata_; + if (context->rMetadata == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native metadata."); + return; + } + context->kVStrArray = GetKVStrArray(records); + SetPropertiesSyncExecute(context); + SetPropertiesComplete(context); +} + +static void GetAllPropertiesSyncExecute(std::unique_ptr &context) +{ + if (context == nullptr) { + IMAGE_LOGE("Empty context"); + return; + } + OHOS::Media::ImageMetadata::PropertyMapPtr allKey = context->rMetadata->GetAllProperties(); + for (const auto &entry : *allKey) { + context->kVStrArray.emplace_back(std::make_pair(entry.first, entry.second)); + } + context->status = OHOS::Media::SUCCESS; +} + +static map GetAllPropertiesSyncComplete(std::unique_ptr const& context) +{ + map result; + if (context == nullptr) { + IMAGE_LOGE("Context is nullptr"); + return result; + } + if (context->status == OHOS::Media::SUCCESS) { + result = CreatePropertiesRecord(context->kVStrArray); + } else { + CreateErrorArray(context); + } + return result; +} + +map MetadataImpl::GetAllPropertiesSync() +{ + std::unique_ptr context = std::make_unique(); + context->rMetadata = nativeMetadata_; + map result; + if (context->rMetadata == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native metadata."); + return result; + } + GetAllPropertiesSyncExecute(context); + result = GetAllPropertiesSyncComplete(context); + return result; +} + +Metadata MetadataImpl::CloneSync() +{ + if (nativeMetadata_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native metadata."); + return make_holder(); + } + auto metadata = nativeMetadata_->CloneMetadata(); + return make_holder(std::move(metadata)); +} + +void MetadataImpl::Release() +{ + if (!isRelease) { + if (nativeMetadata_ != nullptr) { + nativeMetadata_ = nullptr; + } + isRelease = true; + } +} + +} // namespace ANI::Image \ No newline at end of file diff --git a/frameworks/kits/taihe/src/picture_taihe.cpp b/frameworks/kits/taihe/src/picture_taihe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..bdeacada6c19ce8579a9090cc2df3d568f767828 --- /dev/null +++ b/frameworks/kits/taihe/src/picture_taihe.cpp @@ -0,0 +1,349 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "auxiliary_picture_taihe.h" +#include "image_common.h" +#include "image_log.h" +#include "image_taihe_utils.h" +#include "image_type.h" +#include "picture_taihe.h" +#include "picture_taihe_ani.h" +#include "pixel_map_taihe.h" +#include "media_errors.h" +#include "message_parcel.h" +#include "metadata_taihe.h" + +using namespace ANI::Image; + +namespace ANI::Image { + +PictureImpl::PictureImpl() : nativePicture_(nullptr), isRelease(false) {} + +PictureImpl::PictureImpl(std::shared_ptr picture) +{ + nativePicture_ = picture; + if (nativePicture_ == nullptr) { + IMAGE_LOGE("Failed to set nativePicture_ with null. Maybe a reentrancy error"); + } +} + +PictureImpl::PictureImpl(int64_t aniPtr) +{ + OHOS::Media::PictureTaiheAni *pictureAni = reinterpret_cast(aniPtr); + if (pictureAni != nullptr && pictureAni->nativePicture_ != nullptr) { + nativePicture_ = pictureAni->nativePicture_; + } else { + ImageTaiheUtils::ThrowExceptionError("aniPtr is invalid or nativePicture_ is nullptr"); + } +} + +PictureImpl::~PictureImpl() +{ + Release(); +} + +int64_t PictureImpl::GetImplPtr() +{ + return reinterpret_cast(this); +} + +std::shared_ptr PictureImpl::GetNativePtr() +{ + return nativePicture_; +} + +Picture PictureImpl::CreatePicture(std::shared_ptr picture) +{ + return make_holder(picture); +} + +PixelMap PictureImpl::GetMainPixelmap() +{ + if (nativePicture_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Native picture is nullptr!"); + return make_holder(); + } + auto pixelmap = nativePicture_->GetMainPixel(); + if (pixelmap == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Get main pixelmap failed, pixelmap is nullptr!"); + return make_holder(); + } + return PixelMapImpl::CreatePixelMap(pixelmap); +} + +PixelMap PictureImpl::GetHdrComposedPixelmapSync() +{ + IMAGE_LOGD("GetHdrComposedPixelMap IN"); + if (nativePicture_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native pixelmap"); + return make_holder(); + } + if (nativePicture_->GetAuxiliaryPicture(OHOS::Media::AuxiliaryPictureType::GAINMAP) == nullptr) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_UNSUPPORTED_OPERATION, "There is no GAINMAP"); + return make_holder(); + } + if (nativePicture_->GetMainPixel()->GetAllocatorType() != OHOS::Media::AllocatorType::DMA_ALLOC) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_UNSUPPORTED_OPERATION, "Unsupported operations"); + return make_holder(); + } + + auto tmpixel = nativePicture_->GetHdrComposedPixelMap(); + if (tmpixel == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERROR, "Get hdr composed pixelMap failed"); + return make_holder(); + } + return PixelMapImpl::CreatePixelMap(std::move(tmpixel)); +} + +GainMap PictureImpl::GetGainmapPixelmap() +{ + IMAGE_LOGD("GetGainmapPixelmap"); + + if (nativePicture_ != nullptr) { + auto gainpixelmap = nativePicture_->GetGainmapPixelMap(); + return GainMap::make_type_gainMap(PixelMapImpl::CreatePixelMap(gainpixelmap)); + } else { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_MEDIA_UNKNOWN, "Picture is a null pointer"); + return GainMap::make_type_null(); + } +} + +static OHOS::Media::AuxiliaryPictureType ParseAuxiliaryPictureType(int32_t val) +{ + if (val >= static_cast(OHOS::Media::AuxiliaryPictureType::GAINMAP) + && val<= static_cast(OHOS::Media::AuxiliaryPictureType::FRAGMENT_MAP)) { + return OHOS::Media::AuxiliaryPictureType(val); + } + + return OHOS::Media::AuxiliaryPictureType::NONE; +} + +void PictureImpl::SetAuxiliaryPicture(AuxiliaryPictureType type, weak::AuxiliaryPicture auxiliaryPicture) +{ + IMAGE_LOGD("SetAuxiliaryPictureSync IN"); + + OHOS::Media::AuxiliaryPictureType auxType = ParseAuxiliaryPictureType(type.get_value()); + if (auxType == OHOS::Media::AuxiliaryPictureType::NONE) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, + "The type does not match the auxiliary picture type!"); + return; + } + + AuxiliaryPictureImpl* auxiliaryPictureImpl = + reinterpret_cast(auxiliaryPicture->GetImplPtr()); + if (auxiliaryPictureImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Fail to unwrap AuxiliaryPictureImpl!"); + return; + } + + if (nativePicture_ != nullptr) { + auto auxiliaryPicturePtr = auxiliaryPictureImpl->GetNativeAuxiliaryPic(); + if (auxiliaryPicturePtr != nullptr) { + if (auxType != auxiliaryPicturePtr->GetAuxiliaryPictureInfo().auxiliaryPictureType) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, + "The type does not match the auxiliary picture type!"); + } else { + nativePicture_->SetAuxiliaryPicture(auxiliaryPicturePtr); + } + } else { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, + "Native auxiliary picture is nullptr!"); + } + } else { + ImageTaiheUtils::ThrowExceptionError("native picture is nullptr!"); + } +} + +AuxPicture PictureImpl::GetAuxiliaryPicture(AuxiliaryPictureType type) +{ + AuxPicture result = AuxPicture::make_type_null(); + + IMAGE_LOGD("GetAuxiliaryPicture IN"); + OHOS::Media::AuxiliaryPictureType auxType = ParseAuxiliaryPictureType(type.get_value()); + if (auxType == OHOS::Media::AuxiliaryPictureType::NONE) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, + "The type does not match the auxiliary picture type!"); + } + + if (nativePicture_ != nullptr) { + auto auxiliaryPic = nativePicture_->GetAuxiliaryPicture(auxType); + if (auxiliaryPic != nullptr) { + result = AuxPicture::make_type_auxPicture( + make_holder(std::move(auxiliaryPic))); + } else { + ImageTaiheUtils::ThrowExceptionError("native auxiliary picture is nullptr!"); + } + } else { + ImageTaiheUtils::ThrowExceptionError("native picture is nullptr!"); + } + + return result; +} + +void PictureImpl::SetMetadataSync(MetadataType metadataType, weak::Metadata metadata) +{ + IMAGE_LOGD("SetMetadata IN"); + if (nativePicture_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native picture"); + return; + } + + OHOS::Media::MetadataType type; + uint32_t typeValue = metadataType.get_value(); + if (typeValue == static_cast(OHOS::Media::MetadataType::EXIF)) { + type = OHOS::Media::MetadataType(typeValue); + } else { + ImageTaiheUtils::ThrowExceptionError(IMAGE_UNSUPPORTED_METADATA, "Unsupport MetadataType"); + return; + } + + MetadataImpl* metadataImpl = reinterpret_cast(metadata->GetImplPtr()); + if (metadataImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Fail to unwrap MetadataImpl."); + return; + } + std::shared_ptr imageMetadata = metadataImpl->GetNativeMetadata(); + + int32_t status = nativePicture_->SetExifMetadata( + std::reinterpret_pointer_cast(imageMetadata)); + if (status != OHOS::Media::SUCCESS) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERROR, "Set Metadata failed!"); + } +} + +Metadata PictureImpl::GetMetadataSync(MetadataType metadataType) +{ + IMAGE_LOGD("GetMetadata IN"); + if (nativePicture_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Empty native picture"); + return make_holder(); + } + + uint32_t typeValue = metadataType.get_value(); + if (typeValue != static_cast(OHOS::Media::MetadataType::EXIF)) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_UNSUPPORTED_METADATA, "Unsupport MetadataType"); + return make_holder(); + } + + auto imageMetadata = std::reinterpret_pointer_cast(nativePicture_->GetExifMetadata()); + if (imageMetadata == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERROR, "Get Metadata failed!"); + return make_holder(); + } + return make_holder(imageMetadata); +} + +static bool UnwarpMessageParcel(const uintptr_t& sequence, ani_long& nativePtr) +{ + ani_env *env = ::taihe::get_env(); + if (env == nullptr) { + IMAGE_LOGE("%{pubilc}s Get ani env failed.", __func__); + return false; + } + ani_object sequenceObj = reinterpret_cast(sequence); + if (ANI_OK != env->Object_GetFieldByName_Long(sequenceObj, "nativePtr", &nativePtr)) { + IMAGE_LOGE("%{pubilc}s Get messageParcel nativePtr failed.", __func__); + return false; + } + return true; +} + +void PictureImpl::Marshalling(uintptr_t sequence) +{ +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + ani_long nativePtr; + if (!UnwarpMessageParcel(sequence, nativePtr)) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Marshalling picture unwrap failed."); + return; + } + OHOS::MessageParcel* messageParcel = reinterpret_cast(nativePtr); + if (messageParcel == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IPC, "Marshalling picture to parcel failed."); + return; + } + bool st = nativePicture_->Marshalling(*messageParcel); + if (!st) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IPC, "Marshalling picture to parcel failed."); + } +#endif +} + +void PictureImpl::Release() +{ + if (!isRelease) { + if (nativePicture_ != nullptr) { + nativePicture_ = nullptr; + } + isRelease = true; + } +} + +Picture CreatePictureByPixelMap(weak::PixelMap mainPixelmap) +{ + IMAGE_LOGI("CreatePicture IN"); + PixelMapImpl* pixelMapImpl = reinterpret_cast(mainPixelmap->GetImplPtr()); + if (pixelMapImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Pixelmap instance is nullptr!"); + return make_holder(); + } + auto nativePixelMap = pixelMapImpl->GetNativePtr(); + if (nativePixelMap == nullptr) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Get native pixelmap failed!"); + return make_holder(); + } + auto picture = OHOS::Media::Picture::Create(nativePixelMap); + if (picture == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERROR, "Create picture failed!"); + return make_holder(); + } + IMAGE_LOGI("CreatePicture OUT"); + return make_holder(std::move(picture)); +} + +Picture CreatePictureFromParcel(uintptr_t sequence) +{ + IMAGE_LOGD("Call CreatePictureFromParcel"); + + ani_long nativePtr; + if (!UnwarpMessageParcel(sequence, nativePtr)) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Fail to unwrap messageSequence"); + return make_holder(); + } + OHOS::MessageParcel* messageParcel = reinterpret_cast(nativePtr); + if (messageParcel == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IPC, "Get parcel failed"); + return make_holder(); + } + + OHOS::Media::PICTURE_ERR error; + auto picture = OHOS::Media::Picture::Unmarshalling(*messageParcel, error); + if (picture == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IPC, "Unmarshalling picture failed"); + return make_holder(); + } + std::shared_ptr picturePtr(picture); + return make_holder(std::move(picturePtr)); +} + +Picture CreatePictureByPtr(int64_t aniPtr) +{ + return make_holder(aniPtr); +} + +} // namespace ANI::Image + +TH_EXPORT_CPP_API_CreatePictureByPixelMap(CreatePictureByPixelMap); +TH_EXPORT_CPP_API_CreatePictureFromParcel(CreatePictureFromParcel); +TH_EXPORT_CPP_API_CreatePictureByPtr(CreatePictureByPtr); \ No newline at end of file diff --git a/frameworks/kits/taihe/src/picture_taihe_ani.cpp b/frameworks/kits/taihe/src/picture_taihe_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6bc9b95c1d738df3994c8468bb49bee9b1a1da47 --- /dev/null +++ b/frameworks/kits/taihe/src/picture_taihe_ani.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "image_log.h" +#include "picture_taihe_ani.h" + +// This file is for legacy ANI backward compatibility + +namespace OHOS { +namespace Media { +ani_object PictureTaiheAni::CreateEtsPicture(ani_env *env, std::shared_ptr picture) +{ + std::unique_ptr pictureAni = std::make_unique(); + pictureAni->nativePicture_ = picture; + + ani_namespace imageNamespace; + if (env->FindNamespace("L@ohos/multimedia/image/image;", &imageNamespace) != ANI_OK) { + IMAGE_LOGE("%{public}s FindNamespace failed", __func__); + return nullptr; + } + + ani_function createFunc; + if (env->Namespace_FindFunction(imageNamespace, "createPictureByPtr", nullptr, &createFunc) != ANI_OK) { + IMAGE_LOGE("%{public}s Namespace_FindFunction failed", __func__); + return nullptr; + } + + ani_ref pictureObj; + if (env->Function_Call_Ref(createFunc, &pictureObj, reinterpret_cast(pictureAni.get())) != ANI_OK) { + IMAGE_LOGE("%{public}s Function_Call_Ref failed", __func__); + return nullptr; + } + + pictureAni.release(); + return reinterpret_cast(pictureObj); +} +} // namespace Media +} // namespace OHOS \ No newline at end of file diff --git a/frameworks/kits/taihe/src/pixel_map_taihe.cpp b/frameworks/kits/taihe/src/pixel_map_taihe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..203fd74ebf9e78770bacbb4963eac262f6b9bccb --- /dev/null +++ b/frameworks/kits/taihe/src/pixel_map_taihe.cpp @@ -0,0 +1,743 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pixel_map_taihe.h" + +#include "ani_color_space_object_convertor.h" +#include "image_format_convert.h" +#include "image_log.h" +#include "image_taihe_utils.h" +#include "image_utils.h" +#include "media_errors.h" +#include "pixel_map_taihe_ani.h" +#include "taihe/runtime.hpp" +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) +#include +#include "pixel_map_from_surface.h" +#include "transaction/rs_interfaces.h" +#endif + +namespace ANI::Image { + +enum class FormatType : int8_t { + UNKNOWN, + YUV, + RGB, + ASTC +}; + +Size MakeEmptySize() +{ + return {0, 0}; +} + +ImageInfo MakeEmptyImageInfo() +{ + return {MakeEmptySize(), 0, 0, PixelMapFormat(PixelMapFormat::key_t::UNKNOWN), + AlphaType(AlphaType::key_t::UNKNOWN), "", false}; +} + +PixelMap CreatePixelMapByBufferAndOptionsSync(array_view colors, InitializationOptions const& options) +{ + return make_holder(colors, options); +} + +PixelMap CreatePixelMapByOptionsSync(InitializationOptions const& options) +{ + return make_holder(options); +} + +PixelMap CreatePixelMapByPtr(int64_t ptr) +{ + return make_holder(ptr); +} + +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) +static bool GetSurfaceSize(std::string const& surfaceId, Media::Rect& region) +{ + if (region.width <= 0 || region.height <= 0) { + sptr surface = SurfaceUtils::GetInstance()->GetSurface(std::stoull(surfaceId)); + if (surface == nullptr) { + IMAGE_LOGE("[PixelMap ANI] GetSurfaceSize: GetSurface failed"); + return false; + } + sptr fence = SyncFence::InvalidFence(); + // 4 * 4 idetity matrix + float matrix[16] = { + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + }; + sptr surfaceBuffer = nullptr; + GSError ret = surface->GetLastFlushedBuffer(surfaceBuffer, fence, matrix); + if (ret != GSERROR_OK || surfaceBuffer == nullptr) { + IMAGE_LOGE("[PixelMap ANI] GetSurfaceSize: GetLastFlushedBuffer fail, ret = %{public}d", ret); + return false; + } + region.width = surfaceBuffer->GetWidth(); + region.height = surfaceBuffer->GetHeight(); + } + return true; +} + +static PixelMap CreatePixelMapFromSurface(std::string const& surfaceId, Media::Rect& region) +{ + if (!std::regex_match(surfaceId, std::regex("\\d+"))) { + ImageTaiheUtils::ThrowExceptionError(Media::COMMON_ERR_INVALID_PARAMETER, "Empty or invalid surfaceId"); + return make_holder(); + } + if (!GetSurfaceSize(surfaceId, region)) { + ImageTaiheUtils::ThrowExceptionError(Media::COMMON_ERR_INVALID_PARAMETER, "Get surface size failed"); + return make_holder(); + } + + auto &rsClient = Rosen::RSInterfaces::GetInstance(); + OHOS::Rect r = { + .x = region.left, + .y = region.top, + .w = region.width, + .h = region.height, + }; + std::shared_ptr pixelMap = rsClient.CreatePixelMapFromSurfaceId(std::stoull(surfaceId), r); +#ifndef EXT_PIXEL + if (pixelMap == nullptr) { + pixelMap = CreatePixelMapFromSurfaceId(std::stoull(surfaceId), region); + } +#endif + return make_holder(std::move(pixelMap)); +} +#endif + +PixelMap CreatePixelMapFromSurfaceByIdSync(string_view etsSurfaceId) +{ +#if defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM) + return make_holder(); +#else + std::string surfaceId(etsSurfaceId); + Media::Rect region; + IMAGE_LOGD("[PixelMap ANI] createPixelMapFromSurfaceByIdSync: id=%{public}s", surfaceId.c_str()); + return CreatePixelMapFromSurface(surfaceId, region); +#endif +} + +PixelMap CreatePixelMapFromSurfaceByIdAndRegionSync(string_view etsSurfaceId, + ohos::multimedia::image::image::Region const& etsRegion) +{ +#if defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM) + return make_holder(); +#else + std::string surfaceId(etsSurfaceId); + Media::Rect region = {etsRegion.x, etsRegion.y, etsRegion.size.width, etsRegion.size.height}; + IMAGE_LOGD("[PixelMap ANI] createPixelMapFromSurfaceByIdAndRegionSync: id=%{public}s, area=%{public}d,%{public}d," + "%{public}d,%{public}d", surfaceId.c_str(), region.left, region.top, region.width, region.height); + if (region.width <= 0 || region.height <= 0) { + ImageTaiheUtils::ThrowExceptionError(Media::COMMON_ERR_INVALID_PARAMETER, "Invalid region"); + return make_holder(); + } + return CreatePixelMapFromSurface(surfaceId, region); +#endif +} + +PixelMapImpl::PixelMapImpl() {} + +PixelMapImpl::PixelMapImpl(array_view const& colors, InitializationOptions const& etsOptions) +{ + Media::InitializationOptions options; + ParseInitializationOptions(etsOptions, options); + if (!Is10BitFormat(options.pixelFormat)) { + nativePixelMap_ = Media::PixelMap::Create(reinterpret_cast(colors.data()), + colors.size() / sizeof(uint32_t), options); + } + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::COMMON_ERR_INVALID_PARAMETER, + "Create PixelMap by buffer and options failed"); + } +} + +PixelMapImpl::PixelMapImpl(InitializationOptions const& etsOptions) +{ + Media::InitializationOptions options; + ParseInitializationOptions(etsOptions, options); + if (Is10BitFormat(options.pixelFormat)) { + options.useDMA = true; + } + nativePixelMap_ = Media::PixelMap::Create(options); + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::COMMON_ERR_INVALID_PARAMETER, "Create PixelMap by options failed"); + } +} + +PixelMapImpl::PixelMapImpl(std::shared_ptr pixelMap) +{ + nativePixelMap_ = pixelMap; + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::COMMON_ERR_INVALID_PARAMETER, "Create PixelMap failed"); + } +} + +PixelMapImpl::PixelMapImpl(int64_t aniPtr) +{ + Media::PixelMapTaiheAni* pixelMapAni = reinterpret_cast(aniPtr); + nativePixelMap_ = pixelMapAni->nativePixelMap_; + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::COMMON_ERR_INVALID_PARAMETER, "Create PixelMap failed"); + } +} + +PixelMapImpl::~PixelMapImpl() +{ + Release(); +} + +int64_t PixelMapImpl::GetImplPtr() +{ + return reinterpret_cast(this); +} + +std::shared_ptr PixelMapImpl::GetNativePtr() +{ + return nativePixelMap_; +} + +std::shared_ptr PixelMapImpl::GetPixelMap(PixelMap etsPixelMap) +{ + PixelMapImpl *pixelMapImpl = reinterpret_cast(etsPixelMap->GetImplPtr()); + if (pixelMapImpl == nullptr) { + IMAGE_LOGE("[%{public}s] etsPixelMap is nullptr", __func__); + return nullptr; + } + return pixelMapImpl->GetNativePtr(); +} + +PixelMap PixelMapImpl::CreatePixelMap(std::shared_ptr pixelMap) +{ + return make_holder(pixelMap); +} + +ImageInfo PixelMapImpl::GetImageInfoSync() +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return MakeEmptyImageInfo(); + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return MakeEmptyImageInfo(); + } + + Media::ImageInfo imageInfo; + nativePixelMap_->GetImageInfo(imageInfo); + ImageInfo result = ImageTaiheUtils::ToTaiheImageInfo(imageInfo, nativePixelMap_->IsHdr()); + result.density = imageInfo.baseDensity; + result.stride = nativePixelMap_->GetRowStride(); + return result; +} + +void PixelMapImpl::ReadPixelsToBufferSync(array_view dst) +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + uint32_t status = nativePixelMap_->ReadPixels(dst.size(), dst.data()); + if (status != Media::SUCCESS) { + IMAGE_LOGE("[PixelMap ANI] ReadPixels failed"); + } +} + +void PixelMapImpl::ReadPixelsSync(weak::PositionArea area) +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + ohos::multimedia::image::image::Region etsRegion = area->GetRegion(); + Media::Rect region = {etsRegion.x, etsRegion.y, etsRegion.size.width, etsRegion.size.height}; + array etsPixels = area->GetPixels(); + uint32_t status = nativePixelMap_->ReadPixels(etsPixels.size(), area->GetOffset(), area->GetStride(), region, + etsPixels.data()); + if (status == Media::SUCCESS) { + area->SetPixels(etsPixels); + } else { + IMAGE_LOGE("[PixelMap ANI] ReadPixels by region failed"); + } +} + +void PixelMapImpl::WriteBufferToPixelsSync(array_view src) +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + uint32_t status = nativePixelMap_->WritePixels(src.data(), src.size()); + if (status != Media::SUCCESS) { + IMAGE_LOGE("[PixelMap ANI] WritePixels failed"); + } +} + +PixelMap PixelMapImpl::CreateAlphaPixelmapSync() +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return make_holder(); + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return make_holder(); + } + + Media::InitializationOptions options; + options.pixelFormat = Media::PixelFormat::ALPHA_8; + auto alphaPixelMap = Media::PixelMap::Create(*nativePixelMap_, options); + return make_holder(std::move(alphaPixelMap)); +} + +int32_t PixelMapImpl::GetBytesNumberPerRow() +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return 0; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return 0; + } + + return nativePixelMap_->GetRowBytes(); +} + +int32_t PixelMapImpl::GetPixelBytesNumber() +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return 0; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return 0; + } + + return nativePixelMap_->GetByteCount(); +} + +int32_t PixelMapImpl::GetDensity() +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return 0; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return 0; + } + + return nativePixelMap_->GetBaseDensity(); +} + +void PixelMapImpl::ScaleSync(float x, float y) +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + nativePixelMap_->scale(x, y); +} + +void PixelMapImpl::ScaleWithAntiAliasingSync(float x, float y, AntiAliasingLevel level) +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + nativePixelMap_->scale(x, y, Media::AntiAliasingOption(level.get_value())); +} + +void PixelMapImpl::CropSync(ohos::multimedia::image::image::Region const& region) +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + Media::Rect rect = {region.x, region.y, region.size.width, region.size.height}; + uint32_t status = nativePixelMap_->crop(rect); + if (status != Media::SUCCESS) { + IMAGE_LOGE("[PixelMap ANI] crop failed"); + } +} + +void PixelMapImpl::RotateSync(float angle) +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + nativePixelMap_->rotate(angle); +} + +void PixelMapImpl::FlipSync(bool horizontal, bool vertical) +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + nativePixelMap_->flip(horizontal, vertical); +} + +void PixelMapImpl::OpacitySync(float rate) +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + uint32_t status = nativePixelMap_->SetAlpha(rate); + if (status != Media::SUCCESS) { + IMAGE_LOGE("[PixelMap ANI] SetAlpha failed"); + } +} + +void PixelMapImpl::SetMemoryNameSync(string_view name) +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + uint32_t status = nativePixelMap_->SetMemoryName(std::string(name)); + if (status == Media::ERR_MEMORY_NOT_SUPPORT) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_MEMORY_NOT_SUPPORT, "Set memory name not supported"); + } else if (status == Media::COMMON_ERR_INVALID_PARAMETER) { + ImageTaiheUtils::ThrowExceptionError(Media::COMMON_ERR_INVALID_PARAMETER, "Memory name size out of range"); + } +} + +static FormatType FormatTypeOf(Media::PixelFormat pixelForamt) +{ + switch (pixelForamt) { + case Media::PixelFormat::ARGB_8888: + case Media::PixelFormat::RGB_565: + case Media::PixelFormat::RGBA_8888: + case Media::PixelFormat::BGRA_8888: + case Media::PixelFormat::RGB_888: + case Media::PixelFormat::RGBA_F16: + case Media::PixelFormat::RGBA_1010102: + return FormatType::RGB; + case Media::PixelFormat::NV21: + case Media::PixelFormat::NV12: + case Media::PixelFormat::YCBCR_P010: + case Media::PixelFormat::YCRCB_P010: + return FormatType::YUV; + case Media::PixelFormat::ASTC_4x4: + return FormatType::ASTC; + default: + return FormatType::UNKNOWN; + } +} + +void PixelMapImpl::ConvertPixelFormatSync(PixelMapFormat targetPixelFormat) +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + + Media::PixelFormat srcFormat = nativePixelMap_->GetPixelFormat(); + Media::PixelFormat dstFormat = Media::PixelFormat(targetPixelFormat.get_value()); + if (FormatTypeOf(srcFormat) == FormatType::UNKNOWN || FormatTypeOf(dstFormat) == FormatType::UNKNOWN) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_IMAGE_INVALID_PARAMETER, + "Source or target pixel format is not supported or invalid"); + return; + } + + uint32_t status = Media::ImageFormatConvert::ConvertImageFormat(nativePixelMap_, dstFormat); + if (status == Media::SUCCESS) { + Media::ImageUtils::FlushSurfaceBuffer(nativePixelMap_.get()); + } else if (status == Media::ERR_IMAGE_INVALID_PARAMETER) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_IMAGE_INVALID_PARAMETER, "Invalid parameter"); + } else if (status == Media::ERR_IMAGE_SOURCE_DATA_INCOMPLETE) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_IMAGE_SOURCE_DATA_INCOMPLETE, + "Image source data is incomplete"); + } else if (status == Media::IMAGE_RESULT_CREATE_FORMAT_CONVERT_FAILED) { + ImageTaiheUtils::ThrowExceptionError(Media::IMAGE_RESULT_CREATE_FORMAT_CONVERT_FAILED, "Conversion failed"); + } else if (status == Media::ERR_MEDIA_FORMAT_UNSUPPORT) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_MEDIA_FORMAT_UNSUPPORT, + "The target pixel format to be converted is not supported"); + } else if (status == Media::ERR_IMAGE_PIXELMAP_CREATE_FAILED) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_IMAGE_PIXELMAP_CREATE_FAILED, "Failed to create PixelMap"); + } +} + +uintptr_t PixelMapImpl::GetColorSpace() +{ +#ifdef IMAGE_COLORSPACE_FLAG + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_IMAGE_DATA_ABNORMAL, "Invalid native PixelMap"); + return 0; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return 0; + } + + auto grColorSpace = nativePixelMap_->InnerGetGrColorSpacePtr(); + if (grColorSpace == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_IMAGE_DATA_UNSUPPORT, "No color space in PixelMap"); + return 0; + } + return reinterpret_cast(ColorManager::CreateAniColorSpaceObject(get_env(), grColorSpace)); +#else + ImageTaiheUtils::ThrowExceptionError(Media::ERR_INVALID_OPERATION, "Unsupported operation"); + return 0; +#endif +} + +void PixelMapImpl::SetColorSpace(uintptr_t colorSpace) +{ +#ifdef IMAGE_COLORSPACE_FLAG + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + auto grColorSpace = ColorManager::GetColorSpaceByAniObject(get_env(), reinterpret_cast(colorSpace)); + if (grColorSpace == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_IMAGE_INVALID_PARAMETER, "Color space mismatch"); + return; + } + nativePixelMap_->InnerSetColorSpace(*grColorSpace); +#else + ImageTaiheUtils::ThrowExceptionError(Media::ERR_INVALID_OPERATION, "Unsupported operation"); +#endif +} + +void PixelMapImpl::ToSdrSync() +{ + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_MEDIA_INVALID_OPERATION, "Internal error."); + return; + } + + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_MEDIA_INVALID_OPERATION, "Pixelmap is not editable"); + return; + } + + uint32_t status = nativePixelMap_->ToSdr(); + if (status != Media::SUCCESS) { + if (status == Media::ERR_MEDIA_INVALID_OPERATION) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_MEDIA_INVALID_OPERATION, "The pixelmap is not hdr."); + } else if (status == Media::IMAGE_RESULT_GET_SURFAC_FAILED) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_MEDIA_INVALID_OPERATION, "Alloc new memory failed."); + } else if (status == Media::ERR_RESOURCE_UNAVAILABLE) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_MEDIA_INVALID_OPERATION, "Pixelmap is not editable"); + } else { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_MEDIA_INVALID_OPERATION, "Internal error."); + } + } +} + +static uint32_t ParseColorSpace(std::shared_ptr &colorSpace, + uintptr_t targetColorSpace) +{ +#ifdef IMAGE_COLORSPACE_FLAG + ani_object obj = reinterpret_cast(targetColorSpace); + colorSpace = OHOS::ColorManager::GetColorSpaceByAniObject(get_env(), obj); + if (colorSpace == nullptr) { + return Media::ERR_IMAGE_INVALID_PARAMETER; + } + return Media::SUCCESS; +#else + return Media::ERR_IMAGE_DATA_UNSUPPORT; +#endif +} + +void PixelMapImpl::ApplyColorSpaceSync(uintptr_t targetColorSpace) +{ + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_IMAGE_INIT_ABNORMAL, "Internal error."); + return; + } + + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Pixelmap is not editable"); + return; + } + std::shared_ptr colorSpace; + uint32_t status = ParseColorSpace(colorSpace, targetColorSpace); + if (status != Media::SUCCESS) { + ImageTaiheUtils::ThrowExceptionError(status, "ParseColorSpace failed"); + return; + } + + if (colorSpace == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_IMAGE_INIT_ABNORMAL, "ApplyColorSpace Null native ref"); + return; + } + status = nativePixelMap_->ApplyColorSpace(*colorSpace); + if (status != Media::SUCCESS) { + ImageTaiheUtils::ThrowExceptionError(status, "ApplyColorSpace has failed!"); + return; + } +} + +void PixelMapImpl::ReleaseSync() +{ + if (nativePixelMap_ != nullptr) { + if (!nativePixelMap_->IsModifiable()) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Unable to release the PixelMap " + "because it's locked or unmodifiable"); + } else { + IMAGE_LOGD("[PixelMap ANI] Releasing PixelMap with ID: %{public}d", nativePixelMap_->GetUniqueId()); + nativePixelMap_.reset(); + } + } +} + +bool PixelMapImpl::GetIsEditable() +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return false; + } + + return nativePixelMap_->IsEditable(); +} + +bool PixelMapImpl::GetIsStrideAlignment() +{ + if (nativePixelMap_ == nullptr) { + IMAGE_LOGE("[%{public}s] Native PixelMap is nullptr", __func__); + return false; + } + + return nativePixelMap_->IsStrideAlignment(); +} + +void PixelMapImpl::SetCaptureId(int32_t captureId) +{ + captureId_ = captureId; +} + +int32_t PixelMapImpl::GetCaptureId() +{ + return captureId_; +} + +void PixelMapImpl::SetTimestamp(int64_t timestamp) +{ + timestamp_ = timestamp; +} + +int64_t PixelMapImpl::GetTimestamp() +{ + return timestamp_; +} + +bool PixelMapImpl::Is10BitFormat(Media::PixelFormat format) +{ + return format == Media::PixelFormat::RGBA_1010102 || format == Media::PixelFormat::YCBCR_P010 || + format == Media::PixelFormat::YCRCB_P010; +} + +void PixelMapImpl::ParseInitializationOptions(InitializationOptions const& etsOptions, + Media::InitializationOptions &options) +{ + options.size = {etsOptions.size.width, etsOptions.size.height}; + if (etsOptions.srcPixelFormat) { + options.srcPixelFormat = Media::PixelFormat(etsOptions.srcPixelFormat->get_value()); + } + if (etsOptions.pixelFormat) { + options.pixelFormat = Media::PixelFormat(etsOptions.pixelFormat->get_value()); + } + if (etsOptions.editable) { + options.editable = *etsOptions.editable; + } + if (etsOptions.alphaType) { + options.alphaType = Media::AlphaType(etsOptions.alphaType->get_value()); + } + if (etsOptions.scaleMode) { + options.scaleMode = Media::ScaleMode(etsOptions.scaleMode->get_value()); + } +} + +void PixelMapImpl::Release() +{ + if (nativePixelMap_ != nullptr) { + nativePixelMap_.reset(); + } +} + +} // namespace ANI::Image + +TH_EXPORT_CPP_API_MakeEmptySize(ANI::Image::MakeEmptySize); +TH_EXPORT_CPP_API_MakeEmptyImageInfo(ANI::Image::MakeEmptyImageInfo); +TH_EXPORT_CPP_API_CreatePixelMapByBufferAndOptionsSync(ANI::Image::CreatePixelMapByBufferAndOptionsSync); +TH_EXPORT_CPP_API_CreatePixelMapByOptionsSync(ANI::Image::CreatePixelMapByOptionsSync); +TH_EXPORT_CPP_API_CreatePixelMapByPtr(ANI::Image::CreatePixelMapByPtr); +TH_EXPORT_CPP_API_CreatePixelMapFromSurfaceByIdSync(ANI::Image::CreatePixelMapFromSurfaceByIdSync); +TH_EXPORT_CPP_API_CreatePixelMapFromSurfaceByIdAndRegionSync(ANI::Image::CreatePixelMapFromSurfaceByIdAndRegionSync); \ No newline at end of file diff --git a/frameworks/kits/taihe/src/pixel_map_taihe_ani.cpp b/frameworks/kits/taihe/src/pixel_map_taihe_ani.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1b49217ff844217a50bac6513daa0846eaae1201 --- /dev/null +++ b/frameworks/kits/taihe/src/pixel_map_taihe_ani.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pixel_map_taihe_ani.h" + +#include +#include "pixel_map_taihe.h" + +// This file is for legacy ANI backward compatibility + +namespace OHOS { +namespace Media { +using namespace ANI::Image; +using namespace arkts; + +ani_object PixelMapTaiheAni::CreateEtsPixelMap([[maybe_unused]] ani_env* env, std::shared_ptr pixelMap) +{ + std::unique_ptr pixelMapAni = std::make_unique(); + pixelMapAni->nativePixelMap_ = pixelMap; + + ani_signature::Namespace ns = ani_signature::Builder::BuildNamespace("@ohos.multimedia.image.image"); + ani_namespace imageNamespace; + if (env->FindNamespace(ns.Descriptor().c_str(), &imageNamespace) != ANI_OK) { + return nullptr; + } + ani_function createFunc; + if (env->Namespace_FindFunction(imageNamespace, "createPixelMapByPtr", nullptr, &createFunc) != ANI_OK) { + return nullptr; + } + ani_ref pixelMapObj; + if (env->Function_Call_Ref(createFunc, &pixelMapObj, reinterpret_cast(pixelMapAni.get())) == ANI_OK) { + pixelMapAni.release(); + } else { + return nullptr; + } + + return reinterpret_cast(pixelMapObj); +} + +std::shared_ptr PixelMapTaiheAni::GetNativePixelMap([[maybe_unused]] ani_env* env, ani_object obj) +{ + ani_signature::Type cls = ani_signature::Builder::BuildClass("@ohos.multimedia.image.image.PixelMap"); + ani_class pixelMapCls; + if (env->FindClass(cls.Descriptor().c_str(), &pixelMapCls) != ANI_OK) { + return nullptr; + } + ani_signature::SignatureBuilder sb{}; + ani_method getMethod; + sb.SetReturnLong(); + if (env->Class_FindMethod(pixelMapCls, "getImplPtr", sb.BuildSignatureDescriptor().c_str(), &getMethod) != ANI_OK) { + return nullptr; + } + ani_long implPtr; + if (env->Object_CallMethod_Long(obj, getMethod, &implPtr) != ANI_OK) { + return nullptr; + } + + PixelMapImpl* pixelMapImpl = reinterpret_cast(implPtr); + if (pixelMapImpl == nullptr) { + return nullptr; + } + return pixelMapImpl->GetNativePtr(); +} + +} // namespace Media +} // namespace OHOS \ No newline at end of file