[구조체패딩현상]예전에 올렸는데..다시 부탁드리네요.. 왜 결과
지금 bmp파일의 헤더를 파싱하는 프로그램을 작성중인데요.
윈도우와 유닉스가 엔디안이 틀려서 ..그런것일지?? 라는 생각도 들고요..음.
유닉스의 결과와 window의 결과가 왜 틀릴까요??
제가 관심을 가지는 값은 width와 height 이지만서두.. 왜 그런지..원인이 파악이 안네요.
음... 같은 소스를 가지고 한것인데..왜 결과가 틀린지..모르겠네요..컴파일 :: gcc -o getWH getWH.c
window ==>
BITMAPFIELHEADER :ret[14] BITMAPINFOHEADER :ret[40] Remain Data :ret[2786] bftpye[BM]bfsize[2840] bfOffBits[1078] biSize[40] width[42] height[40] planes[1] bitcount[8] compression[0] sizeImage[0 ] XpelsPerMeter[2834] YpleMeter[2834] clrused[0] clrImport[0] ret[14] ret[40] ret[2786] file_length[2840] Press any key to continue
unix 결과==>
getWH 6 12 BITMAPFIELHEADER :ret[14] BITMAPINFOHEADER :ret[40] Remain Data :ret[2786] bftpye[BM ]bfsize[403374080] bfOffBits[906231808] biSize[671088640] width[704643072] height[671088640] planes[256] bitcount[2048] compression[0] sizeImage[0] XpelsPerMeter[302710784] YpleMeter[302710784] clrused[0] clrImport[0] ret[14] ret[40] ret[2786] file_length[2840]
vi getWH.c
"getWH.c" 179 행, 4786 문자
#include<stdio.h>
#include<string.h>
#include<math.h>
#define myPath "./3.bmp"
//win,unix 둘다 없이 했습니다. #pragma align(1) #ifdef Win struct tagBITMAPFIELHEADER{ #else struct __attribute__((packed)) tagBITMAPFIELHEADER #end { unsigned char bfType[2]; //BM unsigned char bfsize[4]; //파일의 크기 unsigned char bfReserved1[2]; unsigned char bfReserved2[2]; unsigned char bfOffBits[4]; //실제 이미지 비트까지의 오프셋 }BITMAPFIELHEADER; #ifdef Win struct tagBITMAPFIELHEADER{ #else struct __attribute__((packed)) tagBITMAPINFOHEADER #end { unsigned char biSize[4]; long biWidth; long biHeight; unsigned char biPlanes[2]; //비트플레인 수 항상 '1' unsigned char biBitCount[2]; //픽셀당 비트수 unsigned char biCompression[4]; //압축유형 unsigned char biSizeImage[4]; //이미지 크기 (바이트단위) long biXPelsPerMeter; //가로 해상도 long biYPelsPerMeter; //세로 해상도 unsigned char biClrUsed[4]; //실제 사용되는 색상수 unsigned char biClrImportant[4]; //중요한 색상 인덱스 } BITMAPINFOHEADER; #pragma align()
int bmp_open(const char *path); //1
unsigned char src_bmp[1000000]; //10M bytes 충분한 양이다.
unsigned char des_bmp[1000000]; //10M bytes 충분한 양이다.
int main()
{
struct __attribute__((packed)) { char a; int b; char c; } foo; struct { char a; int b; char c; } bar; printf("%d\n", sizeof(foo)); printf("%d\n", sizeof(bar));
memset(src_bmp,0x0,sizeof(src_bmp));
memset(des_bmp,0x0,sizeof(des_bmp));
bmp_open(myPath);
return 1;
}//<==main
int bmp_open(const char *path)
{
FILE *fp;
FILE *fp_des;
int i; char c;
int file_length;
int ret;
//bih
unsigned int bfsize;
unsigned int bfOffBits;
//bif
unsigned int biSize,biCompression,biSizeImage,biClrUsed,biClrImportant;
long biWidth,biHeight,biXPelsPerMeter,biYPelsPerMeter;
unsigned short int biPlanes,biBitCount;
int t;
struct tagBITMAPFIELHEADER bih; struct tagBITMAPINFOHEADER bif;
memset(&bih,0x0,sizeof(bih));
memset(&bif,0x0,sizeof(bif));
//======================file 정보 읽어 오는 부분
fp=fopen(path,"rb");
if(fp==NULL)
{
printf("path open fail[%s]\n",path); return -1;
}
fseek(fp,0,SEEK_END);
file_length=ftell(fp);
fseek(fp,0,SEEK_SET);
ret=fread(&bih,1,14,fp);
printf("BITMAPFIELHEADER :ret[%d]\n",ret);
ret=fread(&bif,1,40,fp);
printf("BITMAPINFOHEADER :ret[%d]\n",ret);
ret=fread(src_bmp,1,file_length-(14+40),fp);
printf("Remain Data :ret[%d]\n",ret);
//check_logic 원본.
/*
restHeaderSize = bfh.bfOffBits - sizeof(bfh) - sizeof(bih);
if(restHeaderSize != 0) Error;
다시 더 읽어라.. ^^* 에러 체크 로직을 만들어야 한다.
*/
memcpy(&bfsize,&(bih.bfsize),4);
memcpy(&bfOffBits,&(bih.bfOffBits),4);
printf("bftpye[%s]",bih.bfType);
printf("bfsize[%d] bfOffBits[%d]\n",bfsize,bfOffBits);
memcpy(&biSize,bif.biSize,sizeof(bif.biSize)); //memcpy((long )&biWidth,bif.biWidth,sizeof(bif.biWidth)); // memcpy((long )&biHeight,bif.biHeight,sizeof(bif.biHeight)); biWidth=bif.biWidth; biHeight=bif.biHeight;
memcpy(&biPlanes,bif.biPlanes,sizeof(bif.biPlanes));
memcpy(&biBitCount,bif.biBitCount,sizeof(bif.biBitCount));
memcpy(&biCompression,bif.biCompression,sizeof(bif.biCompression));
memcpy(&biSizeImage,bif.biSizeImage,sizeof(bif.biSizeImage));
// memcpy(&biXPelsPerMeter,bif.biXPelsPerMeter,sizeof(bif.biXPelsPerMeter));
// memcpy(&biYPelsPerMeter,bif.biYPelsPerMeter,sizeof(bif.biYPelsPerMeter));
biXPelsPerMeter=bif.biXPelsPerMeter;
biYPelsPerMeter=bif.biYPelsPerMeter;
memcpy(&biClrUsed,bif.biClrUsed,sizeof(bif.biClrUsed));
memcpy(&biClrImportant,bif.biClrImportant,sizeof(bif.biClrImportant));
printf("biSize[%d] width[%ld] height[%ld] planes[%d] bitcount[%d] compression[%d] sizeImage[%d] XpelsP erMeter[%ld] YpleMeter[%ld] clrused[%d] clrImport[%d]\n", biSize, biWidth,biHeight,biPlanes,biBitCount,biCompression, biSizeImage,biXPelsPerMeter,biYPelsPerMeter,biClrUsed,biClrImportant);fclose(fp);
fp=NULL;
//<========================= file 정보 읽어오는 부분
fp_des=fopen("check_bmp.bmp","wb");
ret=fwrite(&bih,1,14,fp_des);
printf("ret[%d]\n",ret);
ret=fwrite(&bif,1,40,fp_des);
printf("ret[%d]\n",ret);
for(i=0;i<file_length-(14+40);i++)
{
fprintf(fp_des,"%c",src_bmp[i]);
}
printf("ret[%d]\n",i);
fclose(fp_des);
fp_des=NULL;
fp=fopen(path,"rb");
fp_des=fopen("./test_bmp.bmp","wb");
if(fp==NULL)
{
printf("path open fail[%s]\n",path); return -1;
}
fseek(fp,0,SEEK_END);
file_length=ftell(fp);
printf("file_length[%d]\n",file_length);
fseek(fp,0,SEEK_SET);
for(i=0;i<file_length;i++)
{
c=fgetc(fp);
fprintf(fp_des,"%c",c);
}
fclose(fp);
fclose(fp_des);
return 1;
}//<==bmp_open
Re: [구조체패딩현상]예전에 올렸는데..다시 부탁드리네요.. 왜
==================>
결국 엔디안 차이였네요..
bmp파일에서 읽어들인값을 구조체에 그대로 집어넣었는데..
bmp라는 것이 window에서 만든것이니... 엔디안을 바꾸어 주어야 했네요..
쩝.. 여러분께 죄송합니다..
급하게 만든 소스 아래에 다시 올립니다.... 그냥..혹시나 저처럼 생각이 짧은사람들 참조하시라구요..
음.. big,little을 효율적으로 바꾸는 함수 하나..없을까?? 넘 허접한데..생각이...
언제나 즐프를 꿈꾸며~
ntohl, ntohshtonl, htons그럼 고운 하루되시
ntohl, ntohs
htonl, htons
그럼 고운 하루되시길...
=========================
CharSyam ^^ --- 고운 하루
=========================
댓글 달기