• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ext_encoder.h"
17 #include <algorithm>
18 #include <map>
19 
20 #include "SkBitmap.h"
21 #include "SkImageEncoder.h"
22 #ifdef IMAGE_COLORSPACE_FLAG
23 #include "color_space.h"
24 #endif
25 #include "ext_pixel_convert.h"
26 #include "ext_wstream.h"
27 #include "image_type_converter.h"
28 #include "image_utils.h"
29 #include "media_errors.h"
30 #include "string_ex.h"
31 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
32 #include "surface_buffer.h"
33 #endif
34 
35 namespace OHOS {
36 namespace ImagePlugin {
37 using namespace OHOS::HiviewDFX;
38 using namespace Media;
39 namespace {
40     constexpr OHOS::HiviewDFX::HiLogLabel LABEL = {LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "ExtEncoder"};
41 }
42 static const std::map<SkEncodedImageFormat, std::string> FORMAT_NAME = {
43     {SkEncodedImageFormat::kBMP, "image/bmp"},
44     {SkEncodedImageFormat::kGIF, "image/gif"},
45     {SkEncodedImageFormat::kICO, "image/ico"},
46     {SkEncodedImageFormat::kJPEG, "image/jpeg"},
47     {SkEncodedImageFormat::kPNG, "image/png"},
48     {SkEncodedImageFormat::kWBMP, "image/bmp"},
49     {SkEncodedImageFormat::kWEBP, "image/webp"},
50     {SkEncodedImageFormat::kPKM, ""},
51     {SkEncodedImageFormat::kKTX, ""},
52     {SkEncodedImageFormat::kASTC, ""},
53     {SkEncodedImageFormat::kDNG, ""},
54     {SkEncodedImageFormat::kHEIF, "image/heif"},
55 };
56 
ExtEncoder()57 ExtEncoder::ExtEncoder()
58 {
59 }
60 
~ExtEncoder()61 ExtEncoder::~ExtEncoder()
62 {
63 }
64 
StartEncode(OutputDataStream & outputStream,PlEncodeOptions & option)65 uint32_t ExtEncoder::StartEncode(OutputDataStream &outputStream, PlEncodeOptions &option)
66 {
67     output_ = &outputStream;
68     opts_ = option;
69     return SUCCESS;
70 }
71 
AddImage(Media::PixelMap & pixelMap)72 uint32_t ExtEncoder::AddImage(Media::PixelMap &pixelMap)
73 {
74     pixelmap_ = &pixelMap;
75     return SUCCESS;
76 }
77 
78 struct TmpBufferHolder {
79     std::unique_ptr<uint8_t[]> buf = nullptr;
80 };
81 
ToSkInfo(Media::PixelMap * pixelMap)82 static SkImageInfo ToSkInfo(Media::PixelMap *pixelMap)
83 {
84     ImageInfo info;
85     pixelMap->GetImageInfo(info);
86     SkColorType colorType = ImageTypeConverter::ToSkColorType(info.pixelFormat);
87     SkAlphaType alphaType = ImageTypeConverter::ToSkAlphaType(info.alphaType);
88     sk_sp<SkColorSpace> colorSpace = nullptr;
89 #ifdef IMAGE_COLORSPACE_FLAG
90     if (pixelMap->InnerGetGrColorSpacePtr() != nullptr) {
91         colorSpace = pixelMap->InnerGetGrColorSpacePtr()->ToSkColorSpace();
92     }
93 #endif
94     return SkImageInfo::Make(info.size.width, info.size.height, colorType, alphaType, colorSpace);
95 }
96 
RGBToRGBx(Media::PixelMap * pixelMap,SkImageInfo & skInfo,TmpBufferHolder & holder)97 static uint32_t RGBToRGBx(Media::PixelMap *pixelMap, SkImageInfo &skInfo, TmpBufferHolder &holder)
98 {
99     holder.buf = std::make_unique<uint8_t[]>(skInfo.computeMinByteSize());
100     ExtPixels src = {
101         static_cast<uint8_t*>(pixelMap->GetWritablePixels()),
102         pixelMap->GetCapacity(), pixelMap->GetWidth()*pixelMap->GetHeight(),
103     };
104     ExtPixels dst = {
105         holder.buf.get(), skInfo.computeMinByteSize(), skInfo.width()*skInfo.height(),
106     };
107     return ExtPixelConvert::RGBToRGBx(src, dst);
108 }
109 
BuildSkBitmap(Media::PixelMap * pixelMap,SkBitmap & bitmap,SkEncodedImageFormat format,TmpBufferHolder & holder)110 static uint32_t BuildSkBitmap(Media::PixelMap *pixelMap, SkBitmap &bitmap,
111     SkEncodedImageFormat format, TmpBufferHolder &holder)
112 {
113     uint32_t res = SUCCESS;
114     SkImageInfo skInfo = ToSkInfo(pixelMap);
115     auto pixels = pixelMap->GetWritablePixels();
116     if (format == SkEncodedImageFormat::kJPEG &&
117         skInfo.colorType() == SkColorType::kRGB_888x_SkColorType &&
118         pixelMap->GetCapacity() < skInfo.computeMinByteSize()) {
119         res = RGBToRGBx(pixelMap, skInfo, holder);
120         if (res != SUCCESS) {
121             HiLog::Error(LABEL, "ExtEncoder::BuildSkBitmap pixel convert failed %{public}d", res);
122             return res;
123         }
124         pixels = holder.buf.get();
125         skInfo = skInfo.makeColorType(SkColorType::kRGBA_8888_SkColorType);
126     }
127 
128     uint64_t rowStride = skInfo.minRowBytes64();
129     if (pixelMap->GetAllocatorType() == Media::AllocatorType::DMA_ALLOC) {
130         SurfaceBuffer* sbBuffer = reinterpret_cast<SurfaceBuffer*> (pixelMap->GetFd());
131         rowStride = sbBuffer->GetStride();
132     }
133     if (!bitmap.installPixels(skInfo, pixels, rowStride)) {
134         HiLog::Error(LABEL, "ExtEncoder::BuildSkBitmap to skbitmap failed");
135         return ERR_IMAGE_INVALID_PARAMETER;
136     }
137     return res;
138 }
139 
FinalizeEncode()140 uint32_t ExtEncoder::FinalizeEncode()
141 {
142     if (pixelmap_ == nullptr || output_ == nullptr) {
143         return ERR_IMAGE_INVALID_PARAMETER;
144     }
145     auto iter = std::find_if(FORMAT_NAME.begin(), FORMAT_NAME.end(),
146         [this](const std::map<SkEncodedImageFormat, std::string>::value_type item) {
147             return IsSameTextStr(item.second, opts_.format);
148     });
149     if (iter == FORMAT_NAME.end()) {
150         HiLog::Error(LABEL, "ExtEncoder::FinalizeEncode unsupported format %{public}s", opts_.format.c_str());
151         return ERR_IMAGE_INVALID_PARAMETER;
152     }
153     auto encodeFormat = iter->first;
154     SkBitmap bitmap;
155     TmpBufferHolder holder;
156     auto errorCode = BuildSkBitmap(pixelmap_, bitmap, encodeFormat, holder);
157     if (errorCode != SUCCESS) {
158         HiLog::Error(LABEL, "ExtEncoder::FinalizeEncode BuildSkBitmap failed");
159         return errorCode;
160     }
161     ExtWStream wStream(output_);
162     if (!SkEncodeImage(&wStream, bitmap, iter->first, opts_.quality)) {
163         HiLog::Error(LABEL, "ExtEncoder::FinalizeEncode encode failed");
164         return ERR_IMAGE_ENCODE_FAILED;
165     }
166     return SUCCESS;
167 }
168 } // namespace ImagePlugin
169 } // namespace OHOS
170