A basic graphics package for the LPC4088 Display Module.
Dependents: lpc4088_displaymodule_demo_sphere sampleGUI sampleEmptyGUI lpc4088_displaymodule_fs_aid ... more
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 Tue Jul 12 2022 21:27:03 by 1.7.2