![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Graphical demo for the LPC4088 Experiment Base Board with one of the Display Expansion Kits. This program decodes decodes and shows two png images.
bmp.cpp@0:b567d56a59d7, 2014-10-03 (annotated)
- Committer:
- embeddedartists
- Date:
- Fri Oct 03 13:30:09 2014 +0000
- Revision:
- 0:b567d56a59d7
First version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
embeddedartists | 0:b567d56a59d7 | 1 | /* ---------------------------------------------------------------------------- |
embeddedartists | 0:b567d56a59d7 | 2 | * ATMEL Microcontroller Software Support - ROUSSET - |
embeddedartists | 0:b567d56a59d7 | 3 | * ---------------------------------------------------------------------------- |
embeddedartists | 0:b567d56a59d7 | 4 | * Copyright (c) 2006, Atmel Corporation |
embeddedartists | 0:b567d56a59d7 | 5 | |
embeddedartists | 0:b567d56a59d7 | 6 | * All rights reserved. |
embeddedartists | 0:b567d56a59d7 | 7 | * |
embeddedartists | 0:b567d56a59d7 | 8 | * Redistribution and use in source and binary forms, with or without |
embeddedartists | 0:b567d56a59d7 | 9 | * modification, are permitted provided that the following conditions are met: |
embeddedartists | 0:b567d56a59d7 | 10 | * |
embeddedartists | 0:b567d56a59d7 | 11 | * - Redistributions of source code must retain the above copyright notice, |
embeddedartists | 0:b567d56a59d7 | 12 | * this list of conditions and the disclaiimer below. |
embeddedartists | 0:b567d56a59d7 | 13 | * |
embeddedartists | 0:b567d56a59d7 | 14 | * - Redistributions in binary form must reproduce the above copyright notice, |
embeddedartists | 0:b567d56a59d7 | 15 | * this list of conditions and the disclaimer below in the documentation and/or |
embeddedartists | 0:b567d56a59d7 | 16 | * other materials provided with the distribution. |
embeddedartists | 0:b567d56a59d7 | 17 | * |
embeddedartists | 0:b567d56a59d7 | 18 | * Atmel's name may not be used to endorse or promote products derived from |
embeddedartists | 0:b567d56a59d7 | 19 | * this software without specific prior written permission. |
embeddedartists | 0:b567d56a59d7 | 20 | * |
embeddedartists | 0:b567d56a59d7 | 21 | * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR |
embeddedartists | 0:b567d56a59d7 | 22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
embeddedartists | 0:b567d56a59d7 | 23 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE |
embeddedartists | 0:b567d56a59d7 | 24 | * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, |
embeddedartists | 0:b567d56a59d7 | 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
embeddedartists | 0:b567d56a59d7 | 26 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, |
embeddedartists | 0:b567d56a59d7 | 27 | * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
embeddedartists | 0:b567d56a59d7 | 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
embeddedartists | 0:b567d56a59d7 | 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, |
embeddedartists | 0:b567d56a59d7 | 30 | * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
embeddedartists | 0:b567d56a59d7 | 31 | * ---------------------------------------------------------------------------- |
embeddedartists | 0:b567d56a59d7 | 32 | */ |
embeddedartists | 0:b567d56a59d7 | 33 | |
embeddedartists | 0:b567d56a59d7 | 34 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 35 | // Headers |
embeddedartists | 0:b567d56a59d7 | 36 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 37 | |
embeddedartists | 0:b567d56a59d7 | 38 | #include "mbed.h" |
embeddedartists | 0:b567d56a59d7 | 39 | #include "bmp.h" |
embeddedartists | 0:b567d56a59d7 | 40 | |
embeddedartists | 0:b567d56a59d7 | 41 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 42 | // Internal constants |
embeddedartists | 0:b567d56a59d7 | 43 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 44 | |
embeddedartists | 0:b567d56a59d7 | 45 | /// BMP magic number ('BM'). |
embeddedartists | 0:b567d56a59d7 | 46 | #define BMP_TYPE 0x4D42 |
embeddedartists | 0:b567d56a59d7 | 47 | |
embeddedartists | 0:b567d56a59d7 | 48 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 49 | // Internal types |
embeddedartists | 0:b567d56a59d7 | 50 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 51 | |
embeddedartists | 0:b567d56a59d7 | 52 | struct BMPPaletteEntry { |
embeddedartists | 0:b567d56a59d7 | 53 | |
embeddedartists | 0:b567d56a59d7 | 54 | unsigned char b; |
embeddedartists | 0:b567d56a59d7 | 55 | unsigned char g; |
embeddedartists | 0:b567d56a59d7 | 56 | unsigned char r; |
embeddedartists | 0:b567d56a59d7 | 57 | unsigned char filler; |
embeddedartists | 0:b567d56a59d7 | 58 | }; |
embeddedartists | 0:b567d56a59d7 | 59 | |
embeddedartists | 0:b567d56a59d7 | 60 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 61 | // Exported functions |
embeddedartists | 0:b567d56a59d7 | 62 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 63 | |
embeddedartists | 0:b567d56a59d7 | 64 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 65 | /// Returns 1 if the header of a BMP file is valid; otherwise returns 0. |
embeddedartists | 0:b567d56a59d7 | 66 | /// \param file Buffer holding the file to examinate. |
embeddedartists | 0:b567d56a59d7 | 67 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 68 | unsigned char BMP_IsValid(void *file) |
embeddedartists | 0:b567d56a59d7 | 69 | { |
embeddedartists | 0:b567d56a59d7 | 70 | return ((struct BMPHeader *) file)->type == BMP_TYPE; |
embeddedartists | 0:b567d56a59d7 | 71 | } |
embeddedartists | 0:b567d56a59d7 | 72 | |
embeddedartists | 0:b567d56a59d7 | 73 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 74 | /// Returns the size of a BMP image given at least its header (the file does |
embeddedartists | 0:b567d56a59d7 | 75 | /// not have to be complete). |
embeddedartists | 0:b567d56a59d7 | 76 | /// \param file Pointer to the buffer which holds the BMP file. |
embeddedartists | 0:b567d56a59d7 | 77 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 78 | unsigned int BMP_GetFileSize(void *file) |
embeddedartists | 0:b567d56a59d7 | 79 | { |
embeddedartists | 0:b567d56a59d7 | 80 | return ((struct BMPHeader *) file)->fileSize; |
embeddedartists | 0:b567d56a59d7 | 81 | } |
embeddedartists | 0:b567d56a59d7 | 82 | |
embeddedartists | 0:b567d56a59d7 | 83 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 84 | /// Loads a BMP image located at the given address, decodes it and stores the |
embeddedartists | 0:b567d56a59d7 | 85 | /// resulting image inside the provided buffer. Image must have the specified |
embeddedartists | 0:b567d56a59d7 | 86 | /// width & height. |
embeddedartists | 0:b567d56a59d7 | 87 | /// Returns 0 if the image has been loaded; otherwise returns an error code. |
embeddedartists | 0:b567d56a59d7 | 88 | /// \param file Buffer which holds the BMP file. |
embeddedartists | 0:b567d56a59d7 | 89 | /// \param buffer Buffer in which to store the decoded image. |
embeddedartists | 0:b567d56a59d7 | 90 | /// \param width Buffer width in pixels. |
embeddedartists | 0:b567d56a59d7 | 91 | /// \param height Buffer height in pixels. |
embeddedartists | 0:b567d56a59d7 | 92 | /// \param bpp Number of bits per pixels that the buffer stores. |
embeddedartists | 0:b567d56a59d7 | 93 | //------------------------------------------------------------------------------ |
embeddedartists | 0:b567d56a59d7 | 94 | unsigned char BMP_Decode( |
embeddedartists | 0:b567d56a59d7 | 95 | void *file, |
embeddedartists | 0:b567d56a59d7 | 96 | unsigned char *buffer, |
embeddedartists | 0:b567d56a59d7 | 97 | unsigned int width, |
embeddedartists | 0:b567d56a59d7 | 98 | unsigned int height, |
embeddedartists | 0:b567d56a59d7 | 99 | unsigned char bpp) |
embeddedartists | 0:b567d56a59d7 | 100 | { |
embeddedartists | 0:b567d56a59d7 | 101 | struct BMPHeader *header; |
embeddedartists | 0:b567d56a59d7 | 102 | unsigned int i, j; |
embeddedartists | 0:b567d56a59d7 | 103 | unsigned char r, g, b; |
embeddedartists | 0:b567d56a59d7 | 104 | unsigned char *image; |
embeddedartists | 0:b567d56a59d7 | 105 | |
embeddedartists | 0:b567d56a59d7 | 106 | // Read header information |
embeddedartists | 0:b567d56a59d7 | 107 | header = (struct BMPHeader *) file; |
embeddedartists | 0:b567d56a59d7 | 108 | |
embeddedartists | 0:b567d56a59d7 | 109 | // Verify that the file is valid |
embeddedartists | 0:b567d56a59d7 | 110 | if (!BMP_IsValid(file)) { |
embeddedartists | 0:b567d56a59d7 | 111 | |
embeddedartists | 0:b567d56a59d7 | 112 | printf("BMP_Decode: File type is not 'BM' (0x%x).\n\r", |
embeddedartists | 0:b567d56a59d7 | 113 | header->type); |
embeddedartists | 0:b567d56a59d7 | 114 | return 1; |
embeddedartists | 0:b567d56a59d7 | 115 | } |
embeddedartists | 0:b567d56a59d7 | 116 | |
embeddedartists | 0:b567d56a59d7 | 117 | // Check that parameters match |
embeddedartists | 0:b567d56a59d7 | 118 | if ((header->compression != 0) |
embeddedartists | 0:b567d56a59d7 | 119 | || (header->width != width) |
embeddedartists | 0:b567d56a59d7 | 120 | || (header->height != height)) { |
embeddedartists | 0:b567d56a59d7 | 121 | |
embeddedartists | 0:b567d56a59d7 | 122 | printf("BMP_Decode: File format not supported\n\r"); |
embeddedartists | 0:b567d56a59d7 | 123 | printf(" -> .compression = %d\n\r", header->compression); |
embeddedartists | 0:b567d56a59d7 | 124 | printf(" -> .width = %d\n\r", header->width); |
embeddedartists | 0:b567d56a59d7 | 125 | printf(" -> .height = %d\n\r", header->height); |
embeddedartists | 0:b567d56a59d7 | 126 | printf(" -> .bits = %d\n\r", header->bits); |
embeddedartists | 0:b567d56a59d7 | 127 | return 2; |
embeddedartists | 0:b567d56a59d7 | 128 | } |
embeddedartists | 0:b567d56a59d7 | 129 | |
embeddedartists | 0:b567d56a59d7 | 130 | // Get image data |
embeddedartists | 0:b567d56a59d7 | 131 | image = (unsigned char *) ((unsigned int) file + header->offset); |
embeddedartists | 0:b567d56a59d7 | 132 | |
embeddedartists | 0:b567d56a59d7 | 133 | // Check that the bpp resolution is supported |
embeddedartists | 0:b567d56a59d7 | 134 | // Only a 24-bit output & 24- or 8-bit input are supported |
embeddedartists | 0:b567d56a59d7 | 135 | if (bpp != 24) { |
embeddedartists | 0:b567d56a59d7 | 136 | |
embeddedartists | 0:b567d56a59d7 | 137 | printf("BMP_Decode: Output resolution not supported\n\r"); |
embeddedartists | 0:b567d56a59d7 | 138 | return 3; |
embeddedartists | 0:b567d56a59d7 | 139 | } |
embeddedartists | 0:b567d56a59d7 | 140 | else if (header->bits == 24) { |
embeddedartists | 0:b567d56a59d7 | 141 | |
embeddedartists | 0:b567d56a59d7 | 142 | // Modified by Embedded Artists. This padding was not handled in the original |
embeddedartists | 0:b567d56a59d7 | 143 | // implementation. Each row in the Pixel Array is padded to a multiple of 4 bytes in size |
embeddedartists | 0:b567d56a59d7 | 144 | int rowWidthBytes = width * 3; |
embeddedartists | 0:b567d56a59d7 | 145 | rowWidthBytes += (rowWidthBytes % 4); |
embeddedartists | 0:b567d56a59d7 | 146 | |
embeddedartists | 0:b567d56a59d7 | 147 | // Copy raw data from BMP to buffer (reversing row order) |
embeddedartists | 0:b567d56a59d7 | 148 | for (i=0; i < height; i++) { |
embeddedartists | 0:b567d56a59d7 | 149 | #if 1 |
embeddedartists | 0:b567d56a59d7 | 150 | // Modified by Embedded Artists to convert to 565-format instead of 24 bit |
embeddedartists | 0:b567d56a59d7 | 151 | int x; |
embeddedartists | 0:b567d56a59d7 | 152 | for(x=0; x<width; x++) |
embeddedartists | 0:b567d56a59d7 | 153 | { |
embeddedartists | 0:b567d56a59d7 | 154 | r = *(unsigned char *)(image + (height - i - 1) * rowWidthBytes + 3*x + 2); |
embeddedartists | 0:b567d56a59d7 | 155 | g = *(unsigned char *)(image + (height - i - 1) * rowWidthBytes + 3*x + 1); |
embeddedartists | 0:b567d56a59d7 | 156 | b = *(unsigned char *)(image + (height - i - 1) * rowWidthBytes + 3*x + 0); |
embeddedartists | 0:b567d56a59d7 | 157 | *(unsigned short *)(buffer + (i * width) * 2 + 2*x) = (((unsigned short)r & 0xF8) << 8) | |
embeddedartists | 0:b567d56a59d7 | 158 | (((unsigned short)g & 0xFC) << 3) | |
embeddedartists | 0:b567d56a59d7 | 159 | (((unsigned short)b & 0xF8) >> 3); |
embeddedartists | 0:b567d56a59d7 | 160 | } |
embeddedartists | 0:b567d56a59d7 | 161 | #else |
embeddedartists | 0:b567d56a59d7 | 162 | memcpy(buffer + (i * width) * 3, |
embeddedartists | 0:b567d56a59d7 | 163 | image + ((height - i - 1) * width) * 3, |
embeddedartists | 0:b567d56a59d7 | 164 | width * 3); |
embeddedartists | 0:b567d56a59d7 | 165 | #endif |
embeddedartists | 0:b567d56a59d7 | 166 | } |
embeddedartists | 0:b567d56a59d7 | 167 | |
embeddedartists | 0:b567d56a59d7 | 168 | #if 0 |
embeddedartists | 0:b567d56a59d7 | 169 | // Swap red and blue |
embeddedartists | 0:b567d56a59d7 | 170 | for (i=0; i < height; i++) { |
embeddedartists | 0:b567d56a59d7 | 171 | for (j=0; j < width; j++) { |
embeddedartists | 0:b567d56a59d7 | 172 | |
embeddedartists | 0:b567d56a59d7 | 173 | r = buffer[(i * width + j) * 3 + 2]; |
embeddedartists | 0:b567d56a59d7 | 174 | g = buffer[(i * width + j) * 3 + 1]; |
embeddedartists | 0:b567d56a59d7 | 175 | b = buffer[(i * width + j) * 3]; |
embeddedartists | 0:b567d56a59d7 | 176 | |
embeddedartists | 0:b567d56a59d7 | 177 | buffer[(i * width + j) * 3] = r; |
embeddedartists | 0:b567d56a59d7 | 178 | buffer[(i * width + j) * 3 + 1] = g; |
embeddedartists | 0:b567d56a59d7 | 179 | buffer[(i * width + j) * 3 + 2] = b; |
embeddedartists | 0:b567d56a59d7 | 180 | } |
embeddedartists | 0:b567d56a59d7 | 181 | } |
embeddedartists | 0:b567d56a59d7 | 182 | #endif |
embeddedartists | 0:b567d56a59d7 | 183 | } |
embeddedartists | 0:b567d56a59d7 | 184 | else if (header->bits == 8) { |
embeddedartists | 0:b567d56a59d7 | 185 | |
embeddedartists | 0:b567d56a59d7 | 186 | // Retrieve palette |
embeddedartists | 0:b567d56a59d7 | 187 | struct BMPPaletteEntry palette[256]; |
embeddedartists | 0:b567d56a59d7 | 188 | memcpy(palette, |
embeddedartists | 0:b567d56a59d7 | 189 | (unsigned char *) ((unsigned int) file + sizeof(struct BMPHeader)), |
embeddedartists | 0:b567d56a59d7 | 190 | header->offset - sizeof(struct BMPHeader)); |
embeddedartists | 0:b567d56a59d7 | 191 | |
embeddedartists | 0:b567d56a59d7 | 192 | // Decode image (reversing row order) |
embeddedartists | 0:b567d56a59d7 | 193 | for (i=0; i < height; i++) { |
embeddedartists | 0:b567d56a59d7 | 194 | for (j=0; j < width; j++) { |
embeddedartists | 0:b567d56a59d7 | 195 | |
embeddedartists | 0:b567d56a59d7 | 196 | r = palette[image[(height - i - 1) * width + j]].r; |
embeddedartists | 0:b567d56a59d7 | 197 | g = palette[image[(height - i - 1) * width + j]].g; |
embeddedartists | 0:b567d56a59d7 | 198 | b = palette[image[(height - i - 1) * width + j]].b; |
embeddedartists | 0:b567d56a59d7 | 199 | |
embeddedartists | 0:b567d56a59d7 | 200 | buffer[(i * width + j) * 3] = r; |
embeddedartists | 0:b567d56a59d7 | 201 | buffer[(i * width + j) * 3 + 1] = g; |
embeddedartists | 0:b567d56a59d7 | 202 | buffer[(i * width + j) * 3 + 2] = b; |
embeddedartists | 0:b567d56a59d7 | 203 | } |
embeddedartists | 0:b567d56a59d7 | 204 | } |
embeddedartists | 0:b567d56a59d7 | 205 | } |
embeddedartists | 0:b567d56a59d7 | 206 | else { |
embeddedartists | 0:b567d56a59d7 | 207 | |
embeddedartists | 0:b567d56a59d7 | 208 | printf("BMP_Decode: Input resolution not supported\n\r"); |
embeddedartists | 0:b567d56a59d7 | 209 | return 4; |
embeddedartists | 0:b567d56a59d7 | 210 | } |
embeddedartists | 0:b567d56a59d7 | 211 | |
embeddedartists | 0:b567d56a59d7 | 212 | return 0; |
embeddedartists | 0:b567d56a59d7 | 213 | } |
embeddedartists | 0:b567d56a59d7 | 214 | |
embeddedartists | 0:b567d56a59d7 | 215 |