1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "post_proc.h"
17 #include <unistd.h>
18 #include "basic_transformer.h"
19 #include "image_log.h"
20 #include "image_trace.h"
21 #include "image_utils.h"
22 #include "media_errors.h"
23 #include "pixel_convert_adapter.h"
24 #ifndef _WIN32
25 #include "securec.h"
26 #else
27 #include "memory.h"
28 #endif
29
30 #if !defined(_WIN32) && !defined(_APPLE) && !defined(_IOS) &&!defined(_ANDROID)
31 #include <sys/mman.h>
32 #include "ashmem.h"
33 #endif
34
35 namespace OHOS {
36 namespace Media {
37 using namespace std;
38 constexpr uint32_t NEED_NEXT = 1;
39 constexpr float EPSILON = 1e-6;
40 constexpr uint8_t HALF = 2;
41
DecodePostProc(const DecodeOptions & opts,PixelMap & pixelMap,FinalOutputStep finalOutputStep)42 uint32_t PostProc::DecodePostProc(const DecodeOptions &opts, PixelMap &pixelMap, FinalOutputStep finalOutputStep)
43 {
44 ImageInfo srcImageInfo;
45 pixelMap.GetImageInfo(srcImageInfo);
46 ImageInfo dstImageInfo;
47 GetDstImageInfo(opts, pixelMap, srcImageInfo, dstImageInfo);
48 if (finalOutputStep == FinalOutputStep::ROTATE_CHANGE || finalOutputStep == FinalOutputStep::SIZE_CHANGE ||
49 finalOutputStep == FinalOutputStep::DENSITY_CHANGE) {
50 decodeOpts_.allocatorType = AllocatorType::HEAP_ALLOC;
51 }
52 uint32_t errorCode = ConvertProc(opts.CropRect, dstImageInfo, pixelMap, srcImageInfo);
53 if (errorCode != SUCCESS) {
54 IMAGE_LOGE("[PostProc]crop pixel map failed, errcode:%{public}u", errorCode);
55 return errorCode;
56 }
57 decodeOpts_.allocatorType = opts.allocatorType;
58 bool isNeedRotate = !ImageUtils::FloatCompareZero(opts.rotateDegrees);
59 if (isNeedRotate) {
60 if (finalOutputStep == FinalOutputStep::SIZE_CHANGE || finalOutputStep == FinalOutputStep::DENSITY_CHANGE) {
61 decodeOpts_.allocatorType = AllocatorType::HEAP_ALLOC;
62 }
63 if (!RotatePixelMap(opts.rotateDegrees, pixelMap)) {
64 IMAGE_LOGE("[PostProc]rotate:transform pixel map failed");
65 return ERR_IMAGE_TRANSFORM;
66 }
67 }
68 decodeOpts_.allocatorType = opts.allocatorType;
69 if (opts.desiredSize.height > 0 && opts.desiredSize.width > 0) {
70 if (!ScalePixelMap(opts.desiredSize, pixelMap)) {
71 IMAGE_LOGE("[PostProc]scale:transform pixel map failed");
72 return ERR_IMAGE_TRANSFORM;
73 }
74 } else {
75 ImageInfo info;
76 pixelMap.GetImageInfo(info);
77 if ((finalOutputStep == FinalOutputStep::DENSITY_CHANGE) && (info.baseDensity != 0)) {
78 int targetWidth = (pixelMap.GetWidth() * opts.fitDensity + (info.baseDensity >> 1)) / info.baseDensity;
79 int targetHeight = (pixelMap.GetHeight() * opts.fitDensity + (info.baseDensity >> 1)) / info.baseDensity;
80 Size size;
81 size.height = targetHeight;
82 size.width = targetWidth;
83 if (!ScalePixelMap(size, pixelMap)) {
84 IMAGE_LOGE("[PostProc]density scale:transform pixel map failed");
85 return ERR_IMAGE_TRANSFORM;
86 }
87 info.baseDensity = opts.fitDensity;
88 pixelMap.SetImageInfo(info);
89 }
90 }
91 return SUCCESS;
92 }
93
GetDstImageInfo(const DecodeOptions & opts,PixelMap & pixelMap,ImageInfo srcImageInfo,ImageInfo & dstImageInfo)94 void PostProc::GetDstImageInfo(const DecodeOptions &opts, PixelMap &pixelMap,
95 ImageInfo srcImageInfo, ImageInfo &dstImageInfo)
96 {
97 dstImageInfo.size = opts.desiredSize;
98 dstImageInfo.pixelFormat = opts.desiredPixelFormat;
99 dstImageInfo.baseDensity = srcImageInfo.baseDensity;
100 decodeOpts_ = opts;
101 if (opts.desiredPixelFormat == PixelFormat::UNKNOWN) {
102 if (opts.preference == MemoryUsagePreference::LOW_RAM &&
103 srcImageInfo.alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE) {
104 dstImageInfo.pixelFormat = PixelFormat::RGB_565;
105 } else {
106 dstImageInfo.pixelFormat = PixelFormat::RGBA_8888;
107 }
108 }
109 // decode use, this value may be changed by real pixelFormat
110 if (pixelMap.GetAlphaType() == AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL) {
111 dstImageInfo.alphaType = AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
112 } else {
113 dstImageInfo.alphaType = pixelMap.GetAlphaType();
114 }
115 }
116
CenterScale(const Size & size,PixelMap & pixelMap)117 bool PostProc::CenterScale(const Size &size, PixelMap &pixelMap)
118 {
119 int32_t srcWidth = pixelMap.GetWidth();
120 int32_t srcHeight = pixelMap.GetHeight();
121 int32_t targetWidth = size.width;
122 int32_t targetHeight = size.height;
123 if (targetWidth <= 0 || targetHeight <= 0 || srcWidth <= 0 || srcHeight <= 0) {
124 IMAGE_LOGE("[PostProc]params invalid, targetWidth:%{public}d, targetHeight:%{public}d, "
125 "srcWidth:%{public}d, srcHeight:%{public}d",
126 targetWidth, targetHeight, srcWidth, srcHeight);
127 return false;
128 }
129 float widthScale = static_cast<float>(targetWidth) / static_cast<float>(srcWidth);
130 float heightScale = static_cast<float>(targetHeight) / static_cast<float>(srcHeight);
131 float scale = max(widthScale, heightScale);
132 if (!ScalePixelMap(scale, scale, pixelMap)) {
133 IMAGE_LOGE("[PostProc]center scale pixelmap %{public}f fail", scale);
134 return false;
135 }
136 srcWidth = pixelMap.GetWidth();
137 srcHeight = pixelMap.GetHeight();
138 if (srcWidth == targetWidth && srcHeight == targetHeight) {
139 return true;
140 }
141 if (srcWidth < targetWidth || srcHeight < targetHeight) {
142 IMAGE_LOGE("[PostProc]src size [%{public}d, %{public}d] must less than dst size [%{public}d, %{public}d]",
143 srcWidth, srcHeight, targetWidth, targetHeight);
144 return false;
145 }
146
147 return CenterDisplay(pixelMap, srcWidth, srcHeight, targetWidth, targetHeight);
148 }
149
CenterDisplay(PixelMap & pixelMap,int32_t srcWidth,int32_t srcHeight,int32_t targetWidth,int32_t targetHeight)150 bool PostProc::CenterDisplay(PixelMap &pixelMap, int32_t srcWidth, int32_t srcHeight, int32_t targetWidth,
151 int32_t targetHeight)
152 {
153 ImageInfo dstImageInfo;
154 pixelMap.GetImageInfo(dstImageInfo);
155 dstImageInfo.size.width = targetWidth;
156 dstImageInfo.size.height = targetHeight;
157 if (pixelMap.SetImageInfo(dstImageInfo, true) != SUCCESS) {
158 IMAGE_LOGE("update ImageInfo failed");
159 return false;
160 }
161
162 int32_t left = max(0, srcWidth - targetWidth) / HALF;
163 int32_t top = max(0, srcHeight - targetHeight) / HALF;
164 int32_t bufferSize = pixelMap.GetByteCount();
165 uint8_t *dstPixels = nullptr;
166 if (!AllocHeapBuffer(bufferSize, &dstPixels)) {
167 return false;
168 }
169 int32_t copyHeight = srcHeight;
170 if (srcHeight > targetHeight) {
171 copyHeight = targetHeight;
172 }
173 int32_t copyWidth = srcWidth;
174 if (srcWidth > targetWidth) {
175 copyWidth = targetWidth;
176 }
177 int32_t pixelBytes = pixelMap.GetPixelBytes();
178 uint8_t *srcPixels = const_cast<uint8_t *>(pixelMap.GetPixels()) + (top * srcWidth + left) * pixelBytes;
179 uint8_t *dstStartPixel = nullptr;
180 uint8_t *srcStartPixel = nullptr;
181 uint32_t targetRowBytes = targetWidth * pixelBytes;
182 uint32_t srcRowBytes = srcWidth * pixelBytes;
183 uint32_t copyRowBytes = copyWidth * pixelBytes;
184 for (int32_t scanLine = 0; scanLine < copyHeight; scanLine++) {
185 dstStartPixel = dstPixels + scanLine * targetRowBytes;
186 srcStartPixel = srcPixels + scanLine * srcRowBytes;
187 errno_t errRet = memcpy_s(dstStartPixel, targetRowBytes, srcStartPixel, copyRowBytes);
188 if (errRet != 0) {
189 IMAGE_LOGE("[PostProc]memcpy scanline %{public}d fail, errorCode = %{public}d", scanLine, errRet);
190 free(dstPixels);
191 dstPixels = nullptr;
192 return false;
193 }
194 }
195 pixelMap.SetPixelsAddr(dstPixels, nullptr, bufferSize, AllocatorType::HEAP_ALLOC, nullptr);
196 return true;
197 }
198
CheckScanlineFilter(const Rect & cropRect,ImageInfo & dstImageInfo,PixelMap & pixelMap,int32_t pixelBytes,ScanlineFilter & scanlineFilter)199 uint32_t PostProc::CheckScanlineFilter(const Rect &cropRect, ImageInfo &dstImageInfo, PixelMap &pixelMap,
200 int32_t pixelBytes, ScanlineFilter &scanlineFilter)
201 {
202 uint64_t bufferSize = static_cast<uint64_t>(dstImageInfo.size.width) * dstImageInfo.size.height * pixelBytes;
203 uint8_t *resultData = nullptr;
204 int fd = 0;
205 if (decodeOpts_.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
206 resultData = AllocSharedMemory(dstImageInfo.size, bufferSize, fd);
207 if (resultData == nullptr) {
208 IMAGE_LOGE("[PostProc]AllocSharedMemory failed");
209 return ERR_IMAGE_CROP;
210 }
211 } else {
212 if (!AllocHeapBuffer(bufferSize, &resultData)) {
213 return ERR_IMAGE_CROP;
214 }
215 }
216 auto srcData = pixelMap.GetPixels();
217 int32_t scanLine = 0;
218 if (ImageUtils::CheckMulOverflow(dstImageInfo.size.width, pixelBytes)) {
219 IMAGE_LOGE("[PostProc]size.width:%{public}d, is too large",
220 dstImageInfo.size.width);
221 ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
222 return ERR_IMAGE_CROP;
223 }
224 uint32_t rowBytes = pixelBytes * dstImageInfo.size.width;
225 while (scanLine < pixelMap.GetHeight()) {
226 FilterRowType filterRow = scanlineFilter.GetFilterRowType(scanLine);
227 if (filterRow == FilterRowType::NON_REFERENCE_ROW) {
228 scanLine++;
229 continue;
230 }
231 if (filterRow == FilterRowType::LAST_REFERENCE_ROW) {
232 break;
233 }
234 uint32_t ret = scanlineFilter.FilterLine(resultData + ((scanLine - cropRect.top) * rowBytes), rowBytes,
235 srcData + (scanLine * pixelMap.GetRowBytes()));
236 if (ret != SUCCESS) {
237 IMAGE_LOGE("[PostProc]scan line failed, ret:%{public}u", ret);
238 ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
239 return ret;
240 }
241 scanLine++;
242 }
243 uint32_t result = pixelMap.SetImageInfo(dstImageInfo);
244 if (result != SUCCESS) {
245 ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
246 return result;
247 }
248 pixelMap.SetPixelsAddr(resultData, nullptr, bufferSize, decodeOpts_.allocatorType, nullptr);
249 return result;
250 }
251
ConvertProc(const Rect & cropRect,ImageInfo & dstImageInfo,PixelMap & pixelMap,ImageInfo & srcImageInfo)252 uint32_t PostProc::ConvertProc(const Rect &cropRect, ImageInfo &dstImageInfo, PixelMap &pixelMap,
253 ImageInfo &srcImageInfo)
254 {
255 bool hasPixelConvert = HasPixelConvert(srcImageInfo, dstImageInfo);
256 uint32_t ret = NeedScanlineFilter(cropRect, srcImageInfo.size, hasPixelConvert);
257 if (ret != NEED_NEXT) {
258 return ret;
259 }
260
261 // we suppose a quick method to scanline in mostly seen cases: NO CROP && hasPixelConvert
262 if (GetCropValue(cropRect, srcImageInfo.size) == CropValue::NOCROP
263 && dstImageInfo.pixelFormat == PixelFormat::ARGB_8888 && hasPixelConvert) {
264 IMAGE_LOGI("[PostProc]no need crop, only pixel convert.");
265 return PixelConvertProc(dstImageInfo, pixelMap, srcImageInfo);
266 }
267
268 ScanlineFilter scanlineFilter(srcImageInfo.pixelFormat);
269 // this method maybe update dst image size to crop size
270 SetScanlineCropAndConvert(cropRect, dstImageInfo, srcImageInfo, scanlineFilter, hasPixelConvert);
271
272 int32_t pixelBytes = ImageUtils::GetPixelBytes(dstImageInfo.pixelFormat);
273 if (pixelBytes == 0) {
274 return ERR_IMAGE_CROP;
275 }
276 if (ImageUtils::CheckMulOverflow(dstImageInfo.size.width, dstImageInfo.size.height, pixelBytes)) {
277 IMAGE_LOGE("[PostProc]size.width:%{public}d, size.height:%{public}d is too large",
278 dstImageInfo.size.width, dstImageInfo.size.height);
279 return ERR_IMAGE_CROP;
280 }
281 return CheckScanlineFilter(cropRect, dstImageInfo, pixelMap, pixelBytes, scanlineFilter);
282 }
283
PixelConvertProc(ImageInfo & dstImageInfo,PixelMap & pixelMap,ImageInfo & srcImageInfo)284 uint32_t PostProc::PixelConvertProc(ImageInfo &dstImageInfo, PixelMap &pixelMap,
285 ImageInfo &srcImageInfo)
286 {
287 uint32_t ret;
288 int fd = 0;
289 uint64_t bufferSize = 0;
290 uint8_t *resultData = nullptr;
291
292 // as no crop, the size is same as src
293 dstImageInfo.size = srcImageInfo.size;
294 if (AllocBuffer(dstImageInfo, &resultData, bufferSize, fd) != SUCCESS) {
295 ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
296 return ERR_IMAGE_CROP;
297 }
298
299 int32_t pixelBytes = ImageUtils::GetPixelBytes(srcImageInfo.pixelFormat);
300 if (pixelBytes == 0) {
301 return ERR_IMAGE_CROP;
302 }
303
304 ret = pixelMap.SetImageInfo(dstImageInfo);
305 if (ret != SUCCESS) {
306 ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
307 return ret;
308 }
309 pixelMap.SetPixelsAddr(resultData, nullptr, bufferSize, decodeOpts_.allocatorType, nullptr);
310 return ret;
311 }
312
AllocBuffer(ImageInfo imageInfo,uint8_t ** resultData,uint64_t & bufferSize,int & fd)313 uint32_t PostProc::AllocBuffer(ImageInfo imageInfo, uint8_t **resultData, uint64_t &bufferSize, int &fd)
314 {
315 int32_t pixelBytes = ImageUtils::GetPixelBytes(imageInfo.pixelFormat);
316 if (pixelBytes == 0) {
317 return ERR_IMAGE_CROP;
318 }
319 if (ImageUtils::CheckMulOverflow(imageInfo.size.width, imageInfo.size.height, pixelBytes)) {
320 IMAGE_LOGE("[PostProc]size.width:%{public}d, size.height:%{public}d is too large",
321 imageInfo.size.width, imageInfo.size.height);
322 return ERR_IMAGE_CROP;
323 }
324 bufferSize = static_cast<uint64_t>(imageInfo.size.width) * imageInfo.size.height * pixelBytes;
325 IMAGE_LOGD("[PostProc]size.width:%{public}d, size.height:%{public}d, bufferSize:%{public}lld",
326 imageInfo.size.width, imageInfo.size.height, (long long)bufferSize);
327 if (decodeOpts_.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
328 *resultData = AllocSharedMemory(imageInfo.size, bufferSize, fd);
329 if (*resultData == nullptr) {
330 IMAGE_LOGE("[PostProc]AllocSharedMemory failed");
331 return ERR_IMAGE_CROP;
332 }
333 } else {
334 if (!AllocHeapBuffer(bufferSize, resultData)) {
335 return ERR_IMAGE_CROP;
336 }
337 }
338 return SUCCESS;
339 }
340
AllocHeapBuffer(uint64_t bufferSize,uint8_t ** buffer)341 bool PostProc::AllocHeapBuffer(uint64_t bufferSize, uint8_t **buffer)
342 {
343 if (bufferSize == 0 || bufferSize > MALLOC_MAX_LENTH) {
344 IMAGE_LOGE("[PostProc]Invalid value of bufferSize");
345 return false;
346 }
347 *buffer = static_cast<uint8_t *>(malloc(bufferSize));
348 if (*buffer == nullptr) {
349 IMAGE_LOGE("[PostProc]alloc covert color buffersize[%{public}llu] failed.",
350 static_cast<unsigned long long>(bufferSize));
351 return false;
352 }
353 #ifdef _WIN32
354 errno_t backRet = memset_s(*buffer, 0, bufferSize);
355 if (backRet != EOK) {
356 IMAGE_LOGE("[PostProc]memset convertData fail, errorCode = %{public}d", backRet);
357 ReleaseBuffer(AllocatorType::HEAP_ALLOC, 0, 0, buffer);
358 return false;
359 }
360 return true;
361 #else
362 errno_t errRet = memset_s(*buffer, bufferSize, 0, bufferSize);
363 if (errRet != EOK) {
364 IMAGE_LOGE("[PostProc]memset convertData fail, errorCode = %{public}d", errRet);
365 ReleaseBuffer(AllocatorType::HEAP_ALLOC, 0, 0, buffer);
366 return false;
367 }
368 return true;
369 #endif
370 }
371
AllocSharedMemory(const Size & size,const uint64_t bufferSize,int & fd)372 uint8_t *PostProc::AllocSharedMemory(const Size &size, const uint64_t bufferSize, int &fd)
373 {
374 #if defined(_WIN32) || defined(_APPLE) || defined(_IOS) || defined(_ANDROID)
375 return nullptr;
376 #else
377 fd = AshmemCreate("Parcel RawData", bufferSize);
378 if (fd < 0) {
379 IMAGE_LOGE("[PostProc]AllocSharedMemory fd error, bufferSize %{public}lld", (long long)bufferSize);
380 return nullptr;
381 }
382 int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
383 if (result < 0) {
384 IMAGE_LOGE("[PostProc]AshmemSetProt error");
385 ::close(fd);
386 return nullptr;
387 }
388 void* ptr = ::mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
389 if (ptr == MAP_FAILED) {
390 IMAGE_LOGE("[PostProc]mmap error, errno: %{public}s, fd %{public}d, bufferSize %{public}lld",
391 strerror(errno), fd, (long long)bufferSize);
392 ::close(fd);
393 return nullptr;
394 }
395 return reinterpret_cast<uint8_t *>(ptr);
396 #endif
397 }
398
ReleaseBuffer(AllocatorType allocatorType,int fd,uint64_t dataSize,uint8_t ** buffer)399 void PostProc::ReleaseBuffer(AllocatorType allocatorType, int fd, uint64_t dataSize, uint8_t **buffer)
400 {
401 #if !defined(_WIN32) && !defined(_APPLE) && !defined(_IOS) &&!defined(_ANDROID)
402 if (allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
403 if (*buffer != nullptr) {
404 ::munmap(*buffer, dataSize);
405 ::close(fd);
406 }
407 return;
408 }
409 #endif
410
411 if (allocatorType == AllocatorType::HEAP_ALLOC) {
412 if (*buffer != nullptr) {
413 free(*buffer);
414 *buffer = nullptr;
415 }
416 return;
417 }
418 }
419
NeedScanlineFilter(const Rect & cropRect,const Size & srcSize,const bool & hasPixelConvert)420 uint32_t PostProc::NeedScanlineFilter(const Rect &cropRect, const Size &srcSize, const bool &hasPixelConvert)
421 {
422 CropValue value = GetCropValue(cropRect, srcSize);
423 if (value == CropValue::NOCROP && !hasPixelConvert) {
424 IMAGE_LOGI("[PostProc]no need crop and pixel convert.");
425 return SUCCESS;
426 } else if (value == CropValue::INVALID) {
427 IMAGE_LOGE("[PostProc]invalid corp region, top:%{public}d, left:%{public}d, "
428 "width:%{public}d, height:%{public}d",
429 cropRect.top, cropRect.left, cropRect.width, cropRect.height);
430 return ERR_IMAGE_CROP;
431 }
432 return NEED_NEXT;
433 }
434
ConvertPixelMapToPixmapInfo(PixelMap & pixelMap,PixmapInfo & pixmapInfo)435 void PostProc::ConvertPixelMapToPixmapInfo(PixelMap &pixelMap, PixmapInfo &pixmapInfo)
436 {
437 pixmapInfo.imageInfo.size.width = pixelMap.GetWidth();
438 pixmapInfo.imageInfo.size.height = pixelMap.GetHeight();
439 pixmapInfo.imageInfo.pixelFormat = pixelMap.GetPixelFormat();
440 pixmapInfo.imageInfo.colorSpace = pixelMap.GetColorSpace();
441 pixmapInfo.imageInfo.alphaType = pixelMap.GetAlphaType();
442 pixmapInfo.imageInfo.baseDensity = pixelMap.GetBaseDensity();
443 pixmapInfo.data = const_cast<uint8_t *>(pixelMap.GetPixels());
444 pixmapInfo.bufferSize = pixelMap.GetByteCount();
445 }
446
RotatePixelMap(float rotateDegrees,PixelMap & pixelMap)447 bool PostProc::RotatePixelMap(float rotateDegrees, PixelMap &pixelMap)
448 {
449 BasicTransformer trans;
450 PixmapInfo input(false);
451 ConvertPixelMapToPixmapInfo(pixelMap, input);
452 // Default rotation at the center of the image, so divide 2
453 trans.SetRotateParam(rotateDegrees, static_cast<float>(input.imageInfo.size.width) * FHALF,
454 static_cast<float>(input.imageInfo.size.height) * FHALF);
455 return Transform(trans, input, pixelMap);
456 }
457
ScalePixelMap(const Size & size,PixelMap & pixelMap)458 bool PostProc::ScalePixelMap(const Size &size, PixelMap &pixelMap)
459 {
460 int32_t srcWidth = pixelMap.GetWidth();
461 int32_t srcHeight = pixelMap.GetHeight();
462 if (srcWidth <= 0 || srcHeight <= 0) {
463 IMAGE_LOGE("[PostProc]src width:%{public}d, height:%{public}d is invalid.", srcWidth, srcHeight);
464 return false;
465 }
466 float scaleX = static_cast<float>(size.width) / static_cast<float>(srcWidth);
467 float scaleY = static_cast<float>(size.height) / static_cast<float>(srcHeight);
468 return ScalePixelMap(scaleX, scaleY, pixelMap);
469 }
470
ScalePixelMap(float scaleX,float scaleY,PixelMap & pixelMap)471 bool PostProc::ScalePixelMap(float scaleX, float scaleY, PixelMap &pixelMap)
472 {
473 // returns directly with a scale of 1.0
474 if ((fabs(scaleX - 1.0f) < EPSILON) && (fabs(scaleY - 1.0f) < EPSILON)) {
475 return true;
476 }
477 BasicTransformer trans;
478 PixmapInfo input(false);
479 ConvertPixelMapToPixmapInfo(pixelMap, input);
480
481 trans.SetScaleParam(scaleX, scaleY);
482 return Transform(trans, input, pixelMap);
483 }
TranslatePixelMap(float tX,float tY,PixelMap & pixelMap)484 bool PostProc::TranslatePixelMap(float tX, float tY, PixelMap &pixelMap)
485 {
486 BasicTransformer trans;
487 PixmapInfo input(false);
488 ConvertPixelMapToPixmapInfo(pixelMap, input);
489
490 trans.SetTranslateParam(tX, tY);
491 return Transform(trans, input, pixelMap);
492 }
493
Transform(BasicTransformer & trans,const PixmapInfo & input,PixelMap & pixelMap)494 bool PostProc::Transform(BasicTransformer &trans, const PixmapInfo &input, PixelMap &pixelMap)
495 {
496 PixmapInfo output(false);
497 uint32_t ret;
498 if (decodeOpts_.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
499 typedef uint8_t *(*AllocMemory)(const Size &size, const uint64_t bufferSize, int &fd);
500 AllocMemory allcFunc = AllocSharedMemory;
501 ret = trans.TransformPixmap(input, output, allcFunc);
502 } else {
503 ret = trans.TransformPixmap(input, output);
504 }
505 if (ret != IMAGE_SUCCESS) {
506 output.Destroy();
507 return false;
508 }
509
510 if (pixelMap.SetImageInfo(output.imageInfo) != SUCCESS) {
511 output.Destroy();
512 return false;
513 }
514 pixelMap.SetPixelsAddr(output.data, output.context, output.bufferSize, decodeOpts_.allocatorType, nullptr);
515 return true;
516 }
517
GetCropValue(const Rect & rect,const Size & size)518 CropValue PostProc::GetCropValue(const Rect &rect, const Size &size)
519 {
520 bool isSameSize = (rect.top == 0 && rect.left == 0 && rect.height == size.height && rect.width == size.width);
521 if (!IsHasCrop(rect) || isSameSize) {
522 return CropValue::NOCROP;
523 }
524 bool isValid = ((rect.top >= 0 && rect.width > 0 && rect.left >= 0 && rect.height > 0) &&
525 (rect.top + rect.height <= size.height) && (rect.left + rect.width <= size.width));
526 if (!isValid) {
527 return CropValue::INVALID;
528 }
529 return CropValue::VALID;
530 }
531
ValidCropValue(Rect & rect,const Size & size)532 CropValue PostProc::ValidCropValue(Rect &rect, const Size &size)
533 {
534 CropValue res = GetCropValue(rect, size);
535 if (res == CropValue::INVALID) {
536 if (rect.top + rect.height > size.height) {
537 rect.height = size.height - rect.top;
538 }
539 if (rect.left + rect.width > size.width) {
540 rect.width = size.width - rect.left;
541 }
542 res = GetCropValue(rect, size);
543 }
544 return res;
545 }
546
IsHasCrop(const Rect & rect)547 bool PostProc::IsHasCrop(const Rect &rect)
548 {
549 return (rect.top != 0 || rect.left != 0 || rect.width != 0 || rect.height != 0);
550 }
551
HasPixelConvert(const ImageInfo & srcImageInfo,ImageInfo & dstImageInfo)552 bool PostProc::HasPixelConvert(const ImageInfo &srcImageInfo, ImageInfo &dstImageInfo)
553 {
554 dstImageInfo.alphaType = ImageUtils::GetValidAlphaTypeByFormat(dstImageInfo.alphaType, dstImageInfo.pixelFormat);
555 return (dstImageInfo.pixelFormat != srcImageInfo.pixelFormat || dstImageInfo.alphaType != srcImageInfo.alphaType);
556 }
557
SetScanlineCropAndConvert(const Rect & cropRect,ImageInfo & dstImageInfo,ImageInfo & srcImageInfo,ScanlineFilter & scanlineFilter,bool hasPixelConvert)558 void PostProc::SetScanlineCropAndConvert(const Rect &cropRect, ImageInfo &dstImageInfo, ImageInfo &srcImageInfo,
559 ScanlineFilter &scanlineFilter, bool hasPixelConvert)
560 {
561 if (hasPixelConvert) {
562 scanlineFilter.SetPixelConvert(srcImageInfo, dstImageInfo);
563 }
564
565 Rect srcRect = cropRect;
566 if (IsHasCrop(cropRect)) {
567 dstImageInfo.size.width = cropRect.width;
568 dstImageInfo.size.height = cropRect.height;
569 } else {
570 srcRect = { 0, 0, srcImageInfo.size.width, srcImageInfo.size.height };
571 dstImageInfo.size = srcImageInfo.size;
572 }
573 scanlineFilter.SetSrcRegion(srcRect);
574 }
575 } // namespace Media
576 } // namespace OHOS
577