gpt4 book ai didi

c - 位图颜色 - C

转载 作者:太空宇宙 更新时间:2023-11-04 04:32:21 25 4
gpt4 key购买 nike

我仍然无法访问位图图像的颜色位。问题是,将位图的内容保存到缓冲区后,我不知道:

  1. 从哪里开始循环(如果我从 0 开始,我认为它会清除标题)?

  2. 如何访问字节并进行更改(将 BMP 中的颜色转换为输出中所需的颜色)?

  3. 以及,如何将缓冲区插入到新的位图文件中?

我要修改的所有图像都有可被 4 整除的行(当特定字节填充时我必须插入 0)和每像素 24 位。即使是很少的提示,我们也将不胜感激。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "bmp_header.h"

int main(void)
{
FILE *f;
f = fopen("captcha.bmp","rb");
if ((f = fopen("captcha.bmp", "rb")) == NULL)
{
printf("Error opening file %s.\n", "captcha.bmp");
exit(1);
}
fread(&BMP_header,sizeof(BMP_header),1,f);
fread(&BMP_info_header,sizeof(BMP_info_header),1,f);
fseek(f,BMP_header.imageDataOffset,SEEK_SET);
int rows = (BMP_info_header.bitPix * BMP_info_header.width + 31 ) /32 * 4 ;
char *PixelArray =malloc( rows * abs(BMP_info_header.height)*sizeof(char));
int i;
for( i =sizeof(BMP_header)+sizeof(BMP_info_header); i<=(rows * abs(BMP_info_header.height))-2;i+=3)
{
PixelArray[i]=255; // just a random value to test if this makese any sense
PixelArray[i+1]=255;
PixelArray[i+2]=255;

}

return 0;
}

并且,这是bmp_header.h的内容:

#pragma pack(1)

struct bmp_fileheader
{
unsigned char fileMarker1; /* 'B' */
unsigned char fileMarker2; /* 'M' */
unsigned int bfSize; /* File's size */
unsigned short unused1;
unsigned short unused2;
unsigned int imageDataOffset; /* Offset to the start of image data */
}BMP_header,BMP_header_out;

struct bmp_infoheader
{
unsigned int biSize; /* Size of the info header - 40 bytes */
signed int width; /* Width of the image */
signed int height; /* Height of the image */
unsigned short planes;
unsigned short bitPix;
unsigned int biCompression;
unsigned int biSizeImage; /* Size of the image data */
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
}BMP_info_header,BMP_info_header_out;

#pragma pack()

最佳答案

好吧,我写了一些代码来写出一个完全黑色的位图文件,它具有旧位图文件的原始尺寸。

适用于所有类型的位图。例如,16 色位图在信息头后有一个调色板,我的程序没有考虑到这一点。每像素的位数也需要被 8 整除。如果满足这些先决条件,我相信它们在 24 位位图中,那么这个程序应该可以工作。

这里的主要代码在getNewImageData中。我们使用维基百科使用的相同公式计算图像的行大小 - 它计算所需的位,然后将其填充为四字节的倍数,然后将位转换为字节。然后我们将所有像素阵列内存设置为零(主要是我对在填充字节中保留值感到疑惑)。然后我们沿着每一行运行并编辑每个像素。最里面的 for 循环 对应于每个像素。通过中间 for 循环 的一次迭代写入一个像素。

显然,您可以修改此代码以将像素数据读入分配的内存部分,然后在适当的位置编辑像素数据,然后再将其写回。此示例代码不读取输入像素数据,只是写出与输入文件相同尺寸的黑色位图。

编辑:我想我应该提一下你做错了什么。

  • 您调用了两次 fopen,在内存中某处留下了一个打开的文件指针。
  • rows 应该重命名为 rowSize,因为它是一行像素的大小(以字节为单位)
  • PixelArray 未被释放。
  • 您的for 循环 从一个偏移量(两个 header 的大小)开始,然后以像素数据的大小为界。 for 循环 应该从 0 开始并达到像素数据的大小(除非您在执行此操作时正在读取像素数据......您可能不应该这样做)。
  • 您的 for 循环 尝试一次写入所有像素数据,但没有考虑到每行末尾有 0 到 31 位填充的事实像素(我的程序假定填充仅为 0、8、16 或 24 位)。

