2014-08-31 4 views
-2

У меня вопрос о том, как восстановить jpg-изображения (это назначение для CS50). Мой код работает по большей части (я считаю), однако я только получаю кучу миниатюр, когда открываю найденные jpg.C. CS50 восстановить назначение, восстановить изображения Jpg

Я пытался решить это упражнение уже довольно давно, но я не могу понять, почему он не работает. Может кто-нибудь дать мне толчок в правильном направлении.

Вот мой код (также доступен в http://pastebin.com/U2pwJd5e):

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

#include "bmp.h" 


int main(int argc, char* argv[]) 
{ 

    //get input file 
    char* infile = "card.raw"; 
    // open card file 
    FILE* inptr; 
    inptr = fopen("card.raw", "r"); 


    // error checking (copied from copy.c) 
    if (inptr == NULL) 
    { 
     printf("Could not open %s.\n", infile); 
     return 2; 
    } 

    // initialize buffer 
    BYTE buffer[512]; 

    //initialize jpg variables: 
    int increment = 0; 
    char outfilename[8]; 

    // while the end of the file is not reached, continue process & write to buffer next block of 512 bytes 
    while (fread(buffer, 512, 1, inptr) != 0) 
    { 
     // if the inpointer is not empty 
     if(inptr != NULL) 
     { 
      // If the block of 512 bytes starts with markers 
      if(buffer[0] == 0xff && buffer[1] == 0xd8 && buffer[2] == 0xff && (buffer[3]== 0xe1 || buffer[3]== 0xe0)) 
      { 
       // increase file number by 1 
       sprintf(outfilename,"%.3d.jpg", ++increment); 

       // open new file 
       FILE* outptr; 
       outptr = fopen(outfilename, "a"); 

       // write first block of 512 bytes, then read next block 
       fwrite(buffer, 512, 1, outptr); 

       if(fread(buffer, 512, 1, inptr) == 0) 
         break; 

       // copy all information from inpointer to buffer to jpg 
       while((buffer[0] != 0xff && buffer[1] != 0xd8 && buffer[2] != 0xff && (buffer[3]!= 0xe1 || buffer[3]!= 0xe0))) 
       { 
        // if next byte is NULL break 
        if(fread(buffer, 512, 1, inptr) == 0) 
         break; 

        fread(buffer, 512, 1, inptr); 

        //copies jpg file 1 byte at a time 
        fwrite(buffer, 512, 1, outptr); 

       } 

       // close file 
       fclose(outptr); 
      } 
     } 

    } 
    return 0; 
} 
+1

Добро пожаловать в Переполнение стека. Вскоре прочитайте страницу [О программе]. В общем случае, по крайней мере, можно утверждать, что если код работает, он может принадлежать [Code Review] (http://codereview.stackexchange.com/). Если он не работает, вам нужно показать код, который не работает, и, возможно, (ссылка на a) образец сломанного изображения, на котором он не работает. Как правило, людям не очень нравится переходить на другой сайт для кода. Когда операционный код длиной всего 70 с лишним строк, вы можете, вероятно, вставить его здесь. –

ответ

4

Там много недостающей информации в вашей проблеме, но я могу видеть несколько потенциальных проблем:

  1. Вы проверяете только для файл JPEG в начале каждого 512-байтового блока. Если вам не гарантировано, что это так, вы, вероятно, должны проверить запуск файлов JPEG во всем блоке памяти.
  2. Вы только проверяете файлы JPEG с запуском FFD8FFE1 или FFD8FFE0. Что делать, если второй блок в формате JPEG не является FFE1/FFE0?
  3. Следующая проверка в вашем втором if блок не является правильным:

    (buffer[3] != 0xe1 || buffer[3] != 0xe0) 
    

    Это всегда так, как buffer[3] не может быть как 0xE1 и 0xE0 одновременно. Это должно быть:

    (buffer[3] != 0xe1 && buffer[3] != 0xe0) 
    
  4. Ваша проверка на конец изображения JPEG, вероятно, не делать то, что вы хотите:

    while (buffer[0] != 0xff && buffer[1] != 0xd8 && 
         buffer[2] != 0xff && buffer[3] != 0xe1 && buffer[3]!= 0xe0) 
    

    Это заканчивается JPEG, когда вы найдете любой из этих значений в начале 512-байтового блока. Например, байты 01DB0203 закончили бы JPEG, поскольку buffer[1] != 0xd8 является ложным, хотя это не маркер блока JPEG.

  5. Я думаю, что поиск конца файла JPEG потребует от вас поискать весь блок памяти для маркера байтов FFD9, который означает конец JPEG file. Если я правильно понимаю формат JPEG, комбинация байт FFD9 может появляться только в конце допустимого файла JPEG.
  6. Если вы все еще сталкиваетесь с проблемами, я бы создал тестовый файл, состоящий из нескольких известных файлов JPEG и других данных. Затем вы можете напрямую сравнивать то, что выводится на то, что вы знаете, должно выводиться, чтобы сузить место, где/что вызывает проблему.
+0

'0xFFE0' - это подпись JFIF, а' 0xFFE1' - EXIF. Они будут охватывать более 99,9% файлов Jpeg. – rodrigo

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