2015-11-06 16 views
-1

Я пытаюсь прочитать файл ppm и создать новый одинаковый. Но когда я открываю их с помощью GIMP2, изображения не совпадают.Как читать и писать файл ppm?

Где находится проблема с моим кодом?

int main() 
{ 
    FILE *in, *out; 
    in = fopen("parrots.ppm","r"); 
    if(in == NULL) 
    { 
     std::cout<<"Error.\n"; 
     return 0; 
    } 

    unsigned char *buffer = NULL; 

    long size = 0; 
    fseek(in, 0, 2); 
    size = ftell(in); 
    fseek(in, 0, 0); 

    buffer = new unsigned char[size]; 
    if(buffer == NULL) 
    { 
     std::cout<<"Error\n"; 
     return 0; 
    } 

    if(fread(buffer, size, 1, in) < 0) 
    { 
      std::cout<<"Error.\n"; 
      return 0 ; 
    } 

    out = fopen("out.ppm","w"); 
    if(in == NULL) 
    { 
     std::cout<<"Error.\n"; 
     return 0; 
    } 

    if(fwrite(buffer, size, 1, out) < 0) 
    { 
     std::cout<<"Error.\n"; 
     return 0; 
    } 

    delete[] buffer; 

    fcloseall(); 

    return 0; 
} 

Перед тем, что я прочитал файл миллионной доли в структуре, и когда я это написал я получаю такое же изображение, но зеленый был более интенсивным, чем в оригинальной картине. Затем я пробовал это простое чтение и письмо, но получаю тот же результат.

+0

Вы пытались использовать официальную библиотеку для этой цели? - http://netpbm.sourceforge.net/. FYI. – Dummy00001

ответ

1
int main() 

Отсутствует.

FILE *in, *out; 

C стиль ввода/вывода в программе на С ++, почему? Кроме того, объявите в точке инициализации, близкой к первому использованию.

in = fopen("parrots.ppm","r"); 

Это открытие файла в текстовом режиме, что, безусловно, не то, что вы хотите. Используйте режим "rb" для режима.

unsigned char *buffer = NULL; 

Объявите в точке инициализации, рядом с первым использованием.

fseek(in, 0, 2); 

Вы должны использовать SEEK_END, который не гарантируется быть определен как 2.

fseek(in, 0, 0); 

См выше, SEEK_SET не гарантируется быть определен как 0.

buffer = new unsigned char[size]; 
if(buffer == NULL) 

По умолчанию new не возвращает указатель NULL, но бросить std::bad_alloc исключение. (При обкатке, являющейся нормой для большинства текущих операционных систем, проверка на NULL не защитит вас от нехватки памяти даже с malloc(), но приятно видеть, что вы все равно привыкли проверять.)

C++ 11 принес нам smart pointers. Используй их. Они являются отличным инструментом для предотвращения утечек памяти (одна из немногих слабостей C++).

if(fread(buffer, size, 1, in) < 0) 

Успешное использование fread должен возвращать число объектов, написанных, которые должны быть проверены, чтобы быть равным третий параметр (!= 1), не < 0.

out = fopen("out.ppm","w"); 

Текстовый режим снова, вы хотите "wb" здесь.

if(fwrite(buffer, size, 1, out) < 0) 

Смотрите примечание о значении fread возврата выше. То же самое касается и здесь.

fcloseall(); 

Нестандартная функция. Используйте fclose(in); и fclose(out);.11-маньяков решение


C++ (исключая ошибку проверки для краткости) будет выглядеть примерно так:

#include <iostream> 
#include <fstream> 
#include <memory> 

int main() 
{ 
    std::ifstream in("parrots.ppm", std::ios::binary); 
    std::ofstream out("out.ppm", std::ios::binary); 

    in.seekg(0, std::ios::end); 
    auto size = in.tellg(); 
    in.seekg(0); 

    std::unique_ptr<char[]> buffer(new char[ size ]); 

    in.read(buffer.get(), size); 
    out.write(buffer.get(), size); 

    in.close(); 
    out.close(); 

    return 0; 
} 

Конечно, умный решение будет делать фактическую копию файловой системы , либо через Boost.Filesystem, либо standard functionality (экспериментальный на момент написания этой статьи).

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