Click here to Skip to main content
15,888,269 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I wrote a program for converting a file from PPM format to ASCII art. Every pixel of the input image is converted to greyscale by calculating the average of red green and blue values ((red + green +blue)/3).

The upgrade of the basic version is that I calculate the average of RGB in a window of size n*n, and convert it to a character which would decrease the size of the image. So if the given number n is 3, the window is of size 3*3, which means that you sum all nine red, green and blue values and divide it by 3 times n*n (3*3 in this case). When the program counts the greyscale for the first window, it moves to the other one and so on until the end. When there is the end of width, it jumps down by the n number of pixels and reads the next line, etc.

When the greyscale is calculated it is then converted to a character and this character is being written to the output file to form an ASCII art image.

There is the code that should do this work:
#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; // the size of the block

    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"); 

    int width, height; 
    // read header from ppm file
    fscanf(input, "P6\n%d %d\n255\n", &width, &height);

    // 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 (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;
            // greyscale = (red + green +blue)/3;

            int blockx, blocky;
            for(blockx = 0; blockx < n; blockx+=n){
                for(blocky=0; blocky < n; blocky+=n){
                    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 ASCII art to the output file 
                }

            }   
        }fprintf(output,"\n");
    }

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

    return 0;
}


The output file for one ppm should look like this:
                    ..'::....'oo&&:..                                           
               ..:'#8@@oo#@@@@@@@@@8      .8&o              .&o.                
            ooo:'.'o88'    8@@@@@@@&                8'    '@@@@@@' .  .&..      
   '@@@8&'o8&:8@@':@o@#   &@@@@@&         &@@o    .o'@8@@@@@@@@@@@@@@@@@@#o:&o
:& 8@@@@@@@@@@@@@@@@8&.&@o  #@@'   #8     :@@8@@o@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   &@@#o8@@@@@@@@@@   '@o.   :'          @@@ #@@@@@@@@@@@@@@@@@@@@@@@@@@@@8:8&' 
    ..    &@@@@@@@@#&..@@@o           'o  :o.@@@@@@@@@@@@@@@@@@@@@@@@@&   .@    
           &@@@@@@@@@@#@@@@&          '8o@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8        
            8@@@@@@@@@@@@8 &           &@@@@@@@@@@#:@@@@@@@@@@@@@@@@@@@.        
            #@@@@@@@@@@@:             8##:&'@@'..@&&@@@@@@@@@@@@@@@@@& &        
            '@@@@@@@@@@.              @@   '. @@@@@ @@@@@@@@@@@@@@: &  :        
             :@@@@@@@@&               8@@@&    .@@@@@@@@@@@@@@@@@@@  &.         
              :@@@@:.8               :@@@@@@@@@@@@@@@@@@@@@@@@@@@@@             
               '@@.                 :@@@@@@@@@@#8@@&8''@@@@@@@@@@@:             
                '@&.o '.'           @@@@@@@@@@@@:@@@@  .@@@''@@8o               
                  &@&.              @@@@@@@@@@@@@o@&    &@   o@@  .             
                     : :o.          o@@@@@@@@@@@@@'.    .@    '@.  '            
                      :@@@@.         &@@#@@@@@@@@@@      .    :  . o            
                      o@@@@@@             @@@@@@@@.          .# '@              
                      @@@@@@@@o           @@@@@@@             8oo@o .8&'        
                      @@@@@@@@@@.         .@@@@@#              :&.    '@8       
                      .@@@@@@@@8           @@@@@@                    : '        
                       o@@@@@@@'          .@@@@@@ 8                :#@o8'       
                        &@@@@@@            @@@@@ .@              .&@@@@@@       
                        8@@@@&             @@@@8 .o              @@@@@@@@@      
                        @@@@@              .@@@                  o@@@@@@@@      
                        @@@@                @8                   '@o  #@@8      
                       :@@#                                            o&     .o
                       :@#                                              :    .: 
                       8@.                                                   '  
                       o#                                                       
                        '                                                       
                                                                                
                         .'                        ..       ...... . ..         
                        8@               ..:'.o#&@@@@@@:o@@@@@@@@@@@@@@@@@#o.   
         ':8888&&@@@@8@@@@'         8@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8.  
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@




