Сравните две картинки побайтово в unix c - PullRequest
0 голосов
/ 04 мая 2018

Я написал этот метод, который сравнивает два файла, в частности изображения, и выводит на печать результаты, где разница и что это такое. На данный момент результатом этого является то, что каждый байт отличается от другого, но изображение, которое я сравниваю, совпадает. Можете ли вы помочь мне? Вот код:

void compareFiles(char* path1, char* path2){
    FILE* img1;
    FILE* img2;

    if((img1 = fopen(path1,"r")) == NULL || (img2 = fopen(path2,"r")) == NULL){
        printf("ERROR fopen()\n");
        exit(-1);
    }

    int i=0;
    char buffer1,buffer2;

    int c;
    while ((c=fgetc(img1)) != EOF){
        fread(&buffer1, 1,1, img1);
        fread(&buffer2, 1,1, img2);
        if(buffer1 != buffer2){
            printf("Byte differs\n IMG1: %s, IMG2: %s; Position %d\n",&buffer1,&buffer2,i);
            i++;
        }
    }

    fclose(img1);
    fclose(img2);
}

Ответы [ 3 ]

0 голосов
/ 04 мая 2018
while ((c=fgetc(img1)) != EOF)

Это читает первый байт из img1. Предполагая, что это не EOF ...

fread(&buffer1, 1,1, img1);

Это читает второй байт из img1.

fread(&buffer2, 1,1, img2);

Это читает первый байт из img2.

if(buffer1 != buffer2)

Итак, теперь мы сравниваем первый байт img2 со вторым байтом img1.

Если они окажутся равными, мы снова обойдем цикл и в конечном итоге сравним второй байт img2 с четвертым байтом img1.

Похоже, вы, возможно, подумали, что fgetc проверил, есть ли еще один доступный байт, и что fread затем прочитайте его. Но нет. fgetc читает один символ из файла и затем возвращает его. Если вы напишите

c = fgetc(fp);

это почти точно так же, как если бы вы написали

fread(&c, 1, 1, fp);

Таким образом, минимальное исправление вашей программы - избавиться от

fread(&buffer1, 1,1, img1);

и измените критерий равенства на

if(c != buffer2)

Но это приводит к некоторой путанице - более поздний читатель, вероятно, задастся вопросом: «Почему один файл читается с использованием fgetc, а другой с использованием fread

Если бы я писал это, я мог бы прочитать один байт из img1, используя getc, и один байт из img2, используя getc, и сравнить их. Или я мог бы использовать fread, чтобы прочитать N байтов из img1 в массив символов, и N байтов из img2 во второй символьный аддей, и сравнить их, используя функцию memcmp.

Кроме того, как отметил Пол Огилви в комментарии, поскольку это двоичные файлы, когда вы вызываете fopen, чтобы открыть их, вы должны указать режим "rb".

0 голосов
/ 04 мая 2018

Как указывалось в других комментариях, fgetc считывал символ из потока, поэтому 2 потока не синхронизированы перед вызовами fread. Следующее использует 2 вызова fgetc, а затем использует возвращаемые значения для сравнения.

void compareFiles(char* path1, char* path2){
    FILE* img1; 
    FILE* img2; 

    if((img1 = fopen(path1,"rb")) == NULL || (img2 = fopen(path2,"rb")) == NULL){ 
        printf("ERROR fopen()\n"); 
        exit(-1); 
    }   

    int i=0;
    int byte1,byte2;

    while (((byte1=fgetc(img1)) != EOF) && ((byte2=fgetc(img2)) != EOF)){
        if(byte1 != byte2){
            printf("Byte differs\n IMG1: %c, IMG2: %c; Position %d\n",byte1,byte2,i);  
            i++; 
        } 
    }  

    fclose(img1);
    fclose(img2);
} 
0 голосов
/ 04 мая 2018

На мой взгляд, вы должны преобразовать их в два растровых изображения и сравнить заголовок и матрицу. У вас сейчас проблемы, потому что заголовки и теги могут быть разными. Вы можете найти много учебников по этой теме, например , этот на Code Project .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...