有什么不对这个code从图像RGB BMP纯C写的灰度BMP - Windows操作系统 [英] What is wrong with this code for writing grey-scale bmp from an image RGB bmp pure C - Windows OS

查看:121
本文介绍了有什么不对这个code从图像RGB BMP纯C写的灰度BMP - Windows操作系统的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的功能,我使用根据维基百科BITMAPINFOHEADER BMP头。但是,我越来越没有任何图像文件...把填充时,该进程将停止。

  //结构的头信息
 的#pragma包(推,1)
 / * Windows 3.X的位图文件头* /
 typedef结构{
      字符文件类型[2]; / *魔术 - 总是'B''M'* /
      unsigned int类型文件大小;
      短保留1;
      短RESERVED2;
      无符号整型dataoffset; / *以字节为单位实际的位图数据偏移* /
  } file_header;  / * Windows 3.X的位图完整标题,包括文件头* /
 typedef结构{
      file_header FileHeader里;
      无符号整型headersize;
      INT宽度;
      INT高度;
      短面;
      短bitsperpixel; / *我们仅支持24值这里* /
      unsigned int类型的COM pression; / *我们不支持COM pression * /
      无符号整型bitmapsize;
      INT horizo​​ntalres;
      INT verticalres;
      无符号整型numcolors;
      无符号整型importantcolors;
  } bitmap_header;
  的#pragma包(POP)
INT RGB2GREY(字符*输入,字符* greyImage){  //变量声明:
  FILE * FP,*灰色;
  bitmap_header *马力;
  INT N;
  字符*的数据;
  INT oldBitsperpixel;  //打开输入文件:
  FP = FOPEN(输入,RB);
  如果(FP == NULL){
     //清理
  }  //读取输入的文件头:
  HP =(bitmap_header *)malloc的(的sizeof(bitmap_header));
  如果(HP == NULL)
      返回3;  N = FREAD(HP,sizeof的(bitmap_header),1,FP);
  如果(N。1){
     //清理
  }  //读取图像的数据:
  数据=(字符*)malloc的(的sizeof(char)的* HP-> bitmapsize);
  如果(数据== NULL){
      //清理
  }
  //把我头后的位置...
  fseek的(FP,sizeof的(字符)* HP-> fileheader.dataoffset,SEEK_SET);
  的printf(%宽度D和高度%d个\\ N,HP->宽度,HP->高度);  INT I,J;
  unsigned char型BGR [3];
  无符号colorIntensity [3];
  / * unsigned char型bmppad [HP-GT&;宽度] = {0}; * /  的printf(新bitmapSize%d个\\ n \\ n,HP-> bitsperpixel);  //打开greayImage文件:
  灰色= FOPEN(greyImage,WB);
  如果(灰色== NULL){
    //清理
  }
  //写头
  N = FWRITE(HP,sizeof的(炭)的sizeof(bitmap_header),灰色);
  如果(N。1){
      //清理
  }
  //再次去头后位置
  fseek的(出,的sizeof(字符)* HP-> fileheader.dataoffset,SEEK_SET);
  对于(i = 0; I< HP-GT&;高度;我++){
    为(J = 0; J< HP-GT&;宽度; J ++){
        //读取像素的像素
        FREAD(BGR,3,1,FP); // 1 3个位置的无符号的字符
        unsigned char型colorGrey;
        colorGrey =(无符号字符)0.3 * BGR [2] + 0.6 * BGR [1] + 0.1 * BGR [0];
        colorIntensity [2] = colorGrey;
        colorIntensity [1] = colorGrey;
        colorIntensity [0] = colorGrey;
        / *的printf(B%d个摹%d个R%了D,BGR [0],BGR [1],BGR [2]);
        的printf(灰%D,colorIntensity); * /
        FWRITE(colorIntensity,3,1,灰色);
    }
    / *
    //添加垫选项1
    // FWRITE(bmppad,sizeof的(bmppad),1,灰色);
    //添加垫选项2
    为(J = 0; J> HP-GT&;宽度; J ++){
        的fwrite(0,1,1,灰色);
    } * /
}
FCLOSE(FP);
FCLOSE(灰色);
免费(马力);
免费的(数据);
返回0;

}

在灰色的输出文件,我什么也得不到......而且,我不知道是否有从24到8位减少的一种方式。

PS。我的code来自读/在C

该公式由创建灰度BMP从RGB BMP

谢谢,


解决方案

