SOLVED:
Now I have a working bmp24 to rgb565 converter. It both produces a binary file of the image and a header file which has the image information in a data structure.
Here is the code
/*
FILE: bmp24_to_rgb565
....: takes a 24 bit bmp image as input and output a rgb565 image format binary file and a header file
....: which consists of the rgb565 data structre.
....: designed for LITTLE ENDIAN
*/
#include <stdio.h>
#include <string.h>
#include <windows.h>
#define RGB16(red, green, blue) ( ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3))
#define MAX_OSD_WIDTH 720 // Max Davinci OSD width
#define MAX_OSD_HEIGHT 576 // Max Davinci OSD height (for PAL support)
#define MAX_OSD_SIZE MAX_OSD_WIDTH*MAX_OSD_HEIGHT
#define NTSC_OSD_WIDTH 720
#define NTSC_OSD_HEIGHT 480
/*
FUNCTION...: adjusts the given input character array and write to the given file stream.
...........: given input character array is 2 byte rgb565 data, and needed to be formatted properly
...........: to be written into file stream. (which is a header file)
*/
bool convert_bmp24_to_rgb16_in_array(FILE *rgb16SourceFile, char input_character_array[], int newline_flag )
{
char len;
char buffer_write[5];
len = strlen(input_character_array);
switch (len)
{
case 4:
{
buffer_write[0] = input_character_array[0];
buffer_write[1] = input_character_array[1];
buffer_write[2] = input_character_array[2];
buffer_write[3] = input_character_array[3];
buffer_write[4] = '\0';
//printf( "buffer write: %s\n", buffer_write );
}
break;
case 3:
{
buffer_write[0] = '0';
buffer_write[1] = input_character_array[0];
buffer_write[2] = input_character_array[1];
buffer_write[3] = input_character_array[2];
buffer_write[4] = '\0';
//printf( "buffer write: %s\n", buffer_write );
}
break;
case 2:
{
buffer_write[0] = '0';
buffer_write[1] = '0';
buffer_write[2] = input_character_array[0];
buffer_write[3] = input_character_array[1];
buffer_write[4] = '\0';
//printf( "buffer write: %s\n", buffer_write );
}
break;
case 1:
{
buffer_write[0] = '0';
buffer_write[1] = '0';
buffer_write[2] = '0';
buffer_write[3] = input_character_array[0];
buffer_write[4] = '\0';
//printf( "buffer write: %s\n", buffer_write );
}
break;
case 8: /* This case is only entered when no unsigned variables are used/ */
{
buffer_write[0] = input_character_array[7];
buffer_write[1] = input_character_array[6];
buffer_write[2] = input_character_array[5];
buffer_write[3] = input_character_array[4];
buffer_write[4] = '\0';
//printf( "buffer write: %s\n", buffer_write );
}
break;
default:
printf("Err: Unexpected strlen value. len: %d", len);
return false;
}
if( !(newline_flag % 2) )
fprintf(rgb16SourceFile, "0x%s", buffer_write);
else
fprintf(rgb16SourceFile, "%s,\n", buffer_write);
return true;
}
int main(int argc, char *argv[])
{
FILE *rgb24file; /* for bmp file */
FILE *rgb16file; /* for rgb565 binary file */
FILE *rgb16SourceFile; /* for header file which holds rgb565 data structure */
unsigned char red, green, blue; //pixel bytes
long fileSize;
long x, y;
int width=NTSC_OSD_WIDTH, height=NTSC_OSD_HEIGHT; //Default values
char hexString[8];
/* STARTUP ADJUSTMENTS */
if (argc < 2)
{
printf("Usage: %s filename [width][height]\n", argv[0]);
return -1;
}
else if ((argc > 2) && (argc != 4))
{
printf("Must specify both width and height or neither\n");
printf("Usage: %s filename [width][height]\n", argv[0]);
return -1;
}
else if ((argc == 4) && (atoi(argv[2]) > MAX_OSD_WIDTH))
{
printf("width cannot exceed %d pixels\n", MAX_OSD_WIDTH);
return -1;
}
else if ((argc==4) && (atoi(argv[3]) > MAX_OSD_HEIGHT))
{
printf("height cannot exceed %d pixels\n", MAX_OSD_HEIGHT);
return -1;
}
else if (argc==4)
{
//Valid width and Height were entered; therefore override defaults
width = atoi(argv[2]);
height = atoi(argv[3]);
}
unsigned short osdData[width * height];
/* CONVERSION PROCESS STARTING */
printf("Preparing to convert %s (%d x %d)....\n", argv[1], width, height);
// Open file in read-binary mode
rgb24file = fopen(argv[1], "rb");
if (rgb24file == NULL)
{
printf("could not find file %s \n", argv[1]);
return -1;
}
// Get size of file
fseek(rgb24file, 0, SEEK_END);
fileSize = ftell(rgb24file);
fseek(rgb24file, 0, SEEK_SET);
printf("size %d\n", fileSize);
//Skip BMP header information (which is 54 byte)
fseek(rgb24file, 54, SEEK_SET);
fileSize = fileSize - 54;
//Ensure file size does not exceed Max supported OSD size
if (fileSize > (MAX_OSD_SIZE*3))
{
printf("This file is too large, maximum supported size is 720x576x3\n");
}
/*
else if (((fileSize % 3) !=0)|| (fileSize != (width*height*3)))
{
printf("file size: %d\n", fileSize);
printf("this file does not have the size expected \n");
}
*/
/* PROCESS PART */
else
{
for( x=0; x < (width*height); x++) //for every pixel, read the rgb values and store them in osdData[]
{
fread(&blue, sizeof(char), 1, rgb24file);
fread(&green, sizeof(char), 1, rgb24file);
fread(&red, sizeof(char), 1, rgb24file);
osdData[x] = RGB16(red, green, blue);
}
// Open .h file
rgb16SourceFile = fopen("rgb565_image.h", "w");
// Open file in read-binary mode
rgb16file = fopen("osd.r16", "wb");
fprintf (rgb16SourceFile, "unsigned long rgb565_image_720x480[] = {\n");
for (y= height -1; y >=0; y--)
{
for (x=0; x < width; x ++)
{
//write to osd.r16 file in a binary stream
fwrite(&osdData[(width*y) + x], sizeof(short), 1, rgb16file);
//call to write rgb565_image.h file in a structre format
sprintf(hexString, "%X", osdData[(width*y) + x] );
convert_bmp24_to_rgb16_in_array(rgb16SourceFile, hexString, x);
}
}
fprintf (rgb16SourceFile, "};\n");
fclose(rgb16file);
fclose(rgb16SourceFile);
}
fclose(rgb24file);
return 0;
}
Previous Message:
Hi,
I am using the bmp24 to rgb565 converter code from http://focus.ti.com/lit/an/spraad7/spraad7.pdf .
This application saves the bitmap data in a file that is written in a binary manner.
-When I change the file extension .r16 to .raw and open the file with Photoshop or Paintshop, a black and white and corrupted image opens. Is this because of the media opener can not encode the image or is the converter code doesn't work right? I think writing to file operation (loops and the fwrite content) is a little awkward, like it is not writing properly, but I will check it tomorrow morning, and I also think the example of TI can't be wrong.
-I modified the code a little to create a .h file and put the data into an array. (Because, all examples I have seen reads the image data into frame buffer using arrays.) But now I have a problem.
For example, in DSP/BIOS VPBE User Guide, the given example processes a yuv image CbCr.
The array is:
unsigned long yuv_imageCbCr_720x480[] =
{
0x7A756AA2,
...
0x74937C4B
};
Bits per pixel for this format is 16 bits, as RGB565. But in the array, every line is consisted of 4 bytes. Is this because of byte aligning?
My application produces an array like:
unsigned long rgb565_image_720x480[] = {
0x862,
0x10A3,
0x10C3,
...
0x0,
};
Here, every line is 2 bytes. Is that a problem? Do I have to align them to four bytes? If yes, how?
And here is the application code of the BMP24 to RGB565 converter.
#include <stdio.h>
#include <string.h>
#include <windows.h>
#define RGB16(red, green, blue) ( ((red >> 3) << 11) | ((green >> 2) << 5) | (blue >> 3))
#define MAX_OSD_WIDTH 720 // Max Davinci OSD width
#define MAX_OSD_HEIGHT 576 // Max Davinci OSD height (for PAL support)
#define MAX_OSD_SIZE MAX_OSD_WIDTH*MAX_OSD_HEIGHT
#define NTSC_OSD_WIDTH 720
#define NTSC_OSD_HEIGHT 480
int main(int argc, char *argv[])
{
unsigned short osdData[720 * 480];
FILE *rgb24file;
FILE *rgb16file;
FILE *rgb16SourceFile;
unsigned char red, green, blue; //pixel bytes
long fileSize;
int x, y;
int width=NTSC_OSD_WIDTH, height=NTSC_OSD_HEIGHT; //Default values
/* STARTUP ADJUSTMENTS */
if (argc < 2)
{
printf("Usage: %s filename [width][height]\n", argv[0]);
return -1;
}
else if ((argc > 2) && (argc != 4))
{
printf("Must specify both width and height or neither\n");
printf("Usage: %s filename [width][height]\n", argv[0]);
return -1;
}
else if ((argc == 4) && (atoi(argv[2]) > MAX_OSD_WIDTH))
{
printf("width cannot exceed %d pixels\n", MAX_OSD_WIDTH);
return -1;
}
else if ((argc==4) && (atoi(argv[3]) > MAX_OSD_HEIGHT))
{
printf("height cannot exceed %d pixels\n", MAX_OSD_HEIGHT);
return -1;
}
else if (argc==4)
{
//Valid width and Height were entered; therefore override defaults
width = atoi(argv[2]);
height = atoi(argv[3]);
}
/* CONVERSION PROCESS STARTING */
printf("Preparing to convert %s (%d x %d)....\n", argv[1], width, height);
// Open file in read-binary mode
rgb24file = fopen(argv[1], "rb");
if (rgb24file == NULL)
{
printf("could not find file %s \n", argv[1]);
return -1;
}
// Get size of file
fseek(rgb24file, 0, SEEK_END);
fileSize = ftell(rgb24file);
fseek(rgb24file, 0, SEEK_SET);
printf("size %d\n", fileSize);
//Skip BMP header information (which is 54 byte)
fseek(rgb24file, 54, SEEK_SET);
fileSize = fileSize - 54;
//Ensure file size does not exceed Max supported OSD size
if (fileSize > (MAX_OSD_SIZE*3))
{
printf("This file is too large, maximum supported size is 720x576x3\n");
}
else if (((fileSize % 3) !=0)|| (fileSize != (width*height*3)))
{
printf("this file does not have the size expected \n");
}
/* PROCESS PART */
else
{
for( x=0; x < (width*height); x++) //for every pixel, read the rgb values and store them in osdData[]
{
fread(&blue, sizeof(char), 1, rgb24file);
fread(&green, sizeof(char), 1, rgb24file);
fread(&red, sizeof(char), 1, rgb24file);
osdData[x] = RGB16(red, green, blue);
}
// Open .h file
rgb16SourceFile = fopen("rgb565_image.h", "w");
fprintf (rgb16SourceFile, "unsigned long rgb565_image_720x480[] = {\n");
// Open file in read-binary mode
rgb16file = fopen("osd.r16", "wb");
for (y= height -1; y >=0; y--)
{
for (x=0; x < width; x ++)
{
fprintf(rgb16SourceFile, "0x%X,\n", osdData[(width*y) + x]);
//printf(" %X\n", osdData[(width*y) + x]);
//write to osd.r16 file in a binary stream
fwrite(&osdData[(width*y) + x], sizeof(short), 1, rgb16file);
}
}
fprintf (rgb16SourceFile, "};\n");
fclose(rgb16file);
fclose(rgb16SourceFile);
}
fclose(rgb24file);
return 0;
}
Thank you in advance,
A. Erman Kulunyar