/* ---------------------------------------------------------------------------- * ATMEL Microcontroller Software Support * ---------------------------------------------------------------------------- * Copyright (c) 2008, Atmel Corporation * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the disclaimer below. * * Atmel's name may not be used to endorse or promote products derived from * this software without specific prior written permission. * * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ---------------------------------------------------------------------------- */ //------------------------------------------------------------------------------ // Headers //------------------------------------------------------------------------------ #include "board.h" #include //----------------------------------------------------------------------------- // Define //----------------------------------------------------------------------------- /// BMP offset for header #define IMAGE_OFFSET 0x100 //------------------------------------------------------------------------------ // Internal constants //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Internal types //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /// Describe the BMP palette //------------------------------------------------------------------------------ typedef struct _BMPPaletteEntry { /// Blue value uint8_t b; /// Green value uint8_t g; /// Red value uint8_t r; /// Filler character value uint8_t filler; } BMPPaletteEntry ; //------------------------------------------------------------------------------ // Exported functions //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /// Test if BMP is valid /// \param file Buffer holding the file to examinate. /// \return 1 if the header of a BMP file is valid; otherwise returns 0. //------------------------------------------------------------------------------ uint8_t BMP_IsValid( void *file ) { return ((BMPHeader*) file)->type == BMP_TYPE ; } //------------------------------------------------------------------------------ /// Returns the size of a BMP image given at least its header (the file does /// not have to be complete). /// \param file Pointer to the buffer which holds the BMP file. /// \return size of BMP image //------------------------------------------------------------------------------ uint32_t BMP_GetFileSize( void *file ) { return ((BMPHeader *) file)->fileSize ; } //----------------------------------------------------------------------------- /// Write a BMP header /// \param pAddressHeader Begin address of the BMP /// \param bmpHSize BMP heigth size /// \param bmpVSize BMP width size /// \param nbByte_Pixels Number of byte per pixels //----------------------------------------------------------------------------- void WriteBMPheader( uint32_t* pAddressHeader, uint32_t bmpHSize, uint32_t bmpVSize, uint8_t nbByte_Pixels ) { uint32_t i; uint32_t* fill; BMPHeader *Header; fill = pAddressHeader; for ( i=0 ; i < IMAGE_OFFSET ; i+=4 ) { *fill++ = 0; } Header = (BMPHeader*) pAddressHeader; Header->type = BMP_TYPE; Header->fileSize = (bmpHSize * bmpVSize * nbByte_Pixels) + IMAGE_OFFSET; Header->reserved1 = 0; Header->reserved2 = 0; Header->offset = IMAGE_OFFSET; Header->headerSize = BITMAPINFOHEADER; Header->width = bmpHSize; Header->height = bmpVSize; Header->planes = 1; Header->bits = nbByte_Pixels * 8; Header->compression = 0; Header->imageSize = bmpHSize * bmpVSize * nbByte_Pixels; Header->xresolution = 0; Header->yresolution = 0; Header->ncolours = 0; Header->importantcolours = 0; } //------------------------------------------------------------------------------ /// debug function, dislay BMP header /// \param pAddressHeader Address of the BMP //------------------------------------------------------------------------------ #if (TRACE_LEVEL >= TRACE_LEVEL_INFO) void BMP_displayHeader( uint32_t* pAddressHeader ) { BMPHeader *header; header = (BMPHeader*) pAddressHeader; TRACE_INFO("BMP\n\r"); TRACE_INFO("type 0x%X \n\r", header->type); TRACE_INFO("fileSize %d \n\r", header->fileSize); TRACE_INFO("reserved1 %d \n\r", header->reserved1); TRACE_INFO("reserved2 %d \n\r", header->reserved2); TRACE_INFO("offset %d \n\r", header->offset); TRACE_INFO("headerSize %d \n\r", header->headerSize); TRACE_INFO("width %d \n\r", header->width); TRACE_INFO("height %d \n\r", header->height); TRACE_INFO("planes %d \n\r", header->planes); TRACE_INFO("bits %d \n\r", header->bits); TRACE_INFO("compression %d \n\r", header->compression); TRACE_INFO("imageSize %d \n\r", header->imageSize); TRACE_INFO("xresolution %d \n\r", header->xresolution); TRACE_INFO("yresolution %d \n\r", header->yresolution); TRACE_INFO("ncolours %d \n\r", header->ncolours); TRACE_INFO("importantcolours %d\n\r", header->importantcolours); } #endif //------------------------------------------------------------------------------ /// Loads a BMP image located at the given address, decodes it and stores the /// resulting image inside the provided buffer. Image must have the specified /// width & height. /// If no buffer is provided, this function simply checks if it is able to /// decode the image. /// \param file Buffer which holds the BMP file. /// \param buffer Buffer in which to store the decoded image. /// \param width Buffer width in pixels. /// \param height Buffer height in pixels. /// \param bpp Number of bits per pixels that the buffer stores. /// \return 0 if the image has been loaded; otherwise returns an error code. //------------------------------------------------------------------------------ uint8_t BMP_Decode( void *file, uint8_t *buffer, uint32_t width, uint32_t height, uint8_t bpp ) { BMPHeader *header; uint32_t i, j; uint8_t r, g, b; uint8_t *image; // Read header information header = (BMPHeader*) file; // Verify that the file is valid if ( !BMP_IsValid( file ) ) { TRACE_ERROR("BMP_Decode: File type is not 'BM' (0x%04X).\n\r",header->type); return 1; } // Check that parameters match if ( (header->compression != 0) || (header->width != width) || (header->height != height)) { TRACE_ERROR("BMP_Decode: File format not supported\n\r"); TRACE_ERROR(" -> .compression = %u\n\r", (unsigned int)header->compression); TRACE_ERROR(" -> .width = %u\n\r", (unsigned int)header->width); TRACE_ERROR(" -> .height = %u\n\r", (unsigned int)header->height); TRACE_ERROR(" -> .bits = %d\n\r", (int)header->bits); return 2; } // Get image data image = (uint8_t *) ((uint32_t) file + header->offset); // Check that the bpp resolution is supported // Only a 24-bit output & 24- or 8-bit input are supported if ( bpp != 24 ) { TRACE_ERROR("BMP_Decode: Output resolution not supported\n\r"); return 3; } else { if (header->bits == 24) { // Decoding is ok if (!buffer) return 0; // Get image data (swapping red & blue) for ( i=0 ; i < height ; i++ ) { for ( j=0 ; j < width; j++ ) { r = image[((height - i - 1) * width + j) * 3 + 2]; g = image[((height - i - 1) * width + j) * 3 + 1]; b = image[((height - i - 1) * width + j) * 3]; #if defined(BOARD_LCD_RGB565) // Interlacing r = ((r << 1) & 0xF0) | ((g & 0x80) >> 4) | ((r & 0x80) >> 5); g = (g << 1) & 0xF8; b = b & 0xF8; buffer[(i * width + j) * 3] = b; buffer[(i * width + j) * 3 + 1] = g; buffer[(i * width + j) * 3 + 2] = r; #else buffer[(i * width + j) * 3] = r; buffer[(i * width + j) * 3 + 1] = g; buffer[(i * width + j) * 3 + 2] = b; #endif //#if defined(BOARD_LCD_RGB565) } } } else { if ( header->bits == 8 ) { BMPPaletteEntry palette[256]; // Decoding is ok if (!buffer) return 0; // Retrieve palette memcpy( palette, (uint8_t *) ((uint32_t) file + sizeof( BMPHeader )), header->offset - sizeof( BMPHeader ) ) ; // Decode image (reversing row order) for ( i=0 ; i < height ; i++ ) { for (j=0; j < width; j++) { r = palette[image[(height - i - 1) * width + j]].r; g = palette[image[(height - i - 1) * width + j]].g; b = palette[image[(height - i - 1) * width + j]].b; buffer[(i * width + j) * 3] = r; buffer[(i * width + j) * 3 + 1] = g; buffer[(i * width + j) * 3 + 2] = b; } } } else { TRACE_ERROR("BMP_Decode: Input resolution not supported\n\r"); TRACE_INFO("header->bits 0x%X \n\r", header->bits); return 4 ; } } } return 0 ; } //------------------------------------------------------------------------------ /// Convert RGB 565 to RGB 555 (RGB 555 is adapted to LCD) /// \param fileSource Buffer which holds the RGB file /// \param fileDestination Buffer in which to store the decoded image /// \param width Buffer width in pixels. /// \param height Buffer height in pixels. /// \param bpp Number of bits per pixels that the buffer stores. //------------------------------------------------------------------------------ void RGB565toBGR555( uint8_t *fileSource, uint8_t *fileDestination, uint32_t width, uint32_t height, uint8_t bpp ) { uint32_t i; uint32_t j; uint32_t row; for (i=0; i < height*(bpp/8); i++) { row = (i*width*(bpp/8)); for (j=0; j <= width*(bpp/8); j+=2) { fileDestination[row+j] = ((fileSource[row+j+1]>>3)&0x1F) | (fileSource[row+j]&0xE0); fileDestination[row+j+1] = (fileSource[row+j+1]&0x03) | ((fileSource[row+j]&0x1F)<<2); } } }