• 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 "bmp_decoder.h"
17 #include "image_utils.h"
18 #include "media_errors.h"
19 #include "securec.h"
20 #if !defined(IOS_PLATFORM) && !defined(A_PLATFORM)
21 #include "surface_buffer.h"
22 #endif
23 
24 namespace OHOS {
25 namespace ImagePlugin {
26 using namespace OHOS::HiviewDFX;
27 using namespace Media;
28 using namespace std;
29 static constexpr OHOS::HiviewDFX::HiLogLabel LABEL = { LOG_CORE, LOG_TAG_DOMAIN_ID_PLUGIN, "BmpDecoder" };
30 namespace {
31 constexpr uint32_t BMP_IMAGE_NUM = 1;
32 }
33 
SetSource(InputDataStream & sourceStream)34 void BmpDecoder::SetSource(InputDataStream &sourceStream)
35 {
36     stream_ = &sourceStream;
37     state_ = BmpDecodingState::SOURCE_INITED;
38 }
39 
Reset()40 void BmpDecoder::Reset()
41 {
42     if (stream_ != nullptr) {
43         stream_->Seek(0);
44     }
45     codec_.release();
46     info_.reset();
47     desireColor_ = kUnknown_SkColorType;
48 }
49 
GetImageSize(uint32_t index,PlSize & size)50 uint32_t BmpDecoder::GetImageSize(uint32_t index, PlSize &size)
51 {
52     if (index >= BMP_IMAGE_NUM) {
53         HiLog::Error(LABEL, "GetImageSize failed, invalid index:%{public}u, range:%{public}u", index, BMP_IMAGE_NUM);
54         return ERR_IMAGE_INVALID_PARAMETER;
55     }
56     if (state_ < BmpDecodingState::SOURCE_INITED) {
57         HiLog::Error(LABEL, "GetImageSize failed, invalid state:%{public}d", state_);
58         return ERR_MEDIA_INVALID_OPERATION;
59     }
60     if (state_ >= BmpDecodingState::BASE_INFO_PARSED) {
61         size.width = info_.width();
62         size.height = info_.height();
63         return SUCCESS;
64     }
65     if (!DecodeHeader()) {
66         HiLog::Error(LABEL, "GetImageSize failed, decode header failed, state=%{public}d", state_);
67         return ERR_IMAGE_DECODE_HEAD_ABNORMAL;
68     }
69     size.width = info_.width();
70     size.height = info_.height();
71     state_ = BmpDecodingState::BASE_INFO_PARSED;
72     return SUCCESS;
73 }
74 
SetDecodeOptions(uint32_t index,const PixelDecodeOptions & opts,PlImageInfo & info)75 uint32_t BmpDecoder::SetDecodeOptions(uint32_t index, const PixelDecodeOptions &opts, PlImageInfo &info)
76 {
77     if (index >= BMP_IMAGE_NUM) {
78         HiLog::Error(LABEL, "SetDecodeOptions failed, invalid index:%{public}u, range:%{public}u", index,
79                      BMP_IMAGE_NUM);
80         return ERR_IMAGE_INVALID_PARAMETER;
81     }
82     if (state_ < BmpDecodingState::SOURCE_INITED) {
83         HiLog::Error(LABEL, "SetDecodeOptions failed, invalid state %{public}d", state_);
84         return ERR_MEDIA_INVALID_OPERATION;
85     }
86     if (state_ >= BmpDecodingState::IMAGE_DECODING) {
87         Reset();
88         state_ = BmpDecodingState::SOURCE_INITED;
89     }
90     if (state_ < BmpDecodingState::BASE_INFO_PARSED) {
91         if (!DecodeHeader()) {
92             HiLog::Error(LABEL, "GetImageSize failed, decode header failed, state=%{public}d", state_);
93             return ERR_IMAGE_DECODE_HEAD_ABNORMAL;
94         }
95         state_ = BmpDecodingState::BASE_INFO_PARSED;
96     }
97     PlPixelFormat desiredFormat = opts.desiredPixelFormat;
98     desireColor_ = ConvertToColorType(desiredFormat, info.pixelFormat);
99     info.size.width = info_.width();
100     info.size.height = info_.height();
101     info.alphaType = ConvertToAlphaType(info_.alphaType());
102     state_ = BmpDecodingState::IMAGE_DECODING;
103     return SUCCESS;
104 }
105 
SetShareMemBuffer(uint64_t byteCount,DecodeContext & context)106 uint32_t BmpDecoder::SetShareMemBuffer(uint64_t byteCount, DecodeContext &context)
107 {
108 #if !defined(_WIN32) && !defined(_APPLE) && !defined(A_PLATFORM) && !defined(IOS_PLATFORM)
109     uint32_t id = context.pixelmapUniqueId_;
110     std::string name = "BMP RawData, uniqueId: " + std::to_string(getpid()) + '_' + std::to_string(id);
111     int fd = AshmemCreate(name.c_str(), byteCount);
112     if (fd < 0) {
113         return ERR_SHAMEM_DATA_ABNORMAL;
114     }
115     int result = AshmemSetProt(fd, PROT_READ | PROT_WRITE);
116     if (result < 0) {
117         ::close(fd);
118         return ERR_SHAMEM_DATA_ABNORMAL;
119     }
120     void* ptr = ::mmap(nullptr, byteCount, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
121     if (ptr == MAP_FAILED) {
122         ::close(fd);
123         return ERR_SHAMEM_DATA_ABNORMAL;
124     }
125     context.pixelsBuffer.buffer = ptr;
126     void *fdBuffer = new int32_t();
127     if (fdBuffer == nullptr) {
128         ::munmap(ptr, byteCount);
129         ::close(fd);
130         context.pixelsBuffer.buffer = nullptr;
131         return ERR_SHAMEM_DATA_ABNORMAL;
132     }
133     *static_cast<int32_t *>(fdBuffer) = fd;
134     context.pixelsBuffer.context = fdBuffer;
135     context.pixelsBuffer.bufferSize = byteCount;
136     context.allocatorType = AllocatorType::SHARE_MEM_ALLOC;
137     context.freeFunc = nullptr;
138 #endif
139     return SUCCESS;
140 }
141 
DmaMemAlloc(uint64_t count,DecodeContext & context,SkImageInfo & dstInfo)142 static uint32_t DmaMemAlloc(uint64_t count, DecodeContext &context, SkImageInfo &dstInfo)
143 {
144 #if defined(_WIN32) || defined(_APPLE) || defined(A_PLATFORM) || defined(IOS_PLATFORM)
145     HiLog::Error(LABEL, "Unsupport dma mem alloc");
146     return ERR_IMAGE_DATA_UNSUPPORT;
147 #else
148     sptr<SurfaceBuffer> sb = SurfaceBuffer::Create();
149     BufferRequestConfig requestConfig = {
150         .width = dstInfo.width(),
151         .height = dstInfo.height(),
152         .strideAlignment = 0x8, // set 0x8 as default value to alloc SurfaceBufferImpl
153         .format = GRAPHIC_PIXEL_FMT_RGBA_8888, // PixelFormat
154         .usage = BUFFER_USAGE_CPU_READ | BUFFER_USAGE_CPU_WRITE | BUFFER_USAGE_MEM_DMA,
155         .timeout = 0,
156         .colorGamut = GraphicColorGamut::GRAPHIC_COLOR_GAMUT_SRGB,
157         .transform = GraphicTransformType::GRAPHIC_ROTATE_NONE,
158     };
159     GSError ret = sb->Alloc(requestConfig);
160     if (ret != GSERROR_OK) {
161         HiLog::Error(LABEL, "SurfaceBuffer Alloc failed, %{public}s", GSErrorStr(ret).c_str());
162         return ERR_DMA_NOT_EXIST;
163     }
164     void* nativeBuffer = sb.GetRefPtr();
165     int32_t err = ImageUtils::SurfaceBuffer_Reference(nativeBuffer);
166     if (err != OHOS::GSERROR_OK) {
167         HiLog::Error(LABEL, "NativeBufferReference failed");
168         return ERR_DMA_DATA_ABNORMAL;
169     }
170     context.pixelsBuffer.buffer = static_cast<uint8_t*>(sb->GetVirAddr());
171     context.pixelsBuffer.bufferSize = count;
172     context.pixelsBuffer.context = nativeBuffer;
173     context.allocatorType = AllocatorType::DMA_ALLOC;
174     context.freeFunc = nullptr;
175     return SUCCESS;
176 #endif
177 }
178 
SetBuffer(uint64_t byteCount,DecodeContext & context)179 uint32_t SetBuffer(uint64_t byteCount, DecodeContext &context)
180 {
181 #if !defined(_WIN32) && !defined(_APPLE) && !defined(A_PLATFORM) && !defined(IOS_PLATFORM)
182         if (byteCount <= 0) {
183             HiLog::Error(LABEL, "Decode failed, byteCount is invalid value");
184             return ERR_MEDIA_INVALID_VALUE;
185         }
186         void *outputBuffer = malloc(byteCount);
187         if (outputBuffer == nullptr) {
188             HiLog::Error(LABEL, "Decode failed, alloc output buffer size:[%{public}llu] error",
189                          static_cast<unsigned long long>(byteCount));
190             return ERR_IMAGE_MALLOC_ABNORMAL;
191         }
192 #ifdef  _WIN32
193         if (memset_s(outputBuffer, 0, byteCount) != EOK) {
194             HiLog::Error(LABEL, "Decode failed, memset buffer failed", backRet);
195             free(outputBuffer);
196             outputBuffer = nullptr;
197             return ERR_IMAGE_DECODE_FAILED;
198         }
199 #else
200         if (memset_s(outputBuffer, byteCount, 0, byteCount) != EOK) {
201             HiLog::Error(LABEL, "Decode failed, memset buffer failed");
202             free(outputBuffer);
203             outputBuffer = nullptr;
204             return ERR_IMAGE_DECODE_FAILED;
205         }
206 #endif
207         context.pixelsBuffer.buffer = outputBuffer;
208         context.pixelsBuffer.bufferSize = byteCount;
209         context.pixelsBuffer.context = nullptr;
210         context.allocatorType = AllocatorType::HEAP_ALLOC;
211         context.freeFunc = nullptr;
212     context.freeFunc = nullptr;
213 #endif
214     return SUCCESS;
215 }
216 
SetBufferForPlatform(uint64_t byteCount,DecodeContext & context)217 uint32_t SetBufferForPlatform(uint64_t byteCount, DecodeContext &context)
218 {
219     if (byteCount <= 0) {
220         HiLog::Error(LABEL, "Decode failed, byteCount is invalid value");
221         return ERR_MEDIA_INVALID_VALUE;
222     }
223     void *outputBuffer = malloc(byteCount);
224     if (outputBuffer == nullptr) {
225         HiLog::Error(LABEL, "Decode failed, alloc output buffer size:[%{public}llu] error",
226                      static_cast<unsigned long long>(byteCount));
227         return ERR_IMAGE_MALLOC_ABNORMAL;
228     }
229 #ifdef _WIN32
230     if (memset_s(outputBuffer, 0, byteCount) != EOK) {
231         HiLog::Error(LABEL, "Decode failed, memset buffer failed", backRet);
232         free(outputBuffer);
233         outputBuffer = nullptr;
234         return ERR_IMAGE_DECODE_FAILED;
235     }
236 #else
237     if (memset_s(outputBuffer, byteCount, 0, byteCount) != EOK) {
238         HiLog::Error(LABEL, "Decode failed, memset buffer failed");
239         free(outputBuffer);
240         outputBuffer = nullptr;
241         return ERR_IMAGE_DECODE_FAILED;
242     }
243 #endif
244     context.pixelsBuffer.buffer = outputBuffer;
245     context.pixelsBuffer.bufferSize = byteCount;
246     context.pixelsBuffer.context = nullptr;
247     context.allocatorType = AllocatorType::HEAP_ALLOC;
248     context.freeFunc = nullptr;
249     return SUCCESS;
250 }
251 
SetContextPixelsBuffer(uint64_t byteCount,DecodeContext & context,SkImageInfo & dstInfo)252 uint32_t BmpDecoder::SetContextPixelsBuffer(uint64_t byteCount, DecodeContext &context, SkImageInfo &dstInfo)
253 {
254 #if !defined(_WIN32) && !defined(_APPLE) && !defined(A_PLATFORM) && !defined(IOS_PLATFORM)
255     if (context.allocatorType == Media::AllocatorType::SHARE_MEM_ALLOC) {
256         uint32_t res = SetShareMemBuffer(byteCount, context);
257         if (res != SUCCESS) {
258             return res;
259         }
260     } else if (context.allocatorType == Media::AllocatorType::DMA_ALLOC) {
261         uint32_t res = DmaMemAlloc(byteCount, context, dstInfo);
262         if (res != SUCCESS) {
263             return res;
264         }
265     } else {
266         uint32_t res = SetBuffer(byteCount, context);
267         if (res != SUCCESS) {
268             return res;
269         }
270     }
271 #else
272     uint32_t res = SetBufferForPlatform(byteCount, context);
273     if (res != SUCCESS) {
274         return res;
275     }
276 #endif
277     return SUCCESS;
278 }
279 
Decode(uint32_t index,DecodeContext & context)280 uint32_t BmpDecoder::Decode(uint32_t index, DecodeContext &context)
281 {
282     if (index >= BMP_IMAGE_NUM) {
283         HiLog::Error(LABEL, "Decode failed, invalid index:%{public}u, range:%{public}u", index, BMP_IMAGE_NUM);
284         return ERR_IMAGE_INVALID_PARAMETER;
285     }
286     if (codec_ == nullptr) {
287         HiLog::Error(LABEL, "Decode failed, codec is null");
288         return ERR_IMAGE_DECODE_FAILED;
289     }
290     if (state_ != BmpDecodingState::IMAGE_DECODING) {
291         HiLog::Error(LABEL, "Decode failed, invalid state %{public}d", state_);
292         return ERR_MEDIA_INVALID_OPERATION;
293     }
294 
295     SkImageInfo dstInfo = info_.makeColorType(desireColor_);
296     if (ImageUtils::CheckMulOverflow(dstInfo.width(), dstInfo.height(), dstInfo.bytesPerPixel())) {
297         HiLog::Error(LABEL, "Decode failed, width:%{public}d, height:%{public}d is too large",
298                      dstInfo.width(), dstInfo.height());
299         return ERR_IMAGE_DECODE_FAILED;
300     }
301     if (context.pixelsBuffer.buffer == nullptr) {
302         uint64_t byteCount = static_cast<uint64_t>(dstInfo.height()) * dstInfo.width() * dstInfo.bytesPerPixel();
303         uint32_t res = SetContextPixelsBuffer(byteCount, context, dstInfo);
304         if (res != SUCCESS) {
305             return res;
306         }
307     }
308     uint8_t *dstBuffer = static_cast<uint8_t *>(context.pixelsBuffer.buffer);
309     size_t rowBytes = dstInfo.width() * dstInfo.bytesPerPixel();
310     SkCodec::Result ret = codec_->getPixels(dstInfo, dstBuffer, rowBytes);
311     if (ret != SkCodec::kSuccess) {
312         HiLog::Error(LABEL, "Decode failed, get pixels failed, ret=%{public}d", ret);
313         state_ = BmpDecodingState::IMAGE_ERROR;
314         return ERR_IMAGE_DECODE_ABNORMAL;
315     }
316     state_ = BmpDecodingState::IMAGE_DECODED;
317     return SUCCESS;
318 }
319 
PromoteIncrementalDecode(uint32_t index,ProgDecodeContext & context)320 uint32_t BmpDecoder::PromoteIncrementalDecode(uint32_t index, ProgDecodeContext &context)
321 {
322     // currently not support increment decode
323     return ERR_IMAGE_DATA_UNSUPPORT;
324 }
325 
DecodeHeader()326 bool BmpDecoder::DecodeHeader()
327 {
328     codec_ = SkCodec::MakeFromStream(make_unique<BmpStream>(stream_));
329     if (codec_ == nullptr) {
330         HiLog::Error(LABEL, "create codec from stream failed");
331         return false;
332     }
333     info_ = codec_->getInfo();
334     return true;
335 }
336 
ConvertToAlphaType(SkAlphaType alphaType)337 PlAlphaType BmpDecoder::ConvertToAlphaType(SkAlphaType alphaType)
338 {
339     switch (alphaType) {
340         case kOpaque_SkAlphaType:
341             return PlAlphaType::IMAGE_ALPHA_TYPE_OPAQUE;
342         case kPremul_SkAlphaType:
343             return PlAlphaType::IMAGE_ALPHA_TYPE_PREMUL;
344         case kUnpremul_SkAlphaType:
345             return PlAlphaType::IMAGE_ALPHA_TYPE_UNPREMUL;
346         default:
347             HiLog::Error(LABEL, "known alpha type:%{public}d", alphaType);
348             break;
349     }
350     return PlAlphaType::IMAGE_ALPHA_TYPE_UNKNOWN;
351 }
352 
ConvertToColorType(PlPixelFormat format,PlPixelFormat & outputFormat)353 SkColorType BmpDecoder::ConvertToColorType(PlPixelFormat format, PlPixelFormat &outputFormat)
354 {
355     switch (format) {
356         case PlPixelFormat::UNKNOWN:
357         case PlPixelFormat::RGBA_8888: {
358             outputFormat = PlPixelFormat::RGBA_8888;
359             return kRGBA_8888_SkColorType;
360         }
361         case PlPixelFormat::BGRA_8888: {
362             outputFormat = PlPixelFormat::BGRA_8888;
363             return kBGRA_8888_SkColorType;
364         }
365         case PlPixelFormat::ALPHA_8: {
366             SkColorType colorType = info_.colorType();
367             if (colorType == kAlpha_8_SkColorType || (colorType == kGray_8_SkColorType && info_.isOpaque())) {
368                 outputFormat = PlPixelFormat::ALPHA_8;
369                 return kAlpha_8_SkColorType;
370             }
371             break;
372         }
373         case PlPixelFormat::RGB_565: {
374             if (info_.isOpaque()) {
375                 outputFormat = PlPixelFormat::RGB_565;
376                 return kRGB_565_SkColorType;
377             }
378             break;
379         }
380         default: {
381             break;
382         }
383     }
384     HiLog::Debug(LABEL, "unsupported convert to format:%{public}d, set default RGBA", format);
385     outputFormat = PlPixelFormat::RGBA_8888;
386     return kRGBA_8888_SkColorType;
387 }
388 } // namespace ImagePlugin
389 } // namespace OHOS
390