bitmap 이미지를 배열 형태의 c/c++ header로 만드는 소스

이미지 디코더도 없고, RTOS가 사용된 프로세서에서 GUI구성을 위해 만들었던 소스다. 

24bit bitmap 파일을 읽어 이미지 부분을 아래와 같은 형태로 만들어준다.


unsigned short icon_joystick[] = { 48, 48, 
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
 ... 중략 ...
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
0x0000, 0x0000, 0x0000, 0x0000  }; 


배열의 첫번째와 두번째 데이터는 이미지의 width, height다.
이미지의 픽셀 데이터는 RGB16형태로 저장했다.

[사용법]

> bmp2header [bmp file path] ...

bmp 파일은 여러개 사용가능하다.
실행하면 icon.h이 생성된다.

[source code]

/*=========================================================
    INCLUDE
=========================================================*/
#include <stdio.h>
#include <stdarg.h>
#include <tchar.h>
#include <Windows.h>
#include <atlstr.h>
/*=========================================================
DEFINE
=========================================================*/
#ifndef safe_free
#define safe_free(x) if(x){free(x);x=NULL;}
#endif

#ifndef RGB565
#define RGB565(R,G,B) (((R>>3)<<11)+((G>>2)<<5)+(B>>3))
#endif

#define codetext_max_len 512
typedef struct _bmp2bin_ctx_t
{
/* icon header file
*/
HANDLE hHeaderFile;
char code[codetext_max_len];

/* bitmap file
*/
HANDLE hBMPFile;
DWORD dwBMPFileSize;
DWORD dwBMPFileSizeHigh;
BITMAPINFO *bmi;
BYTE *bmp;

}bmp2bin_ctx_t;

/*=========================================================

=========================================================*/
int OpenHeaderFile(bmp2bin_ctx_t *ctx);
int CloseHeaderFile(bmp2bin_ctx_t *ctx);
int OpenBitMapFile(bmp2bin_ctx_t *ctx, _TCHAR* filepath);
int CloseBitMapFile(bmp2bin_ctx_t *ctx);
int ConvertBitMapToHeader(bmp2bin_ctx_t *ctx, _TCHAR* filepath, BOOL bInverse);
void bmp2bin_deinit(bmp2bin_ctx_t *ctx);
bmp2bin_ctx_t *bmp2bin_init();

/*=========================================================

=========================================================*/

