• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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