您实际上把一个32位的色位为32位灰度位图通过改变方式的颜色值,它们显示为灰色(你是不是保存用这种方式的任何空间;将位图保持为大,因为它是)。 Anayway,这解释了为什么你并不需要去适应位图头。

但是,当你阅读每三个字节,并改变每三个字节,你不把扫描线考虑在内。

映像由扫描线和像素的扫描线consits。扫描线被神韵上连字边界上,所以一个扫描线的最后几个字节是未使用的(以及扫描线因此比其上的所有的像素的位长)。

要正确处理输入和创建输出,你的循环必须是:

(编辑:更新时使用的每像素输出1个字节):

 的#pragma包(推,1)
typedef结构{
    unsigned char型rgbBlue;
    unsigned char型rgbGreen;
    unsigned char型rgbRed;
    unsigned char型rgbReserved;
} pal_entry;
的#pragma包(POP)INT ToGreyScale(FILE * FP,FILE *灰色,bitmap_header *马力)
{
    INT I,J;
    INT iScanlineSizeIn =((HP-GT&;宽* HP-GT&; bitsperpixel)+ 31)/ 32 * 4;
    INT iScanlineSizeOut =((HP-GT&;宽* 8)+ 31)/ 32 * 4;
    无符号字符* scanlineIn =的malloc(iScanlineSizeIn),* PIN;
    无符号字符* scanlineOut =的malloc(iScanlineSizeOut),*噘嘴;
    pal_entry PAL [256];    对于(i = 0; I< 256;我++)//创建一个灰度调色板
        {PAL [I] .rgbBlue = I; PAL [I] .rgbGreen = I; PAL [I] .rgbRed = I;}    HP-> bitsperpixel = 8; //设置输出位每像素
    HP-GT&; fileheader.filesize = sizeof的(bitmap_header)+的sizeof(PAL)+ HP-GT&;宽* iScanlineSizeOut;    FWRITE(HP,sizeof的(bitmap_header),1,灰色); //写头...
    FWRITE(PAL,256 * sizeof的(pal_entry),1,灰色);通过调色板//..followed    对于(i = 0; I< HP-GT&;高度;我++)
    {
        如果(!的fread(scanlineIn,iScanlineSizeIn,1,FP)= 1)返回(0);
        PIN = scanlineIn;
        噘嘴= scanlineOut;
        为(J = 0; J< HP-GT&;宽度; J ++)
        {
            *噘++ =(unsigned char型)((0.1 * PIN ++)+(0.6 * PIN ++)+(0.3 * PIN ++));
        }
        FWRITE(scanlineOut,iScanlineSizeOut,1,灰色);
    }
    免费(scanlineIn);
    免费(scanlineOut);
    返回(1);
}

This is my function, I am using the headers BMP according to wikipedia BITMAPINFOHEADER. But, I am getting a file without any image...when putting padding, the process stops.

 // Structures for header info
 #pragma pack(push,1)
 /* Windows 3.x bitmap file header */
 typedef struct {
      char         filetype[2];   /* magic - always 'B' 'M' */
      unsigned int filesize;
      short        reserved1;
      short        reserved2;
      unsigned int dataoffset;    /* offset in bytes to actual bitmap data */
  } file_header;

  /* Windows 3.x bitmap full header, including file header */
 typedef struct {
      file_header  fileheader;
      unsigned int headersize;
      int          width;
      int          height;
      short        planes;
      short        bitsperpixel;  /* we only support the value 24 here */
      unsigned int compression;   /* we do not support compression */
      unsigned int bitmapsize;
      int          horizontalres;
      int          verticalres;
      unsigned int numcolors;
      unsigned int importantcolors;
  } bitmap_header;
  #pragma pack(pop)


