/* ---------------------------------------------------------------------------- * 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 "bmp.h" #include #include #include //----------------------------------------------------------------------------- // Define //----------------------------------------------------------------------------- /// BMP offset for header #define IMAGE_OFFSET 0x100 //------------------------------------------------------------------------------ // Internal constants //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ // Internal types //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /// Describe the BMP palette //------------------------------------------------------------------------------ struct BMPPaletteEntry { /// Blue value unsigned char b; /// Green value unsigned char g; /// Red value unsigned char r; /// Filler character value unsigned char filler; }; //------------------------------------------------------------------------------ // 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. //------------------------------------------------------------------------------ unsigned char BMP_IsValid(void *file) { return ((struct 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 //------------------------------------------------------------------------------ unsigned int BMP_GetFileSize(void *file) { return ((struct 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 bmpRgb Type of BMP (YUV or RGB) /// \param nbByte_Pixels Number of byte per pixels //----------------------------------------------------------------------------- void WriteBMPheader(unsigned int* pAddressHeader, unsigned int bmpHSize, unsigned int bmpVSize, unsigned char bmpRgb, unsigned char nbByte_Pixels) { unsigned int i; unsigned int* fill; struct BMPHeader *Header; fill = pAddressHeader; for (i=0; itype = 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 //------------------------------------------------------------------------------ void BMP_displayHeader(unsigned int* pAddressHeader) { struct BMPHeader *header; header = (struct 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); } //------------------------------------------------------------------------------ /// 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. //------------------------------------------------------------------------------ unsigned char BMP_Decode( void *file, unsigned char *buffer, unsigned int width, unsigned int height, unsigned char bpp) { struct BMPHeader *header; unsigned int i, j; unsigned char r, g, b; unsigned char *image; // Read header information header = (struct 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", header->compression); TRACE_ERROR(" -> .width = %u\n\r", header->width); TRACE_ERROR(" -> .height = %u\n\r", header->height); TRACE_ERROR(" -> .bits = %d\n\r", header->bits); return 2; } // Get image data image = (unsigned char *) ((unsigned int) 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; #elif defined(BOARD_LCD_BGR565) 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) { // Decoding is ok if (!buffer) return 0; // Retrieve palette struct BMPPaletteEntry palette[256]; memcpy(palette, (unsigned char *) ((unsigned int) file + sizeof(struct BMPHeader)), header->offset - sizeof(struct 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( unsigned char *fileSource, unsigned char *fileDestination, unsigned int width, unsigned int height, unsigned char bpp) { unsigned int i; unsigned int j; unsigned int 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); } } }