C Programming - .bmp image manipulation

Hello I am trying to write a program to manipulate image from a 24-bit uncompressed bmp file. To help with reading and writing the image file, the code is given library functions and an example that deals with the bmp file (the image is called example.bmp.

I am trying to write the code for the program to be able to successfully accept
In that case, one can 'chain' the commands using Unix pipes, like:

% ./bmptool -s 4 1.bmp | ./bmptool -c | ./bmptool -v -o 2.bmp

The end result of the program should run: On the first pipe CMD input on the bmptool program will scale the input image 1.bmp by 4 times, it will output the result image through standard output. (since -o is not specified). The second bmptool program will take the output image from the first program as standard input, rotate the scaled image counter clockwise by 90 degrees, and then output the result image through standard output. The third bmptool will take the output of the second program as standard input, and then flip the image vertically. The result will be written out to the output a file called 2.bmp.

The example of the CMD pipe input is below:
% bmptool [-s scale | -r | -c | -f | -v ] [-o outfile] [infile]
• -s means to scale the image by the given 'scale' value (which must be a positive integer: 1, 2, 3, ...); if the image was X*Y in dimension, the result image should be (X*scale)*(Y*scale) in dimension
• -r means to rotate the image clockwise by 90 degrees
• -c means to rotate the image counter-clockwise by 90 degrees
• -f means to flip the image horizontally, left and right (this has been implemented)
• -v means to flip the image vertically, up and down

Please explain or modify my code for me to get this work on the int main() portion of the code to accept the Unix pipe input, using getopt() to recognize:

bmptool [-s scale | -r | -c | -f | -v ] [-o outfile] [infile]

then with the use of 'flags' as a variable to manage (-s, -r, -c, -f or -v) respectively, which then uses a switch constructor correctly to collect inputs from CMD so the program can use the methods to perform the necessary enlarge, rotate, and flip operations on the image.

Also, if you see or feel that my methods to flip, enlarge, or rotate can be improved please do not hesitate to revise the code! Thank You in advance!

So, what I have so far with what I want to do with the code commented, below:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//******main.c*************
#include <stdlib.h>
#include "bmplib.h"
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>

/*
 * This method enlarges a 24-bit, uncompressed .bmp file
 * that has been read in using readFile()
 */
int enlarge(PIXEL* original, int rows, int cols, int scale, 
	    PIXEL** new, int* newrows, int* newcols) 
{
  /* THIS IS THE METHOD THAT YOU SHOULD WRITE */
  int row, col, i, j;
if ((rows <= 0) || (cols <= 0)) return -1;
*newrows = scale*rows;
*newcols = scale*cols;
*new = (PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));
  for (row=0; row < rows; row++) 
    {
    for(i=0; i<scale; i++)
      {
        for (col=0; col < cols; col++) 
        {
            for(j=0; j<scale; j++)
              {
                  PIXEL* o = original + row*cols + col;
                  PIXEL* n = (*new) + row*cols*scale*scale + cols*scale*i + col*scale + j;
                  *n = *o;
              }
        }   
      }
    }
  return 0;
}

/*
 * This method rotates a 24-bit, uncompressed .bmp file that has been
 * read in using readFile(). Rotate 90 degrees clockwise if 'rotation'
 * is 1; rotate 90 degrees counter-clockwise if 'rotation' is 0; all
 * other values of 'rotation' are invalid.
 * 
 */
int rotate(PIXEL* original, int rows, int cols, int rotation,
	   PIXEL** new, int* newrows, int* newcols)
{
  int row, col;
  if(rotation % 360 == 0)
  {
    *newrows = rows;
    *newcols = cols;
    *new = (PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));
    for (row=0; row < rows; row++)
    {
      for (col=0; col < cols; col++) 
        {
          PIXEL* o = original + row*cols + col;
          PIXEL* n = (*new) + row*cols + col;
          *n = *o;
        }
    }
  }
