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