• 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)
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         }
88     }
89     return SUCCESS;
90 }
91 
GetDstImageInfo(const DecodeOptions & opts,PixelMap & pixelMap,ImageInfo srcImageInfo,ImageInfo & dstImageInfo)92 void PostProc::GetDstImageInfo(const DecodeOptions &opts, PixelMap &pixelMap,
93                                ImageInfo srcImageInfo, ImageInfo &dstImageInfo)
94 {
95     dstImageInfo.size = opts.desiredSize;
96     dstImageInfo.pixelFormat = opts.desiredPixelFormat;
97     dstImageInfo.baseDensity = srcImageInfo.baseDensity;
98     decodeOpts_ = opts;
99     if (opts.desiredPixelFormat == PixelFormat::UNKNOWN) {
100         if (opts.preference == MemoryUsagePreference::LOW_RAM &&
101             srcImageInfo.alphaType == AlphaType::IMAGE_ALPHA_TYPE_OPAQUE) {
102             dstImageInfo.pixelFormat = PixelFormat::RGB_565;
103         } else {
104             dstImageInfo.pixelFormat = PixelFormat::RGBA_8888;
105         }
106     }
107     // decode use, this value may be changed by real pixelFormat
108     if (pixelMap.GetAlphaType() == AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL) {
109         dstImageInfo.alphaType = AlphaType::IMAGE_ALPHA_TYPE_PREMUL;
110     } else {
111         dstImageInfo.alphaType = pixelMap.GetAlphaType();
112     }
113 }
114 
CenterScale(const Size & size,PixelMap & pixelMap)115 bool PostProc::CenterScale(const Size &size, PixelMap &pixelMap)
116 {
117     int32_t srcWidth = pixelMap.GetWidth();
118     int32_t srcHeight = pixelMap.GetHeight();
119     int32_t targetWidth = size.width;
120     int32_t targetHeight = size.height;
121     if (targetWidth <= 0 || targetHeight <= 0 || srcWidth <= 0 || srcHeight <= 0) {
122         IMAGE_LOGE("[PostProc]params invalid, targetWidth:%{public}d, targetHeight:%{public}d, "
123                    "srcWidth:%{public}d, srcHeight:%{public}d",
124                    targetWidth, targetHeight, srcWidth, srcHeight);
125         return false;
126     }
127     float widthScale = static_cast<float>(targetWidth) / static_cast<float>(srcWidth);
128     float heightScale = static_cast<float>(targetHeight) / static_cast<float>(srcHeight);
129     float scale = max(widthScale, heightScale);
130     if (!ScalePixelMap(scale, scale, pixelMap)) {
131         IMAGE_LOGE("[PostProc]center scale pixelmap %{public}f fail", scale);
132         return false;
133     }
134     srcWidth = pixelMap.GetWidth();
135     srcHeight = pixelMap.GetHeight();
136     if (srcWidth == targetWidth && srcHeight == targetHeight) {
137         return true;
138     }
139     if (srcWidth < targetWidth || srcHeight < targetHeight) {
140         IMAGE_LOGE("[PostProc]src size [%{public}d, %{public}d] must less than dst size [%{public}d, %{public}d]",
141                    srcWidth, srcHeight, targetWidth, targetHeight);
142         return false;
143     }
144     if (CenterDisplay(pixelMap, srcWidth, srcHeight, targetWidth, targetHeight)) {
145         return true;
146     }
147     return false;
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 ret = pixelMap.SetImageInfo(dstImageInfo);
244     if (ret != SUCCESS) {
245         ReleaseBuffer(decodeOpts_.allocatorType, fd, bufferSize, &resultData);
246         return ret;
247     }
248     pixelMap.SetPixelsAddr(resultData, nullptr, bufferSize, decodeOpts_.allocatorType, nullptr);
249     return ret;
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     memset(*buffer, 0, bufferSize);
355     return true;
356 #else
357     errno_t errRet = memset_s(*buffer, bufferSize, 0, bufferSize);
358     if (errRet != EOK) {
359         IMAGE_LOGE("[PostProc]memset convertData fail, errorCode = %{public}d", errRet);
360         ReleaseBuffer(AllocatorType::HEAP_ALLOC, 0, 0, buffer);
361         return false;
362     }
363     return true;
364 #endif
365 }
366 
AllocSharedMemory(const Size & size,const uint64_t bufferSize,int & fd)367 uint8_t *PostProc::AllocSharedMemory(const Size &size, const uint64_t bufferSize, int &fd)
368 {
369 #if defined(_WIN32) || defined(_APPLE)
370         return nullptr;
371 #else
372     fd = AshmemCreate("Parcel RawData", bufferSize);
373     if (fd < 0) {
374         IMAGE_LOGE("[PostProc]AllocSharedMemory fd error, bufferSize %{public}lld", (long long)bufferSize);
375         return nullptr;
376     }
377     int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
378     if (result < 0) {
379         IMAGE_LOGE("[PostProc]AshmemSetProt error");
380         ::close(fd);
381         return nullptr;
382     }
383     void* ptr = ::mmap(nullptr, bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
384     if (ptr == MAP_FAILED) {
385         IMAGE_LOGE("[PostProc]mmap error, errno: %{public}s, fd %{public}d, bufferSize %{public}lld",
386             strerror(errno), fd, (long long)bufferSize);
387         ::close(fd);
388         return nullptr;
389     }
390     return (uint8_t *)ptr;
391 #endif
392 }
393 
ReleaseBuffer(AllocatorType allocatorType,int fd,uint64_t dataSize,uint8_t ** buffer)394 void PostProc::ReleaseBuffer(AllocatorType allocatorType, int fd, uint64_t dataSize, uint8_t **buffer)
395 {
396 #if !defined(_WIN32) && !defined(_APPLE)
397     if (allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
398         if (*buffer != nullptr) {
399             ::munmap(*buffer, dataSize);
400             ::close(fd);
401         }
402         return;
403     }
404 #endif
405 
406     if (allocatorType == AllocatorType::HEAP_ALLOC) {
407         if (*buffer != nullptr) {
408             free(*buffer);
409             *buffer = nullptr;
410         }
411         return;
412     }
413 }
414 
NeedScanlineFilter(const Rect & cropRect,const Size & srcSize,const bool & hasPixelConvert)415 uint32_t PostProc::NeedScanlineFilter(const Rect &cropRect, const Size &srcSize, const bool &hasPixelConvert)
416 {
417     CropValue value = GetCropValue(cropRect, srcSize);
418     if (value == CropValue::NOCROP && !hasPixelConvert) {
419         IMAGE_LOGI("[PostProc]no need crop and pixel convert.");
420         return SUCCESS;
421     } else if (value == CropValue::INVALID) {
422         IMAGE_LOGE("[PostProc]invalid corp region, top:%{public}d, left:%{public}d, "
423                    "width:%{public}d, height:%{public}d",
424                    cropRect.top, cropRect.left, cropRect.width, cropRect.height);
425         return ERR_IMAGE_CROP;
426     }
427     return NEED_NEXT;
428 }
429 
ConvertPixelMapToPixmapInfo(PixelMap & pixelMap,PixmapInfo & pixmapInfo)430 void PostProc::ConvertPixelMapToPixmapInfo(PixelMap &pixelMap, PixmapInfo &pixmapInfo)
431 {
432     pixmapInfo.imageInfo.size.width = pixelMap.GetWidth();
433     pixmapInfo.imageInfo.size.height = pixelMap.GetHeight();
434     pixmapInfo.imageInfo.pixelFormat = pixelMap.GetPixelFormat();
435     pixmapInfo.imageInfo.colorSpace = pixelMap.GetColorSpace();
436     pixmapInfo.imageInfo.alphaType = pixelMap.GetAlphaType();
437     pixmapInfo.imageInfo.baseDensity = pixelMap.GetBaseDensity();
438     pixmapInfo.data = const_cast<uint8_t *>(pixelMap.GetPixels());
439     pixmapInfo.bufferSize = pixelMap.GetByteCount();
440 }
441 
RotatePixelMap(float rotateDegrees,PixelMap & pixelMap)442 bool PostProc::RotatePixelMap(float rotateDegrees, PixelMap &pixelMap)
443 {
444     BasicTransformer trans;
445     PixmapInfo input(false);
446     ConvertPixelMapToPixmapInfo(pixelMap, input);
447     // Default rotation at the center of the image, so divide 2
448     trans.SetRotateParam(rotateDegrees, static_cast<float>(input.imageInfo.size.width) * FHALF,
449                          static_cast<float>(input.imageInfo.size.height) * FHALF);
450     return Transform(trans, input, pixelMap);
451 }
452 
ScalePixelMap(const Size & size,PixelMap & pixelMap)453 bool PostProc::ScalePixelMap(const Size &size, PixelMap &pixelMap)
454 {
455     int32_t srcWidth = pixelMap.GetWidth();
456     int32_t srcHeight = pixelMap.GetHeight();
457     if (srcWidth <= 0 || srcHeight <= 0) {
458         IMAGE_LOGE("[PostProc]src width:%{public}d, height:%{public}d is invalid.", srcWidth, srcHeight);
459         return false;
460     }
461     float scaleX = static_cast<float>(size.width) / static_cast<float>(srcWidth);
462     float scaleY = static_cast<float>(size.height) / static_cast<float>(srcHeight);
463     return ScalePixelMap(scaleX, scaleY, pixelMap);
464 }
465 
ScalePixelMap(float scaleX,float scaleY,PixelMap & pixelMap)466 bool PostProc::ScalePixelMap(float scaleX, float scaleY, PixelMap &pixelMap)
467 {
468     // returns directly with a scale of 1.0
469     if ((fabs(scaleX - 1.0f) < EPSILON) && (fabs(scaleY - 1.0f) < EPSILON)) {
470         return true;
471     }
472     BasicTransformer trans;
473     PixmapInfo input(false);
474     ConvertPixelMapToPixmapInfo(pixelMap, input);
475 
476     trans.SetScaleParam(scaleX, scaleY);
477     return Transform(trans, input, pixelMap);
478 }
479 
Transform(BasicTransformer & trans,const PixmapInfo & input,PixelMap & pixelMap)480 bool PostProc::Transform(BasicTransformer &trans, const PixmapInfo &input, PixelMap &pixelMap)
481 {
482     PixmapInfo output(false);
483     uint32_t ret;
484     if (decodeOpts_.allocatorType == AllocatorType::SHARE_MEM_ALLOC) {
485         typedef uint8_t *(*AllocMemory)(const Size &size, const uint64_t bufferSize, int &fd);
486         AllocMemory allcFunc = AllocSharedMemory;
487         ret = trans.TransformPixmap(input, output, allcFunc);
488     } else {
489         ret = trans.TransformPixmap(input, output);
490     }
491     if (ret != IMAGE_SUCCESS) {
492         output.Destroy();
493         return false;
494     }
495 
496     if (pixelMap.SetImageInfo(output.imageInfo) != SUCCESS) {
497         output.Destroy();
498         return false;
499     }
500     pixelMap.SetPixelsAddr(output.data, nullptr, output.bufferSize, decodeOpts_.allocatorType, nullptr);
501     return true;
502 }
503 
GetCropValue(const Rect & rect,const Size & size)504 CropValue PostProc::GetCropValue(const Rect &rect, const Size &size)
505 {
506     bool isSameSize = (rect.top == 0 && rect.left == 0 && rect.height == size.height && rect.width == size.width);
507     if (!IsHasCrop(rect) || isSameSize) {
508         return CropValue::NOCROP;
509     }
510     bool isValid = ((rect.top >= 0 && rect.width > 0 && rect.left >= 0 && rect.height > 0) &&
511                     (rect.top + rect.height <= size.height) && (rect.left + rect.width <= size.width));
512     if (!isValid) {
513         return CropValue::INVALID;
514     }
515     return CropValue::VALID;
516 }
517 
ValidCropValue(Rect & rect,const Size & size)518 CropValue PostProc::ValidCropValue(Rect &rect, const Size &size)
519 {
520     CropValue res = GetCropValue(rect, size);
521     if (res == CropValue::INVALID) {
522         if (rect.top + rect.height > size.height) {
523             rect.height = size.height - rect.top;
524         }
525         if (rect.left + rect.width > size.width) {
526             rect.width = size.width - rect.left;
527         }
528         res = GetCropValue(rect, size);
529     }
530     return res;
531 }
532 
IsHasCrop(const Rect & rect)533 bool PostProc::IsHasCrop(const Rect &rect)
534 {
535     return (rect.top != 0 || rect.left != 0 || rect.width != 0 || rect.height != 0);
536 }
537 
HasPixelConvert(const ImageInfo & srcImageInfo,ImageInfo & dstImageInfo)538 bool PostProc::HasPixelConvert(const ImageInfo &srcImageInfo, ImageInfo &dstImageInfo)
539 {
540     dstImageInfo.alphaType = ImageUtils::GetValidAlphaTypeByFormat(dstImageInfo.alphaType, dstImageInfo.pixelFormat);
541     return (dstImageInfo.pixelFormat != srcImageInfo.pixelFormat || dstImageInfo.alphaType != srcImageInfo.alphaType);
542 }
543 
SetScanlineCropAndConvert(const Rect & cropRect,ImageInfo & dstImageInfo,ImageInfo & srcImageInfo,ScanlineFilter & scanlineFilter,bool hasPixelConvert)544 void PostProc::SetScanlineCropAndConvert(const Rect &cropRect, ImageInfo &dstImageInfo, ImageInfo &srcImageInfo,
545                                          ScanlineFilter &scanlineFilter, bool hasPixelConvert)
546 {
547     if (hasPixelConvert) {
548         scanlineFilter.SetPixelConvert(srcImageInfo, dstImageInfo);
549     }
550 
551     Rect srcRect = cropRect;
552     if (IsHasCrop(cropRect)) {
553         dstImageInfo.size.width = cropRect.width;
554         dstImageInfo.size.height = cropRect.height;
555     } else {
556         srcRect = { 0, 0, srcImageInfo.size.width, srcImageInfo.size.height };
557         dstImageInfo.size = srcImageInfo.size;
558     }
559     scanlineFilter.SetSrcRegion(srcRect);
560 }
561 } // namespace Media
562 } // namespace OHOS
563