BMP文件过滤器像素调整 / C语言
我目前正在研究一个正在过滤BMP文件的项目。 该平滑过滤器使用3x3模糊的内核,该内核是固定尺寸的小矩阵。 卷积操作将此内核移到图像上,一次将其移动在像素上,并将矩阵元素的点产物带有下面的像素值。基本上,此滤波器遍历整个图像,从而产生9个相邻像素的单个像素。
为了水平和垂直保持图像大小,通过在图像边缘周围添加0个值的像素,将填充物添加到输入图像中。
相关图像可以在链接上看到:
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
typedef struct{
uint8_t red;
uint8_t green;
uint8_t blue;
}rgb ;
void smoothing_filter(int height, int width, rgb **image, rgb **dest);
int main() {
FILE *inputPtr;
if ((inputPtr = fopen("starry_night.bmp", "rb+")) == NULL) {
printf("The input file could not be opened\n");
} else {
BITMAPFILEHEADER fileheader_input;
fread(&fileheader_input, sizeof(BITMAPFILEHEADER), 1, inputPtr);
BITMAPINFOHEADER infoheader_input;
fread(&infoheader_input, sizeof(BITMAPINFOHEADER), 1, inputPtr);
if (fileheader_input.bfType != 0x4d42 || fileheader_input.bfOffBits != 54 ||
infoheader_input.biSize != 40 || infoheader_input.biBitCount != 24 || infoheader_input.biCompression != 0) {
fclose(inputPtr);
printf("Unsupported input file.\n");
} else {
int height = abs(infoheader_input.biHeight);
int width = infoheader_input.biWidth;
rgb **rgb_array;
rgb_array = calloc(height, sizeof(rgb *));
for (int row = 0; row < height; ++row) {
rgb_array[row] = calloc(width, sizeof(rgb));
}
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; ++col) {
fread(&rgb_array[row][col], sizeof(rgb), 1, inputPtr);
}
}
infoheader_input.biWidth = width + 2;
infoheader_input.biHeight = height + 2;
fileheader_input.bfSize = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) +
3 * abs(infoheader_input.biWidth) * abs(infoheader_input.biHeight);
rewind(inputPtr);
fwrite(&(fileheader_input), sizeof(BITMAPFILEHEADER), 1, inputPtr);
fwrite(&(infoheader_input), sizeof(BITMAPINFOHEADER), 1, inputPtr);
rgb blanckRgb = {0, 0, 0};
for (int i = 0; i < (width + 2); ++i) {
fwrite(&blanckRgb, sizeof(rgb), 1, inputPtr);
}
for (int row = 0; row < height; ++row) {
fwrite(&blanckRgb, sizeof(rgb), 1, inputPtr);
for (int col = 0; col < width; ++col) {
fwrite(&rgb_array[row][col].red, 1, 1, inputPtr);
fwrite(&rgb_array[row][col].green, 1, 1, inputPtr);
fwrite(&rgb_array[row][col].blue, 1, 1, inputPtr);
}
fwrite(&blanckRgb, sizeof(rgb), 1, inputPtr);
}
for (int i = 0; i < (width + 2); ++i) {
fwrite(&blanckRgb, sizeof(rgb), 1, inputPtr);
}
FILE *outputPtr;
if ((outputPtr = fopen("starry_night_filtered.bmp", "wb")) == NULL) {
printf("The \"starry_night_filtered.bmp\" file could not be created\n");
}else{
BITMAPFILEHEADER fileheader_output = fileheader_input;
BITMAPINFOHEADER infoheader_output = infoheader_input;
infoheader_output.biWidth = width;
infoheader_output.biHeight = height;
fileheader_output.bfSize = sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER)+3*abs(width*height);
fwrite(&(fileheader_output), sizeof(BITMAPFILEHEADER), 1, outputPtr);
fwrite(&(infoheader_output), sizeof(BITMAPINFOHEADER), 1, outputPtr);
rgb **image;
image = calloc(infoheader_input.biHeight, sizeof(rgb *));
for (int row = 0; row < infoheader_input.biHeight; ++row) {
image[row] = calloc(infoheader_input.biWidth, sizeof(rgb));
}
rewind(inputPtr);
for (int row = 0; row < infoheader_input.biHeight; row++) {
for (int col = 0; col < infoheader_input.biWidth; col++) {
fread(&image[row][col], sizeof(rgb), 1, inputPtr);
}
}
rgb **dest;
dest = calloc(height, sizeof(rgb *));
for (int row = 0; row < height; ++row) {
dest[row] = calloc(width, sizeof(rgb));
}
smoothing_filter(infoheader_input.biHeight, infoheader_input.biWidth, image, dest);
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
fwrite(&dest[row][col], sizeof(rgb), 1, outputPtr);
}
}
free(image);
free(rgb_array);
fclose(outputPtr);
fclose(inputPtr);
}
}
}
}
void smoothing_filter(int height, int width, rgb **image, rgb **dest)
{
double redVal, blueVal, greenVal;
// Iterate through rows
for (int row = 0; row < (height-2); row++)
{
// Iterate through columns
for (int col = 0; col < (width-2); col++)
{
// Obtain RGB values of current image pixel
redVal = (0.0625*image[row][col].red) + (0.125*image[row][col+1].red) + (0.0625*image[row][col+2].red)
+(0.125*image[row+1][col].red) + (0.25*image[row+1][col+1].red) + (0.125*image[row+1][col+2].red)
+(0.0625*image[row+2][col].red) + (0.125*image[row+2][col+1].red) + (0.0625*image[row+2][col+2].red);
greenVal = (0.0625*image[row][col].green) + (0.125*image[row][col+1].green) + (0.0625*image[row][col+2].green)
+(0.125*image[row+1][col].green) + (0.25*image[row+1][col+1].green) + (0.125*image[row+1][col+2].green)
+(0.0625*image[row+2][col].green) + (0.125*image[row+2][col+1].green) + (0.0625*image[row+2][col+2].green);
blueVal = (0.0625*image[row][col].blue) + (0.125*image[row][col+1].blue) + (0.0625*image[row][col+2].blue)
+(0.125*image[row+1][col].blue) + (0.25*image[row+1][col+1].blue) + (0.125*image[row+1][col+2].blue)
+(0.0625*image[row+2][col].blue) + (0.125*image[row+2][col+1].blue) + (0.0625*image[row+2][col+2].blue);
dest[row][col].red = (int) redVal;
dest[row][col].green = (int) greenVal;
dest[row][col].blue = (int) blueVal;
}
}
}
问题:
我的代码正常运行,除了以某种方式将图像向右移动。 我找不到原因。你能帮我吗? 提前致谢 我的代码的输出:
I am currently working on a project which is filtering a bmp file.
This smoothing filter uses a 3x3 blurring kernel which is a fixed size small matrix.
The convolution operation moves this kernel over the image, shifting it on pixel at a time and takes the dot product of matrix elements with the pixel values underneath. Basically this filter traverses the entire image to producing a single pixel out of 9 adjacent pixels.
In order to preserve the image size both horizontally and vertically, padding is added to the input image by adding 0 valued pixels around the edges of the image.
Related images can be seen on the links:
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include "header.h"
typedef struct{
uint8_t red;
uint8_t green;
uint8_t blue;
}rgb ;
void smoothing_filter(int height, int width, rgb **image, rgb **dest);
int main() {
FILE *inputPtr;
if ((inputPtr = fopen("starry_night.bmp", "rb+")) == NULL) {
printf("The input file could not be opened\n");
} else {
BITMAPFILEHEADER fileheader_input;
fread(&fileheader_input, sizeof(BITMAPFILEHEADER), 1, inputPtr);
BITMAPINFOHEADER infoheader_input;
fread(&infoheader_input, sizeof(BITMAPINFOHEADER), 1, inputPtr);
if (fileheader_input.bfType != 0x4d42 || fileheader_input.bfOffBits != 54 ||
infoheader_input.biSize != 40 || infoheader_input.biBitCount != 24 || infoheader_input.biCompression != 0) {
fclose(inputPtr);
printf("Unsupported input file.\n");
} else {
int height = abs(infoheader_input.biHeight);
int width = infoheader_input.biWidth;
rgb **rgb_array;
rgb_array = calloc(height, sizeof(rgb *));
for (int row = 0; row < height; ++row) {
rgb_array[row] = calloc(width, sizeof(rgb));
}
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; ++col) {
fread(&rgb_array[row][col], sizeof(rgb), 1, inputPtr);
}
}
infoheader_input.biWidth = width + 2;
infoheader_input.biHeight = height + 2;
fileheader_input.bfSize = sizeof(BITMAPINFOHEADER) + sizeof(BITMAPFILEHEADER) +
3 * abs(infoheader_input.biWidth) * abs(infoheader_input.biHeight);
rewind(inputPtr);
fwrite(&(fileheader_input), sizeof(BITMAPFILEHEADER), 1, inputPtr);
fwrite(&(infoheader_input), sizeof(BITMAPINFOHEADER), 1, inputPtr);
rgb blanckRgb = {0, 0, 0};
for (int i = 0; i < (width + 2); ++i) {
fwrite(&blanckRgb, sizeof(rgb), 1, inputPtr);
}
for (int row = 0; row < height; ++row) {
fwrite(&blanckRgb, sizeof(rgb), 1, inputPtr);
for (int col = 0; col < width; ++col) {
fwrite(&rgb_array[row][col].red, 1, 1, inputPtr);
fwrite(&rgb_array[row][col].green, 1, 1, inputPtr);
fwrite(&rgb_array[row][col].blue, 1, 1, inputPtr);
}
fwrite(&blanckRgb, sizeof(rgb), 1, inputPtr);
}
for (int i = 0; i < (width + 2); ++i) {
fwrite(&blanckRgb, sizeof(rgb), 1, inputPtr);
}
FILE *outputPtr;
if ((outputPtr = fopen("starry_night_filtered.bmp", "wb")) == NULL) {
printf("The \"starry_night_filtered.bmp\" file could not be created\n");
}else{
BITMAPFILEHEADER fileheader_output = fileheader_input;
BITMAPINFOHEADER infoheader_output = infoheader_input;
infoheader_output.biWidth = width;
infoheader_output.biHeight = height;
fileheader_output.bfSize = sizeof(BITMAPINFOHEADER)+sizeof(BITMAPFILEHEADER)+3*abs(width*height);
fwrite(&(fileheader_output), sizeof(BITMAPFILEHEADER), 1, outputPtr);
fwrite(&(infoheader_output), sizeof(BITMAPINFOHEADER), 1, outputPtr);
rgb **image;
image = calloc(infoheader_input.biHeight, sizeof(rgb *));
for (int row = 0; row < infoheader_input.biHeight; ++row) {
image[row] = calloc(infoheader_input.biWidth, sizeof(rgb));
}
rewind(inputPtr);
for (int row = 0; row < infoheader_input.biHeight; row++) {
for (int col = 0; col < infoheader_input.biWidth; col++) {
fread(&image[row][col], sizeof(rgb), 1, inputPtr);
}
}
rgb **dest;
dest = calloc(height, sizeof(rgb *));
for (int row = 0; row < height; ++row) {
dest[row] = calloc(width, sizeof(rgb));
}
smoothing_filter(infoheader_input.biHeight, infoheader_input.biWidth, image, dest);
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
fwrite(&dest[row][col], sizeof(rgb), 1, outputPtr);
}
}
free(image);
free(rgb_array);
fclose(outputPtr);
fclose(inputPtr);
}
}
}
}
void smoothing_filter(int height, int width, rgb **image, rgb **dest)
{
double redVal, blueVal, greenVal;
// Iterate through rows
for (int row = 0; row < (height-2); row++)
{
// Iterate through columns
for (int col = 0; col < (width-2); col++)
{
// Obtain RGB values of current image pixel
redVal = (0.0625*image[row][col].red) + (0.125*image[row][col+1].red) + (0.0625*image[row][col+2].red)
+(0.125*image[row+1][col].red) + (0.25*image[row+1][col+1].red) + (0.125*image[row+1][col+2].red)
+(0.0625*image[row+2][col].red) + (0.125*image[row+2][col+1].red) + (0.0625*image[row+2][col+2].red);
greenVal = (0.0625*image[row][col].green) + (0.125*image[row][col+1].green) + (0.0625*image[row][col+2].green)
+(0.125*image[row+1][col].green) + (0.25*image[row+1][col+1].green) + (0.125*image[row+1][col+2].green)
+(0.0625*image[row+2][col].green) + (0.125*image[row+2][col+1].green) + (0.0625*image[row+2][col+2].green);
blueVal = (0.0625*image[row][col].blue) + (0.125*image[row][col+1].blue) + (0.0625*image[row][col+2].blue)
+(0.125*image[row+1][col].blue) + (0.25*image[row+1][col+1].blue) + (0.125*image[row+1][col+2].blue)
+(0.0625*image[row+2][col].blue) + (0.125*image[row+2][col+1].blue) + (0.0625*image[row+2][col+2].blue);
dest[row][col].red = (int) redVal;
dest[row][col].green = (int) greenVal;
dest[row][col].blue = (int) blueVal;
}
}
}
THE PROBLEM:
My code works okay except somehow it shifts an image a little bit to the right.
I could not find the reason of it. Can you help me about that.
Thanks in advance
Output of my codes:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这可能不是出现问题的原因,但是由于几个原因,此代码是有问题的:
malloc
使代码不必要地出于没有充分的理由而慢,因为您打算立即覆盖内存而且您没有Calloc
的零初始化的好处。fread(&amp; rgb_array [row] [col],sizeof(rgb),1,inputptr);
没有充分的理由,因为您一次读取一个项目。文件I/O通常是瓶颈,因此应将其最小化。如果使用了2D数组,则可以一口气读取文件。calloc
和fread
的结果。而是考虑这样的东西:
您需要相应地更改功能,让它们接受2D数组:
This might not be the cause of the problem, but this code is problematic for several reasons:
calloc
instead ofmalloc
makes the code needlessly slow for no good reason, since you intend to immediately overwrite the memory anyway and you have no benefit ofcalloc
's zero initialization.fread(&rgb_array[row][col], sizeof(rgb), 1, inputPtr);
is very slow for no good reason, since you read one single item at a time. File I/O is usually a bottleneck so it should be minimized. If you used 2D arrays you could read the file in one go.calloc
andfread
.Consider something like this instead:
You'll need to change your functions accordingly, to have them accept 2D arrays instead: