• 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 "core/image/image_provider.h"
17 
18 #include "experimental/svg/model/SkSVGDOM.h"
19 #include "third_party/skia/include/core/SkGraphics.h"
20 #include "third_party/skia/include/core/SkStream.h"
21 
22 #include "base/thread/background_task_executor.h"
23 #include "core/common/container.h"
24 #include "core/common/container_scope.h"
25 #include "core/components/image/flutter_render_image.h"
26 #include "core/event/ace_event_helper.h"
27 #include "core/image/flutter_image_cache.h"
28 #include "core/image/image_object.h"
29 
30 namespace OHOS::Ace {
31 namespace {
32 
33 constexpr double RESIZE_MAX_PROPORTION = 0.5 * 0.5; // Cache image when resize exceeds 25%
34 // If a picture is a wide color gamut picture, its area value will be larger than this threshold.
35 constexpr double SRGB_GAMUT_AREA = 0.104149;
36 
37 } // namespace
38 
FetchImageObject(ImageSourceInfo imageInfo,ImageObjSuccessCallback successCallback,UploadSuccessCallback uploadSuccessCallback,FailedCallback failedCallback,const WeakPtr<PipelineContext> context,bool syncMode,bool useSkiaSvg,bool needAutoResize,RefPtr<FlutterRenderTaskHolder> & renderTaskHolder,OnPostBackgroundTask onBackgroundTaskPostCallback)39 void ImageProvider::FetchImageObject(
40     ImageSourceInfo imageInfo,
41     ImageObjSuccessCallback successCallback,
42     UploadSuccessCallback uploadSuccessCallback,
43     FailedCallback failedCallback,
44     const WeakPtr<PipelineContext> context,
45     bool syncMode,
46     bool useSkiaSvg,
47     bool needAutoResize,
48     RefPtr<FlutterRenderTaskHolder>& renderTaskHolder,
49     OnPostBackgroundTask onBackgroundTaskPostCallback)
50 {
51     auto task = [context, imageInfo, successCallback, failedCallback, useSkiaSvg, renderTaskHolder,
52                     uploadSuccessCallback, needAutoResize, id = Container::CurrentId()]() mutable {
53         ContainerScope scope(id);
54         auto pipelineContext = context.Upgrade();
55         if (!pipelineContext) {
56             LOGE("pipline context has been released. imageInfo: %{private}s", imageInfo.ToString().c_str());
57             return;
58         }
59         auto taskExecutor = pipelineContext->GetTaskExecutor();
60         if (!taskExecutor) {
61             LOGE("task executor is null. imageInfo: %{private}s", imageInfo.ToString().c_str());
62             return;
63         }
64         RefPtr<ImageObject> imageObj = QueryImageObjectFromCache(imageInfo, pipelineContext);
65         if (!imageObj) { // if image object is not in cache, generate a new one.
66             imageObj = GeneraterAceImageObject(imageInfo, pipelineContext, useSkiaSvg);
67         }
68         if (!imageObj) { // if it fails to generate an image object, trigger fail callback.
69             taskExecutor->PostTask(
70                 [failedCallback, imageInfo] { failedCallback(imageInfo); }, TaskExecutor::TaskType::UI);
71             return;
72         }
73         taskExecutor->PostTask([successCallback, imageInfo, imageObj]() { successCallback(imageInfo, imageObj); },
74             TaskExecutor::TaskType::UI);
75         bool canStartUploadImageObj = !needAutoResize && (imageObj->GetFrameCount() == 1);
76         if (canStartUploadImageObj) {
77             bool forceResize = (!imageObj->IsSvg()) && (imageInfo.IsSourceDimensionValid());
78             FlutterRenderImage::UploadImageObjToGpuForRender(imageObj, context, renderTaskHolder, uploadSuccessCallback,
79                 failedCallback, imageObj->GetImageSize(), forceResize, true);
80         }
81     };
82     if (syncMode) {
83         task();
84         return;
85     }
86     CancelableTask cancelableTask(std::move(task));
87     if (onBackgroundTaskPostCallback) {
88         onBackgroundTaskPostCallback(cancelableTask);
89     }
90     BackgroundTaskExecutor::GetInstance().PostTask(cancelableTask);
91 }
92 
QueryImageObjectFromCache(const ImageSourceInfo & imageInfo,const RefPtr<PipelineContext> & pipelineContext)93 RefPtr<ImageObject> ImageProvider::QueryImageObjectFromCache(
94     const ImageSourceInfo& imageInfo, const RefPtr<PipelineContext>& pipelineContext)
95 {
96     auto imageCache = pipelineContext->GetImageCache();
97     if (!imageCache) {
98         return nullptr;
99     }
100     return imageCache->GetCacheImgObj(imageInfo.ToString());
101 }
102 
GeneraterAceImageObject(const ImageSourceInfo & imageInfo,const RefPtr<PipelineContext> context,bool useSkiaSvg)103 RefPtr<ImageObject> ImageProvider::GeneraterAceImageObject(
104     const ImageSourceInfo& imageInfo,
105     const RefPtr<PipelineContext> context,
106     bool useSkiaSvg)
107 {
108     auto imageData = LoadImageRawData(imageInfo, context);
109 
110     if (!imageData) {
111         LOGE("load image data failed. imageInfo: %{private}s", imageInfo.ToString().c_str());
112         return nullptr;
113     }
114 
115     return ImageObject::BuildImageObject(imageInfo, context, imageData, useSkiaSvg);
116 }
117 
LoadImageRawData(const ImageSourceInfo & imageInfo,const RefPtr<PipelineContext> context,const Size & targetSize)118 sk_sp<SkData> ImageProvider::LoadImageRawData(
119     const ImageSourceInfo& imageInfo,
120     const RefPtr<PipelineContext> context,
121     const Size& targetSize)
122 {
123     auto imageCache = context->GetImageCache();
124     if (imageCache) {
125         // 1. try get data from cache.
126         auto cacheData = imageCache->GetCacheImageData(imageInfo.GetSrc());
127         if (cacheData) {
128             LOGD("sk data from memory cache.");
129             return AceType::DynamicCast<SkiaCachedImageData>(cacheData)->imageData;
130         }
131         // 2 try get data from file cache.
132         if (targetSize.IsValid()) {
133             LOGD("size valid try load from cache.");
134             std::string cacheFilePath =
135                 ImageCache::GetImageCacheFilePath(ImageObject::GenerateCacheKey(imageInfo, targetSize));
136             LOGD("cache file path: %{private}s", cacheFilePath.c_str());
137             auto data = imageCache->GetDataFromCacheFile(cacheFilePath);
138             if (data) {
139                 LOGD("cache file found : %{public}s", cacheFilePath.c_str());
140                 return AceType::DynamicCast<SkiaCachedImageData>(data)->imageData;
141             }
142         } else {
143             LOGD("target size is not valid, load raw image file.");
144         }
145     }
146     // 3. try load raw image file.
147     auto imageLoader = ImageLoader::CreateImageLoader(imageInfo);
148     if (!imageLoader) {
149         LOGE("imageLoader create failed. imageInfo: %{private}s", imageInfo.ToString().c_str());
150         return nullptr;
151     }
152     auto data = imageLoader->LoadImageData(imageInfo, context);
153     if (data && imageCache) {
154         // cache sk data.
155         imageCache->CacheImageData(imageInfo.GetSrc(), AceType::MakeRefPtr<SkiaCachedImageData>(data));
156     }
157     return data;
158 }
159 
GetSVGImageDOMAsyncFromSrc(const std::string & src,std::function<void (const sk_sp<SkSVGDOM> &)> successCallback,std::function<void ()> failedCallback,const WeakPtr<PipelineContext> context,uint64_t svgThemeColor,OnPostBackgroundTask onBackgroundTaskPostCallback)160 void ImageProvider::GetSVGImageDOMAsyncFromSrc(
161     const std::string& src,
162     std::function<void(const sk_sp<SkSVGDOM>&)> successCallback,
163     std::function<void()> failedCallback,
164     const WeakPtr<PipelineContext> context,
165     uint64_t svgThemeColor,
166     OnPostBackgroundTask onBackgroundTaskPostCallback)
167 {
168     auto task = [src, successCallback, failedCallback, context, svgThemeColor, id = Container::CurrentId()] {
169         ContainerScope scope(id);
170         auto pipelineContext = context.Upgrade();
171         if (!pipelineContext) {
172             LOGW("render image or pipeline has been released. src: %{private}s", src.c_str());
173             return;
174         }
175         auto taskExecutor = pipelineContext->GetTaskExecutor();
176         if (!taskExecutor) {
177             return;
178         }
179         ImageSourceInfo info(src);
180         auto imageLoader = ImageLoader::CreateImageLoader(info);
181         if (!imageLoader) {
182             LOGE("load image failed when create image loader. src: %{private}s", src.c_str());
183             return;
184         }
185         auto imageData = imageLoader->LoadImageData(info, context);
186         if (imageData) {
187             const auto svgStream = std::make_unique<SkMemoryStream>(std::move(imageData));
188             if (svgStream) {
189                 auto skiaDom = SkSVGDOM::MakeFromStream(*svgStream, svgThemeColor);
190                 if (skiaDom) {
191                     taskExecutor->PostTask(
192                         [successCallback, skiaDom] { successCallback(skiaDom); }, TaskExecutor::TaskType::UI);
193                     return;
194                 }
195             }
196         }
197         LOGE("svg data wrong! src: %{private}s", src.c_str());
198         taskExecutor->PostTask([failedCallback] { failedCallback(); }, TaskExecutor::TaskType::UI);
199     };
200     CancelableTask cancelableTask(std::move(task));
201     if (onBackgroundTaskPostCallback) {
202         onBackgroundTaskPostCallback(cancelableTask);
203     }
204     BackgroundTaskExecutor::GetInstance().PostTask(cancelableTask);
205 }
206 
GetSVGImageDOMAsyncFromData(const sk_sp<SkData> & skData,std::function<void (const sk_sp<SkSVGDOM> &)> successCallback,std::function<void ()> failedCallback,const WeakPtr<PipelineContext> context,uint64_t svgThemeColor,OnPostBackgroundTask onBackgroundTaskPostCallback)207 void ImageProvider::GetSVGImageDOMAsyncFromData(
208     const sk_sp<SkData>& skData,
209     std::function<void(const sk_sp<SkSVGDOM>&)> successCallback,
210     std::function<void()> failedCallback,
211     const WeakPtr<PipelineContext> context,
212     uint64_t svgThemeColor,
213     OnPostBackgroundTask onBackgroundTaskPostCallback)
214 {
215     auto task = [skData, successCallback, failedCallback, context, svgThemeColor, id = Container::CurrentId()] {
216         ContainerScope scope(id);
217         auto pipelineContext = context.Upgrade();
218         if (!pipelineContext) {
219             LOGW("render image or pipeline has been released.");
220             return;
221         }
222         auto taskExecutor = pipelineContext->GetTaskExecutor();
223         if (!taskExecutor) {
224             return;
225         }
226 
227         const auto svgStream = std::make_unique<SkMemoryStream>(skData);
228         if (svgStream) {
229             auto skiaDom = SkSVGDOM::MakeFromStream(*svgStream, svgThemeColor);
230             if (skiaDom) {
231                 taskExecutor->PostTask(
232                     [successCallback, skiaDom] { successCallback(skiaDom); }, TaskExecutor::TaskType::UI);
233                 return;
234             }
235         }
236         LOGE("svg data wrong!");
237         taskExecutor->PostTask([failedCallback] { failedCallback(); }, TaskExecutor::TaskType::UI);
238     };
239     CancelableTask cancelableTask(std::move(task));
240     if (onBackgroundTaskPostCallback) {
241         onBackgroundTaskPostCallback(cancelableTask);
242     }
243     BackgroundTaskExecutor::GetInstance().PostTask(cancelableTask);
244 }
245 
UploadImageToGPUForRender(const sk_sp<SkImage> & image,const std::function<void (flutter::SkiaGPUObject<SkImage>)> && callback,const RefPtr<FlutterRenderTaskHolder> & renderTaskHolder)246 void ImageProvider::UploadImageToGPUForRender(
247     const sk_sp<SkImage>& image,
248     const std::function<void(flutter::SkiaGPUObject<SkImage>)>&& callback,
249     const RefPtr<FlutterRenderTaskHolder>& renderTaskHolder)
250 {
251     if (!renderTaskHolder) {
252         LOGW("renderTaskHolder has been released.");
253         return;
254     }
255 #if defined(DUMP_DRAW_CMD) || defined(GPU_DISABLED)
256     // If want to dump draw command or gpu disabled, should use CPU image.
257     callback({ image, renderTaskHolder->unrefQueue });
258 #else
259     // TODO: software render not upload to gpu
260 
261     auto rasterizedImage = image->makeRasterImage();
262     if (!rasterizedImage) {
263         LOGW("Rasterize image failed. callback.");
264         callback({ image, renderTaskHolder->unrefQueue });
265         return;
266     }
267     auto task = [rasterizedImage, callback, renderTaskHolder] () {
268         if (!renderTaskHolder) {
269             LOGW("renderTaskHolder has been released.");
270             return;
271         }
272         // weak reference of io manager must be check and used on io thread, because io manager is created on io thread.
273         if (!renderTaskHolder->ioManager) {
274             // Shell is closing.
275             callback({ rasterizedImage, renderTaskHolder->unrefQueue });
276             return;
277         }
278         ACE_DCHECK(!rasterizedImage->isTextureBacked());
279         auto resContext = renderTaskHolder->ioManager->GetResourceContext();
280         if (!resContext) {
281             callback({ rasterizedImage, renderTaskHolder->unrefQueue });
282             return;
283         }
284         SkPixmap pixmap;
285         if (!rasterizedImage->peekPixels(&pixmap)) {
286             LOGW("Could not peek pixels of image for texture upload.");
287             callback({ rasterizedImage, renderTaskHolder->unrefQueue });
288             return;
289         }
290         auto textureImage =
291             SkImage::MakeCrossContextFromPixmap(resContext.get(), pixmap, true, pixmap.colorSpace(), true);
292         callback({ textureImage ? textureImage : rasterizedImage, renderTaskHolder->unrefQueue });
293 
294         // Trigger purge cpu bitmap resource, after image upload to gpu.
295         SkGraphics::PurgeResourceCache();
296     };
297     renderTaskHolder->ioTaskRunner->PostTask(std::move(task));
298 #endif
299 }
300 
ResizeSkImage(const sk_sp<SkImage> & rawImage,const std::string & src,Size imageSize,bool forceResize)301 sk_sp<SkImage> ImageProvider::ResizeSkImage(
302     const sk_sp<SkImage>& rawImage,
303     const std::string& src,
304     Size imageSize,
305     bool forceResize)
306 {
307     if (!imageSize.IsValid()) {
308         LOGE("not valid size!, imageSize: %{private}s, src: %{private}s", imageSize.ToString().c_str(), src.c_str());
309         return rawImage;
310     }
311     int32_t dstWidth = static_cast<int32_t>(imageSize.Width() + 0.5);
312     int32_t dstHeight = static_cast<int32_t>(imageSize.Height() + 0.5);
313 
314     bool needResize = false;
315 
316     if (!forceResize) {
317         if (rawImage->width() > dstWidth) {
318             needResize = true;
319         } else {
320             dstWidth = rawImage->width();
321         }
322         if (rawImage->height() > dstHeight) {
323             needResize = true;
324         } else {
325             dstHeight = rawImage->height();
326         }
327     }
328 
329     if (!needResize && !forceResize) {
330         return rawImage;
331     }
332     return ApplySizeToSkImage(
333         rawImage,
334         dstWidth,
335         dstHeight,
336         ImageObject::GenerateCacheKey(ImageSourceInfo(src), imageSize));
337 }
338 
ApplySizeToSkImage(const sk_sp<SkImage> & rawImage,int32_t dstWidth,int32_t dstHeight,const std::string & srcKey)339 sk_sp<SkImage> ImageProvider::ApplySizeToSkImage(
340     const sk_sp<SkImage>& rawImage,
341     int32_t dstWidth,
342     int32_t dstHeight,
343     const std::string& srcKey)
344 {
345     auto scaledImageInfo =
346         SkImageInfo::Make(dstWidth, dstHeight, rawImage->colorType(), rawImage->alphaType(), rawImage->refColorSpace());
347     SkBitmap scaledBitmap;
348     if (!scaledBitmap.tryAllocPixels(scaledImageInfo)) {
349         LOGE("Could not allocate bitmap when attempting to scale. srcKey: %{private}s, destination size: [%{public}d x"
350             " %{public}d], raw image size: [%{public}d x %{public}d]",
351             srcKey.c_str(), dstWidth, dstHeight, rawImage->width(), rawImage->height());
352         return rawImage;
353     }
354     if (!rawImage->scalePixels(scaledBitmap.pixmap(), kLow_SkFilterQuality, SkImage::kDisallow_CachingHint)) {
355         LOGE("Could not scale pixels srcKey: %{private}s, destination size: [%{public}d x"
356             " %{public}d], raw image size: [%{public}d x %{public}d]",
357             srcKey.c_str(), dstWidth, dstHeight, rawImage->width(), rawImage->height());
358         return rawImage;
359     }
360     // Marking this as immutable makes the MakeFromBitmap call share the pixels instead of copying.
361     scaledBitmap.setImmutable();
362     auto scaledImage = SkImage::MakeFromBitmap(scaledBitmap);
363     if (scaledImage) {
364         bool needCacheResizedImageFile =
365             (1.0 * dstWidth * dstHeight) / (rawImage->width() * rawImage->height()) < RESIZE_MAX_PROPORTION;
366         if (needCacheResizedImageFile && !srcKey.empty()) {
367             BackgroundTaskExecutor::GetInstance().PostTask(
368                 [srcKey, scaledImage]() {
369                     LOGI("write png cache file: %{private}s", srcKey.c_str());
370                     auto data = scaledImage->encodeToData(SkEncodedImageFormat::kPNG, 100);
371                     if (!data) {
372                         LOGI("encode cache image into cache file failed.");
373                         return;
374                     }
375                     ImageCache::WriteCacheFile(srcKey, data->data(), data->size());
376                 },
377                 BgTaskPriority::LOW);
378         }
379         return scaledImage;
380     }
381     LOGE("Could not create a scaled image from a scaled bitmap. srcKey: %{private}s, destination size: [%{public}d x"
382         " %{public}d], raw image size: [%{public}d x %{public}d]",
383         srcKey.c_str(), dstWidth, dstHeight, rawImage->width(), rawImage->height());
384     return rawImage;
385 }
386 
GetSkImage(const std::string & src,const WeakPtr<PipelineContext> context,Size targetSize)387 sk_sp<SkImage> ImageProvider::GetSkImage(
388     const std::string& src,
389     const WeakPtr<PipelineContext> context,
390     Size targetSize)
391 {
392     ImageSourceInfo info(src);
393     auto imageLoader = ImageLoader::CreateImageLoader(info);
394     if (!imageLoader) {
395         LOGE("Invalid src, src is %{public}s", src.c_str());
396         return nullptr;
397     }
398     auto imageSkData = imageLoader->LoadImageData(info, context);
399     if (!imageSkData) {
400         LOGE("fetch data failed. src: %{private}s", src.c_str());
401         return nullptr;
402     }
403     auto rawImage = SkImage::MakeFromEncoded(imageSkData);
404     if (!rawImage) {
405         LOGE("MakeFromEncoded failed! src: %{private}s", src.c_str());
406         return nullptr;
407     }
408     auto image = ResizeSkImage(rawImage, src, targetSize);
409     return image;
410 }
411 
TryLoadImageInfo(const RefPtr<PipelineContext> & context,const std::string & src,std::function<void (bool,int32_t,int32_t)> && loadCallback)412 void ImageProvider::TryLoadImageInfo(const RefPtr<PipelineContext>& context, const std::string& src,
413     std::function<void(bool, int32_t, int32_t)>&& loadCallback)
414 {
415     BackgroundTaskExecutor::GetInstance().PostTask(
416         [src, callback = std::move(loadCallback), context, id = Container::CurrentId()]() {
417             ContainerScope scope(id);
418             auto taskExecutor = context->GetTaskExecutor();
419             if (!taskExecutor) {
420                 return;
421             }
422             auto image = ImageProvider::GetSkImage(src, context);
423             if (image) {
424                 callback(true, image->width(), image->height());
425                 return;
426             }
427             callback(false, 0, 0);
428         });
429 }
430 
IsWideGamut(const sk_sp<SkColorSpace> & colorSpace)431 bool ImageProvider::IsWideGamut(const sk_sp<SkColorSpace>& colorSpace)
432 {
433     skcms_ICCProfile encodedProfile;
434     colorSpace->toProfile(&encodedProfile);
435     if (!encodedProfile.has_toXYZD50) {
436         LOGI("This profile's gamut can not be represented by a 3x3 transform to XYZD50");
437         return false;
438     }
439     // Normalize gamut by 1.
440     // rgb[3] represents the point of Red, Green and Blue coordinate in color space diagram.
441     Point rgb[3];
442     auto xyzGamut = encodedProfile.toXYZD50;
443     for (int32_t i = 0; i < 3; i++) {
444         auto sum = xyzGamut.vals[i][0] + xyzGamut.vals[i][1] + xyzGamut.vals[i][2];
445         rgb[i].SetX(xyzGamut.vals[i][0] / sum);
446         rgb[i].SetY(xyzGamut.vals[i][1] / sum);
447     }
448     // Calculate the area enclosed by the coordinates of the three RGB points
449     Point red = rgb[0];
450     Point green = rgb[1];
451     Point blue = rgb[2];
452     // Assuming there is a triangle enclosed by three points: A(x1, y1), B(x2, y2), C(x3, y3),
453     // the formula for calculating the area of triangle ABC is as follows:
454     // S = (x1 * y2 + x2 * y3 + x3 * y1 - x1 * y3 - x2 * y1 - x3 * y2) / 2.0
455     auto areaOfPoint = std::fabs(red.GetX() * green.GetY() + green.GetX() * blue.GetY() + blue.GetX() * green.GetY() -
456         red.GetX() * blue.GetY() - blue.GetX() * green.GetY() - green.GetX() * red.GetY()) / 2.0;
457     return GreatNotEqual(areaOfPoint, SRGB_GAMUT_AREA);
458 }
459 
MakeSkImageInfoFromPixelMap(const RefPtr<PixelMap> & pixmap)460 SkImageInfo ImageProvider::MakeSkImageInfoFromPixelMap(const RefPtr<PixelMap>& pixmap)
461 {
462     SkColorType ct = PixelFormatToSkColorType(pixmap);
463     SkAlphaType at = AlphaTypeToSkAlphaType(pixmap);
464     sk_sp<SkColorSpace> cs = ColorSpaceToSkColorSpace(pixmap);
465     return SkImageInfo::Make(pixmap->GetWidth(), pixmap->GetHeight(), ct, at, cs);
466 }
467 
ColorSpaceToSkColorSpace(const RefPtr<PixelMap> & pixmap)468 sk_sp<SkColorSpace> ImageProvider::ColorSpaceToSkColorSpace(const RefPtr<PixelMap>& pixmap)
469 {
470     return SkColorSpace::MakeSRGB(); // Media::PixelMap has not support wide gamut yet.
471 }
472 
AlphaTypeToSkAlphaType(const RefPtr<PixelMap> & pixmap)473 SkAlphaType ImageProvider::AlphaTypeToSkAlphaType(const RefPtr<PixelMap>& pixmap)
474 {
475     switch (pixmap->GetAlphaType()) {
476         case AlphaType::IMAGE_ALPHA_TYPE_UNKNOWN:
477             return SkAlphaType::kUnknown_SkAlphaType;
478         case AlphaType::IMAGE_ALPHA_TYPE_OPAQUE:
479             return SkAlphaType::kOpaque_SkAlphaType;
480         case AlphaType::IMAGE_ALPHA_TYPE_PREMUL:
481             return SkAlphaType::kPremul_SkAlphaType;
482         case AlphaType::IMAGE_ALPHA_TYPE_UNPREMUL:
483             return SkAlphaType::kUnpremul_SkAlphaType;
484         default:
485             return SkAlphaType::kUnknown_SkAlphaType;
486     }
487 }
488 
PixelFormatToSkColorType(const RefPtr<PixelMap> & pixmap)489 SkColorType ImageProvider::PixelFormatToSkColorType(const RefPtr<PixelMap>& pixmap)
490 {
491     switch (pixmap->GetPixelFormat()) {
492         case PixelFormat::RGB_565:
493             return SkColorType::kRGB_565_SkColorType;
494         case PixelFormat::RGBA_8888:
495             return SkColorType::kRGBA_8888_SkColorType;
496         case PixelFormat::BGRA_8888:
497             return SkColorType::kBGRA_8888_SkColorType;
498         case PixelFormat::ALPHA_8:
499             return SkColorType::kAlpha_8_SkColorType;
500         case PixelFormat::RGBA_F16:
501             return SkColorType::kRGBA_F16_SkColorType;
502         case PixelFormat::UNKNOWN:
503         case PixelFormat::ARGB_8888:
504         case PixelFormat::RGB_888:
505         case PixelFormat::NV21:
506         case PixelFormat::NV12:
507         case PixelFormat::CMYK:
508         default:
509             return SkColorType::kUnknown_SkColorType;
510     }
511 }
512 
513 } // namespace OHOS::Ace
514