mirror of
https://github.com/jfdelnero/rf-tools.git
synced 2024-11-21 11:21:47 -05:00
bmp files loader/writer.
This commit is contained in:
parent
ed2a200d4b
commit
fafd7fa578
560
src/common/bmp_file.c
Normal file
560
src/common/bmp_file.c
Normal file
@ -0,0 +1,560 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//-------------------------------------------------------------------------------//
|
||||||
|
//-------------------------------------------------------------------------------//
|
||||||
|
//-----------H----H--X----X-----CCCCC----22222----0000-----0000------11----------//
|
||||||
|
//----------H----H----X-X-----C--------------2---0----0---0----0--1--1-----------//
|
||||||
|
//---------HHHHHH-----X------C----------22222---0----0---0----0-----1------------//
|
||||||
|
//--------H----H----X--X----C----------2-------0----0---0----0-----1-------------//
|
||||||
|
//-------H----H---X-----X---CCCCC-----222222----0000-----0000----1111------------//
|
||||||
|
//-------------------------------------------------------------------------------//
|
||||||
|
//----------------------------------------------------- http://hxc2001.free.fr --//
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// File : bmp_file.c
|
||||||
|
// Contains: bmp image file loader / writer
|
||||||
|
//
|
||||||
|
// This file is part of rf-tools.
|
||||||
|
//
|
||||||
|
// Written by: Jean-François DEL NERO
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 Jean-François DEL NERO
|
||||||
|
//
|
||||||
|
// You are free to do what you want with this code.
|
||||||
|
// A credit is always appreciated if you use it into your product :)
|
||||||
|
//
|
||||||
|
// Change History (most recent first):
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "bmp_file.h"
|
||||||
|
|
||||||
|
int bmp_load(char * file,bitmap_data * bdata)
|
||||||
|
{
|
||||||
|
FILE * f;
|
||||||
|
int i,j;
|
||||||
|
int xsize,ysize;
|
||||||
|
int bitperpixel;
|
||||||
|
int palettesize;
|
||||||
|
unsigned int bitmapdataoffset,bitmapdatalinesize;
|
||||||
|
unsigned char * linebuffer;
|
||||||
|
BITMAPFILEHEADER bitmap_header;
|
||||||
|
BITMAPINFOHEADER bitmap_info_header;
|
||||||
|
RGBQUAD * palette;
|
||||||
|
|
||||||
|
palette = NULL;
|
||||||
|
linebuffer = NULL;
|
||||||
|
|
||||||
|
f = fopen(file,"rb");
|
||||||
|
if(f)
|
||||||
|
{
|
||||||
|
if( fread(&bitmap_header,sizeof(BITMAPFILEHEADER),1,f) != 1 )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
if( bitmap_header.bfType == 19778 )
|
||||||
|
{
|
||||||
|
if( fread(&bitmap_info_header,sizeof(BITMAPINFOHEADER),1,f) != 1 )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
xsize=bitmap_info_header.biWidth;
|
||||||
|
ysize=bitmap_info_header.biHeight;
|
||||||
|
bitperpixel=bitmap_info_header.biBitCount;
|
||||||
|
|
||||||
|
if(!bitmap_info_header.biCompression)
|
||||||
|
{
|
||||||
|
|
||||||
|
// read palette
|
||||||
|
switch(bitperpixel)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
palettesize=2;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
palettesize=16;
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
palettesize=256;
|
||||||
|
break;
|
||||||
|
case 24:
|
||||||
|
palettesize=0;
|
||||||
|
break;
|
||||||
|
case 32:
|
||||||
|
palettesize=0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
palettesize=0;
|
||||||
|
//non supported
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
palette=0;
|
||||||
|
if(palettesize)
|
||||||
|
{
|
||||||
|
palette=(RGBQUAD *) malloc(palettesize*sizeof(RGBQUAD));
|
||||||
|
if(!palette)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
memset(palette,0,palettesize*sizeof(RGBQUAD));
|
||||||
|
|
||||||
|
fseek(f,sizeof(BITMAPFILEHEADER)+ bitmap_info_header.biSize ,SEEK_SET);
|
||||||
|
if( fread(palette,palettesize*sizeof(RGBQUAD),1,f) != 1 )
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmapdataoffset = sizeof(BITMAPFILEHEADER)+ bitmap_info_header.biSize + (palettesize*sizeof(RGBQUAD));
|
||||||
|
fseek(f,bitmapdataoffset ,SEEK_SET);
|
||||||
|
|
||||||
|
bdata->xsize = xsize;
|
||||||
|
bdata->ysize = ysize;
|
||||||
|
bdata->data = (uint32_t *)malloc(xsize*ysize*sizeof(uint32_t));
|
||||||
|
if(!bdata->data)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
memset(bdata->data,0,xsize*ysize*sizeof(uint32_t));
|
||||||
|
|
||||||
|
switch(bitperpixel)
|
||||||
|
{
|
||||||
|
case 1:
|
||||||
|
if((xsize/8 + (xsize&7))&0x3)
|
||||||
|
bitmapdatalinesize = (((xsize/8 + (xsize&7)) & (~0x3)) + 0x4);
|
||||||
|
else
|
||||||
|
bitmapdatalinesize = (xsize/8 + (xsize&7));
|
||||||
|
|
||||||
|
linebuffer = (unsigned char *)malloc(bitmapdatalinesize);
|
||||||
|
if(!linebuffer)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(i = 0; i < ysize; i++ )
|
||||||
|
{
|
||||||
|
fseek(f,bitmapdataoffset + (bitmapdatalinesize*i) ,SEEK_SET);
|
||||||
|
if( fread(linebuffer,bitmapdatalinesize,1,f) != 1 )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(j=0;j<xsize;j++)
|
||||||
|
{
|
||||||
|
bdata->data[(xsize*((ysize-1)-i))+j]=palette[(linebuffer[(j/8)]>>(1*((7-(j))&7)))&0x1].rgbRed |
|
||||||
|
palette[(linebuffer[(j/8)]>>(1*((7-(j))&7)))&0x1].rgbGreen<<8 |
|
||||||
|
palette[(linebuffer[(j/8)]>>(1*((7-(j))&7)))&0x1].rgbBlue<<16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(linebuffer);
|
||||||
|
linebuffer = NULL;
|
||||||
|
free(palette);
|
||||||
|
palette = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if((xsize/2 + (xsize&1))&0x3)
|
||||||
|
bitmapdatalinesize = (((xsize/2 + (xsize&1)) & (~0x3)) + 0x4);
|
||||||
|
else
|
||||||
|
bitmapdatalinesize = (xsize/2 + (xsize&1));
|
||||||
|
|
||||||
|
linebuffer=(unsigned char *) malloc(bitmapdatalinesize);
|
||||||
|
if(!linebuffer)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(i=0;i<ysize;i++)
|
||||||
|
{
|
||||||
|
fseek(f,bitmapdataoffset + (bitmapdatalinesize*i) ,SEEK_SET);
|
||||||
|
if( fread(linebuffer,bitmapdatalinesize,1,f) != 1 )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(j=0;j<xsize;j++)
|
||||||
|
{
|
||||||
|
bdata->data[(xsize*((ysize-1)-i))+j]=palette[(linebuffer[(j/2)]>>(4*((~j)&1)))&0xF].rgbRed |
|
||||||
|
palette[(linebuffer[(j/2)]>>(4*((~j)&1)))&0xF].rgbGreen<<8 |
|
||||||
|
palette[(linebuffer[(j/2)]>>(4*((~j)&1)))&0xF].rgbBlue<<16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(linebuffer);
|
||||||
|
linebuffer = NULL;
|
||||||
|
free(palette);
|
||||||
|
palette = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
if(xsize&0x3)
|
||||||
|
bitmapdatalinesize = ((xsize & (~0x3)) + 0x4);
|
||||||
|
else
|
||||||
|
bitmapdatalinesize = xsize;
|
||||||
|
|
||||||
|
linebuffer = (unsigned char *)malloc(bitmapdatalinesize);
|
||||||
|
if(!linebuffer)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(i=0;i<ysize;i++)
|
||||||
|
{
|
||||||
|
fseek(f,bitmapdataoffset + (bitmapdatalinesize*i) ,SEEK_SET);
|
||||||
|
if( fread(linebuffer,bitmapdatalinesize,1,f) != 1 )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(j=0;j<xsize;j++)
|
||||||
|
{
|
||||||
|
bdata->data[(xsize*((ysize-1)-i))+j]=palette[linebuffer[j]].rgbRed |
|
||||||
|
palette[linebuffer[j]].rgbGreen<<8 |
|
||||||
|
palette[linebuffer[j]].rgbBlue<<16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(linebuffer);
|
||||||
|
linebuffer = NULL;
|
||||||
|
free(palette);
|
||||||
|
palette = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 24:
|
||||||
|
if((xsize*3)&0x3)
|
||||||
|
bitmapdatalinesize=(((xsize*3) & (~0x3)) + 0x4);
|
||||||
|
else
|
||||||
|
bitmapdatalinesize=(xsize*3);
|
||||||
|
|
||||||
|
linebuffer=(unsigned char *)malloc(bitmapdatalinesize);
|
||||||
|
if(!linebuffer)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(i=0;i<ysize;i++)
|
||||||
|
{
|
||||||
|
fseek(f,bitmapdataoffset + (bitmapdatalinesize*i) ,SEEK_SET);
|
||||||
|
if( fread(linebuffer,bitmapdatalinesize,1,f) != 1 )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(j=0;j<xsize;j++)
|
||||||
|
{
|
||||||
|
bdata->data[(xsize*((ysize-1)-i))+j]=linebuffer[j*3+2] |
|
||||||
|
linebuffer[j*3+1]<<8 |
|
||||||
|
linebuffer[j*3+0]<<16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(linebuffer);
|
||||||
|
linebuffer = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 32:
|
||||||
|
if((xsize*4)&0x3)
|
||||||
|
bitmapdatalinesize=(((xsize*4) & (~0x3)) + 0x4);
|
||||||
|
else
|
||||||
|
bitmapdatalinesize=(xsize*4);
|
||||||
|
|
||||||
|
linebuffer=(unsigned char *)malloc(bitmapdatalinesize);
|
||||||
|
if(!linebuffer)
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(i=0;i<ysize;i++)
|
||||||
|
{
|
||||||
|
fseek(f,bitmapdataoffset + (bitmapdatalinesize*i) ,SEEK_SET);
|
||||||
|
if( fread(linebuffer,bitmapdatalinesize,1,f) != 1 )
|
||||||
|
goto error;
|
||||||
|
|
||||||
|
for(j=0;j<xsize;j++)
|
||||||
|
{
|
||||||
|
bdata->data[(xsize*((ysize-1)-i))+j]=linebuffer[j*4+2] |
|
||||||
|
linebuffer[j*4+1]<<8 |
|
||||||
|
linebuffer[j*4+0]<<16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(linebuffer);
|
||||||
|
linebuffer = NULL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
//non supported
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// non supported
|
||||||
|
fclose(f);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// non bitmap file
|
||||||
|
fclose(f);
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
return 0; // ok
|
||||||
|
}
|
||||||
|
|
||||||
|
//file error
|
||||||
|
return -3;
|
||||||
|
|
||||||
|
error:
|
||||||
|
if(f)
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
if(palette)
|
||||||
|
free(palette);
|
||||||
|
|
||||||
|
if(linebuffer)
|
||||||
|
free(linebuffer);
|
||||||
|
|
||||||
|
return -3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bmp24b_write(char * file,bitmap_data * bdata)
|
||||||
|
{
|
||||||
|
FILE * f;
|
||||||
|
int i,j;
|
||||||
|
BITMAPFILEHEADER bitmap_header;
|
||||||
|
BITMAPINFOHEADER bitmap_info_header;
|
||||||
|
uint32_t bitmapdatalinesize;
|
||||||
|
unsigned char * linebuffer;
|
||||||
|
|
||||||
|
f = fopen(file,"wb");
|
||||||
|
if(f)
|
||||||
|
{
|
||||||
|
memset(&bitmap_header,0,sizeof(BITMAPFILEHEADER));
|
||||||
|
|
||||||
|
bitmap_header.bfType = 19778;
|
||||||
|
bitmap_header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
||||||
|
|
||||||
|
bitmapdatalinesize = bdata->xsize*3;
|
||||||
|
|
||||||
|
if(bitmapdatalinesize&0x3)
|
||||||
|
bitmapdatalinesize = ((bitmapdatalinesize & (~0x3)) + 0x4);
|
||||||
|
|
||||||
|
bitmap_header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (bitmapdatalinesize*bdata->ysize);
|
||||||
|
fwrite(&bitmap_header,1,sizeof(BITMAPFILEHEADER),f);
|
||||||
|
|
||||||
|
memset(&bitmap_info_header,0,sizeof(BITMAPINFOHEADER));
|
||||||
|
bitmap_info_header.biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
bitmap_info_header.biBitCount = 24;
|
||||||
|
bitmap_info_header.biHeight = bdata->ysize;
|
||||||
|
bitmap_info_header.biWidth = bdata->xsize;
|
||||||
|
bitmap_info_header.biPlanes = 1;
|
||||||
|
bitmap_info_header.biSizeImage = bitmapdatalinesize*bdata->ysize;
|
||||||
|
|
||||||
|
fwrite(&bitmap_info_header,1,sizeof(BITMAPINFOHEADER),f);
|
||||||
|
|
||||||
|
linebuffer = (unsigned char *)malloc(bitmapdatalinesize);
|
||||||
|
memset(linebuffer,0,bitmapdatalinesize);
|
||||||
|
|
||||||
|
for(i=0;i<bdata->ysize;i++)
|
||||||
|
{
|
||||||
|
for(j=0;j<bdata->xsize;j++)
|
||||||
|
{
|
||||||
|
linebuffer[(j*3)+2] = (unsigned char)( (bdata->data[((((bdata->ysize-1)-i))*bdata->xsize) + j]) & 0xFF);
|
||||||
|
linebuffer[(j*3)+1] = (unsigned char)( (bdata->data[((((bdata->ysize-1)-i))*bdata->xsize) + j]>>8) & 0xFF);
|
||||||
|
linebuffer[(j*3)+0] = (unsigned char)( (bdata->data[((((bdata->ysize-1)-i))*bdata->xsize) + j]>>16) & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(linebuffer,1,bitmapdatalinesize,f);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(linebuffer);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bmp16b_write(char * file,bitmap_data * bdata)
|
||||||
|
{
|
||||||
|
FILE * f;
|
||||||
|
int i,j;
|
||||||
|
unsigned short color;
|
||||||
|
BITMAPFILEHEADER bitmap_header;
|
||||||
|
BITMAPINFOHEADER bitmap_info_header;
|
||||||
|
uint32_t bitmapdatalinesize;
|
||||||
|
unsigned char * linebuffer;
|
||||||
|
|
||||||
|
f = fopen(file,"wb");
|
||||||
|
if(f)
|
||||||
|
{
|
||||||
|
memset(&bitmap_header,0,sizeof(BITMAPFILEHEADER));
|
||||||
|
|
||||||
|
bitmap_header.bfType = 19778;
|
||||||
|
bitmap_header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
|
||||||
|
|
||||||
|
bitmapdatalinesize = bdata->xsize*2;
|
||||||
|
|
||||||
|
if(bitmapdatalinesize&0x3)
|
||||||
|
bitmapdatalinesize = ((bitmapdatalinesize & (~0x3)) + 0x4);
|
||||||
|
|
||||||
|
bitmap_header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (bitmapdatalinesize*bdata->ysize);
|
||||||
|
fwrite(&bitmap_header,1,sizeof(BITMAPFILEHEADER),f);
|
||||||
|
|
||||||
|
memset(&bitmap_info_header,0,sizeof(BITMAPINFOHEADER));
|
||||||
|
bitmap_info_header.biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
bitmap_info_header.biBitCount = 16;
|
||||||
|
bitmap_info_header.biHeight = bdata->ysize;
|
||||||
|
bitmap_info_header.biWidth = bdata->xsize;
|
||||||
|
bitmap_info_header.biPlanes = 1;
|
||||||
|
bitmap_info_header.biSizeImage = bitmapdatalinesize*bdata->ysize;
|
||||||
|
|
||||||
|
fwrite(&bitmap_info_header,1,sizeof(BITMAPINFOHEADER),f);
|
||||||
|
|
||||||
|
linebuffer = (unsigned char *)malloc(bitmapdatalinesize);
|
||||||
|
memset(linebuffer,0,bitmapdatalinesize);
|
||||||
|
|
||||||
|
for(i=0;i<bdata->ysize;i++)
|
||||||
|
{
|
||||||
|
for(j=0;j<bdata->xsize;j++)
|
||||||
|
{
|
||||||
|
|
||||||
|
color = (unsigned short)( (bdata->data[((((bdata->ysize-1)-i))*bdata->xsize) + j]) & 0xFF)>>3;
|
||||||
|
color = (color<<5) | (unsigned short)( (bdata->data[((((bdata->ysize-1)-i))*bdata->xsize) + j]>>8) & 0xFF)>>3;
|
||||||
|
color = (color<<5) | (unsigned short)( (bdata->data[((((bdata->ysize-1)-i))*bdata->xsize) + j]>>16) & 0xFF)>>3;
|
||||||
|
|
||||||
|
linebuffer[(j*2)+0] = color & 0xFF;
|
||||||
|
linebuffer[(j*2)+1] = (color>>8) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(linebuffer,1,bitmapdatalinesize,f);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(linebuffer);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int packlineRLE(unsigned char * src,int size,unsigned char * dst)
|
||||||
|
{
|
||||||
|
int cnt,i,j,lastvalue;
|
||||||
|
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
j = 0;
|
||||||
|
lastvalue = src[0];
|
||||||
|
cnt = 0;
|
||||||
|
while(i < size)
|
||||||
|
{
|
||||||
|
if( (src[i] == lastvalue) && (cnt<254))
|
||||||
|
{
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dst[j++] = cnt;
|
||||||
|
dst[j++] = lastvalue;
|
||||||
|
|
||||||
|
lastvalue = src[i];
|
||||||
|
cnt = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cnt)
|
||||||
|
{
|
||||||
|
dst[j++] = cnt;
|
||||||
|
dst[j++] = lastvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dst[j++] = 0;
|
||||||
|
dst[j++] = 0;
|
||||||
|
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bmpRLE8b_write(char * file,bitmap_data * bdata)
|
||||||
|
{
|
||||||
|
FILE * f;
|
||||||
|
int i,lnsize,datasize;
|
||||||
|
BITMAPFILEHEADER bitmap_header;
|
||||||
|
BITMAPINFOHEADER bitmap_info_header;
|
||||||
|
uint32_t bitmapdatalinesize;
|
||||||
|
unsigned char * linebuffer;
|
||||||
|
unsigned char * src_data;
|
||||||
|
unsigned char pal[256*4];
|
||||||
|
|
||||||
|
|
||||||
|
f = fopen(file,"wb");
|
||||||
|
if(f)
|
||||||
|
{
|
||||||
|
memset(&bitmap_header,0,sizeof(BITMAPFILEHEADER));
|
||||||
|
|
||||||
|
bitmap_header.bfType = 19778;
|
||||||
|
bitmap_header.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (256*4);
|
||||||
|
|
||||||
|
bitmapdatalinesize = bdata->xsize*1;
|
||||||
|
|
||||||
|
if(bitmapdatalinesize&0x3)
|
||||||
|
bitmapdatalinesize = ((bitmapdatalinesize & (~0x3)) + 0x4);
|
||||||
|
|
||||||
|
bitmap_header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(pal) + (bitmapdatalinesize*bdata->ysize);
|
||||||
|
fwrite(&bitmap_header,1,sizeof(BITMAPFILEHEADER),f);
|
||||||
|
|
||||||
|
memset(&bitmap_info_header,0,sizeof(BITMAPINFOHEADER));
|
||||||
|
bitmap_info_header.biSize = sizeof(BITMAPINFOHEADER);
|
||||||
|
bitmap_info_header.biBitCount = 8;
|
||||||
|
bitmap_info_header.biHeight = bdata->ysize;
|
||||||
|
bitmap_info_header.biWidth = bdata->xsize;
|
||||||
|
bitmap_info_header.biPlanes = 1;
|
||||||
|
bitmap_info_header.biCompression = 1;
|
||||||
|
bitmap_info_header.biSizeImage = bitmapdatalinesize*bdata->ysize;
|
||||||
|
|
||||||
|
fwrite(&bitmap_info_header,1,sizeof(BITMAPINFOHEADER),f);
|
||||||
|
|
||||||
|
memset(pal,0,sizeof(pal));
|
||||||
|
if(bdata->palette)
|
||||||
|
{
|
||||||
|
for(i=0;i<256;i++)
|
||||||
|
{
|
||||||
|
pal[(i*4) + 0] = (bdata->palette[(i*4) + 2]);
|
||||||
|
pal[(i*4) + 1] = (bdata->palette[(i*4) + 1]);
|
||||||
|
pal[(i*4) + 2] = (bdata->palette[(i*4) + 0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(i=0;i<256;i++)
|
||||||
|
{
|
||||||
|
pal[(i*4) + 0] = i;
|
||||||
|
pal[(i*4) + 1] = i;
|
||||||
|
pal[(i*4) + 2] = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(pal,sizeof(pal),1,f);
|
||||||
|
|
||||||
|
linebuffer = (unsigned char *)malloc((bitmapdatalinesize*2) + (bdata->ysize*2));
|
||||||
|
memset(linebuffer,0,(bitmapdatalinesize*2) + (bdata->ysize*2));
|
||||||
|
|
||||||
|
datasize = 0;
|
||||||
|
src_data = (unsigned char*)bdata->data;
|
||||||
|
for(i=0;i<bdata->ysize;i++)
|
||||||
|
{
|
||||||
|
lnsize = packlineRLE(&src_data[((bdata->ysize-1)-i)*bdata->xsize],bdata->xsize,linebuffer);
|
||||||
|
|
||||||
|
if( i == (bdata->ysize - 1) )
|
||||||
|
{
|
||||||
|
if(lnsize)
|
||||||
|
{
|
||||||
|
linebuffer[lnsize-1] = 0x01; // End of BMP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fwrite(linebuffer,1,lnsize,f);
|
||||||
|
|
||||||
|
datasize = datasize + lnsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bitmap_header.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(pal) + datasize;
|
||||||
|
fseek(f,0,SEEK_SET);
|
||||||
|
fwrite(&bitmap_header,1,sizeof(BITMAPFILEHEADER),f);
|
||||||
|
|
||||||
|
bitmap_info_header.biSizeImage = datasize;
|
||||||
|
fseek(f,sizeof(BITMAPFILEHEADER),SEEK_SET);
|
||||||
|
fwrite(&bitmap_info_header,1,sizeof(BITMAPINFOHEADER),f);
|
||||||
|
|
||||||
|
free(linebuffer);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
48
src/common/bmp_file.h
Normal file
48
src/common/bmp_file.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#pragma pack(1)
|
||||||
|
|
||||||
|
typedef struct bitmap_data_
|
||||||
|
{
|
||||||
|
int16_t xsize;
|
||||||
|
int16_t ysize;
|
||||||
|
int16_t nb_color;
|
||||||
|
uint8_t * palette;
|
||||||
|
uint32_t * data;
|
||||||
|
}bitmap_data;
|
||||||
|
|
||||||
|
typedef struct tagBITMAPFILEHEADER {
|
||||||
|
uint16_t bfType;
|
||||||
|
uint32_t bfSize;
|
||||||
|
uint16_t bfReserved1;
|
||||||
|
uint16_t bfReserved2;
|
||||||
|
uint32_t bfOffBits;
|
||||||
|
} BITMAPFILEHEADER;
|
||||||
|
|
||||||
|
typedef struct tagBITMAPINFOHEADER {
|
||||||
|
uint32_t biSize;
|
||||||
|
uint32_t biWidth;
|
||||||
|
uint32_t biHeight;
|
||||||
|
uint16_t biPlanes;
|
||||||
|
uint16_t biBitCount;
|
||||||
|
uint32_t biCompression;
|
||||||
|
uint32_t biSizeImage;
|
||||||
|
uint32_t biXPelsPerMeter;
|
||||||
|
uint32_t biYPelsPerMeter;
|
||||||
|
uint32_t biClrUsed;
|
||||||
|
uint32_t biClrImportant;
|
||||||
|
} BITMAPINFOHEADER;
|
||||||
|
|
||||||
|
typedef struct tagRGBQUAD {
|
||||||
|
uint8_t rgbBlue;
|
||||||
|
uint8_t rgbGreen;
|
||||||
|
uint8_t rgbRed;
|
||||||
|
uint8_t rgbReserved;
|
||||||
|
} RGBQUAD;
|
||||||
|
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
|
int bmp_load(char * file,bitmap_data * bdata);
|
||||||
|
int bmpRLE8b_write(char * file,bitmap_data * bdata);
|
||||||
|
int bmp24b_write(char * file,bitmap_data * bdata);
|
||||||
|
int bmp16b_write(char * file,bitmap_data * bdata);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user