我正在尝试从图片中更改像素(格式为bmp,24位) .
我有这3个结构:
对于文件头:
#pragma pack(2)
typedef struct {
unsigned short int typeID;
unsigned int size;
unsigned short int reserved1, reserved2;
unsigned int offset;
}BITMAPFILEHEADER;
#pragma pack(0)
信息 Headers :
typedef struct {
unsigned int headerSize;
signed int widthPixel, heightPixel;
unsigned short int colorPlanes;
unsigned short int bitsPerPixel;
unsigned int compressionMethod;
unsigned int imagesize;
signed int xResolution, yResolution; // pixel per meter
unsigned int nbColor;
unsigned int importantColor;
}BITMAPINFOHEADER;
对于RGB颜色:
typedef struct {
unsigned char blue;
unsigned char green;
unsigned char red;
unsigned char reserved;
} RGBCOLOR;
然后是主要代码:
int main(void) {
BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;
FILE *inFileImage = NULL;
unsigned char *pBitsData = NULL;
int rowSize = 0;
int nImageSize = 0;
inFileImage = fopen("panda.bmp", "r+");
if (inFileImage == NULL)
{
fprintf(stderr, "Unable to open image");
return 0;
}
fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, inFileImage);
rewind(inFileImage);
pBitsData = (unsigned char *)calloc( fileHeader.size, sizeof(unsigned char) );
if( NULL == pBitsData )
{
printf("NO memory!!!!!\n");
}
else
{
fread(pBitsData, fileHeader.size * sizeof(unsigned char), 1, inFileImage);
memcpy(&fileHeader,pBitsData,sizeof(BITMAPFILEHEADER));
printf("Type ID: %x\n", fileHeader.typeID);
printf("File size: %d\n", fileHeader.size);
printf("Offset: %d\n", fileHeader.offset);
printf("**********************\n");
memcpy(&infoHeader, (pBitsData + sizeof(BITMAPFILEHEADER)), sizeof(BITMAPINFOHEADER));
printf("Header size: %u\n", infoHeader.headerSize);
printf("Width: %d\n", infoHeader.widthPixel);
printf("Height: %d\n", infoHeader.heightPixel);
printf("Nb planes: %d\n", infoHeader.colorPlanes);
printf("Bits per pixel: %d\n", infoHeader.bitsPerPixel);
printf("Compression method: %u\n", infoHeader.compressionMethod);
printf("Image size: %u\n", infoHeader.imagesize);
printf("Horizontal pixel per metre: %d\n", infoHeader.xResolution);
printf("Vertical pixel per metre: %d\n", infoHeader.yResolution);
printf("Number color in color table: %u\n", infoHeader.nbColor);
printf("Color important count: %u\n", infoHeader.importantColor);
printf("**********************\n");
rowSize = ((infoHeader.bitsPerPixel * infoHeader.widthPixel + 31) / 32) * 4;
printf("Row Size: %d\n", rowSize);
nImageSize = rowSize * abs(infoHeader.heightPixel);
printf("Pixel Array Size: %d\n", nImageSize);
printf("**********************\n");
RGBCOLOR* pixelData = (RGBCOLOR*)(pBitsData + fileHeader.offset);
// M is define with the value 5 - the 5 pixel from image
printf("Pixel %x, %x, %x\n", pixelData[M].blue, pixelData[M].green, pixelData[M].red);
//fseek(inFileImage, fileHeader.offset, SEEK_CUR);
//fread(pixelData, sizeof(RGBCOLOR), 1, inFileImage);
pixelData[M].red = 0x00;
pixelData[M].blue = 0xef;
pixelData[M].green = 0x00;
//memcpy((pBitsData + fileHeader.offset), &pixelData, sizeof(RGBCOLOR)); // <= here seems to be my problem
//fwrite(pixelData, sizeof(RGBCOLOR), 1, inFileImage); // how can i copy to image from a memory
printf("Pixel %x, %x, %x\n", pixelData[M].blue, pixelData[M].green, pixelData[M].red);
}
fclose(inFileImage);
if(NULL != pBitsData)
{
free(pBitsData);
}
return 0;
}
我想从图像中更改第5个像素(其中之一:蓝色 - >红色,绿色 - >蓝色等) . 你能告诉我我的代码在哪里有错误吗?我怎样才能改变我的代码正常工作?谢谢
编辑:
代替
RGBCOLOR* pixelData = (RGBCOLOR*)(pBitsData + fileHeader.offset);
// M is define with the value 5 - the 5 pixel from image
printf("Pixel %x, %x, %x\n", pixelData[M].blue, pixelData[M].green, pixelData[M].red);
//fseek(inFileImage, fileHeader.offset, SEEK_CUR);
//fread(pixelData, sizeof(RGBCOLOR), 1, inFileImage);
pixelData[M].red = 0x00;
pixelData[M].blue = 0xef;
pixelData[M].green = 0x00;
//memcpy((pBitsData + fileHeader.offset), &pixelData, sizeof(RGBCOLOR)); // <= here seems to be my problem
//fwrite(pixelData, sizeof(RGBCOLOR), 1, inFileImage); // how can i copy to image from a memory
printf("Pixel %x, %x, %x\n", pixelData[M].blue, pixelData[M].green, pixelData[M].red);
如果我写
RGBCOLOR img;
fseek(inFileImage, fileHeader.offset, SEEK_SET);
img.blue = 0x00;
img.green = 0x00;
img.red = 0xff;
fwrite(&img, sizeof(RGBCOLOR), 1, inFileImage);
这将改变第一个像素 . 但我想复制内存,并从那里改变像素 .
1 回答
我使用MinGW,因此您需要更改用于结构对齐的
#pragma
. 这是一个多功能的源头读取图像
更改指定的像素
将修改后的图像输出到新文件
为简洁起见,我没有为任何错误检查而烦恼 . 我用24/32位图像测试了它 . 与32位图像一起使用时,它不会输出有效图像 .
首先,这是前后图像 . 图像本身是2x2像素,为了可见性,我刚刚在这里展示了它 .
Before:
After:
如果仔细观察,可以看到2个图像之间唯一不同的字节是文件中0x3E处的字节 . 我们将红色像素(00 00 FF)更改为紫色像素(FF 00 FF) . 由于图像是自下而上的图像,因此像素数据的前3个字节用于黄色像素,接下来的3个用于蓝色像素,接着是2个字节的填充,然后我们有3个用于红色,3个用于绿色和另外2个填充字节 .
这是进行更改的代码:
编辑:在读取Can someone provide me a specification of 32 bit BMP image format?和https://forums.adobe.com/message/3272950#3272950之后,很明显32位位图正在使用V3标头 - 包含4个长的标头,用于指定4个通道中每个通道的位掩码 . 我随后修改了
saveBitmapFile
和myPixel
例程,并且可以确认代码现在看起来也能正常运行32位位图 .