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
Application/Image.cpp
- Committer:
- embeddedartists
- Date:
- 2015-03-20
- Revision:
- 17:6e2abf107800
- Parent:
- 10:651861441108
File content as of revision 17:6e2abf107800:
/* * Copyright 2014 Embedded Artists AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "mbed.h" #include "Image.h" #include "Resource.h" #include "bmp.h" #include "lodepng.h" struct eaimg_header_t { char prefix[6]; uint16_t width; uint16_t height; } __attribute__ ((packed)); int Image::decode(const unsigned char* pDataIn, unsigned int sizeIn, Resolution resolution, ImageData_t* pDataOut) { Image::Type type = imageType(pDataIn, sizeIn); int result = -1; switch (type) { case BMP: { struct BMPHeader* hdr = (struct BMPHeader *) pDataIn; if (resolution == RES_16BIT) { pDataOut->pixels = (uint16_t*)malloc(hdr->width * hdr->height * 2); } else if (resolution == RES_24BIT) { pDataOut->pixels = (uint16_t*)malloc(hdr->width * hdr->height * 4); } else { return -1; } pDataOut->pointerToFree = pDataOut->pixels; if (pDataOut->pixels != NULL) { unsigned char error = BMP_Decode((void*)pDataIn, (unsigned char*)pDataOut->pixels, hdr->width, hdr->height, 24, ((resolution == RES_16BIT) ? 16 : 24)); if (error == 0) { pDataOut->width = hdr->width; pDataOut->height = hdr->height; pDataOut->res = resolution; return 0; } free(pDataOut->pixels); pDataOut->pointerToFree = NULL; } } break; case PNG: { unsigned char* pTmp; unsigned error = lodepng_decode24(&pTmp, (unsigned*)&pDataOut->width, (unsigned*)&pDataOut->height, pDataIn, sizeIn); pDataOut->res = resolution; if (error == 0) { uint32_t x, y; uint8_t r; uint8_t g; uint8_t b; int off = 0; result = 0; if (resolution == RES_16BIT) { pDataOut->pixels = (uint16_t*)malloc(pDataOut->width * pDataOut->height * 2); pDataOut->pointerToFree = pDataOut->pixels; if (pDataOut->pixels != NULL) { uint16_t* pConverted = pDataOut->pixels; for (y = 0; y < pDataOut->height; y++) { for (x = 0; x < pDataOut->width; x++) { r = pTmp[off ]; g = pTmp[off + 1]; b = pTmp[off + 2]; *pConverted = (((unsigned short)r & 0xF8) << 8) | (((unsigned short)g & 0xFC) << 3) | (((unsigned short)b & 0xF8) >> 3); pConverted++; off += 3; } } } } else if (resolution == RES_24BIT) { uint32_t* pConverted = (uint32_t*)malloc(pDataOut->width * pDataOut->height * 4); pDataOut->pixels = (uint16_t*)pConverted; pDataOut->pointerToFree = pDataOut->pixels; if (pDataOut->pixels != NULL) { uint8_t* p = pTmp; int num = pDataOut->width * pDataOut->height; for (int i = 0; i < num; i++) { uint32_t a = 0; a |= (*p++) << 16; // red a |= (*p++) << 8; // green a |= (*p++) << 0; // blue *pConverted++ = a; } } } else { // unknown format result = -2; } free(pTmp); return result; } } break; case RAW: { eaimg_header_t* hdr = (eaimg_header_t*)pDataIn; pDataOut->width = hdr->width; pDataOut->height = hdr->height; pDataOut->pointerToFree = malloc(sizeIn-sizeof(eaimg_header_t)); pDataOut->pixels = (uint16_t*)pDataOut->pointerToFree; pDataOut->res = RES_16BIT; if (pDataOut->pixels != NULL) { memcpy(pDataOut->pixels, pDataIn+sizeof(eaimg_header_t), sizeIn-sizeof(eaimg_header_t)); return 0; } } break; default: break; } pDataOut->pixels = NULL; pDataOut->pointerToFree = NULL; pDataOut->width = 0; pDataOut->height = 0; pDataOut->res = resolution; return result; } int Image::decode(const char* filename, Resolution res, ImageData_t* pDataOut, Mutex* pLock) { FILE* fh = NULL; uint8_t* buff = NULL; int result = 1; pDataOut->height = 0; pDataOut->width = 0; pDataOut->pixels = NULL; pDataOut->pointerToFree = NULL; pDataOut->res = res; if (pLock != NULL) { pLock->lock(); } do { fh = fopen(filename, "r"); if (fh == NULL) { break; } uint32_t size = fileSize(fh); buff = (uint8_t*)malloc(size); if (buff == NULL) { return 1; } uint32_t num; uint32_t left = size; uint32_t off = 0; do { num = fread(buff+off, 1, left, fh); if (num > 0) { left -= num; off += num; } } while (left > 0 && num > 0); if (left > 0) { break; } fclose(fh); if (pLock != NULL) { pLock->unlock(); } Type type = imageType(buff, size); if (type == RAW) { pDataOut->width = ((eaimg_header_t*)buff)->width; pDataOut->height = ((eaimg_header_t*)buff)->height; pDataOut->pointerToFree = buff; pDataOut->res = RES_16BIT; pDataOut->pixels = (uint16_t*)(buff + sizeof(eaimg_header_t)); } else { result = Image::decode(buff, size, res, pDataOut); free(buff); return result; } // success return 0; } while (false); if (fh != NULL) { fclose(fh); } if (buff != NULL) { free(buff); } if (pLock != NULL) { pLock->unlock(); } return result; } int Image::decode(Resource* res, Resolution resolution, ImageData_t* pDataOut, Mutex* pLock) { int result = 0; if (res == NULL) { result = 1; } else { // Load the image only if it is not already cached if (res->_img.pixels == NULL) { if (res->_isFile) { result = decode(res->_filename, resolution, &res->_img, pLock); } else { result = decode(res->_data, res->_dataSize, resolution, &res->_img); } } if ((result == 0) && (res->_img.pixels != NULL)) { // Copy the cached copy to the user's data, but skip the pointerToFree // as that would break the cache memcpy(pDataOut, &res->_img, sizeof(ImageData_t)); pDataOut->pointerToFree = NULL; } } return result; } Image::Type Image::imageType(const unsigned char* pDataIn, unsigned int sizeIn) { if (sizeIn > 4) { if (pDataIn[0] == 0x89 && pDataIn[1] == 'P' && pDataIn[2] == 'N' && pDataIn[3] == 'G') { return PNG; } } if (BMP_IsValid((void*)pDataIn)) { return BMP; } if (sizeIn >= sizeof(eaimg_header_t)) { eaimg_header_t* hdr = (eaimg_header_t*)pDataIn; if (memcmp(hdr->prefix, "eaimg:", 6) == 0) { return RAW; } } return UNKNOWN; } uint32_t Image::fileSize(FILE* f) { uint32_t pos = ftell(f); fseek(f, 0, SEEK_END); uint32_t size = ftell(f); fseek(f, pos, SEEK_SET); return size; }