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)를 통해 윈도우 화면 미러링 방법

간단한 칼만 필터(Kalman Filter) 소스 코드와 사용 예제

안드로이드(android) 전체 화면 시계 앱(clock app) 예제 코드

mkfs.fat Device or resource busy 에러 해결법