저는 지난 며칠 동안이 문제를보고있는 사람이고 전적으로 당황 스럽습니다. OpenSuse Linux에서 Cairo 그래픽 라이브러리를 사용하여 디스플레이 할 Windows 비트 맵 이미지를 해석하려고합니다. 간단히 말해, 각 픽셀의 색상 정보를 배열로 가져와 카이로 (Cairo)에 공급하면됩니다. pixeldata [i] = someColor, 이미지의 모든 픽셀에 적용됩니다. 지금까지 비트 맵 헤더를 파싱하는 방법을 알아 냈고 24 비트 비트 맵을 표시하는 데 효과적이었습니다.8 비트 비트 맵에서 픽셀 데이터를 작성하고 bmiColor 테이블 정보에 액세스하는 중
하지만 지금은 8 비트 비트 맵을 표시하는 데 어려움을 겪고 있으며 다루기 힘든 비 직관적 인 짐승입니다. 이미지를 표시 할 수는 있지만 표시되는 색상이 잘못되었습니다 ... 단지 프로그램을 실행할 때마다 변경됩니다! : P 필자는 bmiColors 팔레트 배열을 잘못 읽고 해석하고 있다고 생각합니다. 다음은 픽셀 배열을 만드는 나의 오랜 인터넷 연구에서 함께 만든 관련 코드입니다 (이 시점에서 헤더 정보는 이미 구문 분석되었으며 m_bmpInfoHeader 및 m_bmpHeader 객체에서 사용할 수 있음).
#define RGB(r, g, b) ((long)(((char)(r) | ((char)((short)(g)) << 8)) | (((char)(b)) << 16)))
#pragma pack (2)
typedef struct tagRGBQUAD {
long rgbBlue;
long rgbGreen;
long rgbRed;
int rgbReserved;
} RGBQUAD;
typedef struct
{
char verifier[2];
unsigned int size;
unsigned short int reserved1, reserved2;
unsigned int offset;
} BITMAPHEADER;
typedef struct
{
unsigned int size; /* Header size in bytes */
signed int width, height; /* Width and height of image */
unsigned short int planes; /* Number of colour planes */
unsigned short int bits; /* Bits per pixel */
unsigned int compression; /* Compression type */
unsigned int imagesize; /* Image size in bytes */
int xresolution,yresolution; /* Pixels per meter */
unsigned int ncolors; /* Number of colors */
unsigned int importantcolors; /* Important colors */
RGBQUAD bmiColors [1];
} BITMAPINFOHEADER;
#pragma pack()
// Function sets up and returns color index for bitmap.
long BitmapDef::GetColorInx (int numbits, char* data, long offset)
{
long inx;
switch (numbits)
{
case 1:
inx = data[offset >> 3];
offset &= 7;
inx >>= offset;
inx &= 0x01;
break;
case 2:
inx = data[offset >> 2];
offset &= 3;
offset <<= 1;
inx >>= offset;
inx &= 0x03;
break;
case 4:
inx = data[offset >> 1];
if (!(offset & 1))
{
inx >>= 4;
}
inx &= 0x0f;
break;
case 24:
{
offset *= 3;
inx = *((long*) &data[offset]);
char r = GetBValue(inx);
char g = GetGValue(inx);
char b = GetRValue(inx);
inx = ((r << 16) + (g << 8) + b);
break;
}
case 8:
default:
inx = data[offset] & 0xff;
break;
}
return inx;
}
void BitmapDef::Build8BitPixelData()
{
m_PixelData = new unsigned int[m_bmpInfoHeader.width * m_bmpInfoHeader.height];
FILE * pFile;
long lSize;
char * buffer;
size_t result;
pFile = fopen ((const char *)m_Filename, "rb");
if (pFile==NULL)
{
fputs ("File error", stderr);
exit (1);
}
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
buffer = (char*) malloc (sizeof(char) * lSize);
if (buffer == NULL) {fputs ("Memory error", stderr); exit (2);}
// copy the file into the buffer:
result = fread (buffer, 1, lSize, pFile);
if (result != lSize) {fputs ("Reading error",stderr); exit (3);}
BITMAPHEADER* bmfh = (BITMAPHEADER*) (&(buffer[0]));
char* bmp = (char*) &buffer[m_bmpHeader.offset];
BITMAPINFOHEADER * bmi = (BITMAPINFOHEADER*) &buffer[sizeof(*bmfh)];
std::cout<<"\nsize: "<<bmi->size<<std::endl;
std::cout<<"width: "<<bmi->width<<std::endl;
std::cout<<"height: "<<bmi->height<<std::endl;
std::cout<<"planes: "<<bmi->planes<<std::endl;
std::cout<<"bits: "<<bmi->bits<<std::endl;
std::cout<<"annnd compression: "<<bmi->planes<<std::endl;
int ix, iy;
int position = 0;
for (iy = 0; iy < bmi->height; ++iy)
{
for (ix = 0; ix < bmi->width; ++ix)
{
int offset = (m_bmpInfoHeader.height - 1 - iy) * m_bmpInfoHeader.width;
offset += ix;
//std::cout<<"offset: "<<offset<<" bmp[offset]: "<<bmp[offset] << " " ;
long inx = GetColorInx (m_bmpInfoHeader.bits, dataBuf, offset);
//std::cout<<inx<<" ";
m_PixelData[position] = RGB(bmi->bmiColors[inx].rgbRed, bmi->bmiColors[inx].rgbGreen, bmi->bmiColors[inx].rgbBlue);
position++;
}
}
fclose (pFile);
free (buffer);
}
아이디어가 있으십니까? Windows가 아닌 환경에서 작업 중이므로 많은 Windows 중심 함수를 C++에서 작동하도록 변환해야합니다. 어떤 도움을 주셔서 감사합니다, 감사합니다!
업데이트 : cbranch의 추천에
덕분에, 나는 숯불는 4 바이트의 구조를 유지하려면, 대신 긴/INT의 특성을 가지도록 RGBQUAD를 수정했습니다. 이렇게하면 색상이 계속 변경되어 문제가 해결되었습니다. 그러나, 이상하게 색상은 여전히 꺼져 있습니다. 지금은 검정색 배경에 녹색 다이아몬드의 간단한 이미지를 표시하려고하지만 어떤 이유로 다이아몬드가 노란색으로 표시됩니다. 어떤 아이디어?
또한 실수로 원래 게시물의 구조체 주변에서 "#pragma pack()"지시문을 남겨두고 게시물에 추가했습니다.
RGBQUAD의 멤버는 'longs'이 아닌 단일 바이트입니다. 전체 RGBQUAD 구조체는 4 바이트입니다. – cbranch
@cbranch - 감사합니다. 이제 문제가 해결되어 프로그램을 실행할 때마다 색상이 바뀌지 않습니다. 그러나 표시된 색상은 여전히 꺼져 있습니다. ATM 검정색 배경에 작고 간단한 녹색 다이아몬드 이미지를 표시하려하지만 녹색 다이아몬드가 노란색으로 나옵니다. 어떤 아이디어? – user1930581
RGBQUAD 구조와 같은 사운드는 거꾸로입니다. –