else if((rotation > 0 && rotation % 270 == 0) || (rotation < 0 && rotation % 90 == 0 && rotation % 180 != 0 && rotation % 270 != 0))
{
*newrows = cols;
*newcols = rows;
*new = (PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));
for (row=0; row < rows; row++)
  {
for (col=0; col < cols; col++) 
  {
    PIXEL* o = original + row*cols + col;
    PIXEL* n = (*new) + (cols-col-1)*rows + row;   
    *n = *o;
  }
    }
}
  else if((rotation > 0 && rotation % 180 == 0) || (rotation < 0 && rotation % 180 == 0))
    {
*newrows = rows;
*newcols = cols;
*new = (PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));
for (row=0; row < rows; row++)
{
for (col=0; col < cols; col++) 
  {
      PIXEL* o = original + row*cols + col;
      PIXEL* n = (*new) + (rows-row)*cols - (col+1);
      *n = *o;
  }
}
    }
else if((rotation > 0 && rotation % 90 == 0) || (rotation < 0 && rotation % 270 == 0))
  {
*newrows = cols;
*newcols = rows;
*new = (PIXEL*)malloc((*newrows)*(*newcols)*sizeof(PIXEL));
for (row=0; row < rows; row++)
    {
for (col=0; col < cols; col++) 
      {
        PIXEL* o = original + row*cols + col;
        PIXEL* n = (*new) + col*rows + (rows-row-1);
        *n = *o;
      }
}
  }
  return 0;
}
/*
 * This method horizontally flips a 24-bit, uncompressed bmp file
 * that has been read in using readFile(). 
 */
int flip (PIXEL *original, PIXEL **new, int rows, int cols) 
{
  int row, col;
  if ((rows <= 0) || (cols <= 0)) return -1;
  *new = (PIXEL*)malloc(rows*cols*sizeof(PIXEL));
  for (row=0; row < rows; row++)
    for (col=0; col < cols; col++) 
    {
      PIXEL* o = original + row*cols + col;
      PIXEL* n = (*new) + row*cols + (cols-1-col);
      *n = *o;
    }
  return 0;
}

/*
 * This method virtically flips a 24-bit, uncompressed bmp file
 * that has been read in using readFile(). 
 * 
 * original - an array containing the original PIXELs, 3 bytes per each
 * rows     - the number of rows
 * cols     - the number of columns
 *
 * new      - the new array containing the PIXELs, allocated within
 * // THIS IS THE METHOD THAT YOU SHOULD WRITE 
 */
int flipv(PIXEL *original, PIXEL **new, int rows, int cols) 
{
  int row, col;

if ((rows <= 0) || (cols <= 0)) return -1;

*new = (PIXEL*)malloc(rows*cols*sizeof(PIXEL));

for (row=0; row < rows; row++)
    for (col=0; col < cols; col++) {
      PIXEL* o = original + row*cols + col;
      PIXEL* n = (*new) + row*cols + (cols-1-col);
      *n = *o;
    }
  return 0;
}

