• 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 "pixel_convert_adapter.h"
17 #include "pixel_yuv_utils.h"
18 #include <map>
19 
20 #include "image_log.h"
21 #include "include/core/SkBitmap.h"
22 #include "include/core/SkCanvas.h"
23 #include "include/core/SkColor.h"
24 #include "include/core/SkColorSpace.h"
25 #include "include/core/SkImageInfo.h"
26 #include "include/core/SkPaint.h"
27 #include "include/core/SkPixmap.h"
28 #include "media_errors.h"
29 #ifdef _WIN32
30 #include <iomanip>
31 #endif
32 
33 #undef LOG_DOMAIN
34 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_IMAGE
35 
36 #undef LOG_TAG
37 #define LOG_TAG "PixelConvertAdapter"
38 
39 namespace OHOS {
40 namespace Media {
41 using namespace std;
42 
43 static const uint8_t NUM_0 = 0;
44 static const uint8_t NUM_1 = 1;
45 static const uint8_t NUM_2 = 2;
46 static const uint8_t NUM_3 = 3;
47 static const uint8_t NUM_4 = 4;
48 
49 const std::map<PixelFormat, AVPixelFormat> PixelConvertAdapter::FFMPEG_PIXEL_FORMAT_MAP = {
50     {PixelFormat::UNKNOWN, AV_PIX_FMT_NONE},
51     {PixelFormat::NV12, AV_PIX_FMT_NV12},
52     {PixelFormat::NV21, AV_PIX_FMT_NV21},
53     {PixelFormat::RGB_565, AV_PIX_FMT_RGB565},
54     {PixelFormat::RGBA_8888, AV_PIX_FMT_RGBA},
55     {PixelFormat::BGRA_8888, AV_PIX_FMT_BGRA},
56     {PixelFormat::ARGB_8888, AV_PIX_FMT_ARGB},
57     {PixelFormat::RGBA_F16, AV_PIX_FMT_RGBA64},
58     {PixelFormat::RGB_888, AV_PIX_FMT_RGB24},
59     {PixelFormat::YCRCB_P010, AV_PIX_FMT_P010LE},
60     {PixelFormat::YCBCR_P010, AV_PIX_FMT_P010LE},
61 };
62 
63 static const map<PixelFormat, SkColorType> PIXEL_FORMAT_MAP = {
64     { PixelFormat::UNKNOWN, SkColorType::kUnknown_SkColorType},
65     { PixelFormat::ARGB_8888, SkColorType::kRGBA_8888_SkColorType},
66     { PixelFormat::ALPHA_8, SkColorType::kAlpha_8_SkColorType},
67     { PixelFormat::RGB_565, SkColorType::kRGB_565_SkColorType},
68     { PixelFormat::RGBA_F16, SkColorType::kRGBA_F16_SkColorType},
69     { PixelFormat::RGBA_8888, SkColorType::kRGBA_8888_SkColorType},
70     { PixelFormat::BGRA_8888, SkColorType::kBGRA_8888_SkColorType},
71     { PixelFormat::RGB_888, SkColorType::kRGB_888x_SkColorType},
72     { PixelFormat::RGBA_1010102, SkColorType::kRGBA_1010102_SkColorType},
73     { PixelFormat::RGBA_U16, SkColorType::kR16G16B16A16_unorm_SkColorType},
74 };
75 
PixelFormatConvert(const PixelFormat & pixelFormat)76 static SkColorType PixelFormatConvert(const PixelFormat &pixelFormat)
77 {
78     auto formatSearch = PIXEL_FORMAT_MAP.find(pixelFormat);
79     return (formatSearch != PIXEL_FORMAT_MAP.end()) ? formatSearch->second : SkColorType::kUnknown_SkColorType;
80 }
81 
ARGBToRGBA(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)82 void ARGBToRGBA(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
83 {
84     bool cond = byteCount % NUM_4 != NUM_0;
85     CHECK_ERROR_RETURN_LOG(cond, "Pixel count must multiple of 4.");
86     uint8_t *src = srcPixels;
87     uint8_t *dst = dstPixels;
88     for (uint32_t i = NUM_0 ; i < byteCount; i += NUM_4) {
89         // 0-R 1-G 2-B 3-A
90         dst[NUM_0] = src[NUM_1];
91         dst[NUM_1] = src[NUM_2];
92         dst[NUM_2] = src[NUM_3];
93         dst[NUM_3] = src[NUM_0];
94         src += NUM_4;
95         dst += NUM_4;
96     }
97 }
98 
RGBAToARGB(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)99 void RGBAToARGB(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
100 {
101     bool cond = byteCount % NUM_4 != NUM_0;
102     CHECK_ERROR_RETURN_LOG(cond, "Pixel count must multiple of 4.");
103     uint8_t *src = srcPixels;
104     uint8_t *dst = dstPixels;
105     for (uint32_t i = NUM_0 ; i < byteCount; i += NUM_4) {
106         // 0-A 1-R 2-G 3-B
107         dst[NUM_0] = src[NUM_3];
108         dst[NUM_1] = src[NUM_0];
109         dst[NUM_2] = src[NUM_1];
110         dst[NUM_3] = src[NUM_2];
111         src += NUM_4;
112         dst += NUM_4;
113     }
114 }
115 
RGBxToRGB(const uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)116 bool PixelConvertAdapter::RGBxToRGB(const uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
117 {
118     if (byteCount % NUM_4 != NUM_0) {
119         IMAGE_LOGE("Pixel count must be multiple of 4.");
120         return false;
121     }
122     const uint8_t *src = srcPixels;
123     uint8_t *dst = dstPixels;
124     for (uint32_t i = NUM_0 ; i < byteCount; i += NUM_4) {
125         // 0-R 1-G 2-B
126         dst[NUM_0] = src[NUM_0];
127         dst[NUM_1] = src[NUM_1];
128         dst[NUM_2] = src[NUM_2];
129         src += NUM_4;
130         dst += NUM_3;
131     }
132     return true;
133 }
134 
RGBToRGBx(const uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)135 bool PixelConvertAdapter::RGBToRGBx(const uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
136 {
137     if (byteCount % NUM_3 != NUM_0) {
138         IMAGE_LOGE("Pixel count must be multiple of 3.");
139         return false;
140     }
141     const uint8_t *src = srcPixels;
142     uint8_t *dst = dstPixels;
143     for (uint32_t i = NUM_0 ; i < byteCount; i += NUM_3) {
144         // 0-R 1-G 2-B
145         dst[NUM_0] = src[NUM_0];
146         dst[NUM_1] = src[NUM_1];
147         dst[NUM_2] = src[NUM_2];
148         dst[NUM_3] = 0;
149         src += NUM_3;
150         dst += NUM_4;
151     }
152     return true;
153 }
154 
GetRGBxRowBytes(const ImageInfo & imgInfo)155 static int32_t GetRGBxRowBytes(const ImageInfo &imgInfo)
156 {
157     return imgInfo.size.width * NUM_4;
158 }
159 
GetRGBxSize(const ImageInfo & imgInfo)160 static int32_t GetRGBxSize(const ImageInfo &imgInfo)
161 {
162     return imgInfo.size.height * GetRGBxRowBytes(imgInfo);
163 }
164 
WritePixelsConvert(const void * srcPixels,uint32_t srcRowBytes,const ImageInfo & srcInfo,void * dstPixels,const Position & dstPos,uint32_t dstRowBytes,const ImageInfo & dstInfo)165 bool PixelConvertAdapter::WritePixelsConvert(const void *srcPixels, uint32_t srcRowBytes, const ImageInfo &srcInfo,
166                                              void *dstPixels, const Position &dstPos, uint32_t dstRowBytes,
167                                              const ImageInfo &dstInfo)
168 {
169     // basic valid check, other parameters valid check in writePixels method
170     if (srcPixels == nullptr || dstPixels == nullptr) {
171         IMAGE_LOGE("src or dst pixels invalid.");
172         return false;
173     }
174 
175     SkAlphaType srcAlphaType = static_cast<SkAlphaType>(srcInfo.alphaType);
176     SkAlphaType dstAlphaType = static_cast<SkAlphaType>(dstInfo.alphaType);
177     SkColorType srcColorType = PixelFormatConvert(srcInfo.pixelFormat);
178     SkColorType dstColorType = PixelFormatConvert(dstInfo.pixelFormat);
179     SkImageInfo srcImageInfo = SkImageInfo::Make(srcInfo.size.width, srcInfo.size.height, srcColorType, srcAlphaType);
180     SkImageInfo dstImageInfo = SkImageInfo::Make(dstInfo.size.width, dstInfo.size.height, dstColorType, dstAlphaType);
181 
182     int32_t dstRGBxSize = (dstInfo.pixelFormat == PixelFormat::RGB_888) ?
183         GetRGBxSize(dstInfo) : static_cast<int32_t>(NUM_1);
184     auto dstRGBxPixels = std::make_unique<uint8_t[]>(dstRGBxSize);
185     auto keepDstPixels = dstPixels;
186     dstPixels = (dstInfo.pixelFormat == PixelFormat::RGB_888) ? &dstRGBxPixels[0] : dstPixels;
187     dstRowBytes = (dstInfo.pixelFormat == PixelFormat::RGB_888) ?
188         static_cast<uint32_t>(GetRGBxRowBytes(dstInfo)) : dstRowBytes;
189 
190     int32_t srcRGBxSize = (srcInfo.pixelFormat == PixelFormat::RGB_888) ? GetRGBxSize(srcInfo) : NUM_1;
191     auto srcRGBxPixels = std::make_unique<uint8_t[]>(srcRGBxSize);
192     if (srcInfo.pixelFormat == PixelFormat::RGB_888) {
193         RGBToRGBx(static_cast<const uint8_t*>(srcPixels), &srcRGBxPixels[0], srcRowBytes * srcInfo.size.height);
194         srcPixels = &srcRGBxPixels[0];
195         srcRowBytes = static_cast<uint32_t>(GetRGBxRowBytes(srcInfo));
196     }
197     SkPixmap srcPixmap(srcImageInfo, srcPixels, srcRowBytes);
198 
199     SkBitmap dstBitmap;
200     if (!dstBitmap.installPixels(dstImageInfo, dstPixels, dstRowBytes)) {
201         IMAGE_LOGE("WritePixelsConvert dst bitmap install pixels failed.");
202         return false;
203     }
204     if (!dstBitmap.writePixels(srcPixmap, dstPos.x, dstPos.y)) {
205         IMAGE_LOGE("WritePixelsConvert dst bitmap write pixels by source failed.");
206         return false;
207     }
208 
209     if (dstInfo.pixelFormat == PixelFormat::RGB_888) {
210         RGBxToRGB(&dstRGBxPixels[0], static_cast<uint8_t*>(keepDstPixels), dstRGBxSize);
211     }
212 
213     return true;
214 }
215 
ReadPixelsConvert(const void * srcPixels,const Position & srcPos,uint32_t srcRowBytes,const ImageInfo & srcInfo,void * dstPixels,uint32_t dstRowBytes,const ImageInfo & dstInfo)216 bool PixelConvertAdapter::ReadPixelsConvert(const void *srcPixels, const Position &srcPos, uint32_t srcRowBytes,
217                                             const ImageInfo &srcInfo, void *dstPixels, uint32_t dstRowBytes,
218                                             const ImageInfo &dstInfo)
219 {
220     // basic valid check, other parameters valid check in readPixels method
221     if (srcPixels == nullptr || dstPixels == nullptr) {
222         IMAGE_LOGE("src or dst pixels invalid.");
223         return false;
224     }
225     SkAlphaType srcAlphaType = static_cast<SkAlphaType>(srcInfo.alphaType);
226     SkAlphaType dstAlphaType = static_cast<SkAlphaType>(dstInfo.alphaType);
227     SkColorType srcColorType = PixelFormatConvert(srcInfo.pixelFormat);
228     SkColorType dstColorType = PixelFormatConvert(dstInfo.pixelFormat);
229     SkImageInfo srcImageInfo = SkImageInfo::Make(srcInfo.size.width, srcInfo.size.height, srcColorType, srcAlphaType);
230     SkImageInfo dstImageInfo = SkImageInfo::Make(dstInfo.size.width, dstInfo.size.height, dstColorType, dstAlphaType);
231 
232     SkBitmap srcBitmap;
233     if (!srcBitmap.installPixels(srcImageInfo, const_cast<void *>(srcPixels), srcRowBytes)) {
234         IMAGE_LOGE("ReadPixelsConvert src bitmap install pixels failed.");
235         return false;
236     }
237     if (!srcBitmap.readPixels(dstImageInfo, dstPixels, dstRowBytes, srcPos.x, srcPos.y)) {
238         IMAGE_LOGE("ReadPixelsConvert read dst pixels from source failed.");
239         return false;
240     }
241     return true;
242 }
243 
EraseBitmap(const void * srcPixels,uint32_t srcRowBytes,const ImageInfo & srcInfo,uint32_t color)244 bool PixelConvertAdapter::EraseBitmap(const void *srcPixels, uint32_t srcRowBytes, const ImageInfo &srcInfo,
245                                       uint32_t color)
246 {
247     if (srcPixels == nullptr) {
248         IMAGE_LOGE("srcPixels is null.");
249         return false;
250     }
251     SkAlphaType srcAlphaType = static_cast<SkAlphaType>(srcInfo.alphaType);
252     SkColorType srcColorType = PixelFormatConvert(srcInfo.pixelFormat);
253     SkImageInfo srcImageInfo = SkImageInfo::Make(srcInfo.size.width, srcInfo.size.height, srcColorType, srcAlphaType);
254     SkBitmap srcBitmap;
255     if (!srcBitmap.installPixels(srcImageInfo, const_cast<void *>(srcPixels), srcRowBytes)) {
256         IMAGE_LOGE("ReadPixelsConvert src bitmap install pixels failed.");
257         return false;
258     }
259     const SkColor4f skColor = SkColor4f::FromColor(color);
260     SkPaint paint;
261     paint.setColor4f(skColor, SkColorSpace::MakeSRGB().get());
262     paint.setBlendMode(SkBlendMode::kSrc);
263     SkCanvas canvas(srcBitmap);
264     canvas.drawPaint(paint);
265     return true;
266 }
267 
YUV420ToRGB888(const uint8_t * in,YuvImageInfo & srcInfo,uint8_t * out,YuvImageInfo & dstInfo)268 bool PixelConvertAdapter::YUV420ToRGB888(const uint8_t *in, YuvImageInfo &srcInfo, uint8_t *out, YuvImageInfo &dstInfo)
269 {
270     bool cond = PixelYuvUtils::YuvScale(const_cast<uint8_t *>(in), srcInfo, out, dstInfo, SWS_BICUBIC) != SUCCESS;
271     CHECK_ERROR_RETURN_RET_LOG(cond, false, "YUV420ToRGB888 failed");
272     return true;
273 }
274 
275 } // namespace Media
276 } // namespace OHOS
277