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