简体   繁体   English

在裸C中将RGB转换为灰度

[英]Convert RGB to Grayscale in bare C

I am applying a basic tutorial on image processing in C and I am having problems with this program to convert RGB into grayscale but the output pic is somehow corrupted and although the code runs with no errors, and I cant put my hands on the problem. 我在C中应用了一个关于图像处理的基础教程,我在使用这个程序将RGB转换为灰度时遇到了问题,但是输出pic有点损坏,尽管代码运行没有错误,我无法解决问题。 The code is below. 代码如下。

FILE *fIn = fopen("tiger.bmp","rb");                    //Input File name
FILE *fOut = fopen("tiger_gray.bmp","wb");              //Output File name

int i,j,y;
unsigned char byte[54];

if(fIn==NULL)   
{
    printf("File does not exist.\n");
}

for(i=0;i<54;i++)               //read the 54 byte header from fIn
{
    byte[i] = getc(fIn);
}

fwrite(byte,sizeof(unsigned char),54,fOut);         //write the header back
// extract image height, width and bit Depth from image Header
int height = *(int*)&byte[18];
int width = *(int*)&byte[22];
int bitDepth = *(int*)&byte[28];

printf("width: %d\n",width);
printf("height: %d\n",height );

int size = height*width;                        

unsigned char buffer[size][3];              //to store the image data


for(i=0;i<size;i++)                                         //RGB to gray
{
    y=0;
    buffer[i][2]=getc(fIn);                                 //blue
    buffer[i][1]=getc(fIn);                                 //green
    buffer[i][0]=getc(fIn);                                 //red

    y=(buffer[i][0]*0.3) + (buffer[i][1]*0.59)  + (buffer[i][2]*0.11);          //conversion formula of rgb to gray

    putc(y,fOut);
    putc(y,fOut);
    putc(y,fOut);
}

fclose(fOut);
fclose(fIn);

There were two major problems in your code. 您的代码中存在两个主要问题。

  1. You had the width and height reversed. 你的宽度和高度都反转了。
  2. You were not accounting for the required padding at the end of every row to make it a multiple of 4 bytes. 您没有考虑每行末尾所需的填充,以使其成为4个字节的倍数。

You were also allocating a large buffer that you did not need based on how the rest of the code was written. 您还根据其余代码的编写方式分配了一个您不需要的大缓冲区。 Generally I'd prefer to read/process either one full row at a time or even the full image at once, but to do that you want to use malloc or calloc because the data may be larger than the available stack. 一般来说,我更喜欢一次读取/处理一个完整的行,或者甚至一次读取整个图像,但是为了做到这一点,你想使用malloc或calloc,因为数据可能比可用的堆栈大。 In this case, to keep things simple, I just process one pixel at a time. 在这种情况下,为了简单起见,我一次只处理一个像素。

I also got rid of getc/putc because I prefer fread/fwrite and you're never really dealing with 1 byte at a time. 我也摆脱了getc / putc,因为我更喜欢fread / fwrite而且你从来没有真正处理过1个字节。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    FILE *fIn = fopen("tiger.bmp", "rb");
    FILE *fOut = fopen("tiger_gray.bmp", "wb");
    if (!fIn || !fOut)
    {
        printf("File error.\n");
        return 0;
    }

    unsigned char header[54];
    fread(header, sizeof(unsigned char), 54, fIn);
    fwrite(header, sizeof(unsigned char), 54, fOut);

    int width = *(int*)&header[18];
    int height = abs(*(int*)&header[22]);
    int stride = (width * 3 + 3) & ~3;
    int padding = stride - width * 3;

    printf("width: %d (%d)\n", width, width * 3);
    printf("height: %d\n", height);
    printf("stride: %d\n", stride);
    printf("padding: %d\n", padding);

    unsigned char pixel[3];
    for (int y = 0; y < height; ++y)
    {
        for (int x = 0; x < width; ++x)
        {
            fread(pixel, 3, 1, fIn);
            unsigned char gray = pixel[0] * 0.3 + pixel[1] * 0.58 + pixel[2] * 0.11;
            memset(pixel, gray, sizeof(pixel));
            fwrite(&pixel, 3, 1, fOut);
        }
        fread(pixel, padding, 1, fIn);
        fwrite(pixel, padding, 1, fOut);
    }
    fclose(fOut);
    fclose(fIn);
    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM