Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of DMBasicGUI by
Image.cpp
00001 /* 00002 * Copyright 2014 Embedded Artists AB 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "mbed.h" 00018 #include "Image.h" 00019 #include "Resource.h" 00020 00021 #include "bmp.h" 00022 #include "lodepng.h" 00023 00024 struct eaimg_header_t 00025 { 00026 char prefix[6]; 00027 uint16_t width; 00028 uint16_t height; 00029 } __attribute__ ((packed)); 00030 00031 int Image::decode(const unsigned char* pDataIn, unsigned int sizeIn, Resolution resolution, ImageData_t* pDataOut) 00032 { 00033 Image::Type type = imageType(pDataIn, sizeIn); 00034 int result = -1; 00035 switch (type) 00036 { 00037 case BMP: 00038 { 00039 struct BMPHeader* hdr = (struct BMPHeader *) pDataIn; 00040 if (resolution == RES_16BIT) { 00041 pDataOut->pixels = (uint16_t*)malloc(hdr->width * hdr->height * 2); 00042 } else if (resolution == RES_24BIT) { 00043 pDataOut->pixels = (uint16_t*)malloc(hdr->width * hdr->height * 4); 00044 } else { 00045 return -1; 00046 } 00047 pDataOut->pointerToFree = pDataOut->pixels; 00048 if (pDataOut->pixels != NULL) 00049 { 00050 unsigned char error = BMP_Decode((void*)pDataIn, (unsigned char*)pDataOut->pixels, 00051 hdr->width, hdr->height, 24, ((resolution == RES_16BIT) ? 16 : 24)); 00052 if (error == 0) 00053 { 00054 pDataOut->width = hdr->width; 00055 pDataOut->height = hdr->height; 00056 pDataOut->res = resolution; 00057 return 0; 00058 } 00059 free(pDataOut->pixels); 00060 pDataOut->pointerToFree = NULL; 00061 } 00062 } 00063 break; 00064 00065 case PNG: 00066 { 00067 unsigned char* pTmp; 00068 unsigned error = lodepng_decode24(&pTmp, (unsigned*)&pDataOut->width, (unsigned*)&pDataOut->height, pDataIn, sizeIn); 00069 pDataOut->res = resolution; 00070 if (error == 0) 00071 { 00072 uint32_t x, y; 00073 uint8_t r; 00074 uint8_t g; 00075 uint8_t b; 00076 int off = 0; 00077 00078 result = 0; 00079 if (resolution == RES_16BIT) { 00080 pDataOut->pixels = (uint16_t*)malloc(pDataOut->width * pDataOut->height * 2); 00081 pDataOut->pointerToFree = pDataOut->pixels; 00082 if (pDataOut->pixels != NULL) 00083 { 00084 uint16_t* pConverted = pDataOut->pixels; 00085 00086 for (y = 0; y < pDataOut->height; y++) { 00087 for (x = 0; x < pDataOut->width; x++) { 00088 r = pTmp[off ]; 00089 g = pTmp[off + 1]; 00090 b = pTmp[off + 2]; 00091 *pConverted = (((unsigned short)r & 0xF8) << 8) | 00092 (((unsigned short)g & 0xFC) << 3) | 00093 (((unsigned short)b & 0xF8) >> 3); 00094 pConverted++; 00095 off += 3; 00096 } 00097 } 00098 } 00099 } else if (resolution == RES_24BIT) { 00100 uint32_t* pConverted = (uint32_t*)malloc(pDataOut->width * pDataOut->height * 4); 00101 pDataOut->pixels = (uint16_t*)pConverted; 00102 pDataOut->pointerToFree = pDataOut->pixels; 00103 if (pDataOut->pixels != NULL) 00104 { 00105 uint8_t* p = pTmp; 00106 int num = pDataOut->width * pDataOut->height; 00107 for (int i = 0; i < num; i++) { 00108 uint32_t a = 0; 00109 a |= (*p++) << 16; // red 00110 a |= (*p++) << 8; // green 00111 a |= (*p++) << 0; // blue 00112 *pConverted++ = a; 00113 } 00114 } 00115 } else { 00116 // unknown format 00117 result = -2; 00118 } 00119 free(pTmp); 00120 return result; 00121 } 00122 } 00123 break; 00124 00125 case RAW: 00126 { 00127 eaimg_header_t* hdr = (eaimg_header_t*)pDataIn; 00128 pDataOut->width = hdr->width; 00129 pDataOut->height = hdr->height; 00130 pDataOut->pointerToFree = malloc(sizeIn-sizeof(eaimg_header_t)); 00131 pDataOut->pixels = (uint16_t*)pDataOut->pointerToFree; 00132 pDataOut->res = RES_16BIT; 00133 if (pDataOut->pixels != NULL) 00134 { 00135 memcpy(pDataOut->pixels, pDataIn+sizeof(eaimg_header_t), sizeIn-sizeof(eaimg_header_t)); 00136 return 0; 00137 } 00138 } 00139 break; 00140 00141 default: 00142 break; 00143 } 00144 00145 pDataOut->pixels = NULL; 00146 pDataOut->pointerToFree = NULL; 00147 pDataOut->width = 0; 00148 pDataOut->height = 0; 00149 pDataOut->res = resolution; 00150 return result; 00151 } 00152 00153 int Image::decode(const char* filename, Resolution res, ImageData_t* pDataOut, Mutex* pLock) 00154 { 00155 FILE* fh = NULL; 00156 uint8_t* buff = NULL; 00157 int result = 1; 00158 00159 pDataOut->height = 0; 00160 pDataOut->width = 0; 00161 pDataOut->pixels = NULL; 00162 pDataOut->pointerToFree = NULL; 00163 pDataOut->res = res; 00164 00165 if (pLock != NULL) { 00166 pLock->lock(); 00167 } 00168 00169 do 00170 { 00171 fh = fopen(filename, "r"); 00172 if (fh == NULL) { 00173 break; 00174 } 00175 00176 uint32_t size = fileSize(fh); 00177 buff = (uint8_t*)malloc(size); 00178 if (buff == NULL) { 00179 return 1; 00180 } 00181 00182 uint32_t num; 00183 uint32_t left = size; 00184 uint32_t off = 0; 00185 do 00186 { 00187 num = fread(buff+off, 1, left, fh); 00188 if (num > 0) { 00189 left -= num; 00190 off += num; 00191 } 00192 } while (left > 0 && num > 0); 00193 if (left > 0) { 00194 break; 00195 } 00196 00197 fclose(fh); 00198 if (pLock != NULL) { 00199 pLock->unlock(); 00200 } 00201 00202 Type type = imageType(buff, size); 00203 if (type == RAW) { 00204 pDataOut->width = ((eaimg_header_t*)buff)->width; 00205 pDataOut->height = ((eaimg_header_t*)buff)->height; 00206 pDataOut->pointerToFree = buff; 00207 pDataOut->res = RES_16BIT; 00208 pDataOut->pixels = (uint16_t*)(buff + sizeof(eaimg_header_t)); 00209 } else { 00210 result = Image::decode(buff, size, res, pDataOut); 00211 free(buff); 00212 return result; 00213 } 00214 00215 // success 00216 return 0; 00217 00218 } while (false); 00219 00220 if (fh != NULL) { 00221 fclose(fh); 00222 } 00223 if (buff != NULL) { 00224 free(buff); 00225 } 00226 if (pLock != NULL) { 00227 pLock->unlock(); 00228 } 00229 return result; 00230 } 00231 00232 int Image::decode(Resource* res, Resolution resolution, ImageData_t* pDataOut, Mutex* pLock) 00233 { 00234 int result = 0; 00235 if (res == NULL) { 00236 result = 1; 00237 } else { 00238 // Load the image only if it is not already cached 00239 if (res->_img.pixels == NULL) { 00240 if (res->_isFile) { 00241 result = decode(res->_filename, resolution, &res->_img, pLock); 00242 } else { 00243 result = decode(res->_data, res->_dataSize, resolution, &res->_img); 00244 } 00245 } 00246 if ((result == 0) && (res->_img.pixels != NULL)) { 00247 // Copy the cached copy to the user's data, but skip the pointerToFree 00248 // as that would break the cache 00249 memcpy(pDataOut, &res->_img, sizeof(ImageData_t)); 00250 pDataOut->pointerToFree = NULL; 00251 } 00252 } 00253 return result; 00254 } 00255 00256 Image::Type Image::imageType(const unsigned char* pDataIn, unsigned int sizeIn) 00257 { 00258 if (sizeIn > 4) 00259 { 00260 if (pDataIn[0] == 0x89 && pDataIn[1] == 'P' && pDataIn[2] == 'N' && pDataIn[3] == 'G') 00261 { 00262 return PNG; 00263 } 00264 } 00265 if (BMP_IsValid((void*)pDataIn)) 00266 { 00267 return BMP; 00268 } 00269 if (sizeIn >= sizeof(eaimg_header_t)) 00270 { 00271 eaimg_header_t* hdr = (eaimg_header_t*)pDataIn; 00272 if (memcmp(hdr->prefix, "eaimg:", 6) == 0) 00273 { 00274 return RAW; 00275 } 00276 } 00277 return UNKNOWN; 00278 } 00279 00280 uint32_t Image::fileSize(FILE* f) 00281 { 00282 uint32_t pos = ftell(f); 00283 fseek(f, 0, SEEK_END); 00284 uint32_t size = ftell(f); 00285 fseek(f, pos, SEEK_SET); 00286 return size; 00287 }
Generated on Wed Jul 13 2022 03:01:50 by
1.7.2