int OpenBitMapFile(bmp2bin_ctx_t *ctx, _TCHAR* filepath)
{
DWORD dwReadLen;

if (!ctx || !filepath) return -1;

if (ctx->hBMPFile)
{
CloseBitMapFile(ctx);
}

// open file
ctx->hBMPFile = CreateFile(filepath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (ctx->hBMPFile == NULL || ctx->hBMPFile == INVALID_HANDLE_VALUE)
{
printf("err : %S open fail \n", filepath);
ctx->hBMPFile = NULL;
return -1;
}

// get file size
ctx->dwBMPFileSize = GetFileSize(ctx->hBMPFile, &ctx->dwBMPFileSizeHigh);

if (!ctx->dwBMPFileSize)
{
printf("err : please confirm %S \n", filepath);
return -1;
}

// alloc bitmap buffer..
ctx->bmp = (BYTE*)malloc(ctx->dwBMPFileSize);
if (!ctx->bmp)
{
return -1;
}

// read bitmap file
ReadFile(ctx->hBMPFile, ctx->bmp, ctx->dwBMPFileSize, &dwReadLen, NULL);
ctx->bmi = (BITMAPINFO*)(&ctx->bmp[14]);


return 1;
}

int ConvertBitMapToHeader(bmp2bin_ctx_t *ctx, _TCHAR* filepath, BOOL bInverse)
{
CString Name = TEXT("");
DWORD dwWriteLen = 0;
int pixelindex = 0;
int rawcnt = 0;
BYTE R, G, B;
unsigned short rgb16;
int widthcnt = 0;
int widthbytemax = 0;
int paddingcnt = 0;

if (!ctx || !filepath)
return -1;


Name = filepath;
Name.Delete(Name.GetLength() - 4, 4);

pixelindex = 14 + sizeof(BITMAPINFOHEADER);

sprintf_s(ctx->code, codetext_max_len, "unsigned short icon_%S[] = { %d, %d, \r\n\0", Name.GetBuffer(), ctx->bmi->bmiHeader.biWidth, ctx->bmi->bmiHeader.biHeight);

widthbytemax = ctx->bmi->bmiHeader.biWidth * 3;
paddingcnt = (((widthbytemax + 3) / 4) * 4) - widthbytemax;
widthcnt = 0;

WriteFile(ctx->hHeaderFile, ctx->code, strlen(ctx->code), &dwWriteLen, NULL);

while (ctx->dwBMPFileSize > pixelindex)
{
B = ctx->bmp[pixelindex++];
G = ctx->bmp[pixelindex++];
R = ctx->bmp[pixelindex++];
widthcnt++;
if (widthcnt >= ctx->bmi->bmiHeader.biWidth)
{
widthcnt = 0;
pixelindex += paddingcnt;
}

rgb16 = RGB565(R, G, B);

if (ctx->dwBMPFileSize > pixelindex)
{
sprintf_s(ctx->code, codetext_max_len, "0x%04X, \0", rgb16);
}
else
{
sprintf_s(ctx->code, codetext_max_len, "0x%04X  \0", rgb16);
}

WriteFile(ctx->hHeaderFile, ctx->code, strlen(ctx->code), &dwWriteLen, NULL);
rawcnt++;
if (rawcnt >= 10)
{
sprintf_s(ctx->code, codetext_max_len, "\r\n\0");
WriteFile(ctx->hHeaderFile, ctx->code, strlen(ctx->code), &dwWriteLen, NULL);
rawcnt = 0;
}

}

sprintf_s(ctx->code, codetext_max_len, "}; \r\n\r\n\r\n\0");
WriteFile(ctx->hHeaderFile, ctx->code, strlen(ctx->code), &dwWriteLen, NULL);

return 0;
}

int CloseBitMapFile(bmp2bin_ctx_t *ctx)
{
if (!ctx) return -1;

ctx->dwBMPFileSize = 0;
ctx->dwBMPFileSizeHigh = 0;
ctx->bmi = NULL;

safe_free(ctx->bmp);

if (ctx->hBMPFile)
{
CloseHandle(ctx->hBMPFile);
ctx->hBMPFile = NULL;
}

return 1;
}

int OpenHeaderFile(bmp2bin_ctx_t *ctx)
{
DWORD dwWriteLen = 0;

ctx->hHeaderFile = CreateFile(TEXT("icon.h"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (!ctx->hHeaderFile || ctx->hHeaderFile == INVALID_HANDLE_VALUE)
{
printf("err: Create header fail\n");
ctx->hHeaderFile = NULL;
return -1;
}

sprintf_s(ctx->code, codetext_max_len, "#ifndef __ICON_H__\r\n#define __ICON_H__\r\n\r\n\0");
WriteFile(ctx->hHeaderFile, ctx->code, strlen(ctx->code), &dwWriteLen, NULL);

return 0;
}

int CloseHeaderFile(bmp2bin_ctx_t *ctx)
{
DWORD dwWriteLen;
if (ctx->hHeaderFile)
{
sprintf_s(ctx->code, codetext_max_len, "#endif\r\n\0");

WriteFile(ctx->hHeaderFile, ctx->code, strlen(ctx->code), &dwWriteLen, NULL);
CloseHandle(ctx->hHeaderFile);
ctx->hHeaderFile = NULL;
}

return 0;
}

bmp2bin_ctx_t *bmp2bin_init()
{
bmp2bin_ctx_t *ctx = NULL;
ctx = (bmp2bin_ctx_t*)malloc(sizeof(bmp2bin_ctx_t));
if (ctx)
{
memset(ctx, 0, sizeof(bmp2bin_ctx_t));

if (OpenHeaderFile(ctx) < 0)
{
bmp2bin_deinit(ctx);
return NULL;
}
}

return ctx;
}

void bmp2bin_deinit(bmp2bin_ctx_t *ctx)
{
if (ctx)
{
if (ctx->hBMPFile)
{
CloseBitMapFile(ctx);
}

CloseHeaderFile(ctx);

safe_free(ctx);
}
}

/*=========================================================
main
=========================================================*/
void printusage()
{
printf("usage : bmp2header [bmp file path] ...\n");
}

int _tmain(int argc, _TCHAR* argv[])
{
int bmpcnt = argc - 1;
int inparamindex = 1;
bmp2bin_ctx_t *ctx = NULL;

if (bmpcnt <= 0)
{
printf("err : wrong param\n");
printusage();
return 0;
}

ctx = bmp2bin_init();
if (!ctx)
{
return 0;
}

while (bmpcnt>0)
{
if (OpenBitMapFile(ctx, argv[inparamindex])<0)
{
bmp2bin_deinit(ctx);
return 0;
}

ConvertBitMapToHeader(ctx, argv[inparamindex],TRUE);

CloseBitMapFile(ctx);
inparamindex++;
bmpcnt--;
}

bmp2bin_deinit(ctx);
printf("done \n");
return 0;
}

댓글

이 블로그의 인기 게시물

간단한 cfar 알고리즘에 대해

windows에서 간단하게 크롬캐스트(Chromecast)를 통해 윈도우 화면 미러링 방법

base64 인코딩 디코딩 예제 c 소스

아두이노(arduino) 심박센서 (heart rate sensor) 심박수 측정 example code

python asyncio를 이용한 async socket server client example code