But my program outputs it like this:
                    ..'::....'oo&&:..   

               ..:'#8@@oo#@@@@@@@@@8    
  .8&o              .&o.                
            ooo:'.'o88'    8@@@@@@@&    
            8'    '@@@@@@' .  .&..      
   '@@@8&'o8&:8@@':@o@#   &@@@@@&     
    &@@o    .o'@8@@@@@@@@@@@@@@@@@@#o:&o
:& 8@@@@@@@@@@@@@@@@8&.&@o  #@@'   #8   
  :@@8@@o@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
   &@@#o8@@@@@@@@@@   '@o.   :'         
 @@@ #@@@@@@@@@@@@@@@@@@@@@@@@@@@@8:8&' 
    ..    &@@@@@@@@#&..@@@o           'o
  :o.@@@@@@@@@@@@@@@@@@@@@@@@@&   .@    
           &@@@@@@@@@@#@@@@&          '8
o@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8        
            8@@@@@@@@@@@@8 &           &
@@@@@@@@@@#:@@@@@@@@@@@@@@@@@@@.        
            #@@@@@@@@@@@:             8#
#:&'@@'..@&&@@@@@@@@@@@@@@@@@& &        
            '@@@@@@@@@@.              @@
   '. @@@@@ @@@@@@@@@@@@@@: &  :        
             :@@@@@@@@&               8@
@@&    .@@@@@@@@@@@@@@@@@@@  &.         
              :@@@@:.8               :@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@             
               '@@.                 :@@@
@@@@@@@#8@@&8''@@@@@@@@@@@:             
                '@&.o '.'           @@@@
@@@@@@@@:@@@@  .@@@''@@8o               
                  &@&.              @@@@
@@@@@@@@@o@&    &@   o@@  .             
                     : :o.          o@@@
@@@@@@@@@@'.    .@    '@.  '            
                      :@@@@.         &@@
#@@@@@@@@@@      .    :  . o            
                      o@@@@@@           
  @@@@@@@@.          .# '@              
                      @@@@@@@@o         
  @@@@@@@             8oo@o .8&'        
                      @@@@@@@@@@.       
  .@@@@@#              :&.    '@8       
                      .@@@@@@@@8        
   @@@@@@                    : '        
                       o@@@@@@@'        
  .@@@@@@ 8                :#@o8'       
                        &@@@@@@         
   @@@@@ .@              .&@@@@@@       
                        8@@@@&          
   @@@@8 .o              @@@@@@@@@      
                        @@@@@           
   .@@@                  o@@@@@@@@      
                        @@@@            
    @8                   '@o  #@@8      
                       :@@#             
                               o&     .o
                       :@#              
                                :    .: 
                       8@.              
                                     '  
                       o#               

                        '               



                         .'             
           ..       ...... . ..         
                        8@              
 ..:'.o#&@@@@@@:o@@@@@@@@@@@@@@@@@#o.   
         ':8888&&@@@@8@@@@'         8@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@8.  
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@


Can anyone tell me what am I doing wrong?
Posted
Comments
Sergey Alexandrovich Kryukov 22-May-15 17:43pm    
Are you sure you used monospace font? Work with wrong stride length?
The idea is correct, only it would lead to pretty low-quality ASCII art, and the implementation is bad, hard-coded...
—SA

1 solution

Everything looks good until I see this:

C++
int blockx, blocky;
for(blockx = 0; blockx < n; blockx+=n) {
    for(blocky=0; blocky < n; blocky+=n) {
        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 ASCII art to the output file 
    }
}


This code is the same as:

C++
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 ASCII art to the output file


This is because the for loop(s) can only execute once. You say you want to sum the RGB values inside a boxed area (eg. 3 x 3) but the loop above does not sum. You must read all the pixels into memory before they can be summed.

Try something like this:

C++
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
    }
}


Now all the pixels are in memory. Your work can begin.

C++
int greyscale;
int i, j, *pixel;

for (x = 0; x < width; x += n) { 
    for (y=0; y < height; y += n) {
        greyscale = 0;
        for (i = 0; i < n; i++) {
            if (x + i >= width) break;
            for (j = 0; j < n; j++) {
                if (y + j >= height) break;
                pixel = array[x + i][y + j];
                greyscale += pixel[0] + pixel[1] + pixel[2]; // RGB
            }
        }
        greyscale /= 3*n*n;
        char c = method_of_conversion(greyscale);
        fprintf(output,"%c",c); // write ASCII art to the output file 
    }
    fprintf(output,"\n");
}


The above code also handles the boundary condition(s) where width and height are not multiples of "n".
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900