* Copyright (c) 2020-2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "gfx_utils/file.h"
#include "gfx_utils/mem_api.h"
#include "imgdecode/file_img_decoder.h"
#include "imgdecode/image_load.h"
namespace OHOS {
FileImgDecoder& FileImgDecoder::GetInstance()
{
static FileImgDecoder instance;
return instance;
}
RetCode FileImgDecoder::Open(ImgResDsc& dsc)
{
#ifdef _WIN32
int32_t fd = open(dsc.path, O_RDONLY | O_BINARY);
#else
int32_t fd = open(dsc.path, O_RDONLY);
#endif
if (fd == -1) {
return RetCode::FAIL;
}
dsc.fd = fd;
dsc.imgInfo.data = nullptr;
dsc.inCache_ = false;
uint8_t colorMode = dsc.imgInfo.header.colorMode;
if (IsImgValidMode(colorMode)) {
return RetCode::OK;
} else {
return RetCode::FAIL;
}
}
RetCode FileImgDecoder::Close(ImgResDsc& dsc)
{
if (dsc.imgInfo.data != nullptr) {
ImageCacheFree(dsc.imgInfo);
dsc.imgInfo.data = nullptr;
}
if (dsc.fd && (dsc.fd != -1)) {
close(dsc.fd);
dsc.fd = -1;
}
return RetCode::OK;
}
RetCode FileImgDecoder::GetHeader(ImgResDsc& dsc)
{
int32_t fd;
int32_t readCount;
#ifdef _WIN32
fd = open(dsc.path, O_BINARY);
#else
fd = open(dsc.path, O_RDONLY);
#endif
if (fd == -1) {
return RetCode::FAIL;
}
readCount = read(fd, &dsc.imgInfo.header, sizeof(ImageHeader));
close(fd);
dsc.fd = -1;
if (readCount != sizeof(ImageHeader)) {
dsc.imgInfo.header.width = 0;
dsc.imgInfo.header.height = 0;
dsc.imgInfo.header.colorMode = UNKNOWN;
return RetCode::FAIL;
}
return RetCode::OK;
}
RetCode FileImgDecoder::ReadLine(ImgResDsc& dsc, const Point& start, int16_t len, uint8_t* buf)
{
if (IsImgValidMode(dsc.imgInfo.header.colorMode)) {
return ReadLineTrueColor(dsc, start, len, buf);
}
return RetCode::FAIL;
}
RetCode FileImgDecoder::ReadToCache(ImgResDsc& dsc)
{
struct stat info;
if (!dsc.inCache_) {
lseek(dsc.fd, 0, SEEK_SET);
int32_t readCount = read(dsc.fd, &dsc.imgInfo.header, sizeof(ImageHeader));
if (readCount != sizeof(ImageHeader)) {
return RetCode::FAIL;
}
int32_t ret = fstat(dsc.fd, &info);
if (ret != 0) {
return RetCode::FAIL;
}
uint32_t pxCount = info.st_size - readCount;
if (dsc.imgInfo.data != nullptr) {
ImageCacheFree(dsc.imgInfo);
dsc.imgInfo.data = nullptr;
}
bool readSuccess = false;
if (dsc.imgInfo.header.compressMode != COMPRESS_MODE_NONE) {
readSuccess = ImageLoad::GetImageInfo(dsc.fd, pxCount, dsc.imgInfo);
} else {
dsc.imgInfo.dataSize = pxCount;
dsc.imgInfo.data = reinterpret_cast<uint8_t*>(ImageCacheMalloc(dsc.imgInfo));
if (dsc.imgInfo.data == nullptr) {
return RetCode::OK;
}
uint8_t* tmp = const_cast<uint8_t*>(dsc.imgInfo.data);
readSuccess = (static_cast<int32_t>(pxCount) == read(dsc.fd, reinterpret_cast<void*>(tmp), pxCount));
}
if (!readSuccess) {
ImageCacheFree(dsc.imgInfo);
dsc.imgInfo.data = nullptr;
dsc.imgInfo.dataSize = 0;
close(dsc.fd);
dsc.fd = -1;
return RetCode::OK;
}
dsc.inCache_ = true;
close(dsc.fd);
dsc.fd = -1;
}
return RetCode::OK;
}
RetCode FileImgDecoder::ReadLineTrueColor(ImgResDsc& dsc, const Point& start, int16_t len, uint8_t* buf)
{
uint8_t pxSizeInBit = DrawUtils::GetPxSizeByColorMode(dsc.imgInfo.header.colorMode);
off_t res;
uint32_t pos = ((start.y * dsc.imgInfo.header.width + start.x) * pxSizeInBit) >> BYTE_TO_BIT_SHIFT;
pos += sizeof(ImageHeader);
res = lseek(dsc.fd, pos, SEEK_SET);
if (res == -1) {
return RetCode::FAIL;
}
uint32_t btr = len * (pxSizeInBit >> BYTE_TO_BIT_SHIFT);
int32_t br = read(dsc.fd, buf, btr);
if ((br == -1) || (btr != static_cast<uint32_t>(br))) {
return RetCode::FAIL;
}
return RetCode::OK;
}
}