【问题标题】:creating a bitmap image from existing bitmap, in C在 C 中从现有位图创建位图图像
【发布时间】:2012-01-05 03:37:57
【问题描述】:

我正在编写一个 C 程序,它将从位图图像中检索信息(标题信息、像素信息),并使用该信息创建另一个位图图像(新图像显然与原始图像相同)。

问题在于,在某些情况下,额外的字节会(自行)添加到新图像中,从而导致图像形成不正确。
在另一种情况下,由于图像形成本身失败,新图像中缺少一些字节。 (在写入像素信息时会发生这种情况。位图标题信息会正确写入新文件。)
我已经调试了代码,但我找不到是什么原因造成的。 如果有人能告诉我错误是什么,我会很高兴。

//creating a bitmap file
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<math.h>

long extract(FILE *,long ,int );

long extract(FILE *fp1,long offset,int size)
{
        unsigned char *ptr;
    unsigned char temp='0';
    long value=0L;
    int i;

    //to initialize the ptr
    ptr=&temp;

    //sets the file pointer at specific position i.e. after the offset
    fseek(fp1,offset,SEEK_SET);

    //now fgetcing (size) values starting from the offset
    for(i=1;i<=size;i++)
    {
        fread(ptr,sizeof(char),1,fp1);
        value=(long)(value+(*ptr)*(pow(256,(i-1))));   //combining the values   one after another in a single variable
    }

    return value;
}

int main()
{
    int row,col;
    int i,j,k;
    int dataoffset,offset;
    char magicnum[2];
    FILE *fp1,*fp4;
    clrscr();

    if((fp1=fopen("stripes.bmp","rb"))==NULL)
    {
        printf("\a\nCant open the image.\nSystem is exiting.");
        exit(0);
    }

    if((fp4=fopen("op.bmp","a"))==NULL)
    {
        printf("\n\aError while creating a file.\nSystem is exiting ..... ");
        exit(0);
    }

    fputc((int)extract(fp1,0L,1),fp4);
    fputc((int)extract(fp1,1L,1),fp4);
    fputc((int)extract(fp1,2L,1),fp4);
    fputc((int)extract(fp1,3L,1),fp4);
    fputc((int)extract(fp1,4L,1),fp4);
    fputc((int)extract(fp1,5L,1),fp4);
    fputc((int)extract(fp1,6L,1),fp4);
    fputc((int)extract(fp1,7L,1),fp4);
    fputc((int)extract(fp1,8L,1),fp4);
    fputc((int)extract(fp1,9L,1),fp4);
    fputc((int)extract(fp1,10L,1),fp4);
    fputc((int)extract(fp1,11L,1),fp4);
    fputc((int)extract(fp1,12L,1),fp4);
    fputc((int)extract(fp1,13L,1),fp4);
    fputc((int)extract(fp1,14L,1),fp4);
    fputc((int)extract(fp1,15L,1),fp4);
    fputc((int)extract(fp1,16L,1),fp4);
    fputc((int)extract(fp1,17L,1),fp4);
    fputc((int)extract(fp1,18L,1),fp4);
    fputc((int)extract(fp1,19L,1),fp4);
    fputc((int)extract(fp1,20L,1),fp4);
    fputc((int)extract(fp1,21L,1),fp4);
    fputc((int)extract(fp1,22L,1),fp4);
    fputc((int)extract(fp1,23L,1),fp4);
    fputc((int)extract(fp1,24L,1),fp4);
    fputc((int)extract(fp1,25L,1),fp4);
    fputc((int)extract(fp1,26L,1),fp4);
    fputc((int)extract(fp1,27L,1),fp4);
    fputc((int)extract(fp1,28L,1),fp4);
    fputc((int)extract(fp1,29L,1),fp4);
    fputc((int)extract(fp1,30L,1),fp4);
    fputc((int)extract(fp1,31L,1),fp4);
    fputc((int)extract(fp1,32L,1),fp4);
    fputc((int)extract(fp1,33L,1),fp4);
    fputc((int)extract(fp1,34L,1),fp4);
    fputc((int)extract(fp1,35L,1),fp4);
    fputc((int)extract(fp1,36L,1),fp4);
    fputc((int)extract(fp1,37L,1),fp4);
    fputc((int)extract(fp1,38L,1),fp4);
    fputc((int)extract(fp1,39L,1),fp4);
    fputc((int)extract(fp1,40L,1),fp4);
    fputc((int)extract(fp1,41L,1),fp4);
    fputc((int)extract(fp1,42L,1),fp4);
    fputc((int)extract(fp1,43L,1),fp4);
    fputc((int)extract(fp1,44L,1),fp4);
    fputc((int)extract(fp1,45L,1),fp4);
    fputc((int)extract(fp1,46L,1),fp4);
    fputc((int)extract(fp1,47L,1),fp4);
    fputc((int)extract(fp1,48L,1),fp4);
    fputc((int)extract(fp1,49L,1),fp4);
    fputc((int)extract(fp1,50L,1),fp4);
    fputc((int)extract(fp1,51L,1),fp4);
    fputc((int)extract(fp1,52L,1),fp4);
    fputc((int)extract(fp1,53L,1),fp4);

    //setting the file pointer at the beginning
    rewind(fp1);

/*CHECKING WHETHER THE FILE IS IN BMP FORMAT OR NOT, WE CHECK THE MAGIC NUMBER OF THE FILE, MAGIC NUMBER'S OFFSET IS 0 i.e. IT'S STORED AT THE FRONT OF THE IMAGE, AND THE SIZE IS 2*/

    //at first extracting the magic number
    for(i=0;i<2;i++)
    {
        magicnum[i]=(char)extract(fp1,i,1);
    }

    //now checking
    if((magicnum[0]=='B') && (magicnum[1]=='M'))
        ;
    else
    {
        printf("\aThe image is not a bitmap image.\nSystem is exiting ... ");
        exit(0);
    }

    //storing the header information

    //get the starting position or offset of the data(pixel)

    dataoffset=(int)extract(fp1,10,4);

    //get the number of rows
    row=(int)extract(fp1,22,4);

    //get the number of columns
    col=(int)extract(fp1,18,4);

        //storing the data
    offset=dataoffset;
    for(j=0;j<col;j++)
    {
        for(k=0;k<row;k++)
        {
            for(i=0;i<=2;i++)
            {
                fputc((int)extract(fp1,offset++,1),fp4);
            }
        }
    }


    fcloseall();
    return 0;
}

