2 * GraphLCD plugin for the Video Disk Recorder
4 * bmp.c - bmp logo class
6 * (C) 2004 Andreas Brachold <vdr04 AT deltab de>
7 * (C) 2001-2004 Carsten Siebholz <c.siebholz AT t-online de>
10 /***************************************************************************
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
17 * This program is distributed in the hope that it will be useful, *
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20 * GNU General Public License for more details. *
22 * You should have received a copy of the GNU General Public License *
23 * along with this program; *
24 * if not, write to the Free Software Foundation, Inc., *
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
27 ***************************************************************************/
35 #include <glcdgraphics/bitmap.h>
36 #include <glcdgraphics/image.h>
43 uint16_t bmpIdentifier;
46 uint32_t bmpBitmapDataOffset;
47 uint32_t bmpBitmapHeaderSize;
51 uint16_t bmpBitsPerPixel;
52 uint32_t bmpCompression;
53 uint32_t bmpBitmapDataSize;
54 uint32_t bmpHResolution;
55 uint32_t bmpVResolution;
57 uint32_t bmpImportantColors;
58 } BMPHEADER; // 54 bytes
69 uint8_t bitmask[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
70 uint8_t bitmaskl[8] = {0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff};
71 uint8_t bitmaskr[8] = {0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01};
81 bool cBMPFile::Load(GLCD::cImage & image, const std::string & fileName)
92 uint8_t * bitmap = NULL;
95 if (fileName.length() > 0)
97 fIN = fopen(fileName.c_str(), "rb");
100 if (fread(&bmpHeader, sizeof(BMPHEADER), 1, fIN)!=1)
106 // check for Windows BMP
107 if (bmpHeader.bmpBitmapHeaderSize != 0x00000028 )
109 fprintf(stderr, "ERROR: only Windows BMP images are allowed.\n");
115 iNumColors = (1 << bmpHeader.bmpBitsPerPixel);
118 fprintf(stderr, "ERROR: the image has %ld colors, but only images with 2 colors are allowed.\n", iNumColors);
123 iSize = bmpHeader.bmpHeight * bmpHeader.bmpWidth;
125 pPalette = (RGBQUAD *) malloc( iNumColors*sizeof(RGBQUAD));
128 fprintf(stderr, "ERROR: cannot allocate memory\n");
133 if (fread( pPalette, iNumColors*sizeof(RGBQUAD), 1, fIN)!=1)
141 if (pPalette->rgbBlue+pPalette->rgbGreen+pPalette->rgbRed <
142 (pPalette+1)->rgbBlue+(pPalette+1)->rgbGreen+(pPalette+1)->rgbRed)
144 // index 0 represents 'black', index 1 'white'
149 // index 0 represents 'white', index 1 'black'
152 if (fseek(fIN, bmpHeader.bmpBitmapDataOffset, SEEK_SET)==EOF)
159 switch (bmpHeader.bmpCompression)
161 case 0: // BI_RGB no compression
163 image.SetWidth(bmpHeader.bmpWidth);
164 image.SetHeight(bmpHeader.bmpHeight);
166 bitmap = new unsigned char[bmpHeader.bmpHeight * ((bmpHeader.bmpWidth + 7) / 8)];
169 fprintf(stderr, "ERROR: cannot allocate memory\n");
176 for (y = bmpHeader.bmpHeight; y > 0; y--)
178 pByte = (char*)bitmap + (y-1)*((bmpHeader.bmpWidth+7)/8);
180 for (x = 0; x < bmpHeader.bmpWidth / 8; x++)
182 if (fread(pByte, sizeof(char), 1, fIN) != 1)
192 *pByte = *pByte ^ 0xff;
196 if (bmpHeader.bmpWidth % 8)
198 if (fread(pByte, sizeof(char), 1, fIN) != 1)
208 *pByte = *pByte^0xff;
209 *pByte = *pByte & bitmaskl[bmpHeader.bmpWidth%8];
213 // Scan line must be 4-byte-alligned
216 if (fread(&Dummy, sizeof(char), 1, fIN) != 1)
227 image.AddBitmap(new GLCD::cBitmap(bmpHeader.bmpWidth, bmpHeader.bmpHeight, bitmap));
229 case 1: // BI_RLE4 RLE 4bit/pixel
230 case 2: // BI_RLE8 RLE 8bit/pixel
231 case 3: // BI_BITFIELDS
233 fprintf(stderr, "ERROR: only uncompressed RGB images are allowed.\n");
243 fprintf(stderr, "ERROR: cannot open picture %s\n", fileName.c_str());
248 fprintf(stderr, "ERROR: no FileName given!\n");
253 bool cBMPFile::Save(const GLCD::cBitmap * bitmap, const std::string & fileName)
257 RGBQUAD bmpColor1, bmpColor2;
258 uint32_t dBDO, dBDSx, dBDS;
263 const uint8_t * bmpdata = bitmap->Data();
266 && bitmap->Width() > 0
267 && bitmap->Height() > 0)
269 memset(&bmpHeader, 0, sizeof(BMPHEADER));
271 dBDO = sizeof(BMPHEADER)+2*sizeof(RGBQUAD);
272 dBDSx = ((bitmap->Width() + 7) / 8 + 3) & 0xfffffffc;
273 dBDS = dBDSx * bitmap->Height();
275 bmpHeader.bmpIdentifier = 0x4d42; // "BM"
276 bmpHeader.bmpFileSize = dBDO + dBDS;
277 bmpHeader.bmpBitmapDataOffset = dBDO;
278 bmpHeader.bmpBitmapHeaderSize = 0x28;
279 bmpHeader.bmpWidth = bitmap->Width();
280 bmpHeader.bmpHeight = bitmap->Height();
281 bmpHeader.bmpPlanes = 0x01;
282 bmpHeader.bmpBitsPerPixel = 0x01;
283 bmpHeader.bmpCompression = 0x00;
284 bmpHeader.bmpBitmapDataSize = dBDS;
285 bmpHeader.bmpHResolution = 0xb13; // 72dpi
286 bmpHeader.bmpVResolution = 0xb13; // 72dpi
287 bmpHeader.bmpColors = 0x02;
288 bmpHeader.bmpImportantColors = 0x02;
290 bmpColor1.rgbBlue = 0x00;
291 bmpColor1.rgbGreen = 0x00;
292 bmpColor1.rgbRed = 0x00;
293 bmpColor1.rgbReserved = 0x00;
294 bmpColor2.rgbBlue = 0xff;
295 bmpColor2.rgbGreen = 0xff;
296 bmpColor2.rgbRed = 0xff;
297 bmpColor2.rgbReserved = 0x00;
300 fOut = fopen(fileName.c_str(), "wb");
303 fprintf(stderr,"Cannot create file: %s\n", fileName.c_str());
306 fwrite(&bmpHeader, sizeof(BMPHEADER), 1, fOut);
307 fwrite(&bmpColor1, sizeof(RGBQUAD), 1, fOut);
308 fwrite(&bmpColor2, sizeof(RGBQUAD), 1, fOut);
310 for (y=bitmap->Height(); y>0; y--)
312 pByte = (char*)bmpdata + (y-1)*((bitmap->Width()+7)/8);
314 for (x=0; x<(uint32_t) bitmap->Width()/8; x++)
316 *pByte = *pByte^0xff;
317 if (fwrite(pByte, sizeof(char), 1, fOut)!=1)
325 // Scan line must be 4-byte-alligned
328 if (fwrite(&Dummy, sizeof(char), 1, fOut)!=1)
341 bool cBMPFile::Save(GLCD::cImage & image, const std::string & fileName)
343 const GLCD::cBitmap * bitmap;
345 if (image.Count() == 1)
347 bitmap = image.GetBitmap(0);
350 if (!Save(bitmap, fileName))
361 for (i = 0; i < image.Count(); i++)
363 sprintf(tmpStr, "%.248s.%05d", fileName.c_str(), i);
364 bitmap = image.GetBitmap(i);
367 if (!Save(bitmap, tmpStr))