int main(int argc, char *argv[])
{
  int r, c,nr,nc;
  PIXEL *b, *nb;
  //extern int optind;
  //int c, err;
//these are the flags used to determine if certain command inputs were used
// int fflag ; oflag ; rflag; 
//int xcale = 0; degree = 0;
//char*outputfile
//static char usage[]= CMD input [outputfile] [inputfile]
//Usage: bmptool [-s scale | -r degree | -f] [-o output_file] [input_file\n];
/*
while((c = getopt(argc, argv, "s:r:fo:")) !=-1)
  //This switch case set is used to mark flags and place values where they go into the previously declared variables
switch constructor(c)
{
  case s
  scale = atoi(optarg);
  case f 
  fflag = 1
  case o
  oflag =1
  outputfile=optarg
  case r
  rflag =1;
  degree = atoi(optarg);
  if ((degree % 90) != 0)

  fprintf(stderr, uage, argv[0]);
  case ?
  err =1
  if (err== 1)
fprint(strderr,usage, argv[0])
exit(1);
  if(optind < argc)
}
}
*/


//******End of file****main.c*************
Last edited on
first, your code is a complete mess and a mixture of C and C++

secondly, why reinventing the wheel? there are plenty of tested and well working libraries for image data manipulation.

I don't know what open source libs there are (useful for linux systems) but for windows,
Winapi offers WIC.
https://docs.microsoft.com/en-us/windows/win32/api/_wic/
This is clearly a valid C program and not a C++ program (it has variables named new, etc.)
I still don't know why there is such a problem with people asking about C on this forum, even after so many years.

@alexexcl
You are wasting your time reinventing the wheel. Use EasyBMP (http://easybmp.sourceforge.net/).

If this is a school assignment, then alas, you are stuck with your own code, in which case you need to actually ask a question.
He did ask a question:

Please explain or modify my code for me to get this work on the int main() portion of the code to accept the Unix pipe input, using getopt() to recognize:
jonnin is correct, and i am not trying to reinvent the wheel. I do have additional code that I can upload that includes bmplib.h and bmplib.c if anyone needs it. I am just trying to work with pixels in C. Anyways I do have some more code to consider for the int main() perhaps someone can share some revisions to the code so it can accept the Unix pipe input, with getopt() ?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
int main(int argc, char *argv[])
{
  int r, c,nr,nc;
  PIXEL *b, *nb;
char* infile;
char* outfile;
int fl, ro, sc, ou, nro; /* getopt flags */
int argindex;
int val_scale, val_rotate, tmp;
outfile = NULL;
infile = NULL;
argindex = 0;
val_scale = val_rotate = 0;
fl = ro = sc = ou = nro = 0;
while((c = getopt(argc, argv, "srfo")) != -1)
{
switch(c) {
case 's':
if(sc){
fprintf(stderr, "Duplicate options\n");
exit(-1);
}
sc = 1;
break;
case 'r':
if(ro){
fprintf(stderr, "Duplicate options\n");
exit(-1);
}
ro = 1;
break;
case 'f':
if(fl){
fprintf(stderr, "Duplicate options\n");
exit(-1);
}
fl = 1;
break;
case 'o':
if(ou){
fprintf(stderr, "Duplicate options\n");
exit(-1);
}
ou = 1;
break;
case '?':
tmp = atoi(argv[optind]);
if((tmp == 0 || tmp % 90 == 0) && !nro && ro){
nro = 1;
val_rotate = tmp;
}
break;
default:
//usage();
printf("default");
}
}
argc -= optind;
argv += optind;
if(argc < 1 && !nro && !fl){
fprintf(stderr, "Too few arguments");
exit(-1);
}
/* assume if argument are true, they are in order */
if(sc){
val_scale = atoi(argv[argindex++]);
}
if(ro && !nro){
val_rotate = atoi(argv[argindex++]);
}
if(ou){
outfile = argv[argindex++];
}
if(argc - 1 == argindex){
infile = argv[argindex];
}
//read input file
readFile(infile, &r, &c, &b);
//execute function calls based on command line flags
if(fl){
flip(b, &nb, r, c);
}
if(sc){
enlarge(b, r, c, val_scale, &nb, &nr, &nc);
r = nr;
c = nc;
}
if(ro){
rotate(b, r, c, val_rotate, &nb, &nr, &nc);
r = nr;
c = nc;
}
//write results to file
writeFile(outfile, r, c, nb);
free(b);
free(nb);
  return 0;
}
Last edited on
I'd say forget this "can I use Unix pipes to chain" as being a distraction. Are you able to correctly use the two parameters passed into main?

https://www.tutorialspoint.com/cprogramming/c_command_line_arguments.htm

How you interpret the string array parameter is the key.
Topic archived. No new replies allowed.