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 static void ARGBToRGBA(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
83 {
84 if (byteCount % NUM_4 != NUM_0) {
85 IMAGE_LOGE("Pixel count must multiple of 4.");
86 return;
87 }
88 uint8_t *src = srcPixels;
89 uint8_t *dst = dstPixels;
90 for (uint32_t i = NUM_0 ; i < byteCount; i += NUM_4) {
91 // 0-R 1-G 2-B 3-A
92 dst[NUM_0] = src[NUM_1];
93 dst[NUM_1] = src[NUM_2];
94 dst[NUM_2] = src[NUM_3];
95 dst[NUM_3] = src[NUM_0];
96 src += NUM_4;
97 dst += NUM_4;
98 }
99 }
100
RGBAToARGB(uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)101 static void RGBAToARGB(uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
102 {
103 if (byteCount % NUM_4 != NUM_0) {
104 IMAGE_LOGE("Pixel count must multiple of 4.");
105 return;
106 }
107 uint8_t *src = srcPixels;
108 uint8_t *dst = dstPixels;
109 for (uint32_t i = NUM_0 ; i < byteCount; i += NUM_4) {
110 // 0-A 1-R 2-G 3-B
111 dst[NUM_0] = src[NUM_3];
112 dst[NUM_1] = src[NUM_0];
113 dst[NUM_2] = src[NUM_1];
114 dst[NUM_3] = src[NUM_2];
115 src += NUM_4;
116 dst += NUM_4;
117 }
118 }
119
RGBxToRGB(const uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)120 bool PixelConvertAdapter::RGBxToRGB(const uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
121 {
122 if (byteCount % NUM_4 != NUM_0) {
123 IMAGE_LOGE("Pixel count must be multiple of 4.");
124 return false;
125 }
126 const uint8_t *src = srcPixels;
127 uint8_t *dst = dstPixels;
128 for (uint32_t i = NUM_0 ; i < byteCount; i += NUM_4) {
129 // 0-R 1-G 2-B
130 dst[NUM_0] = src[NUM_0];
131 dst[NUM_1] = src[NUM_1];
132 dst[NUM_2] = src[NUM_2];
133 src += NUM_4;
134 dst += NUM_3;
135 }
136 return true;
137 }
138
RGBToRGBx(const uint8_t * srcPixels,uint8_t * dstPixels,uint32_t byteCount)139 bool PixelConvertAdapter::RGBToRGBx(const uint8_t* srcPixels, uint8_t* dstPixels, uint32_t byteCount)
140 {
141 if (byteCount % NUM_3 != NUM_0) {
142 IMAGE_LOGE("Pixel count must be multiple of 3.");
143 return false;
144 }
145 const uint8_t *src = srcPixels;
146 uint8_t *dst = dstPixels;
147 for (uint32_t i = NUM_0 ; i < byteCount; i += NUM_3) {
148 // 0-R 1-G 2-B
149 dst[NUM_0] = src[NUM_0];
150 dst[NUM_1] = src[NUM_1];
151 dst[NUM_2] = src[NUM_2];
152 dst[NUM_3] = 0;
153 src += NUM_3;
154 dst += NUM_4;
155 }
156 return true;
157 }
158
GetRGBxRowBytes(const ImageInfo & imgInfo)159 static int32_t GetRGBxRowBytes(const ImageInfo &imgInfo)
160 {
161 return imgInfo.size.width * NUM_4;
162 }
163
GetRGBxSize(const ImageInfo & imgInfo)164 static int32_t GetRGBxSize(const ImageInfo &imgInfo)
165 {
166 return imgInfo.size.height * GetRGBxRowBytes(imgInfo);
167 }
168
WritePixelsConvert(const void * srcPixels,uint32_t srcRowBytes,const ImageInfo & srcInfo,void * dstPixels,const Position & dstPos,uint32_t dstRowBytes,const ImageInfo & dstInfo)169 bool PixelConvertAdapter::WritePixelsConvert(const void *srcPixels, uint32_t srcRowBytes, const ImageInfo &srcInfo,
170 void *dstPixels, const Position &dstPos, uint32_t dstRowBytes,
171 const ImageInfo &dstInfo)
172 {
173 // basic valid check, other parameters valid check in writePixels method
174 if (srcPixels == nullptr || dstPixels == nullptr) {
175 IMAGE_LOGE("src or dst pixels invalid.");
176 return false;
177 }
178
179 SkAlphaType srcAlphaType = static_cast<SkAlphaType>(srcInfo.alphaType);
180 SkAlphaType dstAlphaType = static_cast<SkAlphaType>(dstInfo.alphaType);
181 SkColorType srcColorType = PixelFormatConvert(srcInfo.pixelFormat);
182 SkColorType dstColorType = PixelFormatConvert(dstInfo.pixelFormat);
183 SkImageInfo srcImageInfo = SkImageInfo::Make(srcInfo.size.width, srcInfo.size.height, srcColorType, srcAlphaType);
184 SkImageInfo dstImageInfo = SkImageInfo::Make(dstInfo.size.width, dstInfo.size.height, dstColorType, dstAlphaType);
185
186 int32_t dstRGBxSize = (dstInfo.pixelFormat == PixelFormat::RGB_888) ?
187 GetRGBxSize(dstInfo) : static_cast<int32_t>(NUM_1);
188 auto dstRGBxPixels = std::make_unique<uint8_t[]>(dstRGBxSize);
189 auto keepDstPixels = dstPixels;
190 dstPixels = (dstInfo.pixelFormat == PixelFormat::RGB_888) ? &dstRGBxPixels[0] : dstPixels;
191 dstRowBytes = (dstInfo.pixelFormat == PixelFormat::RGB_888) ?
192 static_cast<uint32_t>(GetRGBxRowBytes(dstInfo)) : dstRowBytes;
193
194 int32_t srcRGBxSize = (srcInfo.pixelFormat == PixelFormat::RGB_888) ? GetRGBxSize(srcInfo) : NUM_1;
195 auto srcRGBxPixels = std::make_unique<uint8_t[]>(srcRGBxSize);
196 if (srcInfo.pixelFormat == PixelFormat::RGB_888) {
197 RGBToRGBx(static_cast<const uint8_t*>(srcPixels), &srcRGBxPixels[0], srcRowBytes * srcInfo.size.height);
198 srcPixels = &srcRGBxPixels[0];
199 srcRowBytes = static_cast<uint32_t>(GetRGBxRowBytes(srcInfo));
200 }
201 SkPixmap srcPixmap(srcImageInfo, srcPixels, srcRowBytes);
202 if (srcInfo.pixelFormat == PixelFormat::ARGB_8888) {
203 uint8_t* src = static_cast<uint8_t*>(srcPixmap.writable_addr());
204 ARGBToRGBA(src, src, srcRowBytes * srcInfo.size.height);
205 }
206
207 SkBitmap dstBitmap;
208 if (!dstBitmap.installPixels(dstImageInfo, dstPixels, dstRowBytes)) {
209 IMAGE_LOGE("WritePixelsConvert dst bitmap install pixels failed.");
210 return false;
211 }
212 if (!dstBitmap.writePixels(srcPixmap, dstPos.x, dstPos.y)) {
213 IMAGE_LOGE("WritePixelsConvert dst bitmap write pixels by source failed.");
214 return false;
215 }
216
217 if (dstInfo.pixelFormat == PixelFormat::ARGB_8888) {
218 uint32_t dstSize = dstRowBytes * dstInfo.size.height;
219 RGBAToARGB(static_cast<uint8_t*>(dstPixels), static_cast<uint8_t*>(dstPixels), dstSize);
220 } else if (dstInfo.pixelFormat == PixelFormat::RGB_888) {
221 RGBxToRGB(&dstRGBxPixels[0], static_cast<uint8_t*>(keepDstPixels), dstRGBxSize);
222 }
223
224 return true;
225 }
226
ReadPixelsConvert(const void * srcPixels,const Position & srcPos,uint32_t srcRowBytes,const ImageInfo & srcInfo,void * dstPixels,uint32_t dstRowBytes,const ImageInfo & dstInfo)227 bool PixelConvertAdapter::ReadPixelsConvert(const void *srcPixels, const Position &srcPos, uint32_t srcRowBytes,
228 const ImageInfo &srcInfo, void *dstPixels, uint32_t dstRowBytes,
229 const ImageInfo &dstInfo)
230 {
231 // basic valid check, other parameters valid check in readPixels method
232 if (srcPixels == nullptr || dstPixels == nullptr) {
233 IMAGE_LOGE("src or dst pixels invalid.");
234 return false;
235 }
236 SkAlphaType srcAlphaType = static_cast<SkAlphaType>(srcInfo.alphaType);
237 SkAlphaType dstAlphaType = static_cast<SkAlphaType>(dstInfo.alphaType);
238 SkColorType srcColorType = PixelFormatConvert(srcInfo.pixelFormat);
239 SkColorType dstColorType = PixelFormatConvert(dstInfo.pixelFormat);
240 SkImageInfo srcImageInfo = SkImageInfo::Make(srcInfo.size.width, srcInfo.size.height, srcColorType, srcAlphaType);
241 SkImageInfo dstImageInfo = SkImageInfo::Make(dstInfo.size.width, dstInfo.size.height, dstColorType, dstAlphaType);
242
243 SkBitmap srcBitmap;
244 if (!srcBitmap.installPixels(srcImageInfo, const_cast<void *>(srcPixels), srcRowBytes)) {
245 IMAGE_LOGE("ReadPixelsConvert src bitmap install pixels failed.");
246 return false;
247 }
248 if (!srcBitmap.readPixels(dstImageInfo, dstPixels, dstRowBytes, srcPos.x, srcPos.y)) {
249 IMAGE_LOGE("ReadPixelsConvert read dst pixels from source failed.");
250 return false;
251 }
252 return true;
253 }
254
EraseBitmap(const void * srcPixels,uint32_t srcRowBytes,const ImageInfo & srcInfo,uint32_t color)255 bool PixelConvertAdapter::EraseBitmap(const void *srcPixels, uint32_t srcRowBytes, const ImageInfo &srcInfo,
256 uint32_t color)
257 {
258 if (srcPixels == nullptr) {
259 IMAGE_LOGE("srcPixels is null.");
260 return false;
261 }
262 SkAlphaType srcAlphaType = static_cast<SkAlphaType>(srcInfo.alphaType);
263 SkColorType srcColorType = PixelFormatConvert(srcInfo.pixelFormat);
264 SkImageInfo srcImageInfo = SkImageInfo::Make(srcInfo.size.width, srcInfo.size.height, srcColorType, srcAlphaType);
265 SkBitmap srcBitmap;
266 if (!srcBitmap.installPixels(srcImageInfo, const_cast<void *>(srcPixels), srcRowBytes)) {
267 IMAGE_LOGE("ReadPixelsConvert src bitmap install pixels failed.");
268 return false;
269 }
270 const SkColor4f skColor = SkColor4f::FromColor(color);
271 SkPaint paint;
272 paint.setColor4f(skColor, SkColorSpace::MakeSRGB().get());
273 paint.setBlendMode(SkBlendMode::kSrc);
274 SkCanvas canvas(srcBitmap);
275 canvas.drawPaint(paint);
276 return true;
277 }
278
YUV420ToRGB888(const uint8_t * in,YuvImageInfo & srcInfo,uint8_t * out,YuvImageInfo & dstInfo)279 bool PixelConvertAdapter::YUV420ToRGB888(const uint8_t *in, YuvImageInfo &srcInfo, uint8_t *out, YuvImageInfo &dstInfo)
280 {
281 if (PixelYuvUtils::YuvScale(const_cast<uint8_t *>(in), srcInfo, out, dstInfo, SWS_BICUBIC) != SUCCESS) {
282 IMAGE_LOGE("YUV420ToRGB888 failed");
283 return false;
284 }
285 return true;
286 }
287
288 } // namespace Media
289 } // namespace OHOS
290