-1

I'm trying to write a code for converting a ppm image into ASCII art. I've written my code but this is not working properly. In fact, it's showing something clearly different from the original image. I have read the ppm file and wrote the ASCII art characters in a text file. Is there anyone who could help me?

Here's my code:

#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 ){
        return ',';
    }else if(greyscale >= 180 ){
        return ':';
    }else if(greyscale >= 160 ){
        return '^';
    }else if(greyscale >= 130 ){
        return '-';
    }else if(greyscale >= 100 ){
        return '*';
    }else if(greyscale >= 70 ){
        return '8';
    }else if(greyscale >= 50 ){
        return '=';
    }else {
        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, "r");
    FILE *output = fopen(outputFile, "w"); 

    int width, height; // max pixel is always 255
    // read the header from the ppm file
    printf("two files succesfully opened");
    fscanf(input, "P3\n%d %d\n255\n", &width, &height);
    printf("file read correctly that width=%d and height=%d",width ,height);
    // allocate place for array[width][length][3]
    int a, b;
    int ***array;
    array = malloc(width*sizeof(int **));
    for(a = 0; a < width; a++){
        array[a] = malloc(height*sizeof(int *));
        for(b = 0; b < height; b++){
            array[a][b] = malloc(3*sizeof(int));
        }
    }

    int x, y;
    for (y = 0; y < height;y++){ 
        for(x=0; x < width; x++){
            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;
            int blockx,blocky,sum=0;
            // convert blocks of pixels to a character and write it into output file
            for(j = 0; j < height; j+=n){
                for(i=0; i <width ; i+=n){sum=0;
                    for(blocky=0; blocky < n&&(j+blocky)<height; blocky++){
                    for(blockx = 0; blockx  < n&&(i+blockx)<width; blockx++){
                    // greyscale = (red + green +blue)/3;
                    sum+=(array[blockx+i][blocky+j][0] + array[blockx+i][blocky+j][1] +array[blockx+i][blocky+j][2]);
                    }
                    }
                    greyscale = sum/(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;
}
Mika Sundland
  • 18,120
  • 16
  • 38
  • 50
  • 1
    Please read on how to provide [mcve]. For example, if file loading is not an issue, then we don't need to see it. You can remove it and replace it with simpler hardcoded input. Do not make us debug your code. – user694733 Jan 31 '18 at 13:31
  • Using the magic "number" P3 you define a plain PPM where pixels are stored as *"A raster of Height rows, in order from top to bottom. Each row consists of Width pixels, in order from left to right. Each pixel is a triplet of red, green, and blue samples, in that order. "* and *"Each sample in the raster has white space before and after it"* (from http://netpbm.sourceforge.net/doc/ppm.html ). You are reading the file wrongly. – Bob__ Jan 31 '18 at 14:19
  • Also, to "allocate place for array[width][length][3]" you could just declare `int array[height][width][3];` (or even a `short int`). – Bob__ Jan 31 '18 at 14:24
  • 2
    tip: if you have to say _"it's showing something clearly different from the original image"_ or such, then you also need to show (A) the original image (B) what you want (C) what it's showing instead. – underscore_d Jan 31 '18 at 15:24
  • 1
    Welcome to Stack Overflow! Please [edit] your question to show us what kind of debugging you've done. I expect you to have reduced your code to a [mcve] and investigated with a debugger such as GDB, for example. Ensure you've enabled a full set of compiler warnings, too. What did the tools tell you, and what information are they missing? And read Eric Lippert's [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). – Toby Speight Jan 31 '18 at 15:34

1 Answers1

1

Here:

array[x][y][0] = fgetc(input); //red
array[x][y][1] = fgetc(input); //green
array[x][y][2] = fgetc(input); //blue

you read the character code of a single characters from the file. That's not what you want. The PPM format stores the pixel info as numbers between 0 and 255. You could use fscanf to read them:

int res = fscanf(input, "%d%d%d",
                        &array[x][y][0],
                        &array[x][y][1],
                        &array[x][y][2]);

if (res < 3) handle_error();
M Oehm
  • 28,726
  • 3
  • 31
  • 42