代码如下:

#include <stdio.h>
#include "bmp_header.h"
#include <stdlib.h>

int readBitmapHeaders(char* fileLocation, bmp_fileheader* fileheader, bmp_infoheader* infoheader)
{
FILE* f;
f = fopen(fileLocation, "rb");

if (!f)
{
printf("Error opening file %s.\n", fileLocation);
return 1;
}

fread(fileheader, sizeof(bmp_fileheader), 1, f);
fread(infoheader, sizeof(bmp_infoheader), 1, f);

fclose(f);
return 0;
}

int writeBitmap(char* fileName, bmp_fileheader* fileheader, bmp_infoheader* infoheader, char* pixelArray, size_t pixelArraySize)
{
FILE* out;
out = fopen(fileName, "wb");
if (!out)
{
printf("Error opening file %s.\n", fileName);
return 1;
}

fwrite(fileheader, sizeof(bmp_fileheader), 1, out);
fwrite(infoheader, sizeof(bmp_infoheader), 1, out);
fwrite(pixelArray, pixelArraySize, 1, out);

fclose(out);
return 0;
}

char* getNewImageData(bmp_infoheader* infoheader, size_t* imageSize)
{
//rowsize is padded to 4 bytes
size_t rowSize = (infoheader->bitPix * infoheader->width + 31) / 32 * 4;

size_t pixelArraySize = rowSize * abs(infoheader->height);

char* pixelArray = (char*)malloc(pixelArraySize);
if (!pixelArray)
{
return NULL;
}

memset(pixelArray, 0, pixelArraySize);

size_t bytesPerPixel = infoheader->bitPix / 8;
for (int i = 0; i < infoheader->height; i++)
{
for (int j = 0; j < infoheader->width; j++)
{
size_t offset = rowSize * i + bytesPerPixel * j;
for (size_t k = 0; k < bytesPerPixel; k++)
{
pixelArray[offset + k] = 0;
}
}
}

if (imageSize)
{
*imageSize = pixelArraySize;
}
return pixelArray;
}

int main()
{
char* fileLocation = "test.bmp";
bmp_fileheader header;
bmp_infoheader infoheader;

int readResult = readBitmapHeaders(fileLocation, &header, &infoheader);
if (readResult)
{
return readResult;
}

size_t pixelArraySize;
char* pixelArray = getNewImageData(&infoheader, &pixelArraySize);
if (!pixelArray)
{
printf("%s", "Failed to create the new image data. Exiting with fatal error.\n");
return 1;
}

char* outFile = "out.bmp";
int writeResult = writeBitmap(outFile, &header, &infoheader, pixelArray, pixelArraySize);

free(pixelArray);
return writeResult;
}

我稍微更改了位图头文件以对结构进行 typedef 并使生活更轻松(至少对我而言):

#pragma once
#pragma pack(1)

typedef struct _bmp_fileheader
{
unsigned char fileMarker1; /* 'B' */
unsigned char fileMarker2; /* 'M' */
unsigned int bfSize; /* File's size */
unsigned short unused1;
unsigned short unused2;
unsigned int imageDataOffset; /* Offset to the start of image data */
} bmp_fileheader;

typedef struct _bmp_infoheader
{
unsigned int biSize; /* Size of the info header - 40 bytes */
signed int width; /* Width of the image */
signed int height; /* Height of the image */
unsigned short planes;
unsigned short bitPix;
unsigned int biCompression;
unsigned int biSizeImage; /* Size of the image data */
int biXPelsPerMeter;
int biYPelsPerMeter;
unsigned int biClrUsed;
unsigned int biClrImportant;
} bmp_infoheader;

#pragma pack()

关于c - 位图颜色 - C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34465329/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com