#ifdef USE_BMP
/*
 *  BMP format MP3 album image support code
 *
 *  This file is no longer used, since JPEG image is now supported.
 */
#include <t_services.h>
#include "kernel_id.h"
#include "ff.h"
#include "player.h"
#include "lpc23xx.h"
#include "ili9320.h"
#include "lcd.h"

typedef struct tagBITMAPFILEHEADER {
    UH bfType;
    UW  bfSize;
    UH bfReserved1;
    UH bfReserved2;
    UW  bfOffBits;
} __attribute__((packed)) BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER{
    UW biSize;
    W  biWidth;
    W  biHeight;
    UH biPlanes;
    UH biBitCount;
    UW biCompression;
    UW biSizeImage;
    W  biXPixPerMeter;
    W  biYPixPerMeter;
    UW biClrUsed;
    UW biClrImporant;
} BITMAPINFOHEADER;

typedef struct tagV5INFOHEADER {
    UW redMask;
    UW greenMask;
    UW blueMask;
    UW alphaMask;
    UW clorSpaceType;
    UW readX, redY, redZ;
    UW greenX, greenY, greenZ;
    UW blueX, blueY, blueZ;
    UW redGamma, greenGamma, blueGamma;
    UW sRGBSpaceType;
    UW profileOffset, profileSize;
    UW reserved;
} V5INFOHEADER;

static BITMAPFILEHEADER fheader;
static BITMAPINFOHEADER iheader;
static V5INFOHEADER v5header;

#define	IWIDTH	80		/* Maximum image width/height */
#define	IBSIZE	(IWIDTH*3)
static UB row_buffer[IBSIZE];

void display_img_file(Player_Status *pst)
{
    int x, y, width, height, nc, nbytes;
    int b_read, lw;
    UH color, rval, gval, bval;
    UB *bp, *ibp;
    FRESULT result;
    FIL *file = &pst->img_file;

    if (pst->img_flag & IMG_SHOWN)
	return;
    wai_sem(SEM_LCD);
    lcd_fill_rect(AIMAGE_X, AIMAGE_Y, IWIDTH, IWIDTH, C_WHITE);

    if (pst->img_flag == IMG_NONE) {
	goto noimg;
    }
    f_lseek(file, 0);

    result = f_read(file, &fheader, sizeof(BITMAPFILEHEADER), &b_read);
    if ((result != FR_OK) || (b_read != sizeof(BITMAPFILEHEADER))) {
	syslog(LOG_NOTICE, "img: failed to read header. %d, %d", result, b_read);
	goto noimg;
    }
    if (fheader.bfType != 0x4d42) {
	syslog(LOG_NOTICE, "Bad file type magic.");
	goto noimg;
    }
    result = f_read(file, &iheader, sizeof(BITMAPINFOHEADER), &b_read);
    if (result != FR_OK) {
	syslog(LOG_NOTICE, "failed to read info header");
	goto noimg;
    }
#ifdef VDEBUG
    syslog(LOG_NOTICE, "%d X %d (size = %d)", iheader.biWidth, iheader.biHeight, iheader.biSize);
    syslog(LOG_NOTICE, "%d bit %d", iheader.biBitCount, iheader.biCompression);
#endif
    f_lseek(file, sizeof(BITMAPFILEHEADER) + iheader.biSize);

    width = iheader.biWidth;
    height = iheader.biHeight;
    if (width > IWIDTH || height > IWIDTH) {
	syslog(LOG_NOTICE, "size too big (%d x %d)", width, height);
	goto noimg;
    }
    if (iheader.biBitCount != 24) {
	syslog(LOG_NOTICE, "Can't handle biBitCount = %d", iheader.biBitCount);
	goto noimg;
    }
    lw = (width *3 + 3) >> 2;
    lw <<= 2;

    Clear_CS();
    /* Because BMP image is stored in bottom to top order,
     * we change ENTRY mode to meet with this image order.
     */
    lcd_set_register(ENTRY_MODE, 0x9010);  /* TRI, RGB, I/D[1:0] = 01 */
    lcd_set_address(AIMAGE_X, AIMAGE_Y + height - 1);
    lcd_set_register(H_ADDR_START_POSITION, AIMAGE_X);
    lcd_set_register(V_ADDR_START_POSITION, AIMAGE_Y);
    lcd_set_register(H_ADDR_END_POSITION, AIMAGE_X + width - 1);
    lcd_set_register(V_ADDR_END_POSITION, AIMAGE_Y + height - 1);

    lcd_write_command(WRITE_DATA_TO_GRAM);

    for (y = 0; y < height; y++) {
	f_read(file, row_buffer, lw, &b_read);
	if (b_read != lw)
	    break;
	bp = row_buffer;
	for (x = 0; x < width; x++) {
	    bval = (*bp++ >> 2) & 0x3f;
	    gval = (*bp++ >> 2) & 0x3f;
	    rval = (*bp++ >> 2) & 0x3f;
	    color = (rval << 10) | (gval << 4) | (bval >> 2);
	    lcd_write_data(color);
	    color = ((bval & 3) << 14);
	    lcd_write_data(color);
	}
    }
    lcd_set_register(ENTRY_MODE, 0x1030);	/* RGB, I/D[1:0] = 11 */
    Set_CS();
    pst->img_flag |= IMG_SHOWN;
    sig_sem(SEM_LCD);
    return;

noimg:
    pst->img_flag |= IMG_SHOWN;
    sig_sem(SEM_LCD);
    return;
}
#endif
