2012-01-04 2 views
0

Я пишу программу C, которая будет извлекать информацию (информацию заголовка, информацию о пикселях) из растрового изображения и использовать эту информацию для создания другого растрового изображения (новое изображение очевидно, будет таким же, как и оригинал).создание растрового изображения из существующего растрового изображения, в 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; 
} 
+0

Не можете ли вы использовать внешнюю библиотеку для решения этой задачи? Вы видели OpenCV? – karlphillip

+0

В 'extract' параметр' value' можно упростить, например 'value = (значение << 8) + temp;'. Кроме того, 'fread' можно изменить на' fread (& temp, sizeof (temp), 1, fp1); '. Вы также должны проверить, что 'size' никогда не превышает' sizeof (value) '. –

+0

Возможно, вы захотите отметить это своей средой. Я имею в виду '#include ' обычно подразумевает среду Windows, но вы не хотите, чтобы ваши читатели догадывались. – dmckee

ответ

0

Убедитесь, что вы также открываете выходной файл в двоичном режиме.

Если вы этого не сделаете, значение байта, соответствующее «\ n», может быть расширено до возврата каретки и подачи строки.

0

Рассмотрим следующую строку:

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

пау является функцией с плавающей точкой возвращения в два раза. Это означает, что (* ptr) неявно приводится к двойному. Все выражение (value+(*ptr)*(pow(256,(i-1)))) будет двойным. Теперь это может быть больше, чем 2147483647, что является самым большим числом, которое может длиться долго (на большинстве распространенных 32-разрядных платформ), а результат при преобразовании из диапазона с двойным в длинный не определен. Посмотрите, что происходит на этом примере:

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

Вот выход, когда я запускаю его на моей системе: (скрытый в случае, если вы хотите, чтобы угадать или испытать его самостоятельно первым):

unsigned long.

Лично я использовал бы 1 << (8*(i-1)) вместо pow, чтобы избежать беспорядка с плавающей точкой, но есть много других вещей, которые я бы сделал очень разные тоже, но это, вероятно, не подходит для этого вопроса (может быть, вопрос для сайта проверки кода).

Смежные вопросы