blob: 8fcd8ca92ea6c9f0957df37965db59bba6dc796c [file] [log] [blame]
Daniel Stenberg1c0c8612002-05-17 12:22:24 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Linus Nielsen Feltzing
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +000021
22/*
232005-04-16 Tomas Salfischberger:
24 - New BMP loader function, based on the old one (borrowed a lot of
25 calculations and checks there.)
26 - Conversion part needs some optimization, doing unneeded calulations now.
Jens Arnoldadc48482006-11-18 14:29:51 +0000272006-11-18 Jens Arnold: complete rework
28 - All canonical formats supported now (1, 4, 8, 15/16, 24 and 32 bit)
29 - better protection against malformed / non-standard BMPs
30 - code heavily optimised for both size and speed
31 - dithering for 2 bit targets
Andrew Mahone781421a2008-12-09 23:07:59 +0000322008-11-02 Akio Idehara: refactor for scaler frontend
332008-12-08 Andrew Mahone: partial-line reading, scaler frontend
34 - read_part_line does the actual source BMP reading, return columns read
35 and updates fields in a struct bmp_args with the new data and current
36 reader state
37 - skip_lines_bmp and store_part_bmp implement the scaler callbacks to skip
38 ahead by whole lines, or read the next chunk of the current line
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +000039*/
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000040
41#include <stdio.h>
42#include <stdlib.h>
Linus Nielsen Feltzing745adad2006-01-28 12:12:42 +000043#include <string.h>
Jens Arnold83e18d92006-11-11 11:26:42 +000044#include "inttypes.h"
Andrew Mahone4eedc932009-01-04 21:22:05 +000045#ifndef PLUGIN
Felix Arends1f50b8b2002-05-29 14:36:09 +000046#include "debug.h"
Andrew Mahone4eedc932009-01-04 21:22:05 +000047#endif
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +000048#include "lcd.h"
Dave Chapman78d29f52008-03-26 23:35:34 +000049#include "file.h"
Maurus Cuelenaere36c71a62009-01-29 20:49:43 +000050#include "bmp.h"
Jens Arnold848e0b52006-11-20 00:20:09 +000051#ifdef HAVE_REMOTE_LCD
52#include "lcd-remote.h"
53#endif
Andrew Mahone781421a2008-12-09 23:07:59 +000054#ifdef ROCKBOX_DEBUG_BMP_LOADER
55#define BDEBUGF DEBUGF
56#else
57#define BDEBUGF(...)
58#endif
Dave Chapmanb9bb7232008-03-26 18:18:22 +000059#ifndef __PCTOOL__
Linus Nielsen Feltzing745adad2006-01-28 12:12:42 +000060#include "config.h"
Michael Sevakis756ce4a2006-10-11 01:43:53 +000061#include "system.h"
Andrew Mahone781421a2008-12-09 23:07:59 +000062#include "resize.h"
Dave Chapmanb9bb7232008-03-26 18:18:22 +000063#else
Maurus Cuelenaere36c71a62009-01-29 20:49:43 +000064#include "checkwps.h"
Dave Chapmanb9bb7232008-03-26 18:18:22 +000065#undef DEBUGF
66#define DEBUGF(...)
67#endif
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000068
69#ifdef __GNUC__
70#define STRUCT_PACKED __attribute__((packed))
Felix Arends1f50b8b2002-05-29 14:36:09 +000071#else
72#define STRUCT_PACKED
73#pragma pack (push, 2)
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000074#endif
75
Jens Arnoldadc48482006-11-18 14:29:51 +000076/* BMP header structure */
77struct bmp_header {
78 uint16_t type; /* signature - 'BM' */
79 uint32_t size; /* file size in bytes */
80 uint16_t reserved1; /* 0 */
81 uint16_t reserved2; /* 0 */
82 uint32_t off_bits; /* offset to bitmap */
83 uint32_t struct_size; /* size of this struct (40) */
Jens Arnold89bfb662007-11-30 08:51:18 +000084 int32_t width; /* bmap width in pixels */
85 int32_t height; /* bmap height in pixels */
Jens Arnoldadc48482006-11-18 14:29:51 +000086 uint16_t planes; /* num planes - always 1 */
87 uint16_t bit_count; /* bits per pixel */
88 uint32_t compression; /* compression flag */
89 uint32_t size_image; /* image size in bytes */
90 int32_t x_pels_per_meter; /* horz resolution */
91 int32_t y_pels_per_meter; /* vert resolution */
92 uint32_t clr_used; /* 0 -> color table size */
93 uint32_t clr_important; /* important color count */
Daniel Stenberg1c0c8612002-05-17 12:22:24 +000094} STRUCT_PACKED;
95
Jens Arnoldadc48482006-11-18 14:29:51 +000096union rgb_union {
97 struct { /* Little endian */
98 unsigned char blue;
99 unsigned char green;
100 unsigned char red;
101 unsigned char reserved;
Michael Sevakis76a6aaa2006-10-11 01:26:09 +0000102 };
Jens Arnoldadc48482006-11-18 14:29:51 +0000103 uint32_t raw;
104};
Michael Sevakis76a6aaa2006-10-11 01:26:09 +0000105
Andrew Mahone781421a2008-12-09 23:07:59 +0000106/* masks for supported BI_BITFIELDS encodings (16/32 bit) */
107static const struct uint8_rgb bitfields[3][3] = {
108 /* 15bit */
109 {
110 { .blue = 0x00, .green = 0x7c, .red = 0x00 },
111 { .blue = 0xe0, .green = 0x03, .red = 0x00 },
112 { .blue = 0x1f, .green = 0x00, .red = 0x00 },
113 },
114 /* 16bit */
115 {
116 { .blue = 0x00, .green = 0xf8, .red = 0x00 },
117 { .blue = 0xe0, .green = 0x07, .red = 0x00 },
118 { .blue = 0x1f, .green = 0x00, .red = 0x00 },
119 },
120 /* 32bit */
121 {
122 { .blue = 0x00, .green = 0x00, .red = 0xff },
123 { .blue = 0x00, .green = 0xff, .red = 0x00 },
124 { .blue = 0xff, .green = 0x00, .red = 0x00 },
125 },
Jens Arnoldadc48482006-11-18 14:29:51 +0000126};
Michael Sevakis76a6aaa2006-10-11 01:26:09 +0000127
Andrew Mahone07e982d2009-01-08 02:49:23 +0000128#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000129/* the full 16x16 Bayer dither matrix may be calculated quickly with this table
130*/
131const unsigned char dither_table[16] =
132 { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 };
Jens Arnoldadc48482006-11-18 14:29:51 +0000133#endif
Michael Sevakisbed0db22006-10-11 18:12:36 +0000134
Jens Arnold81137172008-03-20 17:40:58 +0000135#if ((LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)) \
136 || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH == 2) \
137 && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED))
Andrew Mahone781421a2008-12-09 23:07:59 +0000138const unsigned short vi_pattern[4] = {
Jens Arnold848e0b52006-11-20 00:20:09 +0000139 0x0101, 0x0100, 0x0001, 0x0000
140};
141#endif
142
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000143/******************************************************************************
144 * read_bmp_file()
145 *
Jens Arnoldadc48482006-11-18 14:29:51 +0000146 * Reads a BMP file and puts the data in rockbox format in *bitmap.
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000147 *
148 *****************************************************************************/
Nicolas Pennequinec6569e2007-11-10 13:26:11 +0000149int read_bmp_file(const char* filename,
Linus Nielsen Feltzing745adad2006-01-28 12:12:42 +0000150 struct bitmap *bm,
151 int maxsize,
Andrew Mahone90586202008-12-26 07:05:13 +0000152 int format,
153 const struct custom_format *cformat)
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000154{
Nicolas Pennequinec6569e2007-11-10 13:26:11 +0000155 int fd, ret;
Andrew Mahone07e982d2009-01-08 02:49:23 +0000156 fd = open(filename, O_RDONLY);
Nicolas Pennequinec6569e2007-11-10 13:26:11 +0000157
158 /* Exit if file opening failed */
159 if (fd < 0) {
160 DEBUGF("read_bmp_file: can't open '%s', rc: %d\n", filename, fd);
161 return fd * 10 - 1;
162 }
163
Andrew Mahone781421a2008-12-09 23:07:59 +0000164 BDEBUGF("read_bmp_file: '%s' remote: %d resize: %d keep_aspect: %d\n",
165 filename, !!(format & FORMAT_REMOTE), !!(format & FORMAT_RESIZE),
166 !!(format & FORMAT_KEEP_ASPECT));
Andrew Mahone90586202008-12-26 07:05:13 +0000167 ret = read_bmp_fd(fd, bm, maxsize, format, cformat);
Andrew Mahone07e982d2009-01-08 02:49:23 +0000168 close(fd);
Nicolas Pennequinec6569e2007-11-10 13:26:11 +0000169 return ret;
170}
171
Andrew Mahone781421a2008-12-09 23:07:59 +0000172static inline void set_rgb_union(struct uint8_rgb *dst, union rgb_union src)
173{
174 dst->red = src.red;
175 dst->green = src.green;
176 dst->blue = src.blue;
177}
178
179struct bmp_args {
180 int fd;
181 short padded_width;
182 short read_width;
183 short width;
184 short depth;
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000185 unsigned char buf[BM_MAX_WIDTH * 4];
Andrew Mahone781421a2008-12-09 23:07:59 +0000186 struct uint8_rgb *palette;
Andrew Mahone20f76d62009-05-04 15:46:41 +0000187#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
188 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000189 int cur_row;
190 int cur_col;
191 struct img_part part;
192#endif
193};
194
195static unsigned int read_part_line(struct bmp_args *ba)
196{
197 const int padded_width = ba->padded_width;
198 const int read_width = ba->read_width;
199 const int width = ba->width;
200 const int depth = ba->depth;
Andrew Mahone20f76d62009-05-04 15:46:41 +0000201#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
202 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000203 int cur_row = ba->cur_row;
204 int cur_col = ba->cur_col;
205#endif
206 const int fd = ba->fd;
207 uint8_t *ibuf;
208 struct uint8_rgb *buf = (struct uint8_rgb *)(ba->buf);
209 const struct uint8_rgb *palette = ba->palette;
210 uint32_t component, data = data;
211 int ret;
212 int i, cols, len;
213
Andrew Mahone20f76d62009-05-04 15:46:41 +0000214#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
215 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000216 cols = MIN(width - cur_col,(int)BM_MAX_WIDTH);
217 BDEBUGF("reading %d cols (width: %d, max: %d)\n",cols,width,BM_MAX_WIDTH);
Andrew Mahone781421a2008-12-09 23:07:59 +0000218 len = (cols * (depth == 15 ? 16 : depth) + 7) >> 3;
219#else
220 cols = width;
221 len = read_width;
222#endif
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000223 ibuf = ((unsigned char *)buf) + (BM_MAX_WIDTH << 2) - len;
Andrew Mahone781421a2008-12-09 23:07:59 +0000224 BDEBUGF("read_part_line: cols=%d len=%d\n",cols,len);
Andrew Mahone07e982d2009-01-08 02:49:23 +0000225 ret = read(fd, ibuf, len);
Andrew Mahone781421a2008-12-09 23:07:59 +0000226 if (ret != len)
227 {
228 DEBUGF("read_part_line: error reading image, read returned %d "
229 "expected %d\n", ret, len);
Andrew Mahone20f76d62009-05-04 15:46:41 +0000230#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
231 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000232 BDEBUGF("cur_row: %d cur_col: %d cols: %d len: %d\n", cur_row, cur_col,
233 cols, len);
Andrew Mahone4eedc932009-01-04 21:22:05 +0000234#endif
Andrew Mahone781421a2008-12-09 23:07:59 +0000235 return 0;
236 }
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000237 while (ibuf < ba->buf + (BM_MAX_WIDTH << 2))
Andrew Mahone781421a2008-12-09 23:07:59 +0000238 {
239 switch (depth)
240 {
241 case 1:
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000242 data = *ibuf++;
243 for (i = 0; i < 8; i++)
244 {
245 *buf++ = palette[data & 0x80 ? 1 : 0];
246 data <<= 1;
247 }
Andrew Mahone781421a2008-12-09 23:07:59 +0000248 break;
249 case 4:
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000250 data = *ibuf++;
251 *buf++ = palette[data >> 4];
252 *buf++ = palette[data & 0xf];
Andrew Mahone781421a2008-12-09 23:07:59 +0000253 break;
254 case 8:
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000255 *buf++ = palette[*ibuf++];
Andrew Mahone781421a2008-12-09 23:07:59 +0000256 break;
257 case 15:
258 case 16:
259 data = letoh16(*(uint16_t*)ibuf);
260 component = (data << 3) & 0xf8;
261 component |= component >> 5;
262 buf->blue = component;
263 if (depth == 15)
264 {
265 data >>= 2;
266 component = data & 0xf8;
267 component |= component >> 5;
268 } else {
269 data >>= 3;
270 component = data & 0xfc;
271 component |= component >> 6;
272 }
273 buf->green = component;
274 data >>= 5;
275 component = data & 0xf8;
276 component |= component >> 5;
277 buf->red = component;
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000278 buf++;
Andrew Mahone781421a2008-12-09 23:07:59 +0000279 ibuf += 2;
280 break;
281 case 32:
282 case 24:
283 buf->blue = *ibuf++;
284 buf->green = *ibuf++;
285 buf->red = *ibuf++;
286 if (depth == 32)
287 ibuf++;
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000288 buf++;
Andrew Mahone781421a2008-12-09 23:07:59 +0000289 break;
290 }
Andrew Mahone781421a2008-12-09 23:07:59 +0000291 }
292
Andrew Mahone20f76d62009-05-04 15:46:41 +0000293#if !defined(HAVE_LCD_COLOR) && \
294 ((LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) || \
295 defined(PLUGIN))
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000296 ibuf = ba->buf;
297 buf = (struct uint8_rgb*)ba->buf;
298 while (ibuf < ba->buf + cols)
299 *ibuf++ = brightness(*buf++);
300#endif
301
Andrew Mahone20f76d62009-05-04 15:46:41 +0000302#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
303 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000304 cur_col += cols;
305 if (cur_col == width)
306 {
307#endif
308 int pad = padded_width - read_width;
309 if (pad > 0)
310 {
311 BDEBUGF("seeking %d bytes to next line\n",pad);
Andrew Mahone07e982d2009-01-08 02:49:23 +0000312 lseek(fd, pad, SEEK_CUR);
Andrew Mahone781421a2008-12-09 23:07:59 +0000313 }
Andrew Mahone20f76d62009-05-04 15:46:41 +0000314#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
315 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000316 cur_col = 0;
317 BDEBUGF("read_part_line: completed row %d\n", cur_row);
318 cur_row += 1;
319 }
320
321 ba->cur_row = cur_row;
322 ba->cur_col = cur_col;
323#endif
324 return cols;
325}
326
Andrew Mahone20f76d62009-05-04 15:46:41 +0000327#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
328 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000329static struct img_part *store_part_bmp(void *args)
330{
331 struct bmp_args *ba = (struct bmp_args *)args;
332
333 ba->part.len = read_part_line(ba);
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000334#ifdef HAVE_LCD_COLOR
Andrew Mahone781421a2008-12-09 23:07:59 +0000335 ba->part.buf = (struct uint8_rgb *)ba->buf;
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000336#else
337 ba->part.buf = (uint8_t *)ba->buf;
338#endif
Andrew Mahone781421a2008-12-09 23:07:59 +0000339 if (ba->part.len)
340 return &(ba->part);
341 else
342 return NULL;
343}
Andrew Mahone781421a2008-12-09 23:07:59 +0000344#endif
345
346static inline int rgbcmp(struct uint8_rgb rgb1, struct uint8_rgb rgb2)
347{
348 if ((rgb1.red == rgb2.red) && (rgb1.green == rgb2.green) &&
349 (rgb1.blue == rgb2.blue))
350 return 0;
351 else
352 return 1;
353}
Andrew Mahone91efc162009-05-09 07:31:27 +0000354#if LCD_DEPTH > 1
Andrew Mahone59e70b52009-05-09 10:32:07 +0000355#if !defined(PLUGIN) && !defined(HAVE_JPEG) && !defined(HAVE_BMP_SCALING)
356static inline
357#endif
Andrew Mahone91efc162009-05-09 07:31:27 +0000358void output_row_8_native(uint32_t row, void * row_in,
359 struct scaler_context *ctx)
360{
361 int col;
362 int fb_width = BM_WIDTH(ctx->bm->width,FORMAT_NATIVE,0);
363 uint8_t dy = DITHERY(row);
364#ifdef HAVE_LCD_COLOR
365 struct uint8_rgb *qp = (struct uint8_rgb*)row_in;
366#else
367 uint8_t *qp = (uint8_t*)row_in;
368#endif
369 BDEBUGF("output_row: y: %lu in: %p\n",row, row_in);
370#if LCD_DEPTH == 2
371#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
372 /* greyscale iPods */
373 fb_data *dest = (fb_data *)ctx->bm->data + fb_width * row;
374 int shift = 6;
375 int delta = 127;
376 unsigned bright;
377 unsigned data = 0;
378
379 for (col = 0; col < ctx->bm->width; col++) {
380 if (ctx->dither)
381 delta = DITHERXDY(col,dy);
382 bright = *qp++;
383 bright = (3 * bright + (bright >> 6) + delta) >> 8;
384 data |= (~bright & 3) << shift;
385 shift -= 2;
386 if (shift < 0) {
387 *dest++ = data;
388 data = 0;
389 shift = 6;
390 }
391 }
392 if (shift < 6)
393 *dest++ = data;
394#elif LCD_PIXELFORMAT == VERTICAL_PACKING
395 /* iriver H1x0 */
396 fb_data *dest = (fb_data *)ctx->bm->data + fb_width *
397 (row >> 2);
398 int shift = 2 * (row & 3);
399 int delta = 127;
400 unsigned bright;
401
402 for (col = 0; col < ctx->bm->width; col++) {
403 if (ctx->dither)
404 delta = DITHERXDY(col,dy);
405 bright = *qp++;
406 bright = (3 * bright + (bright >> 6) + delta) >> 8;
407 *dest++ |= (~bright & 3) << shift;
408 }
409#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
410 /* iAudio M3 */
411 fb_data *dest = (fb_data *)ctx->bm->data + fb_width *
412 (row >> 3);
413 int shift = row & 7;
414 int delta = 127;
415 unsigned bright;
416
417 for (col = 0; col < ctx->bm->width; col++) {
418 if (ctx->dither)
419 delta = DITHERXDY(col,dy);
420 bright = *qp++;
421 bright = (3 * bright + (bright >> 6) + delta) >> 8;
422 *dest++ |= vi_pattern[bright] << shift;
423 }
424#endif /* LCD_PIXELFORMAT */
425#elif LCD_DEPTH == 16
426 /* iriver h300, colour iPods, X5 */
427 fb_data *dest = (fb_data *)ctx->bm->data + fb_width * row;
428 int delta = 127;
429 unsigned r, g, b;
430 for (col = 0; col < ctx->bm->width; col++) {
431 if (ctx->dither)
432 delta = DITHERXDY(col,dy);
433 r = qp->red;
434 g = qp->green;
435 b = (qp++)->blue;
436 r = (31 * r + (r >> 3) + delta) >> 8;
437 g = (63 * g + (g >> 2) + delta) >> 8;
438 b = (31 * b + (b >> 3) + delta) >> 8;
439 *dest++ = LCD_RGBPACK_LCD(r, g, b);
440 }
441#endif /* LCD_DEPTH */
442}
443#endif
Andrew Mahone781421a2008-12-09 23:07:59 +0000444
Nicolas Pennequinec6569e2007-11-10 13:26:11 +0000445/******************************************************************************
446 * read_bmp_fd()
447 *
448 * Reads a BMP file in an open file descriptor and puts the data in rockbox
449 * format in *bitmap.
450 *
451 *****************************************************************************/
452int read_bmp_fd(int fd,
453 struct bitmap *bm,
454 int maxsize,
Andrew Mahone90586202008-12-26 07:05:13 +0000455 int format,
456 const struct custom_format *cformat)
Nicolas Pennequinec6569e2007-11-10 13:26:11 +0000457{
Jens Arnoldadc48482006-11-18 14:29:51 +0000458 struct bmp_header bmph;
Andrew Mahone781421a2008-12-09 23:07:59 +0000459 int padded_width;
460 int read_width;
Jens Arnoldadc48482006-11-18 14:29:51 +0000461 int depth, numcolors, compression, totalsize;
Andrew Mahone781421a2008-12-09 23:07:59 +0000462 int ret;
Maurus Cuelenaereaec37aa2009-05-25 11:12:27 +0000463 bool return_size = format & FORMAT_RETURN_SIZE;
Jens Arnoldadc48482006-11-18 14:29:51 +0000464
465 unsigned char *bitmap = bm->data;
Andrew Mahone781421a2008-12-09 23:07:59 +0000466 struct uint8_rgb palette[256];
Andrew Mahone781421a2008-12-09 23:07:59 +0000467 struct rowset rset;
468 struct dim src_dim;
Andrew Mahone20f76d62009-05-04 15:46:41 +0000469#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) || \
470 defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000471 bool dither = false;
Andrew Mahone20f76d62009-05-04 15:46:41 +0000472#endif
473#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
474 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
475 unsigned int resize = IMG_NORESIZE;
Andrew Mahone781421a2008-12-09 23:07:59 +0000476 bool transparent = false;
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000477
Andrew Mahone781421a2008-12-09 23:07:59 +0000478#ifdef HAVE_REMOTE_LCD
Andrew Mahone4eedc932009-01-04 21:22:05 +0000479 bool remote = false;
Jens Arnold848e0b52006-11-20 00:20:09 +0000480 if (format & FORMAT_REMOTE) {
481 remote = true;
482#if LCD_REMOTE_DEPTH == 1
483 format = FORMAT_MONO;
Jens Arnold848e0b52006-11-20 00:20:09 +0000484#endif
485 }
486#endif /* HAVE_REMOTE_LCD */
Andrew Mahone781421a2008-12-09 23:07:59 +0000487
488 if (format & FORMAT_RESIZE) {
489 resize = IMG_RESIZE;
Andrew Mahone781421a2008-12-09 23:07:59 +0000490 }
491
Jens Arnoldadc48482006-11-18 14:29:51 +0000492 if (format & FORMAT_TRANSPARENT) {
Linus Nielsen Feltzing3722a992006-01-29 09:58:53 +0000493 transparent = true;
Linus Nielsen Feltzing3722a992006-01-29 09:58:53 +0000494 }
Michael Sevakis76a6aaa2006-10-11 01:26:09 +0000495#else
Jens Arnoldadc48482006-11-18 14:29:51 +0000496
497 (void)format;
Andrew Mahone781421a2008-12-09 23:07:59 +0000498#endif /*(LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)*/
Andrew Mahone20f76d62009-05-04 15:46:41 +0000499#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) || \
500 defined(PLUGIN)
501 if (format & FORMAT_DITHER) {
502 dither = true;
503 }
504#endif
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000505 /* read fileheader */
Andrew Mahone07e982d2009-01-08 02:49:23 +0000506 ret = read(fd, &bmph, sizeof(struct bmp_header));
Jens Arnoldadc48482006-11-18 14:29:51 +0000507 if (ret < 0) {
Jens Arnoldadc48482006-11-18 14:29:51 +0000508 return ret * 10 - 2;
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000509 }
Michael Sevakise0710b22006-10-15 17:51:00 +0000510
Jens Arnoldadc48482006-11-18 14:29:51 +0000511 if (ret != sizeof(struct bmp_header)) {
Nicolas Pennequinec6569e2007-11-10 13:26:11 +0000512 DEBUGF("read_bmp_fd: can't read BMP header.");
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000513 return -3;
514 }
515
Andrew Mahone781421a2008-12-09 23:07:59 +0000516 src_dim.width = letoh32(bmph.width);
517 src_dim.height = letoh32(bmph.height);
518 if (src_dim.height < 0) { /* Top-down BMP file */
519 src_dim.height = -src_dim.height;
520 rset.rowstep = 1;
Jens Arnold89bfb662007-11-30 08:51:18 +0000521 } else { /* normal BMP */
Andrew Mahone781421a2008-12-09 23:07:59 +0000522 rset.rowstep = -1;
Jens Arnold89bfb662007-11-30 08:51:18 +0000523 }
524
Andrew Mahone781421a2008-12-09 23:07:59 +0000525 depth = letoh16(bmph.bit_count);
526 /* 4-byte boundary aligned */
527 read_width = ((src_dim.width * (depth == 15 ? 16 : depth) + 7) >> 3);
528 padded_width = (read_width + 3) & ~3;
Jens Arnoldadc48482006-11-18 14:29:51 +0000529
Andrew Mahone781421a2008-12-09 23:07:59 +0000530 BDEBUGF("width: %d height: %d depth: %d padded_width: %d\n", src_dim.width,
531 src_dim.height, depth, padded_width);
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000532
533#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
Andrew Mahone781421a2008-12-09 23:07:59 +0000534 if ((format & 3) == FORMAT_ANY) {
Jens Arnoldadc48482006-11-18 14:29:51 +0000535 if (depth == 1)
Andrew Mahone781421a2008-12-09 23:07:59 +0000536 format = (format & ~3);
Jens Arnoldadc48482006-11-18 14:29:51 +0000537 else
Andrew Mahone781421a2008-12-09 23:07:59 +0000538 format = (format & ~3) | FORMAT_NATIVE;
Jens Arnoldadc48482006-11-18 14:29:51 +0000539 }
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000540 bm->format = format & 1;
541 if ((format & 1) == FORMAT_MONO)
Jens Arnoldadc48482006-11-18 14:29:51 +0000542 {
Andrew Mahone20f76d62009-05-04 15:46:41 +0000543#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
544 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000545 resize &= ~IMG_RESIZE;
546 resize |= IMG_NORESIZE;
Andrew Mahone20f76d62009-05-04 15:46:41 +0000547#endif
Andrew Mahone4eedc932009-01-04 21:22:05 +0000548#ifdef HAVE_REMOTE_LCD
Andrew Mahone781421a2008-12-09 23:07:59 +0000549 remote = 0;
Andrew Mahone4eedc932009-01-04 21:22:05 +0000550#endif
Jens Arnoldadc48482006-11-18 14:29:51 +0000551 }
Andrew Mahone4eedc932009-01-04 21:22:05 +0000552#elif !defined(PLUGIN)
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000553 if (src_dim.width > BM_MAX_WIDTH)
Andrew Mahone781421a2008-12-09 23:07:59 +0000554 return -6;
555#endif /*(LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)*/
556
Andrew Mahone20f76d62009-05-04 15:46:41 +0000557#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
558 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000559 if (resize & IMG_RESIZE) {
560 if(format & FORMAT_KEEP_ASPECT) {
561 /* keep aspect ratio.. */
Andrew Mahone781421a2008-12-09 23:07:59 +0000562 struct dim resize_dim = {
563 .width = bm->width,
564 .height = bm->height,
565 };
566 if (recalc_dimension(&resize_dim, &src_dim))
567 resize = IMG_NORESIZE;
568 bm->width = resize_dim.width;
569 bm->height = resize_dim.height;
570 }
571 }
572
573 if (!(resize & IMG_RESIZE)) {
574#endif
575 /* returning image size */
576 bm->width = src_dim.width;
577 bm->height = src_dim.height;
578
Andrew Mahone20f76d62009-05-04 15:46:41 +0000579#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
580 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000581 }
582#endif
Andrew Mahone20f76d62009-05-04 15:46:41 +0000583#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
584 format &= 1;
585#endif
Andrew Mahone781421a2008-12-09 23:07:59 +0000586 if (rset.rowstep > 0) { /* Top-down BMP file */
587 rset.rowstart = 0;
588 rset.rowstop = bm->height;
589 } else { /* normal BMP */
590 rset.rowstart = bm->height - 1;
591 rset.rowstop = -1;
592 }
593
Andrew Mahone90586202008-12-26 07:05:13 +0000594 if (cformat)
595 totalsize = cformat->get_size(bm);
596 else
597 totalsize = BM_SIZE(bm->width,bm->height,format,remote);
Jens Arnoldadc48482006-11-18 14:29:51 +0000598
Maurus Cuelenaereaec37aa2009-05-25 11:12:27 +0000599 if(return_size)
Maurus Cuelenaere0bddb7e2009-05-25 15:19:34 +0000600 {
Maurus Cuelenaered2ea7db2009-05-25 20:15:02 +0000601#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
602 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Maurus Cuelenaere0bddb7e2009-05-25 15:19:34 +0000603 if(resize)
604 totalsize += BM_SCALED_SIZE(bm->width, 0, 0, 0);
Maurus Cuelenaered2ea7db2009-05-25 20:15:02 +0000605#endif
Maurus Cuelenaereaec37aa2009-05-25 11:12:27 +0000606 return totalsize;
Maurus Cuelenaere0bddb7e2009-05-25 15:19:34 +0000607 }
Maurus Cuelenaereaec37aa2009-05-25 11:12:27 +0000608
Jens Arnoldadc48482006-11-18 14:29:51 +0000609 /* Check if this fits the buffer */
610 if (totalsize > maxsize) {
Nicolas Pennequinec6569e2007-11-10 13:26:11 +0000611 DEBUGF("read_bmp_fd: Bitmap too large for buffer: "
Jens Arnoldadc48482006-11-18 14:29:51 +0000612 "%d bytes.\n", totalsize);
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000613 return -6;
614 }
615
Andrew Mahone781421a2008-12-09 23:07:59 +0000616 compression = letoh32(bmph.compression);
Jens Arnoldadc48482006-11-18 14:29:51 +0000617 if (depth <= 8) {
Andrew Mahone781421a2008-12-09 23:07:59 +0000618 numcolors = letoh32(bmph.clr_used);
Linus Nielsen Feltzing745adad2006-01-28 12:12:42 +0000619 if (numcolors == 0)
Jens Arnold1d6df542009-06-07 21:27:05 +0000620 numcolors = BIT_N(depth);
Jens Arnoldadc48482006-11-18 14:29:51 +0000621 } else
622 numcolors = (compression == 3) ? 3 : 0;
Andrew Mahone781421a2008-12-09 23:07:59 +0000623
Jens Arnoldadc48482006-11-18 14:29:51 +0000624 if (numcolors > 0 && numcolors <= 256) {
Andrew Mahone781421a2008-12-09 23:07:59 +0000625 int i;
626 union rgb_union pal;
627 for (i = 0; i < numcolors; i++) {
Andrew Mahone07e982d2009-01-08 02:49:23 +0000628 if (read(fd, &pal, sizeof(pal)) != (int)sizeof(pal))
Andrew Mahone781421a2008-12-09 23:07:59 +0000629 {
630 DEBUGF("read_bmp_fd: Can't read color palette\n");
631 return -7;
632 }
633 set_rgb_union(&palette[i], pal);
Jens Arnoldadc48482006-11-18 14:29:51 +0000634 }
635 }
636
637 switch (depth) {
638 case 16:
639#if LCD_DEPTH >= 16
640 /* don't dither 16 bit BMP to LCD with same or larger depth */
Jens Arnold848e0b52006-11-20 00:20:09 +0000641#ifdef HAVE_REMOTE_LCD
642 if (!remote)
643#endif
644 dither = false;
Jens Arnoldadc48482006-11-18 14:29:51 +0000645#endif
646 if (compression == 0) { /* BI_RGB, i.e. 15 bit */
647 depth = 15;
648 break;
649 } /* else fall through */
650
651 case 32:
652 if (compression == 3) { /* BI_BITFIELDS */
Andrew Mahone781421a2008-12-09 23:07:59 +0000653 bool found;
654 int i, j;
655
656 /* (i == 0) is 15bit, (i == 1) is 16bit, (i == 2) is 32bit */
657 for (i = 0; i < ARRAY_SIZE(bitfields); i++) {
658 for (j = 0; j < ARRAY_SIZE(bitfields[0]); j++) {
659 if (!rgbcmp(palette[j], bitfields[i][j])) {
660 found = true;
661 } else {
662 found = false;
663 break;
664 }
665 }
666 if (found) {
667 if (i == 0) /* 15bit */
668 depth = 15;
669 break;
670 }
Jens Arnoldadc48482006-11-18 14:29:51 +0000671 }
Andrew Mahone781421a2008-12-09 23:07:59 +0000672 if (found)
Jens Arnoldadc48482006-11-18 14:29:51 +0000673 break;
Jens Arnoldadc48482006-11-18 14:29:51 +0000674 } /* else fall through */
675
676 default:
677 if (compression != 0) { /* not BI_RGB */
Nicolas Pennequinec6569e2007-11-10 13:26:11 +0000678 DEBUGF("read_bmp_fd: Unsupported compression (type %d)\n",
Jens Arnoldadc48482006-11-18 14:29:51 +0000679 compression);
Linus Nielsen Feltzing745adad2006-01-28 12:12:42 +0000680 return -8;
681 }
Jens Arnoldadc48482006-11-18 14:29:51 +0000682 break;
Linus Nielsen Feltzing745adad2006-01-28 12:12:42 +0000683 }
Michael Sevakise0710b22006-10-15 17:51:00 +0000684
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000685 /* Search to the beginning of the image data */
Andrew Mahone07e982d2009-01-08 02:49:23 +0000686 lseek(fd, (off_t)letoh32(bmph.off_bits), SEEK_SET);
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000687
Andrew Mahone07e982d2009-01-08 02:49:23 +0000688 memset(bitmap, 0, totalsize);
Michael Sevakise0710b22006-10-15 17:51:00 +0000689
Andrew Mahone781421a2008-12-09 23:07:59 +0000690 struct bmp_args ba = {
691 .fd = fd, .padded_width = padded_width, .read_width = read_width,
692 .width = src_dim.width, .depth = depth, .palette = palette,
Andrew Mahone20f76d62009-05-04 15:46:41 +0000693#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
694 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000695 .cur_row = 0, .cur_col = 0, .part = {0,0}
Jens Arnoldadc48482006-11-18 14:29:51 +0000696#endif
Andrew Mahone781421a2008-12-09 23:07:59 +0000697 };
Jens Arnoldadc48482006-11-18 14:29:51 +0000698
Andrew Mahone20f76d62009-05-04 15:46:41 +0000699#if (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)) && \
700 defined(HAVE_BMP_SCALING) || defined(PLUGIN)
701#if LCD_DEPTH > 1 && defined(HAVE_BMP_SCALING)
Andrew Mahone91efc162009-05-09 07:31:27 +0000702 if (resize)
Andrew Mahone4eedc932009-01-04 21:22:05 +0000703#endif
Andrew Mahone90586202008-12-26 07:05:13 +0000704 {
705 if (resize_on_load(bm, dither, &src_dim, &rset,
706 bitmap + totalsize, maxsize - totalsize,
Andrew Mahoneeef79452009-05-06 04:53:56 +0000707 cformat, IF_PIX_FMT(0,) store_part_bmp, &ba))
Andrew Mahone90586202008-12-26 07:05:13 +0000708 return totalsize;
709 else
710 return 0;
711 }
Jens Arnoldadc48482006-11-18 14:29:51 +0000712#endif /* LCD_DEPTH */
Jens Arnoldadc48482006-11-18 14:29:51 +0000713
Andrew Mahone91efc162009-05-09 07:31:27 +0000714#if LCD_DEPTH > 1 || defined(PLUGIN)
715 struct scaler_context ctx = {
716 .bm = bm,
717 .dither = dither,
718 };
Andrew Mahone20f76d62009-05-04 15:46:41 +0000719#endif
Andrew Mahone59e70b52009-05-09 10:32:07 +0000720#if defined(PLUGIN) || defined(HAVE_JPEG) || defined(HAVE_BMP_SCALING)
Andrew Mahone91efc162009-05-09 07:31:27 +0000721#if LCD_DEPTH > 1
722 void (*output_row_8)(uint32_t, void*, struct scaler_context*) =
723 output_row_8_native;
724#elif defined(PLUGIN)
725 void (*output_row_8)(uint32_t, void*, struct scaler_context*) = NULL;
726#endif
727#if LCD_DEPTH > 1 || defined(PLUGIN)
728 if (cformat)
729 output_row_8 = cformat->output_row_8;
730#endif
Andrew Mahone59e70b52009-05-09 10:32:07 +0000731#endif
Andrew Mahone781421a2008-12-09 23:07:59 +0000732
Andrew Mahone91efc162009-05-09 07:31:27 +0000733 int row;
Andrew Mahone781421a2008-12-09 23:07:59 +0000734 /* loop to read rows and put them to buffer */
735 for (row = rset.rowstart; row != rset.rowstop; row += rset.rowstep) {
Andrew Mahone91efc162009-05-09 07:31:27 +0000736 if (!read_part_line(&ba))
737 return -9;
738#ifndef PLUGIN
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000739#if !defined(HAVE_LCD_COLOR) && \
740 (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1))
741 uint8_t* qp = ba.buf;
742#else
743 struct uint8_rgb *qp = (struct uint8_rgb *)ba.buf;
744#endif
Andrew Mahone91efc162009-05-09 07:31:27 +0000745#endif
Andrew Mahone781421a2008-12-09 23:07:59 +0000746 /* Convert to destination format */
Andrew Mahone91efc162009-05-09 07:31:27 +0000747#if ((LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) && \
748 !defined(PLUGIN)
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000749 if (format == FORMAT_NATIVE) {
750#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
751 if (remote) {
Andrew Mahone91efc162009-05-09 07:31:27 +0000752 unsigned char dy = DITHERY(row);
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000753#if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED)
754 /* iAudio X5/M5 remote */
755 fb_remote_data *dest = (fb_remote_data *)bitmap
756 + bm->width * (row >> 3);
757 int shift = row & 7;
758 int delta = 127;
759 unsigned bright;
Andrew Mahone781421a2008-12-09 23:07:59 +0000760
Andrew Mahone91efc162009-05-09 07:31:27 +0000761 int col;
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000762 for (col = 0; col < bm->width; col++) {
763 if (dither)
764 delta = DITHERXDY(col,dy);
765#if !defined(HAVE_LCD_COLOR) && \
766 (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1))
767 bright = *qp++;
768#else
769 bright = brightness(*qp++);
Andrew Mahone781421a2008-12-09 23:07:59 +0000770#endif
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000771 bright = (3 * bright + (bright >> 6) + delta) >> 8;
772 *dest++ |= vi_pattern[bright] << shift;
773 }
774#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */
775 } else
776#endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */
Andrew Mahone91efc162009-05-09 07:31:27 +0000777#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) &&
778 (LCD_REMOTE_DEPTH > 1) */
779#if LCD_DEPTH > 1 || defined(PLUGIN)
Andrew Mahone781421a2008-12-09 23:07:59 +0000780 {
Andrew Mahone59e70b52009-05-09 10:32:07 +0000781#if !defined(PLUGIN) && !defined(HAVE_JPEG) && !defined(HAVE_BMP_SCALING)
782 output_row_8_native(row, ba.buf, &ctx);
783#else
Andrew Mahone91efc162009-05-09 07:31:27 +0000784 output_row_8(row, ba.buf, &ctx);
Andrew Mahone59e70b52009-05-09 10:32:07 +0000785#endif
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000786 }
Andrew Mahone91efc162009-05-09 07:31:27 +0000787#endif
788#if ((LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) && \
789 !defined(PLUGIN)
790 }
791#ifndef PLUGIN
792 else
793#endif
794#endif
795#ifndef PLUGIN
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000796 {
Andrew Mahone91efc162009-05-09 07:31:27 +0000797 unsigned char *p = bitmap + bm->width * (row >> 3);
Jens Arnold1d6df542009-06-07 21:27:05 +0000798 unsigned char mask = BIT_N(row & 7);
Andrew Mahone91efc162009-05-09 07:31:27 +0000799 int col;
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000800 for (col = 0; col < bm->width; col++, p++)
801#if !defined(HAVE_LCD_COLOR) && \
802 (LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1))
803 if (*qp++ < 128)
804 *p |= mask;
805#else
Jens Arnoldadc48482006-11-18 14:29:51 +0000806 if (brightness(*qp++) < 128)
807 *p |= mask;
Andrew Mahonef7fa7e52008-12-26 07:03:22 +0000808#endif
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000809 }
Andrew Mahone91efc162009-05-09 07:31:27 +0000810#endif
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000811 }
Linus Nielsen Feltzing745adad2006-01-28 12:12:42 +0000812 return totalsize; /* return the used buffer size. */
Linus Nielsen Feltzing250678b2005-04-25 07:42:10 +0000813}