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