众所周知,每个字节都是无符号字符,表示范围为0 - 255。 我写了一个代码来编写BMP,代码可以工作..问题是当我尝试写一个宽度/高度超过255的bmp时,它显示为小于255的值。
在宽度的下一位我刚推出1
并且它有效。它输出真实的(500),但我希望它也适用于高度..但它不是。图像破了。
更新:高度超过214的混乱导致损坏的bmp。我错过了什么? 这是我的代码:
typedef unsigned char BYTE; //1
typedef unsigned short WORD; //2
typedef unsigned long DWORD; //4
typedef struct BMP_HEADER
{
BYTE bmp_type[2]; //2
BYTE bmp_size[4]; //4
BYTE bmp_as[4]; //4
BYTE bmp_offset[4]; //4
} BMP;
typedef struct DIB_HEADER
{
BYTE dib_size[4]; //4
DWORD dib_BMPwidth; //4
DWORD dib_BMPheight; //4
BYTE dib_BMPcplanes[2]; //2
BYTE dib_BMPBPX[2]; //2
BYTE dib_BIRGB[4]; //4
BYTE dib_rawsize[4]; //4
BYTE dib_Xresolution[4]; //4
BYTE dib_Yresolution[4]; //4
BYTE dib_cpalette[4]; //4
BYTE dib_cimportant[4]; //4
} DIB;
typedef struct PIXEL_ARRAY
{
BYTE BGR[3]; //3
} PIX;
BYTE* PAD;
DWORD padding(DWORD BMPwidth)
{
int pitch = BMPwidth * 3;
if (pitch % 4 != 0)
{
pitch += 4 - (pitch % 4);
}
return pitch - (BMPwidth * 3);
}
void create_bmp(char BMPname[], DWORD BMPwidth, DWORD BMPheight, WORD BMPR, WORD BMPG, WORD BMPB)
{
// variables
char build_name[256];
FILE* fp;
BMP newBMP;
DIB newDIB;
PIX* template;
gedMaxGameMem = 2827465479;
if(BMPwidth > 1 && BMPheight > 1) template = (PIX*)malloc(BMPwidth*BMPheight);
else template = (PIX*)malloc(sizeof(PIX*)*max(BMPwidth, BMPheight));
// make file
sprintf(build_name, "%s.bmp", BMPname);
fp = fopen(build_name, "wb");
// BM
newBMP.bmp_type[0] = 'B';
newBMP.bmp_type[1] = 'M';
fwrite(&newBMP.bmp_type, 1, 2, fp);
{
// SIZE
DWORD sz = (sizeof(newBMP) + sizeof(newDIB) + sizeof(template));
fwrite(&sz, 1, 1, fp);
}
// Application specifics
fwrite(&newBMP.bmp_as, 1, 4, fp);
// offset
newBMP.bmp_offset[0] = (sizeof(newBMP) + sizeof(newDIB));
fwrite(&newBMP.bmp_offset, 1, 4, fp);
//
// DIB SIZE
newDIB.dib_size[0] = sizeof(newDIB);
fwrite(&newDIB.dib_size, 1, 4, fp);
// DIB Image width
newDIB.dib_BMPwidth = BMPwidth;
fwrite(&newDIB.dib_BMPwidth, 1, 4, fp);
// DIB Image height
newDIB.dib_BMPheight = BMPheight;
fwrite(&newDIB.dib_BMPheight, 1, 4, fp);
// DIB Color planes
newDIB.dib_BMPcplanes[0] = 1;
fwrite(&newDIB.dib_BMPcplanes, 1, 2, fp);
// DIB BMP Bits per pixel
newDIB.dib_BMPBPX[0] = 24;
fwrite(&newDIB.dib_BMPBPX, 1, 2, fp);
// DIB Compression method
fwrite(&newDIB.dib_BIRGB, 1, 4, fp);
// DIB Raw size
newDIB.dib_rawsize[0] = sizeof(template);
fwrite(&newDIB.dib_rawsize, 1, 4, fp);
// DIB Xresolution
newDIB.dib_Xresolution[0] = 19;
newDIB.dib_Xresolution[1] = 11;
fwrite(&newDIB.dib_Xresolution, 1, 4, fp);
// DIB Yresolution
newDIB.dib_Yresolution[0] = 19;
newDIB.dib_Yresolution[1] = 11;
fwrite(&newDIB.dib_Yresolution, 1, 4, fp);
// DIB Colors palette
fwrite(&newDIB.dib_cpalette, 1, 4, fp);
// DIB Important colors
fwrite(&newDIB.dib_cimportant, 1, 4, fp);
//
{
int i;
for(i=0; i<BMPwidth+1; i++)
{
template[i].BGR[0] = BMPB;
template[i].BGR[1] = BMPG;
template[i].BGR[2] = BMPR;
fwrite(template->BGR, 3, i, fp);
}
}
free(template);
fclose(fp);
}
答案 0 :(得分:1)
如果你想把宽度和高度作为字节来调整,你不能只将第二个字节设置为1,你必须计算确切的值,例如:
uint32_t h = 1024;
height[0] = h & 0xff;
height[1] = (h >> 8) & 0xff;
height[2] = (h >> 16) & 0xff;
height[3] = (h >> 24) & 0xff;
(& 0xff
的屏蔽在这里真的是不必要的,无论如何在将数字拟合成一个字节时都已完成。)
但也许您应该首先在结构中使用更大的整数类型:
typedef struct DIB_HEADER
{
DWORD dib_size;
DWORD dib_BMPwidth;
DWORD dib_BMPheight;
WORD dib_BMPcplanes];
...
};
(这可能会导致字节序问题,但我认为Windows位图以Little-Endian格式存储,所以它不应该是一个问题。)
修改:进一步查看代码,我看到了一些错误:
sizeof(PIX) * BMPwidth + BMWheight
。您对单行,单列和其他位图的区分是没有意义的,并且还会引入错误(即不为每个像素分配每个像素的大小。)BMP
和DIB
结构;因此,它们可能未被初始化,并且在您未明确初始化的字段中存在垃圾。"BM"
标记,因为结构将在那里填充以使下一个字段以四字节边框开始。你也可以使用编译器选项来始终打包你的结构紧紧。)fwrite
写出数据时,您的参数是错误的:您可能想要编写fwrite(&template[i]->RGB, 3, 1, fp)
。但是你的项目数是i
,这意味着你从一开始就一遍又一遍地编写所有内容,但总是附加最后一个字节,如'AABABCABCDABCDE`。 (当所有像素具有相同颜色时,这无关紧要,但文件大小将关闭。)换句话说。您的代码不适用于具有多行的数据。 : - )
以下是编写单色位图的更简单的代码版本:
void create_bmp_uni(const char *fn, int w, int h, int r, int g, int b)
{
FILE* fp;
DWORD rsize = (w * sizeof(PIX) + 3) / 4 * 4;
DWORD pad = rsize - w * sizeof(PIX);
DWORD rawsize = rsize * h * sizeof(PIX);
BYTE zero[3] = {0};
const char *id = "BM";
BMP bmp = {
2 + sizeof(BMP) + sizeof(DIB) + rawsize,
0,
2 + sizeof(BMP) + sizeof(DIB)
};
DIB dib = {
sizeof(DIB),
w,
h,
1,
24,
0,
rawsize,
2835,
2835,
0,
0
};
PIX pix = {b, g, r};
int i, j;
fp = fopen(fn, "wb");
fwrite(id, 1, 2, fp);
fwrite(&bmp, 1, sizeof(bmp), fp);
fwrite(&dib, 1, sizeof(dib), fp);
for(i = 0; i < h; i++) {
for(j = 0; j < w; j++) {
fwrite(&pix, sizeof(pix), 1, fp);
}
if (pad) fwrite(zero, 1, pad, fp);
}
fclose(fp);
}
(调用者必须添加.bmp
后缀。还要注意BM标记是如何与BMP
结构的其余部分分开编写的。)
答案 1 :(得分:0)
输出: http://i.stack.imgur.com/fqxO9.png(每次都用不同的颜色开心) 目前的代码:
typedef unsigned char BYTE; //1
typedef unsigned short WORD; //2
typedef unsigned long DWORD; //4
typedef struct BMP_HEADER
{
BYTE bmp_size[4]; //4
BYTE bmp_as[4]; //4
BYTE bmp_offset[4]; //4
} BMP;
typedef struct DIB_HEADER
{
BYTE dib_size[4]; //4
DWORD dib_w; //4
BYTE dib_h[4]; //4
BYTE dib_BMPcplanes[2]; //2
BYTE dib_BMPBpix[2]; //2
BYTE dib_BIRGB[4]; //4
BYTE dib_rawsize[4]; //4
BYTE dib_Xresolution[4]; //4
BYTE dib_Yresolution[4]; //4
BYTE dib_cpalette[4]; //4
BYTE dib_cimportant[4]; //4
} DIB;
//_______________________________________________________________________________________________//
typedef struct PIXEL_ARRAY
{
BYTE BGR[3]; //3
} PIX;
BYTE* PAD;
DWORD padding(DWORD w)
{
int pitch = w * 3;
if (pitch % 4 != 0)
{
pitch += 4 - (pitch % 4);
}
return pitch - (w * 3);
}
DWORD row_sz(WORD BMPBpix, DWORD w)
{
return ((BMPBpix*w+31)/32)*4;
}
void create_bmp(char BMPname[], DWORD w, DWORD h, BYTE R, BYTE G, BYTE B)
{
// variables
char build_name[256];
FILE* fp;
BMP newBMP;
DIB newDIB;
PIX* pix;
DWORD rsize = (w * sizeof(PIX) + 3) / 4 * 4;
DWORD pad = rsize - w * sizeof(PIX);
DWORD rawsize = rsize * h * sizeof(PIX);
BYTE zero[3] = {0};
const char *id = "BM";
int i, j;
gedMaxGameMem = 2827465479;
if(w > 1 && h > 1) pix = (PIX*)malloc(w*h);
else pix = (PIX*)malloc(sizeof(PIX*)*max(w, h));
// make file
sprintf(build_name, "%s.bmp", BMPname);
fp = fopen(build_name, "wb");
// BM
fwrite(id, 1, 2, fp);
// SIZE
newBMP.bmp_size[0] = (sizeof(newBMP) + sizeof(newDIB) + sizeof(pix));
fwrite(&newBMP.bmp_size, 1, 4, fp);
// Application specifics
fwrite(&newBMP.bmp_as, 1, 4, fp);
// offset
newBMP.bmp_offset[0] = (sizeof(newBMP) + sizeof(newDIB));
fwrite(&newBMP.bmp_offset, 1, 4, fp);
//
// DIB SIZE
newDIB.dib_size[0] = sizeof(newDIB);
fwrite(&newDIB.dib_size, 1, 4, fp);
// DIB Image width
newDIB.dib_w = w;
fwrite(&newDIB.dib_w, 1, 4, fp);
// DIB Image height
newDIB.dib_h[0] = h;
fwrite(&newDIB.dib_h, 1, 4, fp);
// DIB Color planes
newDIB.dib_BMPcplanes[0] = 1;
fwrite(&newDIB.dib_BMPcplanes, 1, 2, fp);
// DIB BMP Bits per pixel
newDIB.dib_BMPBpix[0] = 24;
fwrite(&newDIB.dib_BMPBpix, 1, 2, fp);
// DIB Compression method
fwrite(&newDIB.dib_BIRGB, 1, 4, fp);
// DIB Raw size
newDIB.dib_rawsize[0] = sizeof(pix);
fwrite(&newDIB.dib_rawsize, 1, 4, fp);
// DIB Xresolution
newDIB.dib_Xresolution[0] = 19;
newDIB.dib_Xresolution[1] = 11;
fwrite(&newDIB.dib_Xresolution, 1, 4, fp);
// DIB Yresolution
newDIB.dib_Yresolution[0] = 19;
newDIB.dib_Yresolution[1] = 11;
fwrite(&newDIB.dib_Yresolution, 1, 4, fp);
// DIB Colors palette
fwrite(&newDIB.dib_cpalette, 1, 4, fp);
// DIB Important colors
fwrite(&newDIB.dib_cimportant, 1, 4, fp);
//
for(i = 0; i < h; i++)
{
for(j = 0; j < w; j++)
{
fwrite(&pix, sizeof(pix), 1, fp);
}
if (pad) fwrite(zero, 1, pad, fp);
}
fclose(fp);
}