Displaying a BMP on a TFT (SAMD21)

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am working on reading BMP images on a USB and displaying them on a SSD1963 TFT.  The below code will read the bmp header, then parse the image data to display on a TFT (BMP565 format). The issue I am having is the code works if  the image is 100px X 100px. But it the height and width are not the same, it doesn't display correctly. e.g. the image is not recognizable, but the height and width are correct. From reading online, I need to calculate the number of pixels in each row, which I do, but I suspect how I am not iterating over the rows correctly.

 

void display_bmp(int x1, int y1, char *bitmap){

	uint32_t bmpWidth  = 0;
	uint32_t bmpHeight = 0;
	uint16_t bmpImageoffset;
	uint16_t rowSize;
	uint8_t header_buff[60];
	uint16_t position = 0;
	uint8_t numberOfPixels = 0;
	uint32_t commpression = 0;
	uint32_t imageSize = 0;
	unsigned int byte_read;
	uint16_t bmpSig;
	volatile uint8_t lun = LUN_ID_USB;

	/* Mount drive */
	memset(&fs, 0, sizeof(FATFS));
	FRESULT res = f_mount(lun, &fs);
	if (FR_INVALID_DRIVE == res) {
		printf("Mount Failed!\n\r");
		return;
	}

	printf("loading  %s\n\r", (char *)bitmap);
	res = f_open(&file_object,(char *)bitmap, FA_OPEN_EXISTING | FA_READ);
	if (res == FR_NOT_READY || res != FR_OK) {
		/* LUN not ready or LUN test error */
		printf("File open failed!\n\r");
		f_close(&file_object);
		return;
	}

	// Read the bmp header
	res = f_read(&file_object, header_buff, sizeof header_buff, &byte_read); 

	if(res != FR_OK){
		print_fs_result(res);
		return;
	}
	bmpSig = (header_buff[1] << 8) | header_buff[0];
	printf("Signature:\t0x%X\n", bmpSig);
	if(bmpSig != 0x4D42){
		return; // not a bmp
	}
	bmpImageoffset =  header_buff[7] * 256 + header_buff[6];
	bmpHeight =  (header_buff[25] << 24) | (header_buff[24] << 16) | (header_buff[23] << 8) | header_buff[22];
	bmpWidth = (header_buff[15] << 24) |  (header_buff[16] << 16) | (header_buff[17] << 8) | header_buff[18];
	position = header_buff[10]; // starting point in file
	numberOfPixels = header_buff[29] * 256 + header_buff[28];
	commpression = (header_buff[30] << 24) |  (header_buff[31] << 16) | (header_buff[32] << 8) | header_buff[33];
	imageSize = (header_buff[37] << 24) |  (header_buff[36] << 16) | (header_buff[35] << 8) | header_buff[34];
	if(tft_conf.orient == LANDSCAPE){
		swap(uint32_t, bmpWidth, bmpHeight);
	}
	rowSize = ((numberOfPixels * bmpWidth + 31) /32 ) * 4;
	printf("Offset:\t%d\n", bmpImageoffset);
	printf("Height:\t%ld\n", bmpHeight);
	printf("Width:\t\t%ld\n", bmpWidth);
	printf("Row Size:\t%d\n", rowSize);
	printf("Start Index:\t%d\n", position);
	printf("# of Pixels:\t%d\n", numberOfPixels);
	printf("Compression:\t%ld\n", commpression);
	printf("Image Size:\t%ld\n", imageSize);
	// end header read

	sam_clearCs();
	sam_setXY(x1, y1,(bmpWidth + x1) -1, (bmpHeight + y1)-1);

	uint8_t row_buff[rowSize]; // only read 1 row at a time	

	res = f_lseek(&file_object, position); // start at beginning of image data

	for(uint32_t row = 0; row < bmpHeight; row++){ // read 1 row at a time

		res = f_read(&file_object, row_buff, sizeof row_buff, &byte_read); // read 1 row

		if(res != FR_OK){
			print_fs_result(res);
			return;
		}

		position = position + rowSize; // calculate next position on disk to read
		res = f_lseek(&file_object, position); // set next position

		if(res != FR_OK){
			print_fs_result(res);
			return;
		}
		// read the buffer and send to TFT
		for (int x = rowSize; x > 0 ; x -= 3) {

			uint16_t colorbyte = sam_color565(row_buff[x + 2], row_buff[x + 1], row_buff[x]);
			sam_writeData(colorbyte >> 8, colorbyte & 0xFF);
		}			

	} // end while

	sam_setCs();
	sam_clrXY();

	f_close(&file_object);
}

 

This topic has a solution.

"When all else fails, read the directions"

Last Edited: Thu. Nov 30, 2017 - 12:38 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Go on.   There are loads of examples.  Most of them are for displaying a 24-bit colour BMP.   It is a common format on PC software.    Just study how they work.

And study how the BMP formats store the data. 

You have several glaring errors. 

David.

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
Go on.

Figured it out. Needed to compensate for row padding and if the height was negative to determine if the pixel data is stored from bottom to top or top to bottom (amongst a few over things).

"When all else fails, read the directions"