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 EmbeddedArtists AB

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Image.cpp Source File

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 }