Lliuyuxiang-bearchmod 755->644
2d5b1fa3创建于 2022年3月26日历史提交
/*
 * 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); /* Skip the header */
    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;
}
} // namespace OHOS