【问题讨论】:

  • 你不能使用外部库来处理这个任务吗?你见过 OpenCV 吗?
  • extract中,value的设置可以简化为value = (value &lt;&lt; 8) + temp;。此外,fread 可以更改为fread(&amp;temp, sizeof(temp), 1, fp1);。您还应该检查size 永远不会大于sizeof(value)
  • 你可能想用你的环境来标记它。我的意思是#include&lt;conio.h&gt; 通常意味着一个 windows 环境,但你不希望你的读者不得不猜测。

标签: c bitmap


【解决方案1】:

确保您也以二进制模式打开输出文件。

如果不这样做,'\n'对应的字节值可能会扩展为回车和换行。

【讨论】:

    【解决方案2】:

    考虑这一行:

    value=(long)(value+(*ptr)*(pow(256,(i-1))));
    

    pow 是一个返回双精度的浮点函数。这意味着 (*ptr) 被隐式转换为 double。整个表达式 (value+(*ptr)*(pow(256,(i-1)))) 将是双精度。现在这可以大于 2147483647,这是 long 可以容纳的最大数字(在最常见的 32 位平台上),并且将超出范围的 double 转换为 long 时的结果是未定义的。看看这个例子会发生什么:

    #include <stdio.h>
    
    int main(int argc, char **argv) {
      int i;
    
      for (i = 0; i < 10; i++) {
        double d = 2147483647.0d + i;
        printf("double=%f long=%ld\n", d, (long)d);
      }
      return 0;
    }
    

    这是我在系统上运行时的输出:(隐藏以防您想先自己猜测或测试):

    double=2147483647.000000 long=2147483647
    双=2147483648.000000 长=-2147483648
    双=2147483649.000000 长=-2147483648
    双=2147483650.000000 长=-2147483648
    双=2147483651.000000 长=-2147483648
    双=2147483652.000000 长=-2147483648
    双=2147483653.000000 长=-2147483648
    双=2147483654.000000 长=-2147483648
    双=2147483655.000000 长=-2147483648
    双=2147483656.000000 长=-2147483648

    解决此问题的一种方法是将其更改为 unsigned long

    我个人会使用 1 &lt;&lt; (8*(i-1)) 而不是 pow 来避免与浮点数混淆,但是还有很多其他的事情我也会做非常不同的事情,但这可能超出了这个问题的范围(可能是代码审查网站的问题)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多