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