Ошибка сегментации в коде c для преобразования искусства ASCII

Пишу программу для преобразования файла из формата PPM в формат ASCII art. Каждый пиксель входного изображения преобразуется в оттенки серого путем вычисления среднего значения красного, зеленого и синего ((красный + зеленый + синий)/3). Обновление базовой версии заключается в том, что я вычисляю среднее значение RGB в окне размером n*n, что уменьшит размер изображения. Входной файл состоит из трех строк: первая — это имя файла, который мы хотим преобразовать, вторая — это имя файла, в который мы хотим записать преобразованное изображение, а третья — размер окна (n) программы. необходимо использовать путем преобразования изображения в ASCII art. Я думаю, что реализовал в программе все, что должен, и она компилируется, но когда я ее тестирую, я получаю ошибку сегментации. Может ли кто-нибудь сказать мне, пожалуйста, где проблема?

Вот код:

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

// convert the calculated greyscale to a character based on brightness
char method_of_conversion(int greyscale){
    if(greyscale >= 230){
        return ' ';
    }else if(greyscale >= 200 && greyscale < 230){
        return '.';
    }else if(greyscale >= 180 && greyscale < 200){
        return '\'';
    }else if(greyscale >= 160 && greyscale < 180){
        return ':';
    }else if(greyscale >= 130 && greyscale < 160){
        return 'o';
    }else if(greyscale >= 100 && greyscale < 130){
        return '&';
    }else if(greyscale >= 70 && greyscale < 100){
        return '8';
    }else if(greyscale >= 50 && greyscale < 70){
        return '#';
    }else if(greyscale < 50){
        return '@';
    }
}

int main(){
    char ppmFile[100];
    char outputFile[100];

    int n;

    scanf("%s", &ppmFile); //read the name of input file
    scanf("%s", &outputFile); //read the name of output file 
    // the size of a window of pixels you have to convert to ascii art character
    scanf("%d", &n); 

    FILE *input = fopen(ppmFile, "rb");
    FILE *output = fopen(outputFile, "w"); 


    char header[5]; //header = P6
    fscanf(input, "%s\n", header);
    int width, height, maxPixel; // max pixel is always 255
    // read the header from the ppm file
    fscanf(input, "%d %d %d\n", &width, &height, &maxPixel);

    // allocate place for array[width][length][3]
    int ***array;
    array = malloc(width*sizeof(int **));
    array[0] = malloc(height*sizeof(int *));
    array[0][0] = malloc(3*sizeof(int));

    int x, y;
    for (x = 0; x < width; x++){ 
        for(y=0; y < height; y++){
            array[x][y][0] = fgetc(input); //red
            array[x][y][1] = fgetc(input); //green
            array[x][y][2] = fgetc(input); //blue

            int greyscale;
            int i, j;
            // convert blocks of pixels to a character and write it into output file
            for(i = 0; i < width; i+=n){
                for(j=0; j < height; j+=n){
                    // greyscale = (red + green +blue)/3;
                    greyscale = (array[x][y][0] + array[x][y][1] +array[x][y][2])/(3*n*n);
                    char c = method_of_conversion(greyscale);
                    fprintf(output,"%c",c); // write the ASCII art directly in the output file
                }
            }   
        }fprintf(output,"\n"); // dont forget to go into a new line
    }

    free(array);
    fclose(input);
    fclose(output);

    return 0;
}

person confused    schedule 22.05.2015    source источник
comment
Вы никогда не проверяете результат fopen. Или любая другая функция файлового ввода-вывода. Поэтому, если формат вашего файла немного отличается от того, что вы ожидаете, произойдет сбой и произойдет сбой.   -  person Eugene Sh.    schedule 22.05.2015


Ответы (1)


array = malloc(width*sizeof(int **));
array[0] = malloc(height*sizeof(int *));
array[0][0] = malloc(3*sizeof(int));

Здесь выделяется только array[0][0], для всех остальных индексов выделения не происходит. Затем следующий цикл пытается записать в индексы, которым не выделена память, что приводит к ошибке сегментации.

person sth    schedule 22.05.2015
comment
Да, вы можете добавить дополнительные циклы, которые выделяют всю необходимую память. В качестве альтернативы вы можете использовать его в циклах, которые у вас уже есть, выделяя память для каждого индекса массива, прежде чем читать значения. - person sth; 22.05.2015