int RGB2GREY(char* input, char *greyImage) {

  //variable declaration:
  FILE *fp, *grey;
  bitmap_header* hp;
  int n;
  char *data;
  int oldBitsperpixel;

  //Open input file:
  fp = fopen(input, "rb");
  if(fp==NULL){
     //cleanup
  }

  //Read the input file headers:
  hp=(bitmap_header*)malloc(sizeof(bitmap_header));
  if(hp==NULL)
      return 3;

  n=fread(hp, sizeof(bitmap_header), 1, fp);
  if(n<1){
     //cleanup
  }

  //Read the data of the image:
  data = (char*)malloc(sizeof(char)*hp->bitmapsize);
  if(data==NULL){
      //cleanup
  }
  //Put me in the position after header...
  fseek(fp,sizeof(char)*hp->fileheader.dataoffset,SEEK_SET);
  printf("Width %d and Height %d\n",hp->width,hp->height);

  int i, j;
  unsigned char BGR[3];
  unsigned colorIntensity[3];
  /*unsigned char bmppad[hp->width] = {0};*/

  printf("New bitmapSize %d\n\n",hp->bitsperpixel);

  //Open greayImage file:
  grey = fopen(greyImage, "wb");
  if(grey==NULL){
    //cleanup
  }
  //Writes the header
  n=fwrite(hp,sizeof(char),sizeof(bitmap_header),grey);
  if(n<1){
      //cleanup
  }
  //Again going to position after header
  fseek(out,sizeof(char)*hp->fileheader.dataoffset,SEEK_SET);
  for (i=0; i<hp->height; i++){
    for (j=0; j<hp->width; j++){
        //Reading pixel by pixel  
        fread(BGR, 3, 1, fp); //1 unsigned char of 3 positions
        unsigned char colorGrey;
        colorGrey = (unsigned char) 0.3*BGR[2] + 0.6*BGR[1]  + 0.1*BGR[0];
        colorIntensity[2] = colorGrey;
        colorIntensity[1] = colorGrey;
        colorIntensity[0] = colorGrey;
        /*printf("B %d G %d R %d ",BGR[0],BGR[1],BGR[2]);
        printf("Gray %d ",colorIntensity);*/
        fwrite(colorIntensity, 3, 1, grey);
    }
    /*
    // Adding pad option1 
    //fwrite(bmppad, sizeof(bmppad), 1, grey); 
    //Adding pad option2
    for (j=0; j>hp->width; j++){
        fwrite(0, 1, 1, grey);
    }*/
}
fclose(fp);
fclose(grey);
free(hp);
free(data);
return 0;

}

In the grey output file, I get nothing...moreover, I wonder if there is a way to reduce from 24 to 8 bits.

ps. My code came from reading/writing bmp files in c

The formula came from Create greyscale BMP from RGB BMP

Thanks,

解决方案

You are essentially turning a 32-bit color bitmap into a 32-bit grey bitmap by changing the color values in a way that they appear grey (you are not saving any space in this way; the bitmap stays as large as it was). Anayway, it explains why you do not need to adapt the bitmap header.

But when you read every three bytes and change every three bytes, you do not take scanlines into account.

An image consists of scanlines and a scanline consits of pixels. Scanlines are alligned on even word boundaries so the last few bytes of a scanline are unused (and the scanline is thus a bit longer than all the pixels on it).

To properly process the input and create the output, your loop must be:

(EDIT: updated to use 1 byte per pixel output):

#pragma pack(push,1)
typedef struct {
    unsigned char rgbBlue;
    unsigned char rgbGreen;
    unsigned char rgbRed;
    unsigned char rgbReserved;
} pal_entry;    
#pragma pack(pop)

int ToGreyScale(FILE *fp, FILE *grey, bitmap_header *hp)
{
    int i, j;
    int iScanlineSizeIn = ((hp->width * hp->bitsperpixel) + 31) / 32 * 4;
    int iScanlineSizeOut= ((hp->width *        8        ) + 31) / 32 * 4;
    unsigned char *scanlineIn = malloc(iScanlineSizeIn), *pIn;
    unsigned char *scanlineOut= malloc(iScanlineSizeOut), *pOut;
    pal_entry pal[256];

    for (i=0; i<256; i++)   // create a gray scale palette
        {pal[i].rgbBlue= i; pal[i].rgbGreen= i; pal[i].rgbRed= i;}

    hp->bitsperpixel= 8;    // set output bits-per-pixel
    hp->fileheader.filesize= sizeof(bitmap_header) + sizeof(pal) + hp->width*iScanlineSizeOut;

    fwrite(hp, sizeof(bitmap_header), 1, grey);     // write the header...
    fwrite(pal, 256*sizeof(pal_entry), 1, grey);    //..followed by palette

    for (i=0; i<hp->height; i++)
    {
        if (fread(scanlineIn, iScanlineSizeIn, 1, fp) != 1) return(0);
        pIn = scanlineIn;
        pOut= scanlineOut;
        for (j=0; j<hp->width; j++)
        {
            *pOut++ = (unsigned char) ((0.1 * *pIn++) + (0.6 * *pIn++) + (0.3 * *pIn++));
        }
        fwrite(scanlineOut, iScanlineSizeOut, 1, grey);
    }
    free(scanlineIn);
    free(scanlineOut);
    return(1);
}   

这篇关于有什么不对这个code从图像RGB BMP纯C写的灰度BMP - Windows操作系统的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