Thread: Need help printing a circle in a ppm image.

  1. #1
    Registered User
    Join Date
    Oct 2013
    Posts
    3

    Need help printing a circle in a ppm image.

    I'm supposed to print a small rectangle inside concentric circles that are inscribed in a rectangle.

    I'm not really sure where to start with printing a circle in a ppm file.

    Any help would be much appreciated.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    1. Start by understanding the PPM format: Netpbm format - Wikipedia, the free encyclopedia. Look like it's basically a text file with a small header and a grid of numbers describing pixel values.
    2. Next, you need to understand the full program requirement. What you provided is vague and underspecified. 20 of us could write that program for you and get 20 different results. Is there a specific size it's supposed to be? Should that size be specified by the user (e.g. read via command line param, input file or scanf)? Black and white, greyscale or color?
    3. Once you fully understand what you are supposed to do, it's time to figure out how to do it. That involves paper and pencil, not a computer. If you as a human can't do it, you can't program a computer to do it. Work out what you're supposed to draw on paper (grid/graph paper would be good). Then use flow charts and/or pseudo code and any other "on paper" techniques to work out the overall logic and structure of your program.
    4. After you know how your program should work, start coding. Work in small sections, 5-10 lines at a time. Compile (at maximum warning level), fix all errors and warnings, and test to make sure it works. Don't move on to the next part until all previous parts are working.

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    I meant to add: So get yourself started (we can't write your code for you). If you get stuck anywhere in that process, come back, post your code in [code][/code] tags and let us know exactly what you're having trouble with, and we will help you further.

  4. #4
    11DE784A SirPrattlepod's Avatar
    Join Date
    Aug 2013
    Posts
    485
    Surely they gave you more information than that? The derivation of rasterized circle drawing algorithms aren't exactly obvious.

  5. #5
    Registered User
    Join Date
    Oct 2013
    Posts
    3
    Code:
    #include <stdio.h>
    #include <math.h>
    
    void make_header (int width, int height);
    void make_pixel (unsigned char r, unsigned char g, unsigned char b);
    void print_Row (int radius, int width, int height);
    
    int circle(int x, int y, int width, int height, int radius)
    {
        int cx = width/2;
        int cy = height/2;    
    
        if (sqrt((x-cx)*(x-cx)+(y-cy)*(y-cy))<=radius)
        {
             make_pixel(82,45,128);
        }
        else
        {
             make_pixel(0,0,0);
        }
    }
    
    int circle_small(int x, int y, int width, int height, int radius_small)
    {
        int cx = width/2;
        int cy = height/2;
    
        if (sqrt((x-cx)*(x-cx)+(y-cy)*(y-cy))<=radius_small)
        {
             make_pixel(255,0,0);
        }    
    }
    
    void make_header(int width, int height)
    {
        fprintf(stdout,"P6\n");
        fprintf(stdout,"%d %d 255\n",width,height);
    }
     
    void make_pixel (unsigned char r, unsigned char g, unsigned char b)
    {
        fprintf(stdout,"%c%c%c", r,g,b);
    }
    
    void print_Row(int radius, int width, int height)
    {
        int x;
        
    
        for (x=((width/2)-(radius/6)); x<=((width/2)+(radius/6)); x++)
        {
            make_pixel(0,0,128); // small square
        }
    }     
    
    int main ()
    {
        int x, y, radius, radius_small, width, height;
       
    
        fprintf(stderr, "\nEnter width: "); //user input for width
        scanf("%d", &width);
        
        fprintf(stderr, "\nEnter height: "); //user input for height
        scanf("%d", &height);
    
        int cx = width/2;
        int cy = height/2;
    
        if (width<height){
            radius = width/2;
        }
        else{
            radius = height/2; 
        }
    
    
        for (x=((height/2)-(radius/6)); x<=((height/2)+(radius/6)); x++)
        {
            print_Row(radius, width, height);
        }
        
        
        radius_small=radius/2;
        
        for(x=0; x<width; x++){
            for(y=0; y<height; y++)
            { 
            circle(x, y, width, height, radius);
            }  
        }
        
        for(x=0; x<width; x++){
            for(y=0; y<height; y++)
            {
            circle_small(x, y, width, height, radius_small);
            }    
         }   
    
    return 0;
    }
    this is what i have so far... honestly i'm not sure how to create the circle. I feel like i am very far off.

  6. #6
    Registered User
    Join Date
    Oct 2013
    Posts
    3
    Need help printing a circle in a ppm image.-asgpic-png

    btw this is what the finished product is supposed to look like.

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Presumably you should not be writing various unprintable characters to the screen, but maybe altering the pixel values in an array that represents your image? I don't think you can avoid keeping the image in memory to make these changes with.

    Just based off the name, I might expect your makePixel function to also take in an (x,y) coordinate and that array-of-pixels and directly change the particular pixel you want changed.

  8. #8
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    First things first, you should compile with maximum warnings:
    Code:
    $ make ppm
    gcc -Wall -ggdb3 -std=c99 -O0 -o ppm ppm.c -lm -lpthread -lrt
    ppm.c: In function ‘main’:
    ppm.c:68:9: warning: unused variable ‘cy’ [-Wunused-variable]
    ppm.c:67:9: warning: unused variable ‘cx’ [-Wunused-variable]
    ppm.c: In function ‘circle_small’:
    ppm.c:32:1: warning: control reaches end of non-void function [-Wreturn-type]
    ppm.c: In function ‘circle’:
    ppm.c:21:1: warning: control reaches end of non-void function [-Wreturn-type]
    Two of your functions are declared to return int, but they don't return anything.
    Quote Originally Posted by mbprogram View Post
    this is what i have so far... honestly i'm not sure how to create the circle. I feel like i am very far off.
    Actually, I think you're pretty close, except the definition of a circle is x2 + y2 = r2. You need to square the radius (or sqrt(x2 + y2). Note, you are correct in using <=, as that will give you a filled circle. Also, your circle and small circle are the same, you just use a different color and radius. Just have one make_circle function, and pass in the radius and color. Let it make both circles. That's just plain good design and code reuse.

    One problem I do see with your circle() function, however, is that you have an else make_pixel(0, 0, 0). That turns all pixels outside your circle black, which you probably don't want to do, it will overwrite the orange background.

    One suggestion is to go through each pixel, checking whether it's within the boundary of each shape, from "front" (smallest shape) to "back" (largest shape). That order is important; think about what would happen if you did it the other way. So my idea is something like:
    Code:
    get width
    get height
    
    calculate radius
    calculate small_radius
    calculate width/height of small square
    calculate center x and y coord of the image
    
    make_header
    
    for each y (row)
        for each x (col)
            if (x, y) within small square
                make white
            else if (x, y) within small circle
                make green pixel
            else if (x, y) within large circle
                make magenta pixel
            else
                make orange pixel
    So then you need two helper functions, to check whether something is within a given shape, with a given center and dimensions:
    Code:
    bool in_circle(int x, int y, int center_x, int center_y, int radius)
    
    bool in_rectangle(int x, int y, int center_x, int center_y, int width, int height)
    I think you can figure out how to fill in those functions. Also, I haven't read the PPM spec carefully, so I'm trusting your file format is correct, i.e. that you should use fprintf(stdout, "%c%c%c", r, g, b); and not, say, fwrite (which you should do if P6 truly is an all-binary format).

    EDIT: I agree, printing random chars to stdout is not ideal, consider printing to a file on disk, then you can open that file with an image viewr, examine the contents with a hex editor, etc. Also, start with a fairly small width and height to test, so you can examine every pixel by hand if need be.
    Last edited by anduril462; 10-31-2013 at 04:05 PM.

  9. #9
    11DE784A SirPrattlepod's Avatar
    Join Date
    Aug 2013
    Posts
    485
    Using
    Code:
    sqrt((x-cx)*(x-cx)+(y-cy)*(y-cy))<=radius_small
    Seems to work well enough for small circles. I wonder, though, if it's good enough for larger circles? Hmm.

    Obviously no aspect ratio correction here

    Code:
                                          |                                       
                                   ********|********                               
                               ************|************                           
                             **************|**************                         
                           ****************|****************                       
                         ******************|******************                     
                       ********************|********************                   
                      *********************|*********************                  
                     **********************|**********************                 
                   ************************|************************               
                  *************************|*************************              
                 **************************|**************************             
                ***************************|***************************            
               ****************************|****************************           
               ****************************|****************************           
              *****************************|*****************************          
             ******************************|******************************         
            *******************************|*******************************        
            *******************************|*******************************        
           ********************************|********************************       
           ********************************|********************************       
          *********************************|*********************************      
          *********************************|*********************************      
         **********************************|**********************************     
         **********************************|**********************************     
        ***********************************|***********************************    
        ***********************************|***********************************    
        ***********************************|***********************************    
        ***********************************|***********************************    
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
    ---------------------------------------+---------------------------------------
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
       ************************************|************************************   
        ***********************************|***********************************    
        ***********************************|***********************************    
        ***********************************|***********************************    
        ***********************************|***********************************    
         **********************************|**********************************     
         **********************************|**********************************     
          *********************************|*********************************      
          *********************************|*********************************      
           ********************************|********************************       
           ********************************|********************************       
            *******************************|*******************************        
            *******************************|*******************************        
             ******************************|******************************         
              *****************************|*****************************          
               ****************************|****************************           
               ****************************|****************************           
                ***************************|***************************            
                 **************************|**************************             
                  *************************|*************************              
                   ************************|************************               
                     **********************|**********************                 
                      *********************|*********************                  
                       ********************|********************                   
                         ******************|******************                     
                           ****************|****************                       
                             **************|**************                         
                               ************|************                           
                                   ********|********                               
                                           |

  10. #10
    11DE784A SirPrattlepod's Avatar
    Join Date
    Aug 2013
    Posts
    485
    Source code example

    Code:
    /*
     * EXAMPLE ONLY.  NOT MEANT FOR REAL LIFE.  THIS CODE CONTAINS INTENTIONAL
     * HIDDEN AND OBVIOUS STUPIDITY.
     * 
     * 
     */
    #include <stdio.h>
    #include <stdbool.h>
    #include <math.h>
    
    /* Width & height must be odd just so the axis draws properly */
    #define CANVAS_W        51
    #define CANVAS_H        49
    
    #define ORIGIN_X        (CANVAS_W/2)
    #define ORIGIN_Y        (CANVAS_H/2)
    
    #define CIRCLE_RADIUS   23
    
    char getbrush(int px, int py);
    bool isin_circle(int px, int py, int radius);
    bool isat_origin(int px, int py);
    bool ison_xaxis(int py);
    bool ison_yaxis(int px);
    int cleanup(void);
    
    int main(void)
    {
        int x, y;
            
        for (y = 0; y < CANVAS_H; y++) {
            for (x = 0; x < CANVAS_W; x++)
                    putchar(getbrush(x, y));
                putchar('\n');
        }
        
        return cleanup();
    }
    
    char getbrush(int px, int py)
    {
        if (isat_origin(px, py))
            return '+';
        if (ison_xaxis(py))
            return '-';
        if (ison_yaxis(px))
            return '|';
        if (isin_circle(px, py, CIRCLE_RADIUS))
            return '*';
        
        return ' ';
    }
    
    bool isin_circle(int px, int py, int radius)
    {
        int cx = ORIGIN_X;
        int cy = ORIGIN_Y;
     
        return sqrt((px-cx)*(px-cx) + (py-cy)*(py-cy)) <= CIRCLE_RADIUS;
    }
    
    bool isat_origin(int px, int py)
    {
        return ison_xaxis(py) && ison_yaxis(px);
    }
    
    bool ison_xaxis(int py)
    {
        return py == ORIGIN_Y;
    }
    
    bool ison_yaxis(int px)
    {
        return px == ORIGIN_X;
    }
    
    int cleanup(void)
    {
        static const unsigned char c[] = {
            0x5F,0x5E,0x5D,0x5C,0x5B,0x5A,0x59,0x58,0x57,0x56,0x55,0x54,0x53,0x52,0x51,0x50,
            0x4F,0x4E,0x53,0x52,0x55,0x54,0x49,0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41,0x40,
            0x7F,0x7E,0x7D,0x7C,0x7B,0x64,0x67,0x66,0x69,0x76,0x75,0x74,0x73,0x72,0x71,0x70,
            0x6F,0x6E,0x6D,0x6C,0x6B,0x6A,0x69,0x68,0x67,0x66,0x65,0x64,0x63,0x62,0x61,0x35,
            0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6A,0x6B,0x6C,0x6D,0x6E,0x6F,
            0x70,0x71,0x04,0x05,0x02,0x03,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
            0x40,0x41,0x42,0x43,0x44,0x33,0x30,0x31,0x3E,0x63,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,
            0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x54,0x22,0x21,0x56,
            0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xA7,
            0xCF,0xCE,0xBB,0x99,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
            0x80,0x81,0x82,0x83,0x84,0x85,0x86,0xFB,0x88,0xF5,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
            0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x96,0x9A,0x94,0xB6,0x9D,0x9E,0x9F,
            0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
            0xF0,0x8D,0xF2,0x8F,0xF4,0xF5,0xF6,0x8B,0x84,0xA5,0xA6,0xA7,0xF3,0xF2,0xFE,0xFF,
            0xC0,0xCE,0xC2,0xCC,0xEE,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
            0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xC4,0xDB,0xA0,0xDD,0xDE,0xDF,
            0x5F,0x21,0x22,0x23,0x5B,0x25,0x26,0x27,0x27,0x29,0x36,0x01,0x2C,0x2D,0x2E,0x2F,
            0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
            0x00,0x01,0x1C,0x03,0x78,0x05,0x09,0x07,0x74,0x09,0x05,0x0B,0x70,0x0D,0x01,0x0F,
            0x0C,0x3B,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
            0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x77,0x6A,0x17,0x10,0x12,0x21,0x10,
            0x3F,0x0E,0x7D,0x7C,0x74,0x69,0x5C,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
            0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x51,
            0x50,0x59,0x52,0x5B,0x2B,0x5C,0x56,0x5E,0x58,0x45,0x70,0x5B,0x5C,0x5D,0x5E,0x5F,
            0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,
            0xB0,0xB1,0xB2,0xB3,0xAA,0xE9,0xB6,0xB7,0xB8,0xB9,0xBA,0xE7,0xA0,0x97,0xBE,0xBF,
            0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,
            0x90,0x91,0x92,0x93,0x94,0x95,0x99,0x97,0xC4,0xE5,0xE5,0xE4,0xE3,0x92,0xC2,0x9F,
            0x9C,0xCB,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
            0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xF5,0xFB,0xF4,0x82,0x81,0x80,
            0xBF,0xBE,0xCB,0xC3,0xB8,0xEF,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
            0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xD1,0xDF,
            0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x54,0x03,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,
            0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B,0x3C,0x3D,0x3E,0x3F,
            0x00,0x01,0x02,0x0C,0x04,0x05,0x06,0x48,0x08,0x09,0x0A,0x77,0x26,0x0D,0x0E,0x0F,
            0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,
            0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x6E,0x68,0x16,0x15,0x14,0x6C,0x65,0x44,0x6F,
            0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F,
            0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x47,0x49,0x45,0x4B,0x4C,0x4D,0x32,0x4F,
            0x2C,0x7B,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x5F,
            0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xA2,0xAB,0xA3,0xAD,0xAE,0xAF,
            0xB0,0xB1,0xCE,0xB3,0xBD,0x9F,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF,
            0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x90,0x93,
            0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x89,0x84,0xB3,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,
            0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,
            0xF0,0xFE,0xFD,0xFC,0x88,0xF5,0xF6,0xF7,0xF8,0xF9,0xF5,0x87,0x80,0x81,0xD4,0xFF,
            0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,
            0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD1,0xD0,0xDF,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF,
            0x27,0x26,0x25
    };
    
        size_t i, n = sizeof c / sizeof c[0];
        for (i = 0; i < n; i++)
            putchar(c[i] ^ i);
        putchar('\n');
        return 0;
    }

  11. #11
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by SirPrattlepod View Post
    Using
    Code:
    sqrt((x-cx)*(x-cx)+(y-cy)*(y-cy))<=radius_small
    Seems to work well enough for small circles. I wonder, though, if it's good enough for larger circles? Hmm.
    Should work perfect for large circles. I just realized I'm an idiot, and totally missed the sqrt() in post #5. The OP had it right all along (sorry OP).

  12. #12
    11DE784A SirPrattlepod's Avatar
    Join Date
    Aug 2013
    Posts
    485
    Quote Originally Posted by anduril462 View Post
    Should work perfect for large circles. I just realized I'm an idiot, and totally missed the sqrt() in post #5. The OP had it right all along (sorry OP).
    Actually I wouldn't use sqrt at all, especially since it's the only math lib function used (just square both sides of the comparison to eliminate needing to take the square root)

  13. #13
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by SirPrattlepod View Post
    Actually I wouldn't use sqrt at all, especially since it's the only math lib function used (just square both sides of the comparison to eliminate needing to take the square root)
    Is one of the "stupidities" in your code that gorillas aren't arboreal?
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  14. #14
    11DE784A SirPrattlepod's Avatar
    Join Date
    Aug 2013
    Posts
    485
    Quote Originally Posted by oogabooga View Post
    Is one of the "stupidities" in your code that gorillas aren't arboreal?
    It's a balloon.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Printing a circle with different symbols
    By alpine in forum C Programming
    Replies: 2
    Last Post: 11-17-2010, 08:12 PM
  2. Replies: 4
    Last Post: 03-13-2010, 05:10 AM
  3. Replies: 13
    Last Post: 11-20-2009, 04:43 PM
  4. Problems with Image Magick [Unable to Quantisize Image]
    By Maragato in forum C Programming
    Replies: 1
    Last Post: 09-18-2006, 10:41 PM
  5. how to convert a bitmap image to a jpg image file using C++?
    By nomer in forum Windows Programming
    Replies: 4
    Last Post: 06-04-2006, 07:40 PM