1 /*
2  * Copyright (c) 2021-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 "skia_image.h"
17 
18 #include "src/core/SkAutoMalloc.h"
19 #include "src/core/SkReadBuffer.h"
20 #include "src/core/SkWriteBuffer.h"
21 #include "src/image/SkImage_Base.h"
22 
23 #include "draw/surface.h"
24 #include "image/bitmap.h"
25 #include "image/image.h"
26 #include "image/picture.h"
27 #include "utils/data.h"
28 #include "utils/log.h"
29 #include "utils/system_properties.h"
30 
31 #include "skia_bitmap.h"
32 #include "skia_data.h"
33 #include "skia_image_info.h"
34 #include "skia_pixmap.h"
35 #include "skia_surface.h"
36 #include "skia_texture_info.h"
37 
38 #ifdef RS_ENABLE_GPU
39 #include "include/core/SkYUVAPixmaps.h"
40 #include "skia_gpu_context.h"
41 #endif
42 
43 namespace OHOS {
44 namespace Rosen {
45 namespace Drawing {
SkiaImage()46 SkiaImage::SkiaImage() noexcept : skiaImage_(nullptr) {}
47 
SkiaImage(sk_sp<SkImage> skImg)48 SkiaImage::SkiaImage(sk_sp<SkImage> skImg) noexcept
49 {
50     PostSkImgToTargetThread();
51     skiaImage_ = skImg;
52 }
53 
~SkiaImage()54 SkiaImage::~SkiaImage()
55 {
56     PostSkImgToTargetThread();
57 }
58 
PostSkImgToTargetThread()59 void SkiaImage::PostSkImgToTargetThread()
60 {
61     if (skiaImage_ == nullptr) {
62         return;
63     }
64     auto context = as_IB(skiaImage_.get())->directContext();
65     auto func = SkiaGPUContext::GetPostFunc(sk_ref_sp(context));
66     if (func) {
67         func([image = std::move(skiaImage_)]() {});
68     }
69 }
70 
MakeFromRaster(const Pixmap & pixmap,RasterReleaseProc rasterReleaseProc,ReleaseContext releaseContext)71 std::shared_ptr<Image> SkiaImage::MakeFromRaster(const Pixmap& pixmap,
72     RasterReleaseProc rasterReleaseProc, ReleaseContext releaseContext)
73 {
74     auto& skPixmap = pixmap.GetImpl<SkiaPixmap>()->ExportSkiaPixmap();
75     sk_sp<SkImage> skImage = SkImage::MakeFromRaster(skPixmap, rasterReleaseProc, releaseContext);
76     if (skImage == nullptr) {
77         LOGD("SkiaImage::MakeFromRaster failed");
78         return nullptr;
79     }
80     std::shared_ptr<ImageImpl> imageImpl = std::make_shared<SkiaImage>(skImage);
81     return std::make_shared<Image>(imageImpl);
82 }
83 
MakeRasterData(const ImageInfo & info,std::shared_ptr<Data> pixels,size_t rowBytes)84 std::shared_ptr<Image> SkiaImage::MakeRasterData(const ImageInfo& info, std::shared_ptr<Data> pixels,
85     size_t rowBytes)
86 {
87     if (pixels == nullptr) {
88         LOGD("SkiaImage::MakeRasterData pixels is nullptr");
89         return nullptr;
90     }
91     SkImageInfo skImageInfo = SkiaImageInfo::ConvertToSkImageInfo(info);
92     auto skData = pixels->GetImpl<SkiaData>()->GetSkData();
93 
94     sk_sp<SkImage> skImage = SkImage::MakeRasterData(skImageInfo, skData, rowBytes);
95     if (skImage == nullptr) {
96         LOGD("skImage nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
97         return nullptr;
98     }
99     std::shared_ptr<ImageImpl> imageImpl = std::make_shared<SkiaImage>(skImage);
100     return std::make_shared<Image>(imageImpl);
101 }
102 
BuildFromBitmap(const Bitmap & bitmap)103 bool SkiaImage::BuildFromBitmap(const Bitmap& bitmap)
104 {
105     auto skBitmapImpl = bitmap.GetImpl<SkiaBitmap>();
106     if (skBitmapImpl != nullptr) {
107         const SkBitmap skBitmap = skBitmapImpl->ExportSkiaBitmap();
108         PostSkImgToTargetThread();
109         skiaImage_ = SkImage::MakeFromBitmap(skBitmap);
110         return skiaImage_ != nullptr;
111     }
112     return false;
113 }
114 
115 #ifdef RS_ENABLE_GPU
MakeFromYUVAPixmaps(GPUContext & gpuContext,const YUVInfo & info,void * memory)116 std::shared_ptr<Image> SkiaImage::MakeFromYUVAPixmaps(GPUContext& gpuContext, const YUVInfo& info, void* memory)
117 {
118     if (!memory) {
119         LOGD("memory nullprt, %{public}s, %{public}d",  __FUNCTION__, __LINE__);
120         return nullptr;
121     }
122 
123     auto grContext = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
124     if (grContext == nullptr) {
125         LOGD("grContext nullprt, %{public}s, %{public}d",  __FUNCTION__, __LINE__);
126         return nullptr;
127     }
128     SkYUVAPixmapInfo pixmapInfo({{info.GetWidth(), info.GetHeight()},
129                                  SkiaYUVInfo::ConvertToSkPlaneConfig(info.GetConfig()),
130                                  SkiaYUVInfo::ConvertToSkSubSampling(info.GetSampling()),
131                                  SkiaYUVInfo::ConvertToSkYUVColorSpace(info.GetColorSpace())},
132                                  SkYUVAPixmapInfo::DataType::kUnorm8,
133                                  nullptr);
134     auto skYUVAPixmaps = SkYUVAPixmaps::FromExternalMemory(pixmapInfo, memory);
135     auto skImage = SkImage::MakeFromYUVAPixmaps(grContext.get(), skYUVAPixmaps);
136     if (skImage == nullptr) {
137         LOGD("skImage nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
138         return nullptr;
139     }
140     std::shared_ptr<ImageImpl> imageImpl = std::make_shared<SkiaImage>(skImage);
141     return std::make_shared<Image>(imageImpl);
142 }
143 
BuildFromBitmap(GPUContext & gpuContext,const Bitmap & bitmap)144 bool SkiaImage::BuildFromBitmap(GPUContext& gpuContext, const Bitmap& bitmap)
145 {
146     grContext_ = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
147     auto& skBitmap = bitmap.GetImpl<SkiaBitmap>()->ExportSkiaBitmap();
148     PostSkImgToTargetThread();
149     skiaImage_ = SkImage::MakeCrossContextFromPixmap(grContext_.get(), skBitmap.pixmap(), false);
150 
151     return (skiaImage_ != nullptr) ? true : false;
152 }
153 
MakeFromEncoded(const std::shared_ptr<Data> & data)154 bool SkiaImage::MakeFromEncoded(const std::shared_ptr<Data>& data)
155 {
156     if (data == nullptr) {
157         LOGD("SkiaImage::MakeFromEncoded failed, data is invalid");
158         return false;
159     }
160 
161     auto skData = data->GetImpl<SkiaData>()->GetSkData();
162     PostSkImgToTargetThread();
163     skiaImage_ = SkImage::MakeFromEncoded(skData);
164     return (skiaImage_ != nullptr);
165 }
166 
BuildSubset(const std::shared_ptr<Image> image,const RectI & rect,GPUContext & gpuContext)167 bool SkiaImage::BuildSubset(const std::shared_ptr<Image> image, const RectI& rect, GPUContext& gpuContext)
168 {
169     if (image == nullptr) {
170         LOGD("SkiaImage::BuildSubset failed, origin Image is invalid");
171         return false;
172     }
173     auto imageImpl = image->GetImpl<SkiaImage>();
174     if (imageImpl == nullptr) {
175         LOGD("SkiaImage::BuildSubset failed, GetImpl failed");
176         return false;
177     }
178     auto skiaImage = imageImpl->GetImage();
179     if (skiaImage == nullptr) {
180         LOGD("SkiaImage::BuildSubset failed, GetImage failed");
181         return false;
182     }
183     auto skiaRect = SkIRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
184     grContext_ = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
185     PostSkImgToTargetThread();
186     skiaImage_ = skiaImage->makeSubset(skiaRect, grContext_.get());
187     return (skiaImage_ != nullptr) ? true : false;
188 }
189 
BuildFromCompressed(GPUContext & gpuContext,const std::shared_ptr<Data> & data,int width,int height,CompressedType type,const std::shared_ptr<ColorSpace> & colorSpace)190 bool SkiaImage::BuildFromCompressed(GPUContext& gpuContext, const std::shared_ptr<Data>& data, int width, int height,
191     CompressedType type, const std::shared_ptr<ColorSpace>& colorSpace)
192 {
193     if (data == nullptr) {
194         LOGD("SkiaImage::BuildFromCompressed, build failed, data is invalid");
195         return false;
196     }
197     grContext_ = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
198     auto skData = data->GetImpl<SkiaData>()->GetSkData();
199     PostSkImgToTargetThread();
200     sk_sp<SkColorSpace> skColorSpace = nullptr;
201     if (colorSpace != nullptr) {
202         auto colorSpaceImpl = colorSpace->GetImpl<SkiaColorSpace>();
203         skColorSpace = colorSpaceImpl ? colorSpaceImpl->GetColorSpace() : SkColorSpace::MakeSRGB();
204     }
205     skiaImage_ = SkImage::MakeTextureFromCompressed(grContext_.get(),
206         skData, width, height, static_cast<SkImage::CompressionType>(type),
207         GrMipmapped::kNo, GrProtected::kNo, skColorSpace);
208     return (skiaImage_ != nullptr) ? true : false;
209 }
210 
DeleteCleanupHelper(void (* deleteFunc)(void *),void * cleanupHelper)211 void SkiaImage::DeleteCleanupHelper(void (*deleteFunc)(void*), void* cleanupHelper)
212 {
213     if (deleteFunc == nullptr || cleanupHelper == nullptr) {
214         return;
215     }
216 
217     (*deleteFunc)(cleanupHelper);
218 }
219 
BuildFromTexture(GPUContext & gpuContext,const TextureInfo & info,TextureOrigin origin,BitmapFormat bitmapFormat,const std::shared_ptr<ColorSpace> & colorSpace,void (* deleteFunc)(void *),void * cleanupHelper)220 bool SkiaImage::BuildFromTexture(GPUContext& gpuContext, const TextureInfo& info, TextureOrigin origin,
221     BitmapFormat bitmapFormat, const std::shared_ptr<ColorSpace>& colorSpace,
222     void (*deleteFunc)(void*), void* cleanupHelper)
223 {
224     grContext_ = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
225     if (!grContext_) {
226         LOGD("SkiaImage BuildFromTexture grContext_ is null");
227         DeleteCleanupHelper(deleteFunc, cleanupHelper);
228         return false;
229     }
230 
231     sk_sp<SkColorSpace> skColorSpace = nullptr;
232     if (colorSpace != nullptr) {
233         auto colorSpaceImpl = colorSpace->GetImpl<SkiaColorSpace>();
234         skColorSpace = colorSpaceImpl ? colorSpaceImpl->GetColorSpace() : SkColorSpace::MakeSRGB();
235     } else {
236         skColorSpace = SkColorSpace::MakeSRGB();
237     }
238 
239 #ifdef RS_ENABLE_VK
240     if (SystemProperties::IsUseVulkan()) {
241         const auto& backendTexture = SkiaTextureInfo::ConvertToGrBackendTexture(info);
242         if (!backendTexture.isValid()) {
243             LOGE("SkiaImage BuildFromTexture backend texture is not valid!!!!");
244             DeleteCleanupHelper(deleteFunc, cleanupHelper);
245             return false;
246         }
247         PostSkImgToTargetThread();
248         skiaImage_ = SkImage::MakeFromTexture(grContext_.get(), backendTexture,
249             SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin),
250             SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
251             SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace, deleteFunc, cleanupHelper);
252     } else {
253         PostSkImgToTargetThread();
254         skiaImage_ = SkImage::MakeFromTexture(grContext_.get(),
255             SkiaTextureInfo::ConvertToGrBackendTexture(info),
256             SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin),
257             SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
258             SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace);
259     }
260 #else
261     PostSkImgToTargetThread();
262     skiaImage_ = SkImage::MakeFromTexture(grContext_.get(),  SkiaTextureInfo::ConvertToGrBackendTexture(info),
263         SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin), SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
264         SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace);
265 #endif
266     if (skiaImage_ == nullptr) {
267         LOGE("SkiaImage::MakeFromTexture skiaImage_ is nullptr!!!! "
268             "TextureInfo format:%{public}u, w:%{public}d, h:%{public}d , bitmapFormat.colorType is %{public}d",
269             info.GetFormat(), info.GetWidth(), info.GetHeight(), static_cast<int>(bitmapFormat.colorType));
270         return false;
271     }
272     return true;
273 }
274 
BuildFromSurface(GPUContext & gpuContext,Surface & surface,TextureOrigin origin,BitmapFormat bitmapFormat,const std::shared_ptr<ColorSpace> & colorSpace)275 bool SkiaImage::BuildFromSurface(GPUContext& gpuContext, Surface& surface, TextureOrigin origin,
276     BitmapFormat bitmapFormat, const std::shared_ptr<ColorSpace>& colorSpace)
277 {
278     auto skSurface = surface.GetImpl<SkiaSurface>()->GetSkSurface();
279     if (!skSurface) {
280         LOGD("SkiaImage::BuildFromSurface skSurface is null");
281         return false;
282     }
283 
284     GrBackendTexture grBackendTexture
285             = skSurface->getBackendTexture(SkSurface::BackendHandleAccess::kFlushRead_BackendHandleAccess);
286     if (!grBackendTexture.isValid()) {
287         LOGD("SkiaImage::BuildFromSurface grBackendTexture is invalid");
288         return false;
289     }
290     grContext_ = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
291 
292     sk_sp<SkColorSpace> skColorSpace = nullptr;
293     if (colorSpace != nullptr) {
294         auto colorSpaceImpl = colorSpace->GetImpl<SkiaColorSpace>();
295         skColorSpace = colorSpaceImpl ? colorSpaceImpl->GetColorSpace() : nullptr;
296     }
297     PostSkImgToTargetThread();
298     skiaImage_ = SkImage::MakeFromTexture(grContext_.get(), grBackendTexture,
299         SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin), SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
300         SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace);
301     return (skiaImage_ != nullptr) ? true : false;
302 }
303 
SetGrBackendTexture(const GrBackendTexture & grBackendTexture)304 void SkiaImage::SetGrBackendTexture(const GrBackendTexture& grBackendTexture)
305 {
306     grBackendTexture_ = grBackendTexture;
307 }
308 
GetBackendTexture(bool flushPendingGrContextIO,TextureOrigin * origin)309 BackendTexture SkiaImage::GetBackendTexture(bool flushPendingGrContextIO, TextureOrigin* origin)
310 {
311     if (skiaImage_ == nullptr) {
312         LOGD("SkiaImage::GetBackendTexture, SkImage is nullptr!");
313         return BackendTexture(false); // invalid
314     }
315     GrBackendTexture skBackendTexture;
316     if (origin == nullptr) {
317         skBackendTexture =
318             skiaImage_->getBackendTexture(flushPendingGrContextIO);
319     } else {
320         GrSurfaceOrigin grOrigin = SkiaTextureInfo::ConvertToGrSurfaceOrigin(*origin);
321         skBackendTexture =
322             skiaImage_->getBackendTexture(flushPendingGrContextIO, &grOrigin);
323     }
324     if (!skBackendTexture.isValid()) {
325         LOGD("SkiaImage::GetBackendTexture, skBackendTexture is nullptr!");
326         return BackendTexture(false); // invalid
327     }
328     auto backendTexture = BackendTexture(true);
329     SetGrBackendTexture(skBackendTexture);
330 #ifdef RS_ENABLE_VK
331     if (SystemProperties::IsUseVulkan()) {
332         TextureInfo info;
333         SkiaTextureInfo::ConvertToVKTexture(skBackendTexture, info);
334         backendTexture.SetTextureInfo(info);
335     } else {
336         backendTexture.SetTextureInfo(SkiaTextureInfo::ConvertToTextureInfo(skBackendTexture));
337     }
338 #else
339     backendTexture.SetTextureInfo(SkiaTextureInfo::ConvertToTextureInfo(skBackendTexture));
340 #endif
341     return backendTexture;
342 }
343 
IsValid(GPUContext * context) const344 bool SkiaImage::IsValid(GPUContext* context) const
345 {
346     if (skiaImage_ == nullptr) {
347         LOGD("SkiaImage::IsValid, skiaImage_ is nullptr!");
348         return false;
349     }
350     if (context == nullptr) {
351         return skiaImage_->isValid(nullptr);
352     }
353     return skiaImage_->isValid(context->GetImpl<SkiaGPUContext>()->GetGrContext().get());
354 }
355 #endif
356 
AsLegacyBitmap(Bitmap & bitmap) const357 bool SkiaImage::AsLegacyBitmap(Bitmap& bitmap) const
358 {
359     if (skiaImage_ == nullptr) {
360         LOGD("SkiaImage::IsValid, skiaImage_ is nullptr!");
361         return false;
362     }
363     SkBitmap newBitmap;
364     if (!skiaImage_->asLegacyBitmap(&newBitmap)) {
365         LOGD("SkiaImage::AsLegacyBitmap failed!");
366         return false;
367     }
368     bitmap.GetImpl<SkiaBitmap>()->SetSkBitmap(newBitmap);
369     return true;
370 }
371 
GetWidth() const372 int SkiaImage::GetWidth() const
373 {
374     return (skiaImage_ == nullptr) ? 0 : skiaImage_->width();
375 }
376 
GetHeight() const377 int SkiaImage::GetHeight() const
378 {
379     return (skiaImage_ == nullptr) ? 0 : skiaImage_->height();
380 }
381 
GetColorType() const382 ColorType SkiaImage::GetColorType() const
383 {
384     return (skiaImage_ == nullptr) ? ColorType::COLORTYPE_UNKNOWN :
385                                      SkiaImageInfo::ConvertToColorType(skiaImage_->colorType());
386 }
387 
GetAlphaType() const388 AlphaType SkiaImage::GetAlphaType() const
389 {
390     return (skiaImage_ == nullptr) ? AlphaType::ALPHATYPE_UNKNOWN :
391                                      SkiaImageInfo::ConvertToAlphaType(skiaImage_->alphaType());
392 }
393 
GetColorSpace() const394 std::shared_ptr<ColorSpace> SkiaImage::GetColorSpace() const
395 {
396     if (skiaImage_ == nullptr) {
397         return nullptr;
398     }
399     sk_sp<SkColorSpace> skColorSpace = skiaImage_->refColorSpace();
400     if (skColorSpace == nullptr) {
401         return nullptr;
402     }
403     std::shared_ptr<ColorSpace> colorSpace = std::make_shared<ColorSpace>();
404     colorSpace->GetImpl<SkiaColorSpace>()->SetColorSpace(skColorSpace);
405     return colorSpace;
406 }
407 
GetUniqueID() const408 uint32_t SkiaImage::GetUniqueID() const
409 {
410     return (skiaImage_ == nullptr) ? 0 : skiaImage_->uniqueID();
411 }
412 
GetImageInfo()413 ImageInfo SkiaImage::GetImageInfo()
414 {
415     if (skiaImage_ == nullptr) {
416         return {};
417     }
418     return SkiaImageInfo::ConvertToRSImageInfo(skiaImage_->imageInfo());
419 }
420 
ReadPixels(Bitmap & bitmap,int x,int y)421 bool SkiaImage::ReadPixels(Bitmap& bitmap, int x, int y)
422 {
423     const auto& skBitmap = bitmap.GetImpl<SkiaBitmap>()->ExportSkiaBitmap();
424     const auto& skPixmap = skBitmap.pixmap();
425 
426     return (skiaImage_ == nullptr) ? false : skiaImage_->readPixels(skPixmap, x, y);
427 }
428 
ReadPixels(Pixmap & pixmap,int x,int y)429 bool SkiaImage::ReadPixels(Pixmap& pixmap, int x, int y)
430 {
431     auto& skPixmap = pixmap.GetImpl<SkiaPixmap>()->ExportSkiaPixmap();
432     return (skiaImage_ == nullptr) ? false : skiaImage_->readPixels(skPixmap, x, y);
433 }
434 
ReadPixels(const ImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int32_t srcX,int32_t srcY) const435 bool SkiaImage::ReadPixels(const ImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
436     int32_t srcX, int32_t srcY) const
437 {
438     SkImageInfo skImageInfo = SkiaImageInfo::ConvertToSkImageInfo(dstInfo);
439     return (skiaImage_ == nullptr) ? false : skiaImage_->readPixels(skImageInfo, dstPixels, dstRowBytes, srcX, srcY);
440 }
441 
IsTextureBacked() const442 bool SkiaImage::IsTextureBacked() const
443 {
444     return (skiaImage_ == nullptr) ? false : skiaImage_->isTextureBacked();
445 }
446 
ScalePixels(const Bitmap & bitmap,const SamplingOptions & sampling,bool allowCachingHint) const447 bool SkiaImage::ScalePixels(const Bitmap& bitmap, const SamplingOptions& sampling, bool allowCachingHint) const
448 {
449     const auto& skBitmap = bitmap.GetImpl<SkiaBitmap>()->ExportSkiaBitmap();
450     const auto& skPixmap = skBitmap.pixmap();
451 
452     SkSamplingOptions samplingOptions;
453     if (sampling.GetUseCubic()) {
454         samplingOptions = SkSamplingOptions({ sampling.GetCubicCoffB(), sampling.GetCubicCoffC() });
455     } else {
456         samplingOptions = SkSamplingOptions(static_cast<SkFilterMode>(sampling.GetFilterMode()),
457             static_cast<SkMipmapMode>(sampling.GetMipmapMode()));
458     }
459 
460     SkImage::CachingHint skCachingHint;
461     if (allowCachingHint) {
462         skCachingHint = SkImage::CachingHint::kAllow_CachingHint;
463     } else {
464         skCachingHint = SkImage::CachingHint::kDisallow_CachingHint;
465     }
466 
467     return (skiaImage_ == nullptr) ? false : skiaImage_->scalePixels(skPixmap, samplingOptions, skCachingHint);
468 }
469 
EncodeToData(EncodedImageFormat encodedImageFormat,int quality) const470 std::shared_ptr<Data> SkiaImage::EncodeToData(EncodedImageFormat encodedImageFormat, int quality) const
471 {
472     if (skiaImage_ == nullptr) {
473         LOGD("SkiaImage::EncodeToData, skiaImage_ is null!");
474         return nullptr;
475     }
476     SkEncodedImageFormat skEncodedImageFormat = SkiaImageInfo::ConvertToSkEncodedImageFormat(encodedImageFormat);
477     auto skData = skiaImage_->encodeToData(skEncodedImageFormat, quality);
478     if (skData == nullptr) {
479         LOGD("SkiaImage::EncodeToData, skData null!");
480         return nullptr;
481     }
482     std::shared_ptr<Data> data = std::make_shared<Data>();
483     data->GetImpl<SkiaData>()->SetSkData(skData);
484     return data;
485 }
486 
IsLazyGenerated() const487 bool SkiaImage::IsLazyGenerated() const
488 {
489     return (skiaImage_ == nullptr) ? false : skiaImage_->isLazyGenerated();
490 }
491 
GetROPixels(Bitmap & bitmap) const492 bool SkiaImage::GetROPixels(Bitmap& bitmap) const
493 {
494     if (skiaImage_ == nullptr) {
495         LOGD("SkiaImage::GetROPixels, skiaImage_ is null!");
496         return false;
497     }
498     auto context = as_IB(skiaImage_.get())->directContext();
499     if (!as_IB(skiaImage_.get())->getROPixels(context, &bitmap.GetImpl<SkiaBitmap>()->GetSkBitmap())) {
500         LOGD("skiaImge getROPixels failed");
501         return false;
502     }
503     return true;
504 }
505 
MakeRasterImage() const506 std::shared_ptr<Image> SkiaImage::MakeRasterImage() const
507 {
508     if (skiaImage_ == nullptr) {
509         return nullptr;
510     }
511     sk_sp<SkImage> skImage = skiaImage_->makeRasterImage();
512     if (skImage == nullptr) {
513         LOGD("skImage nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
514         return nullptr;
515     }
516     std::shared_ptr<ImageImpl> imageImpl = std::make_shared<SkiaImage>(skImage);
517     return std::make_shared<Image>(imageImpl);
518 }
519 
CanPeekPixels() const520 bool SkiaImage::CanPeekPixels() const
521 {
522     SkPixmap pixmap;
523     if (skiaImage_ == nullptr || !skiaImage_->peekPixels(&pixmap)) {
524         return false;
525     }
526     return true;
527 }
528 
IsOpaque() const529 bool SkiaImage::IsOpaque() const
530 {
531     return (skiaImage_ == nullptr) ? false : skiaImage_->isOpaque();
532 }
533 
HintCacheGpuResource() const534 void SkiaImage::HintCacheGpuResource() const
535 {
536     as_IB(skiaImage_.get())->hintCacheGpuResource();
537 }
538 
GetImage() const539 const sk_sp<SkImage> SkiaImage::GetImage() const
540 {
541     return skiaImage_;
542 }
543 
SetSkImage(const sk_sp<SkImage> & skImage)544 void SkiaImage::SetSkImage(const sk_sp<SkImage>& skImage)
545 {
546     PostSkImgToTargetThread();
547     skiaImage_ = skImage;
548 }
549 
550 #ifdef RS_ENABLE_GPU
GetGrContext() const551 sk_sp<GrDirectContext> SkiaImage::GetGrContext() const
552 {
553     return grContext_;
554 }
555 #endif
556 
Serialize() const557 std::shared_ptr<Data> SkiaImage::Serialize() const
558 {
559     if (skiaImage_ == nullptr) {
560         LOGD("SkiaImage::Serialize, SkImage is nullptr!");
561         return nullptr;
562     }
563 
564     SkBinaryWriteBuffer writer;
565     bool type = skiaImage_->isLazyGenerated();
566     writer.writeBool(type);
567     if (type) {
568         writer.writeImage(skiaImage_.get());
569         size_t length = writer.bytesWritten();
570         std::shared_ptr<Data> data = std::make_shared<Data>();
571         data->BuildUninitialized(length);
572         writer.writeToMemory(data->WritableData());
573         return data;
574     } else {
575         SkBitmap bitmap;
576 
577         auto context = as_IB(skiaImage_.get())->directContext();
578         if (!as_IB(skiaImage_.get())->getROPixels(context, &bitmap)) {
579             LOGD("SkiaImage::SerializeNoLazyImage SkImage getROPixels failed");
580             return nullptr;
581         }
582         SkPixmap pixmap;
583         if (!bitmap.peekPixels(&pixmap)) {
584             LOGD("SkiaImage::SerializeNoLazyImage SkImage peekPixels failed");
585             return nullptr;
586         }
587         size_t rb = pixmap.rowBytes();
588         int32_t width = pixmap.width();
589         int32_t height = pixmap.height();
590         const void* addr = pixmap.addr();
591         size_t size = pixmap.computeByteSize();
592 
593         writer.writeUInt(size);
594         writer.writeByteArray(addr, size);
595         writer.writeUInt(rb);
596         writer.write32(width);
597         writer.write32(height);
598 
599         writer.writeUInt(pixmap.colorType());
600         writer.writeUInt(pixmap.alphaType());
601 
602         if (pixmap.colorSpace() == nullptr) {
603             writer.writeUInt(0);
604         } else {
605             auto data = pixmap.colorSpace()->serialize();
606             writer.writeUInt(data->size());
607             writer.writeByteArray(data->data(), data->size());
608         }
609         size_t length = writer.bytesWritten();
610         std::shared_ptr<Data> data = std::make_shared<Data>();
611         data->BuildUninitialized(length);
612         writer.writeToMemory(data->WritableData());
613         return data;
614     }
615 }
616 
Deserialize(std::shared_ptr<Data> data)617 bool SkiaImage::Deserialize(std::shared_ptr<Data> data)
618 {
619     if (data == nullptr) {
620         LOGD("SkiaImage::Deserialize, data is invalid!");
621         return false;
622     }
623 
624     SkReadBuffer reader(data->GetData(), data->GetSize());
625     bool type = reader.readBool();
626     if (type) {
627         PostSkImgToTargetThread();
628         skiaImage_ = reader.readImage();
629         return skiaImage_ != nullptr;
630     } else {
631         size_t pixmapSize = reader.readUInt();
632         SkAutoMalloc pixBuffer(pixmapSize);
633         if (!reader.readByteArray(pixBuffer.get(), pixmapSize)) {
634             return false;
635         }
636 
637         size_t rb = reader.readUInt();
638         int32_t width = reader.read32();
639         int32_t height = reader.read32();
640 
641         SkColorType colorType = static_cast<SkColorType>(reader.readUInt());
642         SkAlphaType alphaType = static_cast<SkAlphaType>(reader.readUInt());
643         sk_sp<SkColorSpace> colorSpace;
644 
645         size_t size = reader.readUInt();
646         if (size == 0) {
647             colorSpace = nullptr;
648         } else {
649             SkAutoMalloc colorBuffer(size);
650             if (!reader.readByteArray(colorBuffer.get(), size)) {
651                 return false;
652             }
653             colorSpace = SkColorSpace::Deserialize(colorBuffer.get(), size);
654         }
655 
656         SkImageInfo imageInfo = SkImageInfo::Make(width, height, colorType, alphaType, colorSpace);
657         auto skData = SkData::MakeWithCopy(const_cast<void*>(pixBuffer.get()), pixmapSize);
658         PostSkImgToTargetThread();
659         skiaImage_ = SkImage::MakeRasterData(imageInfo, skData, rb);
660         return true;
661     }
662 }
663 } // namespace Drawing
664 } // namespace Rosen
665 } // namespace OHOS
666