1a3e0fd82Sopenharmony_ci/*
2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License.
5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at
6a3e0fd82Sopenharmony_ci *
7a3e0fd82Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8a3e0fd82Sopenharmony_ci *
9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and
13a3e0fd82Sopenharmony_ci * limitations under the License.
14a3e0fd82Sopenharmony_ci */
15a3e0fd82Sopenharmony_ci
16a3e0fd82Sopenharmony_ci#include "gfx_utils/file.h"
17a3e0fd82Sopenharmony_ci#include "gfx_utils/mem_api.h"
18a3e0fd82Sopenharmony_ci#include "imgdecode/file_img_decoder.h"
19a3e0fd82Sopenharmony_ci#include "imgdecode/image_load.h"
20a3e0fd82Sopenharmony_ci
21a3e0fd82Sopenharmony_cinamespace OHOS {
22a3e0fd82Sopenharmony_ciFileImgDecoder& FileImgDecoder::GetInstance()
23a3e0fd82Sopenharmony_ci{
24a3e0fd82Sopenharmony_ci    static FileImgDecoder instance;
25a3e0fd82Sopenharmony_ci    return instance;
26a3e0fd82Sopenharmony_ci}
27a3e0fd82Sopenharmony_ci
28a3e0fd82Sopenharmony_ciRetCode FileImgDecoder::Open(ImgResDsc& dsc)
29a3e0fd82Sopenharmony_ci{
30a3e0fd82Sopenharmony_ci#ifdef _WIN32
31a3e0fd82Sopenharmony_ci    int32_t fd = open(dsc.path, O_RDONLY | O_BINARY);
32a3e0fd82Sopenharmony_ci#else
33a3e0fd82Sopenharmony_ci    int32_t fd = open(dsc.path, O_RDONLY);
34a3e0fd82Sopenharmony_ci#endif
35a3e0fd82Sopenharmony_ci    if (fd == -1) {
36a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
37a3e0fd82Sopenharmony_ci    }
38a3e0fd82Sopenharmony_ci    dsc.fd = fd;
39a3e0fd82Sopenharmony_ci
40a3e0fd82Sopenharmony_ci    dsc.imgInfo.data = nullptr;
41a3e0fd82Sopenharmony_ci    dsc.inCache_ = false;
42a3e0fd82Sopenharmony_ci    uint8_t colorMode = dsc.imgInfo.header.colorMode;
43a3e0fd82Sopenharmony_ci    if (IsImgValidMode(colorMode)) {
44a3e0fd82Sopenharmony_ci        return RetCode::OK;
45a3e0fd82Sopenharmony_ci    } else {
46a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
47a3e0fd82Sopenharmony_ci    }
48a3e0fd82Sopenharmony_ci}
49a3e0fd82Sopenharmony_ci
50a3e0fd82Sopenharmony_ciRetCode FileImgDecoder::Close(ImgResDsc& dsc)
51a3e0fd82Sopenharmony_ci{
52a3e0fd82Sopenharmony_ci    if (dsc.imgInfo.data != nullptr) {
53a3e0fd82Sopenharmony_ci        ImageCacheFree(dsc.imgInfo);
54a3e0fd82Sopenharmony_ci        dsc.imgInfo.data = nullptr;
55a3e0fd82Sopenharmony_ci    }
56a3e0fd82Sopenharmony_ci    if (dsc.fd && (dsc.fd != -1)) {
57a3e0fd82Sopenharmony_ci        close(dsc.fd);
58a3e0fd82Sopenharmony_ci        dsc.fd = -1;
59a3e0fd82Sopenharmony_ci    }
60a3e0fd82Sopenharmony_ci
61a3e0fd82Sopenharmony_ci    return RetCode::OK;
62a3e0fd82Sopenharmony_ci}
63a3e0fd82Sopenharmony_ci
64a3e0fd82Sopenharmony_ciRetCode FileImgDecoder::GetHeader(ImgResDsc& dsc)
65a3e0fd82Sopenharmony_ci{
66a3e0fd82Sopenharmony_ci    int32_t fd;
67a3e0fd82Sopenharmony_ci    int32_t readCount;
68a3e0fd82Sopenharmony_ci#ifdef _WIN32
69a3e0fd82Sopenharmony_ci    fd = open(dsc.path, O_BINARY);
70a3e0fd82Sopenharmony_ci#else
71a3e0fd82Sopenharmony_ci    fd = open(dsc.path, O_RDONLY);
72a3e0fd82Sopenharmony_ci#endif
73a3e0fd82Sopenharmony_ci    if (fd == -1) {
74a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
75a3e0fd82Sopenharmony_ci    }
76a3e0fd82Sopenharmony_ci
77a3e0fd82Sopenharmony_ci    readCount = read(fd, &dsc.imgInfo.header, sizeof(ImageHeader));
78a3e0fd82Sopenharmony_ci    close(fd);
79a3e0fd82Sopenharmony_ci    dsc.fd = -1;
80a3e0fd82Sopenharmony_ci    if (readCount != sizeof(ImageHeader)) {
81a3e0fd82Sopenharmony_ci        dsc.imgInfo.header.width = 0;
82a3e0fd82Sopenharmony_ci        dsc.imgInfo.header.height = 0;
83a3e0fd82Sopenharmony_ci        dsc.imgInfo.header.colorMode = UNKNOWN;
84a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
85a3e0fd82Sopenharmony_ci    }
86a3e0fd82Sopenharmony_ci
87a3e0fd82Sopenharmony_ci    return RetCode::OK;
88a3e0fd82Sopenharmony_ci}
89a3e0fd82Sopenharmony_ci
90a3e0fd82Sopenharmony_ciRetCode FileImgDecoder::ReadLine(ImgResDsc& dsc, const Point& start, int16_t len, uint8_t* buf)
91a3e0fd82Sopenharmony_ci{
92a3e0fd82Sopenharmony_ci    if (IsImgValidMode(dsc.imgInfo.header.colorMode)) {
93a3e0fd82Sopenharmony_ci        return ReadLineTrueColor(dsc, start, len, buf);
94a3e0fd82Sopenharmony_ci    }
95a3e0fd82Sopenharmony_ci    return RetCode::FAIL;
96a3e0fd82Sopenharmony_ci}
97a3e0fd82Sopenharmony_ci
98a3e0fd82Sopenharmony_ciRetCode FileImgDecoder::ReadToCache(ImgResDsc& dsc)
99a3e0fd82Sopenharmony_ci{
100a3e0fd82Sopenharmony_ci    struct stat info;
101a3e0fd82Sopenharmony_ci    if (!dsc.inCache_) {
102a3e0fd82Sopenharmony_ci        lseek(dsc.fd, 0, SEEK_SET);
103a3e0fd82Sopenharmony_ci        int32_t readCount = read(dsc.fd, &dsc.imgInfo.header, sizeof(ImageHeader));
104a3e0fd82Sopenharmony_ci        if (readCount != sizeof(ImageHeader)) {
105a3e0fd82Sopenharmony_ci            return RetCode::FAIL;
106a3e0fd82Sopenharmony_ci        }
107a3e0fd82Sopenharmony_ci
108a3e0fd82Sopenharmony_ci        int32_t ret = fstat(dsc.fd, &info);
109a3e0fd82Sopenharmony_ci        if (ret != 0) {
110a3e0fd82Sopenharmony_ci            return RetCode::FAIL;
111a3e0fd82Sopenharmony_ci        }
112a3e0fd82Sopenharmony_ci        uint32_t pxCount = info.st_size - readCount;
113a3e0fd82Sopenharmony_ci        if (dsc.imgInfo.data != nullptr) {
114a3e0fd82Sopenharmony_ci            ImageCacheFree(dsc.imgInfo);
115a3e0fd82Sopenharmony_ci            dsc.imgInfo.data = nullptr;
116a3e0fd82Sopenharmony_ci        }
117a3e0fd82Sopenharmony_ci
118a3e0fd82Sopenharmony_ci        bool readSuccess = false;
119a3e0fd82Sopenharmony_ci        if (dsc.imgInfo.header.compressMode != COMPRESS_MODE_NONE) {
120a3e0fd82Sopenharmony_ci            readSuccess = ImageLoad::GetImageInfo(dsc.fd, pxCount, dsc.imgInfo);
121a3e0fd82Sopenharmony_ci        } else {
122a3e0fd82Sopenharmony_ci            dsc.imgInfo.dataSize = pxCount;
123a3e0fd82Sopenharmony_ci            dsc.imgInfo.data = reinterpret_cast<uint8_t*>(ImageCacheMalloc(dsc.imgInfo));
124a3e0fd82Sopenharmony_ci            if (dsc.imgInfo.data == nullptr) {
125a3e0fd82Sopenharmony_ci                return RetCode::OK;
126a3e0fd82Sopenharmony_ci            }
127a3e0fd82Sopenharmony_ci            uint8_t* tmp = const_cast<uint8_t*>(dsc.imgInfo.data);
128a3e0fd82Sopenharmony_ci            readSuccess = (static_cast<int32_t>(pxCount) == read(dsc.fd, reinterpret_cast<void*>(tmp), pxCount));
129a3e0fd82Sopenharmony_ci        }
130a3e0fd82Sopenharmony_ci        if (!readSuccess) {
131a3e0fd82Sopenharmony_ci            ImageCacheFree(dsc.imgInfo);
132a3e0fd82Sopenharmony_ci            dsc.imgInfo.data = nullptr;
133a3e0fd82Sopenharmony_ci            dsc.imgInfo.dataSize = 0;
134a3e0fd82Sopenharmony_ci            close(dsc.fd);
135a3e0fd82Sopenharmony_ci            dsc.fd = -1;
136a3e0fd82Sopenharmony_ci            return RetCode::OK;
137a3e0fd82Sopenharmony_ci        }
138a3e0fd82Sopenharmony_ci        dsc.inCache_ = true;
139a3e0fd82Sopenharmony_ci        close(dsc.fd);
140a3e0fd82Sopenharmony_ci        dsc.fd = -1;
141a3e0fd82Sopenharmony_ci    }
142a3e0fd82Sopenharmony_ci
143a3e0fd82Sopenharmony_ci    return RetCode::OK;
144a3e0fd82Sopenharmony_ci}
145a3e0fd82Sopenharmony_ci
146a3e0fd82Sopenharmony_ciRetCode FileImgDecoder::ReadLineTrueColor(ImgResDsc& dsc, const Point& start, int16_t len, uint8_t* buf)
147a3e0fd82Sopenharmony_ci{
148a3e0fd82Sopenharmony_ci    uint8_t pxSizeInBit = DrawUtils::GetPxSizeByColorMode(dsc.imgInfo.header.colorMode);
149a3e0fd82Sopenharmony_ci    off_t res;
150a3e0fd82Sopenharmony_ci
151a3e0fd82Sopenharmony_ci    uint32_t pos = ((start.y * dsc.imgInfo.header.width + start.x) * pxSizeInBit) >> BYTE_TO_BIT_SHIFT;
152a3e0fd82Sopenharmony_ci    pos += sizeof(ImageHeader); /* Skip the header */
153a3e0fd82Sopenharmony_ci    res = lseek(dsc.fd, pos, SEEK_SET);
154a3e0fd82Sopenharmony_ci    if (res == -1) {
155a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
156a3e0fd82Sopenharmony_ci    }
157a3e0fd82Sopenharmony_ci    uint32_t btr = len * (pxSizeInBit >> BYTE_TO_BIT_SHIFT);
158a3e0fd82Sopenharmony_ci    int32_t br = read(dsc.fd, buf, btr);
159a3e0fd82Sopenharmony_ci    if ((br == -1) || (btr != static_cast<uint32_t>(br))) {
160a3e0fd82Sopenharmony_ci        return RetCode::FAIL;
161a3e0fd82Sopenharmony_ci    }
162a3e0fd82Sopenharmony_ci
163a3e0fd82Sopenharmony_ci    return RetCode::OK;
164a3e0fd82Sopenharmony_ci}
165a3e0fd82Sopenharmony_ci} // namespace OHOS
166