summaryrefslogtreecommitdiff
path: root/apps/recorder/bmp.h
diff options
context:
space:
mode:
authorAndrew Mahone <andrew.mahone@gmail.com>2008-12-26 07:03:22 +0000
committerAndrew Mahone <andrew.mahone@gmail.com>2008-12-26 07:03:22 +0000
commitf7fa7e5ad537415f1f75b3a9c1a58eb925e10d04 (patch)
treeea469e428a756e4f4979be1b6f5a84179a2cc80f /apps/recorder/bmp.h
parent7428c7cc5b8462ed95683f707fe78609ce8208bf (diff)
downloadrockbox-f7fa7e5ad537415f1f75b3a9c1a58eb925e10d04.tar.gz
rockbox-f7fa7e5ad537415f1f75b3a9c1a58eb925e10d04.zip
Latest work on the bmp on-load scaler:
Macros for calculating size needed for bitmap load and scaling, so that these can be compile-time constant when their inputs are. Reduce size of bayer dither by chopping all but first row of dither matrix, and replacing 2D lookup with 1D lookup and small calculation. Move some functions not related to actual bmp file loading out of bmp.c. A smaller brightness() for mono targets, and a higher-quality one for greyscale targets, both replacing the division by 10 with a shift. Port of the linear and area scalers to greyscale targets, this costs some binsize but produces better output even when dithered to 2bpp. Move duplicated row output code from inside vertical scalers to a separate row output function. Move some multiplies out of the line scaler, for a small speedup and code size reduction, as well as a small improvement in accuracy for the upscaling case. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19592 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/recorder/bmp.h')
-rw-r--r--apps/recorder/bmp.h221
1 files changed, 116 insertions, 105 deletions
diff --git a/apps/recorder/bmp.h b/apps/recorder/bmp.h
index d1b1d7f3ed..273e178bc9 100644
--- a/apps/recorder/bmp.h
+++ b/apps/recorder/bmp.h
@@ -32,11 +32,7 @@
32 32
33#define IMG_NORESIZE 0 33#define IMG_NORESIZE 0
34#define IMG_RESIZE 1 34#define IMG_RESIZE 1
35#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) 35#define BM_MAX_WIDTH (((LCD_WIDTH) + 7) & ~7)
36#define MAX_WIDTH 8
37#else
38#define MAX_WIDTH LCD_WIDTH
39#endif
40 36
41struct uint8_rgb { 37struct uint8_rgb {
42 uint8_t blue; 38 uint8_t blue;
@@ -56,129 +52,144 @@ struct rowset {
56}; 52};
57 53
58#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) 54#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
59extern const unsigned char dither_matrix[16][16]; 55extern const unsigned char dither_table[16];
60static inline unsigned char dither_mat(unsigned int x, unsigned int y) 56#define DITHERY(y) (dither_table[(y) & 15] & 0xAA)
61{ 57#define DITHERX(x) (dither_table[(x) & 15])
62 return dither_matrix[y][x]; 58#define DITHERXDY(x,dy) (DITHERX(x) ^ dy)
63} 59#define DITHERDXY(dx,y) (dx ^ DITHERY(y))
60#define DITHERXY(x,y) (DITHERX(x) ^ DITHERY(y))
64#endif 61#endif
65 62
63/* The /256 version has a mean squared variance from YUV luma of <1 grey level.
64 The /8 version is a good deal less accurate, but sufficient on mono as we
65 don't support HQ output or dithering there, yet.
66*/
66static inline unsigned brightness(struct uint8_rgb color) 67static inline unsigned brightness(struct uint8_rgb color)
67{ 68{
68 return (3 * (unsigned)color.red + 6 * (unsigned)color.green 69#if LCD_DEPTH > 1
69 + (unsigned)color.blue) / 10; 70 return (77 * (unsigned)color.red + 150 * (unsigned)color.green
71 + 29 * (unsigned)color.blue) / 256;
72#else
73 return (2 * (unsigned)color.red + 5 * (unsigned)color.green
74 + (unsigned)color.blue) / 8;
75#endif
70} 76}
71 77
72#if ((LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)) \ 78#if ((LCD_DEPTH == 2) && (LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)) \
73 || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH == 2) \ 79 || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH == 2) \
74 && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED)) 80 && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED))
75extern const unsigned short vi_pattern[4]; 81extern const unsigned short vi_pattern[4];
76static inline unsigned short vi_pat(unsigned int bright)
77{
78 return vi_pattern[bright];
79}
80#endif 82#endif
81 83
82static inline int get_fb_height(struct bitmap *bm, bool remote) 84/* Number of rows of data in a mono bitmap height pixels tall */
83{ 85#define MONO_BM_HEIGHT(height) (((height) + 7) >> 3)
84 const int height = bm->height; 86
85#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) 87/* Number of rows of datain a LCD native bitmap height pixels tall */
86 const int format = bm->format; 88#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
89#if LCD_DEPTH == 1 || \
90 (LCD_DEPTH == 2 && LCD_PIXELFORMAT == VERTICAL_INTERLEAVED)
91#define LCD_BM_HEIGHT(height) (((height) + 7) >> 3)
92#elif LCD_DEPTH == 2 && LCD_PIXELFORMAT == VERTICAL_PACKING
93#define LCD_BM_HEIGHT(height) (((height) + 3) >> 2)
94#else
95#define LCD_BM_HEIGHT(height) (height)
87#endif 96#endif
88 int dst_height;
89 97
90#if !defined(HAVE_REMOTE_LCD) || \ 98/* Number of rows of data in a remote native bitmap height pixels tall. */
91 (defined(HAVE_REMOTE_LCD) &&(LCD_REMOTE_DEPTH == 1)) 99#ifdef HAVE_REMOTE_LCD
92 (void) remote; 100#if LCD_REMOTE_DEPTH == 1 || \
101 (LCD_REMOTE_DEPTH == 2 && LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED)
102#define LCD_REMOTE_BM_HEIGHT(height) (((height) + 7) >> 3)
103#elif LCD_REMOTE_DEPTH == 2 && LCD_REMOTE_PIXELFORMAT == VERTICAL_PACKING
104#define LCD_REMOTE_BM_HEIGHT(height) (((height) + 3) >> 2)
105#else
106#define LCD_REMOTE_BM_HEIGHT(height) (height)
107#endif
108#define NATIVE_BM_HEIGHT(height,remote) ((remote) ? \
109 LCD_REMOTE_BM_HEIGHT(height) : LCD_BM_HEIGHT(height))
110#else
111#define NATIVE_BM_HEIGHT(height,remote) LCD_BM_HEIGHT(height)
93#endif 112#endif
94 113
95#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) 114/* Convenience macro to calculate rows based on height, remote vs main LCD,
96 if (format == FORMAT_NATIVE) { 115 and format
97#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 116*/
98 if (remote) { 117#define BM_HEIGHT(height,format,remote) ((format) == FORMAT_MONO ? \
99#if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) 118 MONO_BM_HEIGHT(height) : NATIVE_BM_HEIGHT(height,remote))
100 dst_height = (height + 7) >> 3; 119#else
101#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ 120#define BM_HEIGHT(height,format,remote) MONO_BM_HEIGHT(height)
102 } else 121#endif
103#endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */
104 {
105#if LCD_DEPTH == 2
106#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
107 dst_height = height;
108#elif LCD_PIXELFORMAT == VERTICAL_PACKING
109 dst_height = (height + 3) >> 2;
110#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
111 dst_height = (height + 7) >> 3;
112#endif /* LCD_PIXELFORMAT */
113#elif LCD_DEPTH == 16
114 dst_height = height;
115#endif /* LCD_DEPTH */
116 }
117 } else
118#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */
119 {
120 dst_height = (height + 7) >> 3;
121 }
122
123 return dst_height;
124}
125 122
126static inline int get_fb_width(struct bitmap *bm, bool remote) 123/* Number of data elements in a mono bitmap width pixels wide */
127{ 124#define MONO_BM_WIDTH(width) (width)
128 const int width = bm->width; 125
129#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) 126/* Number of data elements in a LCD native bitmap width pixels wide */
130 const int format = bm->format; 127#if LCD_DEPTH > 1
128#if LCD_DEPTH == 2 && LCD_PIXELFORMAT == HORIZONTAL_PACKING
129#define LCD_BM_WIDTH(width) (((width) + 3) >> 2)
130#else
131#define LCD_BM_WIDTH(width) (width)
131#endif 132#endif
132 int dst_width;
133 133
134#if !defined(HAVE_REMOTE_LCD) || \ 134/* Number of data elements in a remote native bitmap width pixels wide */
135 (defined(HAVE_REMOTE_LCD) &&(LCD_REMOTE_DEPTH == 1)) 135#ifdef HAVE_LCD_REMOTE
136 (void) remote; 136#if LCD_REMOTE_DEPTH == 2 && LCD_REMOTE_PIXELFORMAT == HORIZONTAL_PACKING
137#define LCD_REMOTE_BM_WIDTH(width) (((width) + 3) >> 2)
138#else
139#define LCD_REMOTE_BM_WIDTH(width) (width)
140#endif
141#define NATIVE_BM_WIDTH(width,remote) ((remote) ? \
142 LCD_REMOTE_BM_WIDTH(width) : LCD_BM_WIDTH(width))
143#else
144#define NATIVE_BM_WIDTH(width,remote) LCD_BM_WIDTH(width)
137#endif 145#endif
138 146
139#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) 147/* Convenience macro to calculate elements based on height, remote vs native
140 if (format == FORMAT_NATIVE) { 148 main LCD, and format
141#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 149*/
142 if (remote) { 150#define BM_WIDTH(width,format,remote) ((format) == FORMAT_MONO ? \
143#if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) 151 MONO_BM_WIDTH(width) : NATIVE_BM_WIDTH(width,remote))
144 dst_width = width; 152#else
145#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ 153#define BM_WIDTH(width,format,remote) MONO_BM_WIDTH(width)
146 } else 154#endif
147#endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */
148 {
149#if LCD_DEPTH == 2
150#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
151 dst_width = (width + 3) >> 2;
152#elif LCD_PIXELFORMAT == VERTICAL_PACKING
153 dst_width = width;
154#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
155 dst_width = width;
156#endif /* LCD_PIXELFORMAT */
157#elif LCD_DEPTH == 16
158 dst_width = width;
159#endif /* LCD_DEPTH */
160 }
161 } else
162#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */
163 {
164 dst_width = width;
165 }
166
167 return dst_width;
168}
169 155
170static inline int get_totalsize(struct bitmap *bm, bool remote) 156/* Size in bytes of a mono bitmap of dimensions width*height */
171{ 157#define MONO_BM_SIZE(width,height) (MONO_BM_WIDTH(width) * \
172 int sz; 158 MONO_BM_HEIGHT(height) * FB_DATA_SZ)
173#ifdef HAVE_REMOTE_LCD
174 if (remote && sizeof(fb_data) != sizeof(fb_remote_data))
175 sz = sizeof(fb_remote_data);
176 else
177#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */
178 sz = sizeof(fb_data);
179 159
180 return get_fb_width(bm, remote) * get_fb_height(bm, remote) * sz; 160/* Size in bytes of a native bitmap of dimensions width*height */
181} 161#if LCD_DEPTH > 1 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
162#if defined(HAVE_REMOTE_LCD) && FB_DATA_SZ != FB_RDATA_SZ
163#define NATIVE_BM_SIZE(width,height,format,remote) \
164 (((remote) ? FB_RDATA_SZ : FB_DATA_SZ) * BM_WIDTH(width,format,remote) \
165 * BM_HEIGHT(height,format,remote))
166#else
167#define NATIVE_BM_SIZE(width,height,format,remote) \
168 (FB_DATA_SZ * BM_WIDTH(width,format,remote) * \
169 BM_HEIGHT(height,format,remote))
170#endif
171
172/* Convenience macro to calculate size in bytes based on height, remote vs
173 main LCD, and format
174*/
175#define BM_SIZE(width,height,format,remote) (((format) == FORMAT_MONO) ? \
176 MONO_BM_SIZE(width,height) : NATIVE_BM_SIZE(width,height,format,remote))
177#else
178#define BM_SIZE(width,height,format,remote) MONO_BM_SIZE(width,height)
179#endif
180
181/* Size in bytes needed to load and scale a bitmap with target size up to
182 width*height, including overhead to allow for buffer alignment.
183*/
184#ifdef HAVE_LCD_COLOR
185#define BM_SCALED_SIZE(width,height,format,remote) \
186 (BM_SIZE(width,height,format,remote) + \
187 (remote ? 0 : BM_WIDTH(width,format,remote) * sizeof(uint32_t) * 9 + 3))
188#else
189#define BM_SCALED_SIZE(width,height,format,remote) \
190 (BM_SIZE(width,height,format,remote) + \
191 (width * sizeof(uint32_t) * 3 + 3))
192#endif
182 193
183/********************************************************************* 194/*********************************************************************
184 * read_bmp_file() 195 * read_bmp_file()