已合并
fix(image): harden pixel map validation and cleanup #5776
fix(image): harden pixel map validation and cleanup #5776
已合并
多面体创建于 29 天前
37 个文件变更+1510-412
@@ -15,6 +15,9 @@
15 15 
16#include "pixel_astc.h"16#include "pixel_astc.h"
17 17 
18+#include <cmath>
19+#include <limits>
20+ 
18#include "image_log.h"21#include "image_log.h"
19#include "image_utils.h"22#include "image_utils.h"
20#include "image_trace.h"23#include "image_trace.h"
@@ -37,6 +40,53 @@ namespace OHOS {
37namespace Media {40namespace Media {
38using namespace std;41using 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+ 
40PixelAstc::~PixelAstc()90PixelAstc::~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 
69void PixelAstc::scale(float xAxis, float yAxis)119void 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 
88uint32_t PixelAstc::Scale(float xAxis, float yAxis, AntiAliasingOption option)124uint32_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 
109uint32_t PixelAstc::Translate(float xAxis, float yAxis)170uint32_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- 
140void PixelAstc::rotate(float degrees)209void PixelAstc::rotate(float degrees)
141{210{
142 Rotate(degrees);211 Rotate(degrees);
@@ -144,17 +213,43 @@ void PixelAstc::rotate(float degrees)
144 213 
145uint32_t PixelAstc::Rotate(float degrees)214uint32_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 
166uint32_t PixelAstc::Flip(bool xAxis, bool yAxis)261uint32_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 
181uint32_t PixelAstc::Crop(const Rect &rect)277uint32_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 Media426} // namespace Media
321-} // namespace OHOS427+} // namespace OHOS
@@ -20,7 +20,9 @@
20#include <algorithm>20#include <algorithm>
21#include <charconv>21#include <charconv>
22#include <chrono>22#include <chrono>
23+#include <cmath>
23#include <iostream>24#include <iostream>
25+#include <limits>
24#include <unistd.h>26#include <unistd.h>
25#if !defined(IOS_PLATFORM) &&!defined(ANDROID_PLATFORM)27#if !defined(IOS_PLATFORM) &&!defined(ANDROID_PLATFORM)
26#include <linux/dma-buf.h>28#include <linux/dma-buf.h>
@@ -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#if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)4494#if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
@@ -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#if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)4524#if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
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+ 
4545struct TransInfos {4593struct 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 
4678uint32_t PixelMap::Scale(float xAxis, float yAxis, AntiAliasingOption option)4731uint32_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 
4746bool PixelMap::resize(float xAxis, float yAxis)4808bool 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 
4768uint32_t PixelMap::Translate(float xAxis, float yAxis)4835uint32_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 
4791uint32_t PixelMap::Rotate(float degrees)4870uint32_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#ifndef FRAMEWORKS_INNERKITSIMPL_CONVERTER_INCLUDE_POST_PROC_SLR_H16#ifndef FRAMEWORKS_INNERKITSIMPL_CONVERTER_INCLUDE_POST_PROC_SLR_H
17#define FRAMEWORKS_INNERKITSIMPL_CONVERTER_INCLUDE_POST_PROC_SLR_H17#define FRAMEWORKS_INNERKITSIMPL_CONVERTER_INCLUDE_POST_PROC_SLR_H
18 18 
19+#include <cstddef>
20+ 
19#include "image_type.h"21#include "image_type.h"
20#ifdef USE_M133_SKIA22#ifdef USE_M133_SKIA
21#include "include/private/base/SkMutex.h"23#include "include/private/base/SkMutex.h"
@@ -31,13 +33,18 @@ namespace Media {
31class SLRMat {33class SLRMat {
32public:34public:
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 
43class SLRWeightKey {50class SLRWeightKey {
@@ -141,9 +148,9 @@ private:
141class SLRProc {148class SLRProc {
142public:149public:
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 Media155} // namespace Media
149} // namespace OHOS156} // namespace OHOS
@@ -15,6 +15,7 @@
15 15 
16#include "post_proc.h"16#include "post_proc.h"
17 17 
18+#include <limits>
18#include <memory>19#include <memory>
19#include <unistd.h>20#include <unistd.h>
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+#if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
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+#else
1220+ return false;
1221+#endif
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+ 
1205bool PostProc::ScalePixelMapWithSLR(const Size &desiredSize, PixelMap &pixelMap, bool useLap)1280bool 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-#endif
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#include "post_proc_slr.h"16#include "post_proc_slr.h"
17 17 
18+#include <algorithm>
18#include <cstdint>19#include <cstdint>
19#include <memory>20#include <memory>
20#include <unistd.h>21#include <unistd.h>
@@ -36,6 +37,35 @@ constexpr float EPSILON = 1e-6;
36constexpr int FFRT_THREAD_LIMIT = 8;37constexpr int FFRT_THREAD_LIMIT = 8;
37constexpr int SLR_MIN_RADIUS = 2;38constexpr int SLR_MIN_RADIUS = 2;
38constexpr int SLR_WEIGHT_SPAN_FACTOR = 2;39constexpr 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 
40float GetSLRFactor(float x, int a)70float GetSLRFactor(float x, int a)
41{71{
@@ -93,8 +123,7 @@ SLRWeightMat SLRProc::GetWeights(float coeff, int n)
93bool SLRCheck(const SLRMat &src, const SLRMat &dst, const SLRWeightMat &x, const SLRWeightMat &y)123bool 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 pixel192+ 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 rgba239 uint32_t b = SLRCast(rgba[2]); // 2 rgba
209 uint32_t a = SLRCast(rgba[3]); // 3 rgba240 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 rgba241+ 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 * c283 return 4 * c
249- - extract(pixels[1], shift) // l left284+ - extract(pixels[1], shift) // l left
250- - extract(pixels[2], shift) // 2 right285+ - extract(pixels[2], shift) // 2 right
251- - extract(pixels[3], shift) // 3 up286+ - extract(pixels[3], shift) // 3 up
252- - extract(pixels[4], shift); // 4 down287+ - 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 r292 (SLRCast(cr + alpha * delta(cr, 24)) << 24) | // 24 r
256 (SLRCast(cg + alpha * delta(cg, 16)) << 16) | // 16 g293 (SLRCast(cg + alpha * delta(cg, 16)) << 16) | // 16 g
257 (SLRCast(cb + alpha * delta(cb, 8)) << 8) | // 8 b294 (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 
277inline void SLRSubtask(const SLRSliceKey &key, const SLRMat &src, SLRMat &dst,316inline 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#if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)332#if !defined(_WIN32) && !defined(_APPLE) && !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
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 size334 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#else366#else
327- SLRProc::Serial(src, dst, x, y);367+ return SLRProc::Serial(src, dst, x, y);
328#endif368#endif
329}369}
330} // namespace Media370} // namespace Media
@@ -16,6 +16,7 @@
16#ifndef FRAMEWORKS_INNERKITSIMPL_EGL_IMAGE_INCLUDE_PIXEL_MAP_GL_COMMON_H16#ifndef FRAMEWORKS_INNERKITSIMPL_EGL_IMAGE_INCLUDE_PIXEL_MAP_GL_COMMON_H
17#define FRAMEWORKS_INNERKITSIMPL_EGL_IMAGE_INCLUDE_PIXEL_MAP_GL_COMMON_H17#define FRAMEWORKS_INNERKITSIMPL_EGL_IMAGE_INCLUDE_PIXEL_MAP_GL_COMMON_H
18 18 
19+#include <cstddef>
19#include <iostream>20#include <iostream>
20 21 
21#include "GLES/gl.h"22#include "GLES/gl.h"
@@ -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 
64private:65private:
@@ -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;
118private:120private:
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() const64 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) const152+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 
167bool PixelMapGlContext::InitGrContext()186bool 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+ 
125bool PixelMapGLPostProcProgram::BuildShader()140bool 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()
346bool PixelMapGLPostProcProgram::BuildProcTexture(GLuint &readTexId)366bool 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 scopedBuffer378 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)
408bool PixelMapGLPostProcProgram::GenProcDmaEndData(void *surfaceBuffer)432bool 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
509bool PixelMapGLPostProcProgram::ReadEndDMAData(void *surfaceBuffer, GLuint &writeFbo)534bool 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 nativeBuffer538 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+ 
248GLuint Shader::loadShader(GLenum type, const char *shaderSrc)259GLuint 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+ 
374bool VertexShader::Build()391bool 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+ 
583bool SLRShader::Build()608bool 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) const91+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 
104bool RenderContext::InitGrContext()125bool 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#include <gtest/gtest.h>16#include <gtest/gtest.h>
17+#include <limits>
18+#include "image_pixel_map_napi_kits.h"
17#include "image_napi_utils.h"19#include "image_napi_utils.h"
18#include "pixel_map_napi.h"20#include "pixel_map_napi.h"
19#include "image_packer_napi.h"21#include "image_packer_napi.h"
@@ -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: NapiTest001151 * @tc.name: NapiTest001
33 * @tc.desc: IsLockPixelMap152 * @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: NapiTest0016379 * @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: PixelAstcTest001168 * @tc.name: PixelAstcTest001
144 * @tc.desc: PixelAstc scale169 * @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+ 
736static void RemoveAstcClTestFile(const std::string &path)751static 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 Multimedia1468} // namespace Multimedia
1454-} // namespace OHOS1469+} // namespace OHOS
@@ -20,6 +20,8 @@
20#include <limits>20#include <limits>
21#include <memory>21#include <memory>
22#include <thread>22#include <thread>
23+#include <type_traits>
24+#include <utility>
23#include <vector>25#include <vector>
24 26 
25#include "pixel_map_egl_utils.h"27#include "pixel_map_egl_utils.h"
@@ -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+ 
48class TestShader : public PixelMapGlShader::Shader {55class TestShader : public PixelMapGlShader::Shader {
49public:56public:
50 bool Clear() override57 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: PixelMapFromSurfaceInterfaceGuardTest001503 * @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_SURFACE177 // 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_SURFACE194 // 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: ImagePixelMapCreate0012330* @tc.name: ImagePixelMapCreate001
2253* @tc.desc: test SLR with DMA2331* @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 Multimedia2404} // namespace Multimedia
2377} // namespace OHOS2405} // namespace OHOS
@@ -16,6 +16,7 @@
16#include <atomic>16#include <atomic>
17#include <chrono>17#include <chrono>
18#include <future>18#include <future>
19+#include <limits>
19 20 
20#define protected public21#define protected public
21#define private public22#define private public
@@ -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: FlipApiTest0013859 * @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#include <gtest/gtest.h>16#include <gtest/gtest.h>
17+#include <limits>
17#include <memory>18#include <memory>
18#include "pixelmap_native.h"19#include "pixelmap_native.h"
19#include "pixelmap_native_impl.h"20#include "pixelmap_native_impl.h"
20#include "common_utils.h"21#include "common_utils.h"
21#include "image_source_native.h"22#include "image_source_native.h"
23+#include "media_errors.h"
22#include "securec.h"24#include "securec.h"
23#include "image_utils.h"25#include "image_utils.h"
24#include "native_color_space_manager.h"26#include "native_color_space_manager.h"
@@ -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+ 
51const int32_t ZERO = 0;69const int32_t ZERO = 0;
52const int32_t ONE = 1;70const int32_t ONE = 1;
53const int32_t TWO = 2;71const 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, &region, &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_Success2860 * @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 &region : 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, &region, &scale, OH_PixelmapNative_AntiAliasing_NONE, &dstPixelmap), IMAGE_BAD_PARAMETER);
3114+ EXPECT_EQ(dstPixelmap, nullptr);
3115+ EXPECT_EQ(OH_PixelmapNative_ApplyCrop(pixelmap, &region), IMAGE_INVALID_REGION);
3116+ EXPECT_EQ(OH_PixelmapNative_Crop(pixelmap, &region), 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_Success3128 * @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#define protected public16#define protected public
17#include <gtest/gtest.h>17#include <gtest/gtest.h>
18#include <fstream>18#include <fstream>
19+#include <limits>
19 20 
20#if !defined(CROSS_PLATFORM)21#if !defined(CROSS_PLATFORM)
21#include "surface_type.h"22#include "surface_type.h"
@@ -29,6 +30,7 @@
29#include "memory_manager.h"30#include "memory_manager.h"
30#include "pixel_map.h"31#include "pixel_map.h"
31#include "post_proc.h"32#include "post_proc.h"
33+#include "post_proc_slr.h"
32#include "basic_transformer.h"34#include "basic_transformer.h"
33 35 
34using namespace testing::ext;36using 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: PostProcTest001114 * @tc.name: PostProcTest001
71 * @tc.desc: test DecodePostProc115 * @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#include "image_log.h"16#include "image_log.h"
17#include "image_napi_utils.h"17#include "image_napi_utils.h"
18#include <array>18#include <array>
19+#include <cmath>
19#include <functional>20#include <functional>
21+#include <limits>
20#include <securec.h>22#include <securec.h>
21#include <unistd.h>23#include <unistd.h>
22#if !defined(CROSS_PLATFORM)24#if !defined(CROSS_PLATFORM)
@@ -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+ 
92bool ImageNapiUtils::GetDoubleByName(napi_env env, napi_value root, const char* name, double *res)120bool 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- 
97static int32_t PixelMapNapiCreate(napi_env env, PixelMapNapiArgs* args)88static 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 
24namespace OHOS {24namespace OHOS {
25namespace Media {25namespace 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#ifdef __cplusplus35#ifdef __cplusplus
27extern "C" {36extern "C" {
28#endif37#endif
@@ -18,6 +18,7 @@
18#include "image_log.h"18#include "image_log.h"
19#include "image_napi_utils.h"19#include "image_napi_utils.h"
20#include "image_pixel_map_napi.h"20#include "image_pixel_map_napi.h"
21+#include "image_pixel_map_napi_kits.h"
21#include "image_source_napi.h"22#include "image_source_napi.h"
22#include "image_trace.h"23#include "image_trace.h"
23#include "log_tags.h"24#include "log_tags.h"
@@ -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- 
239static bool parseSize(napi_env env, napi_value root, Size* size)231static 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", &region->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", &region->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", &region->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", &region->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+ 
3897napi_value PixelMapNapi::CreateCroppedAndScaledPixelMapSync(napi_env env, napi_callback_info info)3954napi_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], &region),
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 
3955STATIC_EXEC_FUNC(CreateCropAndScalePixelMap)4001STATIC_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#include "pixelmap_native.h"16#include "pixelmap_native.h"
17 17 
18#include <charconv>18#include <charconv>
19+#include <limits>
19#include "common_utils.h"20#include "common_utils.h"
20#include "image_type.h"21#include "image_type.h"
21#include "image_utils.h"22#include "image_utils.h"
@@ -143,6 +144,24 @@ static Image_ErrorCode ToNewErrorCode(int code)
143 }144 }
144};145};
145 146 
147+static bool ConvertImageRegionToRect(const Image_Region &region, 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+ 
146static bool IsMatchType(IMAGE_FORMAT type, PixelFormat format)165static 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+ */
64CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClCreate(ClAstcHandle **handle, const std::string &clBinPath);69CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClCreate(ClAstcHandle **handle, const std::string &clBinPath);
65 70 
66CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClFillImage(ClAstcImageOption *imageIn, uint8_t *data,71CL_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,
69CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClEncImage(ClAstcHandle *handle, const ClAstcImageOption *imageIn,74CL_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+ */
72CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClClose(ClAstcHandle *handle);83CL_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 
678static bool CheckClBinIsExist(const std::string &name)676static bool CheckClBinIsExist(const std::string &name)
@@ -832,6 +830,11 @@ static CL_ASTC_STATUS AstcCreateClKernel(ClAstcHandle *clAstcHandle, const std::
832CL_ASTC_SHARE_LIB_API CL_ASTC_STATUS AstcClCreate(ClAstcHandle **handle, const std::string &clBinPath)830CL_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;