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