1a3e0fd82Sopenharmony_ci/* 2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2022 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 "common/image.h" 17a3e0fd82Sopenharmony_ci#include "common/image_decode_ability.h" 18a3e0fd82Sopenharmony_ci#include "draw/draw_image.h" 19a3e0fd82Sopenharmony_ci#include "gfx_utils/file.h" 20a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_log.h" 21a3e0fd82Sopenharmony_ci#include "imgdecode/cache_manager.h" 22a3e0fd82Sopenharmony_ci#if ENABLE_JPEG 23a3e0fd82Sopenharmony_ci#include "jpeglib.h" 24a3e0fd82Sopenharmony_ci#endif 25a3e0fd82Sopenharmony_ci#if ENABLE_PNG 26a3e0fd82Sopenharmony_ci#include "png.h" 27a3e0fd82Sopenharmony_ci#endif 28a3e0fd82Sopenharmony_ci#include "securec.h" 29a3e0fd82Sopenharmony_ci 30a3e0fd82Sopenharmony_cinamespace OHOS { 31a3e0fd82Sopenharmony_ciImage::Image() : imageInfo_(nullptr), path_(nullptr), srcType_(IMG_SRC_UNKNOWN), mallocFlag_(false) {} 32a3e0fd82Sopenharmony_ci 33a3e0fd82Sopenharmony_ciImage::~Image() 34a3e0fd82Sopenharmony_ci{ 35a3e0fd82Sopenharmony_ci if (srcType_ == IMG_SRC_FILE) { 36a3e0fd82Sopenharmony_ci CacheManager::GetInstance().Close(path_); 37a3e0fd82Sopenharmony_ci } 38a3e0fd82Sopenharmony_ci 39a3e0fd82Sopenharmony_ci ReInitImageInfo(nullptr, false); 40a3e0fd82Sopenharmony_ci 41a3e0fd82Sopenharmony_ci if (path_ != nullptr) { 42a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(path_)); 43a3e0fd82Sopenharmony_ci path_ = nullptr; 44a3e0fd82Sopenharmony_ci } 45a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_UNKNOWN; 46a3e0fd82Sopenharmony_ci} 47a3e0fd82Sopenharmony_ci 48a3e0fd82Sopenharmony_civoid Image::GetHeader(ImageHeader& header) const 49a3e0fd82Sopenharmony_ci{ 50a3e0fd82Sopenharmony_ci if ((srcType_ == IMG_SRC_VARIABLE) && (imageInfo_ != nullptr)) { 51a3e0fd82Sopenharmony_ci header = imageInfo_->header; 52a3e0fd82Sopenharmony_ci } else if ((srcType_ == IMG_SRC_FILE) && (path_ != nullptr)) { 53a3e0fd82Sopenharmony_ci CacheManager::GetInstance().GetImageHeader(path_, header); 54a3e0fd82Sopenharmony_ci } 55a3e0fd82Sopenharmony_ci} 56a3e0fd82Sopenharmony_ci 57a3e0fd82Sopenharmony_ci#if ENABLE_JPEG || ENABLE_PNG 58a3e0fd82Sopenharmony_ciOHOS::Image::ImageType Image::CheckImgType(const char* src) 59a3e0fd82Sopenharmony_ci{ 60a3e0fd82Sopenharmony_ci char buf[IMG_BYTES_TO_CHECK] = {0}; 61a3e0fd82Sopenharmony_ci#ifdef _WIN32 62a3e0fd82Sopenharmony_ci int32_t fd = open(src, O_RDONLY | O_BINARY); 63a3e0fd82Sopenharmony_ci#else 64a3e0fd82Sopenharmony_ci int32_t fd = open(src, O_RDONLY); 65a3e0fd82Sopenharmony_ci#endif 66a3e0fd82Sopenharmony_ci if (fd < 0) { 67a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("can't open %s\n", src); 68a3e0fd82Sopenharmony_ci return IMG_UNKNOWN; 69a3e0fd82Sopenharmony_ci } 70a3e0fd82Sopenharmony_ci if (read(fd, buf, IMG_BYTES_TO_CHECK) != IMG_BYTES_TO_CHECK) { 71a3e0fd82Sopenharmony_ci close(fd); 72a3e0fd82Sopenharmony_ci return IMG_UNKNOWN; 73a3e0fd82Sopenharmony_ci } 74a3e0fd82Sopenharmony_ci close(fd); 75a3e0fd82Sopenharmony_ci#if ENABLE_PNG 76a3e0fd82Sopenharmony_ci if (!png_sig_cmp(reinterpret_cast<png_const_bytep>(buf), 0, IMG_BYTES_TO_CHECK)) { 77a3e0fd82Sopenharmony_ci return IMG_PNG; 78a3e0fd82Sopenharmony_ci } 79a3e0fd82Sopenharmony_ci#endif 80a3e0fd82Sopenharmony_ci#if ENABLE_JPEG 81a3e0fd82Sopenharmony_ci // 0xFF 0xD8: JPEG file's header 82a3e0fd82Sopenharmony_ci if ((static_cast<uint8_t>(buf[0]) == 0xFF) && (static_cast<uint8_t>(buf[1]) == 0xD8)) { 83a3e0fd82Sopenharmony_ci return IMG_JPEG; 84a3e0fd82Sopenharmony_ci } 85a3e0fd82Sopenharmony_ci#endif 86a3e0fd82Sopenharmony_ci if ((static_cast<uint8_t>(buf[0]) == 0x47) && (static_cast<uint8_t>(buf[1]) == 0x49) && 87a3e0fd82Sopenharmony_ci (static_cast<uint8_t>(buf[2]) == 0x46)) { // 2: array index of GIF file's header 88a3e0fd82Sopenharmony_ci return IMG_GIF; 89a3e0fd82Sopenharmony_ci } 90a3e0fd82Sopenharmony_ci return IMG_UNKNOWN; 91a3e0fd82Sopenharmony_ci} 92a3e0fd82Sopenharmony_ci#endif 93a3e0fd82Sopenharmony_ci 94a3e0fd82Sopenharmony_cibool Image::SetStandardSrc(const char* src) 95a3e0fd82Sopenharmony_ci{ 96a3e0fd82Sopenharmony_ci if (src == nullptr) { 97a3e0fd82Sopenharmony_ci return false; 98a3e0fd82Sopenharmony_ci } 99a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_UNKNOWN; 100a3e0fd82Sopenharmony_ci 101a3e0fd82Sopenharmony_ci const char* ptr = strrchr(src, '.'); 102a3e0fd82Sopenharmony_ci if (ptr == nullptr) { 103a3e0fd82Sopenharmony_ci return false; 104a3e0fd82Sopenharmony_ci } 105a3e0fd82Sopenharmony_ci 106a3e0fd82Sopenharmony_ci#if ENABLE_JPEG || ENABLE_PNG 107a3e0fd82Sopenharmony_ci ImageType imageType = CheckImgType(src); 108a3e0fd82Sopenharmony_ci#if ENABLE_PNG 109a3e0fd82Sopenharmony_ci if (imageType == IMG_PNG) { 110a3e0fd82Sopenharmony_ci return SetPNGSrc(src); 111a3e0fd82Sopenharmony_ci } 112a3e0fd82Sopenharmony_ci#endif 113a3e0fd82Sopenharmony_ci#if ENABLE_JPEG 114a3e0fd82Sopenharmony_ci if (imageType == IMG_JPEG) { 115a3e0fd82Sopenharmony_ci return SetJPEGSrc(src); 116a3e0fd82Sopenharmony_ci } 117a3e0fd82Sopenharmony_ci#endif 118a3e0fd82Sopenharmony_ci#endif 119a3e0fd82Sopenharmony_ci 120a3e0fd82Sopenharmony_ci size_t strLen = strlen(src) + 1; 121a3e0fd82Sopenharmony_ci char* imagePath = static_cast<char*>(UIMalloc(static_cast<uint32_t>(strLen))); 122a3e0fd82Sopenharmony_ci if (imagePath == nullptr) { 123a3e0fd82Sopenharmony_ci return false; 124a3e0fd82Sopenharmony_ci } 125a3e0fd82Sopenharmony_ci 126a3e0fd82Sopenharmony_ci if (strcpy_s(imagePath, strLen, src) != EOK) { 127a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(imagePath)); 128a3e0fd82Sopenharmony_ci imagePath = nullptr; 129a3e0fd82Sopenharmony_ci return false; 130a3e0fd82Sopenharmony_ci } 131a3e0fd82Sopenharmony_ci path_ = imagePath; 132a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_FILE; 133a3e0fd82Sopenharmony_ci return true; 134a3e0fd82Sopenharmony_ci} 135a3e0fd82Sopenharmony_ci 136a3e0fd82Sopenharmony_cibool Image::SetLiteSrc(const char* src) 137a3e0fd82Sopenharmony_ci{ 138a3e0fd82Sopenharmony_ci if (src == nullptr) { 139a3e0fd82Sopenharmony_ci return false; 140a3e0fd82Sopenharmony_ci } 141a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_UNKNOWN; 142a3e0fd82Sopenharmony_ci 143a3e0fd82Sopenharmony_ci const char* ptr = strrchr(src, '.'); 144a3e0fd82Sopenharmony_ci if (ptr == nullptr) { 145a3e0fd82Sopenharmony_ci return false; 146a3e0fd82Sopenharmony_ci } 147a3e0fd82Sopenharmony_ci 148a3e0fd82Sopenharmony_ci const char* suffixName = ".bin"; 149a3e0fd82Sopenharmony_ci size_t strLen = strlen(src) + strlen(suffixName) + 1; 150a3e0fd82Sopenharmony_ci char* imagePath = static_cast<char*>(UIMalloc(static_cast<uint32_t>(strLen))); 151a3e0fd82Sopenharmony_ci if (imagePath == nullptr) { 152a3e0fd82Sopenharmony_ci return false; 153a3e0fd82Sopenharmony_ci } 154a3e0fd82Sopenharmony_ci if (IsImgValid(ptr)) { 155a3e0fd82Sopenharmony_ci if (memcpy_s(imagePath, strLen, src, strLen) != EOK) { 156a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(imagePath)); 157a3e0fd82Sopenharmony_ci imagePath = nullptr; 158a3e0fd82Sopenharmony_ci return false; 159a3e0fd82Sopenharmony_ci } 160a3e0fd82Sopenharmony_ci if (strcat_s(imagePath, strLen, suffixName) != EOK) { // The format is xxx.xxx.bin 161a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(imagePath)); 162a3e0fd82Sopenharmony_ci imagePath = nullptr; 163a3e0fd82Sopenharmony_ci return false; 164a3e0fd82Sopenharmony_ci } 165a3e0fd82Sopenharmony_ci if (access(imagePath, F_OK) != EOK) { // Check whether the xxx.xxx.bin file exists 166a3e0fd82Sopenharmony_ci if (memcpy_s(imagePath, strLen, src, strLen) != EOK) { 167a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(imagePath)); 168a3e0fd82Sopenharmony_ci imagePath = nullptr; 169a3e0fd82Sopenharmony_ci return false; 170a3e0fd82Sopenharmony_ci } 171a3e0fd82Sopenharmony_ci (ptr - src + imagePath)[0] = '\0'; // remove suffix 172a3e0fd82Sopenharmony_ci if (strcat_s(imagePath, strLen, suffixName) != EOK) { // The format is xxx.bin 173a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(imagePath)); 174a3e0fd82Sopenharmony_ci imagePath = nullptr; 175a3e0fd82Sopenharmony_ci return false; 176a3e0fd82Sopenharmony_ci } 177a3e0fd82Sopenharmony_ci } 178a3e0fd82Sopenharmony_ci } else { 179a3e0fd82Sopenharmony_ci if (memcpy_s(imagePath, strLen, src, strLen) != EOK) { 180a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(imagePath)); 181a3e0fd82Sopenharmony_ci imagePath = nullptr; 182a3e0fd82Sopenharmony_ci return false; 183a3e0fd82Sopenharmony_ci } 184a3e0fd82Sopenharmony_ci } 185a3e0fd82Sopenharmony_ci path_ = imagePath; 186a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_FILE; 187a3e0fd82Sopenharmony_ci return true; 188a3e0fd82Sopenharmony_ci} 189a3e0fd82Sopenharmony_ci 190a3e0fd82Sopenharmony_cibool Image::SetSrc(const char* src) 191a3e0fd82Sopenharmony_ci{ 192a3e0fd82Sopenharmony_ci if (path_ != nullptr) { 193a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(path_)); 194a3e0fd82Sopenharmony_ci path_ = nullptr; 195a3e0fd82Sopenharmony_ci } 196a3e0fd82Sopenharmony_ci 197a3e0fd82Sopenharmony_ci if (src != nullptr) { 198a3e0fd82Sopenharmony_ci uint32_t imageType = ImageDecodeAbility::GetInstance().GetImageDecodeAbility(); 199a3e0fd82Sopenharmony_ci if (((imageType & IMG_SUPPORT_JPEG) == IMG_SUPPORT_JPEG) || 200a3e0fd82Sopenharmony_ci ((imageType & IMG_SUPPORT_PNG) == IMG_SUPPORT_PNG)) { 201a3e0fd82Sopenharmony_ci return SetStandardSrc(src); 202a3e0fd82Sopenharmony_ci } 203a3e0fd82Sopenharmony_ci return SetLiteSrc(src); 204a3e0fd82Sopenharmony_ci } 205a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_UNKNOWN; 206a3e0fd82Sopenharmony_ci return true; 207a3e0fd82Sopenharmony_ci} 208a3e0fd82Sopenharmony_ci 209a3e0fd82Sopenharmony_cibool Image::SetSrc(const ImageInfo* src) 210a3e0fd82Sopenharmony_ci{ 211a3e0fd82Sopenharmony_ci ReInitImageInfo(nullptr, false); 212a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_UNKNOWN; 213a3e0fd82Sopenharmony_ci imageInfo_ = nullptr; 214a3e0fd82Sopenharmony_ci 215a3e0fd82Sopenharmony_ci if (src != nullptr) { 216a3e0fd82Sopenharmony_ci imageInfo_ = static_cast<ImageInfo*>(UIMalloc(static_cast<uint32_t>(sizeof(ImageInfo)))); 217a3e0fd82Sopenharmony_ci if (imageInfo_ == nullptr) { 218a3e0fd82Sopenharmony_ci return false; 219a3e0fd82Sopenharmony_ci } 220a3e0fd82Sopenharmony_ci 221a3e0fd82Sopenharmony_ci if (memcpy_s(const_cast<ImageInfo*>(imageInfo_), sizeof(ImageInfo), src, sizeof(ImageInfo)) != EOK) { 222a3e0fd82Sopenharmony_ci return false; 223a3e0fd82Sopenharmony_ci } 224a3e0fd82Sopenharmony_ci 225a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_VARIABLE; 226a3e0fd82Sopenharmony_ci } 227a3e0fd82Sopenharmony_ci 228a3e0fd82Sopenharmony_ci return true; 229a3e0fd82Sopenharmony_ci} 230a3e0fd82Sopenharmony_ci 231a3e0fd82Sopenharmony_cibool Image::PreParse(const char *src) 232a3e0fd82Sopenharmony_ci{ 233a3e0fd82Sopenharmony_ci if (src == nullptr) { 234a3e0fd82Sopenharmony_ci return false; 235a3e0fd82Sopenharmony_ci } 236a3e0fd82Sopenharmony_ci const char* ptr = strrchr(src, '.'); 237a3e0fd82Sopenharmony_ci if (ptr == nullptr) { 238a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_UNKNOWN; 239a3e0fd82Sopenharmony_ci return false; 240a3e0fd82Sopenharmony_ci } 241a3e0fd82Sopenharmony_ci if (path_ != nullptr) { 242a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(path_)); 243a3e0fd82Sopenharmony_ci } 244a3e0fd82Sopenharmony_ci size_t strLen = strlen(src) + 1; 245a3e0fd82Sopenharmony_ci char* path = static_cast<char*>(UIMalloc(static_cast<uint32_t>(strLen))); 246a3e0fd82Sopenharmony_ci if (strcpy_s(path, strLen, src) != EOK) { 247a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(path)); 248a3e0fd82Sopenharmony_ci return false; 249a3e0fd82Sopenharmony_ci } 250a3e0fd82Sopenharmony_ci path_ = path; 251a3e0fd82Sopenharmony_ci bool isSucess = true; 252a3e0fd82Sopenharmony_ci#if ENABLE_JPEG || ENABLE_PNG 253a3e0fd82Sopenharmony_ci ImageType imageType = CheckImgType(src); 254a3e0fd82Sopenharmony_ci if (imageType == IMG_PNG) { 255a3e0fd82Sopenharmony_ci#if ENABLE_PNG 256a3e0fd82Sopenharmony_ci isSucess = SetPNGSrc(src); 257a3e0fd82Sopenharmony_ci#endif 258a3e0fd82Sopenharmony_ci } else if (imageType == IMG_JPEG) { 259a3e0fd82Sopenharmony_ci#if ENABLE_JPEG 260a3e0fd82Sopenharmony_ci isSucess = SetJPEGSrc(src); 261a3e0fd82Sopenharmony_ci#endif 262a3e0fd82Sopenharmony_ci } else if (imageType == IMG_GIF) { 263a3e0fd82Sopenharmony_ci isSucess = true; 264a3e0fd82Sopenharmony_ci } else { 265a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_UNKNOWN; 266a3e0fd82Sopenharmony_ci return false; 267a3e0fd82Sopenharmony_ci } 268a3e0fd82Sopenharmony_ci#endif 269a3e0fd82Sopenharmony_ci return isSucess; 270a3e0fd82Sopenharmony_ci} 271a3e0fd82Sopenharmony_ci 272a3e0fd82Sopenharmony_civoid Image::DrawImage(BufferInfo& gfxDstBuffer, 273a3e0fd82Sopenharmony_ci const Rect& coords, 274a3e0fd82Sopenharmony_ci const Rect& mask, 275a3e0fd82Sopenharmony_ci const Style& style, 276a3e0fd82Sopenharmony_ci uint8_t opaScale) const 277a3e0fd82Sopenharmony_ci{ 278a3e0fd82Sopenharmony_ci if (srcType_ == IMG_SRC_VARIABLE) { 279a3e0fd82Sopenharmony_ci DrawImage::DrawCommon(gfxDstBuffer, coords, mask, imageInfo_, style, opaScale); 280a3e0fd82Sopenharmony_ci } else if (srcType_ == IMG_SRC_FILE) { 281a3e0fd82Sopenharmony_ci DrawImage::DrawCommon(gfxDstBuffer, coords, mask, path_, style, opaScale); 282a3e0fd82Sopenharmony_ci } else { 283a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("Image::DrawImage:: failed with error srctype!\n"); 284a3e0fd82Sopenharmony_ci } 285a3e0fd82Sopenharmony_ci} 286a3e0fd82Sopenharmony_ci 287a3e0fd82Sopenharmony_ci#if ENABLE_PNG 288a3e0fd82Sopenharmony_cistatic inline void FreePngBytep(png_bytep** rowPointer, uint16_t size) 289a3e0fd82Sopenharmony_ci{ 290a3e0fd82Sopenharmony_ci png_bytep* tmpRowPointer = *rowPointer; 291a3e0fd82Sopenharmony_ci for (uint16_t i = 0; i < size; i++) { 292a3e0fd82Sopenharmony_ci UIFree(tmpRowPointer[i]); 293a3e0fd82Sopenharmony_ci tmpRowPointer[i] = nullptr; 294a3e0fd82Sopenharmony_ci } 295a3e0fd82Sopenharmony_ci UIFree(*rowPointer); 296a3e0fd82Sopenharmony_ci *rowPointer = nullptr; 297a3e0fd82Sopenharmony_ci} 298a3e0fd82Sopenharmony_ci 299a3e0fd82Sopenharmony_cistatic inline png_bytep* MallocPngBytep(uint16_t height, uint32_t rowBytes) 300a3e0fd82Sopenharmony_ci{ 301a3e0fd82Sopenharmony_ci png_bytep* rowPointer = static_cast<png_bytep*>(UIMalloc(sizeof(png_bytep) * height)); 302a3e0fd82Sopenharmony_ci if (rowPointer == nullptr) { 303a3e0fd82Sopenharmony_ci return nullptr; 304a3e0fd82Sopenharmony_ci } 305a3e0fd82Sopenharmony_ci for (uint16_t y = 0; y < height; y++) { 306a3e0fd82Sopenharmony_ci rowPointer[y] = static_cast<png_byte*>(UIMalloc(rowBytes)); 307a3e0fd82Sopenharmony_ci if (rowPointer[y] == nullptr) { 308a3e0fd82Sopenharmony_ci FreePngBytep(&rowPointer, y); 309a3e0fd82Sopenharmony_ci return nullptr; 310a3e0fd82Sopenharmony_ci } 311a3e0fd82Sopenharmony_ci } 312a3e0fd82Sopenharmony_ci return rowPointer; 313a3e0fd82Sopenharmony_ci} 314a3e0fd82Sopenharmony_ci 315a3e0fd82Sopenharmony_cibool Image::SetPNGSrc(const char* src) 316a3e0fd82Sopenharmony_ci{ 317a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_UNKNOWN; 318a3e0fd82Sopenharmony_ci png_bytep* rowPointer = nullptr; 319a3e0fd82Sopenharmony_ci png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); 320a3e0fd82Sopenharmony_ci if (png == nullptr) { 321a3e0fd82Sopenharmony_ci return false; 322a3e0fd82Sopenharmony_ci } 323a3e0fd82Sopenharmony_ci png_infop info = png_create_info_struct(png); 324a3e0fd82Sopenharmony_ci if (info == nullptr) { 325a3e0fd82Sopenharmony_ci png_destroy_read_struct(&png, &info, nullptr); 326a3e0fd82Sopenharmony_ci return false; 327a3e0fd82Sopenharmony_ci } 328a3e0fd82Sopenharmony_ci FILE* infile = fopen(src, "rb"); 329a3e0fd82Sopenharmony_ci if (infile == nullptr) { 330a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("can't open %s\n", src); 331a3e0fd82Sopenharmony_ci png_destroy_read_struct(&png, &info, nullptr); 332a3e0fd82Sopenharmony_ci return false; 333a3e0fd82Sopenharmony_ci } 334a3e0fd82Sopenharmony_ci png_init_io(png, infile); 335a3e0fd82Sopenharmony_ci png_read_info(png, info); 336a3e0fd82Sopenharmony_ci 337a3e0fd82Sopenharmony_ci uint8_t pixelByteSize = DrawUtils::GetPxSizeByColorMode(ARGB8888) >> 3; // 3: Shift right 3 bits 338a3e0fd82Sopenharmony_ci uint16_t width = png_get_image_width(png, info); 339a3e0fd82Sopenharmony_ci uint16_t height = png_get_image_height(png, info); 340a3e0fd82Sopenharmony_ci uint8_t colorType = png_get_color_type(png, info); 341a3e0fd82Sopenharmony_ci uint8_t bitDepth = png_get_bit_depth(png, info); 342a3e0fd82Sopenharmony_ci uint32_t dataSize = height * width * pixelByteSize; 343a3e0fd82Sopenharmony_ci 344a3e0fd82Sopenharmony_ci if ((colorType == PNG_COLOR_TYPE_GRAY) && (bitDepth < 8)) { // 8: Expand grayscale images to the full 8 bits 345a3e0fd82Sopenharmony_ci png_set_expand_gray_1_2_4_to_8(png); 346a3e0fd82Sopenharmony_ci } 347a3e0fd82Sopenharmony_ci if ((colorType == PNG_COLOR_TYPE_GRAY) || (colorType == PNG_COLOR_TYPE_GRAY_ALPHA)) { 348a3e0fd82Sopenharmony_ci png_set_gray_to_rgb(png); 349a3e0fd82Sopenharmony_ci } 350a3e0fd82Sopenharmony_ci if (colorType == PNG_COLOR_TYPE_PALETTE) { 351a3e0fd82Sopenharmony_ci png_set_palette_to_rgb(png); 352a3e0fd82Sopenharmony_ci } 353a3e0fd82Sopenharmony_ci if (bitDepth == 16) { // 16: Chop 16-bit depth images to 8-bit depth 354a3e0fd82Sopenharmony_ci png_set_strip_16(png); 355a3e0fd82Sopenharmony_ci } 356a3e0fd82Sopenharmony_ci if (png_get_valid(png, info, PNG_INFO_tRNS)) { 357a3e0fd82Sopenharmony_ci png_set_tRNS_to_alpha(png); 358a3e0fd82Sopenharmony_ci } 359a3e0fd82Sopenharmony_ci if (!(colorType & PNG_COLOR_MASK_ALPHA)) { 360a3e0fd82Sopenharmony_ci png_set_add_alpha(png, 0xFF, PNG_FILLER_AFTER); 361a3e0fd82Sopenharmony_ci } 362a3e0fd82Sopenharmony_ci png_set_interlace_handling(png); 363a3e0fd82Sopenharmony_ci png_read_update_info(png, info); 364a3e0fd82Sopenharmony_ci 365a3e0fd82Sopenharmony_ci rowPointer = MallocPngBytep(height, png_get_rowbytes(png, info)); 366a3e0fd82Sopenharmony_ci if (rowPointer == nullptr) { 367a3e0fd82Sopenharmony_ci fclose(infile); 368a3e0fd82Sopenharmony_ci png_destroy_read_struct(&png, &info, nullptr); 369a3e0fd82Sopenharmony_ci return false; 370a3e0fd82Sopenharmony_ci } 371a3e0fd82Sopenharmony_ci 372a3e0fd82Sopenharmony_ci png_read_image(png, rowPointer); 373a3e0fd82Sopenharmony_ci fclose(infile); 374a3e0fd82Sopenharmony_ci png_destroy_read_struct(&png, &info, nullptr); 375a3e0fd82Sopenharmony_ci 376a3e0fd82Sopenharmony_ci ImageInfo* imgInfo = static_cast<ImageInfo*>(UIMalloc(sizeof(ImageInfo))); 377a3e0fd82Sopenharmony_ci if (imgInfo == nullptr) { 378a3e0fd82Sopenharmony_ci FreePngBytep(&rowPointer, height); 379a3e0fd82Sopenharmony_ci return false; 380a3e0fd82Sopenharmony_ci } 381a3e0fd82Sopenharmony_ci uint8_t* srcData = static_cast<uint8_t*>(UIMalloc(dataSize)); 382a3e0fd82Sopenharmony_ci if (srcData == nullptr) { 383a3e0fd82Sopenharmony_ci FreePngBytep(&rowPointer, height); 384a3e0fd82Sopenharmony_ci UIFree(imgInfo); 385a3e0fd82Sopenharmony_ci return false; 386a3e0fd82Sopenharmony_ci } 387a3e0fd82Sopenharmony_ci uint32_t n = 0; 388a3e0fd82Sopenharmony_ci for (uint16_t y = 0; y < height; y++) { 389a3e0fd82Sopenharmony_ci png_bytep row = rowPointer[y]; 390a3e0fd82Sopenharmony_ci for (uint16_t x = 0; x < width * pixelByteSize; x += pixelByteSize) { 391a3e0fd82Sopenharmony_ci srcData[n++] = row[x + 2]; // 2: B channel 392a3e0fd82Sopenharmony_ci srcData[n++] = row[x + 1]; // 1: G channel 393a3e0fd82Sopenharmony_ci srcData[n++] = row[x + 0]; // 0: R channel 394a3e0fd82Sopenharmony_ci srcData[n++] = row[x + 3]; // 3: Alpha channel 395a3e0fd82Sopenharmony_ci } 396a3e0fd82Sopenharmony_ci } 397a3e0fd82Sopenharmony_ci FreePngBytep(&rowPointer, height); 398a3e0fd82Sopenharmony_ci 399a3e0fd82Sopenharmony_ci imgInfo->header.width = width; 400a3e0fd82Sopenharmony_ci imgInfo->header.height = height; 401a3e0fd82Sopenharmony_ci imgInfo->header.colorMode = ARGB8888; 402a3e0fd82Sopenharmony_ci imgInfo->dataSize = dataSize; 403a3e0fd82Sopenharmony_ci imgInfo->data = srcData; 404a3e0fd82Sopenharmony_ci 405a3e0fd82Sopenharmony_ci ReInitImageInfo(imgInfo, true); 406a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_VARIABLE; 407a3e0fd82Sopenharmony_ci return true; 408a3e0fd82Sopenharmony_ci} 409a3e0fd82Sopenharmony_ci#endif 410a3e0fd82Sopenharmony_ci 411a3e0fd82Sopenharmony_ci#if ENABLE_JPEG 412a3e0fd82Sopenharmony_cibool Image::SetJPEGSrc(const char* src) 413a3e0fd82Sopenharmony_ci{ 414a3e0fd82Sopenharmony_ci struct jpeg_decompress_struct cinfo; 415a3e0fd82Sopenharmony_ci struct jpeg_error_mgr jerr; 416a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_UNKNOWN; 417a3e0fd82Sopenharmony_ci 418a3e0fd82Sopenharmony_ci FILE* infile = fopen(src, "rb"); 419a3e0fd82Sopenharmony_ci if (infile == nullptr) { 420a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("can't open %s\n", src); 421a3e0fd82Sopenharmony_ci return false; 422a3e0fd82Sopenharmony_ci } 423a3e0fd82Sopenharmony_ci cinfo.err = jpeg_std_error(&jerr); 424a3e0fd82Sopenharmony_ci jpeg_create_decompress(&cinfo); 425a3e0fd82Sopenharmony_ci jpeg_stdio_src(&cinfo, infile); 426a3e0fd82Sopenharmony_ci jpeg_read_header(&cinfo, TRUE); 427a3e0fd82Sopenharmony_ci jpeg_start_decompress(&cinfo); 428a3e0fd82Sopenharmony_ci 429a3e0fd82Sopenharmony_ci uint8_t pixelByteSize = DrawUtils::GetPxSizeByColorMode(ARGB8888) >> 3; // 3: Shift right 3 bits 430a3e0fd82Sopenharmony_ci uint16_t width = cinfo.output_width; 431a3e0fd82Sopenharmony_ci uint16_t height = cinfo.output_height; 432a3e0fd82Sopenharmony_ci uint32_t dataSize = width * height * pixelByteSize; 433a3e0fd82Sopenharmony_ci uint16_t rowStride = cinfo.output_width * pixelByteSize; 434a3e0fd82Sopenharmony_ci JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)(reinterpret_cast<j_common_ptr>(&cinfo), JPOOL_IMAGE, rowStride, 435a3e0fd82Sopenharmony_ci 1); // 1: one-row-high array 436a3e0fd82Sopenharmony_ci ImageInfo* imgInfo = static_cast<ImageInfo*>(UIMalloc(sizeof(ImageInfo))); 437a3e0fd82Sopenharmony_ci if (imgInfo == nullptr) { 438a3e0fd82Sopenharmony_ci jpeg_finish_decompress(&cinfo); 439a3e0fd82Sopenharmony_ci jpeg_destroy_decompress(&cinfo); 440a3e0fd82Sopenharmony_ci fclose(infile); 441a3e0fd82Sopenharmony_ci return false; 442a3e0fd82Sopenharmony_ci } 443a3e0fd82Sopenharmony_ci uint8_t* srcData = static_cast<uint8_t*>(UIMalloc(dataSize)); 444a3e0fd82Sopenharmony_ci if (srcData == nullptr) { 445a3e0fd82Sopenharmony_ci jpeg_finish_decompress(&cinfo); 446a3e0fd82Sopenharmony_ci jpeg_destroy_decompress(&cinfo); 447a3e0fd82Sopenharmony_ci fclose(infile); 448a3e0fd82Sopenharmony_ci UIFree(imgInfo); 449a3e0fd82Sopenharmony_ci return false; 450a3e0fd82Sopenharmony_ci } 451a3e0fd82Sopenharmony_ci uint32_t n = 0; 452a3e0fd82Sopenharmony_ci while (cinfo.output_scanline < cinfo.output_height) { 453a3e0fd82Sopenharmony_ci jpeg_read_scanlines(&cinfo, buffer, 1); // 1: read one line each time 454a3e0fd82Sopenharmony_ci for (uint16_t x = 0; x < width * 3; x += 3) { // 3: color components per pixel 455a3e0fd82Sopenharmony_ci srcData[n++] = buffer[0][x + 2]; // 2: B channel 456a3e0fd82Sopenharmony_ci srcData[n++] = buffer[0][x + 1]; // 1: G channel 457a3e0fd82Sopenharmony_ci srcData[n++] = buffer[0][x + 0]; // 0: R channel 458a3e0fd82Sopenharmony_ci srcData[n++] = 255; // 255: set alpha channel 459a3e0fd82Sopenharmony_ci } 460a3e0fd82Sopenharmony_ci } 461a3e0fd82Sopenharmony_ci jpeg_finish_decompress(&cinfo); 462a3e0fd82Sopenharmony_ci jpeg_destroy_decompress(&cinfo); 463a3e0fd82Sopenharmony_ci fclose(infile); 464a3e0fd82Sopenharmony_ci 465a3e0fd82Sopenharmony_ci imgInfo->header.width = width; 466a3e0fd82Sopenharmony_ci imgInfo->header.height = height; 467a3e0fd82Sopenharmony_ci imgInfo->header.colorMode = ARGB8888; 468a3e0fd82Sopenharmony_ci imgInfo->dataSize = dataSize; 469a3e0fd82Sopenharmony_ci imgInfo->data = srcData; 470a3e0fd82Sopenharmony_ci 471a3e0fd82Sopenharmony_ci ReInitImageInfo(imgInfo, true); 472a3e0fd82Sopenharmony_ci srcType_ = IMG_SRC_VARIABLE; 473a3e0fd82Sopenharmony_ci return true; 474a3e0fd82Sopenharmony_ci} 475a3e0fd82Sopenharmony_ci#endif 476a3e0fd82Sopenharmony_ci 477a3e0fd82Sopenharmony_civoid Image::ReInitImageInfo(ImageInfo* imgInfo, bool mallocFlag) 478a3e0fd82Sopenharmony_ci{ 479a3e0fd82Sopenharmony_ci if (mallocFlag_) { 480a3e0fd82Sopenharmony_ci if (imageInfo_->data != nullptr) { 481a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(const_cast<uint8_t*>(imageInfo_->data))); 482a3e0fd82Sopenharmony_ci } 483a3e0fd82Sopenharmony_ci } 484a3e0fd82Sopenharmony_ci UIFree(reinterpret_cast<void*>(const_cast<ImageInfo*>(imageInfo_))); 485a3e0fd82Sopenharmony_ci 486a3e0fd82Sopenharmony_ci imageInfo_ = imgInfo; 487a3e0fd82Sopenharmony_ci mallocFlag_ = mallocFlag; 488a3e0fd82Sopenharmony_ci} 489a3e0fd82Sopenharmony_ci} // namespace OHOS 490