I'm trying to write an unsigned char
array that I grab from a camera to a bmp file. It's seems to work well except that the output image is strange and blurry. What's strange is that when I save to png format I have a good image. When I check the file with an hexreader I get the good header and the right data size. So I'm wondering why the image is getting blurry if I just write pixel to it.I'm wanting to use bmp format because I grab picture from a camera on a raspberry pi. I want to have a high framerate so png is too slow to write on disk.
The header of the bmp file :
00000000: 424d 36bb 1700 0000 0000 3600 0000 2800 BM6.......6...(.
00000010: 0000 a005 0000 3804 0000 0100 0800 0000 ......8.........
00000020: 0000 00bb 1700 232e 0000 232e 0000 0000 ......#...#.....
00000030: 0000 0000 0000 ......
The after is the right length : 1555200 bytes.
Here is my function that write bmp file :
#define BMP_HEADER_SIZE 14
#define BMP_INFO_HEADER_SIZE 40
#define BMP_NO_COMPRESSION 0
#define BMP_MAX_NUMBER_OF_COLORS 0
#define BMP_ALL_COLOR_REQUIRED 0
int saveImgToBmp(unsigned char *data, const char *path, int width, int height,
int bytesPerPixel) {
FILE *fp = fopen(path, "wb");
// Writing header
const char *BM = "BM";
fwrite(&BM[0], 1, 1, fp);
fwrite(&BM[1], 1, 1, fp);
int paddedRowSize = (int) (4 * ceil((float) width / 4.0f)) * bytesPerPixel;
uint32_t fileSize = paddedRowSize * height + BMP_HEADER_SIZE + BMP_INFO_HEADER_SIZE;
fwrite(&fileSize, 4, 1, fp);
uint32_t reserved = 0x0000;
fwrite(&reserved, 4, 1, fp);
uint32_t dataOffset = BMP_HEADER_SIZE + BMP_INFO_HEADER_SIZE;
fwrite(&dataOffset, 4, 1, fp);
// Writing info header
uint32_t infoHeaderSize= BMP_INFO_HEADER_SIZE;
fwrite(&infoHeaderSize, 4, 1, fp);
fwrite(&width, 4, 1, fp);
fwrite(&height, 4 ,1, fp);
uint16_t planes = 1;
fwrite(&planes, 2, 1, fp);
uint16_t bitsPerPixel = bytesPerPixel * 8;
fwrite(&bitsPerPixel, 2, 1, fp);
uint32_t compression = BMP_NO_COMPRESSION;
fwrite(&compression, 4, 1, fp);
uint32_t imageSize = width * height * bytesPerPixel;
fwrite(&imageSize, 4, 1, fp);
uint32_t resolution = 11811;
fwrite(&resolution, 4, 1, fp);
fwrite(&resolution, 4, 1, fp);
uint32_t colorsUsed = BMP_MAX_NUMBER_OF_COLORS;
fwrite(&colorsUsed, 4, 1, fp);
uint32_t importantColors = BMP_ALL_COLOR_REQUIRED;
fwrite(&importantColors, 4, 1, fp);
// Writing pixels
int i = 0;
int unpaddedRowSize = width * bytesPerPixel;
for(i = 0; i < height; i++) {
int pixelOffset = ((height - i) - 1) * unpaddedRowSize;
fwrite(&data[pixelOffset], 1, paddedRowSize, fp);
}
fclose(fp);
return 0;
}
And the piece of code that's calling this function :
if(grabResult.Status == Grabbed) {
// Success
getMinMax(imgBuf, grabResult.SizeX, grabResult.SizeY, &min, &max);
printf("Acquisition de l'image #%2d. Valeur grise min = %3u, max = %3u\n",
i + 1, min, max);
char path[11];
sprintf(path, "data/%d.bmp", i + 1);
c = clock();
saveImgToBmp(imgBuf, path, grabResult.SizeX, grabResult.SizeY, 1);
c = clock() - c;
double time_taken = ((double) c)/CLOCKS_PER_SEC;
printf("Temps écoulé : %fs\n", time_taken);
} else if(grabResult.Status == Failed){
fprintf(stderr, "L'image %d n'as pas pu être acquise avec succès. Code d'erreur : 0x%08X/\n", i + 1, grabResult.ErrorCode);
}
The saveImgToPng function :
int saveImgToPng(unsigned char *data, const char * path, int width, int height){
FILE *fp;
int status;
png_bytep row;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
size_t x, y;
fp = fopen(path, "wb");
if(!fp) {
goto fopen_failed;
}
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if(png_ptr == NULL) {
goto png_create_write_struct_failed;
}
info_ptr = png_create_info_struct(png_ptr);
if(info_ptr == NULL) {
goto png_create_info_struct_failed;
}
if (setjmp (png_jmpbuf (png_ptr))) {
goto png_failure;
}
png_set_IHDR (png_ptr,
info_ptr,
width,
height,
8,
PNG_COLOR_TYPE_GRAY,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT);
png_init_io(png_ptr, fp);
png_write_info(png_ptr, info_ptr);
row = (png_bytep) data;
for(y = 0; y < height; y++) {
png_write_row(png_ptr, row);
row += width;
}
png_write_end(png_ptr, NULL);
png_failure:
png_create_info_struct_failed:
png_destroy_write_struct (&png_ptr, &info_ptr);
png_create_write_struct_failed:
fclose (fp);
fopen_failed:
return status;
}
Here an example picture :