#include "bmp_helper.h"
+static void draw_unencoded_bitmap(uint16_t **dst, uint8_t *bmap, uint16_t *cmap,
+ uint32_t cnt)
+{
+ while (cnt > 0) {
+ *(*dst)++ = cmap[*bmap++];
+ cnt--;
+ }
+}
+
+static void draw_encoded_bitmap(uint16_t **dst, uint16_t c, uint32_t cnt)
+{
+ uint16_t *fb = *dst;
+ int cnt_8copy = cnt >> 3;
+
+ cnt -= cnt_8copy << 3;
+ while (cnt_8copy > 0) {
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ *fb++ = c;
+ cnt_8copy--;
+ }
+ while (cnt > 0) {
+ *fb++ = c;
+ cnt--;
+ }
+ *dst = fb;
+}
+
static void yuv_to_rgb(int y, int u, int v, int *r, int *g, int *b)
{
int rdif, invgdif, bdif;
*b = range(y + bdif, 0, 0xff);
}
-int datatobmp(void *__iomem *vaddr, int width, int height, u8 data_format,
- void *data, void (*fn)(void *, void *, int))
+int bmpencoder(void *__iomem *vaddr, int width, int height, u8 data_format,
+ void *data, void (*fn)(void *, void *, int))
{
- uint32_t *d, *d1, *d2;
- uint8_t *dst, *yrgb, *uv, *y1, *y2;
- int y, u, v, r, g, b;
+ uint32_t *d = NULL, *d1 = NULL, *d2 = NULL;
+ uint8_t *dst = NULL, *yrgb = NULL, *uv = NULL, *y1 = NULL, *y2 = NULL;
+ int y = 0, u = 0, v = 0, r = 0, g = 0, b = 0;
int yu = width * 4 % 4;
int byteperline;
return 0;
}
+
+static void decode_rle8_bitmap(uint8_t *psrc, uint8_t *pdst, uint16_t *cmap,
+ unsigned int width, unsigned int height,
+ int bits, int x_off, int y_off, bool flip)
+{
+ uint32_t cnt, runlen;
+ int x = 0, y = 0;
+ int decode = 1;
+ uint8_t *bmap = psrc;
+ uint8_t *dst = pdst;
+ int linesize = width * 2;
+
+ if (flip) {
+ y = height - 1;
+ dst = pdst + y * linesize;
+ }
+
+ while (decode) {
+ if (bmap[0] == BMP_RLE8_ESCAPE) {
+ switch (bmap[1]) {
+ case BMP_RLE8_EOL:
+ /* end of line */
+ bmap += 2;
+ x = 0;
+ if (flip) {
+ y--;
+ dst -= linesize * 2;
+ } else {
+ y++;
+ }
+ break;
+ case BMP_RLE8_EOBMP:
+ /* end of bitmap */
+ decode = 0;
+ break;
+ case BMP_RLE8_DELTA:
+ /* delta run */
+ x += bmap[2];
+ if (flip) {
+ y -= bmap[3];
+ dst -= bmap[3] * linesize;
+ dst += bmap[2] * 2;
+ } else {
+ y += bmap[3];
+ dst += bmap[3] * linesize;
+ dst += bmap[2] * 2;
+ }
+ bmap += 4;
+ break;
+ default:
+ /* unencoded run */
+ runlen = bmap[1];
+ bmap += 2;
+ if (y >= height || x >= width) {
+ decode = 0;
+ break;
+ }
+ if (x + runlen > width)
+ cnt = width - x;
+ else
+ cnt = runlen;
+ draw_unencoded_bitmap((uint16_t **)&dst, bmap,
+ cmap, cnt);
+ x += runlen;
+ bmap += runlen;
+ if (runlen & 1)
+ bmap++;
+ }
+ } else {
+ /* encoded run */
+ if (y < height) {
+ runlen = bmap[0];
+ if (x < width) {
+ /* aggregate the same code */
+ while (bmap[0] == 0xff &&
+ bmap[2] != BMP_RLE8_ESCAPE &&
+ bmap[1] == bmap[3]) {
+ runlen += bmap[2];
+ bmap += 2;
+ }
+ if (x + runlen > width)
+ cnt = width - x;
+ else
+ cnt = runlen;
+ draw_encoded_bitmap((uint16_t **)&dst,
+ cmap[bmap[1]], cnt);
+ }
+ x += runlen;
+ }
+ bmap += 2;
+ }
+ }
+}
+
+int bmpdecoder(void *bmp_addr, void *pdst, int *width, int *height, int *bits)
+{
+ BITMAPHEADER header;
+ BITMAPINFOHEADER infoheader;
+ uint16_t *bmp_logo_palette;
+ uint32_t size;
+ uint16_t linesize;
+ int stride;
+ char *cmap_base;
+ char *src = bmp_addr;
+ char *dst = pdst;
+ int i;
+ bool flip = false;
+
+ memcpy(&header, src, sizeof(header));
+ src += sizeof(header);
+
+ if (header.type != 0x4d42) {
+ pr_err("not bmp file type[%x], can't support\n", header.type);
+ return -1;
+ }
+ memcpy(&infoheader, src, sizeof(infoheader));
+ *width = infoheader.width;
+ *height = infoheader.height;
+
+ if (*height < 0)
+ *height = 0 - *height;
+ else
+ flip = true;
+
+ size = header.size - header.offset;
+ linesize = *width * infoheader.bitcount >> 3;
+ cmap_base = src + sizeof(infoheader);
+ src = bmp_addr + header.offset;
+
+ switch (infoheader.bitcount) {
+ case 8:
+ bmp_logo_palette = kmalloc(sizeof(bmp_logo_palette) * 256, GFP_KERNEL);
+
+ /* Set color map */
+ for (i = 0; i < 256; i++) {
+ ushort colreg = ((cmap_base[2] << 8) & 0xf800) |
+ ((cmap_base[1] << 3) & 0x07e0) |
+ ((cmap_base[0] >> 3) & 0x001f) ;
+ cmap_base += 4;
+ bmp_logo_palette[i] = colreg;
+ }
+
+ /*
+ * only support convert 8bit bmap file to RGB565.
+ */
+ decode_rle8_bitmap(src, dst, bmp_logo_palette,
+ infoheader.width, infoheader.height,
+ infoheader.bitcount, 0, 0, flip);
+ kfree(bmp_logo_palette);
+ *bits = 16;
+ break;
+ case 16:
+ /*
+ * Todo
+ */
+ pr_info("unsupport bit=%d now\n", infoheader.bitcount);
+ break;
+ case 24:
+ stride = ALIGN(*width * 3, 4);
+ if (flip)
+ src += stride * (*height - 1);
+
+ for (i = 0; i < *height; i++) {
+ memcpy(dst, src, 3 * (*width));
+ dst += stride;
+ src += stride;
+ if (flip)
+ src -= stride * 2;
+ }
+
+ *bits = 24;
+ break;
+ case 32:
+ /*
+ * Todo
+ */
+ pr_info("unsupport bit=%d now\n", infoheader.bitcount);
+ break;
+ default:
+ pr_info("unsupport bit=%d now\n", infoheader.bitcount);
+ break;
+ }
+
+ return 0;
+}