diff --git a/bundle.json b/bundle.json index 7e98c3b70d0c7f61f082eb89eed62499ee1fff3d..1baecd0cb4dbcdfc0b7c3a6b51ddf1f75184170c 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,21 @@ }, "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_taihe.h", + "picture_taihe.h", + "pixel_map_taihe_ani.h", + "pixel_map_taihe.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/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..e7670b5ac533b3d6f3e1fa1b0dfca61ce097edc2 --- /dev/null +++ b/frameworks/kits/taihe/BUILD.gn @@ -0,0 +1,159 @@ +# 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 += [ + "${image_subsystem}/frameworks/innerkitsimpl/accessor/src/exif_metadata_formatter.cpp", + "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/picture_taihe.cpp", + "src/pixel_map_taihe.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:EGL", + "graphic_2d:ani_color_space_object_convertor", + "graphic_2d:color_manager", + "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/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" ] +} 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..d6fab062bf7604296420db02b9304b7675a3682e --- /dev/null +++ b/frameworks/kits/taihe/idl/ohos.multimedia.image.image.taihe @@ -0,0 +1,707 @@ +/* + * 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 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; +} + +enum AuxiliaryPictureType: i32 { + GAINMAP = 1, + DEPTH_MAP = 2, + UNREFOCUS_MAP = 3, + LINEAR_MAP = 4, + FRAGMENT_MAP = 5, +} + +struct AuxiliaryPictureInfo { + auxiliaryPictureType: AuxiliaryPictureType; + size: Size; + rowStride: i32; + pixelFormat: PixelMapFormat; + colorSpace: @sts_type("colorSpaceManager.ColorSpaceManager") Opaque; +} + +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; + + ReadPixelsSync(area: PositionArea): void; + + WriteBufferToPixelsSync(src: @arraybuffer Array): void; + + @gen_async("createAlphaPixelmap") + @gen_promise("createAlphaPixelmap") + CreateAlphaPixelmapSync(): PixelMap; + + GetBytesNumberPerRow(): i32; + + GetPixelBytesNumber(): i32; + + @gen_async("scale") + @gen_promise("scale") + @overload("scaleSync") + ScaleSync(x: f64, y: f64): void; + + @gen_promise("scale") + @overload("scaleSync") + ScaleWithAntiAliasingSync(x: f64, y: f64, level: AntiAliasingLevel): void; + + @gen_async("crop") + @gen_promise("crop") + CropSync(region: Region): void; + + @gen_async("rotate") + @gen_promise("rotate") + RotateSync(angle: f64): void; + + @gen_async("flip") + @gen_promise("flip") + FlipSync(horizontal: bool, vertical: bool): void; + + @gen_async("opacity") + @gen_promise("opacity") + OpacitySync(rate: f64): void; + + SetMemoryNameSync(name: String): void; + + @gen_async("release") + @gen_promise("release") + ReleaseSync(): void; + + @get GetIsStrideAlignment(): bool; + + @set SetCaptureId(captureId: i32): void; + @get GetCaptureId(): i32; + + @set SetTimestamp(timestamp: i64): void; + @get GetTimestamp(): i64; +} + +interface Picture { + GetImplPtr(): i64; + + GetMainPixelmap(): PixelMap; + + Marshalling(sequence: @sts_type("rpc.MessageSequence") Opaque): void; + + Release(): void; +} + +interface AuxiliaryPicture { + @gen_promise("readPixelsToBuffer") + ReadPixelsToBufferSync(): @arraybuffer Array; + + GetAuxiliaryPictureInfo(): AuxiliaryPictureInfo; + + SetAuxiliaryPictureInfo(info: AuxiliaryPictureInfo): void; + + Release(): void; +} + +interface ImageSource { + GetImplPtr(): i64; + @gen_async("getImageInfo") + @gen_promise("getImageInfoPromiseWithIndex") + GetImageInfoSyncWithIndex(index: u32): 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("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("release") + @gen_promise("release") + ReleaseSync(): void; + + @get GetSupportedFormats(): Array; +} + +interface ImagePacker { + @gen_async("packing") + @gen_promise("packing") + PackingPixelMapSync(source: PixelMap, option: PackingOption): @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("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("size") GetSize(): Size; + @get("format") GetFormat(): i32; + + @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; + + @!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("release") + @gen_promise("release") + ReleaseSync(): void; +} + +function MakeEmptySize(): Size; +function MakeEmptyImageInfo(): ImageInfo; + +@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("createImageSource") +function CreateImageSourceByRawFileDescriptorOption(rawfile: @sts_type("resourceManager.RawFileDescriptor") Opaque, options: Optional): ImageSource; + +function CreateImagePacker(): ImagePacker; + +@overload("createImageCreator") +function CreateImageCreator(width: i32, height: i32, format: i32, capacity: i32): ImageCreator; + +@overload("createImageCreator") +function CreateImageCreatorBySize(size: Size, format: ImageFormat, capacity: i32): ImageCreator; + +@overload("createImageReceiver") +function CreateImageReceiver(width: i32, height: i32, format: i32, capacity: i32): ImageReceiver; + +@overload("createImageReceiver") +function CreateImageReceiverBySize(size: Size, format: ImageFormat, capacity: i32): ImageReceiver; + +@overload("createPicture") +function CreatePictureByPixelMap(mainPixelmap : PixelMap): 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..51d1a9dbd508faf76715d10552be927829e4d2a3 --- /dev/null +++ b/frameworks/kits/taihe/include/auxiliary_picture_taihe.h @@ -0,0 +1,44 @@ +/* + * 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(); + + array ReadPixelsToBufferSync(); + 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..45413093d5293ab0a44be6faa643d7aa2fb7ace6 --- /dev/null +++ b/frameworks/kits/taihe/include/image_creator_taihe.h @@ -0,0 +1,45 @@ +/* + * 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 "image_creator.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 ImageCreatorImpl { +public: + ImageCreatorImpl(); + explicit ImageCreatorImpl(std::shared_ptr imageCreator); + ~ImageCreatorImpl(); + + int32_t GetCapacity(); + ImageFormat GetFormat(); + + void ReleaseSync(); + +private: + std::shared_ptr imageCreator_; + bool isRelease = false; +}; +} // 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..0c4881332ada78b1f3c55ab96623058e8b95d821 --- /dev/null +++ b/frameworks/kits/taihe/include/image_packer_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_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(); + + void PackImageSourceToFileSync(weak::ImageSource source, int32_t fd, PackingOption const& options); + void PackPixelMapToFileSync(weak::PixelMap source, int32_t fd, PackingOption const& options); + void PackPictureToFileSync(weak::Picture picture, int32_t fd, PackingOption const& options); + + array PackingPixelMapSync(weak::PixelMap source, PackingOption const& option); + array PackingPictureSync(weak::Picture picture, PackingOption 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..c2df2147dbf19337286b80043ff2d346522d40dd --- /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(); + 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 { + ani_env *env = nullptr; + 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..42ee6c9aa88e33702d906c7097e20258acc49b16 --- /dev/null +++ b/frameworks/kits/taihe/include/image_source_taihe.h @@ -0,0 +1,70 @@ +/* + * 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(); + int64_t GetImplPtr(); + + ImageInfo GetImageInfoSyncWithIndex(uint32_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(); + 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 ReleaseSync(); + + 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_taihe.h b/frameworks/kits/taihe/include/image_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..432edc1831ea16141f4bc426a7c01faadd821931 --- /dev/null +++ b/frameworks/kits/taihe/include/image_taihe.h @@ -0,0 +1,49 @@ +/* + * 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(); + + static struct Image Create(std::shared_ptr nativeImage); + void ReleaseSync(); + + Size GetSize(); + int32_t GetFormat(); + +private: + static OHOS::Media::ImageHolderManager sNativeImageHolder_; + std::shared_ptr nativeImage_; + bool isTestImage_ = false; + bool isRelease = false; +}; +} // 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..ceb46cac9a45babbf5b024a24e19422d24bee4cb --- /dev/null +++ b/frameworks/kits/taihe/include/image_taihe_utils.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_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); +}; +} // 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/picture_taihe.h b/frameworks/kits/taihe/include/picture_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..9a995224494f415f6afcbc17bb21dc390ffa018b --- /dev/null +++ b/frameworks/kits/taihe/include/picture_taihe.h @@ -0,0 +1,46 @@ +/* + * 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 GetImplPtr(); + std::shared_ptr GetNativePtr(); + + PixelMap GetMainPixelmap(); + 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/pixel_map_taihe.h b/frameworks/kits/taihe/include/pixel_map_taihe.h new file mode 100644 index 0000000000000000000000000000000000000000..604e0cf6ba2b23cd43d02997ccee087c2483e627 --- /dev/null +++ b/frameworks/kits/taihe/include/pixel_map_taihe.h @@ -0,0 +1,76 @@ +/* + * 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(); + void ScaleSync(double x, double y); + void ScaleWithAntiAliasingSync(double x, double y, AntiAliasingLevel level); + void CropSync(ohos::multimedia::image::image::Region const& region); + void RotateSync(double angle); + void FlipSync(bool horizontal, bool vertical); + void OpacitySync(double rate); + void SetMemoryNameSync(string_view name); + void ReleaseSync(); + 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..22a7b2d4133e00bb033977a47de6f8f76875bc47 --- /dev/null +++ b/frameworks/kits/taihe/src/auxiliary_picture_taihe.cpp @@ -0,0 +1,281 @@ +/* + * 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 "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 AuxColorSpace = nullptr; +}; + +AuxiliaryPictureImpl::AuxiliaryPictureImpl() {} + +AuxiliaryPictureImpl::AuxiliaryPictureImpl(std::shared_ptr auxiliaryPicture) +{ + nativeAuxiliaryPicture_ = auxiliaryPicture; +} + +AuxiliaryPictureImpl::~AuxiliaryPictureImpl() +{ + Release(); +} + +static bool ReadPixelsToBufferSyncExecute(std::unique_ptr &context) +{ + OHOS::Media::AuxiliaryPictureInfo info = context->rAuxiliaryPicture->GetAuxiliaryPictureInfo(); + context->arrayBufferSize = + static_cast(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; +} + +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) +{ + AuxiliaryPictureType::key_t auxiliaryPictureTypeKey; + ImageTaiheUtils::GetEnumKeyByValue(static_cast(src.auxiliaryPictureType), + auxiliaryPictureTypeKey); + + Size size { + .width = src.size.width, + .height = src.size.height, + }; + + PixelMapFormat::key_t pixelFormatKey; + ImageTaiheUtils::GetEnumKeyByValue(static_cast(src.pixelFormat), pixelFormatKey); + + AuxiliaryPictureInfo result { + .auxiliaryPictureType = AuxiliaryPictureType(auxiliaryPictureTypeKey), + .size = size, + .rowStride = static_cast(src.rowStride), + .pixelFormat = PixelMapFormat(pixelFormatKey), + }; + return result; +} + +AuxiliaryPictureInfo AuxiliaryPictureImpl::GetAuxiliaryPictureInfo() +{ + if (nativeAuxiliaryPicture_ != nullptr) { + AuxiliaryPictureInfo info = ToTaiheAuxiliaryPictureInfo(nativeAuxiliaryPicture_->GetAuxiliaryPictureInfo()); + return info; + } 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..1a2e4cf6e3b716374f07fe701b7974857fc5d2f8 --- /dev/null +++ b/frameworks/kits/taihe/src/image_creator_taihe.cpp @@ -0,0 +1,148 @@ +/* + * 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; +const int ARGS4 = 4; +const int PARAM0 = 0; +const int PARAM1 = 1; +const int PARAM2 = 2; +const int PARAM3 = 3; + +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; + } +} + +static bool isTest(const int32_t* args, const int32_t len) +{ + if ((args[PARAM0] == TEST_WIDTH) && + (args[PARAM1] == TEST_HEIGHT) && + (args[PARAM2] == TEST_FORMAT) && + (args[PARAM3] == TEST_CAPACITY) && + (len == ARGS4)) { + return true; + } + return false; +} + +ImageCreator CreateImageCreatorInner(int32_t width, int32_t height, int32_t format, int32_t capacity) +{ + int32_t args[ARGS4] = {0}; + args[PARAM0] = width; + args[PARAM1] = height; + args[PARAM2] = format; + args[PARAM3] = capacity; + + int32_t len = sizeof(args) / sizeof(args[PARAM0]); + if (isTest(args, len)) { + g_isCreatorTest = true; + } + if (!g_isCreatorTest) { + auto imageCreator = OHOS::Media::ImageCreator::CreateImageCreator(args[PARAM0], + args[PARAM1], args[PARAM2], args[PARAM3]); + if (imageCreator != nullptr) { + return make_holder(imageCreator); + } + ImageTaiheUtils::ThrowExceptionError("Create image creator failed."); + } + return make_holder(); +} + +ImageCreator CreateImageCreator(int32_t width, int32_t height, int32_t format, int32_t capacity) +{ + return CreateImageCreatorInner(width, height, format, capacity); +} + +ImageCreator CreateImageCreatorBySize(Size const& size, ImageFormat format, int32_t capacity) +{ + return CreateImageCreatorInner(size.width, size.height, format.get_value(), capacity); +} +} // namespace ANI::Image + +TH_EXPORT_CPP_API_CreateImageCreator(CreateImageCreator); +TH_EXPORT_CPP_API_CreateImageCreatorBySize(CreateImageCreatorBySize); \ 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..8a37ff111490c713ba01ae412f9aea377b0eab3e --- /dev/null +++ b/frameworks/kits/taihe/src/image_packer_taihe.cpp @@ -0,0 +1,600 @@ +/* + * 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 + +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; +}; + +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 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; +} + +#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 { + ImageTaiheUtils::ThrowExceptionError(packRes, "PackedSize outside size"); + IMAGE_LOGE("Packing failed, packedSize outside size."); + if (context->packType == TYPE_PICTURE) { + ImageTaiheUtils::ThrowExceptionError(packRes == OHOS::Media::ERR_IMAGE_INVALID_PARAMETER ? + IMAGE_BAD_PARAMETER : IMAGE_ENCODE_FAILED, "PackToFile picture failed"); + } + 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 CheckPackToFileContext(std::unique_ptr &context) +{ + if (context->rImagePacker == nullptr) { + TH_THROW(std::runtime_error, "ImagePacker is nullptr"); + return false; + } + if (context->packType == TYPE_IMAGE_SOURCE) { + if (context->rImageSource == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, "ImageSource is nullptr"); + return false; + } + } else if (context->packType == TYPE_PIXEL_MAP) { + if (context->rPixelMap == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, "PixelMap is nullptr"); + return false; + } +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + } else if (context->packType == TYPE_PICTURE) { + if (context->rPicture == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, "Picture is nullptr"); + return false; + } +#endif + } else if (context->packType == TYPE_ARRAY) { + if (context->rPixelMaps == nullptr) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, "PixelMaps is nullptr"); + return false; + } + } + if (context->fd <= INVALID_FD) { + uint32_t errorCode = ((context->packType == TYPE_PICTURE || + context->packType == TYPE_ARRAY)) ? IMAGE_BAD_PARAMETER : OHOS::Media::ERR_IMAGE_INVALID_PARAMETER; + ImageTaiheUtils::ThrowExceptionError(errorCode, "Invaild fd"); + return false; + } + return true; +} + +void ImagePackerImpl::PackImageSourceToFileSync(weak::ImageSource source, int32_t fd, PackingOption const& options) +{ + OHOS::Media::ImageTrace imageTrace("ImagePackerTaihe::PackImageSourceToFile"); + + ImageSourceImpl* imageSourceImpl = reinterpret_cast(source->GetImplPtr()); + if (imageSourceImpl == nullptr) { + return; + } + std::unique_ptr taiheContext = std::make_unique(); + taiheContext->rImageSource = imageSourceImpl->nativeImgSrc; + taiheContext->packType = TYPE_IMAGE_SOURCE; + taiheContext->rImagePacker = nativeImagePacker_; + taiheContext->packOption = ParsePackOptions(options); + taiheContext->fd = fd; + if (!CheckPackToFileContext(taiheContext)) { + return; + } + + ImageTaiheUtils::HicheckerReport(); + + if (!PackToFileExec(taiheContext)) { + IMAGE_LOGE("PackToFileExec Failed"); + } +} + +void ImagePackerImpl::PackPixelMapToFileSync(weak::PixelMap source, int32_t fd, PackingOption const& options) +{ + OHOS::Media::ImageTrace imageTrace("ImagePackerTaihe::PackPixelMapToFile"); + + PixelMapImpl* pixelMapImpl = reinterpret_cast(source->GetImplPtr()); + if (pixelMapImpl == nullptr) { + return; + } + std::unique_ptr taiheContext = std::make_unique(); + taiheContext->rPixelMap = pixelMapImpl->GetNativePtr(); + taiheContext->packType = TYPE_PIXEL_MAP; + taiheContext->rImagePacker = nativeImagePacker_; + taiheContext->packOption = ParsePackOptions(options); + taiheContext->fd = fd; + if (!CheckPackToFileContext(taiheContext)) { + return; + } + + ImageTaiheUtils::HicheckerReport(); + + if (!PackToFileExec(taiheContext)) { + IMAGE_LOGE("PackToFileExec Failed"); + } +} + +void ImagePackerImpl::PackPictureToFileSync(weak::Picture picture, int32_t fd, PackingOption const& options) +{ +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + OHOS::Media::ImageTrace imageTrace("ImagePackerTaihe::PackPictureToFile"); + + PictureImpl* pictureImpl = reinterpret_cast(picture->GetImplPtr()); + if (pictureImpl == nullptr) { + return; + } + std::unique_ptr taiheContext = std::make_unique(); + taiheContext->rPicture = pictureImpl->GetNativePtr(); + taiheContext->packType = TYPE_PIXEL_MAP; + taiheContext->rImagePacker = nativeImagePacker_; + taiheContext->packOption = ParsePackOptions(options); + taiheContext->fd = fd; + if (!CheckPackToFileContext(taiheContext)) { + return; + } + + ImageTaiheUtils::HicheckerReport(); + + if (!PackToFileExec(taiheContext)) { + IMAGE_LOGE("PackToFileExec Failed"); + } +#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 CheckPackingContext(std::unique_ptr &context) +{ + if (context->rImagePacker == nullptr) { + ThrowPackingError(context, OHOS::Media::ERR_IMAGE_INVALID_PARAMETER, "native ImagePacker is nullptr"); + return false; + } + if (context->packType == TYPE_IMAGE_SOURCE) { + if (context->rImageSource == nullptr) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "ImageSource is nullptr"); + return false; + } + } else if (context->packType == TYPE_PIXEL_MAP) { + if (context->rPixelMap == nullptr) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "PixelMap is nullptr"); + return false; + } +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + } else if (context->packType == TYPE_PICTURE) { + if (context->rPicture == nullptr) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "Picture is nullptr"); + return false; + } +#endif + } else if (context->packType == TYPE_ARRAY) { + if (context->rPixelMaps == nullptr) { + ThrowPackingError(context, OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "PixelMaps is nullptr"); + return false; + } + } + return true; +} + +static array Packing(std::unique_ptr& taiheContext) +{ + ImageTaiheUtils::HicheckerReport(); + + if (!CheckPackingContext(taiheContext)) { + return array(0); + } + + if (!PackingExec(taiheContext)) { + IMAGE_LOGE("PackingExec Failed"); + return array(0); + } + return PackingComplete(taiheContext); +} + +array ImagePackerImpl::PackingPixelMapSync(weak::PixelMap source, PackingOption const& option) +{ + OHOS::Media::ImageTrace imageTrace("ImagePackerTaihe::PackingPixelMapSync"); + IMAGE_LOGI("PackingPixelMapSync IN"); + + std::unique_ptr taiheContext = std::make_unique(); + PixelMapImpl* pixelMapImpl = reinterpret_cast(source->GetImplPtr()); + if (pixelMapImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("fail to unwrap pixelMapImpl."); + return array(0); + } + taiheContext->needReturnErrorCode = false; + + taiheContext->rImagePacker = nativeImagePacker_; + taiheContext->packType = TYPE_PIXEL_MAP; + taiheContext->rPixelMap = pixelMapImpl->GetNativePtr(); + taiheContext->packOption = ParsePackOptions(option); + taiheContext->resultBufferSize = ParseBufferSize(taiheContext, option); + + return Packing(taiheContext); +} + +array ImagePackerImpl::PackingPictureSync(weak::Picture picture, PackingOption const& options) +{ +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + OHOS::Media::ImageTrace imageTrace("ImagePackerTaihe::PackingPictureSync"); + IMAGE_LOGI("PackingPictureSync IN"); + + std::unique_ptr taiheContext = std::make_unique(); + PictureImpl* pictureImpl = reinterpret_cast(picture->GetImplPtr()); + if (pictureImpl == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Unwarp pictureImpl failed."); + return array(0); + } + taiheContext->needReturnErrorCode = true; + + taiheContext->rImagePacker = nativeImagePacker_; + taiheContext->packType = TYPE_PICTURE; + taiheContext->rPicture = pictureImpl->GetNativePtr(); + taiheContext->packOption = ParsePackOptions(options); + taiheContext->resultBufferSize = ParseBufferSize(taiheContext, options); + + return Packing(taiheContext); +#else + ImageTaiheUtils::ThrowExceptionError("Invalid type!"); +#endif +} + +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..f109e443adcb3016541e3bc3c044ed9cc1503260 --- /dev/null +++ b/frameworks/kits/taihe/src/image_receiver_taihe.cpp @@ -0,0 +1,495 @@ +/* + * 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) { + return false; + } + + if (!mainHandler_) { + std::shared_ptr runner = OHOS::AppExecFwk::EventRunner::GetMainEventRunner(); + if (!runner) { + return false; + } + mainHandler_ = std::make_shared(runner); + } + + if (!mainHandler_->PostTask(cb, name, 0, OHOS::AppExecFwk::EventQueue::Priority::IMMEDIATE, {})) { + 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 ReadLatestImageSyncProcess(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); + if (::taihe::has_error()) { + IMAGE_LOGE("ImageImpl::Create failed!"); + context->status = OHOS::Media::ERR_IMAGE_INIT_ABNORMAL; + return std::monostate{}; + } + context->status = OHOS::Media::SUCCESS; + return image; + }; + + return ReadLatestImageSyncProcess(args, this); +} + +static void DoCallBack(std::shared_ptr &context) +{ + auto localContext = std::make_unique>(context); + if (context == nullptr || context->env == 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(context->env, NUM_0, "Callback is OK"); + (*cacheCallback)(reinterpret_cast(err), ImageTaiheUtils::GetUndefinedPtr(context->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->env = taihe::get_env(); + 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(int32_t width, int32_t height, int32_t format, int32_t capacity) +{ + if (!CheckFormat(format)) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::COMMON_ERR_INVALID_PARAMETER, "Invalid format"); + return make_holder(); + } + + std::shared_ptr imageReceiver = OHOS::Media::ImageReceiver::CreateImageReceiver( + width, height, format, capacity); + if (imageReceiver == nullptr) { + ImageTaiheUtils::ThrowExceptionError("Create native image receiver failed"); + return make_holder(); + } + return make_holder(imageReceiver); +} + +ImageReceiver CreateImageReceiverBySize(Size const& size, ImageFormat format, int32_t capacity) +{ + return CreateImageReceiver(size.width, size.height, format.get_value(), capacity); +} +} // namespace ANI::Image + +TH_EXPORT_CPP_API_CreateImageReceiver(CreateImageReceiver); +TH_EXPORT_CPP_API_CreateImageReceiverBySize(CreateImageReceiverBySize); \ 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..130d59584317b907068862f2a743b46672d1d10b --- /dev/null +++ b/frameworks/kits/taihe/src/image_source_taihe.cpp @@ -0,0 +1,1195 @@ +/* + * 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_taihe_utils.h" +#include "image_trace.h" +#include "image_type.h" +#include "jpeg_decoder_yuv.h" +#include "media_errors.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; + 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; +}; + +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() +{ + ReleaseSync(); +} + +int64_t ImageSourceImpl::GetImplPtr() +{ + return reinterpret_cast(this); +} + +ImageInfo ImageSourceImpl::GetImageInfoSyncWithIndex(uint32_t index) +{ + OHOS::Media::ImageInfo imageinfo; + bool isHdr = false; + if (nativeImgSrc != nullptr) { + index = index >= NUM_0 ? index : NUM_0; + nativeImgSrc->GetImageInfo(index, imageinfo); + isHdr = nativeImgSrc->IsHdrImage(); + } else { + ImageTaiheUtils::ThrowExceptionError("nativeImgSrc is nullptr"); + } + return ImageTaiheUtils::ToTaiheImageInfo(imageinfo, isHdr); +} + +ImageInfo ImageSourceImpl::GetImageInfoSync() +{ + uint32_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.desiredRegion = 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))); + } + } + 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) { + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, "thisPtr is nullptr"); + return array(nullptr, 0); + } + + if (!ParseDecodeOptions(options, taiheContext->decodeOpts, taiheContext->index, + taiheContext->errMsg)) { + IMAGE_LOGE("DecodeOptions mismatch."); + ImageTaiheUtils::ThrowExceptionError(OHOS::Media::ERR_IMAGE_DATA_ABNORMAL, "DecodeOptions mismatch."); + return array(nullptr, 0); + } + + 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); + } else { + return array(taihe::copy_data_t{}, delayTimes->data(), delayTimes->size()); + } +} + +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.begin(); it != errMsgArray.end(); ++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); +} + +void ImageSourceImpl::ReleaseSync() +{ + if (!isRelease) { + if (nativeImgSrc != nullptr) { + nativeImgSrc = nullptr; + } + isRelease = true; + } +} + +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 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); +} +} // 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); \ 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..a14dc88cd94f4f63d61598b8816ded599d08eb36 --- /dev/null +++ b/frameworks/kits/taihe/src/image_taihe.cpp @@ -0,0 +1,114 @@ +/* + * 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.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), isTestImage_(false), isRelease(false) {} + +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() +{ + ReleaseSync(); +} + +struct Image ImageImpl::Create(std::shared_ptr nativeImage) +{ + return make_holder(nativeImage); +} + +void ImageImpl::ReleaseSync() +{ + if (!isRelease) { + if (nativeImage_ != nullptr) { + nativeImage_ = nullptr; + } + isRelease = true; + } +} + +Size ImageImpl::GetSize() +{ + Size result {NUM0, NUM0}; + if (isTestImage_) { + result.width = TEST_WIDTH; + result.height = TEST_HEIGHT; + return result; + } + if (nativeImage_ == nullptr) { + IMAGE_LOGE("Image surface buffer is nullptr"); + return result; + } + + if (nativeImage_->GetSize(result.width, result.height) != OHOS::Media::SUCCESS) { + IMAGE_LOGE("Image native get size failed"); + } + return result; +} + +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; +} +} // 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..b0f1c14beea3b7b3bb63dd7f7c11d250de8ee152 --- /dev/null +++ b/frameworks/kits/taihe/src/image_taihe_utils.cpp @@ -0,0 +1,169 @@ +/* + * 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::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); +} // 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..f9136c3d57338babbbccc045e7acdaaadda41996 --- /dev/null +++ b/frameworks/kits/taihe/src/picture_taihe.cpp @@ -0,0 +1,123 @@ +/* + * 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_taihe_utils.h" +#include "picture_taihe.h" +#include "pixel_map_taihe.h" +#include "media_errors.h" +#include "message_parcel.h" + +using namespace ANI::Image; + +namespace ANI::Image { + +PictureImpl::PictureImpl() : nativePicture_(nullptr), isRelease(false) {} + +PictureImpl::PictureImpl(std::shared_ptr picture) +{ + nativePicture_ = picture; +} + +PictureImpl::~PictureImpl() +{ + Release(); +} + +int64_t PictureImpl::GetImplPtr() +{ + return reinterpret_cast(this); +} + +std::shared_ptr PictureImpl::GetNativePtr() +{ + return nativePicture_; +} + +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); +} + +void PictureImpl::Marshalling(uintptr_t sequence) +{ +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) + ani_env *env = ::taihe::get_env(); + if (env == nullptr) { + ImageTaiheUtils::ThrowExceptionError(IMAGE_BAD_PARAMETER, "Ani unwarp messageParcel failed."); + return; + } + ani_object sequenceObj = reinterpret_cast(sequence); + ani_long nativePtr; + if (ANI_OK != env->Object_GetFieldByName_Long(sequenceObj, "nativePtr", &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)); +} +} // namespace ANI::Image + +TH_EXPORT_CPP_API_CreatePictureByPixelMap(CreatePictureByPixelMap); \ 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..ccb4d85e122451ac33f2fafa8fafd09421a6742c --- /dev/null +++ b/frameworks/kits/taihe/src/pixel_map_taihe.cpp @@ -0,0 +1,535 @@ +/* + * 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" +#include "media_errors.h" +#include "pixel_map_taihe_ani.h" +#include "pixel_map_taihe.h" +#if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) +#include +#include "pixel_map_from_surface.h" +#include "sync_fence.h" +#include "transaction/rs_interfaces.h" +#endif + +namespace ANI::Image { + +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) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + 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) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + 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) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + 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) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + 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) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + 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) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + 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) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + return 0; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return 0; + } + + return nativePixelMap_->GetByteCount(); +} + +void PixelMapImpl::ScaleSync(double x, double y) +{ + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + nativePixelMap_->scale(static_cast(x), static_cast(y)); +} + +void PixelMapImpl::ScaleWithAntiAliasingSync(double x, double y, AntiAliasingLevel level) +{ + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + nativePixelMap_->scale(static_cast(x), static_cast(y), Media::AntiAliasingOption(level.get_value())); +} + +void PixelMapImpl::CropSync(ohos::multimedia::image::image::Region const& region) +{ + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + 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(double angle) +{ + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + nativePixelMap_->rotate(static_cast(angle)); +} + +void PixelMapImpl::FlipSync(bool horizontal, bool vertical) +{ + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + nativePixelMap_->flip(horizontal, vertical); +} + +void PixelMapImpl::OpacitySync(double rate) +{ + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + return; + } + if (!aniEditable_) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "PixelMap has crossed threads"); + return; + } + + uint32_t status = nativePixelMap_->SetAlpha(static_cast(rate)); + if (status != Media::SUCCESS) { + IMAGE_LOGE("[PixelMap ANI] SetAlpha failed"); + } +} + +void PixelMapImpl::SetMemoryNameSync(string_view name) +{ + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + 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"); + } +} + +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::GetIsStrideAlignment() +{ + if (nativePixelMap_ == nullptr) { + ImageTaiheUtils::ThrowExceptionError(Media::ERR_RESOURCE_UNAVAILABLE, "Native PixelMap is nullptr"); + 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..83361cc123b4f723ece002c657ad0f3b02e594e6 --- /dev/null +++ b/frameworks/kits/taihe/src/pixel_map_taihe_ani.cpp @@ -0,0 +1,69 @@ +/* + * 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 "pixel_map_taihe.h" + +// This file is for legacy ANI backward compatibility + +namespace OHOS { +namespace Media { +using namespace ANI::Image; + +ani_object PixelMapTaiheAni::CreateEtsPixelMap([[maybe_unused]] ani_env* env, std::shared_ptr pixelMap) +{ + std::unique_ptr pixelMapAni = std::make_unique(); + pixelMapAni->nativePixelMap_ = pixelMap; + + ani_namespace imageNamespace; + if (env->FindNamespace("L@ohos/multimedia/image/image;", &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.release())) != ANI_OK) { + return nullptr; + } + + return reinterpret_cast(pixelMapObj); +} + +std::shared_ptr PixelMapTaiheAni::GetNativePixelMap([[maybe_unused]] ani_env* env, ani_object obj) +{ + ani_class pixelMapCls; + if (env->FindClass("L@ohos/multimedia/image/image/PixelMap;", &pixelMapCls) != ANI_OK) { + return nullptr; + } + ani_method getMethod; + if (env->Class_FindMethod(pixelMapCls, "getImplPtr", ":J", &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