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 "imgdecode/image_load.h" 17a3e0fd82Sopenharmony_ci#include "gfx_utils/file.h" 18a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_log.h" 19a3e0fd82Sopenharmony_ci#include "gfx_utils/mem_api.h" 20a3e0fd82Sopenharmony_ci 21a3e0fd82Sopenharmony_cinamespace { 22a3e0fd82Sopenharmony_ciconst uint8_t BITMAP_ZIP_LEN = 3; 23a3e0fd82Sopenharmony_ciconst uint8_t BITMAP_MID_BIT = 1; 24a3e0fd82Sopenharmony_ciconst uint8_t BITMAP_LOW_BIT = 2; 25a3e0fd82Sopenharmony_ciconst uint32_t BITMAP_ZIP24_FLAG = 0x456789; 26a3e0fd82Sopenharmony_ciconst uint32_t BITMAP_ZIP_FLAG = 0x23456789; 27a3e0fd82Sopenharmony_ciconst uint32_t BITMAP_ALPHA_MASK = 0xFF000000; 28a3e0fd82Sopenharmony_ciconst uint32_t BITMAP_MAXCON_PIXNUM = 0xCB100; 29a3e0fd82Sopenharmony_ciconst uint32_t MOVE_HIGH = 16; 30a3e0fd82Sopenharmony_ciconst uint32_t MOVE_LOW = 8; 31a3e0fd82Sopenharmony_ci} // namespace 32a3e0fd82Sopenharmony_ci 33a3e0fd82Sopenharmony_cinamespace OHOS { 34a3e0fd82Sopenharmony_cibool ImageLoad::CreateImage(ImageInfo& imageInfo) 35a3e0fd82Sopenharmony_ci{ 36a3e0fd82Sopenharmony_ci uint32_t bytePerPixel = 4; 37a3e0fd82Sopenharmony_ci ImageHeader& imageHeader = imageInfo.header; 38a3e0fd82Sopenharmony_ci 39a3e0fd82Sopenharmony_ci switch (imageHeader.colorMode) { 40a3e0fd82Sopenharmony_ci case ARGB8888: 41a3e0fd82Sopenharmony_ci bytePerPixel = 4; // 4 bytes per pixel 42a3e0fd82Sopenharmony_ci break; 43a3e0fd82Sopenharmony_ci case RGB888: 44a3e0fd82Sopenharmony_ci bytePerPixel = 3; // 3 bytes per pixel 45a3e0fd82Sopenharmony_ci break; 46a3e0fd82Sopenharmony_ci case RGB565: 47a3e0fd82Sopenharmony_ci bytePerPixel = 2; // 2 bytes per pixel 48a3e0fd82Sopenharmony_ci break; 49a3e0fd82Sopenharmony_ci default: 50a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("CreateImage invalid colorMode."); 51a3e0fd82Sopenharmony_ci return false; 52a3e0fd82Sopenharmony_ci } 53a3e0fd82Sopenharmony_ci 54a3e0fd82Sopenharmony_ci imageInfo.dataSize = imageHeader.width * imageHeader.height * bytePerPixel; 55a3e0fd82Sopenharmony_ci imageInfo.data = static_cast<uint8_t*>(ImageCacheMalloc(imageInfo)); 56a3e0fd82Sopenharmony_ci if (imageInfo.data == nullptr) { 57a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("ImageCacheMalloc error."); 58a3e0fd82Sopenharmony_ci return false; 59a3e0fd82Sopenharmony_ci } 60a3e0fd82Sopenharmony_ci 61a3e0fd82Sopenharmony_ci return true; 62a3e0fd82Sopenharmony_ci} 63a3e0fd82Sopenharmony_ci 64a3e0fd82Sopenharmony_cibool ImageLoad::UncompressImageInZip(ImageInfo& imageInfo, uint8_t* buffer, uint32_t size) 65a3e0fd82Sopenharmony_ci{ 66a3e0fd82Sopenharmony_ci if (!CreateImage(imageInfo)) { 67a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("Create image error."); 68a3e0fd82Sopenharmony_ci return false; 69a3e0fd82Sopenharmony_ci } 70a3e0fd82Sopenharmony_ci 71a3e0fd82Sopenharmony_ci if (imageInfo.header.colorMode == RGB888) { 72a3e0fd82Sopenharmony_ci return Unzip24Image(buffer, size, imageInfo); 73a3e0fd82Sopenharmony_ci } else { 74a3e0fd82Sopenharmony_ci return UnzipImage(buffer, size, imageInfo); 75a3e0fd82Sopenharmony_ci } 76a3e0fd82Sopenharmony_ci} 77a3e0fd82Sopenharmony_ci 78a3e0fd82Sopenharmony_cibool ImageLoad::UnzipImage(uint8_t* imageBuffer, uint32_t size, ImageInfo& imageInfo) 79a3e0fd82Sopenharmony_ci{ 80a3e0fd82Sopenharmony_ci if ((imageBuffer == nullptr) || (size == 0)) { 81a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("imageHeader is null."); 82a3e0fd82Sopenharmony_ci return false; 83a3e0fd82Sopenharmony_ci } 84a3e0fd82Sopenharmony_ci 85a3e0fd82Sopenharmony_ci uint32_t* source = reinterpret_cast<uint32_t*>(imageBuffer); 86a3e0fd82Sopenharmony_ci uint32_t* sourceEnd = reinterpret_cast<uint32_t*>(imageBuffer + size); 87a3e0fd82Sopenharmony_ci uint32_t* dest = nullptr; 88a3e0fd82Sopenharmony_ci uint32_t* destEnd = nullptr; 89a3e0fd82Sopenharmony_ci 90a3e0fd82Sopenharmony_ci dest = reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(imageInfo.data)); 91a3e0fd82Sopenharmony_ci destEnd = reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(imageInfo.data) + imageInfo.dataSize); 92a3e0fd82Sopenharmony_ci 93a3e0fd82Sopenharmony_ci while ((source < sourceEnd) && (dest < destEnd)) { 94a3e0fd82Sopenharmony_ci if (*source != BITMAP_ZIP_FLAG) { 95a3e0fd82Sopenharmony_ci *dest++ = *source++; 96a3e0fd82Sopenharmony_ci } else { 97a3e0fd82Sopenharmony_ci source++; 98a3e0fd82Sopenharmony_ci uint32_t value = *source++; 99a3e0fd82Sopenharmony_ci uint32_t count = *source++; 100a3e0fd82Sopenharmony_ci if (destEnd < count + dest) { 101a3e0fd82Sopenharmony_ci break; 102a3e0fd82Sopenharmony_ci } 103a3e0fd82Sopenharmony_ci 104a3e0fd82Sopenharmony_ci while (count--) { 105a3e0fd82Sopenharmony_ci *dest++ = value; 106a3e0fd82Sopenharmony_ci } 107a3e0fd82Sopenharmony_ci } 108a3e0fd82Sopenharmony_ci } 109a3e0fd82Sopenharmony_ci 110a3e0fd82Sopenharmony_ci if (dest == destEnd) { 111a3e0fd82Sopenharmony_ci return true; 112a3e0fd82Sopenharmony_ci } 113a3e0fd82Sopenharmony_ci ImageCacheFree(imageInfo); 114a3e0fd82Sopenharmony_ci imageInfo.data = nullptr; 115a3e0fd82Sopenharmony_ci return false; 116a3e0fd82Sopenharmony_ci} 117a3e0fd82Sopenharmony_ci 118a3e0fd82Sopenharmony_cibool ImageLoad::Unzip24Image(uint8_t* imageBuffer, uint32_t size, ImageInfo& imageInfo) 119a3e0fd82Sopenharmony_ci{ 120a3e0fd82Sopenharmony_ci if ((imageBuffer == nullptr) || (size == 0)) { 121a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("imageHeader is null."); 122a3e0fd82Sopenharmony_ci return false; 123a3e0fd82Sopenharmony_ci } 124a3e0fd82Sopenharmony_ci 125a3e0fd82Sopenharmony_ci uint8_t* source = reinterpret_cast<uint8_t*>(imageBuffer); 126a3e0fd82Sopenharmony_ci uint8_t* sourceEnd = reinterpret_cast<uint8_t*>(imageBuffer + size); 127a3e0fd82Sopenharmony_ci uint32_t* dest = reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(imageInfo.data)); 128a3e0fd82Sopenharmony_ci uint32_t* destEnd = reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(imageInfo.data) + imageInfo.dataSize); 129a3e0fd82Sopenharmony_ci while ((source < sourceEnd) && (dest < destEnd)) { 130a3e0fd82Sopenharmony_ci // Little endian 131a3e0fd82Sopenharmony_ci uint32_t value = ((*source)) + (*(source + BITMAP_MID_BIT) << MOVE_LOW) 132a3e0fd82Sopenharmony_ci + (*(source + BITMAP_LOW_BIT) << MOVE_HIGH); 133a3e0fd82Sopenharmony_ci source = source + BITMAP_ZIP_LEN; 134a3e0fd82Sopenharmony_ci if (value != BITMAP_ZIP24_FLAG) { 135a3e0fd82Sopenharmony_ci *dest = value | BITMAP_ALPHA_MASK; 136a3e0fd82Sopenharmony_ci dest++; 137a3e0fd82Sopenharmony_ci } else { 138a3e0fd82Sopenharmony_ci value = ((*source)) + (*(source + BITMAP_MID_BIT) << MOVE_LOW) + (*(source + BITMAP_LOW_BIT) << MOVE_HIGH); 139a3e0fd82Sopenharmony_ci source = source + BITMAP_ZIP_LEN; 140a3e0fd82Sopenharmony_ci 141a3e0fd82Sopenharmony_ci uint32_t count = ((*source)) + (*(source + BITMAP_MID_BIT) << MOVE_LOW) 142a3e0fd82Sopenharmony_ci + (*(source + BITMAP_LOW_BIT) << MOVE_HIGH); 143a3e0fd82Sopenharmony_ci source = source + BITMAP_ZIP_LEN; 144a3e0fd82Sopenharmony_ci 145a3e0fd82Sopenharmony_ci if (count > BITMAP_MAXCON_PIXNUM) { 146a3e0fd82Sopenharmony_ci *dest = BITMAP_ZIP24_FLAG | BITMAP_ALPHA_MASK; 147a3e0fd82Sopenharmony_ci dest++; 148a3e0fd82Sopenharmony_ci *dest = value | BITMAP_ALPHA_MASK; 149a3e0fd82Sopenharmony_ci dest++; 150a3e0fd82Sopenharmony_ci *dest = count | BITMAP_ALPHA_MASK; 151a3e0fd82Sopenharmony_ci dest++; 152a3e0fd82Sopenharmony_ci continue; 153a3e0fd82Sopenharmony_ci } 154a3e0fd82Sopenharmony_ci if (static_cast<uintptr_t>(destEnd - dest) < static_cast<uintptr_t>(count)) { 155a3e0fd82Sopenharmony_ci break; 156a3e0fd82Sopenharmony_ci } 157a3e0fd82Sopenharmony_ci while (count--) { 158a3e0fd82Sopenharmony_ci *dest = value | BITMAP_ALPHA_MASK; 159a3e0fd82Sopenharmony_ci dest++; 160a3e0fd82Sopenharmony_ci } 161a3e0fd82Sopenharmony_ci } 162a3e0fd82Sopenharmony_ci } 163a3e0fd82Sopenharmony_ci 164a3e0fd82Sopenharmony_ci if (dest == destEnd) { 165a3e0fd82Sopenharmony_ci return true; 166a3e0fd82Sopenharmony_ci } 167a3e0fd82Sopenharmony_ci ImageCacheFree(imageInfo); 168a3e0fd82Sopenharmony_ci imageInfo.data = nullptr; 169a3e0fd82Sopenharmony_ci return false; 170a3e0fd82Sopenharmony_ci} 171a3e0fd82Sopenharmony_ci 172a3e0fd82Sopenharmony_cibool ImageLoad::UnZip2ImageInfo(ImageInfo& imageInfo, uint8_t* buffer, uint32_t size) 173a3e0fd82Sopenharmony_ci{ 174a3e0fd82Sopenharmony_ci switch (imageInfo.header.compressMode) { 175a3e0fd82Sopenharmony_ci case COMPRESS_MODE__ZIP_ALG: 176a3e0fd82Sopenharmony_ci return UncompressImageInZip(imageInfo, buffer, size); 177a3e0fd82Sopenharmony_ci default: 178a3e0fd82Sopenharmony_ci return false; 179a3e0fd82Sopenharmony_ci } 180a3e0fd82Sopenharmony_ci} 181a3e0fd82Sopenharmony_ci 182a3e0fd82Sopenharmony_cibool ImageLoad::GetImageInfo(int32_t fd, uint32_t size, ImageInfo& imageInfo) 183a3e0fd82Sopenharmony_ci{ 184a3e0fd82Sopenharmony_ci if (size == 0) { 185a3e0fd82Sopenharmony_ci return false; 186a3e0fd82Sopenharmony_ci } 187a3e0fd82Sopenharmony_ci 188a3e0fd82Sopenharmony_ci uint8_t* buffer = reinterpret_cast<uint8_t*>(UIMalloc(size)); 189a3e0fd82Sopenharmony_ci if (buffer == nullptr) { 190a3e0fd82Sopenharmony_ci return false; 191a3e0fd82Sopenharmony_ci } 192a3e0fd82Sopenharmony_ci 193a3e0fd82Sopenharmony_ci if (read(fd, buffer, size) != static_cast<int32_t>(size)) { 194a3e0fd82Sopenharmony_ci UIFree(buffer); 195a3e0fd82Sopenharmony_ci GRAPHIC_LOGE("SeekImageFile error."); 196a3e0fd82Sopenharmony_ci return false; 197a3e0fd82Sopenharmony_ci } 198a3e0fd82Sopenharmony_ci bool ret = UnZip2ImageInfo(imageInfo, buffer, size); 199a3e0fd82Sopenharmony_ci UIFree(buffer); 200a3e0fd82Sopenharmony_ci return ret; 201a3e0fd82Sopenharmony_ci} 202a3e0fd82Sopenharmony_ci} // namespace OHOS 203