arm start.c: Make runtime function address calculation tolerant for more compilers
[barebox-mini2440.git] / commands / bmp.c
blob6e17200a1a5dd6e7b7d77742f6588e50c1cdc59d
1 #include <common.h>
2 #include <command.h>
3 #include <fs.h>
4 #include <linux/stat.h>
5 #include <errno.h>
6 #include <malloc.h>
7 #include <getopt.h>
8 #include <fcntl.h>
9 #include <fb.h>
10 #include <bmp_layout.h>
11 #include <asm/byteorder.h>
13 static inline void set_pixel(struct fb_info *info, void *adr, int r, int g, int b)
15 u32 px;
17 px = (r >> (8 - info->red.length)) << info->red.offset |
18 (g >> (8 - info->green.length)) << info->green.offset |
19 (b >> (8 - info->blue.length)) << info->blue.offset;
21 switch (info->bits_per_pixel) {
22 case 8:
23 break;
24 case 16:
25 *(u16 *)adr = px;
26 break;
27 case 32:
28 break;
32 static int do_bmp(struct command *cmdtp, int argc, char *argv[])
34 int ret, opt, fd;
35 char *fbdev = "/dev/fb0";
36 void *fb, *offscreenbuf = NULL;
37 struct fb_info info;
38 struct bmp_image *bmp;
39 char *bmpfile;
40 int bmpsize;
41 char *image;
42 int sw, sh, width, height, startx = -1, starty = -1;
43 int bits_per_pixel, fbsize;
44 int xres, yres;
45 int offscreen = 0;
46 void *adr, *buf;
48 while((opt = getopt(argc, argv, "f:x:y:o")) > 0) {
49 switch(opt) {
50 case 'f':
51 fbdev = optarg;
52 break;
53 case 'x':
54 startx = simple_strtoul(optarg, NULL, 0);
55 break;
56 case 'y':
57 starty = simple_strtoul(optarg, NULL, 0);
58 case 'o':
59 offscreen = 1;
63 if (optind == argc) {
64 printf("no filename given\n");
65 return 1;
67 bmpfile = argv[optind];
69 fd = open(fbdev, O_RDWR);
70 if (fd < 0) {
71 perror("open");
72 return 1;
75 fb = memmap(fd, PROT_READ | PROT_WRITE);
76 if (fb == (void *)-1) {
77 perror("memmap");
78 goto failed_memmap;
81 ret = ioctl(fd, FBIOGET_SCREENINFO, &info);
82 if (ret) {
83 perror("ioctl");
84 goto failed_memmap;
87 xres = info.xres;
88 yres = info.yres;
90 bmp = read_file(bmpfile, &bmpsize);
91 if (!bmp) {
92 printf("unable to read %s\n", bmpfile);
93 goto failed_memmap;
96 if (bmp->header.signature[0] != 'B' ||
97 bmp->header.signature[1] != 'M') {
98 printf("No valid bmp file\n");
101 sw = le32_to_cpu(bmp->header.width);
102 sh = le32_to_cpu(bmp->header.height);
104 if (startx < 0) {
105 startx = (xres - sw) / 2;
106 if (startx < 0)
107 startx = 0;
110 if (starty < 0) {
111 starty = (yres - sh) / 2;
112 if (starty < 0)
113 starty = 0;
116 width = min(sw, xres - startx);
117 height = min(sh, yres - starty);
119 bits_per_pixel = le16_to_cpu(bmp->header.bit_count);
120 fbsize = xres * yres * (info.bits_per_pixel >> 3);
122 if (offscreen) {
123 /* Don't fail if malloc fails, just continue rendering directly
124 * on the framebuffer
126 offscreenbuf = malloc(fbsize);
127 if (offscreenbuf)
128 memcpy(offscreenbuf, fb, fbsize);
131 buf = offscreenbuf ? offscreenbuf : fb;
133 if (bits_per_pixel == 8) {
134 int x, y;
135 struct bmp_color_table_entry *color_table = bmp->color_table;
137 for (y = 0; y < height; y++) {
138 image = (char *)bmp +
139 le32_to_cpu(bmp->header.data_offset);
140 image += (sh - y - 1) * sw * (bits_per_pixel >> 3);
141 adr = buf + ((y + starty) * xres + startx) *
142 (info.bits_per_pixel >> 3);
143 for (x = 0; x < width; x++) {
144 int pixel;
146 pixel = *image;
148 set_pixel(&info, adr, color_table[pixel].red,
149 color_table[pixel].green,
150 color_table[pixel].blue);
151 adr += info.bits_per_pixel >> 3;
153 image += bits_per_pixel >> 3;
156 } else if (bits_per_pixel == 24) {
157 int x, y;
159 for (y = 0; y < height; y++) {
160 image = (char *)bmp +
161 le32_to_cpu(bmp->header.data_offset);
162 image += (sh - y - 1) * sw * (bits_per_pixel >> 3);
163 adr = buf + ((y + starty) * xres + startx) *
164 (info.bits_per_pixel >> 3);
165 for (x = 0; x < width; x++) {
166 char *pixel;
168 pixel = image;
170 set_pixel(&info, adr, pixel[2], pixel[1],
171 pixel[0]);
172 adr += info.bits_per_pixel >> 3;
174 image += bits_per_pixel >> 3;
177 } else
178 printf("bmp: illegal bits per pixel value: %d\n", bits_per_pixel);
180 if (offscreenbuf) {
181 memcpy(fb, offscreenbuf, fbsize);
182 free(offscreenbuf);
185 free(bmp);
186 close(fd);
188 return 0;
190 failed_memmap:
191 close(fd);
193 return 1;
196 static const __maybe_unused char cmd_bmp_help[] =
197 "Usage: bmp [OPTION]... FILE\n"
198 "show bmp image FILE.\n"
199 " -f <fb> framebuffer device (/dev/fb0)\n"
200 " -x <xofs> x offset (default center)\n"
201 " -y <yofs> y offset (default center)\n"
202 " -o render offscreen\n";
204 BAREBOX_CMD_START(bmp)
205 .cmd = do_bmp,
206 .usage = "show a bmp image",
207 BAREBOX_CMD_HELP(cmd_bmp_help)
208 BAREBOX_CMD_END