1/* 2 * Copyright (c) 2020-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 "gfx_utils/file.h" 17#include "gfx_utils/mem_api.h" 18#include "imgdecode/file_img_decoder.h" 19#include "imgdecode/image_load.h" 20 21namespace OHOS { 22FileImgDecoder& FileImgDecoder::GetInstance() 23{ 24 static FileImgDecoder instance; 25 return instance; 26} 27 28RetCode FileImgDecoder::Open(ImgResDsc& dsc) 29{ 30#ifdef _WIN32 31 int32_t fd = open(dsc.path, O_RDONLY | O_BINARY); 32#else 33 int32_t fd = open(dsc.path, O_RDONLY); 34#endif 35 if (fd == -1) { 36 return RetCode::FAIL; 37 } 38 dsc.fd = fd; 39 40 dsc.imgInfo.data = nullptr; 41 dsc.inCache_ = false; 42 uint8_t colorMode = dsc.imgInfo.header.colorMode; 43 if (IsImgValidMode(colorMode)) { 44 return RetCode::OK; 45 } else { 46 return RetCode::FAIL; 47 } 48} 49 50RetCode FileImgDecoder::Close(ImgResDsc& dsc) 51{ 52 if (dsc.imgInfo.data != nullptr) { 53 ImageCacheFree(dsc.imgInfo); 54 dsc.imgInfo.data = nullptr; 55 } 56 if (dsc.fd && (dsc.fd != -1)) { 57 close(dsc.fd); 58 dsc.fd = -1; 59 } 60 61 return RetCode::OK; 62} 63 64RetCode FileImgDecoder::GetHeader(ImgResDsc& dsc) 65{ 66 int32_t fd; 67 int32_t readCount; 68#ifdef _WIN32 69 fd = open(dsc.path, O_BINARY); 70#else 71 fd = open(dsc.path, O_RDONLY); 72#endif 73 if (fd == -1) { 74 return RetCode::FAIL; 75 } 76 77 readCount = read(fd, &dsc.imgInfo.header, sizeof(ImageHeader)); 78 close(fd); 79 dsc.fd = -1; 80 if (readCount != sizeof(ImageHeader)) { 81 dsc.imgInfo.header.width = 0; 82 dsc.imgInfo.header.height = 0; 83 dsc.imgInfo.header.colorMode = UNKNOWN; 84 return RetCode::FAIL; 85 } 86 87 return RetCode::OK; 88} 89 90RetCode FileImgDecoder::ReadLine(ImgResDsc& dsc, const Point& start, int16_t len, uint8_t* buf) 91{ 92 if (IsImgValidMode(dsc.imgInfo.header.colorMode)) { 93 return ReadLineTrueColor(dsc, start, len, buf); 94 } 95 return RetCode::FAIL; 96} 97 98RetCode FileImgDecoder::ReadToCache(ImgResDsc& dsc) 99{ 100 struct stat info; 101 if (!dsc.inCache_) { 102 lseek(dsc.fd, 0, SEEK_SET); 103 int32_t readCount = read(dsc.fd, &dsc.imgInfo.header, sizeof(ImageHeader)); 104 if (readCount != sizeof(ImageHeader)) { 105 return RetCode::FAIL; 106 } 107 108 int32_t ret = fstat(dsc.fd, &info); 109 if (ret != 0) { 110 return RetCode::FAIL; 111 } 112 uint32_t pxCount = info.st_size - readCount; 113 if (dsc.imgInfo.data != nullptr) { 114 ImageCacheFree(dsc.imgInfo); 115 dsc.imgInfo.data = nullptr; 116 } 117 118 bool readSuccess = false; 119 if (dsc.imgInfo.header.compressMode != COMPRESS_MODE_NONE) { 120 readSuccess = ImageLoad::GetImageInfo(dsc.fd, pxCount, dsc.imgInfo); 121 } else { 122 dsc.imgInfo.dataSize = pxCount; 123 dsc.imgInfo.data = reinterpret_cast<uint8_t*>(ImageCacheMalloc(dsc.imgInfo)); 124 if (dsc.imgInfo.data == nullptr) { 125 return RetCode::OK; 126 } 127 uint8_t* tmp = const_cast<uint8_t*>(dsc.imgInfo.data); 128 readSuccess = (static_cast<int32_t>(pxCount) == read(dsc.fd, reinterpret_cast<void*>(tmp), pxCount)); 129 } 130 if (!readSuccess) { 131 ImageCacheFree(dsc.imgInfo); 132 dsc.imgInfo.data = nullptr; 133 dsc.imgInfo.dataSize = 0; 134 close(dsc.fd); 135 dsc.fd = -1; 136 return RetCode::OK; 137 } 138 dsc.inCache_ = true; 139 close(dsc.fd); 140 dsc.fd = -1; 141 } 142 143 return RetCode::OK; 144} 145 146RetCode FileImgDecoder::ReadLineTrueColor(ImgResDsc& dsc, const Point& start, int16_t len, uint8_t* buf) 147{ 148 uint8_t pxSizeInBit = DrawUtils::GetPxSizeByColorMode(dsc.imgInfo.header.colorMode); 149 off_t res; 150 151 uint32_t pos = ((start.y * dsc.imgInfo.header.width + start.x) * pxSizeInBit) >> BYTE_TO_BIT_SHIFT; 152 pos += sizeof(ImageHeader); /* Skip the header */ 153 res = lseek(dsc.fd, pos, SEEK_SET); 154 if (res == -1) { 155 return RetCode::FAIL; 156 } 157 uint32_t btr = len * (pxSizeInBit >> BYTE_TO_BIT_SHIFT); 158 int32_t br = read(dsc.fd, buf, btr); 159 if ((br == -1) || (btr != static_cast<uint32_t>(br))) { 160 return RetCode::FAIL; 161 } 162 163 return RetCode::OK; 164} 165} // namespace OHOS 166