• 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_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