已合并
fix(image): harden pixel map validation and cleanup #5776
多面体创建于 29 天前
fix(image): harden pixel map validation and cleanup #5776
已合并
共 37 个文件变更+1510-412
| @@ -15,6 +15,9 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 18 | 21 | ||
| 19 | 22 | ||
| 20 | 23 | ||
| @@ -37,6 +40,53 @@ namespace OHOS { | |||
| 37 | namespace Media { | 40 | namespace Media { |
| 38 | using namespace std; | 41 | using namespace std; |
| 39 | 42 | ||
| 43 | +namespace { | ||
| 44 | +constexpr double PI = 3.14159265358979323846; | ||
| 45 | +constexpr double FULL_ROTATION_DEGREES = 360.0; | ||
| 46 | + | ||
| 47 | +bool SafeCastToInt32(double value, int32_t &result) | ||
| 48 | +{ | ||
| 49 | + if (!std::isfinite(value) || | ||
| 50 | + value < static_cast<double>(std::numeric_limits<int32_t>::min()) || | ||
| 51 | + value > static_cast<double>(std::numeric_limits<int32_t>::max())) { | ||
| 52 | + return false; | ||
| 53 | + } | ||
| 54 | + result = static_cast<int32_t>(value); | ||
| 55 | + return true; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +bool SafeRoundToInt32(double value, int32_t &result) | ||
| 59 | +{ | ||
| 60 | + if (!std::isfinite(value)) { | ||
| 61 | + return false; | ||
| 62 | + } | ||
| 63 | + return SafeCastToInt32(std::round(value), result); | ||
| 64 | +} | ||
| 65 | + | ||
| 66 | +bool SafeCastToFloat(double value, float &result) | ||
| 67 | +{ | ||
| 68 | + if (!std::isfinite(value) || | ||
| 69 | + value < -static_cast<double>(std::numeric_limits<float>::max()) || | ||
| 70 | + value > static_cast<double>(std::numeric_limits<float>::max())) { | ||
| 71 | + return false; | ||
| 72 | + } | ||
| 73 | + result = static_cast<float>(value); | ||
| 74 | + return true; | ||
| 75 | +} | ||
| 76 | + | ||
| 77 | +std::pair<double, double> CalculateRotatedDimensions(int32_t width, int32_t height, double rotationDegrees) | ||
| 78 | +{ | ||
| 79 | + double radians = rotationDegrees * PI / 180.0; | ||
| 80 | + double cosTheta = std::cos(radians); | ||
| 81 | + double sinTheta = std::sin(radians); | ||
| 82 | + double newWidth = std::abs(static_cast<double>(width) * cosTheta) + | ||
| 83 | + std::abs(static_cast<double>(height) * sinTheta); | ||
| 84 | + double newHeight = std::abs(static_cast<double>(width) * sinTheta) + | ||
| 85 | + std::abs(static_cast<double>(height) * cosTheta); | ||
| 86 | + return {newWidth, newHeight}; | ||
| 87 | +} | ||
| 88 | +} | ||
| 89 | + | ||
| 40 | PixelAstc::~PixelAstc() | 90 | PixelAstc::~PixelAstc() |
| 41 | { | 91 | { |
| 42 | IMAGE_LOGD("PixelAstc destory"); | 92 | IMAGE_LOGD("PixelAstc destory"); |
| @@ -68,30 +118,41 @@ bool PixelAstc::GetARGB32Color(int32_t x, int32_t y, uint32_t &color) | |||
| 68 | 118 | ||
| 69 | void PixelAstc::scale(float xAxis, float yAxis) | 119 | void PixelAstc::scale(float xAxis, float yAxis) |
| 70 | { | 120 | { |
| 71 | - if (xAxis == 0 || yAxis == 0) { | 121 | + Scale(xAxis, yAxis, AntiAliasingOption::NONE); |
| 72 | - IMAGE_LOGE("scale param incorrect on pixelastc"); | ||
| 73 | - return; | ||
| 74 | - } else { | ||
| 75 | - TransformData transformData; | ||
| 76 | - GetTransformData(transformData); | ||
| 77 | - transformData.scaleX *= xAxis; | ||
| 78 | - transformData.scaleY *= yAxis; | ||
| 79 | - SetTransformData(transformData); | ||
| 80 | - ImageInfo imageInfo; | ||
| 81 | - GetImageInfo(imageInfo); | ||
| 82 | - imageInfo.size.width = static_cast<int32_t>(round(imageInfo.size.width * abs(xAxis))); | ||
| 83 | - imageInfo.size.height = static_cast<int32_t>(round(imageInfo.size.height * abs(yAxis))); | ||
| 84 | - SetImageInfo(imageInfo, true); | ||
| 85 | - } | ||
| 86 | } | 122 | } |
| 87 | 123 | ||
| 88 | uint32_t PixelAstc::Scale(float xAxis, float yAxis, AntiAliasingOption option) | 124 | uint32_t PixelAstc::Scale(float xAxis, float yAxis, AntiAliasingOption option) |
| 89 | { | 125 | { |
| 90 | - if (xAxis == 0 || yAxis == 0) { | 126 | + std::lock_guard<std::mutex> lock(*translationMutex_); |
| 91 | - IMAGE_LOGE("Invalid scale ratio: 0"); | 127 | + if (!std::isfinite(xAxis) || !std::isfinite(yAxis) || xAxis == 0.0f || yAxis == 0.0f) { |
| 128 | + IMAGE_LOGE("Invalid scale ratio"); | ||
| 92 | return ERR_IMAGE_INVALID_PARAMETER; | 129 | return ERR_IMAGE_INVALID_PARAMETER; |
| 93 | } | 130 | } |
| 94 | - scale(xAxis, yAxis); | 131 | + TransformData transformData; |
| 132 | + GetTransformData(transformData); | ||
| 133 | + ImageInfo imageInfo; | ||
| 134 | + GetImageInfo(imageInfo); | ||
| 135 | + ImageInfo scaledImageInfo = imageInfo; | ||
| 136 | + double scaledWidth = std::abs(static_cast<double>(imageInfo.size.width) * xAxis); | ||
| 137 | + double scaledHeight = std::abs(static_cast<double>(imageInfo.size.height) * yAxis); | ||
| 138 | + if (!SafeRoundToInt32(scaledWidth, scaledImageInfo.size.width) || | ||
| 139 | + !SafeRoundToInt32(scaledHeight, scaledImageInfo.size.height) || | ||
| 140 | + scaledImageInfo.size.width <= 0 || scaledImageInfo.size.height <= 0 || | ||
| 141 | + !SafeCastToFloat(static_cast<double>(transformData.scaleX) * xAxis, transformData.scaleX) || | ||
| 142 | + !SafeCastToFloat(static_cast<double>(transformData.scaleY) * yAxis, transformData.scaleY)) { | ||
| 143 | + IMAGE_LOGE("Invalid scaled image or transform size"); | ||
| 144 | + return ERR_IMAGE_INVALID_PARAMETER; | ||
| 145 | + } | ||
| 146 | + uint32_t ret = SetImageInfo(scaledImageInfo, true); | ||
| 147 | + if (ret != SUCCESS) { | ||
| 148 | + IMAGE_LOGE("PixelAstc scale SetImageInfo failed, ret: %{public}u", ret); | ||
| 149 | + uint32_t restoreRet = SetImageInfo(imageInfo, true); | ||
| 150 | + if (restoreRet != SUCCESS) { | ||
| 151 | + IMAGE_LOGE("PixelAstc scale restore ImageInfo failed, ret: %{public}u", restoreRet); | ||
| 152 | + } | ||
| 153 | + return ret; | ||
| 154 | + } | ||
| 155 | + SetTransformData(transformData); | ||
| 95 | return SUCCESS; | 156 | return SUCCESS; |
| 96 | } | 157 | } |
| 97 | 158 | ||
| @@ -108,35 +169,43 @@ void PixelAstc::translate(float xAxis, float yAxis) | |||
| 108 | 169 | ||
| 109 | uint32_t PixelAstc::Translate(float xAxis, float yAxis) | 170 | uint32_t PixelAstc::Translate(float xAxis, float yAxis) |
| 110 | { | 171 | { |
| 172 | + std::lock_guard<std::mutex> lock(*translationMutex_); | ||
| 173 | + if (!std::isfinite(xAxis) || !std::isfinite(yAxis)) { | ||
| 174 | + IMAGE_LOGE("Invalid translate distance"); | ||
| 175 | + return ERR_IMAGE_INVALID_PARAMETER; | ||
| 176 | + } | ||
| 111 | TransformData transformData; | 177 | TransformData transformData; |
| 112 | GetTransformData(transformData); | 178 | GetTransformData(transformData); |
| 113 | - transformData.translateX += xAxis; | ||
| 114 | - transformData.translateY += yAxis; | ||
| 115 | ImageInfo imageInfo; | 179 | ImageInfo imageInfo; |
| 116 | GetImageInfo(imageInfo); | 180 | GetImageInfo(imageInfo); |
| 117 | - imageInfo.size.width += static_cast<int32_t>(xAxis); | 181 | + ImageInfo translatedImageInfo = imageInfo; |
| 118 | - imageInfo.size.height += static_cast<int32_t>(yAxis); | 182 | + int32_t translatedXAxis = 0; |
| 119 | - if (imageInfo.size.width <= 0 || imageInfo.size.height <= 0) { | 183 | + int32_t translatedYAxis = 0; |
| 184 | + if (!SafeCastToInt32(xAxis, translatedXAxis) || | ||
| 185 | + !SafeCastToInt32(yAxis, translatedYAxis) || | ||
| 186 | + !SafeCastToInt32(static_cast<double>(imageInfo.size.width) + translatedXAxis, | ||
| 187 | + translatedImageInfo.size.width) || | ||
| 188 | + !SafeCastToInt32(static_cast<double>(imageInfo.size.height) + translatedYAxis, | ||
| 189 | + translatedImageInfo.size.height) || | ||
| 190 | + translatedImageInfo.size.width <= 0 || translatedImageInfo.size.height <= 0 || | ||
| 191 | + !SafeCastToFloat(static_cast<double>(transformData.translateX) + xAxis, transformData.translateX) || | ||
| 192 | + !SafeCastToFloat(static_cast<double>(transformData.translateY) + yAxis, transformData.translateY)) { | ||
| 120 | IMAGE_LOGE("PixelAstc translate failed"); | 193 | IMAGE_LOGE("PixelAstc translate failed"); |
| 121 | return ERR_IMAGE_INVALID_PARAMETER; | 194 | return ERR_IMAGE_INVALID_PARAMETER; |
| 122 | } | 195 | } |
| 196 | + uint32_t ret = SetImageInfo(translatedImageInfo, true); | ||
| 197 | + if (ret != SUCCESS) { | ||
| 198 | + IMAGE_LOGE("PixelAstc translate SetImageInfo failed, ret: %{public}u", ret); | ||
| 199 | + uint32_t restoreRet = SetImageInfo(imageInfo, true); | ||
| 200 | + if (restoreRet != SUCCESS) { | ||
| 201 | + IMAGE_LOGE("PixelAstc translate restore ImageInfo failed, ret: %{public}u", restoreRet); | ||
| 202 | + } | ||
| 203 | + return ret; | ||
| 204 | + } | ||
| 123 | SetTransformData(transformData); | 205 | SetTransformData(transformData); |
| 124 | - SetImageInfo(imageInfo, true); | ||
| 125 | return SUCCESS; | 206 | return SUCCESS; |
| 126 | } | 207 | } |
| 127 | 208 | ||
| 128 | -std::pair<float, float> calculateRotatedDimensions(float width, float height, float rotationDegrees) | ||
| 129 | -{ | ||
| 130 | - float radians = rotationDegrees * M_PI / 180.0f; | ||
| 131 | - | ||
| 132 | - float cosTheta = std::cos(radians); | ||
| 133 | - float sinTheta = std::sin(radians); | ||
| 134 | - | ||
| 135 | - float newWidth = std::abs(width * cosTheta) + std::abs(height * sinTheta); | ||
| 136 | - float newHeight = std::abs(width * sinTheta) + std::abs(height * cosTheta); | ||
| 137 | - return {newWidth, newHeight}; | ||
| 138 | -} | ||
| 139 | - | ||
| 140 | void PixelAstc::rotate(float degrees) | 209 | void PixelAstc::rotate(float degrees) |
| 141 | { | 210 | { |
| 142 | Rotate(degrees); | 211 | Rotate(degrees); |
| @@ -144,17 +213,43 @@ void PixelAstc::rotate(float degrees) | |||
| 144 | 213 | ||
| 145 | uint32_t PixelAstc::Rotate(float degrees) | 214 | uint32_t PixelAstc::Rotate(float degrees) |
| 146 | { | 215 | { |
| 216 | + std::lock_guard<std::mutex> lock(*translationMutex_); | ||
| 217 | + if (!std::isfinite(degrees)) { | ||
| 218 | + IMAGE_LOGE("Invalid rotate degrees"); | ||
| 219 | + return ERR_IMAGE_INVALID_PARAMETER; | ||
| 220 | + } | ||
| 147 | TransformData transformData; | 221 | TransformData transformData; |
| 148 | GetTransformData(transformData); | 222 | GetTransformData(transformData); |
| 149 | - transformData.rotateD += degrees; | 223 | + double normalizedDegrees = std::fmod(static_cast<double>(degrees), FULL_ROTATION_DEGREES); |
| 150 | - transformData.rotateD = fmod(fmod(transformData.rotateD, 360.0f) + 360.0f, 360.0f); // Normalize to [0, 360) | 224 | + double accumulatedDegrees = std::fmod( |
| 151 | - SetTransformData(transformData); | 225 | + static_cast<double>(transformData.rotateD) + normalizedDegrees, FULL_ROTATION_DEGREES); |
| 226 | + accumulatedDegrees = std::fmod( | ||
| 227 | + accumulatedDegrees + FULL_ROTATION_DEGREES, FULL_ROTATION_DEGREES); | ||
| 228 | + if (!SafeCastToFloat(accumulatedDegrees, transformData.rotateD)) { | ||
| 229 | + IMAGE_LOGE("Invalid accumulated rotate degrees"); | ||
| 230 | + return ERR_IMAGE_INVALID_PARAMETER; | ||
| 231 | + } | ||
| 152 | ImageInfo imageInfo; | 232 | ImageInfo imageInfo; |
| 153 | GetImageInfo(imageInfo); | 233 | GetImageInfo(imageInfo); |
| 154 | - auto newDimensions = calculateRotatedDimensions(imageInfo.size.width, imageInfo.size.height, degrees); | 234 | + ImageInfo rotatedImageInfo = imageInfo; |
| 155 | - imageInfo.size.width = static_cast<int32_t>(newDimensions.first); | 235 | + auto newDimensions = CalculateRotatedDimensions( |
| 156 | - imageInfo.size.height = static_cast<int32_t>(newDimensions.second); | 236 | + imageInfo.size.width, imageInfo.size.height, normalizedDegrees); |
| 157 | - SetImageInfo(imageInfo, true); | 237 | + if (!SafeCastToInt32(newDimensions.first, rotatedImageInfo.size.width) || |
| 238 | + !SafeCastToInt32(newDimensions.second, rotatedImageInfo.size.height) || | ||
| 239 | + rotatedImageInfo.size.width <= 0 || rotatedImageInfo.size.height <= 0) { | ||
| 240 | + IMAGE_LOGE("Invalid rotated image size"); | ||
| 241 | + return ERR_IMAGE_INVALID_PARAMETER; | ||
| 242 | + } | ||
| 243 | + uint32_t ret = SetImageInfo(rotatedImageInfo, true); | ||
| 244 | + if (ret != SUCCESS) { | ||
| 245 | + IMAGE_LOGE("PixelAstc rotate SetImageInfo failed, ret: %{public}u", ret); | ||
| 246 | + uint32_t restoreRet = SetImageInfo(imageInfo, true); | ||
| 247 | + if (restoreRet != SUCCESS) { | ||
| 248 | + IMAGE_LOGE("PixelAstc rotate restore ImageInfo failed, ret: %{public}u", restoreRet); | ||
| 249 | + } | ||
| 250 | + return ret; | ||
| 251 | + } | ||
| 252 | + SetTransformData(transformData); | ||
| 158 | return SUCCESS; | 253 | return SUCCESS; |
| 159 | } | 254 | } |
| 160 | 255 | ||
| @@ -165,6 +260,7 @@ void PixelAstc::flip(bool xAxis, bool yAxis) | |||
| 165 | 260 | ||
| 166 | uint32_t PixelAstc::Flip(bool xAxis, bool yAxis) | 261 | uint32_t PixelAstc::Flip(bool xAxis, bool yAxis) |
| 167 | { | 262 | { |
| 263 | + std::lock_guard<std::mutex> lock(*translationMutex_); | ||
| 168 | TransformData transformData; | 264 | TransformData transformData; |
| 169 | GetTransformData(transformData); | 265 | GetTransformData(transformData); |
| 170 | transformData.flipX = xAxis; | 266 | transformData.flipX = xAxis; |
| @@ -180,6 +276,7 @@ uint32_t PixelAstc::crop(const Rect &rect) | |||
| 180 | 276 | ||
| 181 | uint32_t PixelAstc::Crop(const Rect &rect) | 277 | uint32_t PixelAstc::Crop(const Rect &rect) |
| 182 | { | 278 | { |
| 279 | + std::lock_guard<std::mutex> lock(*translationMutex_); | ||
| 183 | ImageInfo imageInfo; | 280 | ImageInfo imageInfo; |
| 184 | GetImageInfo(imageInfo); | 281 | GetImageInfo(imageInfo); |
| 185 | if (rect.left >= 0 && rect.top >= 0 && rect.width > 0 && rect.height > 0 && | 282 | if (rect.left >= 0 && rect.top >= 0 && rect.width > 0 && rect.height > 0 && |
| @@ -192,10 +289,19 @@ uint32_t PixelAstc::Crop(const Rect &rect) | |||
| 192 | transformData.cropTop = rect.top; | 289 | transformData.cropTop = rect.top; |
| 193 | transformData.cropWidth = rect.width; | 290 | transformData.cropWidth = rect.width; |
| 194 | transformData.cropHeight = rect.height; | 291 | transformData.cropHeight = rect.height; |
| 292 | + ImageInfo croppedImageInfo = imageInfo; | ||
| 293 | + croppedImageInfo.size.width = rect.width; | ||
| 294 | + croppedImageInfo.size.height = rect.height; | ||
| 295 | + uint32_t ret = SetImageInfo(croppedImageInfo, true); | ||
| 296 | + if (ret != SUCCESS) { | ||
| 297 | + IMAGE_LOGE("PixelAstc crop SetImageInfo failed, ret: %{public}u", ret); | ||
| 298 | + uint32_t restoreRet = SetImageInfo(imageInfo, true); | ||
| 299 | + if (restoreRet != SUCCESS) { | ||
| 300 | + IMAGE_LOGE("PixelAstc crop restore ImageInfo failed, ret: %{public}u", restoreRet); | ||
| 301 | + } | ||
| 302 | + return ret; | ||
| 303 | + } | ||
| 195 | SetTransformData(transformData); | 304 | SetTransformData(transformData); |
| 196 | - imageInfo.size.width = rect.width; | ||
| 197 | - imageInfo.size.height = rect.height; | ||
| 198 | - SetImageInfo(imageInfo, true); | ||
| 199 | } else { | 305 | } else { |
| 200 | IMAGE_LOGE("crop failed"); | 306 | IMAGE_LOGE("crop failed"); |
| 201 | return ERR_IMAGE_CROP; | 307 | return ERR_IMAGE_CROP; |
| @@ -318,4 +424,4 @@ void* PixelAstc::GetWritablePixels() const | |||
| 318 | return nullptr; | 424 | return nullptr; |
| 319 | } | 425 | } |
| 320 | } // namespace Media | 426 | } // namespace Media |
| 321 | -} // namespace OHOS | 427 | +} // namespace OHOS |
| @@ -20,7 +20,9 @@ | |||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | + | ||
| 23 | 24 | ||
| 25 | + | ||
| 24 | 26 | ||
| 25 | 27 | ||
| 26 | 28 | ||
| @@ -4351,7 +4353,7 @@ static uint32_t ValidateSetAlpha(float percent, bool modifiable, AlphaType alpha | |||
| 4351 | IMAGE_LOGE("[PixelMap] SetAlpha could not set alpha on %{public}s", GetNamedAlphaType(alphaType).c_str()); | 4353 | IMAGE_LOGE("[PixelMap] SetAlpha could not set alpha on %{public}s", GetNamedAlphaType(alphaType).c_str()); |
| 4352 | return ERR_IMAGE_DATA_UNSUPPORT; | 4354 | return ERR_IMAGE_DATA_UNSUPPORT; |
| 4353 | } | 4355 | } |
| 4354 | - if (percent <= 0 || percent > 1) { | 4356 | + if (!std::isfinite(percent) || percent <= 0 || percent > 1) { |
| 4355 | IMAGE_LOGE("[PixelMap] SetAlpha input should satisfy (0 < input <= 1). Current input is %{public}f", percent); | 4357 | IMAGE_LOGE("[PixelMap] SetAlpha input should satisfy (0 < input <= 1). Current input is %{public}f", percent); |
| 4356 | return ERR_IMAGE_INVALID_PARAMETER; | 4358 | return ERR_IMAGE_INVALID_PARAMETER; |
| 4357 | } | 4359 | } |
| @@ -4458,11 +4460,35 @@ struct TransMemoryInfo { | |||
| 4458 | std::unique_ptr<AbsMemory> memory = nullptr; | 4460 | std::unique_ptr<AbsMemory> memory = nullptr; |
| 4459 | }; | 4461 | }; |
| 4460 | 4462 | ||
| 4461 | -constexpr float HALF = 0.5f; | 4463 | +static bool SafeCastToInt32(double value, int32_t &result) |
| 4462 | - | ||
| 4463 | -static inline int FloatToInt(float a) | ||
| 4464 | { | 4464 | { |
| 4465 | - return static_cast<int>(a + HALF); | 4465 | + if (!std::isfinite(value) || |
| 4466 | + value < static_cast<double>(std::numeric_limits<int32_t>::min()) || | ||
| 4467 | + value > static_cast<double>(std::numeric_limits<int32_t>::max())) { | ||
| 4468 | + return false; | ||
| 4469 | + } | ||
| 4470 | + result = static_cast<int32_t>(value); | ||
| 4471 | + return true; | ||
| 4472 | +} | ||
| 4473 | + | ||
| 4474 | +static bool SafeRoundToInt32(double value, int32_t &result) | ||
| 4475 | +{ | ||
| 4476 | + if (!std::isfinite(value)) { | ||
| 4477 | + return false; | ||
| 4478 | + } | ||
| 4479 | + return SafeCastToInt32(std::round(value), result); | ||
| 4480 | +} | ||
| 4481 | + | ||
| 4482 | +static bool GetScaledSize(const Size &srcSize, float xAxis, float yAxis, Size &dstSize) | ||
| 4483 | +{ | ||
| 4484 | + if (!std::isfinite(xAxis) || !std::isfinite(yAxis) || xAxis == 0.0f || yAxis == 0.0f) { | ||
| 4485 | + return false; | ||
| 4486 | + } | ||
| 4487 | + double scaledWidth = std::abs(static_cast<double>(srcSize.width) * static_cast<double>(xAxis)); | ||
| 4488 | + double scaledHeight = std::abs(static_cast<double>(srcSize.height) * static_cast<double>(yAxis)); | ||
| 4489 | + return SafeRoundToInt32(scaledWidth, dstSize.width) && | ||
| 4490 | + SafeRoundToInt32(scaledHeight, dstSize.height) && | ||
| 4491 | + dstSize.width > 0 && dstSize.height > 0; | ||
| 4466 | } | 4492 | } |
| 4467 | 4493 | ||
| 4468 | 4494 | ||
| @@ -4491,17 +4517,9 @@ static void GenSrcTransInfo(SkTransInfo &srcInfo, ImageInfo &imageInfo, uint8_t* | |||
| 4491 | srcInfo.bitmap.installPixels(srcInfo.info, pixels, srcInfo.info.minRowBytes()); | 4517 | srcInfo.bitmap.installPixels(srcInfo.info, pixels, srcInfo.info.minRowBytes()); |
| 4492 | } | 4518 | } |
| 4493 | 4519 | ||
| 4494 | -static bool GenDstTransInfo(SkTransInfo &srcInfo, SkTransInfo &dstInfo, SkMatrix &matrix, | 4520 | +static bool AllocDstTransMemory(SkTransInfo &srcInfo, SkTransInfo &dstInfo, TransMemoryInfo &memoryInfo, |
| 4495 | - TransMemoryInfo &memoryInfo, uint64_t usage) | 4521 | + uint64_t usage) |
| 4496 | { | 4522 | { |
| 4497 | - dstInfo.r = matrix.mapRect(srcInfo.r); | ||
| 4498 | - int width = FloatToInt(dstInfo.r.width()); | ||
| 4499 | - int height = FloatToInt(dstInfo.r.height()); | ||
| 4500 | - if (matrix.isTranslate()) { | ||
| 4501 | - width += dstInfo.r.fLeft; | ||
| 4502 | - height += dstInfo.r.fTop; | ||
| 4503 | - } | ||
| 4504 | - dstInfo.info = srcInfo.info.makeWH(width, height); | ||
| 4505 | PixelFormat format = ImageTypeConverter::ToPixelFormat(srcInfo.info.colorType()); | 4523 | PixelFormat format = ImageTypeConverter::ToPixelFormat(srcInfo.info.colorType()); |
| 4506 | 4524 | ||
| 4507 | Size desiredSize = {dstInfo.info.width(), dstInfo.info.height()}; | 4525 | Size desiredSize = {dstInfo.info.width(), dstInfo.info.height()}; |
| @@ -4542,6 +4560,36 @@ static bool GenDstTransInfo(SkTransInfo &srcInfo, SkTransInfo &dstInfo, SkMatrix | |||
| 4542 | return true; | 4560 | return true; |
| 4543 | } | 4561 | } |
| 4544 | 4562 | ||
| 4563 | +static bool GenDstTransInfo(SkTransInfo &srcInfo, SkTransInfo &dstInfo, SkMatrix &matrix, | ||
| 4564 | + TransMemoryInfo &memoryInfo, uint64_t usage) | ||
| 4565 | +{ | ||
| 4566 | + dstInfo.r = matrix.mapRect(srcInfo.r); | ||
| 4567 | + if (!std::isfinite(dstInfo.r.fLeft) || !std::isfinite(dstInfo.r.fTop) || | ||
| 4568 | + !std::isfinite(dstInfo.r.fRight) || !std::isfinite(dstInfo.r.fBottom)) { | ||
| 4569 | + IMAGE_LOGE("Invalid transformed rectangle"); | ||
| 4570 | + return false; | ||
| 4571 | + } | ||
| 4572 | + int32_t width = 0; | ||
| 4573 | + int32_t height = 0; | ||
| 4574 | + if (!SafeRoundToInt32(dstInfo.r.width(), width) || !SafeRoundToInt32(dstInfo.r.height(), height)) { | ||
| 4575 | + IMAGE_LOGE("Invalid transformed image size"); | ||
| 4576 | + return false; | ||
| 4577 | + } | ||
| 4578 | + if (matrix.isTranslate()) { | ||
| 4579 | + if (!SafeCastToInt32(static_cast<double>(width) + dstInfo.r.fLeft, width) || | ||
| 4580 | + !SafeCastToInt32(static_cast<double>(height) + dstInfo.r.fTop, height)) { | ||
| 4581 | + IMAGE_LOGE("Invalid translated image size"); | ||
| 4582 | + return false; | ||
| 4583 | + } | ||
| 4584 | + } | ||
| 4585 | + if (width <= 0 || height <= 0) { | ||
| 4586 | + IMAGE_LOGE("Transformed image size must be positive"); | ||
| 4587 | + return false; | ||
| 4588 | + } | ||
| 4589 | + dstInfo.info = srcInfo.info.makeWH(width, height); | ||
| 4590 | + return AllocDstTransMemory(srcInfo, dstInfo, memoryInfo, usage); | ||
| 4591 | +} | ||
| 4592 | + | ||
| 4545 | struct TransInfos { | 4593 | struct TransInfos { |
| 4546 | SkMatrix matrix; | 4594 | SkMatrix matrix; |
| 4547 | }; | 4595 | }; |
| @@ -4657,8 +4705,13 @@ void PixelMap::scale(float xAxis, float yAxis) | |||
| 4657 | IMAGE_LOGE("scale does not support Y8"); | 4705 | IMAGE_LOGE("scale does not support Y8"); |
| 4658 | return; | 4706 | return; |
| 4659 | } | 4707 | } |
| 4660 | - if ((static_cast<int32_t>(round(imageInfo_.size.width * xAxis)) - imageInfo_.size.width) == 0 && | 4708 | + Size scaledSize; |
| 4661 | - (static_cast<int32_t>(round(imageInfo_.size.height * yAxis)) - imageInfo_.size.height) == 0) { | 4709 | + if (!GetScaledSize(imageInfo_.size, xAxis, yAxis, scaledSize)) { |
| 4710 | + IMAGE_LOGE("Invalid scale ratio"); | ||
| 4711 | + return; | ||
| 4712 | + } | ||
| 4713 | + if (xAxis > 0.0f && yAxis > 0.0f && | ||
| 4714 | + scaledSize.width == imageInfo_.size.width && scaledSize.height == imageInfo_.size.height) { | ||
| 4662 | return; | 4715 | return; |
| 4663 | } | 4716 | } |
| 4664 | TransInfos infos; | 4717 | TransInfos infos; |
| @@ -4677,12 +4730,13 @@ void PixelMap::scale(float xAxis, float yAxis, const AntiAliasingOption &option) | |||
| 4677 | 4730 | ||
| 4678 | uint32_t PixelMap::Scale(float xAxis, float yAxis, AntiAliasingOption option) | 4731 | uint32_t PixelMap::Scale(float xAxis, float yAxis, AntiAliasingOption option) |
| 4679 | { | 4732 | { |
| 4680 | - if (xAxis == 0 || yAxis == 0) { | 4733 | + Size scaledSize; |
| 4681 | - IMAGE_LOGE("Invalid scale ratio: 0"); | 4734 | + if (!GetScaledSize(imageInfo_.size, xAxis, yAxis, scaledSize)) { |
| 4735 | + IMAGE_LOGE("Invalid scale ratio"); | ||
| 4682 | return ERR_IMAGE_INVALID_PARAMETER; | 4736 | return ERR_IMAGE_INVALID_PARAMETER; |
| 4683 | } | 4737 | } |
| 4684 | - if ((static_cast<int32_t>(round(imageInfo_.size.width * xAxis)) - imageInfo_.size.width) == 0 && | 4738 | + if (xAxis > 0.0f && yAxis > 0.0f && |
| 4685 | - (static_cast<int32_t>(round(imageInfo_.size.height * yAxis)) - imageInfo_.size.height) == 0) { | 4739 | + scaledSize.width == imageInfo_.size.width && scaledSize.height == imageInfo_.size.height) { |
| 4686 | return SUCCESS; | 4740 | return SUCCESS; |
| 4687 | } | 4741 | } |
| 4688 | if (IsAstcOrY8Format()) { | 4742 | if (IsAstcOrY8Format()) { |
| @@ -4723,8 +4777,16 @@ uint32_t PixelMap::ScaleWithSLR(float xAxis, float yAxis) | |||
| 4723 | ImageInfo tmpInfo; | 4777 | ImageInfo tmpInfo; |
| 4724 | GetImageInfo(tmpInfo); | 4778 | GetImageInfo(tmpInfo); |
| 4725 | Size desiredSize; | 4779 | Size desiredSize; |
| 4726 | - desiredSize.width = static_cast<int32_t>(imageInfo_.size.width * xAxis); | 4780 | + if (!SafeCastToInt32(static_cast<double>(imageInfo_.size.width * xAxis), desiredSize.width) || |
| 4727 | - desiredSize.height = static_cast<int32_t>(imageInfo_.size.height * yAxis); | 4781 | + !SafeCastToInt32(static_cast<double>(imageInfo_.size.height * yAxis), desiredSize.height) || |
| 4782 | + desiredSize.width == 0 || desiredSize.height == 0) { | ||
| 4783 | + IMAGE_LOGE("PixelMap::scale with SLR invalid scale ratio"); | ||
| 4784 | + return ERR_IMAGE_INVALID_PARAMETER; | ||
| 4785 | + } | ||
| 4786 | + if (desiredSize.width < 0 || desiredSize.height < 0) { | ||
| 4787 | + IMAGE_LOGE("PixelMap::scale with SLR does not support negative scale ratio"); | ||
| 4788 | + return ERR_IMAGE_TRANSFORM; | ||
| 4789 | + } | ||
| 4728 | 4790 | ||
| 4729 | PostProc postProc; | 4791 | PostProc postProc; |
| 4730 | if (!postProc.ScalePixelMapWithSLR(desiredSize, *this)) { | 4792 | if (!postProc.ScalePixelMapWithSLR(desiredSize, *this)) { |
| @@ -4745,6 +4807,11 @@ uint32_t PixelMap::ScaleWithSLR(float xAxis, float yAxis) | |||
| 4745 | 4807 | ||
| 4746 | bool PixelMap::resize(float xAxis, float yAxis) | 4808 | bool PixelMap::resize(float xAxis, float yAxis) |
| 4747 | { | 4809 | { |
| 4810 | + Size scaledSize; | ||
| 4811 | + if (!GetScaledSize(imageInfo_.size, xAxis, yAxis, scaledSize)) { | ||
| 4812 | + IMAGE_LOGE("resize invalid scale ratio"); | ||
| 4813 | + return false; | ||
| 4814 | + } | ||
| 4748 | if (IsYUV(imageInfo_.pixelFormat)) { | 4815 | if (IsYUV(imageInfo_.pixelFormat)) { |
| 4749 | IMAGE_LOGE("resize temp disabled for YUV data"); | 4816 | IMAGE_LOGE("resize temp disabled for YUV data"); |
| 4750 | return true; | 4817 | return true; |
| @@ -4767,6 +4834,18 @@ void PixelMap::translate(float xAxis, float yAxis) | |||
| 4767 | 4834 | ||
| 4768 | uint32_t PixelMap::Translate(float xAxis, float yAxis) | 4835 | uint32_t PixelMap::Translate(float xAxis, float yAxis) |
| 4769 | { | 4836 | { |
| 4837 | + if (!std::isfinite(xAxis) || !std::isfinite(yAxis)) { | ||
| 4838 | + IMAGE_LOGE("Invalid translate distance"); | ||
| 4839 | + return ERR_IMAGE_INVALID_PARAMETER; | ||
| 4840 | + } | ||
| 4841 | + int32_t translatedWidth = 0; | ||
| 4842 | + int32_t translatedHeight = 0; | ||
| 4843 | + if (!SafeCastToInt32(static_cast<double>(imageInfo_.size.width) + xAxis, translatedWidth) || | ||
| 4844 | + !SafeCastToInt32(static_cast<double>(imageInfo_.size.height) + yAxis, translatedHeight) || | ||
| 4845 | + translatedWidth <= 0 || translatedHeight <= 0) { | ||
| 4846 | + IMAGE_LOGE("Invalid translated image size"); | ||
| 4847 | + return ERR_IMAGE_INVALID_PARAMETER; | ||
| 4848 | + } | ||
| 4770 | if (imageInfo_.pixelFormat == PixelFormat::Y8) { | 4849 | if (imageInfo_.pixelFormat == PixelFormat::Y8) { |
| 4771 | IMAGE_LOGE("Translate does not support Y8"); | 4850 | IMAGE_LOGE("Translate does not support Y8"); |
| 4772 | return ERR_IMAGE_DATA_UNSUPPORT; | 4851 | return ERR_IMAGE_DATA_UNSUPPORT; |
| @@ -4790,6 +4869,10 @@ void PixelMap::rotate(float degrees) | |||
| 4790 | 4869 | ||
| 4791 | uint32_t PixelMap::Rotate(float degrees) | 4870 | uint32_t PixelMap::Rotate(float degrees) |
| 4792 | { | 4871 | { |
| 4872 | + if (!std::isfinite(degrees)) { | ||
| 4873 | + IMAGE_LOGE("Invalid rotate degrees"); | ||
| 4874 | + return ERR_IMAGE_INVALID_PARAMETER; | ||
| 4875 | + } | ||
| 4793 | if (ImageUtils::FloatEqual(degrees, 0.0f)) { | 4876 | if (ImageUtils::FloatEqual(degrees, 0.0f)) { |
| 4794 | return SUCCESS; | 4877 | return SUCCESS; |
| 4795 | } | 4878 | } |
| @@ -16,6 +16,8 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 20 | + | ||
| 19 | 21 | ||
| 20 | 22 | ||
| 21 | 23 | ||
| @@ -31,13 +33,18 @@ namespace Media { | |||
| 31 | class SLRMat { | 33 | class SLRMat { |
| 32 | public: | 34 | public: |
| 33 | SLRMat() = default; | 35 | SLRMat() = default; |
| 34 | - SLRMat(Size size, PixelFormat format, void *data, int32_t rowStride) | 36 | + SLRMat(Size size, PixelFormat format, void *data, int32_t rowStride, size_t bufferSize) |
| 35 | - :size_(size), format_(format), data_(data), rowStride_(rowStride) {} | 37 | + : size_(size), format_(format), data_(data), rowStride_(rowStride), bufferSize_(bufferSize) {} |
| 36 | ~SLRMat() = default; | 38 | ~SLRMat() = default; |
| 37 | - Size size_; | 39 | + |
| 38 | - PixelFormat format_; | 40 | + bool IsValid() const; |
| 39 | - void *data_; | 41 | + bool GetIndex(int32_t row, int32_t column, size_t &index) const; |
| 40 | - int32_t rowStride_; | 42 | + |
| 43 | + Size size_ = {}; | ||
| 44 | + PixelFormat format_ = PixelFormat::UNKNOWN; | ||
| 45 | + void *data_ = nullptr; | ||
| 46 | + int32_t rowStride_ = 0; | ||
| 47 | + size_t bufferSize_ = 0; | ||
| 41 | }; | 48 | }; |
| 42 | 49 | ||
| 43 | class SLRWeightKey { | 50 | class SLRWeightKey { |
| @@ -141,9 +148,9 @@ private: | |||
| 141 | class SLRProc { | 148 | class SLRProc { |
| 142 | public: | 149 | public: |
| 143 | static SLRWeightMat GetWeights(float coeff, int n); | 150 | static SLRWeightMat GetWeights(float coeff, int n); |
| 144 | - static void Serial(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y); | 151 | + static bool Serial(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y); |
| 145 | - static void Parallel(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y); | 152 | + static bool Parallel(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y); |
| 146 | - static void Laplacian(SLRMat &srcMat, void* data, float alpha); | 153 | + static bool Laplacian(const SLRMat &src, SLRMat &dst, float alpha); |
| 147 | }; | 154 | }; |
| 148 | } // namespace Media | 155 | } // namespace Media |
| 149 | } // namespace OHOS | 156 | } // namespace OHOS |
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | + | ||
| 18 | 19 | ||
| 19 | 20 | ||
| 20 | 21 | ||
| @@ -1085,6 +1086,7 @@ bool PostProc::RotateInRectangularSteps(PixelMap &pixelMap, float degrees, bool | |||
| 1085 | .size = imageInfo.size, | 1086 | .size = imageInfo.size, |
| 1086 | .stride = pixelMap.GetRowStride(), | 1087 | .stride = pixelMap.GetRowStride(), |
| 1087 | .pixelBytes = ImageUtils::GetPixelBytes(pixelMap.GetPixelFormat()), | 1088 | .pixelBytes = ImageUtils::GetPixelBytes(pixelMap.GetPixelFormat()), |
| 1089 | + .bufferSize = pixelMap.GetAllocationByteCount(), | ||
| 1088 | .addr = pixelMap.GetPixels(), | 1090 | .addr = pixelMap.GetPixels(), |
| 1089 | .context = pixelMap.GetFd(), | 1091 | .context = pixelMap.GetFd(), |
| 1090 | }; | 1092 | }; |
| @@ -1119,6 +1121,7 @@ bool PostProc::ScalePixelMapWithGPU(PixelMap &pixelMap, const Size &desiredSize, | |||
| 1119 | .size = imageInfo.size, | 1121 | .size = imageInfo.size, |
| 1120 | .stride = pixelMap.GetRowStride(), | 1122 | .stride = pixelMap.GetRowStride(), |
| 1121 | .pixelBytes = ImageUtils::GetPixelBytes(pixelMap.GetPixelFormat()), | 1123 | .pixelBytes = ImageUtils::GetPixelBytes(pixelMap.GetPixelFormat()), |
| 1124 | + .bufferSize = pixelMap.GetAllocationByteCount(), | ||
| 1122 | .addr = pixelMap.GetPixels(), | 1125 | .addr = pixelMap.GetPixels(), |
| 1123 | .context = pixelMap.GetFd(), | 1126 | .context = pixelMap.GetFd(), |
| 1124 | }; | 1127 | }; |
| @@ -1176,13 +1179,8 @@ float getLapFactor(const ImageInfo& imgInfo, const Size &desiredSize) | |||
| 1176 | return 0.15f; | 1179 | return 0.15f; |
| 1177 | } | 1180 | } |
| 1178 | 1181 | ||
| 1179 | -struct SLRContext { | 1182 | +bool ExecuteSLR(PixelMap& pixelMap, const Size& desiredSize, SLRMat &src, SLRMat &scaledDst, |
| 1180 | - void *data; | 1183 | + SLRMat *laplacianDst) |
| 1181 | - bool useLap; | ||
| 1182 | -}; | ||
| 1183 | - | ||
| 1184 | -bool ExecuteSLR(PixelMap& pixelMap, const Size& desiredSize, SLRMat &src, SLRMat &dst, | ||
| 1185 | - SLRContext scalingContext) | ||
| 1186 | { | 1184 | { |
| 1187 | ImageInfo imgInfo; | 1185 | ImageInfo imgInfo; |
| 1188 | pixelMap.GetImageInfo(imgInfo); | 1186 | pixelMap.GetImageInfo(imgInfo); |
| @@ -1190,18 +1188,95 @@ bool ExecuteSLR(PixelMap& pixelMap, const Size& desiredSize, SLRMat &src, SLRMat | |||
| 1190 | CHECK_ERROR_RETURN_RET_LOG(weightTuplePtr == nullptr, false, "PostProcExecuteSLR init failed"); | 1188 | CHECK_ERROR_RETURN_RET_LOG(weightTuplePtr == nullptr, false, "PostProcExecuteSLR init failed"); |
| 1191 | SLRWeightMat slrWeightX = std::get<0>(*weightTuplePtr); | 1189 | SLRWeightMat slrWeightX = std::get<0>(*weightTuplePtr); |
| 1192 | SLRWeightMat slrWeightY = std::get<1>(*weightTuplePtr); | 1190 | SLRWeightMat slrWeightY = std::get<1>(*weightTuplePtr); |
| 1191 | + bool success = false; | ||
| 1193 | if (ImageSystemProperties::GetSLRParallelEnabled()) { | 1192 | if (ImageSystemProperties::GetSLRParallelEnabled()) { |
| 1194 | - SLRProc::Parallel(src, dst, slrWeightX, slrWeightY); | 1193 | + success = SLRProc::Parallel(src, scaledDst, slrWeightX, slrWeightY); |
| 1195 | } else { | 1194 | } else { |
| 1196 | - SLRProc::Serial(src, dst, slrWeightX, slrWeightY); | 1195 | + success = SLRProc::Serial(src, scaledDst, slrWeightX, slrWeightY); |
| 1197 | } | 1196 | } |
| 1198 | - if (scalingContext.useLap) { | 1197 | + CHECK_ERROR_RETURN_RET_LOG(!success, false, "PostProcExecuteSLR scale failed"); |
| 1198 | + if (laplacianDst != nullptr) { | ||
| 1199 | float factor = getLapFactor(imgInfo, desiredSize); | 1199 | float factor = getLapFactor(imgInfo, desiredSize); |
| 1200 | - SLRProc::Laplacian(dst, scalingContext.data, factor); | 1200 | + CHECK_ERROR_RETURN_RET_LOG(!SLRProc::Laplacian(scaledDst, *laplacianDst, factor), false, |
| 1201 | + "PostProcExecuteSLR laplacian failed"); | ||
| 1201 | } | 1202 | } |
| 1202 | return true; | 1203 | return true; |
| 1203 | } | 1204 | } |
| 1204 | 1205 | ||
| 1206 | +static bool GetSLRMemoryLayout(AbsMemory &memory, const Size &size, int32_t pixelBytes, | ||
| 1207 | + size_t &bufferSize, int32_t &rowStride) | ||
| 1208 | +{ | ||
| 1209 | + CHECK_ERROR_RETURN_RET_LOG(memory.data.data == nullptr || pixelBytes <= 0, false, | ||
| 1210 | + "GetSLRMemoryLayout invalid memory"); | ||
| 1211 | + uint64_t rowStrideBytes = static_cast<uint64_t>(size.width) * static_cast<uint64_t>(pixelBytes); | ||
| 1212 | + bufferSize = memory.data.size; | ||
| 1213 | + if (memory.GetType() == AllocatorType::DMA_ALLOC) { | ||
| 1214 | + | ||
| 1215 | + auto surfaceBuffer = reinterpret_cast<SurfaceBuffer *>(memory.extend.data); | ||
| 1216 | + CHECK_ERROR_RETURN_RET_LOG(surfaceBuffer == nullptr, false, "GetSLRMemoryLayout surface buffer is null"); | ||
| 1217 | + rowStrideBytes = static_cast<uint64_t>(surfaceBuffer->GetStride()); | ||
| 1218 | + bufferSize = surfaceBuffer->GetSize(); | ||
| 1219 | + | ||
| 1220 | + return false; | ||
| 1221 | + | ||
| 1222 | + } | ||
| 1223 | + CHECK_ERROR_RETURN_RET_LOG(rowStrideBytes == 0 || | ||
| 1224 | + rowStrideBytes % static_cast<uint64_t>(pixelBytes) != 0, false, | ||
| 1225 | + "GetSLRMemoryLayout invalid row stride"); | ||
| 1226 | + const uint64_t rowStridePixels = rowStrideBytes / static_cast<uint64_t>(pixelBytes); | ||
| 1227 | + CHECK_ERROR_RETURN_RET_LOG(rowStridePixels > static_cast<uint64_t>(std::numeric_limits<int32_t>::max()), | ||
| 1228 | + false, "GetSLRMemoryLayout row stride overflow"); | ||
| 1229 | + rowStride = static_cast<int32_t>(rowStridePixels); | ||
| 1230 | + return true; | ||
| 1231 | +} | ||
| 1232 | + | ||
| 1233 | +struct SLRTargetCtx { | ||
| 1234 | + const Size &desiredSize; | ||
| 1235 | + int32_t pixelBytes; | ||
| 1236 | + PixelFormat format; | ||
| 1237 | + PixelMap &pixelMap; | ||
| 1238 | + uint32_t dstBufferSize; | ||
| 1239 | + bool useLap; | ||
| 1240 | + std::unique_ptr<AbsMemory> &m; | ||
| 1241 | + std::unique_ptr<AbsMemory> &lapMemory; | ||
| 1242 | + SLRMat &scaledDst; | ||
| 1243 | + SLRMat &finalDst; | ||
| 1244 | +}; | ||
| 1245 | + | ||
| 1246 | +static bool PrepareSLRTargets(SLRTargetCtx &ctx) | ||
| 1247 | +{ | ||
| 1248 | + ctx.m = nullptr; | ||
| 1249 | + ctx.lapMemory = CreateSLRMemory(ctx.pixelMap, ctx.dstBufferSize, ctx.desiredSize, ctx.m, ctx.useLap); | ||
| 1250 | + bool cond = ctx.m == nullptr || (ctx.useLap && (ctx.lapMemory == nullptr)); | ||
| 1251 | + CHECK_ERROR_RETURN_RET_LOG(cond, false, "pixelMap scale slr memory nullptr"); | ||
| 1252 | + AbsMemory *scaledMemory = ctx.useLap ? ctx.lapMemory.get() : ctx.m.get(); | ||
| 1253 | + size_t scaledBufferSize = 0; | ||
| 1254 | + int32_t scaledRowStride = 0; | ||
| 1255 | + cond = !GetSLRMemoryLayout(*scaledMemory, ctx.desiredSize, ctx.pixelBytes, scaledBufferSize, scaledRowStride); | ||
| 1256 | + if (cond) { | ||
| 1257 | + IMAGE_LOGE("ScalePixelMapWithSLR invalid scale target layout"); | ||
| 1258 | + ctx.m->Release(); | ||
| 1259 | + if (ctx.lapMemory) { | ||
| 1260 | + ctx.lapMemory->Release(); | ||
| 1261 | + } | ||
| 1262 | + return false; | ||
| 1263 | + } | ||
| 1264 | + ctx.scaledDst = SLRMat(ctx.desiredSize, ctx.format, scaledMemory->data.data, scaledRowStride, scaledBufferSize); | ||
| 1265 | + size_t finalBufferSize = 0; | ||
| 1266 | + int32_t finalRowStride = 0; | ||
| 1267 | + cond = !GetSLRMemoryLayout(*ctx.m, ctx.desiredSize, ctx.pixelBytes, finalBufferSize, finalRowStride); | ||
| 1268 | + if (cond) { | ||
| 1269 | + IMAGE_LOGE("ScalePixelMapWithSLR invalid final target layout"); | ||
| 1270 | + ctx.m->Release(); | ||
| 1271 | + if (ctx.lapMemory) { | ||
| 1272 | + ctx.lapMemory->Release(); | ||
| 1273 | + } | ||
| 1274 | + return false; | ||
| 1275 | + } | ||
| 1276 | + ctx.finalDst = SLRMat(ctx.desiredSize, ctx.format, ctx.m->data.data, finalRowStride, finalBufferSize); | ||
| 1277 | + return true; | ||
| 1278 | +} | ||
| 1279 | + | ||
| 1205 | bool PostProc::ScalePixelMapWithSLR(const Size &desiredSize, PixelMap &pixelMap, bool useLap) | 1280 | bool PostProc::ScalePixelMapWithSLR(const Size &desiredSize, PixelMap &pixelMap, bool useLap) |
| 1206 | { | 1281 | { |
| 1207 | ImageInfo imgInfo; | 1282 | ImageInfo imgInfo; |
| @@ -1211,23 +1286,28 @@ bool PostProc::ScalePixelMapWithSLR(const Size &desiredSize, PixelMap &pixelMap, | |||
| 1211 | useLap = useLap && ImageSystemProperties::GetSLRLaplacianEnabled(); | 1286 | useLap = useLap && ImageSystemProperties::GetSLRLaplacianEnabled(); |
| 1212 | ImageTrace imageTrace("ScalePixelMapWithSLR"); | 1287 | ImageTrace imageTrace("ScalePixelMapWithSLR"); |
| 1213 | int32_t pixelBytes = pixelMap.GetPixelBytes(); | 1288 | int32_t pixelBytes = pixelMap.GetPixelBytes(); |
| 1214 | - SLRMat src(imgInfo.size, imgInfo.pixelFormat, pixelMap.GetWritablePixels(), pixelMap.GetRowStride() / pixelBytes); | 1289 | + const int32_t srcRowStrideBytes = pixelMap.GetRowStride(); |
| 1215 | - uint32_t dstBufferSize = desiredSize.height * desiredSize.width * pixelBytes; | 1290 | + CHECK_ERROR_RETURN_RET_LOG(srcRowStrideBytes <= 0 || srcRowStrideBytes % pixelBytes != 0, false, |
| 1291 | + "ScalePixelMapWithSLR invalid source row stride"); | ||
| 1292 | + SLRMat src(imgInfo.size, imgInfo.pixelFormat, pixelMap.GetWritablePixels(), srcRowStrideBytes / pixelBytes, | ||
| 1293 | + pixelMap.GetAllocationByteCount()); | ||
| 1294 | + CHECK_ERROR_RETURN_RET_LOG(!src.IsValid(), false, "ScalePixelMapWithSLR invalid source buffer layout"); | ||
| 1295 | + const uint64_t dstBufferSize64 = static_cast<uint64_t>(desiredSize.height) * | ||
| 1296 | + static_cast<uint64_t>(desiredSize.width) * static_cast<uint64_t>(pixelBytes); | ||
| 1297 | + CHECK_ERROR_RETURN_RET_LOG(dstBufferSize64 > std::numeric_limits<uint32_t>::max(), false, | ||
| 1298 | + "ScalePixelMapWithSLR desired size overflow"); | ||
| 1299 | + uint32_t dstBufferSize = static_cast<uint32_t>(dstBufferSize64); | ||
| 1216 | std::unique_ptr<AbsMemory> m = nullptr; | 1300 | std::unique_ptr<AbsMemory> m = nullptr; |
| 1217 | - auto lapMemory = CreateSLRMemory(pixelMap, dstBufferSize, desiredSize, m, useLap); | 1301 | + std::unique_ptr<AbsMemory> lapMemory = nullptr; |
| 1218 | - cond = m == nullptr || (useLap && (lapMemory == nullptr)); | 1302 | + SLRMat scaledDst; |
| 1219 | - CHECK_ERROR_RETURN_RET_LOG(cond, false, "pixelMap scale slr memory nullptr"); | 1303 | + SLRMat finalDst; |
| 1220 | - size_t rowStride; | 1304 | + SLRTargetCtx ctx{desiredSize, pixelBytes, imgInfo.pixelFormat, pixelMap, dstBufferSize, useLap, |
| 1221 | - if (m->GetType() == AllocatorType::DMA_ALLOC) { | 1305 | + m, lapMemory, scaledDst, finalDst}; |
| 1222 | -#if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM) | 1306 | + if (!PrepareSLRTargets(ctx)) { |
| 1223 | - rowStride = reinterpret_cast<SurfaceBuffer*>(m->extend.data)->GetStride(); | 1307 | + return false; |
| 1224 | - | ||
| 1225 | - } else { | ||
| 1226 | - rowStride = desiredSize.width * pixelBytes; | ||
| 1227 | } | 1308 | } |
| 1228 | - void *data = useLap ? lapMemory->data.data : m->data.data; | 1309 | + SLRMat *laplacianDst = useLap ? &finalDst : nullptr; |
| 1229 | - SLRMat dst({desiredSize.width, desiredSize.height}, imgInfo.pixelFormat, data, rowStride / pixelBytes); | 1310 | + if (!ExecuteSLR(pixelMap, desiredSize, src, scaledDst, laplacianDst)) { |
| 1230 | - if (!ExecuteSLR(pixelMap, desiredSize, src, dst, {m->data.data, useLap})) { | ||
| 1231 | m->Release(); | 1311 | m->Release(); |
| 1232 | if (useLap && lapMemory) { | 1312 | if (useLap && lapMemory) { |
| 1233 | lapMemory->Release(); | 1313 | lapMemory->Release(); |
| @@ -15,6 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | + | ||
| 18 | 19 | ||
| 19 | 20 | ||
| 20 | 21 | ||
| @@ -36,6 +37,35 @@ constexpr float EPSILON = 1e-6; | |||
| 36 | constexpr int FFRT_THREAD_LIMIT = 8; | 37 | constexpr int FFRT_THREAD_LIMIT = 8; |
| 37 | constexpr int SLR_MIN_RADIUS = 2; | 38 | constexpr int SLR_MIN_RADIUS = 2; |
| 38 | constexpr int SLR_WEIGHT_SPAN_FACTOR = 2; | 39 | constexpr int SLR_WEIGHT_SPAN_FACTOR = 2; |
| 40 | +constexpr size_t SLR_PIXEL_BYTES = sizeof(uint32_t); | ||
| 41 | + | ||
| 42 | +bool SLRMat::IsValid() const | ||
| 43 | +{ | ||
| 44 | + if (data_ == nullptr || size_.width <= 0 || size_.height <= 0 || rowStride_ <= 0 || | ||
| 45 | + rowStride_ < size_.width) { | ||
| 46 | + return false; | ||
| 47 | + } | ||
| 48 | + const size_t stride = static_cast<size_t>(rowStride_); | ||
| 49 | + const size_t height = static_cast<size_t>(size_.height); | ||
| 50 | + const size_t width = static_cast<size_t>(size_.width); | ||
| 51 | + const uint64_t requiredPixels = static_cast<uint64_t>(height - 1) * static_cast<uint64_t>(stride) + | ||
| 52 | + static_cast<uint64_t>(width); | ||
| 53 | + return requiredPixels <= static_cast<uint64_t>(bufferSize_ / SLR_PIXEL_BYTES); | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | +bool SLRMat::GetIndex(int32_t row, int32_t column, size_t &index) const | ||
| 57 | +{ | ||
| 58 | + if (row < 0 || column < 0 || row >= size_.height || column >= size_.width || rowStride_ <= 0) { | ||
| 59 | + return false; | ||
| 60 | + } | ||
| 61 | + const uint64_t index64 = static_cast<uint64_t>(row) * static_cast<uint64_t>(rowStride_) + | ||
| 62 | + static_cast<uint64_t>(column); | ||
| 63 | + if (index64 >= static_cast<uint64_t>(bufferSize_ / SLR_PIXEL_BYTES)) { | ||
| 64 | + return false; | ||
| 65 | + } | ||
| 66 | + index = static_cast<size_t>(index64); | ||
| 67 | + return true; | ||
| 68 | +} | ||
| 39 | 69 | ||
| 40 | float GetSLRFactor(float x, int a) | 70 | float GetSLRFactor(float x, int a) |
| 41 | { | 71 | { |
| @@ -93,8 +123,7 @@ SLRWeightMat SLRProc::GetWeights(float coeff, int n) | |||
| 93 | bool SLRCheck(const SLRMat &src, const SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y) | 123 | bool SLRCheck(const SLRMat &src, const SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y) |
| 94 | { | 124 | { |
| 95 | CHECK_ERROR_RETURN_RET(x == nullptr || y == nullptr, false); | 125 | CHECK_ERROR_RETURN_RET(x == nullptr || y == nullptr, false); |
| 96 | - CHECK_ERROR_RETURN_RET(src.size_.width == 0 || src.size_.height == 0, false); | 126 | + CHECK_ERROR_RETURN_RET(!src.IsValid() || !dst.IsValid(), false); |
| 97 | - CHECK_ERROR_RETURN_RET(dst.size_.width == 0 || dst.size_.height == 0, false); | ||
| 98 | CHECK_ERROR_RETURN_RET((*x).empty() || (*y).empty(), false); | 127 | CHECK_ERROR_RETURN_RET((*x).empty() || (*y).empty(), false); |
| 99 | CHECK_ERROR_RETURN_RET(static_cast<int>((*x).size()) != dst.size_.width, false); | 128 | CHECK_ERROR_RETURN_RET(static_cast<int>((*x).size()) != dst.size_.width, false); |
| 100 | CHECK_ERROR_RETURN_RET(static_cast<int>((*y).size()) != dst.size_.height, false); | 129 | CHECK_ERROR_RETURN_RET(static_cast<int>((*y).size()) != dst.size_.height, false); |
| @@ -105,8 +134,12 @@ bool SLRCheck(const SLRMat &src, const SLRMat &dst, const SLRWeightMat &x, const | |||
| 105 | float taoY = 1 / coeffY; | 134 | float taoY = 1 / coeffY; |
| 106 | int aX = std::max(SLR_MIN_RADIUS, static_cast<int>(std::floor(taoX))); | 135 | int aX = std::max(SLR_MIN_RADIUS, static_cast<int>(std::floor(taoX))); |
| 107 | int aY = std::max(SLR_MIN_RADIUS, static_cast<int>(std::floor(taoY))); | 136 | int aY = std::max(SLR_MIN_RADIUS, static_cast<int>(std::floor(taoY))); |
| 108 | - CHECK_ERROR_RETURN_RET((*x)[0].size() < static_cast<size_t>(SLR_WEIGHT_SPAN_FACTOR * aY), false); | 137 | + const size_t minXWeightSize = static_cast<size_t>(SLR_WEIGHT_SPAN_FACTOR * aY); |
| 109 | - CHECK_ERROR_RETURN_RET((*y)[0].size() < static_cast<size_t>(SLR_WEIGHT_SPAN_FACTOR * aX), false); | 138 | + const size_t minYWeightSize = static_cast<size_t>(SLR_WEIGHT_SPAN_FACTOR * aX); |
| 139 | + CHECK_ERROR_RETURN_RET(std::any_of(x->begin(), x->end(), | ||
| 140 | + [minXWeightSize](const auto &weights) { return weights.size() < minXWeightSize; }), false); | ||
| 141 | + CHECK_ERROR_RETURN_RET(std::any_of(y->begin(), y->end(), | ||
| 142 | + [minYWeightSize](const auto &weights) { return weights.size() < minYWeightSize; }), false); | ||
| 110 | return true; | 143 | return true; |
| 111 | } | 144 | } |
| 112 | 145 | ||
| @@ -146,19 +179,18 @@ bool SLRBoxCheck(const SLRSliceKey &key, const SLRMat &src, const SLRMat &dst, c | |||
| 146 | int aX = std::max(SLR_MIN_RADIUS, static_cast<int>(std::floor(taoX))); | 179 | int aX = std::max(SLR_MIN_RADIUS, static_cast<int>(std::floor(taoX))); |
| 147 | int aY = std::max(SLR_MIN_RADIUS, static_cast<int>(std::floor(taoY))); | 180 | int aY = std::max(SLR_MIN_RADIUS, static_cast<int>(std::floor(taoY))); |
| 148 | if (key.y >= static_cast<int>((*x).size()) || | 181 | if (key.y >= static_cast<int>((*x).size()) || |
| 149 | - static_cast<int>((*x)[0].size()) < SLR_WEIGHT_SPAN_FACTOR * aY) { | 182 | + static_cast<int>((*x)[key.y].size()) < SLR_WEIGHT_SPAN_FACTOR * aY) { |
| 150 | IMAGE_LOGE("SLRBoxCheck h_y error:%{public}zu, %{public}d", (*x).size(), aY); | 183 | IMAGE_LOGE("SLRBoxCheck h_y error:%{public}zu, %{public}d", (*x).size(), aY); |
| 151 | return false; | 184 | return false; |
| 152 | } | 185 | } |
| 153 | if (key.x >= static_cast<int>((*y).size()) || | 186 | if (key.x >= static_cast<int>((*y).size()) || |
| 154 | - static_cast<int>((*y)[0].size()) < SLR_WEIGHT_SPAN_FACTOR * aX) { | 187 | + static_cast<int>((*y)[key.x].size()) < SLR_WEIGHT_SPAN_FACTOR * aX) { |
| 155 | IMAGE_LOGE("SLRBoxCheck h_x error:%{public}zu, %{public}d", (*y).size(), aX); | 188 | IMAGE_LOGE("SLRBoxCheck h_x error:%{public}zu, %{public}d", (*y).size(), aX); |
| 156 | return false; | 189 | return false; |
| 157 | } | 190 | } |
| 158 | - int dstIndex = key.x * dst.rowStride_ + key.y; | 191 | + size_t dstIndex = 0; |
| 159 | - int maxDstSize = dstM * dst.rowStride_; // the rowStride_ here represents pixel | 192 | + CHECK_ERROR_RETURN_RET_LOG(!dst.GetIndex(key.x, key.y, dstIndex), false, |
| 160 | - CHECK_ERROR_RETURN_RET_LOG(dstIndex >= maxDstSize, false, | 193 | + "SLRBoxCheck dst index error:%{public}d, %{public}d", key.x, key.y); |
| 161 | - "SLRBoxCheck dst index error:%{public}d, %{public}d", dstIndex, maxDstSize); | ||
| 162 | return true; | 194 | return true; |
| 163 | } | 195 | } |
| 164 | 196 | ||
| @@ -184,16 +216,15 @@ void SLRBox(const SLRSliceKey &key, const SLRMat &src, SLRMat &dst, const SLRWei | |||
| 184 | int cStart = etaJ - aY + 1; | 216 | int cStart = etaJ - aY + 1; |
| 185 | int cEnd = etaJ + aY; | 217 | int cEnd = etaJ + aY; |
| 186 | float rgba[4]{ .0f, .0f, .0f, .0f }; | 218 | float rgba[4]{ .0f, .0f, .0f, .0f }; |
| 187 | - int maxSrcSize = srcM * src.rowStride_; // the rowStride_ here represents pixel | ||
| 188 | for (int r = rStart; r <= rEnd; ++r) { | 219 | for (int r = rStart; r <= rEnd; ++r) { |
| 189 | int nR = min(max(0, r), srcM - 1); | 220 | int nR = min(max(0, r), srcM - 1); |
| 190 | for (int c = cStart; c <= cEnd; ++c) { | 221 | for (int c = cStart; c <= cEnd; ++c) { |
| 191 | int nC = min(max(0, c), srcN - 1); | 222 | int nC = min(max(0, c), srcN - 1); |
| 192 | auto w = (*x)[key.y][c - cStart]; | 223 | auto w = (*x)[key.y][c - cStart]; |
| 193 | w *= (*y)[key.x][r - rStart]; | 224 | w *= (*y)[key.x][r - rStart]; |
| 194 | - int srcIndex = nR * src.rowStride_ + nC; | 225 | + size_t srcIndex = 0; |
| 195 | - if (srcIndex < 0 || srcIndex >= maxSrcSize) { | 226 | + if (!src.GetIndex(nR, nC, srcIndex)) { |
| 196 | - IMAGE_LOGE("SLRBox src index error:%{public}d, %{public}d", srcIndex, maxSrcSize); | 227 | + IMAGE_LOGE("SLRBox src index error:%{public}d, %{public}d", nR, nC); |
| 197 | return; | 228 | return; |
| 198 | } | 229 | } |
| 199 | uint32_t color = *(srcArr + srcIndex); | 230 | uint32_t color = *(srcArr + srcIndex); |
| @@ -207,29 +238,33 @@ void SLRBox(const SLRSliceKey &key, const SLRMat &src, SLRMat &dst, const SLRWei | |||
| 207 | uint32_t g = SLRCast(rgba[1]); | 238 | uint32_t g = SLRCast(rgba[1]); |
| 208 | uint32_t b = SLRCast(rgba[2]); // 2 rgba | 239 | uint32_t b = SLRCast(rgba[2]); // 2 rgba |
| 209 | uint32_t a = SLRCast(rgba[3]); // 3 rgba | 240 | uint32_t a = SLRCast(rgba[3]); // 3 rgba |
| 210 | - dstArr[key.x * dst.rowStride_ + key.y] = (r << 24) | (g << 16) | (b << 8) | a; // 24 16 8 rgba | 241 | + size_t dstIndex = 0; |
| 242 | + CHECK_ERROR_RETURN(!dst.GetIndex(key.x, key.y, dstIndex)); | ||
| 243 | + dstArr[dstIndex] = (r << 24) | (g << 16) | (b << 8) | a; // 24 16 8 rgba | ||
| 211 | } | 244 | } |
| 212 | 245 | ||
| 213 | -void SLRProc::Laplacian(SLRMat &srcMat, void* data, float alpha) | 246 | +bool SLRProc::Laplacian(const SLRMat &src, SLRMat &dst, float alpha) |
| 214 | { | 247 | { |
| 215 | - IMAGE_LOGD("Laplacian pixelMap SLR:width=%{public}d,height=%{public}d,alpha=%{public}f", srcMat.size_.width, | 248 | + IMAGE_LOGD("Laplacian pixelMap SLR:width=%{public}d,height=%{public}d,alpha=%{public}f", src.size_.width, |
| 216 | - srcMat.size_.height, alpha); | 249 | + src.size_.height, alpha); |
| 217 | - CHECK_ERROR_RETURN_LOG(data == nullptr, "SLRProc::Laplacian create memory failed"); | 250 | + CHECK_ERROR_RETURN_RET_LOG(!src.IsValid() || !dst.IsValid() || src.size_.width != dst.size_.width || |
| 218 | - const int m = srcMat.size_.height; | 251 | + src.size_.height != dst.size_.height, false, "SLRProc::Laplacian invalid buffer layout"); |
| 219 | - const int n = srcMat.size_.width; | 252 | + const int m = src.size_.height; |
| 220 | - const int stride = srcMat.rowStride_; | 253 | + const int n = src.size_.width; |
| 221 | - uint32_t* srcArr = static_cast<uint32_t*>(srcMat.data_); | 254 | + uint32_t* srcArr = static_cast<uint32_t*>(src.data_); |
| 222 | - uint32_t* dstArr = static_cast<uint32_t*>(data); | 255 | + uint32_t* dstArr = static_cast<uint32_t*>(dst.data_); |
| 223 | 256 | ||
| 224 | - auto getPixel = [&](int i, int j) ->uint32_t { | 257 | + auto getPixel = [&](int i, int j) -> uint32_t { |
| 225 | i = std::clamp(i, 0, m - 1); | 258 | i = std::clamp(i, 0, m - 1); |
| 226 | j = std::clamp(j, 0, n - 1); | 259 | j = std::clamp(j, 0, n - 1); |
| 227 | - return *(srcArr + i * stride + j); | 260 | + size_t index = 0; |
| 261 | + if (!src.GetIndex(i, j, index)) { | ||
| 262 | + return 0; | ||
| 263 | + } | ||
| 264 | + return srcArr[index]; | ||
| 228 | }; | 265 | }; |
| 229 | 266 | ||
| 230 | - auto extract = [](uint32_t color, int shift) -> uint32_t { | 267 | + auto extract = [](uint32_t color, int shift) -> uint32_t { return (color >> shift) & 0xFF; }; |
| 231 | - return (color >> shift) & 0xFF; | ||
| 232 | - }; | ||
| 233 | for (int i = 0; i < m; i++) { | 268 | for (int i = 0; i < m; i++) { |
| 234 | for (int j = 0; j < n; j++) { | 269 | for (int j = 0; j < n; j++) { |
| 235 | const uint32_t pixels[5] = { | 270 | const uint32_t pixels[5] = { |
| @@ -246,23 +281,26 @@ void SLRProc::Laplacian(SLRMat &srcMat, void* data, float alpha) | |||
| 246 | 281 | ||
| 247 | auto delta = [&](uint32_t c, int shift) -> int { | 282 | auto delta = [&](uint32_t c, int shift) -> int { |
| 248 | return 4 * c | 283 | return 4 * c |
| 249 | - - extract(pixels[1], shift) // l left | 284 | + - extract(pixels[1], shift) // l left |
| 250 | - - extract(pixels[2], shift) // 2 right | 285 | + - extract(pixels[2], shift) // 2 right |
| 251 | - - extract(pixels[3], shift) // 3 up | 286 | + - extract(pixels[3], shift) // 3 up |
| 252 | - - extract(pixels[4], shift); // 4 down | 287 | + - extract(pixels[4], shift); // 4 down |
| 253 | }; | 288 | }; |
| 254 | - dstArr[i * stride + j] = | 289 | + size_t dstIndex = 0; |
| 290 | + CHECK_ERROR_RETURN_RET(!dst.GetIndex(i, j, dstIndex), false); | ||
| 291 | + dstArr[dstIndex] = | ||
| 255 | (SLRCast(cr + alpha * delta(cr, 24)) << 24) | // 24 r | 292 | (SLRCast(cr + alpha * delta(cr, 24)) << 24) | // 24 r |
| 256 | (SLRCast(cg + alpha * delta(cg, 16)) << 16) | // 16 g | 293 | (SLRCast(cg + alpha * delta(cg, 16)) << 16) | // 16 g |
| 257 | (SLRCast(cb + alpha * delta(cb, 8)) << 8) | // 8 b | 294 | (SLRCast(cb + alpha * delta(cb, 8)) << 8) | // 8 b |
| 258 | ca; | 295 | ca; |
| 259 | } | 296 | } |
| 260 | } | 297 | } |
| 298 | + return true; | ||
| 261 | } | 299 | } |
| 262 | 300 | ||
| 263 | -void SLRProc::Serial(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y) | 301 | +bool SLRProc::Serial(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y) |
| 264 | { | 302 | { |
| 265 | - CHECK_ERROR_RETURN_LOG(!SLRCheck(src, dst, x, y), "SLRProc::Serial param error"); | 303 | + CHECK_ERROR_RETURN_RET_LOG(!SLRCheck(src, dst, x, y), false, "SLRProc::Serial param error"); |
| 266 | 304 | ||
| 267 | int m = dst.size_.height; | 305 | int m = dst.size_.height; |
| 268 | int n = dst.size_.width; | 306 | int n = dst.size_.width; |
| @@ -272,6 +310,7 @@ void SLRProc::Serial(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, cons | |||
| 272 | SLRBox(key, src, dst, x, y); | 310 | SLRBox(key, src, dst, x, y); |
| 273 | } | 311 | } |
| 274 | } | 312 | } |
| 313 | + return true; | ||
| 275 | } | 314 | } |
| 276 | 315 | ||
| 277 | inline void SLRSubtask(const SLRSliceKey &key, const SLRMat &src, SLRMat &dst, | 316 | inline void SLRSubtask(const SLRSliceKey &key, const SLRMat &src, SLRMat &dst, |
| @@ -288,10 +327,10 @@ inline void SLRSubtask(const SLRSliceKey &key, const SLRMat &src, SLRMat &dst, | |||
| 288 | } | 327 | } |
| 289 | } | 328 | } |
| 290 | 329 | ||
| 291 | -void SLRProc::Parallel(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y) | 330 | +bool SLRProc::Parallel(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y) |
| 292 | { | 331 | { |
| 293 | 332 | ||
| 294 | - CHECK_ERROR_RETURN_LOG(!SLRCheck(src, dst, x, y), "SLRProc::Parallel param error"); | 333 | + CHECK_ERROR_RETURN_RET_LOG(!SLRCheck(src, dst, x, y), false, "SLRProc::Parallel param error"); |
| 295 | const int maxThread = 16; // 16 max thread size | 334 | const int maxThread = 16; // 16 max thread size |
| 296 | int m = dst.size_.height; | 335 | int m = dst.size_.height; |
| 297 | int n = dst.size_.width; | 336 | int n = dst.size_.width; |
| @@ -323,8 +362,9 @@ void SLRProc::Parallel(const SLRMat &src, SLRMat &dst, const SLRWeightMat &x, co | |||
| 323 | 362 | ||
| 324 | ffrt::wait(ffrtHandles); | 363 | ffrt::wait(ffrtHandles); |
| 325 | ffrt::wait(ffrtHandles1); | 364 | ffrt::wait(ffrtHandles1); |
| 365 | + return true; | ||
| 326 | 366 | ||
| 327 | - SLRProc::Serial(src, dst, x, y); | 367 | + return SLRProc::Serial(src, dst, x, y); |
| 328 | 368 | ||
| 329 | } | 369 | } |
| 330 | } // namespace Media | 370 | } // namespace Media |
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| @@ -158,6 +159,7 @@ struct GlImageInfo { | |||
| 158 | Size size; | 159 | Size size; |
| 159 | int32_t stride; | 160 | int32_t stride; |
| 160 | int pixelBytes; | 161 | int pixelBytes; |
| 162 | + size_t bufferSize = 0; | ||
| 161 | const uint8_t *addr = nullptr; | 163 | const uint8_t *addr = nullptr; |
| 162 | void *context = nullptr; | 164 | void *context = nullptr; |
| 163 | void *outdata = nullptr; | 165 | void *outdata = nullptr; |
| @@ -61,7 +61,7 @@ public: | |||
| 61 | 61 | ||
| 62 | bool Init(); | 62 | bool Init(); |
| 63 | 63 | ||
| 64 | - void MakeCurrent(EGLSurface surface) const; | 64 | + bool MakeCurrent(EGLSurface surface) const; |
| 65 | 65 | ||
| 66 | bool MakeCurrentSimple(bool needCurrent); | 66 | bool MakeCurrentSimple(bool needCurrent); |
| 67 | 67 | ||
| @@ -59,6 +59,7 @@ private: | |||
| 59 | bool ResizeScaleWithGL(); | 59 | bool ResizeScaleWithGL(); |
| 60 | bool ReadEndData(char *targetData, GLuint &writeTexId); | 60 | bool ReadEndData(char *targetData, GLuint &writeTexId); |
| 61 | bool ReadEndDMAData(void *surfaceBuffer, GLuint &writeTexId); | 61 | bool ReadEndDMAData(void *surfaceBuffer, GLuint &writeTexId); |
| 62 | + void AbandonGLResources() noexcept; | ||
| 62 | void Clear() noexcept; | 63 | void Clear() noexcept; |
| 63 | 64 | ||
| 64 | private: | 65 | private: |
| @@ -282,19 +282,34 @@ inline bool IsValidGlTransferSize(const Size &size) | |||
| 282 | size.width <= MAX_GL_TRANSFER_DIMENSION && size.height <= MAX_GL_TRANSFER_DIMENSION; | 282 | size.width <= MAX_GL_TRANSFER_DIMENSION && size.height <= MAX_GL_TRANSFER_DIMENSION; |
| 283 | } | 283 | } |
| 284 | 284 | ||
| 285 | -inline bool CopyStridedToLinear(const uint8_t *src, int32_t srcStride, int32_t height, size_t rowBytes, | 285 | +inline bool ValidateStridedBufferSize(size_t bufferSize, int32_t stride, int32_t height, size_t rowBytes) |
| 286 | - char *dst, size_t dstSize) | 286 | +{ |
| 287 | + if (stride <= 0 || height <= 0 || rowBytes == 0 || rowBytes > static_cast<size_t>(stride)) { | ||
| 288 | + return false; | ||
| 289 | + } | ||
| 290 | + const size_t rowsBeforeLast = static_cast<size_t>(height - 1); | ||
| 291 | + const size_t strideSize = static_cast<size_t>(stride); | ||
| 292 | + if (rowsBeforeLast > (std::numeric_limits<size_t>::max() - rowBytes) / strideSize) { | ||
| 293 | + return false; | ||
| 294 | + } | ||
| 295 | + return rowsBeforeLast * strideSize + rowBytes <= bufferSize; | ||
| 296 | +} | ||
| 297 | + | ||
| 298 | +inline bool CopyStridedToLinear(const uint8_t *src, size_t srcSize, int32_t srcStride, int32_t height, | ||
| 299 | + size_t rowBytes, char *dst, size_t dstSize) | ||
| 287 | { | 300 | { |
| 288 | if (src == nullptr || dst == nullptr || srcStride <= 0 || height <= 0 || rowBytes == 0) { | 301 | if (src == nullptr || dst == nullptr || srcStride <= 0 || height <= 0 || rowBytes == 0) { |
| 289 | return false; | 302 | return false; |
| 290 | } | 303 | } |
| 304 | + if (!ValidateStridedBufferSize(srcSize, srcStride, height, rowBytes) || | ||
| 305 | + static_cast<size_t>(height) > dstSize / rowBytes) { | ||
| 306 | + return false; | ||
| 307 | + } | ||
| 291 | for (int32_t i = 0; i < height; ++i) { | 308 | for (int32_t i = 0; i < height; ++i) { |
| 292 | const size_t rowOffset = rowBytes * static_cast<size_t>(i); | 309 | const size_t rowOffset = rowBytes * static_cast<size_t>(i); |
| 293 | - if (rowOffset > dstSize || dstSize - rowOffset < rowBytes) { | 310 | + const size_t srcOffset = static_cast<size_t>(srcStride) * static_cast<size_t>(i); |
| 294 | - return false; | ||
| 295 | - } | ||
| 296 | if (memcpy_s(dst + rowOffset, dstSize - rowOffset, | 311 | if (memcpy_s(dst + rowOffset, dstSize - rowOffset, |
| 297 | - src + static_cast<size_t>(srcStride) * static_cast<size_t>(i), rowBytes) != EOK) { | 312 | + src + srcOffset, rowBytes) != EOK) { |
| 298 | return false; | 313 | return false; |
| 299 | } | 314 | } |
| 300 | } | 315 | } |
| @@ -55,6 +55,7 @@ public: | |||
| 55 | } | 55 | } |
| 56 | virtual bool Use() { return false; } | 56 | virtual bool Use() { return false; } |
| 57 | virtual bool Clear() = 0; | 57 | virtual bool Clear() = 0; |
| 58 | + virtual void Abandon(); | ||
| 58 | GLuint &GetReadTexId() | 59 | GLuint &GetReadTexId() |
| 59 | { | 60 | { |
| 60 | return readTexId_; | 61 | return readTexId_; |
| @@ -115,6 +116,7 @@ public: | |||
| 115 | bool Build() override; | 116 | bool Build() override; |
| 116 | bool LoadProgram() override; | 117 | bool LoadProgram() override; |
| 117 | bool Clear() override; | 118 | bool Clear() override; |
| 119 | + void Abandon() override; | ||
| 118 | private: | 120 | private: |
| 119 | GLuint vbo_ = 0U; | 121 | GLuint vbo_ = 0U; |
| 120 | }; | 122 | }; |
| @@ -156,6 +158,7 @@ public: | |||
| 156 | bool SetParams(const GPUTransformData &transformData) override; | 158 | bool SetParams(const GPUTransformData &transformData) override; |
| 157 | bool Use() override; | 159 | bool Use() override; |
| 158 | bool Clear() override; | 160 | bool Clear() override; |
| 161 | + void Abandon() override; | ||
| 159 | void SetEglImage(EGLImageKHR eglImage) | 162 | void SetEglImage(EGLImageKHR eglImage) |
| 160 | { | 163 | { |
| 161 | eglImage_ = eglImage; | 164 | eglImage_ = eglImage; |
| @@ -59,7 +59,7 @@ public: | |||
| 59 | 59 | ||
| 60 | bool Init(); | 60 | bool Init(); |
| 61 | 61 | ||
| 62 | - void MakeCurrent(EGLSurface surface) const; | 62 | + bool MakeCurrent(EGLSurface surface) const; |
| 63 | 63 | ||
| 64 | sk_sp<GrDirectContext> GetGrContext() const | 64 | sk_sp<GrDirectContext> GetGrContext() const |
| 65 | { | 65 | { |
| @@ -95,8 +95,14 @@ bool PixelMapGlContext::InitEGLContext() | |||
| 95 | eglContext_ = EGL_NO_CONTEXT; | 95 | eglContext_ = EGL_NO_CONTEXT; |
| 96 | return false; | 96 | return false; |
| 97 | } | 97 | } |
| 98 | + if (!MakeCurrent(pbufferSurface_)) { | ||
| 99 | + (void)eglDestroySurface(eglDisplay_, pbufferSurface_); | ||
| 100 | + (void)eglDestroyContext(eglDisplay_, eglContext_); | ||
| 101 | + pbufferSurface_ = EGL_NO_SURFACE; | ||
| 102 | + eglContext_ = EGL_NO_CONTEXT; | ||
| 103 | + return false; | ||
| 104 | + } | ||
| 98 | ++g_contextRefCount; | 105 | ++g_contextRefCount; |
| 99 | - MakeCurrent(pbufferSurface_); | ||
| 100 | 106 | ||
| 101 | return true; | 107 | return true; |
| 102 | } | 108 | } |
| @@ -143,25 +149,38 @@ bool PixelMapGlContext::MakeCurrentSimple(bool needCurrent) | |||
| 143 | return true; | 149 | return true; |
| 144 | } | 150 | } |
| 145 | 151 | ||
| 146 | -void PixelMapGlContext::MakeCurrent(EGLSurface surface) const | 152 | +bool PixelMapGlContext::MakeCurrent(EGLSurface surface) const |
| 147 | { | 153 | { |
| 148 | if (eglDisplay_ == EGL_NO_DISPLAY || eglContext_ == EGL_NO_CONTEXT) { | 154 | if (eglDisplay_ == EGL_NO_DISPLAY || eglContext_ == EGL_NO_CONTEXT) { |
| 149 | IMAGE_LOGE("PixelMapGlContext::MakeCurrent invalid egl context"); | 155 | IMAGE_LOGE("PixelMapGlContext::MakeCurrent invalid egl context"); |
| 150 | - return; | 156 | + return false; |
| 151 | } | 157 | } |
| 152 | EGLSurface currSurface = surface; | 158 | EGLSurface currSurface = surface; |
| 153 | if (currSurface == EGL_NO_SURFACE) { | 159 | if (currSurface == EGL_NO_SURFACE) { |
| 154 | currSurface = pbufferSurface_; | 160 | currSurface = pbufferSurface_; |
| 155 | } | 161 | } |
| 162 | + if (currSurface == EGL_NO_SURFACE) { | ||
| 163 | + IMAGE_LOGE("PixelMapGlContext::MakeCurrent invalid egl surface"); | ||
| 164 | + return false; | ||
| 165 | + } | ||
| 156 | 166 | ||
| 157 | if (eglMakeCurrent(eglDisplay_, currSurface, currSurface, eglContext_) != EGL_TRUE) { | 167 | if (eglMakeCurrent(eglDisplay_, currSurface, currSurface, eglContext_) != EGL_TRUE) { |
| 168 | + const EGLint makeCurrentError = eglGetError(); | ||
| 158 | EGLint surfaceId = -1; | 169 | EGLint surfaceId = -1; |
| 159 | - eglQuerySurface(eglDisplay_, surface, EGL_CONFIG_ID, &surfaceId); | 170 | + if (eglQuerySurface(eglDisplay_, currSurface, EGL_CONFIG_ID, &surfaceId) != EGL_TRUE) { |
| 171 | + IMAGE_LOGE( | ||
| 172 | + "PixelMapGlContext::MakeCurrent failed, error is %{public}x, query surface failed %{public}x", | ||
| 173 | + makeCurrentError, | ||
| 174 | + eglGetError()); | ||
| 175 | + return false; | ||
| 176 | + } | ||
| 160 | IMAGE_LOGE( | 177 | IMAGE_LOGE( |
| 161 | "PixelMapGlContext::MakeCurrent failed for eglSurface %{public}d, error is %{public}x", | 178 | "PixelMapGlContext::MakeCurrent failed for eglSurface %{public}d, error is %{public}x", |
| 162 | surfaceId, | 179 | surfaceId, |
| 163 | - eglGetError()); | 180 | + makeCurrentError); |
| 181 | + return false; | ||
| 164 | } | 182 | } |
| 183 | + return true; | ||
| 165 | } | 184 | } |
| 166 | 185 | ||
| 167 | bool PixelMapGlContext::InitGrContext() | 186 | bool PixelMapGlContext::InitGrContext() |
| @@ -122,6 +122,21 @@ void PixelMapGLPostProcProgram::Clear() noexcept | |||
| 122 | } | 122 | } |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | +void PixelMapGLPostProcProgram::AbandonGLResources() noexcept | ||
| 126 | +{ | ||
| 127 | + eglImage_ = EGL_NO_IMAGE_KHR; | ||
| 128 | + auto abandon = [](auto &shader) { | ||
| 129 | + if (shader != nullptr) { | ||
| 130 | + shader->Abandon(); | ||
| 131 | + shader.reset(); | ||
| 132 | + } | ||
| 133 | + }; | ||
| 134 | + abandon(rotateShader_); | ||
| 135 | + abandon(slrShader_); | ||
| 136 | + abandon(lapShader_); | ||
| 137 | + abandon(vertexShader_); | ||
| 138 | +} | ||
| 139 | + | ||
| 125 | bool PixelMapGLPostProcProgram::BuildShader() | 140 | bool PixelMapGLPostProcProgram::BuildShader() |
| 126 | { | 141 | { |
| 127 | ImageTrace imageTrace("PixelMapGLPostProcProgram::BuildShader"); | 142 | ImageTrace imageTrace("PixelMapGLPostProcProgram::BuildShader"); |
| @@ -189,6 +204,11 @@ bool PixelMapGLPostProcProgram::CreateNormalImage(const uint8_t *data, GLuint &i | |||
| 189 | IMAGE_LOGE("slr_gpu %{public}s invalid source image layout", __func__); | 204 | IMAGE_LOGE("slr_gpu %{public}s invalid source image layout", __func__); |
| 190 | return false; | 205 | return false; |
| 191 | } | 206 | } |
| 207 | + if (!PixelMapGlResource::ValidateStridedBufferSize(transformData_.sourceInfo_.bufferSize, | ||
| 208 | + transformData_.sourceInfo_.stride, sourceSize.height, rowBytes)) { | ||
| 209 | + IMAGE_LOGE("slr_gpu %{public}s source buffer is too small", __func__); | ||
| 210 | + return false; | ||
| 211 | + } | ||
| 192 | GLuint newImageTexId = 0U; | 212 | GLuint newImageTexId = 0U; |
| 193 | glGenTextures(1, &newImageTexId); | 213 | glGenTextures(1, &newImageTexId); |
| 194 | PixelMapGlResource::ScopedTexture scopedImageTexture(newImageTexId); | 214 | PixelMapGlResource::ScopedTexture scopedImageTexture(newImageTexId); |
| @@ -212,8 +232,8 @@ bool PixelMapGLPostProcProgram::CreateNormalImage(const uint8_t *data, GLuint &i | |||
| 212 | if (mapPointer == NULL) { | 232 | if (mapPointer == NULL) { |
| 213 | return false; | 233 | return false; |
| 214 | } | 234 | } |
| 215 | - if (!PixelMapGlResource::CopyStridedToLinear(data, transformData_.sourceInfo_.stride, | 235 | + if (!PixelMapGlResource::CopyStridedToLinear(data, transformData_.sourceInfo_.bufferSize, |
| 216 | - sourceSize.height, rowBytes, mapPointer, contiguousSize)) { | 236 | + transformData_.sourceInfo_.stride, sourceSize.height, rowBytes, mapPointer, contiguousSize)) { |
| 217 | IMAGE_LOGE("slr_gpu %{public}s CopyStridedToLinear failed", __func__); | 237 | IMAGE_LOGE("slr_gpu %{public}s CopyStridedToLinear failed", __func__); |
| 218 | glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); | 238 | glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); |
| 219 | return false; | 239 | return false; |
| @@ -346,11 +366,15 @@ bool PixelMapGLPostProcProgram::InitGLResource() | |||
| 346 | bool PixelMapGLPostProcProgram::BuildProcTexture(GLuint &readTexId) | 366 | bool PixelMapGLPostProcProgram::BuildProcTexture(GLuint &readTexId) |
| 347 | { | 367 | { |
| 348 | if (!transformData_.isSourceDma) { | 368 | if (!transformData_.isSourceDma) { |
| 369 | + CHECK_ERROR_RETURN_RET_LOG(transformData_.sourceInfo_.addr == nullptr, false, | ||
| 370 | + "slr_gpu BuildProcTexture source address is null"); | ||
| 349 | if (!CreateNormalImage(transformData_.sourceInfo_.addr, readTexId)) { | 371 | if (!CreateNormalImage(transformData_.sourceInfo_.addr, readTexId)) { |
| 350 | return false; | 372 | return false; |
| 351 | } | 373 | } |
| 352 | } else { | 374 | } else { |
| 353 | void *surfaceBuffer = transformData_.sourceInfo_.context; | 375 | void *surfaceBuffer = transformData_.sourceInfo_.context; |
| 376 | + CHECK_ERROR_RETURN_RET_LOG(surfaceBuffer == nullptr, false, | ||
| 377 | + "slr_gpu BuildProcTexture source surface buffer is null"); | ||
| 354 | PixelMapGlResource::ScopedNativeWindowBuffer scopedBuffer | 378 | PixelMapGlResource::ScopedNativeWindowBuffer scopedBuffer |
| 355 | (CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuffer)); | 379 | (CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuffer)); |
| 356 | if (!CreateEGLImage(scopedBuffer.Get(), eglImage_, readTexId)) { | 380 | if (!CreateEGLImage(scopedBuffer.Get(), eglImage_, readTexId)) { |
| @@ -408,6 +432,7 @@ bool PixelMapGLPostProcProgram::GenProcEndData(char *lcdData) | |||
| 408 | bool PixelMapGLPostProcProgram::GenProcDmaEndData(void *surfaceBuffer) | 432 | bool PixelMapGLPostProcProgram::GenProcDmaEndData(void *surfaceBuffer) |
| 409 | { | 433 | { |
| 410 | ImageTrace imageTrace("GenProcEndData-surface"); | 434 | ImageTrace imageTrace("GenProcEndData-surface"); |
| 435 | + CHECK_ERROR_RETURN_RET_LOG(surfaceBuffer == nullptr, false, "slr_gpu GenProcDmaEndData surface buffer is null"); | ||
| 411 | switch (transformData_.transformationType) { | 436 | switch (transformData_.transformationType) { |
| 412 | case TransformationType::SCALE : | 437 | case TransformationType::SCALE : |
| 413 | if (!(BuildProcTexture(slrShader_->GetReadTexId()) && | 438 | if (!(BuildProcTexture(slrShader_->GetReadTexId()) && |
| @@ -509,6 +534,7 @@ bool PixelMapGLPostProcProgram::ReadEndData(char *targetData, GLuint &writeTexId | |||
| 509 | bool PixelMapGLPostProcProgram::ReadEndDMAData(void *surfaceBuffer, GLuint &writeFbo) | 534 | bool PixelMapGLPostProcProgram::ReadEndDMAData(void *surfaceBuffer, GLuint &writeFbo) |
| 510 | { | 535 | { |
| 511 | ImageTrace imageTrace("ReadEndDMAData "); | 536 | ImageTrace imageTrace("ReadEndDMAData "); |
| 537 | + CHECK_ERROR_RETURN_RET_LOG(surfaceBuffer == nullptr, false, "slr_gpu ReadEndDMAData surface buffer is null"); | ||
| 512 | PixelMapGlResource::ScopedNativeWindowBuffer nativeBuffer | 538 | PixelMapGlResource::ScopedNativeWindowBuffer nativeBuffer |
| 513 | (CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuffer)); | 539 | (CreateNativeWindowBufferFromSurfaceBuffer(&surfaceBuffer)); |
| 514 | if (nativeBuffer.Get() == nullptr) { | 540 | if (nativeBuffer.Get() == nullptr) { |
| @@ -245,6 +245,17 @@ bool Shader::clearResources() | |||
| 245 | return true; | 245 | return true; |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | +void Shader::Abandon() | ||
| 249 | +{ | ||
| 250 | + programId_ = 0U; | ||
| 251 | + vShader_ = 0U; | ||
| 252 | + fShader_ = 0U; | ||
| 253 | + readTexId_ = 0U; | ||
| 254 | + writeFbo_ = 0U; | ||
| 255 | + writeTexId_ = 0U; | ||
| 256 | + eglImage_ = EGL_NO_IMAGE_KHR; | ||
| 257 | +} | ||
| 258 | + | ||
| 248 | GLuint Shader::loadShader(GLenum type, const char *shaderSrc) | 259 | GLuint Shader::loadShader(GLenum type, const char *shaderSrc) |
| 249 | { | 260 | { |
| 250 | ImageTrace imageTrace("Shader::loadShader"); | 261 | ImageTrace imageTrace("Shader::loadShader"); |
| @@ -371,6 +382,12 @@ bool VertexShader::Clear() | |||
| 371 | return Shader::Clear(); | 382 | return Shader::Clear(); |
| 372 | } | 383 | } |
| 373 | 384 | ||
| 385 | +void VertexShader::Abandon() | ||
| 386 | +{ | ||
| 387 | + vbo_ = 0U; | ||
| 388 | + Shader::Abandon(); | ||
| 389 | +} | ||
| 390 | + | ||
| 374 | bool VertexShader::Build() | 391 | bool VertexShader::Build() |
| 375 | { | 392 | { |
| 376 | ImageTrace imageTrace("VertexShader::Build"); | 393 | ImageTrace imageTrace("VertexShader::Build"); |
| @@ -580,6 +597,14 @@ bool SLRShader::Clear() | |||
| 580 | return Shader::Clear(); | 597 | return Shader::Clear(); |
| 581 | } | 598 | } |
| 582 | 599 | ||
| 600 | +void SLRShader::Abandon() | ||
| 601 | +{ | ||
| 602 | + texture_[0] = 0U; | ||
| 603 | + texture_[1] = 0U; | ||
| 604 | + eglImage_ = EGL_NO_IMAGE_KHR; | ||
| 605 | + Shader::Abandon(); | ||
| 606 | +} | ||
| 607 | + | ||
| 583 | bool SLRShader::Build() | 608 | bool SLRShader::Build() |
| 584 | { | 609 | { |
| 585 | static const char vSlrShaderStr[] = | 610 | static const char vSlrShaderStr[] = |
| @@ -70,7 +70,15 @@ bool RenderContext::InitEGLContext() | |||
| 70 | eglDisplay_ = EGL_NO_DISPLAY; | 70 | eglDisplay_ = EGL_NO_DISPLAY; |
| 71 | return false; | 71 | return false; |
| 72 | } | 72 | } |
| 73 | - MakeCurrent(pbufferSurface_); | 73 | + if (!MakeCurrent(pbufferSurface_)) { |
| 74 | + (void)eglDestroySurface(eglDisplay_, pbufferSurface_); | ||
| 75 | + (void)eglDestroyContext(eglDisplay_, eglContext_); | ||
| 76 | + (void)eglTerminate(eglDisplay_); | ||
| 77 | + pbufferSurface_ = EGL_NO_SURFACE; | ||
| 78 | + eglContext_ = EGL_NO_CONTEXT; | ||
| 79 | + eglDisplay_ = EGL_NO_DISPLAY; | ||
| 80 | + return false; | ||
| 81 | + } | ||
| 74 | 82 | ||
| 75 | return true; | 83 | return true; |
| 76 | } | 84 | } |
| @@ -80,25 +88,38 @@ bool RenderContext::CreatePbufferSurface() | |||
| 80 | return PixelMapEglUtils::CreatePbufferSurface(eglDisplay_, config_, pbufferSurface_); | 88 | return PixelMapEglUtils::CreatePbufferSurface(eglDisplay_, config_, pbufferSurface_); |
| 81 | } | 89 | } |
| 82 | 90 | ||
| 83 | -void RenderContext::MakeCurrent(EGLSurface surface) const | 91 | +bool RenderContext::MakeCurrent(EGLSurface surface) const |
| 84 | { | 92 | { |
| 85 | if (eglDisplay_ == EGL_NO_DISPLAY || eglContext_ == EGL_NO_CONTEXT) { | 93 | if (eglDisplay_ == EGL_NO_DISPLAY || eglContext_ == EGL_NO_CONTEXT) { |
| 86 | IMAGE_LOGE("RenderContext::MakeCurrent invalid egl context"); | 94 | IMAGE_LOGE("RenderContext::MakeCurrent invalid egl context"); |
| 87 | - return; | 95 | + return false; |
| 88 | } | 96 | } |
| 89 | EGLSurface currSurface = surface; | 97 | EGLSurface currSurface = surface; |
| 90 | if (currSurface == EGL_NO_SURFACE) { | 98 | if (currSurface == EGL_NO_SURFACE) { |
| 91 | currSurface = pbufferSurface_; | 99 | currSurface = pbufferSurface_; |
| 92 | } | 100 | } |
| 101 | + if (currSurface == EGL_NO_SURFACE) { | ||
| 102 | + IMAGE_LOGE("RenderContext::MakeCurrent invalid egl surface"); | ||
| 103 | + return false; | ||
| 104 | + } | ||
| 93 | 105 | ||
| 94 | if (eglMakeCurrent(eglDisplay_, currSurface, currSurface, eglContext_) != EGL_TRUE) { | 106 | if (eglMakeCurrent(eglDisplay_, currSurface, currSurface, eglContext_) != EGL_TRUE) { |
| 107 | + const EGLint makeCurrentError = eglGetError(); | ||
| 95 | EGLint surfaceId = -1; | 108 | EGLint surfaceId = -1; |
| 96 | - eglQuerySurface(eglDisplay_, surface, EGL_CONFIG_ID, &surfaceId); | 109 | + if (eglQuerySurface(eglDisplay_, currSurface, EGL_CONFIG_ID, &surfaceId) != EGL_TRUE) { |
| 110 | + IMAGE_LOGE( | ||
| 111 | + "RenderContext::MakeCurrent failed, error is %{public}x, query surface failed %{public}x", | ||
| 112 | + makeCurrentError, | ||
| 113 | + eglGetError()); | ||
| 114 | + return false; | ||
| 115 | + } | ||
| 97 | IMAGE_LOGE( | 116 | IMAGE_LOGE( |
| 98 | "RenderContext::MakeCurrent failed for eglSurface %{public}d, error is %{public}x", | 117 | "RenderContext::MakeCurrent failed for eglSurface %{public}d, error is %{public}x", |
| 99 | surfaceId, | 118 | surfaceId, |
| 100 | - eglGetError()); | 119 | + makeCurrentError); |
| 120 | + return false; | ||
| 101 | } | 121 | } |
| 122 | + return true; | ||
| 102 | } | 123 | } |
| 103 | 124 | ||
| 104 | bool RenderContext::InitGrContext() | 125 | bool RenderContext::InitGrContext() |
| @@ -1252,15 +1252,18 @@ ohos_unittest("napitest") { | |||
| 1252 | ] | 1252 | ] |
| 1253 | sources = [ "unittest/napi_test.cpp" ] | 1253 | sources = [ "unittest/napi_test.cpp" ] |
| 1254 | 1254 | ||
| 1255 | - deps = [ "$image_subsystem/interfaces/kits/js/common:image" ] | 1255 | + deps = [ |
| 1256 | + "$image_subsystem/interfaces/innerkits:image_native", | ||
| 1257 | + "$image_subsystem/interfaces/kits/js/common:image", | ||
| 1258 | + ] | ||
| 1256 | 1259 | ||
| 1257 | external_deps = [ | 1260 | external_deps = [ |
| 1258 | - "ipc:ipc_single", | 1261 | + "c_utils:utils", |
| 1259 | "googletest:gmock_main", | 1262 | "googletest:gmock_main", |
| 1260 | "googletest:gtest_main", | 1263 | "googletest:gtest_main", |
| 1261 | "graphic_2d:color_manager", | 1264 | "graphic_2d:color_manager", |
| 1262 | - "napi:ace_napi", | ||
| 1263 | "ipc:ipc_single", | 1265 | "ipc:ipc_single", |
| 1266 | + "napi:ace_napi", | ||
| 1264 | ] | 1267 | ] |
| 1265 | } | 1268 | } |
| 1266 | 1269 | ||
| @@ -14,6 +14,8 @@ | |||
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | + | ||
| 18 | + | ||
| 17 | 19 | ||
| 18 | 20 | ||
| 19 | 21 | ||
| @@ -28,6 +30,123 @@ public: | |||
| 28 | ~NapiTest() {} | 30 | ~NapiTest() {} |
| 29 | }; | 31 | }; |
| 30 | 32 | ||
| 33 | +class AntiAliasingOptionRecordingPixelMap : public PixelMap { | ||
| 34 | +public: | ||
| 35 | + void scale(float, float, const AntiAliasingOption &option) override | ||
| 36 | + { | ||
| 37 | + lastOption_ = option; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + AntiAliasingOption lastOption_ = AntiAliasingOption::HIGH; | ||
| 41 | +}; | ||
| 42 | + | ||
| 43 | +/** | ||
| 44 | + * @tc.name: PixelMapNapiScaleWithAntiAliasingOutOfRangeUsesNone | ||
| 45 | + * @tc.desc: Use NONE when NAPI receives a public anti-aliasing level that is out of range. | ||
| 46 | + * @tc.type: FUNC | ||
| 47 | + */ | ||
| 48 | +HWTEST_F(NapiTest, PixelMapNapiScaleWithAntiAliasingOutOfRangeUsesNone, TestSize.Level3) | ||
| 49 | +{ | ||
| 50 | + PixelMapNapi pixelMapNapi; | ||
| 51 | + auto recordingPixelMap = std::make_shared<AntiAliasingOptionRecordingPixelMap>(); | ||
| 52 | + *(pixelMapNapi.GetPixelMap()) = recordingPixelMap; | ||
| 53 | + | ||
| 54 | + PixelMapNapiArgs args = {}; | ||
| 55 | + args.inFloat0 = 0.5f; | ||
| 56 | + args.inFloat1 = 0.5f; | ||
| 57 | + args.inNum0 = -1; | ||
| 58 | + ASSERT_EQ(PixelMapNapiNativeCtxCall(CTX_FUNC_SCALE, &pixelMapNapi, &args), IMAGE_RESULT_SUCCESS); | ||
| 59 | + EXPECT_EQ(recordingPixelMap->lastOption_, AntiAliasingOption::NONE); | ||
| 60 | + | ||
| 61 | + recordingPixelMap->lastOption_ = AntiAliasingOption::HIGH; | ||
| 62 | + args.inNum0 = static_cast<int32_t>(AntiAliasingOption::HIGH) + 1; | ||
| 63 | + ASSERT_EQ(PixelMapNapiNativeCtxCall(CTX_FUNC_SCALE, &pixelMapNapi, &args), IMAGE_RESULT_SUCCESS); | ||
| 64 | + EXPECT_EQ(recordingPixelMap->lastOption_, AntiAliasingOption::NONE); | ||
| 65 | + | ||
| 66 | + args.inNum0 = static_cast<int32_t>(AntiAliasingOption::HIGH); | ||
| 67 | + ASSERT_EQ(PixelMapNapiNativeCtxCall(CTX_FUNC_SCALE, &pixelMapNapi, &args), IMAGE_RESULT_SUCCESS); | ||
| 68 | + EXPECT_EQ(recordingPixelMap->lastOption_, AntiAliasingOption::HIGH); | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +/** | ||
| 72 | + * @tc.name: ImageNapiUtilsConvertDoubleToInt32RejectsInvalidValues | ||
| 73 | + * @tc.desc: Reject non-finite and out-of-range values before converting them to int32. | ||
| 74 | + * @tc.type: FUNC | ||
| 75 | + */ | ||
| 76 | +HWTEST_F(NapiTest, ImageNapiUtilsConvertDoubleToInt32RejectsInvalidValues, TestSize.Level3) | ||
| 77 | +{ | ||
| 78 | + int32_t result = 0; | ||
| 79 | + constexpr double int32Max = static_cast<double>(std::numeric_limits<int32_t>::max()); | ||
| 80 | + constexpr double int32Min = static_cast<double>(std::numeric_limits<int32_t>::min()); | ||
| 81 | + | ||
| 82 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToInt32(int32Max + 1.0, &result)); | ||
| 83 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToInt32(int32Min - 1.0, &result)); | ||
| 84 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToInt32(4294967297.0, &result)); | ||
| 85 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToInt32(std::numeric_limits<double>::infinity(), &result)); | ||
| 86 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToInt32(-std::numeric_limits<double>::infinity(), &result)); | ||
| 87 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToInt32(std::numeric_limits<double>::quiet_NaN(), &result)); | ||
| 88 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToInt32(0.0, nullptr)); | ||
| 89 | +} | ||
| 90 | + | ||
| 91 | +/** | ||
| 92 | + * @tc.name: ImageNapiUtilsConvertDoubleToInt32PreservesCompatibleValues | ||
| 93 | + * @tc.desc: Accept int32 boundaries and preserve truncation for finite fractional values in range. | ||
| 94 | + * @tc.type: FUNC | ||
| 95 | + */ | ||
| 96 | +HWTEST_F(NapiTest, ImageNapiUtilsConvertDoubleToInt32PreservesCompatibleValues, TestSize.Level3) | ||
| 97 | +{ | ||
| 98 | + int32_t result = 0; | ||
| 99 | + | ||
| 100 | + ASSERT_TRUE(ImageNapiUtils::ConvertDoubleToInt32( | ||
| 101 | + static_cast<double>(std::numeric_limits<int32_t>::max()), &result)); | ||
| 102 | + EXPECT_EQ(result, std::numeric_limits<int32_t>::max()); | ||
| 103 | + | ||
| 104 | + ASSERT_TRUE(ImageNapiUtils::ConvertDoubleToInt32( | ||
| 105 | + static_cast<double>(std::numeric_limits<int32_t>::min()), &result)); | ||
| 106 | + EXPECT_EQ(result, std::numeric_limits<int32_t>::min()); | ||
| 107 | + | ||
| 108 | + ASSERT_TRUE(ImageNapiUtils::ConvertDoubleToInt32(1.75, &result)); | ||
| 109 | + EXPECT_EQ(result, 1); | ||
| 110 | + | ||
| 111 | + ASSERT_TRUE(ImageNapiUtils::ConvertDoubleToInt32(-1.75, &result)); | ||
| 112 | + EXPECT_EQ(result, -1); | ||
| 113 | +} | ||
| 114 | + | ||
| 115 | +/** | ||
| 116 | + * @tc.name: ImageNapiUtilsConvertDoubleToFloatRejectsInvalidValues | ||
| 117 | + * @tc.desc: Reject non-finite and out-of-float-range values before converting them to float. | ||
| 118 | + * @tc.type: FUNC | ||
| 119 | + */ | ||
| 120 | +HWTEST_F(NapiTest, ImageNapiUtilsConvertDoubleToFloatRejectsInvalidValues, TestSize.Level3) | ||
| 121 | +{ | ||
| 122 | + float result = 0.0f; | ||
| 123 | + constexpr double floatMax = static_cast<double>(std::numeric_limits<float>::max()); | ||
| 124 | + | ||
| 125 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToFloat(floatMax * 2.0, &result)); | ||
| 126 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToFloat(-floatMax * 2.0, &result)); | ||
| 127 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToFloat(std::numeric_limits<double>::infinity(), &result)); | ||
| 128 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToFloat(-std::numeric_limits<double>::infinity(), &result)); | ||
| 129 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToFloat(std::numeric_limits<double>::quiet_NaN(), &result)); | ||
| 130 | + EXPECT_FALSE(ImageNapiUtils::ConvertDoubleToFloat(0.0, nullptr)); | ||
| 131 | +} | ||
| 132 | + | ||
| 133 | +/** | ||
| 134 | + * @tc.name: ImageNapiUtilsConvertDoubleToFloatPreservesCompatibleValues | ||
| 135 | + * @tc.desc: Accept finite values within the float range. | ||
| 136 | + * @tc.type: FUNC | ||
| 137 | + */ | ||
| 138 | +HWTEST_F(NapiTest, ImageNapiUtilsConvertDoubleToFloatPreservesCompatibleValues, TestSize.Level3) | ||
| 139 | +{ | ||
| 140 | + float result = 0.0f; | ||
| 141 | + | ||
| 142 | + ASSERT_TRUE(ImageNapiUtils::ConvertDoubleToFloat(1.25, &result)); | ||
| 143 | + EXPECT_FLOAT_EQ(result, 1.25f); | ||
| 144 | + | ||
| 145 | + ASSERT_TRUE(ImageNapiUtils::ConvertDoubleToFloat( | ||
| 146 | + static_cast<double>(std::numeric_limits<float>::max()), &result)); | ||
| 147 | + EXPECT_EQ(result, std::numeric_limits<float>::max()); | ||
| 148 | +} | ||
| 149 | + | ||
| 31 | /** | 150 | /** |
| 32 | * @tc.name: NapiTest001 | 151 | * @tc.name: NapiTest001 |
| 33 | * @tc.desc: IsLockPixelMap | 152 | * @tc.desc: IsLockPixelMap |
| @@ -255,20 +374,6 @@ HWTEST_F(NapiTest, NapiTest0014, TestSize.Level3) | |||
| 255 | 374 | ||
| 256 | GTEST_LOG_(INFO) << "NapiTest: NapiTest0014 end"; | 375 | GTEST_LOG_(INFO) << "NapiTest: NapiTest0014 end"; |
| 257 | } | 376 | } |
| 258 | -/** | ||
| 259 | - * @tc.name: NapiTest0015 | ||
| 260 | - * @tc.desc: OH_PixelMap_SetOpacity | ||
| 261 | - * @tc.type: FUNC | ||
| 262 | - */ | ||
| 263 | -HWTEST_F(NapiTest, NapiTest0015, TestSize.Level3) | ||
| 264 | -{ | ||
| 265 | - GTEST_LOG_(INFO) << "NapiTest: NapiTest0015 start"; | ||
| 266 | - ImageSourceNapi napi; | ||
| 267 | - ImageResource resource = napi.GetImageResource(); | ||
| 268 | - ASSERT_EQ(resource.buffer, nullptr); | ||
| 269 | - | ||
| 270 | - GTEST_LOG_(INFO) << "NapiTest: NapiTest0015 end"; | ||
| 271 | -} | ||
| 272 | 377 | ||
| 273 | /** | 378 | /** |
| 274 | * @tc.name: NapiTest0016 | 379 | * @tc.name: NapiTest0016 |
| @@ -139,6 +139,31 @@ static void ConstructPixelAstc(std::unique_ptr<PixelMap>& pixelMap, uint8_t** da | |||
| 139 | *dataIn = data; | 139 | *dataIn = data; |
| 140 | } | 140 | } |
| 141 | 141 | ||
| 142 | +/** | ||
| 143 | + * @tc.name: PixelAstcTestScaleRounding001 | ||
| 144 | + * @tc.desc: PixelAstc scale rounding covers both round-down and round-up | ||
| 145 | + * @tc.type: FUNC | ||
| 146 | + */ | ||
| 147 | +HWTEST_F(PixelAstcTest, PixelAstcTestScaleRounding001, TestSize.Level3) | ||
| 148 | +{ | ||
| 149 | + GTEST_LOG_(INFO) << "PixelAstcTest: PixelAstcTestScaleRounding001 start"; | ||
| 150 | + std::unique_ptr<PixelMap> pixelAstc = std::unique_ptr<PixelMap>(); | ||
| 151 | + uint8_t* data = nullptr; | ||
| 152 | + ConstructPixelAstc(pixelAstc, &data); | ||
| 153 | + ASSERT_NE(pixelAstc.get(), nullptr); | ||
| 154 | + float xAxis = 0.7f; // 256 * 0.7 = 179.2, rounds down to 179 | ||
| 155 | + float yAxis = 1.3f; // 256 * 1.3 = 332.8, rounds up to 333 | ||
| 156 | + pixelAstc->scale(xAxis, yAxis); | ||
| 157 | + ImageInfo outInfo; | ||
| 158 | + pixelAstc->GetImageInfo(outInfo); | ||
| 159 | + EXPECT_EQ(179, outInfo.size.width); | ||
| 160 | + EXPECT_EQ(333, outInfo.size.height); | ||
| 161 | + if (data != nullptr) { | ||
| 162 | + free(data); | ||
| 163 | + } | ||
| 164 | + GTEST_LOG_(INFO) << "PixelAstcTest: PixelAstcTestScaleRounding001 end"; | ||
| 165 | +} | ||
| 166 | + | ||
| 142 | /** | 167 | /** |
| 143 | * @tc.name: PixelAstcTest001 | 168 | * @tc.name: PixelAstcTest001 |
| 144 | * @tc.desc: PixelAstc scale | 169 | * @tc.desc: PixelAstc scale |
| @@ -733,6 +733,21 @@ HWTEST_F(PluginTextureEncodeTest, AstcEncBasedOnCl003, TestSize.Level3) | |||
| 733 | GTEST_LOG_(INFO) << "PluginTextureEncodeTest: AstcEncBasedOnCl003 end"; | 733 | GTEST_LOG_(INFO) << "PluginTextureEncodeTest: AstcEncBasedOnCl003 end"; |
| 734 | } | 734 | } |
| 735 | 735 | ||
| 736 | +/** | ||
| 737 | + * @tc.name: AstcEncBasedOnCl006 | ||
| 738 | + * @tc.desc: AstcClCreate rejects a null output handle | ||
| 739 | + * @tc.type: FUNC | ||
| 740 | + */ | ||
| 741 | +HWTEST_F(PluginTextureEncodeTest, AstcEncBasedOnCl006, TestSize.Level3) | ||
| 742 | +{ | ||
| 743 | + GTEST_LOG_(INFO) << "PluginTextureEncodeTest: AstcEncBasedOnCl006 start"; | ||
| 744 | + | ||
| 745 | + uint32_t ret = AstcClCreate(nullptr, ""); | ||
| 746 | + ASSERT_EQ(ret, CL_ASTC_ENC_FAILED); | ||
| 747 | + | ||
| 748 | + GTEST_LOG_(INFO) << "PluginTextureEncodeTest: AstcEncBasedOnCl006 end"; | ||
| 749 | +} | ||
| 750 | + | ||
| 736 | static void RemoveAstcClTestFile(const std::string &path) | 751 | static void RemoveAstcClTestFile(const std::string &path) |
| 737 | { | 752 | { |
| 738 | (void)std::remove(path.c_str()); | 753 | (void)std::remove(path.c_str()); |
| @@ -1451,4 +1466,4 @@ HWTEST_F(PluginTextureEncodeTest, FillMetaDataTest001, TestSize.Level3) | |||
| 1451 | EXPECT_FALSE(codec.FillMetaData(info, mapNoFd.get())); | 1466 | EXPECT_FALSE(codec.FillMetaData(info, mapNoFd.get())); |
| 1452 | } | 1467 | } |
| 1453 | } // namespace Multimedia | 1468 | } // namespace Multimedia |
| 1454 | -} // namespace OHOS | 1469 | +} // namespace OHOS |
| @@ -20,6 +20,8 @@ | |||
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | 22 | ||
| 23 | + | ||
| 24 | + | ||
| 23 | 25 | ||
| 24 | 26 | ||
| 25 | 27 | ||
| @@ -45,6 +47,11 @@ public: | |||
| 45 | ~EglImageHelperTest() override = default; | 47 | ~EglImageHelperTest() override = default; |
| 46 | }; | 48 | }; |
| 47 | 49 | ||
| 50 | +static_assert(std::is_same_v< | ||
| 51 | + decltype(std::declval<PixelMapGlContext &>().MakeCurrent(EGL_NO_SURFACE)), bool>); | ||
| 52 | +static_assert(std::is_same_v< | ||
| 53 | + decltype(std::declval<RenderContext &>().MakeCurrent(EGL_NO_SURFACE)), bool>); | ||
| 54 | + | ||
| 48 | class TestShader : public PixelMapGlShader::Shader { | 55 | class TestShader : public PixelMapGlShader::Shader { |
| 49 | public: | 56 | public: |
| 50 | bool Clear() override | 57 | bool Clear() override |
| @@ -63,6 +70,23 @@ public: | |||
| 63 | { | 70 | { |
| 64 | targetSize_ = targetSize; | 71 | targetSize_ = targetSize; |
| 65 | } | 72 | } |
| 73 | + | ||
| 74 | + void SetResourcesForTest() | ||
| 75 | + { | ||
| 76 | + programId_ = 1U; | ||
| 77 | + vShader_ = 2U; | ||
| 78 | + fShader_ = 3U; | ||
| 79 | + readTexId_ = 4U; | ||
| 80 | + writeFbo_ = 5U; | ||
| 81 | + writeTexId_ = 6U; | ||
| 82 | + eglImage_ = reinterpret_cast<EGLImageKHR>(1); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | + bool HasNoResourcesForTest() const | ||
| 86 | + { | ||
| 87 | + return programId_ == 0U && vShader_ == 0U && fShader_ == 0U && readTexId_ == 0U && | ||
| 88 | + writeFbo_ == 0U && writeTexId_ == 0U && eglImage_ == EGL_NO_IMAGE_KHR; | ||
| 89 | + } | ||
| 66 | }; | 90 | }; |
| 67 | 91 | ||
| 68 | /** | 92 | /** |
| @@ -98,6 +122,7 @@ HWTEST_F(EglImageHelperTest, PixelMapGlCommonTransformDefaultsTest001, TestSize. | |||
| 98 | EXPECT_FALSE(transformData.isTargetDma); | 122 | EXPECT_FALSE(transformData.isTargetDma); |
| 99 | EXPECT_EQ(transformData.sourceInfo_.addr, nullptr); | 123 | EXPECT_EQ(transformData.sourceInfo_.addr, nullptr); |
| 100 | EXPECT_EQ(transformData.sourceInfo_.context, nullptr); | 124 | EXPECT_EQ(transformData.sourceInfo_.context, nullptr); |
| 125 | + EXPECT_EQ(transformData.sourceInfo_.bufferSize, 0); | ||
| 101 | EXPECT_EQ(transformData.targetInfo_.outdata, nullptr); | 126 | EXPECT_EQ(transformData.targetInfo_.outdata, nullptr); |
| 102 | EXPECT_EQ(transformData.targetInfo_.context, nullptr); | 127 | EXPECT_EQ(transformData.targetInfo_.context, nullptr); |
| 103 | 128 | ||
| @@ -182,8 +207,12 @@ HWTEST_F(EglImageHelperTest, PixelMapGlResourceCopyFailureTest001, TestSize.Leve | |||
| 182 | constexpr size_t rowBytes = 8; | 207 | constexpr size_t rowBytes = 8; |
| 183 | const uint8_t src[12] = {0}; | 208 | const uint8_t src[12] = {0}; |
| 184 | char dst[16] = {0}; | 209 | char dst[16] = {0}; |
| 185 | - EXPECT_FALSE(PixelMapGlResource::CopyStridedToLinear(nullptr, 8, 2, rowBytes, dst, sizeof(dst))); | 210 | + EXPECT_FALSE(PixelMapGlResource::CopyStridedToLinear( |
| 186 | - EXPECT_FALSE(PixelMapGlResource::CopyStridedToLinear(src, 8, 3, rowBytes, dst, sizeof(dst))); | 211 | + nullptr, 0, 8, 2, rowBytes, dst, sizeof(dst))); |
| 212 | + EXPECT_FALSE(PixelMapGlResource::CopyStridedToLinear( | ||
| 213 | + src, sizeof(src), 8, 2, rowBytes, dst, sizeof(dst))); | ||
| 214 | + EXPECT_FALSE(PixelMapGlResource::ValidateStridedBufferSize(sizeof(src), 8, 2, rowBytes)); | ||
| 215 | + EXPECT_TRUE(PixelMapGlResource::ValidateStridedBufferSize(sizeof(dst), 8, 2, rowBytes)); | ||
| 187 | 216 | ||
| 188 | const char linear[16] = {0}; | 217 | const char linear[16] = {0}; |
| 189 | uint8_t strided[12] = {0}; | 218 | uint8_t strided[12] = {0}; |
| @@ -293,14 +322,13 @@ HWTEST_F(EglImageHelperTest, PixelMapContextInvalidStateTest001, TestSize.Level3 | |||
| 293 | EXPECT_FALSE(glContext.CreatePbufferSurface()); | 322 | EXPECT_FALSE(glContext.CreatePbufferSurface()); |
| 294 | EXPECT_FALSE(glContext.MakeCurrentSimple(true)); | 323 | EXPECT_FALSE(glContext.MakeCurrentSimple(true)); |
| 295 | EXPECT_FALSE(glContext.MakeCurrentSimple(false)); | 324 | EXPECT_FALSE(glContext.MakeCurrentSimple(false)); |
| 296 | - glContext.MakeCurrent(EGL_NO_SURFACE); | 325 | + EXPECT_FALSE(glContext.MakeCurrent(EGL_NO_SURFACE)); |
| 297 | glContext.Clear(); | 326 | glContext.Clear(); |
| 298 | 327 | ||
| 299 | RenderContext renderContext; | 328 | RenderContext renderContext; |
| 300 | EXPECT_FALSE(renderContext.CreatePbufferSurface()); | 329 | EXPECT_FALSE(renderContext.CreatePbufferSurface()); |
| 301 | - renderContext.MakeCurrent(EGL_NO_SURFACE); | 330 | + EXPECT_FALSE(renderContext.MakeCurrent(EGL_NO_SURFACE)); |
| 302 | renderContext.Clear(); | 331 | renderContext.Clear(); |
| 303 | - SUCCEED(); | ||
| 304 | } | 332 | } |
| 305 | 333 | ||
| 306 | /** | 334 | /** |
| @@ -450,11 +478,27 @@ HWTEST_F(EglImageHelperTest, PixelMapProgramExecutionGuardTest001, TestSize.Leve | |||
| 450 | program.SetGPUTransformData(transformData); | 478 | program.SetGPUTransformData(transformData); |
| 451 | char output = 0; | 479 | char output = 0; |
| 452 | EXPECT_TRUE(program.GenProcEndData(&output)); | 480 | EXPECT_TRUE(program.GenProcEndData(&output)); |
| 481 | + EXPECT_FALSE(program.GenProcDmaEndData(nullptr)); | ||
| 453 | EXPECT_TRUE(program.GenProcDmaEndData(reinterpret_cast<void *>(0x1))); | 482 | EXPECT_TRUE(program.GenProcDmaEndData(reinterpret_cast<void *>(0x1))); |
| 454 | 483 | ||
| 455 | EXPECT_FALSE(PixelMapProgramManager::ExecutProgram(nullptr)); | 484 | EXPECT_FALSE(PixelMapProgramManager::ExecutProgram(nullptr)); |
| 456 | } | 485 | } |
| 457 | 486 | ||
| 487 | +/** | ||
| 488 | + * @tc.name: PixelMapShaderAbandonTest001 | ||
| 489 | + * @tc.desc: Drop GL names without issuing GL calls when no context can be made current. | ||
| 490 | + * @tc.type: FUNC | ||
| 491 | + */ | ||
| 492 | +HWTEST_F(EglImageHelperTest, PixelMapShaderAbandonTest001, TestSize.Level3) | ||
| 493 | +{ | ||
| 494 | + TestShader shader; | ||
| 495 | + shader.SetResourcesForTest(); | ||
| 496 | + | ||
| 497 | + shader.Abandon(); | ||
| 498 | + | ||
| 499 | + EXPECT_TRUE(shader.HasNoResourcesForTest()); | ||
| 500 | +} | ||
| 501 | + | ||
| 458 | /** | 502 | /** |
| 459 | * @tc.name: PixelMapFromSurfaceInterfaceGuardTest001 | 503 | * @tc.name: PixelMapFromSurfaceInterfaceGuardTest001 |
| 460 | * @tc.desc: Test PixelMapFromSurface public create interface rejects invalid parameters consistently. | 504 | * @tc.desc: Test PixelMapFromSurface public create interface rejects invalid parameters consistently. |
| @@ -489,7 +533,11 @@ HWTEST_F(EglImageHelperTest, PixelMapGlContextInterfaceLifecycleTest001, TestSiz | |||
| 489 | EXPECT_TRUE(context.MakeCurrentSimple(true)); | 533 | EXPECT_TRUE(context.MakeCurrentSimple(true)); |
| 490 | EXPECT_TRUE(context.MakeCurrentSimple(true)); | 534 | EXPECT_TRUE(context.MakeCurrentSimple(true)); |
| 491 | EXPECT_TRUE(context.MakeCurrentSimple(false)); | 535 | EXPECT_TRUE(context.MakeCurrentSimple(false)); |
| 492 | - context.MakeCurrent(EGL_NO_SURFACE); | 536 | + EXPECT_TRUE(context.MakeCurrent(EGL_NO_SURFACE)); |
| 537 | + const EGLSurface pbufferSurface = context.pbufferSurface_; | ||
| 538 | + context.pbufferSurface_ = EGL_NO_SURFACE; | ||
| 539 | + EXPECT_FALSE(context.MakeCurrent(EGL_NO_SURFACE)); | ||
| 540 | + context.pbufferSurface_ = pbufferSurface; | ||
| 493 | context.Clear(); | 541 | context.Clear(); |
| 494 | EXPECT_EQ(context.GetEGLContext(), EGL_NO_CONTEXT); | 542 | EXPECT_EQ(context.GetEGLContext(), EGL_NO_CONTEXT); |
| 495 | EXPECT_EQ(context.pbufferSurface_, EGL_NO_SURFACE); | 543 | EXPECT_EQ(context.pbufferSurface_, EGL_NO_SURFACE); |
| @@ -513,7 +561,11 @@ HWTEST_F(EglImageHelperTest, RenderContextInterfaceLifecycleTest001, TestSize.Le | |||
| 513 | EXPECT_NE(context.GetEGLDisplay(), EGL_NO_DISPLAY); | 561 | EXPECT_NE(context.GetEGLDisplay(), EGL_NO_DISPLAY); |
| 514 | EXPECT_NE(context.pbufferSurface_, EGL_NO_SURFACE); | 562 | EXPECT_NE(context.pbufferSurface_, EGL_NO_SURFACE); |
| 515 | EXPECT_TRUE(context.CreatePbufferSurface()); | 563 | EXPECT_TRUE(context.CreatePbufferSurface()); |
| 516 | - context.MakeCurrent(EGL_NO_SURFACE); | 564 | + EXPECT_TRUE(context.MakeCurrent(EGL_NO_SURFACE)); |
| 565 | + const EGLSurface pbufferSurface = context.pbufferSurface_; | ||
| 566 | + context.pbufferSurface_ = EGL_NO_SURFACE; | ||
| 567 | + EXPECT_FALSE(context.MakeCurrent(EGL_NO_SURFACE)); | ||
| 568 | + context.pbufferSurface_ = pbufferSurface; | ||
| 517 | context.Clear(); | 569 | context.Clear(); |
| 518 | EXPECT_EQ(context.GetEGLContext(), EGL_NO_CONTEXT); | 570 | EXPECT_EQ(context.GetEGLContext(), EGL_NO_CONTEXT); |
| 519 | EXPECT_EQ(context.GetEGLDisplay(), EGL_NO_DISPLAY); | 571 | EXPECT_EQ(context.GetEGLDisplay(), EGL_NO_DISPLAY); |
| @@ -172,7 +172,7 @@ HWTEST_F(EglImageTest, RenderContextTest003, TestSize.Level1) | |||
| 172 | auto renderContext = std::make_unique<RenderContext>(); | 172 | auto renderContext = std::make_unique<RenderContext>(); |
| 173 | auto ret = renderContext->Init(); | 173 | auto ret = renderContext->Init(); |
| 174 | EXPECT_EQ(ret, true); | 174 | EXPECT_EQ(ret, true); |
| 175 | - renderContext->MakeCurrent(EGL_NO_SURFACE); | 175 | + EXPECT_TRUE(renderContext->MakeCurrent(EGL_NO_SURFACE)); |
| 176 | auto currSurface = eglGetCurrentSurface(EGL_DRAW); | 176 | auto currSurface = eglGetCurrentSurface(EGL_DRAW); |
| 177 | // even though MakeCurrent(EGL_NO_SURFACE), current surface is still not EGL_NO_SURFACE | 177 | // even though MakeCurrent(EGL_NO_SURFACE), current surface is still not EGL_NO_SURFACE |
| 178 | // in our renderContext, it will be a pbufferSurface. | 178 | // in our renderContext, it will be a pbufferSurface. |
| @@ -189,7 +189,7 @@ HWTEST_F(EglImageTest, RenderContextTest005, TestSize.Level1) | |||
| 189 | auto renderContext = std::make_unique<RenderContext>(); | 189 | auto renderContext = std::make_unique<RenderContext>(); |
| 190 | auto ret = renderContext->Init(); | 190 | auto ret = renderContext->Init(); |
| 191 | EXPECT_EQ(ret, true); | 191 | EXPECT_EQ(ret, true); |
| 192 | - renderContext->MakeCurrent(EGL_NO_SURFACE); | 192 | + EXPECT_TRUE(renderContext->MakeCurrent(EGL_NO_SURFACE)); |
| 193 | auto currSurface = eglGetCurrentSurface(EGL_DRAW); | 193 | auto currSurface = eglGetCurrentSurface(EGL_DRAW); |
| 194 | // even though MakeCurrent(EGL_NO_SURFACE), current surface is still not EGL_NO_SURFACE | 194 | // even though MakeCurrent(EGL_NO_SURFACE), current surface is still not EGL_NO_SURFACE |
| 195 | // in our renderContext, it will be a pbufferSurface. | 195 | // in our renderContext, it will be a pbufferSurface. |
| @@ -198,7 +198,7 @@ HWTEST_F(EglImageTest, RenderContextTest005, TestSize.Level1) | |||
| 198 | renderContext->GetEGLDisplay(), renderContext->GetEGLConfig(), | 198 | renderContext->GetEGLDisplay(), renderContext->GetEGLConfig(), |
| 199 | static_cast<EGLNativeWindowType>(nativeWindow), nullptr); | 199 | static_cast<EGLNativeWindowType>(nativeWindow), nullptr); |
| 200 | EXPECT_NE(surface, EGL_NO_SURFACE); | 200 | EXPECT_NE(surface, EGL_NO_SURFACE); |
| 201 | - renderContext->MakeCurrent(surface); | 201 | + EXPECT_TRUE(renderContext->MakeCurrent(surface)); |
| 202 | EXPECT_EQ(surface, eglGetCurrentSurface(EGL_DRAW)); | 202 | EXPECT_EQ(surface, eglGetCurrentSurface(EGL_DRAW)); |
| 203 | } | 203 | } |
| 204 | 204 | ||
| @@ -134,7 +134,7 @@ HWTEST_F(EglImageTest, PixelMapGlResourceCopyHelpersTest001, TestSize.Level3) | |||
| 134 | }; | 134 | }; |
| 135 | std::vector<char> linear(16, 0); | 135 | std::vector<char> linear(16, 0); |
| 136 | EXPECT_TRUE(PixelMapGlResource::CopyStridedToLinear( | 136 | EXPECT_TRUE(PixelMapGlResource::CopyStridedToLinear( |
| 137 | - src.data(), stride, height, rowBytes, linear.data(), linear.size())); | 137 | + src.data(), src.size(), stride, height, rowBytes, linear.data(), linear.size())); |
| 138 | EXPECT_EQ(static_cast<uint8_t>(linear[0]), 1); | 138 | EXPECT_EQ(static_cast<uint8_t>(linear[0]), 1); |
| 139 | EXPECT_EQ(static_cast<uint8_t>(linear[7]), 8); | 139 | EXPECT_EQ(static_cast<uint8_t>(linear[7]), 8); |
| 140 | EXPECT_EQ(static_cast<uint8_t>(linear[8]), 9); | 140 | EXPECT_EQ(static_cast<uint8_t>(linear[8]), 9); |
| @@ -2248,6 +2248,84 @@ HWTEST_F(ImagePixelMapTest, ImagePixelMapSLR006, TestSize.Level3) | |||
| 2248 | GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapSLR006 scale end"; | 2248 | GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapSLR006 scale end"; |
| 2249 | } | 2249 | } |
| 2250 | 2250 | ||
| 2251 | +/** | ||
| 2252 | + * @tc.name: ImagePixelMapScaleRounding001 | ||
| 2253 | + * @tc.desc: test non-SLR scale rounding covers both round-down and round-up | ||
| 2254 | + * @tc.type: FUNC | ||
| 2255 | + */ | ||
| 2256 | +HWTEST_F(ImagePixelMapTest, ImagePixelMapScaleRounding001, TestSize.Level3) | ||
| 2257 | +{ | ||
| 2258 | + GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapScaleRounding001 scale start"; | ||
| 2259 | + uint32_t* data = nullptr; | ||
| 2260 | + std::unique_ptr<PixelMap> pixelMap = ConstructPixelMap(&data); | ||
| 2261 | + EXPECT_NE(pixelMap, nullptr); | ||
| 2262 | + float xAxis = 0.7f; // 3 * 0.7 = 2.1, rounds down to 2 | ||
| 2263 | + float yAxis = 1.3f; // 3 * 1.3 = 3.9, rounds up to 4 | ||
| 2264 | + pixelMap->scale(xAxis, yAxis); | ||
| 2265 | + ImageInfo outInfo; | ||
| 2266 | + pixelMap->GetImageInfo(outInfo); | ||
| 2267 | + EXPECT_EQ(2, outInfo.size.width); | ||
| 2268 | + EXPECT_EQ(4, outInfo.size.height); | ||
| 2269 | + if (data != nullptr) { | ||
| 2270 | + delete[] data; | ||
| 2271 | + } | ||
| 2272 | + GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapScaleRounding001 scale end"; | ||
| 2273 | +} | ||
| 2274 | + | ||
| 2275 | +/** | ||
| 2276 | + * @tc.name: ImagePixelMapSLRWithlap001 | ||
| 2277 | + * @tc.desc: test SLR with Laplacian | ||
| 2278 | + * @tc.type: FUNC | ||
| 2279 | + */ | ||
| 2280 | +HWTEST_F(ImagePixelMapTest, ImagePixelMapSLRWithLap001, TestSize.Level3) | ||
| 2281 | +{ | ||
| 2282 | + GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapSLRWithLap001 scale start"; | ||
| 2283 | + std::unique_ptr<PixelMap> pixelMap = ConstructSLRPixelMap(); | ||
| 2284 | + EXPECT_NE(pixelMap, nullptr); | ||
| 2285 | + ImageInfo imageInfo; | ||
| 2286 | + pixelMap->GetImageInfo(imageInfo); | ||
| 2287 | + | ||
| 2288 | + float xAxis = 0.7f; // 0.7f scale test | ||
| 2289 | + float yAxis = 0.9f; // 0.9f scale test | ||
| 2290 | + Size desiredSize; | ||
| 2291 | + desiredSize.width = static_cast<int32_t>(imageInfo.size.width * xAxis); | ||
| 2292 | + desiredSize.height = static_cast<int32_t>(imageInfo.size.height * yAxis); | ||
| 2293 | + | ||
| 2294 | + PostProc postProc; | ||
| 2295 | + bool ret = postProc.ScalePixelMapWithSLR(desiredSize, *pixelMap.get(), true); | ||
| 2296 | + EXPECT_EQ(ret, true); | ||
| 2297 | + EXPECT_EQ(pixelMap->GetWidth(), desiredSize.width); | ||
| 2298 | + EXPECT_EQ(pixelMap->GetHeight(), desiredSize.height); | ||
| 2299 | + GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapSLRWithLap001 scale end"; | ||
| 2300 | +} | ||
| 2301 | + | ||
| 2302 | +/** | ||
| 2303 | + * @tc.name: ImagePixelMapSLRWithLap002 | ||
| 2304 | + * @tc.desc: test SLR with Laplacian | ||
| 2305 | + * @tc.type: FUNC | ||
| 2306 | + */ | ||
| 2307 | +HWTEST_F(ImagePixelMapTest, ImagePixelMapSLRWithLap002, TestSize.Level3) | ||
| 2308 | +{ | ||
| 2309 | + GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapSLRWithLap002 scale start"; | ||
| 2310 | + std::unique_ptr<PixelMap> pixelMap = ConstructSLRPixelMap(); | ||
| 2311 | + EXPECT_NE(pixelMap, nullptr); | ||
| 2312 | + ImageInfo imageInfo; | ||
| 2313 | + pixelMap->GetImageInfo(imageInfo); | ||
| 2314 | + | ||
| 2315 | + float xAxis = 0.7f; // 0.7f scale test | ||
| 2316 | + float yAxis = 0.9f; // 0.9f scale test | ||
| 2317 | + Size desiredSize; | ||
| 2318 | + desiredSize.width = static_cast<int32_t>(imageInfo.size.width * xAxis); | ||
| 2319 | + desiredSize.height = static_cast<int32_t>(imageInfo.size.height * yAxis); | ||
| 2320 | + | ||
| 2321 | + PostProc postProc; | ||
| 2322 | + bool ret = postProc.ScalePixelMapWithSLR(desiredSize, *pixelMap.get(), false); | ||
| 2323 | + EXPECT_EQ(ret, true); | ||
| 2324 | + EXPECT_EQ(pixelMap->GetWidth(), desiredSize.width); | ||
| 2325 | + EXPECT_EQ(pixelMap->GetHeight(), desiredSize.height); | ||
| 2326 | + GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapSLRWithLap002 scale end"; | ||
| 2327 | +} | ||
| 2328 | + | ||
| 2251 | /** | 2329 | /** |
| 2252 | * @tc.name: ImagePixelMapCreate001 | 2330 | * @tc.name: ImagePixelMapCreate001 |
| 2253 | * @tc.desc: test SLR with DMA | 2331 | * @tc.desc: test SLR with DMA |
| @@ -2323,55 +2401,5 @@ HWTEST_F(ImagePixelMapTest, ImagePixelMapCreate002, TestSize.Level3) | |||
| 2323 | 2401 | ||
| 2324 | GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapCreate002 scale end"; | 2402 | GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapCreate002 scale end"; |
| 2325 | } | 2403 | } |
| 2326 | - | ||
| 2327 | -/** | ||
| 2328 | -* @tc.name: ImagePixelMapSLRWithlap001 | ||
| 2329 | -* @tc.desc: test SLR with Laplacian | ||
| 2330 | -* @tc.type: FUNC | ||
| 2331 | -*/ | ||
| 2332 | -HWTEST_F(ImagePixelMapTest, ImagePixelMapSLRWithLap001, TestSize.Level3) | ||
| 2333 | -{ | ||
| 2334 | - GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapSLRWithLap001 scale start"; | ||
| 2335 | - std::unique_ptr<PixelMap> pixelMap = ConstructSLRPixelMap(); | ||
| 2336 | - EXPECT_NE(pixelMap, nullptr); | ||
| 2337 | - ImageInfo imageInfo; | ||
| 2338 | - pixelMap->GetImageInfo(imageInfo); | ||
| 2339 | - | ||
| 2340 | - float xAxis = 0.7f; // 0.7f scale test | ||
| 2341 | - float yAxis = 0.9f; // 0.9f scale test | ||
| 2342 | - Size desiredSize; | ||
| 2343 | - desiredSize.width = static_cast<int32_t>(imageInfo.size.width * xAxis); | ||
| 2344 | - desiredSize.height = static_cast<int32_t>(imageInfo.size.height * yAxis); | ||
| 2345 | - | ||
| 2346 | - PostProc postProc; | ||
| 2347 | - bool ret = postProc.ScalePixelMapWithSLR(desiredSize, *pixelMap.get(), true); | ||
| 2348 | - EXPECT_NE(ret, false); | ||
| 2349 | - GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapSLRWithLap001 scale end"; | ||
| 2350 | -} | ||
| 2351 | - | ||
| 2352 | -/** | ||
| 2353 | -* @tc.name: ImagePixelMapSLRWithlap002 | ||
| 2354 | -* @tc.desc: test SLR with Laplacian | ||
| 2355 | -* @tc.type: FUNC | ||
| 2356 | -*/ | ||
| 2357 | -HWTEST_F(ImagePixelMapTest, ImagePixelMapSLRWithlap002, TestSize.Level3) | ||
| 2358 | -{ | ||
| 2359 | - GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapSLRWithlap002 scale start"; | ||
| 2360 | - std::unique_ptr<PixelMap> pixelMap = ConstructSLRPixelMap(); | ||
| 2361 | - EXPECT_NE(pixelMap, nullptr); | ||
| 2362 | - ImageInfo imageInfo; | ||
| 2363 | - pixelMap->GetImageInfo(imageInfo); | ||
| 2364 | - | ||
| 2365 | - float xAxis = 0.7f; // 0.7f scale test | ||
| 2366 | - float yAxis = 0.9f; // 0.9f scale test | ||
| 2367 | - Size desiredSize; | ||
| 2368 | - desiredSize.width = static_cast<int32_t>(imageInfo.size.width * xAxis); | ||
| 2369 | - desiredSize.height = static_cast<int32_t>(imageInfo.size.height * yAxis); | ||
| 2370 | - | ||
| 2371 | - PostProc postProc; | ||
| 2372 | - bool ret = postProc.ScalePixelMapWithSLR(desiredSize, *pixelMap.get(), false); | ||
| 2373 | - EXPECT_NE(ret, false); | ||
| 2374 | - GTEST_LOG_(INFO) << "ImagePixelMapTest: ImagePixelMapSLRWithlap002 scale end"; | ||
| 2375 | -} | ||
| 2376 | } // namespace Multimedia | 2404 | } // namespace Multimedia |
| 2377 | } // namespace OHOS | 2405 | } // namespace OHOS |
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| @@ -3796,6 +3797,64 @@ HWTEST_F(PixelMapTest, RotateApiTest001, TestSize.Level3) | |||
| 3796 | GTEST_LOG_(INFO) << "PixelMapTest: RotateApiTest001 end"; | 3797 | GTEST_LOG_(INFO) << "PixelMapTest: RotateApiTest001 end"; |
| 3797 | } | 3798 | } |
| 3798 | 3799 | ||
| 3800 | +/** | ||
| 3801 | + * @tc.name: TransformApiInvalidFloatTest001 | ||
| 3802 | + * @tc.desc: Verify transform APIs reject non-finite and overflowing float parameters without changing image size. | ||
| 3803 | + * @tc.type: FUNC | ||
| 3804 | + */ | ||
| 3805 | +HWTEST_F(PixelMapTest, TransformApiInvalidFloatTest001, TestSize.Level3) | ||
| 3806 | +{ | ||
| 3807 | + auto [pixelMap, errCode] = CreateTransformApiPixelMap(PixelFormat::RGBA_8888, 4, 2); | ||
| 3808 | + ASSERT_EQ(errCode, SUCCESS); | ||
| 3809 | + ASSERT_NE(pixelMap, nullptr); | ||
| 3810 | + | ||
| 3811 | + const float nan = std::numeric_limits<float>::quiet_NaN(); | ||
| 3812 | + const float infinity = std::numeric_limits<float>::infinity(); | ||
| 3813 | + const float maxFloat = std::numeric_limits<float>::max(); | ||
| 3814 | + EXPECT_EQ(pixelMap->Scale(nan, 1.0f, AntiAliasingOption::NONE), ERR_IMAGE_INVALID_PARAMETER); | ||
| 3815 | + EXPECT_EQ(pixelMap->Scale(maxFloat, 1.0f, AntiAliasingOption::NONE), ERR_IMAGE_INVALID_PARAMETER); | ||
| 3816 | + EXPECT_EQ(pixelMap->Translate(infinity, 0.0f), ERR_IMAGE_INVALID_PARAMETER); | ||
| 3817 | + EXPECT_EQ(pixelMap->Translate(maxFloat, 0.0f), ERR_IMAGE_INVALID_PARAMETER); | ||
| 3818 | + EXPECT_EQ(pixelMap->Rotate(nan), ERR_IMAGE_INVALID_PARAMETER); | ||
| 3819 | + EXPECT_FALSE(pixelMap->resize(1.0f, infinity)); | ||
| 3820 | + EXPECT_EQ(pixelMap->GetWidth(), 4); | ||
| 3821 | + EXPECT_EQ(pixelMap->GetHeight(), 2); | ||
| 3822 | +} | ||
| 3823 | + | ||
| 3824 | +/** | ||
| 3825 | + * @tc.name: SetAlphaInvalidFloatTest001 | ||
| 3826 | + * @tc.desc: Verify SetAlpha rejects NaN instead of passing it to pixel conversion. | ||
| 3827 | + * @tc.type: FUNC | ||
| 3828 | + */ | ||
| 3829 | +HWTEST_F(PixelMapTest, SetAlphaInvalidFloatTest001, TestSize.Level3) | ||
| 3830 | +{ | ||
| 3831 | + auto [pixelMap, errCode] = CreateTransformApiPixelMap(PixelFormat::RGBA_8888, 4, 2); | ||
| 3832 | + ASSERT_EQ(errCode, SUCCESS); | ||
| 3833 | + ASSERT_NE(pixelMap, nullptr); | ||
| 3834 | + | ||
| 3835 | + const float nan = std::numeric_limits<float>::quiet_NaN(); | ||
| 3836 | + EXPECT_EQ(pixelMap->SetAlpha(nan), ERR_IMAGE_INVALID_PARAMETER); | ||
| 3837 | + EXPECT_EQ(pixelMap->GetWidth(), 4); | ||
| 3838 | + EXPECT_EQ(pixelMap->GetHeight(), 2); | ||
| 3839 | +} | ||
| 3840 | + | ||
| 3841 | +/** | ||
| 3842 | + * @tc.name: CropApiOverflowTest001 | ||
| 3843 | + * @tc.desc: Verify crop rejects a rectangle whose coordinates overflow without changing image size. | ||
| 3844 | + * @tc.type: FUNC | ||
| 3845 | + */ | ||
| 3846 | +HWTEST_F(PixelMapTest, CropApiOverflowTest001, TestSize.Level3) | ||
| 3847 | +{ | ||
| 3848 | + auto [pixelMap, errCode] = CreateTransformApiPixelMap(PixelFormat::RGBA_8888, 4, 2); | ||
| 3849 | + ASSERT_EQ(errCode, SUCCESS); | ||
| 3850 | + ASSERT_NE(pixelMap, nullptr); | ||
| 3851 | + | ||
| 3852 | + Rect rect = {std::numeric_limits<int32_t>::max(), 0, std::numeric_limits<int32_t>::max(), 1}; | ||
| 3853 | + EXPECT_EQ(pixelMap->Crop(rect), ERR_IMAGE_INVALID_PARAMETER); | ||
| 3854 | + EXPECT_EQ(pixelMap->GetWidth(), 4); | ||
| 3855 | + EXPECT_EQ(pixelMap->GetHeight(), 2); | ||
| 3856 | +} | ||
| 3857 | + | ||
| 3799 | /** | 3858 | /** |
| 3800 | * @tc.name: FlipApiTest001 | 3859 | * @tc.name: FlipApiTest001 |
| 3801 | * @tc.desc: Verify Flip succeeds for RGBA_8888 and NV21 PixelMaps. [AUTO-GENERATED] | 3860 | * @tc.desc: Verify Flip succeeds for RGBA_8888 and NV21 PixelMaps. [AUTO-GENERATED] |
| @@ -14,11 +14,13 @@ | |||
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | + | ||
| 17 | 18 | ||
| 18 | 19 | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| 23 | + | ||
| 22 | 24 | ||
| 23 | 25 | ||
| 24 | 26 | ||
| @@ -48,6 +50,22 @@ public: | |||
| 48 | ~PixelMapNdk2Test() {} | 50 | ~PixelMapNdk2Test() {} |
| 49 | }; | 51 | }; |
| 50 | 52 | ||
| 53 | +class AntiAliasingOptionRecordingPixelMap : public PixelMap { | ||
| 54 | +public: | ||
| 55 | + void scale(float, float, const AntiAliasingOption &option) override | ||
| 56 | + { | ||
| 57 | + lastOption_ = option; | ||
| 58 | + } | ||
| 59 | + | ||
| 60 | + uint32_t Scale(float, float, AntiAliasingOption option) override | ||
| 61 | + { | ||
| 62 | + lastOption_ = option; | ||
| 63 | + return SUCCESS; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + AntiAliasingOption lastOption_ = AntiAliasingOption::HIGH; | ||
| 67 | +}; | ||
| 68 | + | ||
| 51 | const int32_t ZERO = 0; | 69 | const int32_t ZERO = 0; |
| 52 | const int32_t ONE = 1; | 70 | const int32_t ONE = 1; |
| 53 | const int32_t TWO = 2; | 71 | const int32_t TWO = 2; |
| @@ -2793,6 +2811,51 @@ HWTEST_F(PixelMapNdk2Test, OH_PixelmapNative_ApplyScaleWithAntiAliasing_Failure, | |||
| 2793 | GTEST_LOG_(INFO) << "PixelMapNdk2Test: OH_PixelmapNative_ApplyScaleWithAntiAliasing_Failure end"; | 2811 | GTEST_LOG_(INFO) << "PixelMapNdk2Test: OH_PixelmapNative_ApplyScaleWithAntiAliasing_Failure end"; |
| 2794 | } | 2812 | } |
| 2795 | 2813 | ||
| 2814 | +/** | ||
| 2815 | + * @tc.name: OH_PixelmapNative_AntiAliasingLevel_OutOfRangeUsesNone | ||
| 2816 | + * @tc.desc: Use NONE for anti-aliasing levels outside the public enum range. | ||
| 2817 | + * @tc.type: FUNC | ||
| 2818 | + */ | ||
| 2819 | +HWTEST_F(PixelMapNdk2Test, OH_PixelmapNative_AntiAliasingLevel_OutOfRangeUsesNone, TestSize.Level3) | ||
| 2820 | +{ | ||
| 2821 | + const auto belowRange = static_cast<OH_PixelmapNative_AntiAliasingLevel>(-1); | ||
| 2822 | + const auto aboveRange = static_cast<OH_PixelmapNative_AntiAliasingLevel>( | ||
| 2823 | + static_cast<int32_t>(OH_PixelmapNative_AntiAliasing_HIGH) + 1); | ||
| 2824 | + | ||
| 2825 | + auto recordingPixelmap = std::make_shared<AntiAliasingOptionRecordingPixelMap>(); | ||
| 2826 | + OH_PixelmapNative nativeRecordingPixelmap(recordingPixelmap); | ||
| 2827 | + EXPECT_EQ(OH_PixelmapNative_ApplyScaleWithAntiAliasing( | ||
| 2828 | + &nativeRecordingPixelmap, 0.5f, 0.5f, aboveRange), IMAGE_SUCCESS); | ||
| 2829 | + EXPECT_EQ(recordingPixelmap->lastOption_, AntiAliasingOption::NONE); | ||
| 2830 | + | ||
| 2831 | + recordingPixelmap->lastOption_ = AntiAliasingOption::HIGH; | ||
| 2832 | + EXPECT_EQ(OH_PixelmapNative_ScaleWithAntiAliasing( | ||
| 2833 | + &nativeRecordingPixelmap, 0.5f, 0.5f, belowRange), IMAGE_SUCCESS); | ||
| 2834 | + EXPECT_EQ(recordingPixelmap->lastOption_, AntiAliasingOption::NONE); | ||
| 2835 | + | ||
| 2836 | + OH_PixelmapNative *pixelmap = CreateEmptyPixelmapNativeForTest(); | ||
| 2837 | + ASSERT_NE(pixelmap, nullptr); | ||
| 2838 | + Image_Region region = {0, 0, TWO, TWO}; | ||
| 2839 | + Image_Scale scale = {2.0f, 2.0f}; | ||
| 2840 | + OH_PixelmapNative *croppedPixelmap = nullptr; | ||
| 2841 | + EXPECT_EQ(OH_PixelmapNative_CreateCroppedAndScaledPixelMap( | ||
| 2842 | + pixelmap, ®ion, &scale, aboveRange, &croppedPixelmap), IMAGE_SUCCESS); | ||
| 2843 | + EXPECT_NE(croppedPixelmap, nullptr); | ||
| 2844 | + | ||
| 2845 | + OH_PixelmapNative *scaledPixelmap = nullptr; | ||
| 2846 | + EXPECT_EQ(OH_PixelmapNative_CreateScaledPixelMapWithAntiAliasing( | ||
| 2847 | + pixelmap, &scaledPixelmap, 2.0f, 2.0f, belowRange), IMAGE_SUCCESS); | ||
| 2848 | + EXPECT_NE(scaledPixelmap, nullptr); | ||
| 2849 | + | ||
| 2850 | + if (croppedPixelmap != nullptr) { | ||
| 2851 | + OH_PixelmapNative_Destroy(&croppedPixelmap); | ||
| 2852 | + } | ||
| 2853 | + if (scaledPixelmap != nullptr) { | ||
| 2854 | + OH_PixelmapNative_Destroy(&scaledPixelmap); | ||
| 2855 | + } | ||
| 2856 | + OH_PixelmapNative_Destroy(&pixelmap); | ||
| 2857 | +} | ||
| 2858 | + | ||
| 2796 | /** | 2859 | /** |
| 2797 | * @tc.name: OH_PixelmapNative_ApplyTranslate_Success | 2860 | * @tc.name: OH_PixelmapNative_ApplyTranslate_Success |
| 2798 | * @tc.desc: Test OH_PixelmapNative_ApplyTranslate success path. [AUTO-GENERATED] | 2861 | * @tc.desc: Test OH_PixelmapNative_ApplyTranslate success path. [AUTO-GENERATED] |
| @@ -3010,6 +3073,57 @@ HWTEST_F(PixelMapNdk2Test, OH_PixelmapNative_ApplyCrop_Failure, TestSize.Level3) | |||
| 3010 | GTEST_LOG_(INFO) << "PixelMapNdk2Test: OH_PixelmapNative_ApplyCrop_Failure end"; | 3073 | GTEST_LOG_(INFO) << "PixelMapNdk2Test: OH_PixelmapNative_ApplyCrop_Failure end"; |
| 3011 | } | 3074 | } |
| 3012 | 3075 | ||
| 3076 | +/** | ||
| 3077 | + * @tc.name: OH_PixelmapNative_ImageRegionOverflow_Failure | ||
| 3078 | + * @tc.desc: Reject Image_Region fields that cannot be represented by the inner Rect type. | ||
| 3079 | + * @tc.type: FUNC | ||
| 3080 | + */ | ||
| 3081 | +HWTEST_F(PixelMapNdk2Test, OH_PixelmapNative_ImageRegionOverflow_Failure, TestSize.Level3) | ||
| 3082 | +{ | ||
| 3083 | + constexpr uint32_t outOfRange = static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) + 1U; | ||
| 3084 | + Image_Region invalidRegions[] = { | ||
| 3085 | + {outOfRange, 0, 1, 1}, | ||
| 3086 | + {0, outOfRange, 1, 1}, | ||
| 3087 | + {0, 0, outOfRange, 1}, | ||
| 3088 | + {0, 0, 1, outOfRange}, | ||
| 3089 | + }; | ||
| 3090 | + | ||
| 3091 | + OH_PixelmapNative *pixelmap = CreateEmptyPixelmapNativeForTest(); | ||
| 3092 | + ASSERT_NE(pixelmap, nullptr); | ||
| 3093 | + uint32_t widthBefore = 0; | ||
| 3094 | + uint32_t heightBefore = 0; | ||
| 3095 | + ASSERT_TRUE(GetPixelmapNativeImageInfoForTest(pixelmap, widthBefore, heightBefore)); | ||
| 3096 | + | ||
| 3097 | + uint8_t pixels[ARGB_8888_BYTES] = {}; | ||
| 3098 | + Image_PositionArea area = { | ||
| 3099 | + .pixels = pixels, | ||
| 3100 | + .pixelsSize = sizeof(pixels), | ||
| 3101 | + .offset = 0, | ||
| 3102 | + .stride = sizeof(pixels), | ||
| 3103 | + .region = {0, 0, 1, 1}, | ||
| 3104 | + }; | ||
| 3105 | + Image_Scale scale = {1.0f, 1.0f}; | ||
| 3106 | + for (auto ®ion : invalidRegions) { | ||
| 3107 | + area.region = region; | ||
| 3108 | + EXPECT_EQ(OH_PixelmapNative_ReadPixelsFromArea(pixelmap, &area), IMAGE_BAD_PARAMETER); | ||
| 3109 | + EXPECT_EQ(OH_PixelmapNative_WritePixelsToArea(pixelmap, &area), IMAGE_BAD_PARAMETER); | ||
| 3110 | + | ||
| 3111 | + OH_PixelmapNative *dstPixelmap = nullptr; | ||
| 3112 | + EXPECT_EQ(OH_PixelmapNative_CreateCroppedAndScaledPixelMap( | ||
| 3113 | + pixelmap, ®ion, &scale, OH_PixelmapNative_AntiAliasing_NONE, &dstPixelmap), IMAGE_BAD_PARAMETER); | ||
| 3114 | + EXPECT_EQ(dstPixelmap, nullptr); | ||
| 3115 | + EXPECT_EQ(OH_PixelmapNative_ApplyCrop(pixelmap, ®ion), IMAGE_INVALID_REGION); | ||
| 3116 | + EXPECT_EQ(OH_PixelmapNative_Crop(pixelmap, ®ion), IMAGE_BAD_PARAMETER); | ||
| 3117 | + } | ||
| 3118 | + | ||
| 3119 | + uint32_t widthAfter = 0; | ||
| 3120 | + uint32_t heightAfter = 0; | ||
| 3121 | + ASSERT_TRUE(GetPixelmapNativeImageInfoForTest(pixelmap, widthAfter, heightAfter)); | ||
| 3122 | + EXPECT_EQ(widthAfter, widthBefore); | ||
| 3123 | + EXPECT_EQ(heightAfter, heightBefore); | ||
| 3124 | + OH_PixelmapNative_Destroy(&pixelmap); | ||
| 3125 | +} | ||
| 3126 | + | ||
| 3013 | /** | 3127 | /** |
| 3014 | * @tc.name: OH_PixelmapNative_ConvertAlphaType_Success | 3128 | * @tc.name: OH_PixelmapNative_ConvertAlphaType_Success |
| 3015 | * @tc.desc: Test OH_PixelmapNative_ConvertAlphaType success path. [AUTO-GENERATED] | 3129 | * @tc.desc: Test OH_PixelmapNative_ConvertAlphaType success path. [AUTO-GENERATED] |
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| @@ -29,6 +30,7 @@ | |||
| 29 | 30 | ||
| 30 | 31 | ||
| 31 | 32 | ||
| 33 | + | ||
| 32 | 34 | ||
| 33 | 35 | ||
| 34 | using namespace testing::ext; | 36 | using namespace testing::ext; |
| @@ -66,6 +68,48 @@ public: | |||
| 66 | ~PostProcTest() {} | 68 | ~PostProcTest() {} |
| 67 | }; | 69 | }; |
| 68 | 70 | ||
| 71 | +/** | ||
| 72 | + * @tc.name: SLRMatRejectsInvalidBufferLayout | ||
| 73 | + * @tc.desc: Reject row strides and buffer capacities that cannot cover the last pixel. | ||
| 74 | + * @tc.type: FUNC | ||
| 75 | + */ | ||
| 76 | +HWTEST_F(PostProcTest, SLRMatRejectsInvalidBufferLayout, TestSize.Level3) | ||
| 77 | +{ | ||
| 78 | + constexpr Size size = { 4, 3 }; | ||
| 79 | + uint32_t pixels[12] = {}; | ||
| 80 | + | ||
| 81 | + SLRMat valid(size, PixelFormat::RGBA_8888, pixels, 4, sizeof(pixels)); | ||
| 82 | + EXPECT_TRUE(valid.IsValid()); | ||
| 83 | + | ||
| 84 | + SLRMat shortStride(size, PixelFormat::RGBA_8888, pixels, 3, sizeof(pixels)); | ||
| 85 | + EXPECT_FALSE(shortStride.IsValid()); | ||
| 86 | + | ||
| 87 | + SLRMat shortBuffer(size, PixelFormat::RGBA_8888, pixels, 4, sizeof(pixels) - sizeof(uint32_t)); | ||
| 88 | + EXPECT_FALSE(shortBuffer.IsValid()); | ||
| 89 | + | ||
| 90 | + SLRMat hugeStride(size, PixelFormat::RGBA_8888, pixels, std::numeric_limits<int32_t>::max(), sizeof(pixels)); | ||
| 91 | + EXPECT_FALSE(hugeStride.IsValid()); | ||
| 92 | +} | ||
| 93 | + | ||
| 94 | +/** | ||
| 95 | + * @tc.name: SLRProcRejectsInvalidDestinationCapacity | ||
| 96 | + * @tc.desc: Do not run SLR when the destination buffer cannot cover its declared layout. | ||
| 97 | + * @tc.type: FUNC | ||
| 98 | + */ | ||
| 99 | +HWTEST_F(PostProcTest, SLRProcRejectsInvalidDestinationCapacity, TestSize.Level3) | ||
| 100 | +{ | ||
| 101 | + constexpr Size srcSize = { 4, 4 }; | ||
| 102 | + constexpr Size dstSize = { 2, 2 }; | ||
| 103 | + uint32_t srcPixels[16] = {}; | ||
| 104 | + uint32_t dstPixels[3] = {}; | ||
| 105 | + SLRMat src(srcSize, PixelFormat::RGBA_8888, srcPixels, 4, sizeof(srcPixels)); | ||
| 106 | + SLRMat dst(dstSize, PixelFormat::RGBA_8888, dstPixels, 2, sizeof(dstPixels)); | ||
| 107 | + auto weightX = SLRProc::GetWeights(0.5f, dstSize.width); | ||
| 108 | + auto weightY = SLRProc::GetWeights(0.5f, dstSize.height); | ||
| 109 | + | ||
| 110 | + EXPECT_FALSE(SLRProc::Serial(src, dst, weightX, weightY)); | ||
| 111 | +} | ||
| 112 | + | ||
| 69 | /** | 113 | /** |
| 70 | * @tc.name: PostProcTest001 | 114 | * @tc.name: PostProcTest001 |
| 71 | * @tc.desc: test DecodePostProc | 115 | * @tc.desc: test DecodePostProc |
| @@ -1927,4 +1971,4 @@ HWTEST_F(PostProcTest, ScalePixelMapExYuvTest004, TestSize.Level3) | |||
| 1927 | GTEST_LOG_(INFO) << "PostProcTest: ScalePixelMapExYuvTest004 end"; | 1971 | GTEST_LOG_(INFO) << "PostProcTest: ScalePixelMapExYuvTest004 end"; |
| 1928 | } | 1972 | } |
| 1929 | } | 1973 | } |
| 1930 | -} | 1974 | +} |
| @@ -16,7 +16,9 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 21 | + | ||
| 20 | 22 | ||
| 21 | 23 | ||
| 22 | 24 | ||
| @@ -89,6 +91,32 @@ bool ImageNapiUtils::GetInt32ByName(napi_env env, napi_value root, const char* n | |||
| 89 | return true; | 91 | return true; |
| 90 | } | 92 | } |
| 91 | 93 | ||
| 94 | +bool ImageNapiUtils::GetInt32ByNameWithRange(napi_env env, napi_value root, const char* name, int32_t *res) | ||
| 95 | +{ | ||
| 96 | + double value = 0.0; | ||
| 97 | + IMG_NAPI_CHECK_RET(GetDoubleByName(env, root, name, &value), false); | ||
| 98 | + return ConvertDoubleToInt32(value, res); | ||
| 99 | +} | ||
| 100 | + | ||
| 101 | +bool ImageNapiUtils::ConvertDoubleToInt32(double value, int32_t *res) | ||
| 102 | +{ | ||
| 103 | + IMG_NAPI_CHECK_RET(res != nullptr, false); | ||
| 104 | + constexpr double int32Min = static_cast<double>(std::numeric_limits<int32_t>::min()); | ||
| 105 | + constexpr double int32Max = static_cast<double>(std::numeric_limits<int32_t>::max()); | ||
| 106 | + IMG_NAPI_CHECK_RET(std::isfinite(value) && value >= int32Min && value <= int32Max, false); | ||
| 107 | + *res = static_cast<int32_t>(value); | ||
| 108 | + return true; | ||
| 109 | +} | ||
| 110 | + | ||
| 111 | +bool ImageNapiUtils::ConvertDoubleToFloat(double value, float *res) | ||
| 112 | +{ | ||
| 113 | + IMG_NAPI_CHECK_RET(res != nullptr, false); | ||
| 114 | + constexpr double floatMax = static_cast<double>(std::numeric_limits<float>::max()); | ||
| 115 | + IMG_NAPI_CHECK_RET(std::isfinite(value) && value >= -floatMax && value <= floatMax, false); | ||
| 116 | + *res = static_cast<float>(value); | ||
| 117 | + return true; | ||
| 118 | +} | ||
| 119 | + | ||
| 92 | bool ImageNapiUtils::GetDoubleByName(napi_env env, napi_value root, const char* name, double *res) | 120 | bool ImageNapiUtils::GetDoubleByName(napi_env env, napi_value root, const char* name, double *res) |
| 93 | { | 121 | { |
| 94 | napi_value tempValue = nullptr; | 122 | napi_value tempValue = nullptr; |
| @@ -85,15 +85,6 @@ static ScaleMode ParseScaleMode(int32_t val) | |||
| 85 | return ScaleMode::FIT_TARGET_SIZE; | 85 | return ScaleMode::FIT_TARGET_SIZE; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | -static AntiAliasingOption ParseAntiAliasingOption(int32_t val) | ||
| 89 | -{ | ||
| 90 | - if (val <= static_cast<int32_t>(AntiAliasingOption::SPLINE)) { | ||
| 91 | - return AntiAliasingOption(val); | ||
| 92 | - } | ||
| 93 | - | ||
| 94 | - return AntiAliasingOption::NONE; | ||
| 95 | -} | ||
| 96 | - | ||
| 97 | static int32_t PixelMapNapiCreate(napi_env env, PixelMapNapiArgs* args) | 88 | static int32_t PixelMapNapiCreate(napi_env env, PixelMapNapiArgs* args) |
| 98 | { | 89 | { |
| 99 | if (args == nullptr || args->outValue == nullptr) { | 90 | if (args == nullptr || args->outValue == nullptr) { |
| @@ -283,7 +274,7 @@ static int32_t PixelMapNapiScale(PixelMapNapi* native, PixelMapNapiArgs* args) | |||
| 283 | if (args->inNum0 == static_cast<int32_t>(AntiAliasingOption::NONE)) { | 274 | if (args->inNum0 == static_cast<int32_t>(AntiAliasingOption::NONE)) { |
| 284 | pixelmap->scale(args->inFloat0, args->inFloat1); | 275 | pixelmap->scale(args->inFloat0, args->inFloat1); |
| 285 | } else { | 276 | } else { |
| 286 | - pixelmap->scale(args->inFloat0, args->inFloat1, ParseAntiAliasingOption(args->inNum0)); | 277 | + pixelmap->scale(args->inFloat0, args->inFloat1, ParsePublicAntiAliasingOption(args->inNum0)); |
| 287 | } | 278 | } |
| 288 | return pixelmap->errorCode == 0 ? IMAGE_RESULT_SUCCESS : pixelmap->errorCode; | 279 | return pixelmap->errorCode == 0 ? IMAGE_RESULT_SUCCESS : pixelmap->errorCode; |
| 289 | } | 280 | } |
| @@ -168,6 +168,9 @@ public: | |||
| 168 | static bool GetBufferByName(napi_env env, napi_value root, const char* name, void **res, size_t* len); | 168 | static bool GetBufferByName(napi_env env, napi_value root, const char* name, void **res, size_t* len); |
| 169 | static bool GetUint32ByName(napi_env env, napi_value root, const char* name, uint32_t *res); | 169 | static bool GetUint32ByName(napi_env env, napi_value root, const char* name, uint32_t *res); |
| 170 | static bool GetInt32ByName(napi_env env, napi_value root, const char* name, int32_t *res); | 170 | static bool GetInt32ByName(napi_env env, napi_value root, const char* name, int32_t *res); |
| 171 | + static bool GetInt32ByNameWithRange(napi_env env, napi_value root, const char* name, int32_t *res); | ||
| 172 | + static bool ConvertDoubleToInt32(double value, int32_t *res); | ||
| 173 | + static bool ConvertDoubleToFloat(double value, float *res); | ||
| 171 | static bool GetDoubleByName(napi_env env, napi_value root, const char* name, double *res); | 174 | static bool GetDoubleByName(napi_env env, napi_value root, const char* name, double *res); |
| 172 | static bool GetBoolByName(napi_env env, napi_value root, const char* name, bool *res); | 175 | static bool GetBoolByName(napi_env env, napi_value root, const char* name, bool *res); |
| 173 | static bool GetNodeByName(napi_env env, napi_value root, const char* name, napi_value *res); | 176 | static bool GetNodeByName(napi_env env, napi_value root, const char* name, napi_value *res); |
| @@ -23,6 +23,15 @@ | |||
| 23 | 23 | ||
| 24 | namespace OHOS { | 24 | namespace OHOS { |
| 25 | namespace Media { | 25 | namespace Media { |
| 26 | +inline AntiAliasingOption ParsePublicAntiAliasingOption(int32_t value) | ||
| 27 | +{ | ||
| 28 | + if (value < static_cast<int32_t>(AntiAliasingOption::NONE) || | ||
| 29 | + value > static_cast<int32_t>(AntiAliasingOption::HIGH)) { | ||
| 30 | + return AntiAliasingOption::NONE; | ||
| 31 | + } | ||
| 32 | + return static_cast<AntiAliasingOption>(value); | ||
| 33 | +} | ||
| 34 | + | ||
| 26 | 35 | ||
| 27 | extern "C" { | 36 | extern "C" { |
| 28 | 37 | ||
| @@ -18,6 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | + | ||
| 21 | 22 | ||
| 22 | 23 | ||
| 23 | 24 | ||
| @@ -227,15 +228,6 @@ static ScaleMode ParseScaleMode(int32_t val) | |||
| 227 | return ScaleMode::FIT_TARGET_SIZE; | 228 | return ScaleMode::FIT_TARGET_SIZE; |
| 228 | } | 229 | } |
| 229 | 230 | ||
| 230 | -static AntiAliasingOption ParseAntiAliasingOption(int32_t val) | ||
| 231 | -{ | ||
| 232 | - if (val <= static_cast<int32_t>(AntiAliasingOption::SPLINE)) { | ||
| 233 | - return AntiAliasingOption(val); | ||
| 234 | - } | ||
| 235 | - | ||
| 236 | - return AntiAliasingOption::NONE; | ||
| 237 | -} | ||
| 238 | - | ||
| 239 | static bool parseSize(napi_env env, napi_value root, Size* size) | 231 | static bool parseSize(napi_env env, napi_value root, Size* size) |
| 240 | { | 232 | { |
| 241 | if (size == nullptr) { | 233 | if (size == nullptr) { |
| @@ -322,7 +314,7 @@ ImageType PixelMapNapi::ParserImageType(napi_env env, napi_value argv) | |||
| 322 | return ImageType::TYPE_UNKNOWN; | 314 | return ImageType::TYPE_UNKNOWN; |
| 323 | } | 315 | } |
| 324 | 316 | ||
| 325 | -static bool parseRegion(napi_env env, napi_value root, Rect* region) | 317 | +static bool parseRegion(napi_env env, napi_value root, Rect* region, bool checkRange = false) |
| 326 | { | 318 | { |
| 327 | napi_value tmpValue = nullptr; | 319 | napi_value tmpValue = nullptr; |
| 328 | 320 | ||
| @@ -330,11 +322,15 @@ static bool parseRegion(napi_env env, napi_value root, Rect* region) | |||
| 330 | return false; | 322 | return false; |
| 331 | } | 323 | } |
| 332 | 324 | ||
| 333 | - if (!GET_INT32_BY_NAME(root, "x", region->left)) { | 325 | + auto getInt32ByName = [env, checkRange](napi_value object, const char* name, int32_t* value) { |
| 326 | + return checkRange ? ImageNapiUtils::GetInt32ByNameWithRange(env, object, name, value) : | ||
| 327 | + ImageNapiUtils::GetInt32ByName(env, object, name, value); | ||
| 328 | + }; | ||
| 329 | + if (!getInt32ByName(root, "x", ®ion->left)) { | ||
| 334 | return false; | 330 | return false; |
| 335 | } | 331 | } |
| 336 | 332 | ||
| 337 | - if (!GET_INT32_BY_NAME(root, "y", region->top)) { | 333 | + if (!getInt32ByName(root, "y", ®ion->top)) { |
| 338 | return false; | 334 | return false; |
| 339 | } | 335 | } |
| 340 | 336 | ||
| @@ -342,11 +338,11 @@ static bool parseRegion(napi_env env, napi_value root, Rect* region) | |||
| 342 | return false; | 338 | return false; |
| 343 | } | 339 | } |
| 344 | 340 | ||
| 345 | - if (!GET_INT32_BY_NAME(tmpValue, "height", region->height)) { | 341 | + if (!getInt32ByName(tmpValue, "height", ®ion->height)) { |
| 346 | return false; | 342 | return false; |
| 347 | } | 343 | } |
| 348 | 344 | ||
| 349 | - if (!GET_INT32_BY_NAME(tmpValue, "width", region->width)) { | 345 | + if (!getInt32ByName(tmpValue, "width", ®ion->width)) { |
| 350 | return false; | 346 | return false; |
| 351 | } | 347 | } |
| 352 | 348 | ||
| @@ -1921,7 +1917,14 @@ static void SetOpacityExec(napi_env env, void* data) | |||
| 1921 | return; | 1917 | return; |
| 1922 | } | 1918 | } |
| 1923 | 1919 | ||
| 1924 | - context->status = context->rPixelMap->SetAlpha(static_cast<float>(context->alpha)); | 1920 | + float opacity = 0.0f; |
| 1921 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->alpha, &opacity)) { | ||
| 1922 | + context->status = ERR_IMAGE_INVALID_PARAMETER; | ||
| 1923 | + context->errCode = ERR_IMAGE_INVALID_PARAM; | ||
| 1924 | + context->errMsg = "Invalid parameter: Opacity must be a finite value in the float range."; | ||
| 1925 | + return; | ||
| 1926 | + } | ||
| 1927 | + context->status = context->rPixelMap->SetAlpha(opacity); | ||
| 1925 | if (context->status == ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY) { | 1928 | if (context->status == ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY) { |
| 1926 | context->errCode = ERR_MEDIA_UNSUPPORT_OPERATION; | 1929 | context->errCode = ERR_MEDIA_UNSUPPORT_OPERATION; |
| 1927 | context->errMsg = "The PixelMap is locked. Release the lock before modifying the PixelMap."; | 1930 | context->errMsg = "The PixelMap is locked. Release the lock before modifying the PixelMap."; |
| @@ -2056,8 +2059,16 @@ static void ApplyScaleExec(napi_env env, void* data) | |||
| 2056 | return; | 2059 | return; |
| 2057 | } | 2060 | } |
| 2058 | 2061 | ||
| 2059 | - context->status = context->rPixelMap->Scale(static_cast<float>(context->xArg), static_cast<float>(context->yArg), | 2062 | + float scaleX = 0.0f; |
| 2060 | - context->antiAliasing); | 2063 | + float scaleY = 0.0f; |
| 2064 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->xArg, &scaleX) || | ||
| 2065 | + !ImageNapiUtils::ConvertDoubleToFloat(context->yArg, &scaleY)) { | ||
| 2066 | + context->status = ERR_IMAGE_INVALID_PARAMETER; | ||
| 2067 | + context->errCode = ERR_IMAGE_INVALID_PARAM; | ||
| 2068 | + context->errMsg = "Invalid parameter: Scale factors must be finite values in the float range."; | ||
| 2069 | + return; | ||
| 2070 | + } | ||
| 2071 | + context->status = context->rPixelMap->Scale(scaleX, scaleY, context->antiAliasing); | ||
| 2061 | HandleAffineTransformReturnStatus(context->status, context->errCode, context->errMsg, "scale"); | 2072 | HandleAffineTransformReturnStatus(context->status, context->errCode, context->errMsg, "scale"); |
| 2062 | } | 2073 | } |
| 2063 | 2074 | ||
| @@ -2095,7 +2106,7 @@ napi_value PixelMapNapi::ApplyScale(napi_env env, napi_callback_info info) | |||
| 2095 | CreatePendingErrorIfAbsent(env, context->error, ERR_IMAGE_INVALID_PARAM, | 2106 | CreatePendingErrorIfAbsent(env, context->error, ERR_IMAGE_INVALID_PARAM, |
| 2096 | "Invalid parameter: The 3rd argument must be a number."); | 2107 | "Invalid parameter: The 3rd argument must be a number."); |
| 2097 | } | 2108 | } |
| 2098 | - context->antiAliasing = ParseAntiAliasingOption(antiAliasing); | 2109 | + context->antiAliasing = ParsePublicAntiAliasingOption(antiAliasing); |
| 2099 | 2110 | ||
| 2100 | napi_create_promise(env, &(context->deferred), &result); | 2111 | napi_create_promise(env, &(context->deferred), &result); |
| 2101 | 2112 | ||
| @@ -2159,7 +2170,7 @@ napi_value PixelMapNapi::ApplyScaleSync(napi_env env, napi_callback_info info) | |||
| 2159 | "Invalid parameter: The 3rd argument must be a number.", true); | 2170 | "Invalid parameter: The 3rd argument must be a number.", true); |
| 2160 | return result; | 2171 | return result; |
| 2161 | } | 2172 | } |
| 2162 | - context->antiAliasing = ParseAntiAliasingOption(antiAliasing); | 2173 | + context->antiAliasing = ParsePublicAntiAliasingOption(antiAliasing); |
| 2163 | 2174 | ||
| 2164 | ApplyScaleExec(env, static_cast<void*>(context.get())); | 2175 | ApplyScaleExec(env, static_cast<void*>(context.get())); |
| 2165 | if (context->errCode != SUCCESS) { | 2176 | if (context->errCode != SUCCESS) { |
| @@ -2183,8 +2194,16 @@ static void ApplyTranslateExec(napi_env env, void* data) | |||
| 2183 | return; | 2194 | return; |
| 2184 | } | 2195 | } |
| 2185 | 2196 | ||
| 2186 | - context->status = | 2197 | + float translateX = 0.0f; |
| 2187 | - context->rPixelMap->Translate(static_cast<float>(context->xArg), static_cast<float>(context->yArg)); | 2198 | + float translateY = 0.0f; |
| 2199 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->xArg, &translateX) || | ||
| 2200 | + !ImageNapiUtils::ConvertDoubleToFloat(context->yArg, &translateY)) { | ||
| 2201 | + context->status = ERR_IMAGE_INVALID_PARAMETER; | ||
| 2202 | + context->errCode = ERR_IMAGE_INVALID_PARAM; | ||
| 2203 | + context->errMsg = "Invalid parameter: Translation values must be finite values in the float range."; | ||
| 2204 | + return; | ||
| 2205 | + } | ||
| 2206 | + context->status = context->rPixelMap->Translate(translateX, translateY); | ||
| 2188 | HandleAffineTransformReturnStatus(context->status, context->errCode, context->errMsg, "translate"); | 2207 | HandleAffineTransformReturnStatus(context->status, context->errCode, context->errMsg, "translate"); |
| 2189 | } | 2208 | } |
| 2190 | 2209 | ||
| @@ -2335,7 +2354,7 @@ napi_value PixelMapNapi::ApplyCrop(napi_env env, napi_callback_info info) | |||
| 2335 | context->rPixelMap = context->nConstructor->nativePixelMap_; | 2354 | context->rPixelMap = context->nConstructor->nativePixelMap_; |
| 2336 | } | 2355 | } |
| 2337 | 2356 | ||
| 2338 | - if (!parseRegion(env, argv[NUM_0], &(context->area.region))) { | 2357 | + if (!parseRegion(env, argv[NUM_0], &(context->area.region), true)) { |
| 2339 | CreatePendingErrorIfAbsent(env, context->error, ERR_MEDIA_INVALID_REGION, | 2358 | CreatePendingErrorIfAbsent(env, context->error, ERR_MEDIA_INVALID_REGION, |
| 2340 | "The specified region is invalid. Ensure all attributes are valid integers within the PixelMap bounds."); | 2359 | "The specified region is invalid. Ensure all attributes are valid integers within the PixelMap bounds."); |
| 2341 | } | 2360 | } |
| @@ -2386,7 +2405,7 @@ napi_value PixelMapNapi::ApplyCropSync(napi_env env, napi_callback_info info) | |||
| 2386 | } | 2405 | } |
| 2387 | context->rPixelMap = context->nConstructor->nativePixelMap_; | 2406 | context->rPixelMap = context->nConstructor->nativePixelMap_; |
| 2388 | 2407 | ||
| 2389 | - if (!parseRegion(env, argv[NUM_0], &(context->area.region))) { | 2408 | + if (!parseRegion(env, argv[NUM_0], &(context->area.region), true)) { |
| 2390 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_INVALID_REGION, "The specified region is invalid. " | 2409 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_INVALID_REGION, "The specified region is invalid. " |
| 2391 | "Ensure all attributes are valid integers within the PixelMap bounds.", true); | 2410 | "Ensure all attributes are valid integers within the PixelMap bounds.", true); |
| 2392 | return result; | 2411 | return result; |
| @@ -2414,7 +2433,14 @@ static void ApplyRotateExec(napi_env env, void* data) | |||
| 2414 | return; | 2433 | return; |
| 2415 | } | 2434 | } |
| 2416 | 2435 | ||
| 2417 | - context->status = context->rPixelMap->Rotate(static_cast<float>(context->xArg)); | 2436 | + float angle = 0.0f; |
| 2437 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->xArg, &angle)) { | ||
| 2438 | + context->status = ERR_IMAGE_INVALID_PARAMETER; | ||
| 2439 | + context->errCode = ERR_IMAGE_INVALID_PARAM; | ||
| 2440 | + context->errMsg = "Invalid parameter: Rotation angle must be a finite value in the float range."; | ||
| 2441 | + return; | ||
| 2442 | + } | ||
| 2443 | + context->status = context->rPixelMap->Rotate(angle); | ||
| 2418 | HandleAffineTransformReturnStatus(context->status, context->errCode, context->errMsg, "rotate"); | 2444 | HandleAffineTransformReturnStatus(context->status, context->errCode, context->errMsg, "rotate"); |
| 2419 | } | 2445 | } |
| 2420 | 2446 | ||
| @@ -3894,6 +3920,37 @@ static napi_value BuildClonePixelMapError(napi_env& env, int32_t errorCode) | |||
| 3894 | return ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_MEMORY_ALLOC_FAILED, "Clone PixelMap failed"); | 3920 | return ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_MEMORY_ALLOC_FAILED, "Clone PixelMap failed"); |
| 3895 | } | 3921 | } |
| 3896 | 3922 | ||
| 3923 | +struct CropScaleArgs { | ||
| 3924 | + Rect region; | ||
| 3925 | + float scaleX = 0.0f; | ||
| 3926 | + float scaleY = 0.0f; | ||
| 3927 | + bool canScale = false; | ||
| 3928 | + int32_t antiAliasing = 0; | ||
| 3929 | +}; | ||
| 3930 | + | ||
| 3931 | +static napi_value CropScaleClonePixelMap(napi_env env, PixelMapNapi* pixelMapNapi, const CropScaleArgs& args) | ||
| 3932 | +{ | ||
| 3933 | + napi_value result = nullptr; | ||
| 3934 | + napi_get_undefined(env, &result); | ||
| 3935 | + auto nativePixelMap = pixelMapNapi->GetPixelNapiInner(); | ||
| 3936 | + if (nativePixelMap != nullptr) { | ||
| 3937 | + int32_t errorCode = 0; | ||
| 3938 | + auto clonePixelMap = nativePixelMap->Clone(errorCode); | ||
| 3939 | + if (clonePixelMap == nullptr) { | ||
| 3940 | + return BuildClonePixelMapError(env, errorCode); | ||
| 3941 | + } | ||
| 3942 | + IMG_NAPI_CHECK_RET_D(SUCCESS == clonePixelMap->crop(args.region), ImageNapiUtils::ThrowExceptionError(env, | ||
| 3943 | + ERR_MEDIA_INVALID_REGION, "Crop failed, region or properties invalid"), {}); | ||
| 3944 | + if (args.canScale) { | ||
| 3945 | + clonePixelMap->scale(args.scaleX, args.scaleY, ParsePublicAntiAliasingOption(args.antiAliasing)); | ||
| 3946 | + } else { | ||
| 3947 | + IMAGE_LOGW("Scale factors are non-finite or out of float range, skip scaling"); | ||
| 3948 | + } | ||
| 3949 | + result = PixelMapNapi::CreatePixelMap(env, std::move(clonePixelMap)); | ||
| 3950 | + } | ||
| 3951 | + return result; | ||
| 3952 | +} | ||
| 3953 | + | ||
| 3897 | napi_value PixelMapNapi::CreateCroppedAndScaledPixelMapSync(napi_env env, napi_callback_info info) | 3954 | napi_value PixelMapNapi::CreateCroppedAndScaledPixelMapSync(napi_env env, napi_callback_info info) |
| 3898 | { | 3955 | { |
| 3899 | napi_value result = nullptr; | 3956 | napi_value result = nullptr; |
| @@ -3914,42 +3971,31 @@ napi_value PixelMapNapi::CreateCroppedAndScaledPixelMapSync(napi_env env, napi_c | |||
| 3914 | IMG_NAPI_CHECK_RET_D(pixelMapNapi->nativePixelMap_ != nullptr, | 3971 | IMG_NAPI_CHECK_RET_D(pixelMapNapi->nativePixelMap_ != nullptr, |
| 3915 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "native pixelmap has released"), {}); | 3972 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "native pixelmap has released"), {}); |
| 3916 | 3973 | ||
| 3917 | - IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(), | 3974 | + IMG_NAPI_CHECK_RET_D(pixelMapNapi->GetPixelNapiEditable(), ImageNapiUtils::ThrowExceptionError(env, |
| 3918 | - ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, | 3975 | + ERR_MEDIA_UNSUPPORT_OPERATION, "Pixelmap has crossed threads. CreateCroppedAndScaledPixelMapSync failed"), {}); |
| 3919 | - "Pixelmap has crossed threads. CreateCroppedAndScaledPixelMapSync failed"), {}); | ||
| 3920 | 3976 | ||
| 3921 | - IMG_NAPI_CHECK_RET_D((argCount == NUM_3 || argCount == NUM_4), | 3977 | + IMG_NAPI_CHECK_RET_D((argCount == NUM_3 || argCount == NUM_4), ImageNapiUtils::ThrowExceptionError(env, |
| 3922 | - ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Invalid argument count"), | 3978 | + ERR_MEDIA_UNSUPPORT_OPERATION, "Invalid argument count"), {}); |
| 3923 | - IMAGE_LOGE("%{public}s Invalid argument count", __func__)); | ||
| 3924 | 3979 | ||
| 3925 | - Rect region; | 3980 | + CropScaleArgs args; |
| 3926 | double xArg = 0; | 3981 | double xArg = 0; |
| 3927 | double yArg = 0; | 3982 | double yArg = 0; |
| 3928 | - int32_t antiAliasing = 0; | 3983 | + IMG_NAPI_CHECK_RET_D(parseRegion(env, argValue[NUM_0], &args.region), |
| 3929 | - IMG_NAPI_CHECK_RET_D(parseRegion(env, argValue[NUM_0], ®ion), | ||
| 3930 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_INVALID_REGION, "Invalid argument region type"), {}); | 3984 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_INVALID_REGION, "Invalid argument region type"), {}); |
| 3931 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_double(env, argValue[NUM_1], &xArg)), | 3985 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_double(env, argValue[NUM_1], &xArg)), |
| 3932 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Invalid argument x"), {}); | 3986 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Invalid argument x"), {}); |
| 3933 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_double(env, argValue[NUM_2], &yArg)), | 3987 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_double(env, argValue[NUM_2], &yArg)), |
| 3934 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Invalid argument y"), {}); | 3988 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Invalid argument y"), {}); |
| 3989 | + args.canScale = ImageNapiUtils::ConvertDoubleToFloat(xArg, &args.scaleX) && | ||
| 3990 | + ImageNapiUtils::ConvertDoubleToFloat(yArg, &args.scaleY); | ||
| 3935 | if (argCount == NUM_4) { | 3991 | if (argCount == NUM_4) { |
| 3936 | - IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_int32(env, argValue[NUM_3], &antiAliasing)), | 3992 | + IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_int32(env, argValue[NUM_3], &args.antiAliasing)), |
| 3937 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Invalid antiAliasing"), {}); | 3993 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Invalid antiAliasing"), {}); |
| 3938 | - IMG_NAPI_CHECK_RET_D(antiAliasing >= static_cast<int32_t>(NUM_0) && antiAliasing <= static_cast<int32_t>(NUM_3), | 3994 | + IMG_NAPI_CHECK_RET_D(args.antiAliasing >= static_cast<int32_t>(AntiAliasingOption::NONE) && |
| 3995 | + args.antiAliasing <= static_cast<int32_t>(AntiAliasingOption::HIGH), | ||
| 3939 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Not support antiAliasing"), {}); | 3996 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Not support antiAliasing"), {}); |
| 3940 | } | 3997 | } |
| 3941 | - if (pixelMapNapi->nativePixelMap_ != nullptr) { | 3998 | + return CropScaleClonePixelMap(env, pixelMapNapi, args); |
| 3942 | - int32_t errorCode = 0; | ||
| 3943 | - auto clonePixelMap = pixelMapNapi->nativePixelMap_->Clone(errorCode); | ||
| 3944 | - if (clonePixelMap == nullptr) { | ||
| 3945 | - return BuildClonePixelMapError(env, errorCode); | ||
| 3946 | - } | ||
| 3947 | - IMG_NAPI_CHECK_RET_D(SUCCESS == clonePixelMap->crop(region), ImageNapiUtils::ThrowExceptionError(env, | ||
| 3948 | - ERR_MEDIA_INVALID_REGION, "Crop failed, region or properties invalid"), {}); | ||
| 3949 | - clonePixelMap->scale(xArg, yArg, ParseAntiAliasingOption(antiAliasing)); | ||
| 3950 | - result = PixelMapNapi::CreatePixelMap(env, std::move(clonePixelMap)); | ||
| 3951 | - } | ||
| 3952 | - return result; | ||
| 3953 | } | 3999 | } |
| 3954 | 4000 | ||
| 3955 | STATIC_EXEC_FUNC(CreateCropAndScalePixelMap) | 4001 | STATIC_EXEC_FUNC(CreateCropAndScalePixelMap) |
| @@ -3961,6 +4007,13 @@ STATIC_EXEC_FUNC(CreateCropAndScalePixelMap) | |||
| 3961 | auto context = static_cast<PixelMapAsyncContext*>(data); | 4007 | auto context = static_cast<PixelMapAsyncContext*>(data); |
| 3962 | std::shared_ptr<PixelMap> pixelMap = context->wPixelMap; | 4008 | std::shared_ptr<PixelMap> pixelMap = context->wPixelMap; |
| 3963 | if (pixelMap != nullptr) { | 4009 | if (pixelMap != nullptr) { |
| 4010 | + float scaleX = 0.0f; | ||
| 4011 | + float scaleY = 0.0f; | ||
| 4012 | + bool canScale = ImageNapiUtils::ConvertDoubleToFloat(context->xArg, &scaleX) && | ||
| 4013 | + ImageNapiUtils::ConvertDoubleToFloat(context->yArg, &scaleY); | ||
| 4014 | + if (!canScale) { | ||
| 4015 | + IMAGE_LOGW("Scale factors are non-finite or out of float range, skip scaling"); | ||
| 4016 | + } | ||
| 3964 | int32_t errorCode = SUCCESS; | 4017 | int32_t errorCode = SUCCESS; |
| 3965 | auto clonePixelMap = pixelMap->Clone(errorCode); | 4018 | auto clonePixelMap = pixelMap->Clone(errorCode); |
| 3966 | if (clonePixelMap == nullptr || errorCode != SUCCESS) { | 4019 | if (clonePixelMap == nullptr || errorCode != SUCCESS) { |
| @@ -3974,7 +4027,9 @@ STATIC_EXEC_FUNC(CreateCropAndScalePixelMap) | |||
| 3974 | context->resultUint32 = NUM_2; | 4027 | context->resultUint32 = NUM_2; |
| 3975 | return; | 4028 | return; |
| 3976 | } | 4029 | } |
| 3977 | - clonePixelMap->scale(context->xArg, context->yArg, context->antiAliasing); | 4030 | + if (canScale) { |
| 4031 | + clonePixelMap->scale(scaleX, scaleY, context->antiAliasing); | ||
| 4032 | + } | ||
| 3978 | context->rPixelMap = std::move(clonePixelMap); | 4033 | context->rPixelMap = std::move(clonePixelMap); |
| 3979 | } | 4034 | } |
| 3980 | } | 4035 | } |
| @@ -4075,17 +4130,16 @@ napi_value PixelMapNapi::CreateCroppedAndScaledPixelMap(napi_env env, napi_callb | |||
| 4075 | if (argCount == NUM_4) { | 4130 | if (argCount == NUM_4) { |
| 4076 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_int32(env, argValue[NUM_3], &antiAliasing)), | 4131 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_int32(env, argValue[NUM_3], &antiAliasing)), |
| 4077 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Invalid antiAliasing"), {}); | 4132 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Invalid antiAliasing"), {}); |
| 4078 | - IMG_NAPI_CHECK_RET_D(antiAliasing >= static_cast<int32_t>(NUM_0) && antiAliasing <= static_cast<int32_t>(NUM_3), | 4133 | + IMG_NAPI_CHECK_RET_D(antiAliasing >= static_cast<int32_t>(AntiAliasingOption::NONE) && |
| 4134 | + antiAliasing <= static_cast<int32_t>(AntiAliasingOption::HIGH), | ||
| 4079 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Not support antiAliasing"), {}); | 4135 | ImageNapiUtils::ThrowExceptionError(env, ERR_MEDIA_UNSUPPORT_OPERATION, "Not support antiAliasing"), {}); |
| 4080 | - asyncContext->antiAliasing = ParseAntiAliasingOption(antiAliasing); | 4136 | + asyncContext->antiAliasing = ParsePublicAntiAliasingOption(antiAliasing); |
| 4081 | } | 4137 | } |
| 4082 | 4138 | ||
| 4083 | napi_create_promise(env, &(asyncContext->deferred), &result); | 4139 | napi_create_promise(env, &(asyncContext->deferred), &result); |
| 4084 | IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateCropAndScalePixelMap", CreateCropAndScalePixelMapExec, | 4140 | IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateCropAndScalePixelMap", CreateCropAndScalePixelMapExec, |
| 4085 | CreateCropAndScalePixelMapComplete, asyncContext, asyncContext->work); | 4141 | CreateCropAndScalePixelMapComplete, asyncContext, asyncContext->work); |
| 4086 | - IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, { | 4142 | + IMG_NAPI_CHECK_RET_D(IMG_IS_OK(status), nullptr, { NAPI_CHECK_AND_DELETE_REF(env, asyncContext->callbackRef); }); |
| 4087 | - NAPI_CHECK_AND_DELETE_REF(env, asyncContext->callbackRef); | ||
| 4088 | - }); | ||
| 4089 | return result; | 4143 | return result; |
| 4090 | } | 4144 | } |
| 4091 | 4145 | ||
| @@ -5091,8 +5145,13 @@ static void SetAlphaExec(napi_env env, PixelMapAsyncContext* context) | |||
| 5091 | } | 5145 | } |
| 5092 | if (context->status == SUCCESS) { | 5146 | if (context->status == SUCCESS) { |
| 5093 | if (context->rPixelMap != nullptr) { | 5147 | if (context->rPixelMap != nullptr) { |
| 5094 | - context->status = context->rPixelMap->SetAlpha( | 5148 | + float alpha = 0.0f; |
| 5095 | - static_cast<float>(context->alpha)); | 5149 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->alpha, &alpha)) { |
| 5150 | + IMAGE_LOGW("Alpha is non-finite or out of float range, skip setting alpha"); | ||
| 5151 | + context->status = SUCCESS; | ||
| 5152 | + return; | ||
| 5153 | + } | ||
| 5154 | + context->status = context->rPixelMap->SetAlpha(alpha); | ||
| 5096 | } else { | 5155 | } else { |
| 5097 | IMAGE_LOGE("Null native ref"); | 5156 | IMAGE_LOGE("Null native ref"); |
| 5098 | context->status = ERR_IMAGE_INIT_ABNORMAL; | 5157 | context->status = ERR_IMAGE_INIT_ABNORMAL; |
| @@ -5187,10 +5246,14 @@ napi_value PixelMapNapi::SetAlphaSync(napi_env env, napi_callback_info info) | |||
| 5187 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, | 5246 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, |
| 5188 | "Pixelmap has crossed threads . SetAlphaSync failed"), | 5247 | "Pixelmap has crossed threads . SetAlphaSync failed"), |
| 5189 | IMAGE_LOGE("Pixelmap has crossed threads . SetAlphaSync failed")); | 5248 | IMAGE_LOGE("Pixelmap has crossed threads . SetAlphaSync failed")); |
| 5249 | + float safeAlpha = 0.0f; | ||
| 5250 | + if (!ImageNapiUtils::ConvertDoubleToFloat(alpha, &safeAlpha)) { | ||
| 5251 | + IMAGE_LOGW("Alpha is non-finite or out of float range, skip setting alpha"); | ||
| 5252 | + return result; | ||
| 5253 | + } | ||
| 5190 | 5254 | ||
| 5191 | if (pixelMapNapi->nativePixelMap_ != nullptr) { | 5255 | if (pixelMapNapi->nativePixelMap_ != nullptr) { |
| 5192 | - status = pixelMapNapi->nativePixelMap_->SetAlpha( | 5256 | + status = pixelMapNapi->nativePixelMap_->SetAlpha(safeAlpha); |
| 5193 | - static_cast<float>(alpha)); | ||
| 5194 | if (status != SUCCESS) { | 5257 | if (status != SUCCESS) { |
| 5195 | IMAGE_LOGE("SetAlphaSync failed"); | 5258 | IMAGE_LOGE("SetAlphaSync failed"); |
| 5196 | } | 5259 | } |
| @@ -5208,11 +5271,18 @@ static void ScaleExec(napi_env env, PixelMapAsyncContext* context) | |||
| 5208 | } | 5271 | } |
| 5209 | if (context->status == SUCCESS) { | 5272 | if (context->status == SUCCESS) { |
| 5210 | if (context->rPixelMap != nullptr) { | 5273 | if (context->rPixelMap != nullptr) { |
| 5274 | + float scaleX = 0.0f; | ||
| 5275 | + float scaleY = 0.0f; | ||
| 5276 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->xArg, &scaleX) || | ||
| 5277 | + !ImageNapiUtils::ConvertDoubleToFloat(context->yArg, &scaleY)) { | ||
| 5278 | + IMAGE_LOGW("Scale factors are non-finite or out of float range, skip scaling"); | ||
| 5279 | + context->status = SUCCESS; | ||
| 5280 | + return; | ||
| 5281 | + } | ||
| 5211 | if (context->antiAliasing == AntiAliasingOption::NONE) { | 5282 | if (context->antiAliasing == AntiAliasingOption::NONE) { |
| 5212 | - context->rPixelMap->scale(static_cast<float>(context->xArg), static_cast<float>(context->yArg)); | 5283 | + context->rPixelMap->scale(scaleX, scaleY); |
| 5213 | } else { | 5284 | } else { |
| 5214 | - context->rPixelMap->scale(static_cast<float>(context->xArg), static_cast<float>(context->yArg), | 5285 | + context->rPixelMap->scale(scaleX, scaleY, context->antiAliasing); |
| 5215 | - context->antiAliasing); | ||
| 5216 | } | 5286 | } |
| 5217 | context->status = SUCCESS; | 5287 | context->status = SUCCESS; |
| 5218 | } else { | 5288 | } else { |
| @@ -5234,7 +5304,7 @@ static void NapiParseCallbackOrAntiAliasing(napi_env &env, NapiValues &nVal, int | |||
| 5234 | IMAGE_LOGE("Arg %{public}d type mismatch", argi); | 5304 | IMAGE_LOGE("Arg %{public}d type mismatch", argi); |
| 5235 | nVal.context->status = ERR_IMAGE_INVALID_PARAMETER; | 5305 | nVal.context->status = ERR_IMAGE_INVALID_PARAMETER; |
| 5236 | } | 5306 | } |
| 5237 | - nVal.context->antiAliasing = ParseAntiAliasingOption(antiAliasing); | 5307 | + nVal.context->antiAliasing = ParsePublicAntiAliasingOption(antiAliasing); |
| 5238 | } | 5308 | } |
| 5239 | } | 5309 | } |
| 5240 | 5310 | ||
| @@ -5310,8 +5380,7 @@ napi_value PixelMapNapi::ScaleSync(napi_env env, napi_callback_info info) | |||
| 5310 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to arg info")); | 5380 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napiStatus), result, IMAGE_LOGE("fail to arg info")); |
| 5311 | 5381 | ||
| 5312 | IMG_NAPI_CHECK_RET_D(argCount == NUM_2 || argCount == NUM_3, | 5382 | IMG_NAPI_CHECK_RET_D(argCount == NUM_2 || argCount == NUM_3, |
| 5313 | - ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, | 5383 | + ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, "Invalid args count"), |
| 5314 | - "Invalid args count"), | ||
| 5315 | IMAGE_LOGE("Invalid args count %{public}zu", argCount)); | 5384 | IMAGE_LOGE("Invalid args count %{public}zu", argCount)); |
| 5316 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_double(env, argValue[NUM_0], &xArg)), | 5385 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_double(env, argValue[NUM_0], &xArg)), |
| 5317 | result, IMAGE_LOGE("Arg 0 type mismatch")); | 5386 | result, IMAGE_LOGE("Arg 0 type mismatch")); |
| @@ -5329,13 +5398,18 @@ napi_value PixelMapNapi::ScaleSync(napi_env env, napi_callback_info info) | |||
| 5329 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, | 5398 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, |
| 5330 | "Pixelmap has crossed threads . ScaleSync failed"), | 5399 | "Pixelmap has crossed threads . ScaleSync failed"), |
| 5331 | IMAGE_LOGE("Pixelmap has crossed threads . ScaleSync failed")); | 5400 | IMAGE_LOGE("Pixelmap has crossed threads . ScaleSync failed")); |
| 5401 | + float scaleX = 0.0f; | ||
| 5402 | + float scaleY = 0.0f; | ||
| 5403 | + if (!ImageNapiUtils::ConvertDoubleToFloat(xArg, &scaleX) || !ImageNapiUtils::ConvertDoubleToFloat(yArg, &scaleY)) { | ||
| 5404 | + IMAGE_LOGW("Scale factors are non-finite or out of float range, skip scaling"); | ||
| 5405 | + return result; | ||
| 5406 | + } | ||
| 5332 | 5407 | ||
| 5333 | if (pixelMapNapi->nativePixelMap_ != nullptr) { | 5408 | if (pixelMapNapi->nativePixelMap_ != nullptr) { |
| 5334 | if (antiAliasing == 0) { | 5409 | if (antiAliasing == 0) { |
| 5335 | - pixelMapNapi->nativePixelMap_->scale(static_cast<float>(xArg), static_cast<float>(yArg)); | 5410 | + pixelMapNapi->nativePixelMap_->scale(scaleX, scaleY); |
| 5336 | } else { | 5411 | } else { |
| 5337 | - pixelMapNapi->nativePixelMap_->scale(static_cast<float>(xArg), static_cast<float>(yArg), | 5412 | + pixelMapNapi->nativePixelMap_->scale(scaleX, scaleY, ParsePublicAntiAliasingOption(antiAliasing)); |
| 5338 | - ParseAntiAliasingOption(antiAliasing)); | ||
| 5339 | } | 5413 | } |
| 5340 | } else { | 5414 | } else { |
| 5341 | IMAGE_LOGE("Null native ref"); | 5415 | IMAGE_LOGE("Null native ref"); |
| @@ -5349,28 +5423,36 @@ static void CreateScaledPixelMapExec(napi_env env, PixelMapAsyncContext* context | |||
| 5349 | IMAGE_LOGE("Null context"); | 5423 | IMAGE_LOGE("Null context"); |
| 5350 | return; | 5424 | return; |
| 5351 | } | 5425 | } |
| 5352 | - if (context->status == SUCCESS) { | 5426 | + if (context->status != SUCCESS) { |
| 5353 | - if (context->rPixelMap != nullptr) { | 5427 | + IMAGE_LOGD("CreateScaledPixelMap has failed, do nothing"); |
| 5354 | - InitializationOptions opts; | 5428 | + return; |
| 5355 | - std::unique_ptr<PixelMap> clonePixelMap = PixelMap::Create(*(context->rPixelMap), opts); | 5429 | + } |
| 5356 | - if (clonePixelMap == nullptr) { | 5430 | + |
| 5357 | - IMAGE_LOGE("Null clonePixelMap"); | 5431 | + if (context->rPixelMap != nullptr) { |
| 5358 | - return; | 5432 | + float scaleX = 0.0f; |
| 5359 | - } | 5433 | + float scaleY = 0.0f; |
| 5360 | - if (context->antiAliasing == AntiAliasingOption::NONE) { | 5434 | + bool canScale = ImageNapiUtils::ConvertDoubleToFloat(context->xArg, &scaleX) && |
| 5361 | - clonePixelMap->scale(static_cast<float>(context->xArg), static_cast<float>(context->yArg)); | 5435 | + ImageNapiUtils::ConvertDoubleToFloat(context->yArg, &scaleY); |
| 5362 | - } else { | 5436 | + InitializationOptions opts; |
| 5363 | - clonePixelMap->scale(static_cast<float>(context->xArg), static_cast<float>(context->yArg), | 5437 | + std::unique_ptr<PixelMap> clonePixelMap = PixelMap::Create(*(context->rPixelMap), opts); |
| 5364 | - context->antiAliasing); | 5438 | + if (clonePixelMap == nullptr) { |
| 5365 | - } | 5439 | + IMAGE_LOGE("Null clonePixelMap"); |
| 5366 | - context->alphaMap = std::move(clonePixelMap); | 5440 | + return; |
| 5367 | - context->status = SUCCESS; | ||
| 5368 | - } else { | ||
| 5369 | - IMAGE_LOGE("Null native ref"); | ||
| 5370 | - context->status = COMMON_ERR_INVALID_PARAMETER; | ||
| 5371 | } | 5441 | } |
| 5442 | + if (canScale) { | ||
| 5443 | + if (context->antiAliasing == AntiAliasingOption::NONE) { | ||
| 5444 | + clonePixelMap->scale(scaleX, scaleY); | ||
| 5445 | + } else { | ||
| 5446 | + clonePixelMap->scale(scaleX, scaleY, context->antiAliasing); | ||
| 5447 | + } | ||
| 5448 | + } else { | ||
| 5449 | + IMAGE_LOGW("Scale factors are non-finite or out of float range, skip scaling"); | ||
| 5450 | + } | ||
| 5451 | + context->alphaMap = std::move(clonePixelMap); | ||
| 5452 | + context->status = SUCCESS; | ||
| 5372 | } else { | 5453 | } else { |
| 5373 | - IMAGE_LOGD("Scale has failed. do nothing"); | 5454 | + IMAGE_LOGE("Null native ref"); |
| 5455 | + context->status = COMMON_ERR_INVALID_PARAMETER; | ||
| 5374 | } | 5456 | } |
| 5375 | } | 5457 | } |
| 5376 | 5458 | ||
| @@ -5425,7 +5507,7 @@ napi_value PixelMapNapi::CreateScaledPixelMap(napi_env env, napi_callback_info i | |||
| 5425 | BuildContextError(env, asyncContext->error, "Arg 2 type mismatch", | 5507 | BuildContextError(env, asyncContext->error, "Arg 2 type mismatch", |
| 5426 | COMMON_ERR_INVALID_PARAMETER), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateScaledPixelMapGeneralError", | 5508 | COMMON_ERR_INVALID_PARAMETER), IMG_CREATE_CREATE_ASYNC_WORK(env, status, "CreateScaledPixelMapGeneralError", |
| 5427 | [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work), result); | 5509 | [](napi_env env, void *data) {}, GeneralErrorComplete, asyncContext, asyncContext->work), result); |
| 5428 | - asyncContext->antiAliasing = ParseAntiAliasingOption(antiAliasing); | 5510 | + asyncContext->antiAliasing = ParsePublicAntiAliasingOption(antiAliasing); |
| 5429 | } | 5511 | } |
| 5430 | status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor)); | 5512 | status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&asyncContext->nConstructor)); |
| 5431 | IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor), | 5513 | IMG_NAPI_CHECK_RET_D(IMG_IS_READY(status, asyncContext->nConstructor), |
| @@ -5461,7 +5543,7 @@ static napi_value CreateScaledPixelMapSyncPrepareArgs(napi_env env, struct NapiV | |||
| 5461 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_int32(env, nVal->argv[NUM_2], &antiAliasing)), | 5543 | IMG_NAPI_CHECK_RET_D(IMG_IS_OK(napi_get_value_int32(env, nVal->argv[NUM_2], &antiAliasing)), |
| 5462 | ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, "Arg 2 type mismatch"), | 5544 | ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, "Arg 2 type mismatch"), |
| 5463 | IMAGE_LOGE("Arg 2 type mismatch")); | 5545 | IMAGE_LOGE("Arg 2 type mismatch")); |
| 5464 | - nVal->context->antiAliasing = ParseAntiAliasingOption(antiAliasing); | 5546 | + nVal->context->antiAliasing = ParsePublicAntiAliasingOption(antiAliasing); |
| 5465 | } | 5547 | } |
| 5466 | IMG_NAPI_CHECK_RET_D(nVal->context->nConstructor->GetPixelNapiEditable(), | 5548 | IMG_NAPI_CHECK_RET_D(nVal->context->nConstructor->GetPixelNapiEditable(), |
| 5467 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, | 5549 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, |
| @@ -5489,11 +5571,16 @@ napi_value PixelMapNapi::CreateScaledPixelMapSync(napi_env env, napi_callback_in | |||
| 5489 | IMG_NAPI_CHECK_RET_D(clonePixelMap != nullptr, | 5571 | IMG_NAPI_CHECK_RET_D(clonePixelMap != nullptr, |
| 5490 | ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, "Null clonePixelMap"), | 5572 | ImageNapiUtils::ThrowExceptionError(env, COMMON_ERR_INVALID_PARAMETER, "Null clonePixelMap"), |
| 5491 | IMAGE_LOGE("Null clonePixelMap")); | 5573 | IMAGE_LOGE("Null clonePixelMap")); |
| 5492 | - if (nVal.context->antiAliasing == AntiAliasingOption::NONE) { | 5574 | + float scaleX = 0.0f; |
| 5493 | - clonePixelMap->scale(static_cast<float>(nVal.context->xArg), static_cast<float>(nVal.context->yArg)); | 5575 | + float scaleY = 0.0f; |
| 5576 | + bool canScale = ImageNapiUtils::ConvertDoubleToFloat(nVal.context->xArg, &scaleX) && | ||
| 5577 | + ImageNapiUtils::ConvertDoubleToFloat(nVal.context->yArg, &scaleY); | ||
| 5578 | + if (!canScale) { | ||
| 5579 | + IMAGE_LOGW("Scale factors are non-finite or out of float range, skip scaling"); | ||
| 5580 | + } else if (nVal.context->antiAliasing == AntiAliasingOption::NONE) { | ||
| 5581 | + clonePixelMap->scale(scaleX, scaleY); | ||
| 5494 | } else { | 5582 | } else { |
| 5495 | - clonePixelMap->scale(static_cast<float>(nVal.context->xArg), static_cast<float>(nVal.context->yArg), | 5583 | + clonePixelMap->scale(scaleX, scaleY, nVal.context->antiAliasing); |
| 5496 | - nVal.context->antiAliasing); | ||
| 5497 | } | 5584 | } |
| 5498 | nVal.result = PixelMapNapi::CreatePixelMap(env, std::move(clonePixelMap)); | 5585 | nVal.result = PixelMapNapi::CreatePixelMap(env, std::move(clonePixelMap)); |
| 5499 | return nVal.result; | 5586 | return nVal.result; |
| @@ -5681,7 +5768,15 @@ static void TranslateExec(napi_env env, PixelMapAsyncContext* context) | |||
| 5681 | } | 5768 | } |
| 5682 | if (context->status == SUCCESS) { | 5769 | if (context->status == SUCCESS) { |
| 5683 | if (context->rPixelMap != nullptr) { | 5770 | if (context->rPixelMap != nullptr) { |
| 5684 | - context->rPixelMap->translate(static_cast<float>(context->xArg), static_cast<float>(context->yArg)); | 5771 | + float translateX = 0.0f; |
| 5772 | + float translateY = 0.0f; | ||
| 5773 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->xArg, &translateX) || | ||
| 5774 | + !ImageNapiUtils::ConvertDoubleToFloat(context->yArg, &translateY)) { | ||
| 5775 | + IMAGE_LOGW("Translation values are non-finite or out of float range, skip translation"); | ||
| 5776 | + context->status = SUCCESS; | ||
| 5777 | + return; | ||
| 5778 | + } | ||
| 5779 | + context->rPixelMap->translate(translateX, translateY); | ||
| 5685 | context->status = SUCCESS; | 5780 | context->status = SUCCESS; |
| 5686 | } else { | 5781 | } else { |
| 5687 | IMAGE_LOGE("Null native ref"); | 5782 | IMAGE_LOGE("Null native ref"); |
| @@ -5772,7 +5867,6 @@ napi_value PixelMapNapi::TranslateSync(napi_env env, napi_callback_info info) | |||
| 5772 | IMAGE_LOGE("get arraybuffer info failed"); | 5867 | IMAGE_LOGE("get arraybuffer info failed"); |
| 5773 | return result; | 5868 | return result; |
| 5774 | } | 5869 | } |
| 5775 | - | ||
| 5776 | PixelMapNapi* pixelMapNapi = nullptr; | 5870 | PixelMapNapi* pixelMapNapi = nullptr; |
| 5777 | status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi)); | 5871 | status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi)); |
| 5778 | 5872 | ||
| @@ -5781,9 +5875,16 @@ napi_value PixelMapNapi::TranslateSync(napi_env env, napi_callback_info info) | |||
| 5781 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, | 5875 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, |
| 5782 | "Pixelmap has crossed threads . TranslateSync failed"), | 5876 | "Pixelmap has crossed threads . TranslateSync failed"), |
| 5783 | IMAGE_LOGE("Pixelmap has crossed threads . TranslateSync failed")); | 5877 | IMAGE_LOGE("Pixelmap has crossed threads . TranslateSync failed")); |
| 5878 | + float translateX = 0.0f; | ||
| 5879 | + float translateY = 0.0f; | ||
| 5880 | + if (!ImageNapiUtils::ConvertDoubleToFloat(x, &translateX) || | ||
| 5881 | + !ImageNapiUtils::ConvertDoubleToFloat(y, &translateY)) { | ||
| 5882 | + IMAGE_LOGW("Translation values are non-finite or out of float range, skip translation"); | ||
| 5883 | + return result; | ||
| 5884 | + } | ||
| 5784 | 5885 | ||
| 5785 | if (pixelMapNapi->nativePixelMap_ != nullptr) { | 5886 | if (pixelMapNapi->nativePixelMap_ != nullptr) { |
| 5786 | - pixelMapNapi->nativePixelMap_->translate(static_cast<float>(x), static_cast<float>(y)); | 5887 | + pixelMapNapi->nativePixelMap_->translate(translateX, translateY); |
| 5787 | } else { | 5888 | } else { |
| 5788 | IMAGE_LOGE("Null native ref"); | 5889 | IMAGE_LOGE("Null native ref"); |
| 5789 | } | 5890 | } |
| @@ -5798,7 +5899,13 @@ static void RotateExec(napi_env env, PixelMapAsyncContext* context) | |||
| 5798 | } | 5899 | } |
| 5799 | if (context->status == SUCCESS) { | 5900 | if (context->status == SUCCESS) { |
| 5800 | if (context->rPixelMap != nullptr) { | 5901 | if (context->rPixelMap != nullptr) { |
| 5801 | - context->rPixelMap->rotate(context->xArg); | 5902 | + float angle = 0.0f; |
| 5903 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->xArg, &angle)) { | ||
| 5904 | + IMAGE_LOGW("Rotation angle is non-finite or out of float range, skip rotation"); | ||
| 5905 | + context->status = SUCCESS; | ||
| 5906 | + return; | ||
| 5907 | + } | ||
| 5908 | + context->rPixelMap->rotate(angle); | ||
| 5802 | context->status = SUCCESS; | 5909 | context->status = SUCCESS; |
| 5803 | } else { | 5910 | } else { |
| 5804 | IMAGE_LOGE("Null native ref"); | 5911 | IMAGE_LOGE("Null native ref"); |
| @@ -5881,7 +5988,6 @@ napi_value PixelMapNapi::RotateSync(napi_env env, napi_callback_info info) | |||
| 5881 | IMAGE_LOGE("RotateSync failed, invalid parameter")); | 5988 | IMAGE_LOGE("RotateSync failed, invalid parameter")); |
| 5882 | napiStatus = napi_get_value_double(env, argValue[NUM_0], &angle); | 5989 | napiStatus = napi_get_value_double(env, argValue[NUM_0], &angle); |
| 5883 | IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed")); | 5990 | IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed")); |
| 5884 | - | ||
| 5885 | PixelMapNapi* pixelMapNapi = nullptr; | 5991 | PixelMapNapi* pixelMapNapi = nullptr; |
| 5886 | status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi)); | 5992 | status = napi_unwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi)); |
| 5887 | 5993 | ||
| @@ -5890,9 +5996,14 @@ napi_value PixelMapNapi::RotateSync(napi_env env, napi_callback_info info) | |||
| 5890 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, | 5996 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, |
| 5891 | "Pixelmap has crossed threads . RotateSync failed"), | 5997 | "Pixelmap has crossed threads . RotateSync failed"), |
| 5892 | IMAGE_LOGE("Pixelmap has crossed threads . RotateSync failed")); | 5998 | IMAGE_LOGE("Pixelmap has crossed threads . RotateSync failed")); |
| 5999 | + float safeAngle = 0.0f; | ||
| 6000 | + if (!ImageNapiUtils::ConvertDoubleToFloat(angle, &safeAngle)) { | ||
| 6001 | + IMAGE_LOGW("Rotation angle is non-finite or out of float range, skip rotation"); | ||
| 6002 | + return result; | ||
| 6003 | + } | ||
| 5893 | 6004 | ||
| 5894 | if (pixelMapNapi->nativePixelMap_ != nullptr) { | 6005 | if (pixelMapNapi->nativePixelMap_ != nullptr) { |
| 5895 | - pixelMapNapi->nativePixelMap_->rotate(static_cast<float>(angle)); | 6006 | + pixelMapNapi->nativePixelMap_->rotate(safeAngle); |
| 5896 | } else { | 6007 | } else { |
| 5897 | IMAGE_LOGE("Null native ref"); | 6008 | IMAGE_LOGE("Null native ref"); |
| 5898 | } | 6009 | } |
| @@ -16,6 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | + | ||
| 19 | 20 | ||
| 20 | 21 | ||
| 21 | 22 | ||
| @@ -143,6 +144,24 @@ static Image_ErrorCode ToNewErrorCode(int code) | |||
| 143 | } | 144 | } |
| 144 | }; | 145 | }; |
| 145 | 146 | ||
| 147 | +static bool ConvertImageRegionToRect(const Image_Region ®ion, OHOS::Media::Rect &rect) | ||
| 148 | +{ | ||
| 149 | + constexpr uint32_t maxInt32 = static_cast<uint32_t>(std::numeric_limits<int32_t>::max()); | ||
| 150 | + if (region.x > maxInt32 || region.y > maxInt32 || region.width > maxInt32 || region.height > maxInt32) { | ||
| 151 | + IMAGE_LOGE("Image_Region exceeds int32 range, x: %{public}u, y: %{public}u, " | ||
| 152 | + "width: %{public}u, height: %{public}u", | ||
| 153 | + region.x, region.y, region.width, region.height); | ||
| 154 | + return false; | ||
| 155 | + } | ||
| 156 | + rect = { | ||
| 157 | + .left = static_cast<int32_t>(region.x), | ||
| 158 | + .top = static_cast<int32_t>(region.y), | ||
| 159 | + .width = static_cast<int32_t>(region.width), | ||
| 160 | + .height = static_cast<int32_t>(region.height) | ||
| 161 | + }; | ||
| 162 | + return true; | ||
| 163 | +} | ||
| 164 | + | ||
| 146 | static bool IsMatchType(IMAGE_FORMAT type, PixelFormat format) | 165 | static bool IsMatchType(IMAGE_FORMAT type, PixelFormat format) |
| 147 | { | 166 | { |
| 148 | if (type == IMAGE_FORMAT::IMAGE_FORMAT_YUV_TYPE) { | 167 | if (type == IMAGE_FORMAT::IMAGE_FORMAT_YUV_TYPE) { |
| @@ -797,12 +816,10 @@ Image_ErrorCode OH_PixelmapNative_ReadPixelsFromArea(OH_PixelmapNative *pixelmap | |||
| 797 | return IMAGE_BAD_PARAMETER; | 816 | return IMAGE_BAD_PARAMETER; |
| 798 | } | 817 | } |
| 799 | 818 | ||
| 800 | - OHOS::Media::Rect region = { | 819 | + OHOS::Media::Rect region; |
| 801 | - .left = static_cast<int32_t>(area->region.x), | 820 | + if (!ConvertImageRegionToRect(area->region, region)) { |
| 802 | - .top = static_cast<int32_t>(area->region.y), | 821 | + return IMAGE_BAD_PARAMETER; |
| 803 | - .width = static_cast<int32_t>(area->region.width), | 822 | + } |
| 804 | - .height = static_cast<int32_t>(area->region.height) | ||
| 805 | - }; | ||
| 806 | return ToNewErrorCode(pixelmap->GetInnerPixelmap()->ReadPixels( | 823 | return ToNewErrorCode(pixelmap->GetInnerPixelmap()->ReadPixels( |
| 807 | area->pixelsSize, area->offset, area->stride, region, area->pixels)); | 824 | area->pixelsSize, area->offset, area->stride, region, area->pixels)); |
| 808 | } | 825 | } |
| @@ -814,12 +831,10 @@ Image_ErrorCode OH_PixelmapNative_WritePixelsToArea(OH_PixelmapNative *pixelmap, | |||
| 814 | return IMAGE_BAD_PARAMETER; | 831 | return IMAGE_BAD_PARAMETER; |
| 815 | } | 832 | } |
| 816 | 833 | ||
| 817 | - OHOS::Media::Rect region = { | 834 | + OHOS::Media::Rect region; |
| 818 | - .left = static_cast<int32_t>(area->region.x), | 835 | + if (!ConvertImageRegionToRect(area->region, region)) { |
| 819 | - .top = static_cast<int32_t>(area->region.y), | 836 | + return IMAGE_BAD_PARAMETER; |
| 820 | - .width = static_cast<int32_t>(area->region.width), | 837 | + } |
| 821 | - .height = static_cast<int32_t>(area->region.height) | ||
| 822 | - }; | ||
| 823 | return ToNewErrorCode(pixelmap->GetInnerPixelmap()->WritePixels( | 838 | return ToNewErrorCode(pixelmap->GetInnerPixelmap()->WritePixels( |
| 824 | area->pixels, area->pixelsSize, area->offset, area->stride, region)); | 839 | area->pixels, area->pixelsSize, area->offset, area->stride, region)); |
| 825 | } | 840 | } |
| @@ -978,7 +993,8 @@ Image_ErrorCode OH_PixelmapNative_ApplyScaleWithAntiAliasing(OH_PixelmapNative * | |||
| 978 | return IMAGE_PIXELMAP_RELEASED; | 993 | return IMAGE_PIXELMAP_RELEASED; |
| 979 | } | 994 | } |
| 980 | 995 | ||
| 981 | - uint32_t status = pixelmap->GetInnerPixelmap()->Scale(scaleX, scaleY, static_cast<AntiAliasingOption>(level)); | 996 | + uint32_t status = pixelmap->GetInnerPixelmap()->Scale( |
| 997 | + scaleX, scaleY, ParsePublicAntiAliasingOption(static_cast<int32_t>(level))); | ||
| 982 | if (status == ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY) { | 998 | if (status == ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY) { |
| 983 | return IMAGE_UNSUPPORTED_OPERATION; | 999 | return IMAGE_UNSUPPORTED_OPERATION; |
| 984 | } else if (status == ERR_IMAGE_MALLOC_ABNORMAL) { | 1000 | } else if (status == ERR_IMAGE_MALLOC_ABNORMAL) { |
| @@ -999,7 +1015,8 @@ Image_ErrorCode OH_PixelmapNative_ScaleWithAntiAliasing(OH_PixelmapNative *pixel | |||
| 999 | if (pixelmap == nullptr) { | 1015 | if (pixelmap == nullptr) { |
| 1000 | return IMAGE_BAD_PARAMETER; | 1016 | return IMAGE_BAD_PARAMETER; |
| 1001 | } | 1017 | } |
| 1002 | - pixelmap->GetInnerPixelmap()->scale(scaleX, scaleY, static_cast<AntiAliasingOption>(level)); | 1018 | + pixelmap->GetInnerPixelmap()->scale( |
| 1019 | + scaleX, scaleY, ParsePublicAntiAliasingOption(static_cast<int32_t>(level))); | ||
| 1003 | return IMAGE_SUCCESS; | 1020 | return IMAGE_SUCCESS; |
| 1004 | } | 1021 | } |
| 1005 | 1022 | ||
| @@ -1052,17 +1069,16 @@ Image_ErrorCode OH_PixelmapNative_CreateCroppedAndScaledPixelMap(OH_PixelmapNati | |||
| 1052 | return ToNewErrorCode(errorCode); | 1069 | return ToNewErrorCode(errorCode); |
| 1053 | } | 1070 | } |
| 1054 | 1071 | ||
| 1055 | - OHOS::Media::Rect rect = { | 1072 | + OHOS::Media::Rect rect; |
| 1056 | - .left = static_cast<int32_t>(region->x), | 1073 | + if (!ConvertImageRegionToRect(*region, rect)) { |
| 1057 | - .top = static_cast<int32_t>(region->y), | 1074 | + return IMAGE_BAD_PARAMETER; |
| 1058 | - .width = static_cast<int32_t>(region->width), | 1075 | + } |
| 1059 | - .height = static_cast<int32_t>(region->height) | ||
| 1060 | - }; | ||
| 1061 | uint32_t status = clonedPixelmap->crop(rect); | 1076 | uint32_t status = clonedPixelmap->crop(rect); |
| 1062 | if (status != SUCCESS) { | 1077 | if (status != SUCCESS) { |
| 1063 | return IMAGE_BAD_PARAMETER; | 1078 | return IMAGE_BAD_PARAMETER; |
| 1064 | } | 1079 | } |
| 1065 | - clonedPixelmap->scale(scale->x, scale->y, static_cast<AntiAliasingOption>(level)); | 1080 | + clonedPixelmap->scale( |
| 1081 | + scale->x, scale->y, ParsePublicAntiAliasingOption(static_cast<int32_t>(level))); | ||
| 1066 | *dstPixelmap = new OH_PixelmapNative(std::move(clonedPixelmap)); | 1082 | *dstPixelmap = new OH_PixelmapNative(std::move(clonedPixelmap)); |
| 1067 | return IMAGE_SUCCESS; | 1083 | return IMAGE_SUCCESS; |
| 1068 | } | 1084 | } |
| @@ -1096,7 +1112,8 @@ Image_ErrorCode OH_PixelmapNative_CreateScaledPixelMapWithAntiAliasing(OH_Pixelm | |||
| 1096 | if (clonePixelmap == nullptr) { | 1112 | if (clonePixelmap == nullptr) { |
| 1097 | return IMAGE_BAD_PARAMETER; | 1113 | return IMAGE_BAD_PARAMETER; |
| 1098 | } | 1114 | } |
| 1099 | - clonePixelmap->scale(scaleX, scaleY, static_cast<AntiAliasingOption>(level)); | 1115 | + clonePixelmap->scale( |
| 1116 | + scaleX, scaleY, ParsePublicAntiAliasingOption(static_cast<int32_t>(level))); | ||
| 1100 | *dstPixelmap = new OH_PixelmapNative(std::move(clonePixelmap)); | 1117 | *dstPixelmap = new OH_PixelmapNative(std::move(clonePixelmap)); |
| 1101 | return IMAGE_SUCCESS; | 1118 | return IMAGE_SUCCESS; |
| 1102 | } | 1119 | } |
| @@ -1215,12 +1232,10 @@ Image_ErrorCode OH_PixelmapNative_ApplyCrop(OH_PixelmapNative *pixelmap, Image_R | |||
| 1215 | return IMAGE_PIXELMAP_RELEASED; | 1232 | return IMAGE_PIXELMAP_RELEASED; |
| 1216 | } | 1233 | } |
| 1217 | 1234 | ||
| 1218 | - OHOS::Media::Rect rect = { | 1235 | + OHOS::Media::Rect rect; |
| 1219 | - .left = static_cast<int32_t>(region->x), | 1236 | + if (!ConvertImageRegionToRect(*region, rect)) { |
| 1220 | - .top = static_cast<int32_t>(region->y), | 1237 | + return IMAGE_INVALID_REGION; |
| 1221 | - .width = static_cast<int32_t>(region->width), | 1238 | + } |
| 1222 | - .height = static_cast<int32_t>(region->height) | ||
| 1223 | - }; | ||
| 1224 | uint32_t status = pixelmap->GetInnerPixelmap()->Crop(rect); | 1239 | uint32_t status = pixelmap->GetInnerPixelmap()->Crop(rect); |
| 1225 | if (status == ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY) { | 1240 | if (status == ERR_IMAGE_PIXELMAP_NOT_ALLOW_MODIFY) { |
| 1226 | return IMAGE_UNSUPPORTED_OPERATION; | 1241 | return IMAGE_UNSUPPORTED_OPERATION; |
| @@ -1242,10 +1257,9 @@ Image_ErrorCode OH_PixelmapNative_Crop(OH_PixelmapNative *pixelmap, Image_Region | |||
| 1242 | return IMAGE_BAD_PARAMETER; | 1257 | return IMAGE_BAD_PARAMETER; |
| 1243 | } | 1258 | } |
| 1244 | OHOS::Media::Rect rect; | 1259 | OHOS::Media::Rect rect; |
| 1245 | - rect.left = static_cast<int32_t>(region->x); | 1260 | + if (!ConvertImageRegionToRect(*region, rect)) { |
| 1246 | - rect.top = static_cast<int32_t>(region->y); | 1261 | + return IMAGE_BAD_PARAMETER; |
| 1247 | - rect.width = static_cast<int32_t>(region->width); | 1262 | + } |
| 1248 | - rect.height = static_cast<int32_t>(region->height); | ||
| 1249 | pixelmap->GetInnerPixelmap()->crop(rect); | 1263 | pixelmap->GetInnerPixelmap()->crop(rect); |
| 1250 | return IMAGE_SUCCESS; | 1264 | return IMAGE_SUCCESS; |
| 1251 | } | 1265 | } |
| @@ -2317,8 +2317,13 @@ static void SetAlphaExec(napi_env env, SendablePixelMapAsyncContext* context) | |||
| 2317 | } | 2317 | } |
| 2318 | if (context->status == SUCCESS) { | 2318 | if (context->status == SUCCESS) { |
| 2319 | if (context->rPixelMap != nullptr) { | 2319 | if (context->rPixelMap != nullptr) { |
| 2320 | - context->status = context->rPixelMap->SetAlpha( | 2320 | + float alpha = 0.0f; |
| 2321 | - static_cast<float>(context->alpha)); | 2321 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->alpha, &alpha)) { |
| 2322 | + IMAGE_LOGW("Alpha is non-finite or out of float range, skip setting alpha"); | ||
| 2323 | + context->status = SUCCESS; | ||
| 2324 | + return; | ||
| 2325 | + } | ||
| 2326 | + context->status = context->rPixelMap->SetAlpha(alpha); | ||
| 2322 | } else { | 2327 | } else { |
| 2323 | IMAGE_LOGE("Null native ref"); | 2328 | IMAGE_LOGE("Null native ref"); |
| 2324 | context->status = ERR_IMAGE_INIT_ABNORMAL; | 2329 | context->status = ERR_IMAGE_INIT_ABNORMAL; |
| @@ -2414,10 +2419,14 @@ napi_value SendablePixelMapNapi::SetAlphaSync(napi_env env, napi_callback_info i | |||
| 2414 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, | 2419 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, |
| 2415 | "Pixelmap has crossed threads . SetAlphaSync failed"), | 2420 | "Pixelmap has crossed threads . SetAlphaSync failed"), |
| 2416 | IMAGE_LOGE("Pixelmap has crossed threads . SetAlphaSync failed")); | 2421 | IMAGE_LOGE("Pixelmap has crossed threads . SetAlphaSync failed")); |
| 2422 | + float safeAlpha = 0.0f; | ||
| 2423 | + if (!ImageNapiUtils::ConvertDoubleToFloat(alpha, &safeAlpha)) { | ||
| 2424 | + IMAGE_LOGW("Alpha is non-finite or out of float range, skip setting alpha"); | ||
| 2425 | + return result; | ||
| 2426 | + } | ||
| 2417 | 2427 | ||
| 2418 | if (pixelMapNapi->nativePixelMap_ != nullptr) { | 2428 | if (pixelMapNapi->nativePixelMap_ != nullptr) { |
| 2419 | - status = pixelMapNapi->nativePixelMap_->SetAlpha( | 2429 | + status = pixelMapNapi->nativePixelMap_->SetAlpha(safeAlpha); |
| 2420 | - static_cast<float>(alpha)); | ||
| 2421 | if (status != SUCCESS) { | 2430 | if (status != SUCCESS) { |
| 2422 | IMAGE_LOGE("SetAlphaSync failed"); | 2431 | IMAGE_LOGE("SetAlphaSync failed"); |
| 2423 | } | 2432 | } |
| @@ -2435,7 +2444,15 @@ static void ScaleExec(napi_env env, SendablePixelMapAsyncContext* context) | |||
| 2435 | } | 2444 | } |
| 2436 | if (context->status == SUCCESS) { | 2445 | if (context->status == SUCCESS) { |
| 2437 | if (context->rPixelMap != nullptr) { | 2446 | if (context->rPixelMap != nullptr) { |
| 2438 | - context->rPixelMap->scale(static_cast<float>(context->xArg), static_cast<float>(context->yArg)); | 2447 | + float scaleX = 0.0f; |
| 2448 | + float scaleY = 0.0f; | ||
| 2449 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->xArg, &scaleX) || | ||
| 2450 | + !ImageNapiUtils::ConvertDoubleToFloat(context->yArg, &scaleY)) { | ||
| 2451 | + IMAGE_LOGW("Scale factors are non-finite or out of float range, skip scaling"); | ||
| 2452 | + context->status = SUCCESS; | ||
| 2453 | + return; | ||
| 2454 | + } | ||
| 2455 | + context->rPixelMap->scale(scaleX, scaleY); | ||
| 2439 | context->status = SUCCESS; | 2456 | context->status = SUCCESS; |
| 2440 | } else { | 2457 | } else { |
| 2441 | IMAGE_LOGE("Null native ref"); | 2458 | IMAGE_LOGE("Null native ref"); |
| @@ -2533,9 +2550,16 @@ napi_value SendablePixelMapNapi::ScaleSync(napi_env env, napi_callback_info info | |||
| 2533 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, | 2550 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, |
| 2534 | "Pixelmap has crossed threads . ScaleSync failed"), | 2551 | "Pixelmap has crossed threads . ScaleSync failed"), |
| 2535 | IMAGE_LOGE("Pixelmap has crossed threads . ScaleSync failed")); | 2552 | IMAGE_LOGE("Pixelmap has crossed threads . ScaleSync failed")); |
| 2553 | + float scaleX = 0.0f; | ||
| 2554 | + float scaleY = 0.0f; | ||
| 2555 | + if (!ImageNapiUtils::ConvertDoubleToFloat(xArg, &scaleX) || | ||
| 2556 | + !ImageNapiUtils::ConvertDoubleToFloat(yArg, &scaleY)) { | ||
| 2557 | + IMAGE_LOGW("Scale factors are non-finite or out of float range, skip scaling"); | ||
| 2558 | + return result; | ||
| 2559 | + } | ||
| 2536 | 2560 | ||
| 2537 | if (pixelMapNapi->nativePixelMap_ != nullptr) { | 2561 | if (pixelMapNapi->nativePixelMap_ != nullptr) { |
| 2538 | - pixelMapNapi->nativePixelMap_->scale(static_cast<float>(xArg), static_cast<float>(yArg)); | 2562 | + pixelMapNapi->nativePixelMap_->scale(scaleX, scaleY); |
| 2539 | } else { | 2563 | } else { |
| 2540 | IMAGE_LOGE("Null native ref"); | 2564 | IMAGE_LOGE("Null native ref"); |
| 2541 | } | 2565 | } |
| @@ -2550,7 +2574,15 @@ static void TranslateExec(napi_env env, SendablePixelMapAsyncContext* context) | |||
| 2550 | } | 2574 | } |
| 2551 | if (context->status == SUCCESS) { | 2575 | if (context->status == SUCCESS) { |
| 2552 | if (context->rPixelMap != nullptr) { | 2576 | if (context->rPixelMap != nullptr) { |
| 2553 | - context->rPixelMap->translate(static_cast<float>(context->xArg), static_cast<float>(context->yArg)); | 2577 | + float translateX = 0.0f; |
| 2578 | + float translateY = 0.0f; | ||
| 2579 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->xArg, &translateX) || | ||
| 2580 | + !ImageNapiUtils::ConvertDoubleToFloat(context->yArg, &translateY)) { | ||
| 2581 | + IMAGE_LOGW("Translation values are non-finite or out of float range, skip translation"); | ||
| 2582 | + context->status = SUCCESS; | ||
| 2583 | + return; | ||
| 2584 | + } | ||
| 2585 | + context->rPixelMap->translate(translateX, translateY); | ||
| 2554 | context->status = SUCCESS; | 2586 | context->status = SUCCESS; |
| 2555 | } else { | 2587 | } else { |
| 2556 | IMAGE_LOGE("Null native ref"); | 2588 | IMAGE_LOGE("Null native ref"); |
| @@ -2641,7 +2673,6 @@ napi_value SendablePixelMapNapi::TranslateSync(napi_env env, napi_callback_info | |||
| 2641 | IMAGE_LOGE("get arraybuffer info failed"); | 2673 | IMAGE_LOGE("get arraybuffer info failed"); |
| 2642 | return result; | 2674 | return result; |
| 2643 | } | 2675 | } |
| 2644 | - | ||
| 2645 | SendablePixelMapNapi* pixelMapNapi = nullptr; | 2676 | SendablePixelMapNapi* pixelMapNapi = nullptr; |
| 2646 | napiStatus = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi)); | 2677 | napiStatus = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi)); |
| 2647 | IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, | 2678 | IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, |
| @@ -2650,9 +2681,16 @@ napi_value SendablePixelMapNapi::TranslateSync(napi_env env, napi_callback_info | |||
| 2650 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, | 2681 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, |
| 2651 | "Pixelmap has crossed threads . TranslateSync failed"), | 2682 | "Pixelmap has crossed threads . TranslateSync failed"), |
| 2652 | IMAGE_LOGE("Pixelmap has crossed threads . TranslateSync failed")); | 2683 | IMAGE_LOGE("Pixelmap has crossed threads . TranslateSync failed")); |
| 2684 | + float translateX = 0.0f; | ||
| 2685 | + float translateY = 0.0f; | ||
| 2686 | + if (!ImageNapiUtils::ConvertDoubleToFloat(x, &translateX) || | ||
| 2687 | + !ImageNapiUtils::ConvertDoubleToFloat(y, &translateY)) { | ||
| 2688 | + IMAGE_LOGW("Translation values are non-finite or out of float range, skip translation"); | ||
| 2689 | + return result; | ||
| 2690 | + } | ||
| 2653 | 2691 | ||
| 2654 | if (pixelMapNapi->nativePixelMap_ != nullptr) { | 2692 | if (pixelMapNapi->nativePixelMap_ != nullptr) { |
| 2655 | - pixelMapNapi->nativePixelMap_->translate(static_cast<float>(x), static_cast<float>(y)); | 2693 | + pixelMapNapi->nativePixelMap_->translate(translateX, translateY); |
| 2656 | } else { | 2694 | } else { |
| 2657 | IMAGE_LOGE("Null native ref"); | 2695 | IMAGE_LOGE("Null native ref"); |
| 2658 | } | 2696 | } |
| @@ -2667,7 +2705,13 @@ static void RotateExec(napi_env env, SendablePixelMapAsyncContext* context) | |||
| 2667 | } | 2705 | } |
| 2668 | if (context->status == SUCCESS) { | 2706 | if (context->status == SUCCESS) { |
| 2669 | if (context->rPixelMap != nullptr) { | 2707 | if (context->rPixelMap != nullptr) { |
| 2670 | - context->rPixelMap->rotate(context->xArg); | 2708 | + float angle = 0.0f; |
| 2709 | + if (!ImageNapiUtils::ConvertDoubleToFloat(context->xArg, &angle)) { | ||
| 2710 | + IMAGE_LOGW("Rotation angle is non-finite or out of float range, skip rotation"); | ||
| 2711 | + context->status = SUCCESS; | ||
| 2712 | + return; | ||
| 2713 | + } | ||
| 2714 | + context->rPixelMap->rotate(angle); | ||
| 2671 | context->status = SUCCESS; | 2715 | context->status = SUCCESS; |
| 2672 | } else { | 2716 | } else { |
| 2673 | IMAGE_LOGE("Null native ref"); | 2717 | IMAGE_LOGE("Null native ref"); |
| @@ -2752,7 +2796,6 @@ napi_value SendablePixelMapNapi::RotateSync(napi_env env, napi_callback_info inf | |||
| 2752 | IMAGE_LOGE("RotateSync failed, invalid parameter")); | 2796 | IMAGE_LOGE("RotateSync failed, invalid parameter")); |
| 2753 | napiStatus = napi_get_value_double(env, argValue[NUM_0], &angle); | 2797 | napiStatus = napi_get_value_double(env, argValue[NUM_0], &angle); |
| 2754 | IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed")); | 2798 | IMG_NAPI_CHECK_RET_D(napiStatus == napi_ok, result, IMAGE_LOGE("get arraybuffer info failed")); |
| 2755 | - | ||
| 2756 | SendablePixelMapNapi* pixelMapNapi = nullptr; | 2799 | SendablePixelMapNapi* pixelMapNapi = nullptr; |
| 2757 | napiStatus = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi)); | 2800 | napiStatus = NapiUnwrap(env, thisVar, reinterpret_cast<void**>(&pixelMapNapi)); |
| 2758 | IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, | 2801 | IMG_NAPI_CHECK_RET_D(IMG_IS_READY(napiStatus, pixelMapNapi), result, |
| @@ -2761,9 +2804,14 @@ napi_value SendablePixelMapNapi::RotateSync(napi_env env, napi_callback_info inf | |||
| 2761 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, | 2804 | ImageNapiUtils::ThrowExceptionError(env, ERR_RESOURCE_UNAVAILABLE, |
| 2762 | "Pixelmap has crossed threads . RotateSync failed"), | 2805 | "Pixelmap has crossed threads . RotateSync failed"), |
| 2763 | IMAGE_LOGE("Pixelmap has crossed threads . RotateSync failed")); | 2806 | IMAGE_LOGE("Pixelmap has crossed threads . RotateSync failed")); |
| 2807 | + float safeAngle = 0.0f; | ||
| 2808 | + if (!ImageNapiUtils::ConvertDoubleToFloat(angle, &safeAngle)) { | ||
| 2809 | + IMAGE_LOGW("Rotation angle is non-finite or out of float range, skip rotation"); | ||
| 2810 | + return result; | ||
| 2811 | + } | ||
| 2764 | 2812 | ||
| 2765 | if (pixelMapNapi->nativePixelMap_ != nullptr) { | 2813 | if (pixelMapNapi->nativePixelMap_ != nullptr) { |
| 2766 | - pixelMapNapi->nativePixelMap_->rotate(static_cast<float>(angle)); | 2814 | + pixelMapNapi->nativePixelMap_->rotate(safeAngle); |
| 2767 | } else { | 2815 | } else { |
| 2768 | IMAGE_LOGE("Null native ref"); | 2816 | IMAGE_LOGE("Null native ref"); |
| 2769 | } | 2817 | } |
| @@ -872,7 +872,8 @@ Image_ErrorCode OH_PixelmapNative_Scale(OH_PixelmapNative *pixelmap, float scale | |||
| 872 | * @param pixelmap Pointer of the PixelMap to be scaled. | 872 | * @param pixelmap Pointer of the PixelMap to be scaled. |
| 873 | * @param scaleX The scale ratio of width. | 873 | * @param scaleX The scale ratio of width. |
| 874 | * @param scaleY The scale ratio of height. | 874 | * @param scaleY The scale ratio of height. |
| 875 | - * @param level The anti-aliasing algorithm to be used. | 875 | + * @param level The anti-aliasing algorithm to be used. Values outside the defined range use |
| 876 | + * {@link OH_PixelmapNative_AntiAliasing_NONE}. | ||
| 876 | * @return Function result code: | 877 | * @return Function result code: |
| 877 | * {@link IMAGE_SUCCESS} The operation is successful. | 878 | * {@link IMAGE_SUCCESS} The operation is successful. |
| 878 | * {@link IMAGE_GET_IMAGE_DATA_FAILED} Failed to get image data. | 879 | * {@link IMAGE_GET_IMAGE_DATA_FAILED} Failed to get image data. |
| @@ -894,7 +895,8 @@ Image_ErrorCode OH_PixelmapNative_ApplyScaleWithAntiAliasing(OH_PixelmapNative * | |||
| 894 | * @param pixelmap The Pixelmap pointer will be operated. | 895 | * @param pixelmap The Pixelmap pointer will be operated. |
| 895 | * @param scaleX Scaling ratio of the width. | 896 | * @param scaleX Scaling ratio of the width. |
| 896 | * @param scaleY Scaling ratio of the height. | 897 | * @param scaleY Scaling ratio of the height. |
| 897 | - * @param level The anti-aliasing algorithm to be used. | 898 | + * @param level The anti-aliasing algorithm to be used. Values outside the defined range use |
| 899 | + * {@link OH_PixelmapNative_AntiAliasing_NONE}. | ||
| 898 | * @return Returns {@link Image_ErrorCode} IMAGE_SUCCESS - if the operation is successful. | 900 | * @return Returns {@link Image_ErrorCode} IMAGE_SUCCESS - if the operation is successful. |
| 899 | * returns {@link Image_ErrorCode} IMAGE_BAD_PARAMETER - if invalid parameter, x and y are incorrect. | 901 | * returns {@link Image_ErrorCode} IMAGE_BAD_PARAMETER - if invalid parameter, x and y are incorrect. |
| 900 | * returns {@link Image_ErrorCode} IMAGE_TOO_LARGE - if image is too large. | 902 | * returns {@link Image_ErrorCode} IMAGE_TOO_LARGE - if image is too large. |
| @@ -974,7 +976,8 @@ Image_ErrorCode OH_PixelmapNative_Clone(OH_PixelmapNative *srcPixelmap, OH_Pixel | |||
| 974 | * @param srcPixelmap The source PixelMap. | 976 | * @param srcPixelmap The source PixelMap. |
| 975 | * @param region The crop region. | 977 | * @param region The crop region. |
| 976 | * @param scale The scale ratio of width and height. | 978 | * @param scale The scale ratio of width and height. |
| 977 | - * @param level The scaling interpolation algorithm to be used. | 979 | + * @param level The scaling interpolation algorithm to be used. Values outside the defined range use |
| 980 | + * {@link OH_PixelmapNative_AntiAliasing_NONE}. | ||
| 978 | * @param dstPixelmap The target PixelMap to be created. | 981 | * @param dstPixelmap The target PixelMap to be created. |
| 979 | * @return Function result code: | 982 | * @return Function result code: |
| 980 | * {@link IMAGE_SUCCESS} If the operation is successful. | 983 | * {@link IMAGE_SUCCESS} If the operation is successful. |
| @@ -1013,7 +1016,8 @@ Image_ErrorCode OH_PixelmapNative_CreateScaledPixelMap(OH_PixelmapNative *srcPix | |||
| 1013 | * @param dstPixelmap The destination native pixelmap for create. | 1016 | * @param dstPixelmap The destination native pixelmap for create. |
| 1014 | * @param scaleX Scaling ratio of the width. | 1017 | * @param scaleX Scaling ratio of the width. |
| 1015 | * @param scaleY Scaling ratio of the height. | 1018 | * @param scaleY Scaling ratio of the height. |
| 1016 | - * @param level The anti-aliasing algorithm to be used. | 1019 | + * @param level The anti-aliasing algorithm to be used. Values outside the defined range use |
| 1020 | + * {@link OH_PixelmapNative_AntiAliasing_NONE}. | ||
| 1017 | * @return Function result code: | 1021 | * @return Function result code: |
| 1018 | * {@link IMAGE_SUCCESS} If the execution is successful. | 1022 | * {@link IMAGE_SUCCESS} If the execution is successful. |
| 1019 | * {@link IMAGE_BAD_PARAMETER} If the param is nullptr or invalid. | 1023 | * {@link IMAGE_BAD_PARAMETER} If the param is nullptr or invalid. |
| @@ -443,7 +443,8 @@ int32_t OH_PixelMap_Scale(const NativePixelMap* native, float x, float y); | |||
| 443 | * @param native Indicates the pointer to a <b>NativePixelMap</b> object. | 443 | * @param native Indicates the pointer to a <b>NativePixelMap</b> object. |
| 444 | * @param x Indicates the scaling ratio of the width. | 444 | * @param x Indicates the scaling ratio of the width. |
| 445 | * @param y Indicates the scaling ratio of the height. | 445 | * @param y Indicates the scaling ratio of the height. |
| 446 | - * @param level Indicates the anti-aliasing algorithm to be used. | 446 | + * @param level Indicates the anti-aliasing algorithm to be used. Values outside the defined range use |
| 447 | + * {@link OH_PixelMap_AntiAliasing_NONE}. | ||
| 447 | * @return Returns {@link IRNdkErrCode} IMAGE_RESULT_SUCCESS - if the operation is successful. | 448 | * @return Returns {@link IRNdkErrCode} IMAGE_RESULT_SUCCESS - if the operation is successful. |
| 448 | * returns {@link IRNdkErrCode} IMAGE_RESULT_JNI_ENV_ABNORMAL - if Abnormal JNI environment. | 449 | * returns {@link IRNdkErrCode} IMAGE_RESULT_JNI_ENV_ABNORMAL - if Abnormal JNI environment. |
| 449 | * returns {@link IRNdkErrCode} IMAGE_RESULT_INVALID_PARAMETER - if invalid parameter, x and y are incorrect. | 450 | * returns {@link IRNdkErrCode} IMAGE_RESULT_INVALID_PARAMETER - if invalid parameter, x and y are incorrect. |
| @@ -61,6 +61,11 @@ struct ClAstcHandle { | |||
| 61 | ClAstcObjEnc encObj; | 61 | ClAstcObjEnc encObj; |
| 62 | }; | 62 | }; |
| 63 | 63 | ||
| 64 | +/** | ||
| 65 | + * Creates an ASTC OpenCL encoder handle. | ||
| 66 | + * | ||
| 67 | + * When handle is non-null, the output handle is set to nullptr on failure. | ||
| 68 | + */ | ||
| 64 | CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClCreate(ClAstcHandle **handle, const std::string &clBinPath); | 69 | CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClCreate(ClAstcHandle **handle, const std::string &clBinPath); |
| 65 | 70 | ||
| 66 | CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClFillImage(ClAstcImageOption *imageIn, uint8_t *data, | 71 | CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClFillImage(ClAstcImageOption *imageIn, uint8_t *data, |
| @@ -69,6 +74,12 @@ CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClFillImage(ClAstcImageOption *imageIn, | |||
| 69 | CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClEncImage(ClAstcHandle *handle, const ClAstcImageOption *imageIn, | 74 | CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClEncImage(ClAstcHandle *handle, const ClAstcImageOption *imageIn, |
| 70 | uint8_t *buffer); | 75 | uint8_t *buffer); |
| 71 | 76 | ||
| 77 | +/** | ||
| 78 | + * Closes an ASTC OpenCL encoder handle. | ||
| 79 | + * | ||
| 80 | + * Ownership of a non-null handle is consumed regardless of the return value. The handle storage is always freed, | ||
| 81 | + * and the caller must not retry AstcClClose or access the handle after this call. | ||
| 82 | + */ | ||
| 72 | CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClClose(ClAstcHandle *handle); | 83 | CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClClose(ClAstcHandle *handle); |
| 73 | } | 84 | } |
| 74 | } | 85 | } |
| @@ -640,28 +640,28 @@ CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClClose(ClAstcHandle *clAstcHandle) | |||
| 640 | IMAGE_LOGE("astc AstcClClose clAstcHandle is nullptr!"); | 640 | IMAGE_LOGE("astc AstcClClose clAstcHandle is nullptr!"); |
| 641 | return CL_ASTC_ENC_FAILED; | 641 | return CL_ASTC_ENC_FAILED; |
| 642 | } | 642 | } |
| 643 | - cl_int clRet; | 643 | + bool allSuccess = true; |
| 644 | if (clAstcHandle->kernel != nullptr) { | 644 | if (clAstcHandle->kernel != nullptr) { |
| 645 | - clRet = clReleaseKernel(clAstcHandle->kernel); | 645 | + cl_int clRet = clReleaseKernel(clAstcHandle->kernel); |
| 646 | if (clRet != CL_SUCCESS) { | 646 | if (clRet != CL_SUCCESS) { |
| 647 | IMAGE_LOGE("astc clReleaseKernel failed ret %{public}d!", clRet); | 647 | IMAGE_LOGE("astc clReleaseKernel failed ret %{public}d!", clRet); |
| 648 | - return CL_ASTC_ENC_FAILED; | 648 | + allSuccess = false; |
| 649 | } | 649 | } |
| 650 | clAstcHandle->kernel = nullptr; | 650 | clAstcHandle->kernel = nullptr; |
| 651 | } | 651 | } |
| 652 | if (clAstcHandle->queue != nullptr) { | 652 | if (clAstcHandle->queue != nullptr) { |
| 653 | - clRet = clReleaseCommandQueue(clAstcHandle->queue); | 653 | + cl_int clRet = clReleaseCommandQueue(clAstcHandle->queue); |
| 654 | if (clRet != CL_SUCCESS) { | 654 | if (clRet != CL_SUCCESS) { |
| 655 | IMAGE_LOGE("astc clReleaseCommandQueue failed ret %{public}d!", clRet); | 655 | IMAGE_LOGE("astc clReleaseCommandQueue failed ret %{public}d!", clRet); |
| 656 | - return CL_ASTC_ENC_FAILED; | 656 | + allSuccess = false; |
| 657 | } | 657 | } |
| 658 | clAstcHandle->queue = nullptr; | 658 | clAstcHandle->queue = nullptr; |
| 659 | } | 659 | } |
| 660 | if (clAstcHandle->context != nullptr) { | 660 | if (clAstcHandle->context != nullptr) { |
| 661 | - clRet = clReleaseContext(clAstcHandle->context); | 661 | + cl_int clRet = clReleaseContext(clAstcHandle->context); |
| 662 | if (clRet != CL_SUCCESS) { | 662 | if (clRet != CL_SUCCESS) { |
| 663 | IMAGE_LOGE("astc clReleaseContext failed ret %{public}d!", clRet); | 663 | IMAGE_LOGE("astc clReleaseContext failed ret %{public}d!", clRet); |
| 664 | - return CL_ASTC_ENC_FAILED; | 664 | + allSuccess = false; |
| 665 | } | 665 | } |
| 666 | clAstcHandle->context = nullptr; | 666 | clAstcHandle->context = nullptr; |
| 667 | } | 667 | } |
| @@ -669,10 +669,8 @@ CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClClose(ClAstcHandle *clAstcHandle) | |||
| 669 | free(clAstcHandle->encObj.blockErrs_); | 669 | free(clAstcHandle->encObj.blockErrs_); |
| 670 | clAstcHandle->encObj.blockErrs_ = nullptr; | 670 | clAstcHandle->encObj.blockErrs_ = nullptr; |
| 671 | } | 671 | } |
| 672 | - if (clAstcHandle != nullptr) { | 672 | + free(clAstcHandle); |
| 673 | - free(clAstcHandle); | 673 | + return allSuccess ? CL_ASTC_ENC_SUCCESS : CL_ASTC_ENC_FAILED; |
| 674 | - } | ||
| 675 | - return CL_ASTC_ENC_SUCCESS; | ||
| 676 | } | 674 | } |
| 677 | 675 | ||
| 678 | static bool CheckClBinIsExist(const std::string &name) | 676 | static bool CheckClBinIsExist(const std::string &name) |
| @@ -832,6 +830,11 @@ static CL_ASTC_STATUS AstcCreateClKernel(ClAstcHandle *clAstcHandle, const std:: | |||
| 832 | CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClCreate(ClAstcHandle **handle, const std::string &clBinPath) | 830 | CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClCreate(ClAstcHandle **handle, const std::string &clBinPath) |
| 833 | { | 831 | { |
| 834 | Media::ImageTrace imageTrace("AstcClCreate"); | 832 | Media::ImageTrace imageTrace("AstcClCreate"); |
| 833 | + if (handle == nullptr) { | ||
| 834 | + IMAGE_LOGE("astc AstcClCreate handle is nullptr!"); | ||
| 835 | + return CL_ASTC_ENC_FAILED; | ||
| 836 | + } | ||
| 837 | + *handle = nullptr; | ||
| 835 | ClAstcHandle *clAstcHandle = static_cast<ClAstcHandle *>(calloc(1, sizeof(ClAstcHandle))); | 838 | ClAstcHandle *clAstcHandle = static_cast<ClAstcHandle *>(calloc(1, sizeof(ClAstcHandle))); |
| 836 | if (clAstcHandle == nullptr) { | 839 | if (clAstcHandle == nullptr) { |
| 837 | IMAGE_LOGE("astc AstcClCreate handle calloc failed!"); | 840 | IMAGE_LOGE("astc AstcClCreate handle calloc failed!"); |
| @@ -844,11 +847,13 @@ CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClCreate(ClAstcHandle **handle, const s | |||
| 844 | if (clAstcHandle->encObj.blockErrs_ == nullptr) { | 847 | if (clAstcHandle->encObj.blockErrs_ == nullptr) { |
| 845 | IMAGE_LOGE("astc blockErrs_ malloc failed!"); | 848 | IMAGE_LOGE("astc blockErrs_ malloc failed!"); |
| 846 | AstcClClose(*handle); | 849 | AstcClClose(*handle); |
| 850 | + *handle = nullptr; | ||
| 847 | return CL_ASTC_ENC_FAILED; | 851 | return CL_ASTC_ENC_FAILED; |
| 848 | } | 852 | } |
| 849 | if (AstcCreateClKernel(clAstcHandle, clBinPath) != CL_ASTC_ENC_SUCCESS) { | 853 | if (AstcCreateClKernel(clAstcHandle, clBinPath) != CL_ASTC_ENC_SUCCESS) { |
| 850 | IMAGE_LOGE("astc AstcCreateClKernel failed!"); | 854 | IMAGE_LOGE("astc AstcCreateClKernel failed!"); |
| 851 | AstcClClose(*handle); | 855 | AstcClClose(*handle); |
| 856 | + *handle = nullptr; | ||
| 852 | return CL_ASTC_ENC_FAILED; | 857 | return CL_ASTC_ENC_FAILED; |
| 853 | } | 858 | } |
| 854 | return CL_ASTC_ENC_SUCCESS; | 859 | return CL_ASTC_ENC_SUCCESS; |