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 #ifdef USE_M133_SKIA
19 #include "src/base/SkAutoMalloc.h"
20 #include "include/encode/SkJpegEncoder.h"
21 #include "include/encode/SkPngEncoder.h"
22 #include "include/encode/SkWebpEncoder.h"
23 #else
24 #include "src/core/SkAutoMalloc.h"
25 #endif
26 #include "src/core/SkReadBuffer.h"
27 #include "src/core/SkWriteBuffer.h"
28 #include "src/image/SkImage_Base.h"
29
30 #include "draw/surface.h"
31 #include "image/bitmap.h"
32 #include "image/image.h"
33 #include "image/picture.h"
34 #include "utils/data.h"
35 #include "utils/log.h"
36 #include "utils/system_properties.h"
37
38 #include "skia_bitmap.h"
39 #include "skia_data.h"
40 #include "skia_image_info.h"
41 #include "skia_pixmap.h"
42 #include "skia_surface.h"
43 #include "skia_texture_info.h"
44
45 #ifdef RS_ENABLE_GPU
46 #include "include/core/SkYUVAPixmaps.h"
47 #include "skia_gpu_context.h"
48 #endif
49
50 namespace OHOS {
51 namespace Rosen {
52 namespace Drawing {
SkiaImage()53 SkiaImage::SkiaImage() noexcept : skiaImage_(nullptr) {}
54
SkiaImage(sk_sp<SkImage> skImg)55 SkiaImage::SkiaImage(sk_sp<SkImage> skImg) noexcept
56 {
57 PostSkImgToTargetThread();
58 skiaImage_ = skImg;
59 }
60
~SkiaImage()61 SkiaImage::~SkiaImage()
62 {
63 PostSkImgToTargetThread();
64 }
65
PostSkImgToTargetThread()66 void SkiaImage::PostSkImgToTargetThread()
67 {
68 if (skiaImage_ == nullptr) {
69 return;
70 }
71 #ifdef RS_ENABLE_GPU
72 auto context = as_IB(skiaImage_.get())->directContext();
73 auto func = SkiaGPUContext::GetPostFunc(sk_ref_sp(context));
74 if (func) {
75 func([image = skiaImage_.release()]() { SkSafeUnref(image); });
76 }
77 #endif
78 }
79
MakeFromRaster(const Pixmap & pixmap,RasterReleaseProc rasterReleaseProc,ReleaseContext releaseContext)80 std::shared_ptr<Image> SkiaImage::MakeFromRaster(const Pixmap& pixmap,
81 RasterReleaseProc rasterReleaseProc, ReleaseContext releaseContext)
82 {
83 auto& skPixmap = pixmap.GetImpl<SkiaPixmap>()->ExportSkiaPixmap();
84 #ifdef USE_M133_SKIA
85 sk_sp<SkImage> skImage = SkImages::RasterFromPixmap(skPixmap, rasterReleaseProc, releaseContext);
86 #else
87 sk_sp<SkImage> skImage = SkImage::MakeFromRaster(skPixmap, rasterReleaseProc, releaseContext);
88 #endif
89 if (skImage == nullptr) {
90 LOGD("SkiaImage::MakeFromRaster failed");
91 return nullptr;
92 }
93 std::shared_ptr<Image> image = std::make_shared<Image>();
94 image->GetImpl<SkiaImage>()->SetSkImage(skImage);
95 return image;
96 }
97
MakeRasterData(const ImageInfo & info,std::shared_ptr<Data> pixels,size_t rowBytes)98 std::shared_ptr<Image> SkiaImage::MakeRasterData(const ImageInfo& info, std::shared_ptr<Data> pixels,
99 size_t rowBytes)
100 {
101 if (pixels == nullptr) {
102 LOGD("SkiaImage::MakeRasterData pixels is nullptr");
103 return nullptr;
104 }
105 SkImageInfo skImageInfo = SkiaImageInfo::ConvertToSkImageInfo(info);
106 auto skData = pixels->GetImpl<SkiaData>()->GetSkData();
107
108 #ifdef USE_M133_SKIA
109 sk_sp<SkImage> skImage = SkImages::RasterFromData(skImageInfo, skData, rowBytes);
110 #else
111 sk_sp<SkImage> skImage = SkImage::MakeRasterData(skImageInfo, skData, rowBytes);
112 #endif
113 if (skImage == nullptr) {
114 LOGD("skImage nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
115 return nullptr;
116 }
117 std::shared_ptr<Image> image = std::make_shared<Image>();
118 image->GetImpl<SkiaImage>()->SetSkImage(skImage);
119 return image;
120 }
121
BuildFromBitmap(const Bitmap & bitmap)122 bool SkiaImage::BuildFromBitmap(const Bitmap& bitmap)
123 {
124 auto skBitmapImpl = bitmap.GetImpl<SkiaBitmap>();
125 if (skBitmapImpl != nullptr) {
126 const SkBitmap skBitmap = skBitmapImpl->ExportSkiaBitmap();
127 PostSkImgToTargetThread();
128 #ifdef USE_M133_SKIA
129 skiaImage_ = SkImages::RasterFromBitmap(skBitmap);
130 #else
131 skiaImage_ = SkImage::MakeFromBitmap(skBitmap);
132 #endif
133 return skiaImage_ != nullptr;
134 }
135 return false;
136 }
137
138 #ifdef RS_ENABLE_GPU
MakeFromYUVAPixmaps(GPUContext & gpuContext,const YUVInfo & info,void * memory)139 std::shared_ptr<Image> SkiaImage::MakeFromYUVAPixmaps(GPUContext& gpuContext, const YUVInfo& info, void* memory)
140 {
141 if (!memory) {
142 LOGD("memory nullprt, %{public}s, %{public}d", __FUNCTION__, __LINE__);
143 return nullptr;
144 }
145
146 auto grContext = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
147 if (grContext == nullptr) {
148 LOGD("grContext nullprt, %{public}s, %{public}d", __FUNCTION__, __LINE__);
149 return nullptr;
150 }
151 SkYUVAPixmapInfo pixmapInfo({{info.GetWidth(), info.GetHeight()},
152 SkiaYUVInfo::ConvertToSkPlaneConfig(info.GetConfig()),
153 SkiaYUVInfo::ConvertToSkSubSampling(info.GetSampling()),
154 SkiaYUVInfo::ConvertToSkYUVColorSpace(info.GetColorSpace())},
155 SkiaYUVInfo::ConvertToSkDataType(info.GetDataType()),
156 nullptr);
157 auto skYUVAPixmaps = SkYUVAPixmaps::FromExternalMemory(pixmapInfo, memory);
158 #ifdef USE_M133_SKIA
159 auto skImage = SkImages::TextureFromYUVAPixmaps(grContext.get(), skYUVAPixmaps);
160 #else
161 auto skImage = SkImage::MakeFromYUVAPixmaps(grContext.get(), skYUVAPixmaps);
162 #endif
163 if (skImage == nullptr) {
164 LOGD("skImage nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
165 return nullptr;
166 }
167 std::shared_ptr<Image> image = std::make_shared<Image>();
168 image->GetImpl<SkiaImage>()->SetSkImage(skImage);
169 return image;
170 }
171
BuildFromBitmap(GPUContext & gpuContext,const Bitmap & bitmap)172 bool SkiaImage::BuildFromBitmap(GPUContext& gpuContext, const Bitmap& bitmap)
173 {
174 grContext_ = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
175 auto& skBitmap = bitmap.GetImpl<SkiaBitmap>()->ExportSkiaBitmap();
176 PostSkImgToTargetThread();
177 #ifdef USE_M133_SKIA
178 skiaImage_ = SkImages::CrossContextTextureFromPixmap(grContext_.get(), skBitmap.pixmap(), false);
179 #else
180 skiaImage_ = SkImage::MakeCrossContextFromPixmap(grContext_.get(), skBitmap.pixmap(), false);
181 #endif
182
183 return (skiaImage_ != nullptr) ? true : false;
184 }
185
MakeFromEncoded(const std::shared_ptr<Data> & data)186 bool SkiaImage::MakeFromEncoded(const std::shared_ptr<Data>& data)
187 {
188 if (data == nullptr) {
189 LOGD("SkiaImage::MakeFromEncoded failed, data is invalid");
190 return false;
191 }
192
193 auto skData = data->GetImpl<SkiaData>()->GetSkData();
194 PostSkImgToTargetThread();
195 #ifdef USE_M133_SKIA
196 skiaImage_ = SkImages::DeferredFromEncodedData(skData);
197 #else
198 skiaImage_ = SkImage::MakeFromEncoded(skData);
199 #endif
200 return (skiaImage_ != nullptr);
201 }
202
BuildSubset(const std::shared_ptr<Image> image,const RectI & rect,GPUContext & gpuContext)203 bool SkiaImage::BuildSubset(const std::shared_ptr<Image> image, const RectI& rect, GPUContext& gpuContext)
204 {
205 if (image == nullptr) {
206 LOGD("SkiaImage::BuildSubset failed, origin Image is invalid");
207 return false;
208 }
209 auto imageImpl = image->GetImpl<SkiaImage>();
210 if (imageImpl == nullptr) {
211 LOGD("SkiaImage::BuildSubset failed, GetImpl failed");
212 return false;
213 }
214 auto skiaImage = imageImpl->GetImage();
215 if (skiaImage == nullptr) {
216 LOGD("SkiaImage::BuildSubset failed, GetImage failed");
217 return false;
218 }
219
220 auto skiaRect = SkIRect::MakeLTRB(rect.GetLeft(), rect.GetTop(), rect.GetRight(), rect.GetBottom());
221 grContext_ = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
222 PostSkImgToTargetThread();
223 #ifdef USE_M133_SKIA
224 skiaImage_ = skiaImage->makeSubset(grContext_.get(), skiaRect);
225 #else
226 skiaImage_ = skiaImage->makeSubset(skiaRect, grContext_.get());
227 #endif
228 return (skiaImage_ != nullptr) ? true : false;
229 }
230
BuildFromCompressed(GPUContext & gpuContext,const std::shared_ptr<Data> & data,int width,int height,CompressedType type,const std::shared_ptr<ColorSpace> & colorSpace)231 bool SkiaImage::BuildFromCompressed(GPUContext& gpuContext, const std::shared_ptr<Data>& data, int width, int height,
232 CompressedType type, const std::shared_ptr<ColorSpace>& colorSpace)
233 {
234 if (data == nullptr) {
235 LOGD("SkiaImage::BuildFromCompressed, build failed, data is invalid");
236 return false;
237 }
238 grContext_ = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
239 auto skData = data->GetImpl<SkiaData>()->GetSkData();
240 PostSkImgToTargetThread();
241 sk_sp<SkColorSpace> skColorSpace = nullptr;
242 if (colorSpace != nullptr) {
243 auto colorSpaceImpl = colorSpace->GetImpl<SkiaColorSpace>();
244 skColorSpace = colorSpaceImpl ? colorSpaceImpl->GetColorSpace() : SkColorSpace::MakeSRGB();
245 }
246 #ifdef USE_M133_SKIA
247 skiaImage_ = SkImages::TextureFromCompressedTextureData(grContext_.get(), skData, width, height,
248 static_cast<SkTextureCompressionType>(type), skgpu::Mipmapped::kNo, GrProtected::kNo, skColorSpace);
249 #else
250 skiaImage_ = SkImage::MakeTextureFromCompressed(grContext_.get(),
251 skData, width, height, static_cast<SkImage::CompressionType>(type),
252 GrMipmapped::kNo, GrProtected::kNo, skColorSpace);
253 #endif
254 return (skiaImage_ != nullptr) ? true : false;
255 }
256
DeleteCleanupHelper(void (* deleteFunc)(void *),void * cleanupHelper)257 void SkiaImage::DeleteCleanupHelper(void (*deleteFunc)(void*), void* cleanupHelper)
258 {
259 if (deleteFunc == nullptr || cleanupHelper == nullptr) {
260 return;
261 }
262
263 (*deleteFunc)(cleanupHelper);
264 }
265
BuildFromTexture(GPUContext & gpuContext,const TextureInfo & info,TextureOrigin origin,BitmapFormat bitmapFormat,const std::shared_ptr<ColorSpace> & colorSpace,void (* deleteFunc)(void *),void * cleanupHelper)266 bool SkiaImage::BuildFromTexture(GPUContext& gpuContext, const TextureInfo& info, TextureOrigin origin,
267 BitmapFormat bitmapFormat, const std::shared_ptr<ColorSpace>& colorSpace,
268 void (*deleteFunc)(void*), void* cleanupHelper)
269 {
270 grContext_ = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
271 if (!grContext_) {
272 LOGD("SkiaImage BuildFromTexture grContext_ is null");
273 DeleteCleanupHelper(deleteFunc, cleanupHelper);
274 return false;
275 }
276
277 sk_sp<SkColorSpace> skColorSpace = nullptr;
278 if (colorSpace != nullptr) {
279 auto colorSpaceImpl = colorSpace->GetImpl<SkiaColorSpace>();
280 skColorSpace = colorSpaceImpl ? colorSpaceImpl->GetColorSpace() : SkColorSpace::MakeSRGB();
281 } else {
282 skColorSpace = SkColorSpace::MakeSRGB();
283 }
284
285 #ifdef RS_ENABLE_VK
286 if (SystemProperties::IsUseVulkan()) {
287 const auto& backendTexture = SkiaTextureInfo::ConvertToGrBackendTexture(info);
288 if (!backendTexture.isValid()) {
289 LOGE("SkiaImage BuildFromTexture backend texture is not valid!!!!");
290 DeleteCleanupHelper(deleteFunc, cleanupHelper);
291 return false;
292 }
293 PostSkImgToTargetThread();
294 #ifdef USE_M133_SKIA
295 skiaImage_ = SkImages::BorrowTextureFrom(grContext_.get(), backendTexture,
296 SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin),
297 SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
298 SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace, deleteFunc, cleanupHelper);
299 #else
300 skiaImage_ = SkImage::MakeFromTexture(grContext_.get(), backendTexture,
301 SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin),
302 SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
303 SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace, deleteFunc, cleanupHelper);
304 #endif
305 } else {
306 PostSkImgToTargetThread();
307 #ifdef USE_M133_SKIA
308 skiaImage_ = SkImages::BorrowTextureFrom(grContext_.get(),
309 SkiaTextureInfo::ConvertToGrBackendTexture(info),
310 SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin),
311 SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
312 SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace);
313 #else
314 skiaImage_ = SkImage::MakeFromTexture(grContext_.get(),
315 SkiaTextureInfo::ConvertToGrBackendTexture(info),
316 SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin),
317 SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
318 SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace);
319 #endif
320 }
321 #else
322 PostSkImgToTargetThread();
323 #ifdef USE_M133_SKIA
324 skiaImage_ = SkImages::BorrowTextureFrom(grContext_.get(), SkiaTextureInfo::ConvertToGrBackendTexture(info),
325 SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin), SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
326 SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace);
327 #else
328 skiaImage_ = SkImage::MakeFromTexture(grContext_.get(), SkiaTextureInfo::ConvertToGrBackendTexture(info),
329 SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin), SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
330 SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace);
331 #endif
332 #endif
333 if (skiaImage_ == nullptr) {
334 LOGE("SkiaImage::MakeFromTexture skiaImage_ is nullptr!!!! "
335 "TextureInfo format:%{public}u, w:%{public}d, h:%{public}d , bitmapFormat.colorType is %{public}d",
336 info.GetFormat(), info.GetWidth(), info.GetHeight(), static_cast<int>(bitmapFormat.colorType));
337 return false;
338 }
339 return true;
340 }
341
BuildFromSurface(GPUContext & gpuContext,Surface & surface,TextureOrigin origin,BitmapFormat bitmapFormat,const std::shared_ptr<ColorSpace> & colorSpace)342 bool SkiaImage::BuildFromSurface(GPUContext& gpuContext, Surface& surface, TextureOrigin origin,
343 BitmapFormat bitmapFormat, const std::shared_ptr<ColorSpace>& colorSpace)
344 {
345 auto skSurface = surface.GetImpl<SkiaSurface>()->GetSkSurface();
346 if (!skSurface) {
347 LOGD("SkiaImage::BuildFromSurface skSurface is null");
348 return false;
349 }
350
351 #ifdef USE_M133_SKIA
352 GrBackendTexture grBackendTexture =
353 SkSurfaces::GetBackendTexture(skSurface.get(), SkSurface::BackendHandleAccess::kFlushRead_BackendHandleAccess);
354 #else
355 GrBackendTexture grBackendTexture
356 = skSurface->getBackendTexture(SkSurface::BackendHandleAccess::kFlushRead_BackendHandleAccess);
357 #endif
358 if (!grBackendTexture.isValid()) {
359 LOGD("SkiaImage::BuildFromSurface grBackendTexture is invalid");
360 return false;
361 }
362 grContext_ = gpuContext.GetImpl<SkiaGPUContext>()->GetGrContext();
363
364 sk_sp<SkColorSpace> skColorSpace = nullptr;
365 if (colorSpace != nullptr) {
366 auto colorSpaceImpl = colorSpace->GetImpl<SkiaColorSpace>();
367 skColorSpace = colorSpaceImpl ? colorSpaceImpl->GetColorSpace() : nullptr;
368 }
369 PostSkImgToTargetThread();
370 #ifdef USE_M133_SKIA
371 skiaImage_ = SkImages::BorrowTextureFrom(grContext_.get(), grBackendTexture,
372 SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin), SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
373 SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace);
374 #else
375 skiaImage_ = SkImage::MakeFromTexture(grContext_.get(), grBackendTexture,
376 SkiaTextureInfo::ConvertToGrSurfaceOrigin(origin), SkiaImageInfo::ConvertToSkColorType(bitmapFormat.colorType),
377 SkiaImageInfo::ConvertToSkAlphaType(bitmapFormat.alphaType), skColorSpace);
378 #endif
379 return (skiaImage_ != nullptr) ? true : false;
380 }
381
SetGrBackendTexture(const GrBackendTexture & grBackendTexture)382 void SkiaImage::SetGrBackendTexture(const GrBackendTexture& grBackendTexture)
383 {
384 grBackendTexture_ = grBackendTexture;
385 }
386
GetBackendTexture(bool flushPendingGrContextIO,TextureOrigin * origin)387 BackendTexture SkiaImage::GetBackendTexture(bool flushPendingGrContextIO, TextureOrigin* origin)
388 {
389 if (skiaImage_ == nullptr) {
390 LOGD("SkiaImage::GetBackendTexture, SkImage is nullptr!");
391 return BackendTexture(false); // invalid
392 }
393 GrBackendTexture skBackendTexture;
394 #ifdef USE_M133_SKIA
395 if (origin == nullptr) {
396 SkImages::GetBackendTextureFromImage(skiaImage_.get(), &skBackendTexture, flushPendingGrContextIO);
397 } else {
398 GrSurfaceOrigin grOrigin = SkiaTextureInfo::ConvertToGrSurfaceOrigin(*origin);
399 SkImages::GetBackendTextureFromImage(skiaImage_.get(), &skBackendTexture, flushPendingGrContextIO, &grOrigin);
400 *origin = static_cast<TextureOrigin>(grOrigin);
401 }
402 #else
403 if (origin == nullptr) {
404 skBackendTexture =
405 skiaImage_->getBackendTexture(flushPendingGrContextIO);
406 } else {
407 GrSurfaceOrigin grOrigin;
408 skBackendTexture =
409 skiaImage_->getBackendTexture(flushPendingGrContextIO, &grOrigin);
410 *origin = static_cast<TextureOrigin>(grOrigin);
411 }
412 #endif
413 if (!skBackendTexture.isValid()) {
414 LOGD("SkiaImage::GetBackendTexture, skBackendTexture is nullptr!");
415 return BackendTexture(false); // invalid
416 }
417 auto backendTexture = BackendTexture(true);
418 SetGrBackendTexture(skBackendTexture);
419 #ifdef RS_ENABLE_VK
420 if (SystemProperties::IsUseVulkan()) {
421 TextureInfo info;
422 SkiaTextureInfo::ConvertToVKTexture(skBackendTexture, info);
423 backendTexture.SetTextureInfo(info);
424 } else {
425 backendTexture.SetTextureInfo(SkiaTextureInfo::ConvertToTextureInfo(skBackendTexture));
426 }
427 #else
428 backendTexture.SetTextureInfo(SkiaTextureInfo::ConvertToTextureInfo(skBackendTexture));
429 #endif
430 return backendTexture;
431 }
432
IsValid(GPUContext * context) const433 bool SkiaImage::IsValid(GPUContext* context) const
434 {
435 if (skiaImage_ == nullptr) {
436 LOGD("SkiaImage::IsValid, skiaImage_ is nullptr!");
437 return false;
438 }
439 if (context == nullptr) {
440 return skiaImage_->isValid(nullptr);
441 }
442 return skiaImage_->isValid(context->GetImpl<SkiaGPUContext>()->GetGrContext().get());
443 }
444 #endif
445
AsLegacyBitmap(Bitmap & bitmap) const446 bool SkiaImage::AsLegacyBitmap(Bitmap& bitmap) const
447 {
448 if (skiaImage_ == nullptr) {
449 LOGD("SkiaImage::IsValid, skiaImage_ is nullptr!");
450 return false;
451 }
452 SkBitmap newBitmap;
453 if (!skiaImage_->asLegacyBitmap(&newBitmap)) {
454 LOGD("SkiaImage::AsLegacyBitmap failed!");
455 return false;
456 }
457 bitmap.GetImpl<SkiaBitmap>()->SetSkBitmap(newBitmap);
458 return true;
459 }
460
GetWidth() const461 int SkiaImage::GetWidth() const
462 {
463 return (skiaImage_ == nullptr) ? 0 : skiaImage_->width();
464 }
465
GetHeight() const466 int SkiaImage::GetHeight() const
467 {
468 return (skiaImage_ == nullptr) ? 0 : skiaImage_->height();
469 }
470
GetColorType() const471 ColorType SkiaImage::GetColorType() const
472 {
473 return (skiaImage_ == nullptr) ? ColorType::COLORTYPE_UNKNOWN :
474 SkiaImageInfo::ConvertToColorType(skiaImage_->colorType());
475 }
476
GetAlphaType() const477 AlphaType SkiaImage::GetAlphaType() const
478 {
479 return (skiaImage_ == nullptr) ? AlphaType::ALPHATYPE_UNKNOWN :
480 SkiaImageInfo::ConvertToAlphaType(skiaImage_->alphaType());
481 }
482
GetColorSpace() const483 std::shared_ptr<ColorSpace> SkiaImage::GetColorSpace() const
484 {
485 if (skiaImage_ == nullptr) {
486 return nullptr;
487 }
488 sk_sp<SkColorSpace> skColorSpace = skiaImage_->refColorSpace();
489 if (skColorSpace == nullptr) {
490 return nullptr;
491 }
492 std::shared_ptr<ColorSpace> colorSpace = std::make_shared<ColorSpace>();
493 colorSpace->GetImpl<SkiaColorSpace>()->SetColorSpace(skColorSpace);
494 return colorSpace;
495 }
496
GetUniqueID() const497 uint32_t SkiaImage::GetUniqueID() const
498 {
499 return (skiaImage_ == nullptr) ? 0 : skiaImage_->uniqueID();
500 }
501
GetImageInfo()502 ImageInfo SkiaImage::GetImageInfo()
503 {
504 if (skiaImage_ == nullptr) {
505 return {};
506 }
507 return SkiaImageInfo::ConvertToRSImageInfo(skiaImage_->imageInfo());
508 }
509
ReadPixels(Bitmap & bitmap,int x,int y)510 bool SkiaImage::ReadPixels(Bitmap& bitmap, int x, int y)
511 {
512 const auto& skBitmap = bitmap.GetImpl<SkiaBitmap>()->ExportSkiaBitmap();
513 const auto& skPixmap = skBitmap.pixmap();
514
515 return (skiaImage_ == nullptr) ? false : skiaImage_->readPixels(skPixmap, x, y);
516 }
517
ReadPixels(Pixmap & pixmap,int x,int y)518 bool SkiaImage::ReadPixels(Pixmap& pixmap, int x, int y)
519 {
520 auto& skPixmap = pixmap.GetImpl<SkiaPixmap>()->ExportSkiaPixmap();
521 return (skiaImage_ == nullptr) ? false : skiaImage_->readPixels(skPixmap, x, y);
522 }
523
ReadPixels(const ImageInfo & dstInfo,void * dstPixels,size_t dstRowBytes,int32_t srcX,int32_t srcY) const524 bool SkiaImage::ReadPixels(const ImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
525 int32_t srcX, int32_t srcY) const
526 {
527 SkImageInfo skImageInfo = SkiaImageInfo::ConvertToSkImageInfo(dstInfo);
528 return (skiaImage_ == nullptr) ? false : skiaImage_->readPixels(skImageInfo, dstPixels, dstRowBytes, srcX, srcY);
529 }
530
IsTextureBacked() const531 bool SkiaImage::IsTextureBacked() const
532 {
533 return (skiaImage_ == nullptr) ? false : skiaImage_->isTextureBacked();
534 }
535
ScalePixels(const Bitmap & bitmap,const SamplingOptions & sampling,bool allowCachingHint) const536 bool SkiaImage::ScalePixels(const Bitmap& bitmap, const SamplingOptions& sampling, bool allowCachingHint) const
537 {
538 const auto& skBitmap = bitmap.GetImpl<SkiaBitmap>()->ExportSkiaBitmap();
539 const auto& skPixmap = skBitmap.pixmap();
540
541 SkSamplingOptions samplingOptions;
542 if (sampling.GetUseCubic()) {
543 samplingOptions = SkSamplingOptions({ sampling.GetCubicCoffB(), sampling.GetCubicCoffC() });
544 } else {
545 samplingOptions = SkSamplingOptions(static_cast<SkFilterMode>(sampling.GetFilterMode()),
546 static_cast<SkMipmapMode>(sampling.GetMipmapMode()));
547 }
548
549 SkImage::CachingHint skCachingHint;
550 if (allowCachingHint) {
551 skCachingHint = SkImage::CachingHint::kAllow_CachingHint;
552 } else {
553 skCachingHint = SkImage::CachingHint::kDisallow_CachingHint;
554 }
555
556 return (skiaImage_ == nullptr) ? false : skiaImage_->scalePixels(skPixmap, samplingOptions, skCachingHint);
557 }
558
EncodeToData(EncodedImageFormat encodedImageFormat,int quality) const559 std::shared_ptr<Data> SkiaImage::EncodeToData(EncodedImageFormat encodedImageFormat, int quality) const
560 {
561 if (skiaImage_ == nullptr) {
562 LOGD("SkiaImage::EncodeToData, skiaImage_ is null!");
563 return nullptr;
564 }
565 #ifdef USE_M133_SKIA
566 auto grContext = as_IB(skiaImage_.get())->directContext();
567 sk_sp<SkData> skData = nullptr;
568 if (encodedImageFormat == EncodedImageFormat::PNG) {
569 SkPngEncoder::Options options;
570 skData = SkPngEncoder::Encode(grContext, skiaImage_.get(), options);
571 } else if (encodedImageFormat == EncodedImageFormat::JPEG) {
572 SkJpegEncoder::Options options;
573 options.fQuality = quality;
574 skData = SkJpegEncoder::Encode(grContext, skiaImage_.get(), options);
575 } else if (encodedImageFormat == EncodedImageFormat::WEBP) {
576 SkWebpEncoder::Options options;
577 if (quality == 100) { // quality is 100
578 options.fCompression = SkWebpEncoder::Compression::kLossless;
579 options.fQuality = 75; // default options quality is 75
580 } else {
581 options.fCompression = SkWebpEncoder::Compression::kLossy;
582 options.fQuality = quality;
583 }
584 skData = SkWebpEncoder::Encode(grContext, skiaImage_.get(), options);
585 } else {
586 LOGD("SkiaImage::EncodeToData failed, unsupported format!");
587 return nullptr;
588 }
589 #else
590 SkEncodedImageFormat skEncodedImageFormat = SkiaImageInfo::ConvertToSkEncodedImageFormat(encodedImageFormat);
591 auto skData = skiaImage_->encodeToData(skEncodedImageFormat, quality);
592 #endif
593 if (skData == nullptr) {
594 LOGD("SkiaImage::EncodeToData, skData null!");
595 return nullptr;
596 }
597 std::shared_ptr<Data> data = std::make_shared<Data>();
598 data->GetImpl<SkiaData>()->SetSkData(skData);
599 return data;
600 }
601
IsLazyGenerated() const602 bool SkiaImage::IsLazyGenerated() const
603 {
604 return (skiaImage_ == nullptr) ? false : skiaImage_->isLazyGenerated();
605 }
606
GetROPixels(Bitmap & bitmap) const607 bool SkiaImage::GetROPixels(Bitmap& bitmap) const
608 {
609 if (skiaImage_ == nullptr) {
610 LOGD("SkiaImage::GetROPixels, skiaImage_ is null!");
611 return false;
612 }
613 auto context = as_IB(skiaImage_.get())->directContext();
614 if (!as_IB(skiaImage_.get())->getROPixels(context, &bitmap.GetImpl<SkiaBitmap>()->GetSkBitmap())) {
615 LOGD("skiaImge getROPixels failed");
616 return false;
617 }
618 return true;
619 }
620
MakeRasterImage() const621 std::shared_ptr<Image> SkiaImage::MakeRasterImage() const
622 {
623 if (skiaImage_ == nullptr) {
624 return nullptr;
625 }
626 sk_sp<SkImage> skImage = skiaImage_->makeRasterImage();
627 if (skImage == nullptr) {
628 LOGD("skImage nullptr, %{public}s, %{public}d", __FUNCTION__, __LINE__);
629 return nullptr;
630 }
631 std::shared_ptr<Image> image = std::make_shared<Image>();
632 image->GetImpl<SkiaImage>()->SetSkImage(skImage);
633 return image;
634 }
635
CanPeekPixels() const636 bool SkiaImage::CanPeekPixels() const
637 {
638 SkPixmap pixmap;
639 if (skiaImage_ == nullptr || !skiaImage_->peekPixels(&pixmap)) {
640 return false;
641 }
642 return true;
643 }
644
IsOpaque() const645 bool SkiaImage::IsOpaque() const
646 {
647 return (skiaImage_ == nullptr) ? false : skiaImage_->isOpaque();
648 }
649
HintCacheGpuResource() const650 void SkiaImage::HintCacheGpuResource() const
651 {
652 as_IB(skiaImage_.get())->hintCacheGpuResource();
653 }
654
GetImage() const655 const sk_sp<SkImage> SkiaImage::GetImage() const
656 {
657 return skiaImage_;
658 }
659
SetSkImage(const sk_sp<SkImage> & skImage)660 void SkiaImage::SetSkImage(const sk_sp<SkImage>& skImage)
661 {
662 PostSkImgToTargetThread();
663 skiaImage_ = skImage;
664 }
665
666 #ifdef RS_ENABLE_GPU
GetGrContext() const667 sk_sp<GrDirectContext> SkiaImage::GetGrContext() const
668 {
669 return grContext_;
670 }
671 #endif
672
Serialize() const673 std::shared_ptr<Data> SkiaImage::Serialize() const
674 {
675 if (skiaImage_ == nullptr) {
676 LOGD("SkiaImage::Serialize, SkImage is nullptr!");
677 return nullptr;
678 }
679
680 #ifdef USE_M133_SKIA
681 SkBinaryWriteBuffer writer({});
682 #else
683 SkBinaryWriteBuffer writer;
684 #endif
685 bool type = skiaImage_->isLazyGenerated();
686 writer.writeBool(type);
687 if (type) {
688 writer.writeImage(skiaImage_.get());
689 size_t length = writer.bytesWritten();
690 std::shared_ptr<Data> data = std::make_shared<Data>();
691 data->BuildUninitialized(length);
692 writer.writeToMemory(data->WritableData());
693 return data;
694 } else {
695 SkBitmap bitmap;
696
697 auto context = as_IB(skiaImage_.get())->directContext();
698 if (!as_IB(skiaImage_.get())->getROPixels(context, &bitmap)) {
699 LOGD("SkiaImage::SerializeNoLazyImage SkImage getROPixels failed");
700 return nullptr;
701 }
702 SkPixmap pixmap;
703 if (!bitmap.peekPixels(&pixmap)) {
704 LOGD("SkiaImage::SerializeNoLazyImage SkImage peekPixels failed");
705 return nullptr;
706 }
707 size_t rb = pixmap.rowBytes();
708 int32_t width = pixmap.width();
709 int32_t height = pixmap.height();
710 const void* addr = pixmap.addr();
711 size_t size = pixmap.computeByteSize();
712
713 writer.writeUInt(size);
714 writer.writeByteArray(addr, size);
715 writer.writeUInt(rb);
716 writer.write32(width);
717 writer.write32(height);
718
719 writer.writeUInt(pixmap.colorType());
720 writer.writeUInt(pixmap.alphaType());
721
722 if (pixmap.colorSpace() == nullptr) {
723 writer.writeUInt(0);
724 } else {
725 auto data = pixmap.colorSpace()->serialize();
726 writer.writeUInt(data->size());
727 writer.writeByteArray(data->data(), data->size());
728 }
729 size_t length = writer.bytesWritten();
730 std::shared_ptr<Data> data = std::make_shared<Data>();
731 data->BuildUninitialized(length);
732 writer.writeToMemory(data->WritableData());
733 return data;
734 }
735 }
736
Deserialize(std::shared_ptr<Data> data)737 bool SkiaImage::Deserialize(std::shared_ptr<Data> data)
738 {
739 if (data == nullptr) {
740 LOGD("SkiaImage::Deserialize, data is invalid!");
741 return false;
742 }
743
744 SkReadBuffer reader(data->GetData(), data->GetSize());
745 bool type = reader.readBool();
746 if (type) {
747 PostSkImgToTargetThread();
748 skiaImage_ = reader.readImage();
749 return skiaImage_ != nullptr;
750 } else {
751 size_t pixmapSize = reader.readUInt();
752 SkAutoMalloc pixBuffer(pixmapSize);
753 if (!reader.readByteArray(pixBuffer.get(), pixmapSize)) {
754 return false;
755 }
756
757 size_t rb = reader.readUInt();
758 int32_t width = reader.read32();
759 int32_t height = reader.read32();
760
761 SkColorType colorType = static_cast<SkColorType>(reader.readUInt());
762 SkAlphaType alphaType = static_cast<SkAlphaType>(reader.readUInt());
763 sk_sp<SkColorSpace> colorSpace;
764
765 size_t size = reader.readUInt();
766 if (size == 0) {
767 colorSpace = nullptr;
768 } else {
769 SkAutoMalloc colorBuffer(size);
770 if (!reader.readByteArray(colorBuffer.get(), size)) {
771 return false;
772 }
773 colorSpace = SkColorSpace::Deserialize(colorBuffer.get(), size);
774 }
775
776 SkImageInfo imageInfo = SkImageInfo::Make(width, height, colorType, alphaType, colorSpace);
777 auto skData = SkData::MakeWithCopy(const_cast<void*>(pixBuffer.get()), pixmapSize);
778 PostSkImgToTargetThread();
779 #ifdef USE_M133_SKIA
780 skiaImage_ = SkImages::RasterFromData(imageInfo, skData, rb);
781 #else
782 skiaImage_ = SkImage::MakeRasterData(imageInfo, skData, rb);
783 #endif
784
785 return true;
786 }
787 }
788
SetHeadroom(float headroom)789 void SkiaImage::SetHeadroom(float headroom)
790 {
791 LOGD("SkiaImage does not support SetHeadroom!");
792 }
793
GetHeadroom() const794 float SkiaImage::GetHeadroom() const
795 {
796 LOGD("SkiaImage does not support GetHeadroom!");
797 return 1.0f;
798 }
799 } // namespace Drawing
800 } // namespace Rosen
801 } // namespace OHOS
802