1 /*
2 * Copyright (c) 2023 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 "render/rs_pixel_map_util.h"
17 #include <memory>
18
19 #include "pixel_map.h"
20 #include "platform/common/rs_log.h"
21 #include "platform/common/rs_system_properties.h"
22 #include "drawing/engine_adapter/impl_interface/bitmap_impl.h"
23 #include "image/yuv_info.h"
24
25 namespace OHOS {
26 namespace Rosen {
27 using namespace Media;
28 namespace {
29 constexpr float HALF_F = 2;
30 }
31
ColorSpaceToDrawingColorSpace(ColorManager::ColorSpaceName colorSpaceName)32 static std::shared_ptr<Drawing::ColorSpace> ColorSpaceToDrawingColorSpace(
33 ColorManager::ColorSpaceName colorSpaceName)
34 {
35 switch (colorSpaceName) {
36 case ColorManager::ColorSpaceName::DCI_P3:
37 case ColorManager::ColorSpaceName::DISPLAY_P3:
38 return Drawing::ColorSpace::CreateRGB(
39 Drawing::CMSTransferFuncType::SRGB, Drawing::CMSMatrixType::DCIP3);
40 case ColorManager::ColorSpaceName::LINEAR_SRGB:
41 return Drawing::ColorSpace::CreateSRGBLinear();
42 case ColorManager::ColorSpaceName::SRGB:
43 return Drawing::ColorSpace::CreateSRGB();
44 default:
45 return Drawing::ColorSpace::CreateSRGB();
46 }
47 }
48
PixelFormatToDrawingColorType(PixelFormat pixelFormat)49 static Drawing::ColorType PixelFormatToDrawingColorType(PixelFormat pixelFormat)
50 {
51 switch (pixelFormat) {
52 case PixelFormat::RGB_565:
53 return Drawing::ColorType::COLORTYPE_RGB_565;
54 case PixelFormat::RGBA_8888:
55 return Drawing::ColorType::COLORTYPE_RGBA_8888;
56 case PixelFormat::BGRA_8888:
57 return Drawing::ColorType::COLORTYPE_BGRA_8888;
58 case PixelFormat::ALPHA_8:
59 return Drawing::ColorType::COLORTYPE_ALPHA_8;
60 case PixelFormat::RGBA_F16:
61 return Drawing::ColorType::COLORTYPE_RGBA_F16;
62 case PixelFormat::RGBA_1010102:
63 return Drawing::ColorType::COLORTYPE_RGBA_1010102;
64 case PixelFormat::UNKNOWN:
65 case PixelFormat::ARGB_8888:
66 case PixelFormat::RGB_888:
67 case PixelFormat::NV21:
68 case PixelFormat::NV12:
69 case PixelFormat::CMYK:
70 default:
71 return Drawing::ColorType::COLORTYPE_UNKNOWN;
72 }
73 }
74
AlphaTypeToDrawingAlphaType(AlphaType alphaType)75 static Drawing::AlphaType AlphaTypeToDrawingAlphaType(AlphaType alphaType)
76 {
77 switch (alphaType) {
78 case AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
79 return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
80 case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
81 return Drawing::AlphaType::ALPHATYPE_OPAQUE;
82 case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
83 return Drawing::AlphaType::ALPHATYPE_PREMUL;
84 case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
85 return Drawing::AlphaType::ALPHATYPE_UNPREMUL;
86 default:
87 return Drawing::AlphaType::ALPHATYPE_UNKNOWN;
88 }
89 }
90
91
92 struct PixelMapReleaseContext {
PixelMapReleaseContextOHOS::Rosen::PixelMapReleaseContext93 explicit PixelMapReleaseContext(std::shared_ptr<PixelMap> pixelMap) : pixelMap_(pixelMap) {}
94
~PixelMapReleaseContextOHOS::Rosen::PixelMapReleaseContext95 ~PixelMapReleaseContext()
96 {
97 pixelMap_ = nullptr;
98 }
99
100 private:
101 std::shared_ptr<PixelMap> pixelMap_;
102 };
103
PixelMapReleaseProc(const void *,void * context)104 static void PixelMapReleaseProc(const void* /* pixels */, void* context)
105 {
106 PixelMapReleaseContext* ctx = static_cast<PixelMapReleaseContext*>(context);
107 if (ctx) {
108 delete ctx;
109 ctx = nullptr;
110 }
111 }
112
GetPixelmapColorSpace(const std::shared_ptr<Media::PixelMap> & pixelMap)113 std::shared_ptr<Drawing::ColorSpace> RSPixelMapUtil::GetPixelmapColorSpace(
114 const std::shared_ptr<Media::PixelMap>& pixelMap)
115 {
116 if (!pixelMap) {
117 return Drawing::ColorSpace::CreateSRGB();
118 }
119 return ColorSpaceToDrawingColorSpace(pixelMap->InnerGetGrColorSpace().GetColorSpaceName());
120 }
121
ExtractDrawingImage(std::shared_ptr<Media::PixelMap> pixelMap)122 std::shared_ptr<Drawing::Image> RSPixelMapUtil::ExtractDrawingImage(
123 std::shared_ptr<Media::PixelMap> pixelMap)
124 {
125 if (!pixelMap) {
126 return nullptr;
127 }
128 ImageInfo imageInfo;
129 pixelMap->GetImageInfo(imageInfo);
130 Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
131 PixelFormatToDrawingColorType(imageInfo.pixelFormat),
132 AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
133 ColorSpaceToDrawingColorSpace(pixelMap->InnerGetGrColorSpace().GetColorSpaceName()) };
134 Drawing::Pixmap imagePixmap(drawingImageInfo,
135 reinterpret_cast<const void*>(pixelMap->GetPixels()), pixelMap->GetRowStride());
136 PixelMapReleaseContext* releaseContext = new PixelMapReleaseContext(pixelMap);
137 auto image = Drawing::Image::MakeFromRaster(imagePixmap, PixelMapReleaseProc, releaseContext);
138 if (!image) {
139 RS_LOGE("RSPixelMapUtil::ExtractDrawingImage fail");
140 delete releaseContext;
141 releaseContext = nullptr;
142 }
143 return image;
144 }
145
146
TransformDataSetForAstc(std::shared_ptr<Media::PixelMap> pixelMap,Drawing::Rect & src,Drawing::Rect & dst,Drawing::Canvas & canvas)147 void RSPixelMapUtil::TransformDataSetForAstc(std::shared_ptr<Media::PixelMap> pixelMap,
148 Drawing::Rect& src, Drawing::Rect& dst, Drawing::Canvas& canvas)
149 {
150 TransformData transformData;
151 pixelMap->GetTransformData(transformData);
152 Size realSize;
153 pixelMap->GetAstcRealSize(realSize);
154 dst.SetLeft(dst.GetLeft() - (realSize.width - src.GetRight()) / HALF_F);
155 dst.SetTop(dst.GetTop() - (realSize.height - src.GetBottom()) / HALF_F);
156 dst.SetRight(dst.GetRight() + (realSize.width - src.GetRight()) / HALF_F);
157 dst.SetBottom(dst.GetBottom() + (realSize.height - src.GetBottom()) / HALF_F);
158 if (transformData.scaleX != 0 && transformData.scaleY != 0) {
159 src.SetRight(src.GetRight() / abs(transformData.scaleX));
160 src.SetBottom(src.GetBottom() / abs(transformData.scaleY));
161 }
162 Drawing::Matrix matrix;
163 matrix.PostScale(transformData.scaleX, transformData.scaleY, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
164 dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
165 matrix.PostRotate(transformData.rotateD, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
166 dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
167 if (transformData.flipX) {
168 matrix.PostScale(-1, 1, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
169 dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
170 }
171 if (transformData.flipY) {
172 matrix.PostScale(1, -1, dst.GetLeft() / HALF_F + dst.GetRight() / HALF_F,
173 dst.GetTop() / HALF_F + dst.GetBottom() / HALF_F);
174 }
175 canvas.ConcatMatrix(matrix);
176 if (transformData.cropLeft >= 0 && transformData.cropTop >= 0 && transformData.cropWidth > 0 &&
177 transformData.cropHeight > 0 && transformData.cropLeft + transformData.cropWidth <= realSize.width &&
178 transformData.cropTop + transformData.cropHeight <= realSize.height) {
179 float rightMinus = src.GetRight() - transformData.cropLeft - transformData.cropWidth;
180 float bottomMinus = src.GetBottom() - transformData.cropTop - transformData.cropHeight;
181 src.SetLeft(src.GetLeft() + transformData.cropLeft);
182 src.SetTop(src.GetTop() + transformData.cropTop);
183 src.SetRight(src.GetRight() - rightMinus);
184 src.SetBottom(src.GetBottom() - bottomMinus);
185 dst.SetLeft(dst.GetLeft() + (realSize.width - transformData.cropWidth) / HALF_F);
186 dst.SetTop(dst.GetTop() + (realSize.height - transformData.cropHeight) / HALF_F);
187 dst.SetRight(dst.GetRight() - (realSize.width - transformData.cropWidth) / HALF_F);
188 dst.SetBottom(dst.GetBottom() - (realSize.height - transformData.cropHeight) / HALF_F);
189 }
190 if (transformData.scaleX != 0 && transformData.scaleY != 0) {
191 dst.SetLeft(dst.GetLeft() + transformData.translateX / HALF_F / abs(transformData.scaleX));
192 dst.SetTop(dst.GetTop() + transformData.translateY / HALF_F / abs(transformData.scaleY));
193 dst.SetRight(dst.GetRight() + transformData.translateX / HALF_F / abs(transformData.scaleX));
194 dst.SetBottom(dst.GetBottom() + transformData.translateY / HALF_F / abs(transformData.scaleY));
195 }
196 }
197
DrawPixelMap(Drawing::Canvas & canvas,Media::PixelMap & pixelMap,const Drawing::scalar px,const Drawing::scalar py)198 void RSPixelMapUtil::DrawPixelMap(Drawing::Canvas& canvas, Media::PixelMap& pixelMap,
199 const Drawing::scalar px, const Drawing::scalar py)
200 {
201 ImageInfo imageInfo;
202 pixelMap.GetImageInfo(imageInfo);
203 Drawing::ImageInfo drawingImageInfo { imageInfo.size.width, imageInfo.size.height,
204 PixelFormatToDrawingColorType(imageInfo.pixelFormat),
205 AlphaTypeToDrawingAlphaType(imageInfo.alphaType),
206 ColorSpaceToDrawingColorSpace(pixelMap.InnerGetGrColorSpace().GetColorSpaceName()) };
207 Drawing::Bitmap pixelBitmap;
208 pixelBitmap.InstallPixels(
209 drawingImageInfo, reinterpret_cast<void*>(pixelMap.GetWritablePixels()),
210 static_cast<uint32_t>(pixelMap.GetRowBytes()));
211 canvas.DrawBitmap(pixelBitmap, px, py);
212 }
213
IsYUVFormat(std::shared_ptr<Media::PixelMap> pixelMap)214 bool RSPixelMapUtil::IsYUVFormat(std::shared_ptr<Media::PixelMap> pixelMap)
215 {
216 if (!pixelMap) {
217 return false;
218 }
219 #if defined(ROSEN_OHOS) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
220 if (pixelMap->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC) {
221 return false;
222 }
223 #endif
224 ImageInfo imageInfo;
225 pixelMap->GetImageInfo(imageInfo);
226 return imageInfo.pixelFormat == Media::PixelFormat::NV21 || imageInfo.pixelFormat == Media::PixelFormat::NV12;
227 }
228
YUVPixelFormatToPlaneConfig(Media::PixelFormat pixelFormat)229 static Drawing::YUVInfo::PlaneConfig YUVPixelFormatToPlaneConfig(Media::PixelFormat pixelFormat)
230 {
231 switch (pixelFormat) {
232 case Media::PixelFormat::NV12:
233 return Drawing::YUVInfo::PlaneConfig::Y_UV;
234 case Media::PixelFormat::NV21:
235 return Drawing::YUVInfo::PlaneConfig::Y_VU;
236 default:
237 return Drawing::YUVInfo::PlaneConfig::UNKNOWN;
238 }
239 }
240
YUVPixelFormatToSubSampling(Media::PixelFormat pixelFormat)241 static Drawing::YUVInfo::SubSampling YUVPixelFormatToSubSampling(Media::PixelFormat pixelFormat)
242 {
243 switch (pixelFormat) {
244 case Media::PixelFormat::NV12:
245 case Media::PixelFormat::NV21:
246 return Drawing::YUVInfo::SubSampling::K420;
247 default:
248 return Drawing::YUVInfo::SubSampling::UNKNOWN;
249 }
250 }
251
YUVPixelFormatToYUVColorSpace(Media::PixelFormat pixelFormat)252 static Drawing::YUVInfo::YUVColorSpace YUVPixelFormatToYUVColorSpace(Media::PixelFormat pixelFormat)
253 {
254 switch (pixelFormat) {
255 case Media::PixelFormat::NV12:
256 case Media::PixelFormat::NV21:
257 return Drawing::YUVInfo::YUVColorSpace::JPEG_FULL_YUVCOLORSPACE;
258 default:
259 return Drawing::YUVInfo::YUVColorSpace::IDENTITY_YUVCOLORSPACE;
260 }
261 }
262
ConvertYUVPixelMapToDrawingImage(std::shared_ptr<Drawing::GPUContext> gpuContext,std::shared_ptr<Media::PixelMap> pixelMap)263 std::shared_ptr<Drawing::Image> RSPixelMapUtil::ConvertYUVPixelMapToDrawingImage(
264 std::shared_ptr<Drawing::GPUContext> gpuContext, std::shared_ptr<Media::PixelMap> pixelMap)
265 {
266 if (gpuContext && pixelMap && IsYUVFormat(pixelMap)) {
267 ImageInfo imageInfo;
268 pixelMap->GetImageInfo(imageInfo);
269 Drawing::YUVInfo info(pixelMap->GetWidth(), pixelMap->GetHeight(),
270 YUVPixelFormatToPlaneConfig(imageInfo.pixelFormat),
271 YUVPixelFormatToSubSampling(imageInfo.pixelFormat),
272 YUVPixelFormatToYUVColorSpace(imageInfo.pixelFormat));
273 return Drawing::Image::MakeFromYUVAPixmaps(*gpuContext, info,
274 const_cast<void *>(reinterpret_cast<const void*>(pixelMap->GetPixels())));
275 }
276 return nullptr;
277 }
278
IsSupportZeroCopy(std::shared_ptr<Media::PixelMap> pixelMap,const Drawing::SamplingOptions & sampling)279 bool RSPixelMapUtil::IsSupportZeroCopy(std::shared_ptr<Media::PixelMap> pixelMap,
280 const Drawing::SamplingOptions& sampling)
281 {
282 if (!(pixelMap->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC)) {
283 return false;
284 }
285 ImageInfo imageInfo;
286 pixelMap->GetImageInfo(imageInfo);
287 if (imageInfo.pixelFormat == Media::PixelFormat::RGBA_8888) {
288 return sampling.GetMipmapMode() != Drawing::MipmapMode::LINEAR && RSSystemProperties::IsPhoneType();
289 }
290 return true;
291 }
292 } // namespace Rosen
293 } // namespace OHOS
294