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