在C中从现有位图创建位图图像

时间:2012-01-04 18:05:13

标签: c bitmap

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

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

//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;
}

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

考虑这一行:

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

pow是一个返回double的浮点函数。这意味着(* ptr)被隐式地转换为double。整个表达式(value+(*ptr)*(pow(256,(i-1))))将是双倍的。现在这可能大于2147483647,这是长期可以容纳的最大数字(在大多数常见的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
    double = 2147483648.000000 long = -2147483648
    double = 2147483649.000000 long = -2147483648
    double = 2147483650.000000 long = -2147483648
    double = 2147483651.000000 long = -2147483648
    double = 2147483652.000000 long = -2147483648
    double = 2147483653.000000 long = -2147483648
    double = 2147483654.000000 long = -2147483648
    double = 2147483655.000000 long = -2147483648
    double = 2147483656.000000 long = -2147483648

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

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