Thread: Hello.I am new to programming. I need help with an algorithm for mangling a picture.

  1. #16
    Registered User
    Join Date
    Sep 2022
    Posts
    11
    Thanks, that was a relief... I thought that I was in trouble for a moment there. It is good to know where I stand. I'll work on it. Thanks, Mr. SRU.

  2. #17
    Registered User
    Join Date
    Sep 2022
    Posts
    11

    Progress made on spiral to array.

    Yes, Salem, indeed, you are correct.

    I was rushing and I neglected to test my algorithm.

    Oh well, we live and learn, and over this weekend I did as you requested/suggested.

    Here is the partially completed algorithm.

    I have tested it and it works.

    As you said, the key point is to keep on breaking it down and testing it.

    Here:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void printSpiral(int rows, int cols, char image[rows][cols])
    {
    
        for (int c = 0 ; c < cols ; c++ )
           {
            printf("%c\n", image[0][c] );
           } //Works across ways left to right
    
        for (int r = 1; r < rows; r++ )
           {
            printf("%c\n", image[r][4] );
           }//Works downwards top to bottom
    
          for (int c = cols-1; c > 0 ; c-- )
           {//
            printf("%c\n", image[4][c-1] );
           }//Works across ways right to left
    
       for (int r = rows-2 ; r >=1; r-- )
          {
            printf("%c\n", image[r][0] );
          }//Works upwards bottom to top*/
    }
    
    int main ( )
    {
        int c, r, cols=5, rows=5;
        char image[5][5] =
       {
            { 'a', 'b', 'c', 'd', 'e' },
            { 'p', 'q', 'r', 's', 'f' },
            { 'o', 'x', 'y', 't', 'g' },
            { 'n', 'w', 'v', 'u', 'h' },
            { 'm', 'l', 'k', 'j', 'i' },
       };
    printSpiral(rows, cols, image);
    }
    Now, -I have to get someone to show me how to put these characters (a-to-p) into an array.

    Then the next part of the task is to make one full completion of a spiral, and I think that we should work on both these things.

    I will get back to you in due course, thanks,

    Mr. SRU.

  3. #18
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by ursellsarn View Post
    Yes, Salem, indeed, you are correct.

    I was rushing and I neglected to test my algorithm.

    Oh well, we live and learn, and over this weekend I did as you requested/suggested.

    Here is the partially completed algorithm.

    I have tested it and it works.

    As you said, the key point is to keep on breaking it down and testing it.

    Here:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void printSpiral(int rows, int cols, char image[rows][cols])
    {
    
        for (int c = 0 ; c < cols ; c++ )
           {
            printf("%c\n", image[0][c] );
           } //Works across ways left to right
    
        for (int r = 1; r < rows; r++ )
           {
            printf("%c\n", image[r][4] );
           }//Works downwards top to bottom
    
          for (int c = cols-1; c > 0 ; c-- )
           {//
            printf("%c\n", image[4][c-1] );
           }//Works across ways right to left
    
       for (int r = rows-2 ; r >=1; r-- )
          {
            printf("%c\n", image[r][0] );
          }//Works upwards bottom to top*/
    }
    
    int main ( )
    {
        int c, r, cols=5, rows=5;
        char image[5][5] =
       {
            { 'a', 'b', 'c', 'd', 'e' },
            { 'p', 'q', 'r', 's', 'f' },
            { 'o', 'x', 'y', 't', 'g' },
            { 'n', 'w', 'v', 'u', 'h' },
            { 'm', 'l', 'k', 'j', 'i' },
       };
    printSpiral(rows, cols, image);
    }
    Now, -I have to get someone to show me how to put these characters (a-to-p) into an array.

    Then the next part of the task is to make one full completion of a spiral, and I think that we should work on both these things.

    I will get back to you in due course, thanks,

    Mr. SRU.
    Just swap out the printf statement for a callback eg:
    Code:
    typedef (*print_pixel_cb)( unsigned int pixel );
    
    void printSpiral( unsigned int *img, int rows, int cols, print_pixel_cb print )
    {
    	...
    	for (int c = 0 ; c < cols ; c++ )
    		print( (image + (cols * y))[c] );
    	...
    }
    And Salem, what is your deal, you on a power trip or something? Stop deleting my posts for no apparent reason, if there IS a tangible reason at least highlight it in a PM so I can see it myself

  4. #19
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > printf("%c\n", image[r][4] );
    > printf("%c\n", image[4][c-1] );
    In generalised code, you only have expressions involving rows and cols.

    If you pass in a different sized image, this isn't going to work just by using 4.

    1. Storing in an array
    You need the following snippets.
    Code:
    void printSpiral(int rows, int cols, char image[rows][cols], char *result)
    Wherever you print, you do this
    Code:
    *result++ = image[0][c];  // substitute what you print
    Then a main like so.
    I changed the dimensions to be #defines so that we can do arithmetic on the sizes and still have valid code.
    Code:
    int main ( )
    {
        #define rows 5
        #define cols 5
        char image[rows][cols] =
        {
            { 'a', 'b', 'c', 'd', 'e' },
            { 'p', 'q', 'r', 's', 'f' },
            { 'o', 'x', 'y', 't', 'g' },
            { 'n', 'w', 'v', 'u', 'h' },
            { 'm', 'l', 'k', 'j', 'i' },
        };
        char result[(rows*cols)+1] = { 0 };     // +1 because we treat it as a string
        printSpiral(rows, cols, image, result);
        printf("%s\n", result );
    }
    2. Completing the spiral.
    Imagine your grid as looking like this.
    Code:
            { '1', '1', '1', '1', '1' },
            { '1', '2', '2', '2', '1' },
            { '1', '2', '3', '2', '1' },
            { '1', '2', '2', '2', '1' },
            { '1', '1', '1', '1', '1' },
    On the first pass, you want all the 1's.
    On the second pass, you want all the 2's.
    On the third pass, you want all the 3's.

    Notice how the start position lies on a diagonal.
    1's start at 0,0
    2's start at 1,1
    3's start at 2,2

    Also notice there is a pattern to how many elements there are on the respective ring, based on the starting position. There's two less for each step in towards the centre.

    Now consider a function with a prototype of
    Code:
    void printSpiral(int rows, int cols, char image[rows][cols], int startx, int starty)
    And a main that does
    Code:
    int main ( )
    {
        int c, r, cols=5, rows=5;
        char image[5][5] =
       {
            { 'a', 'b', 'c', 'd', 'e' },
            { 'p', 'q', 'r', 's', 'f' },
            { 'o', 'x', 'y', 't', 'g' },
            { 'n', 'w', 'v', 'u', 'h' },
            { 'm', 'l', 'k', 'j', 'i' },
       };
       printSpiral(rows, cols, image, 0, 0);
       printSpiral(rows, cols, image, 1, 1);
    Can you get a-p then q-x ?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #20
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    @awdert, stop posting your overly complicated drivel!

    WFT - callbacks - sheesh.
    Read the posts, ursellsarn has barely got past hello world in terms of skill.

    Help the poster, not show off how 'smart' you are.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #21
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by Salem View Post
    @awdert, stop posting your overly complicated drivel!

    WFT - callbacks - sheesh.
    Read the posts, ursellsarn has barely got past hello world in terms of skill.

    Help the poster, not show off how 'smart' you are.
    What's overly complicated about a callback? I'm sure they've already encountered typedefs before, I just showed them another usage of it, as for trying to "show off", that wasn't my aim, rarely is and when it is it's usually in a dedicated thread and caught & brought back to reality by peops who've spotted the bugs I haven't.

  7. #22
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    If the ursellsarn is still here, I want to show them light at the end of the tunnel.

    There is a really simple file format "Portable Pixel Map" (a.k.a "PPM") that is a great way to do simple image manipulation programs like what you want to do. See Netpbm - Wikipedia.

    PPM files are well supported on Linux, however if you are on Windows you can use online viewers like Online NetPBM Viewer to view the output, and may need a tool to convert your input image into a PPM file - on Linux you can use the "jpegtoppm" command line program.

    Have a read through that Wikipedia page on that image format, to get a grasp on what we are about to do, then come back here.

    Here's a C program to generate a very simple 512x512 image file (called "output.ppm").

    Code:
    /////////////////////////////////////////////////
    // Program to generate the simplest 512x512 image
    /////////////////////////////////////////////////
    
    
    #include <stdio.h>
    
    
    int main(int argc, char *argv[]) {
       FILE *f;
       // The size of the image
       int width = 512;
       int height = 512;
    
    
       f = fopen("output.ppm","w");
       if(f == NULL) {
          fprintf(stderr, "Failed to open output.ppm for writing\n");
          return EXIT_FAILURE;
       }
    
    
       // Output the file header
       fprintf(f,"P6\n");    // The file type - P6 is a PPM file with binary RGB data
       fprintf(f,"%i %i\n", width, height);
       fprintf(f,"255\n");   // The maximum pixel value
    
    
       // Output the pixel data
       for(int y = 0; y < height; y++) {    // For each line in the image
          for(int x = 0; x < width; x++) {  // For each column in the image
             // Make up some pixel colour values
             int red   = x;     // A red fade horizontally
             int green = x+y;   // A green diagonal fade
             int blue  = y;     // A blue fade vertically
    
    
             // Output the pixel Red/Green/Blue values
             putc(red,   f);
             putc(green, f);
             putc(blue,  f);
          }
       }
       fclose(f);
       return EXIT_SUCCESS;
    }
    As written, this code isn't directly useful for your project - it generates each pixel one by one - so they are not held in memory so you can reorder them.

    So here's an improved version., where a structure called "Image" can hold all the pixels for an image (up to 1024x1024) and has a separate function to write the image out to a PPM file:

    Code:
    ////////////////////////////////////////////////////
    // Program to generate an  image 
    ////////////////////////////////////////////////////
    #include <stdio.h>
    #include <stdlib.h>
    
    
    //////////////////////////////////////////////////////
    // The maximum size images this program will work with
    //////////////////////////////////////////////////////
    #define MAX_IMAGE_HEIGHT 1024
    #define MAX_IMAGE_WIDTH  1024
    
    
    /////////////////////////////////////////////////////
    // Structures used in this program to hold the image
    /////////////////////////////////////////////////////
    
    
    // A structure to hold a pixel's colour values
    struct Pixel {
       unsigned char red;
       unsigned char green;
       unsigned char blue;
    };
    
    
    // A structure to hold the image size and pixels;
    struct Image {
       int width;
       int height;
       struct Pixel pixels[MAX_IMAGE_HEIGHT][MAX_IMAGE_WIDTH];
    };
    
    
    ////////////////////////////////////////////////////////
    // Function prototypes
    ////////////////////////////////////////////////////////
    // 'Prototype' for the image write function.
    int image_write(struct Image *image, char *file_name);
    
    
    ///////////////////////////////////////////////////////////////
    // main(): Generate a 400x300 image and then write it to a file
    ///////////////////////////////////////////////////////////////
    int main(int argc, char *argv[]) {
       // Set aside space for our image on the stack
       // Not the best idea, but it will work!
       struct Image image;
    
    
       // Set the width and height of the image
       image.width = 400;
       image.height = 300;
    
    
       // Fill the image's pizels
       for(int y = 0; y < image.height; y++) {    // For each line in the image
          for(int x = 0; x < image.width; x++) {  // For each column in the image
             image.pixels[y][x].red   = x;     // A red fade horizontally
             image.pixels[y][x].green = x+y;   // A green diagonal fade
             image.pixels[y][x].blue  = y;     // A blue fade vertically
          }
       }
    
    
       // Write the image out to a file
       if(image_write(&image,"output.ppm"))
          return EXIT_SUCCESS;
       else
          return EXIT_FAILURE;
    }
    
    
    ////////////////////////////////////////////////////////
    // A function to write an image to a PPM file
    ////////////////////////////////////////////////////////
    int image_write(struct Image *image, char *file_name) {
       FILE *f;
    
    
       f = fopen(file_name,"w");
       if(f == NULL) {
          fprintf(stderr, "Failed to open output.ppm for writing\n");
          return 0; // logical false = failed to write image
       }
    
    
       // Output the file header
       fprintf(f,"P6\n");    // The file type - P6 is a PPM file with binary RGB data
       fprintf(f,"%i %i\n", image->width, image->height);
       fprintf(f,"255\n");   // The maximum pixel value
    
    
       // Output the pixel data
       for(int y = 0; y < image->height; y++) {    // For each line in the image
          for(int x = 0; x < image->width; x++) {  // For each column in the image
             // Output the pixel Red/Green/Blue values
             putc(image->pixels[y][x].red,   f);
             putc(image->pixels[y][x].green, f);
             putc(image->pixels[y][x].blue,  f);
          }
       }
       fclose(f);
       return 1; // Success!
    }
    
    
    //////// END OF PROGRAM //////////
    Have a look at that, and work through what it is doing. Play with it a bit changing the image size and the colours.

    You should then be able to see a clear path for how you can progress your program:

    - You will need to add a function to read in an image (from a PPM file) into an "Image" structure. This might be harder than you think.

    - Then a function to build a new image, using data from the image you have just read in. Maybe start small with flipping or rotating the image.

    - The you will need to write the manipulated image out - exactly the way the code above does.

    Hopefully that offers some insight into what you need to do, and the level of complexity you will be working at.

  8. #23
    Registered User
    Join Date
    Sep 2022
    Posts
    11

    To print 2D matrix array to 1D row array

    Mr. SRU says:

    I have been giving this some thought about what Salem said, and, and yes, indeed, it is a case of the spiral array printing from:

    11111
    12221
    12321
    12221
    11111

    ...to give:

    1111111111111111222222223.

    I played around with the code and I managed, (after quite a few tries), (using Code:Blocks), -to get:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int c, r, cols=5, rows=5;
    int top=0, bottom=5, left=0, int right=5, llimiter=0, rlimiter=0, blimiter=0, int tlimiter=0;
    int llimiter_2=0, rlimiter_2=0, blimiter_2=0, tlimiter_2=0, llimiter_3=0, rlimiter_3=0, blimiter_3, tlimiter_3=0;
    
    char image[5][5] =
       {
         { 'a', 'b', 'c', 'd', 'e' },
         { 'p', 'q', 'r', 's', 'f' },
         { 'o', 'x', 'y', 't', 'g' },
         { 'n', 'w', 'v', 'u', 'h' },
         { 'm', 'l', 'k', 'j', 'i' },
       };
    
    void printSpiral(int rows, int cols, char image[rows][cols])
    {
     while(left<right && top<bottom)
      {
        for (int c = 0 + llimiter_3 ; c < (cols - rlimiter); c++ )
           {
            printf("%c\n", image[(0 + tlimiter_2)][c] );
           } //Works across ways left to right
            right--;
            rlimiter++;
            tlimiter_2++;
            llimiter_3++;
        for (int r = (1+tlimiter_3); r < (rows - blimiter); r++ )
           {
            printf("%c\n", image[r][4 - rlimiter_2] );
           }//Works downwards top to bottom
            bottom--;
            blimiter++;
            rlimiter_2++;
            tlimiter_3++;
        for (int c = (cols-2-rlimiter_3); c > llimiter ; c-- )
           {//
            printf("%c\n", image[(4 - blimiter_2)][c] );
           }//Works across ways right to left
            left++;
            llimiter++;
            blimiter_2++;
            rlimiter_3++;
       for (int r = rows-1-blimiter_3; r >=(1 + tlimiter); r-- )
           {
            printf("%c\n", image[r][(0+llimiter_2)] );
           }//Works upwards bottom to top*/
            top++;
            tlimiter++;
            llimiter_2++;
            blimiter_3++;
       }
    }
    
    
    int main ( )
    {
     printSpiral(rows, cols, image);
    return 0;
    }
    I have tested the code, and yes, it works...

    Now, what is needed, is for someone to tell me EXACTLY how to print these characters to a 1 by 25 array (1X25), (-essentially a row type array).

    I mean, I know how to print from an array's cells, but to print from "one 2D array to another 1D array", is there a special way to do this?

    Surely it would it just be a matter of stating:

    image[r][c]=image_2[1][r_2]?

    I am unsure how to instruct the computer to do this...

    Obviously we are going to have to declare the array (image_2), but we should use the print function, (perhaps?) to print the row-array image_2.

    So, -we may have to modify the code, and here, I take the first for loop of the main printSpiral function, to give:

    Code:
    for (int c = 0 + llimiter_3 ; c < (cols - rlimiter); c++ )
           {
            image[(0 + tlimiter_2)][c]=image_2[1][r_2];
            printf("%c\n", image_2[1][(r_2]);
           } //Works across ways left to right
            right--;
            rlimiter++;
            tlimiter_2++;
            llimiter_3++;
            r_2++//This must be placed within all for loops.
    I need to print out the matrix's cells to a row, rather than a column, and, of course, I will need to declare a new variable for this (r_2).

    It will be good practice for me, as I need all the practice that i can get.

    At a later stage we need to apply row array print to a style of a zig-zag to print to a matrix.

    Thanks,

    Mr. S R U.

  9. #24
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    Code:
    int c, r, cols=5, rows=5;
    int top=0, bottom=5, left=0, int right=5, llimiter=0, rlimiter=0, blimiter=0, int tlimiter=0;
    int llimiter_2=0, rlimiter_2=0, blimiter_2=0, tlimiter_2=0, llimiter_3=0, rlimiter_3=0, blimiter_3, tlimiter_3=0;
    These should all be local variables inside the function.

    > printf("%c\n", image[r][4 - rlimiter_2] );
    ...
    > printf("%c\n", image[(4 - blimiter_2)][c] );
    As I said in post #19, using 4 here limits you to only a 5x5 image.
    You need to use only expressions derived from the input parameters of rows and cols.


    > Now, what is needed, is for someone to tell me EXACTLY how to print these characters to a 1 by 25 array (1X25), (-essentially a row type array).
    Again, in post #19, read
    "1. Storing in an array"
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #25
    Registered User awsdert's Avatar
    Join Date
    Jan 2015
    Posts
    1,733
    Quote Originally Posted by ursellsarn View Post
    Mr. SRU says:

    I have been giving this some thought about what Salem said, and, and yes, indeed, it is a case of the spiral array printing from:

    11111
    12221
    12321
    12221
    11111

    ...to give:

    1111111111111111222222223.

    I played around with the code and I managed, (after quite a few tries), (using Code:Blocks), -to get:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int c, r, cols=5, rows=5;
    int top=0, bottom=5, left=0, int right=5, llimiter=0, rlimiter=0, blimiter=0, int tlimiter=0;
    int llimiter_2=0, rlimiter_2=0, blimiter_2=0, tlimiter_2=0, llimiter_3=0, rlimiter_3=0, blimiter_3, tlimiter_3=0;
    
    char image[5][5] =
       {
         { 'a', 'b', 'c', 'd', 'e' },
         { 'p', 'q', 'r', 's', 'f' },
         { 'o', 'x', 'y', 't', 'g' },
         { 'n', 'w', 'v', 'u', 'h' },
         { 'm', 'l', 'k', 'j', 'i' },
       };
    
    void printSpiral(int rows, int cols, char image[rows][cols])
    {
     while(left<right && top<bottom)
      {
        for (int c = 0 + llimiter_3 ; c < (cols - rlimiter); c++ )
           {
            printf("%c\n", image[(0 + tlimiter_2)][c] );
           } //Works across ways left to right
            right--;
            rlimiter++;
            tlimiter_2++;
            llimiter_3++;
        for (int r = (1+tlimiter_3); r < (rows - blimiter); r++ )
           {
            printf("%c\n", image[r][4 - rlimiter_2] );
           }//Works downwards top to bottom
            bottom--;
            blimiter++;
            rlimiter_2++;
            tlimiter_3++;
        for (int c = (cols-2-rlimiter_3); c > llimiter ; c-- )
           {//
            printf("%c\n", image[(4 - blimiter_2)][c] );
           }//Works across ways right to left
            left++;
            llimiter++;
            blimiter_2++;
            rlimiter_3++;
       for (int r = rows-1-blimiter_3; r >=(1 + tlimiter); r-- )
           {
            printf("%c\n", image[r][(0+llimiter_2)] );
           }//Works upwards bottom to top*/
            top++;
            tlimiter++;
            llimiter_2++;
            blimiter_3++;
       }
    }
    
    
    int main ( )
    {
     printSpiral(rows, cols, image);
    return 0;
    }
    I have tested the code, and yes, it works...

    Now, what is needed, is for someone to tell me EXACTLY how to print these characters to a 1 by 25 array (1X25), (-essentially a row type array).

    I mean, I know how to print from an array's cells, but to print from "one 2D array to another 1D array", is there a special way to do this?

    Surely it would it just be a matter of stating:

    image[r][c]=image_2[1][r_2]?

    I am unsure how to instruct the computer to do this...

    Obviously we are going to have to declare the array (image_2), but we should use the print function, (perhaps?) to print the row-array image_2.

    So, -we may have to modify the code, and here, I take the first for loop of the main printSpiral function, to give:

    Code:
    for (int c = 0 + llimiter_3 ; c < (cols - rlimiter); c++ )
           {
            image[(0 + tlimiter_2)][c]=image_2[1][r_2];
            printf("%c\n", image_2[1][(r_2]);
           } //Works across ways left to right
            right--;
            rlimiter++;
            tlimiter_2++;
            llimiter_3++;
            r_2++//This must be placed within all for loops.
    I need to print out the matrix's cells to a row, rather than a column, and, of course, I will need to declare a new variable for this (r_2).

    It will be good practice for me, as I need all the practice that i can get.

    At a later stage we need to apply row array print to a style of a zig-zag to print to a matrix.

    Thanks,

    Mr. S R U.
    Well you can just expand your function like this:

    Code:
    printSpiral( int rows, int cols, char img[rows][cols], char *dst, int cap ) { ... }
    and just set the contents directly, using cap as the limit to stop printing, you can call it like this:
    Code:
    int main()
    {
    #define rows 5
    #define cols 5
    	int x, y, sep;
    	char img[rows][cols] = { ... };
    	char dst[rows][cols] = {{0}};
    	printSpiral( rows, cols, img, &(dst[0][0]), rows * cols );
    	/* Confirmation print */
    	for ( x = 0; x < rows; ++x )
    	{
    		sep = 0;
    		for ( y = 0; y < cols; ++y )
    		{
    			printf("%c%c", sep, dst[x][y] );
    			sep = ' ';
    		}
    		putchar('\n');
    	}
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 03-27-2012, 07:23 AM
  2. shared libraries in c++ name mangling error
    By mayank.gupta22 in forum Linux Programming
    Replies: 7
    Last Post: 02-13-2012, 05:11 PM
  3. stdcall name mangling on Widnows
    By Uwar in forum C Programming
    Replies: 0
    Last Post: 06-05-2010, 05:13 AM
  4. Clickie mangling?
    By Imperito in forum A Brief History of Cprogramming.com
    Replies: 5
    Last Post: 11-14-2002, 12:31 AM
  5. picture
    By anonymous in forum C Programming
    Replies: 1
    Last Post: 01-29-2002, 02:44 AM

Tags for this Thread