Submission
Due Date
By Friday 26 October 2018 23:42
Directory Hierarchy
Create your git repository (replace john.smith by your own login).
$ git clone git@git.cri.epita.net:p/2022-spe-tp/tp03-john.smith
It must contain the following files and directories:
-
pw_03_arrays_sdl/
- AUTHORS
-
arrays/
- This directory will contain code for the first series of exercises (Basic Array Manipulations).
-
sdl/
- This directory will contain code for the second series of exercises (SDL).
Create an AUTHORS
file
that contains the following information.
First Name
Family Name
Login
Email Address
For instance:
John
Smith
john.smith
john.smith@epita.fr
Be careful, if you do not follow all the given instructions, no point will be given to your answers.
Basic Array Manipulations
Provided Code
Two helper files are provided. They are common to all exercises. Other specific files will be given in due time.
The first provided file is a header, which contains some useful functions for testing.
/* Tools for testing array functions */
# ifndef EPITA_IP_ARRAY_TESTS_TOOLS_H_
# define EPITA_IP_ARRAY_TESTS_TOOLS_H_
/*
* Needed in order to use some POSIX functions
* see feature_test_macros(7)
*/
# define _XOPEN_SOURCE 500
# include <stdio.h>
# include <stdlib.h>
/*
* helper functions (array fill, display ... )
* all functions are statically inlined, no links dependencies
*/
/*
* array_random_fill(array, len, maxval): fill array with random values
* maxval is the maximum random value
*/
static inline
void array_random_fill(int array[], size_t len, int maxval)
{
for (size_t i = 0; i < len; ++i)
array[i] = random() % maxval;
}
/*
* array_sorted_fill(array, len, step): fill array with sorted value
* step is the difference between values
*/
static inline
void array_sorted_fill(int array[], size_t len, int step)
{
int cur = 0;
for (size_t i = 0; i < len; ++i, cur += step)
array[i] = cur;
}
/*
* array_reverse_sorted_fill(array, len, step): fill array with values in
* reverse order
* step is the difference between values
*/
static inline
void array_reverse_sorted_fill(int array[], size_t len, int step)
{
int cur = (len - 1) * step;
for (size_t i = 0; i < len; ++i, cur -= step)
array[i] = cur;
}
/*
* int_len(int x): number of decimal digit
*/
static inline
int int_len(int x)
{
int len = 0;
for (; x > 0; x /= 10)
len += 1;
return len;
}
/*
* array_print(array, len): print the array
*/
static inline
void array_print(int array[], size_t len, int maxval)
{
int line = 0;
int intlen = int_len(maxval);
for (size_t i = 0; i < len; ++i)
{
if (line > 72)
{
printf("|\n");
line = 0;
}
line += printf("| %*d ", intlen, array[i]);
}
printf("|\n");
}
#define check(C__) ((C__) ? "\x1b[44mOK\x1b[0m" : "\x1b[41mKO\x1b[0m")
# endif /* EPITA_IP_ARRAY_TESTS_TOOLS_H_ */
The second provided file is a simple Makefile.
# Simple Makefile
# Compilers vars
CC=gcc
CPPFLAGS= -MMD
CFLAGS= -Wall -Wextra -std=c99 -O2
LDFLAGS=
LDLIBS=
SRC= array_min_max.c array_searching.c array_sorting.c
DEP= ${SRC:.c=.d}
PRG= ${SRC:.c=}
all: ${PRG}
-include ${DEP}
clean:
rm -f *.o
rm -f ${DEP}
rm -f ${PRG}
# END Makefile
Minimal and Maximal Values
In this section, you will implement the four following functions:
int array_min(int array[], size_t len);
int array_max(int array[], size_t len);
size_t array_min_index(int array[], size_t len);
size_t array_max_index(int array[], size_t len);
-
array_min()
returns the minimal value of an array of size len. -
array_max()
returns the maximal value of an array of size len. -
array_min_index()
returns the index of the minimal value of an array of size len. -
array_max_index()
returns the index of the maximal value of an array of size len.
Complete the following array_min_max.c
file
(replace only the TODO comments by your own code).
Some tests are also provided.
/* array_min_max.c: min and max searching */
# define _XOPEN_SOURCE 500
# include <assert.h>
# include <err.h>
# include <stdio.h>
# include <stdlib.h>
# include "tests_tools.h"
# define MAXVAL 100
# define STEP 10
/*
* In all following functions parameters array and len are defined as:
* array: an integer array
* len: the length of the array, must be greater than 0
*/
/*
* min and max value
*/
/*
* array_min(array, len): returns min value of array
*/
int array_min(int array[], size_t len)
{
// TODO
}
/*
* array_max(array, len): returns max value of array
*/
int array_max(int array[], size_t len)
{
// TODO
}
/*
* min and max index
*/
/*
* array_min_index(array, len): returns the index of the min value of array
*/
size_t array_min_index(int array[], size_t len)
{
// TODO
}
/*
* array_max_index(array, len): returns the index of the max value of array
*/
size_t array_max_index(int array[], size_t len)
{
// TODO
}
/*
* Tests
*/
/*
* Test functions
*/
/*
* min value tests
*/
void test_min(int array[], size_t len)
{
int min;
printf("*** Test min value search ***\n");
printf("**** Sorted array ****\n");
array_sorted_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
min = array_min(array, len);
printf(" array_min: %d\t(should be %d)\n", min, array[0]);
printf("**** Reverse sorted array ****\n");
array_reverse_sorted_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
min = array_min(array, len);
printf(" array_min: %d\t(should be %d)\n", min, array[len - 1]);
printf("**** Random array ****\n");
array_random_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
min = array_min(array, len);
printf(" array_min: %d\n", min);
}
/*
* max value tests
*/
void test_max(int array[], size_t len)
{
int max;
printf("*** Test max value search ***\n");
printf("**** Sorted array ****\n");
array_sorted_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
max = array_max(array, len);
printf(" array_max: %d\t(should be %d)\n", max, array[len - 1]);
printf("**** Reverse sorted array ****\n");
array_reverse_sorted_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
max = array_max(array, len);
printf(" array_max: %d\t(should be %d)\n", max, array[0]);
printf("**** Random array ****\n");
array_random_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
max = array_max(array, len);
printf(" array_max: %d\n", max);
}
/*
* min index test
*/
void test_min_index(int array[], size_t len)
{
size_t min;
printf("*** Test min value index search ***\n");
printf("**** Sorted array ****\n");
array_sorted_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
min = array_min_index(array, len);
printf(" array_min_index: array[%zu] = %d\n", min, array[min]);
printf("**** Reverse sorted array ****\n");
array_reverse_sorted_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
min = array_min_index(array, len);
printf(" array_min_index: array[%zu] = %d\n", min, array[min]);
printf("**** Random array ****\n");
array_random_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
min = array_min_index(array, len);
printf(" array_min_index: array[%zu] = %d\n", min, array[min]);
}
/*
* max index test
*/
void test_max_index(int array[], size_t len)
{
size_t max;
printf("*** Test max value index search ***\n");
printf("**** Sorted array ****\n");
array_sorted_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
max = array_max_index(array, len);
printf(" array_max_index: array[%zu] = %d\n", max, array[max]);
printf("**** Reverse sorted array ****\n");
array_reverse_sorted_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
max = array_max_index(array, len);
printf(" array_max_index: array[%zu] = %d\n", max, array[max]);
printf("**** Random array ****\n");
array_random_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
max = array_max_index(array, len);
printf(" array_max_index: array[%zu] = %d\n", max, array[max]);
}
/*
* main
*/
int main(int argc, char *argv[])
{
size_t len;
if (argc < 2)
errx(1, "must provide array length");
len = strtoul(argv[1], NULL, 10);
int *array = calloc(len, sizeof (int));
test_min(array, len);
printf("\n");
test_max(array, len);
printf("\n");
test_min_index(array, len);
printf("\n");
test_max_index(array, len);
printf("\n");
free(array);
return 0;
}
Finally, you can compile and test your code with the following commands:
$ make array_min_max gc
c -Wall -Wextra -std=c99 -O2 -MMD array_min_max.c tests_tools.h -o array_min_max $ ./array_min_max 10 # ...snip...
Searching
In this section, you will implement the two following functions:
size_t array_find(int array[], size_t len, int x);
size_t array_bin_search(int array[], size_t len, int x);
-
array_find()
returns the index of an x value if this value is in the given array. Otherwise, it returns len. -
array_bin_search()
returns the index of an x value if this value is in the given sorted array. Otherwise, it returns the expected index of x. This function must implement a binary search algorithm.
The binary search algorithm is as follows (you should already know it):
bin_search(array, left, right, x):
if left == right:
return right
mid = left + (right - left) / 2
if array[mid] == x:
return mid
if x < array[mid]:
return bin_search(array, left, mid, x)
else:
return bin_search(array, mid + 1, right, x)
Of course, you can turn it into a loop. Note also that if x is not in the array, the binary search should return the expected position of x, that is, where x should be inserted if we want to preserve the order of the sorted array.
Complete the following array_searching.c
file
(replace only the TODO comments by your own code).
Some tests are also provided.
/* searching in array */
# define _XOPEN_SOURCE 500
# include <assert.h>
# include <err.h>
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include "tests_tools.h"
# define MAXVAL 100
# define STEP 10
/*
* In all following functions parameters array and len are defined as:
* array: an integer array
* len: the length of the array, must be greater than 0
*/
/*
* searching for value
*/
/*
* array_find(array, len, x): returns the position of x in array or len if not
* present
*/
size_t array_find(int array[], size_t len, int x)
{
// TODO
}
/*
* array_bin_search(array, len, x): search in a sorted array using binary search
* returns the position of x, or the expected position of x if not present
*/
size_t array_bin_search(int array[], size_t len, int x)
{
// TODO
}
/*
* Tests
*/
int array_random_sorted_fill(int array[], size_t len, int maxstep)
{
int cur = 0;
for (size_t i = 0; i < len; ++i)
{
int step = 1 + random() % maxstep;
cur += step;
array[i] = cur;
}
return cur;
}
typedef size_t (*search_fun)(int *, size_t, int);
static inline
void search_help(search_fun fun, int array[], size_t len, int x)
{
printf(" searching %d: ", x);
size_t i = fun(array, len, x);
if (i < len)
printf("array[%zu] = %d\n", i, array[i]);
else
printf("not found (%zu)\n", i);
}
static
void test_search(int array[], size_t len)
{
int x;
printf("*** Test value search ***\n");
printf("**** Sorted array ****\n");
array_sorted_fill(array, len, STEP);
array_print(array, len, (len - 1) * STEP);
x = array[0];
search_help(array_find, array, len, x);
x = array[len - 1];
search_help(array_find, array, len, x);
x = array[random() % len];
search_help(array_find, array, len, x);
x = len * STEP;
search_help(array_find, array, len, x);
printf("**** Reverse sorted array ****\n");
array_reverse_sorted_fill(array, len, STEP);
array_print(array, len, (len - 1) * STEP);
x = array[0];
search_help(array_find, array, len, x);
x = array[len - 1];
search_help(array_find, array, len, x);
x = array[random() % len];
search_help(array_find, array, len, x);
x = len * STEP;
search_help(array_find, array, len, x);
printf("**** Random array ****\n");
array_random_fill(array, len, MAXVAL);
array_print(array, len, MAXVAL);
x = array[0];
search_help(array_find, array, len, x);
x = array[len - 1];
search_help(array_find, array, len, x);
x = array[random() % len];
search_help(array_find, array, len, x);
x = random() % (MAXVAL * 2);
search_help(array_find, array, len, x);
}
static
void test_bin_search(int array[], size_t len)
{
int x;
printf("*** Test value binary search ***\n");
printf(" founded index may not contain searched value\n");
printf("**** Basic sorted array ****\n");
array_sorted_fill(array, len, STEP);
array_print(array, len, (len - 1) * STEP);
x = array[0];
search_help(array_bin_search, array, len, x);
x = array[len - 1];
search_help(array_bin_search, array, len, x);
x = array[random() % len];
search_help(array_bin_search, array, len, x);
x = len * STEP;
search_help(array_bin_search, array, len, x);
printf("**** Basic sorted array ****\n");
int maxval = array_random_sorted_fill(array, len, STEP);
array_print(array, len, maxval);
x = array[0];
search_help(array_bin_search, array, len, x);
x = array[len - 1];
search_help(array_bin_search, array, len, x);
x = array[random() % len];
search_help(array_bin_search, array, len, x);
x = random() % (maxval * 2);
search_help(array_bin_search, array, len, x);
}
/*
* main
*/
int main(int argc, char *argv[])
{
srandom(time(NULL));
size_t len;
if (argc < 2)
errx(1, "must provide array length");
len = strtoul(argv[1], NULL, 10);
int *array = calloc(len, sizeof (int));
test_search(array, len);
printf("\n");
test_bin_search(array, len);
printf("\n");
free(array);
return 0;
}
Finally, you can compile and test your code with the following commands:
$ make array_searching gc
c -Wall -Wextra -std=c99 -O2 -MMD array_searching.c tests_tools.h -o array_searching $ ./array_searching 10 # ...snip...
Sorting
In this section, you will implement a selection sort algorithm:
select_sort(array, len):
for i in range(len):
# find min index in array between i and len
min = array_min(array[i:len])
swap(array[i], array[min])
As you can see, we need a function
that finds the index of the minimal value in an array
(we've already done it!) and a function for swapping array cells.
We also want a function that checks if an array is sorted (for tests).
For the index of the minimal value, you are free to reuse your code
(you can call your function shifted by i with
array_min_index(array+i, len-i)
but beware of shifting the resulting index by i again)
or write a specific version or simply include the code in the sort function.
Therefore, you have to write the three following functions:
int array_is_sorted(int array[], size_t len);
void array_swap(int array[], size_t i, size_t j);
void array_select_sort(int array[], size_t len);
-
is_sorted()
returns true (not 0) if the given array is sorted in increasing order. -
array_swap()
swaps the i and j cells of the given array. -
array_select_sort()
sorts the given array by using the select sort algorithm.
To do so, complete the following array_sorting.c
file
(replace only the TODO comments by your own code).
Some tests are also provided.
/* array_sorting.c : sorting arrays */
# define _XOPEN_SOURCE 500
# include <assert.h>
# include <err.h>
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include "tests_tools.h"
# define MAXVAL 100
# define STEP 10
/*
* In all following functions parameters array and len are defined as:
* array: an integer array
* len: the length of the array, must be greater than 0
*/
/* tools for sorting */
/*
* array_is_sorted(array, len): returns true if array is sorted in increasing
* order
*/
int array_is_sorted(int array[], size_t len)
{
// TODO
}
/*
* array_swap(array, i, j): swap cell value at position i and j
*/
void array_swap(int array[], size_t i, size_t j)
{
// TODO
}
/* Selection sort */
/*
* array_select_sort(array, len): sort array using select sort
*/
void array_select_sort(int array[], size_t len)
{
// TODO
}
/*
* Tests
*/
static inline
double time_gdiff(struct timespec t0, struct timespec t1)
{
double s = t1.tv_sec - t0.tv_sec;
s += (t1.tv_nsec - t0.tv_nsec) * 1e-9;
return s;
}
static inline
void sort_help(int array[], size_t len, int maxval)
{
struct timespec t0, t1;
printf("Array before sort:\n");
array_print(array, len, maxval);
printf(" ... sorting ...\n");
clock_gettime(CLOCK_MONOTONIC, &t0);
array_select_sort(array, len);
clock_gettime(CLOCK_MONOTONIC, &t1);
printf("Array after sort:\n");
array_print(array, len, maxval);
printf(" time for sorting: %gs\n", time_gdiff(t0, t1));
printf(" sort check: %s\n", check(array_is_sorted(array, len)));
}
void test_sorting(int array[], size_t len)
{
printf("*** Sorted array ***\n");
array_sorted_fill(array, len, STEP);
sort_help(array, len, STEP * (len - 1));
printf("\n*** Reverse sorted array ***\n");
array_reverse_sorted_fill(array, len, STEP);
sort_help(array, len, STEP * (len - 1));
printf("\n*** Random array ***\n");
array_random_fill(array, len, MAXVAL);
sort_help(array, len, MAXVAL);
}
/*
* main
*/
int main(int argc, char *argv[])
{
srandom(time(NULL));
size_t len;
if (argc < 2)
errx(1, "must provide array length");
len = strtoul(argv[1], NULL, 10);
int *array = calloc(len, sizeof (int));
test_sorting(array, len);
printf("\n");
free(array);
return 0;
}
Finally, you can compile and test your code with the following commands:
$ make array_sorting gc
c -Wall -Wextra -std=c99 -O2 -MMD array_sorting.c -o array_sorting $ ./array_sorting 10 # ...snip...
Simple DirectMedia Layer (SDL)
Checking Libraries
First, you have to check that you have all the libraries you need.
The pkg-config
command gives the compiler options.
Execute the commands below and check that you have the same results
(the ls
command prints
the installation paths of the library).
$ pkg-config --cflags sdl
-D_GNU_SOURCE=1 -D_REENTRANT -I/usr/include/SDL
$ ls /usr/include/SDL/SDL.h /usr/include/SDL/SDL_image.h
/usr/include/SDL/SDL.h /usr/include/SDL/SDL_image.h
Makefile
The following Makefile
is provided:
# Simple SDL mini Makefile
CC=gcc
CPPFLAGS= `pkg-config --cflags sdl` -MMD
CFLAGS= -Wall -Wextra -Werror -std=c99 -O3
LDFLAGS=
LDLIBS= `pkg-config --libs sdl` -lSDL_image
all: display grayscale
display: display.o
grayscale: pixel_operations.o grayscale.o
grayscale.o: pixel_operations.h
clean:
${RM} *.o
${RM} *.d
${RM} display
${RM} grayscale
# END
Displaying an Image
You will display an image by using the SDL.
To do so, you have to:
- Initialize the SDL.
- Load an image from a file.
- Display the image.
- Wait for a key to be pressed.
- Free the allocated memory used for loading and displaying the image.
Some parts of this code is not really interesting. So, some commented functions are given.
Initializing the SDL:
void init_sdl()
{
// Init only the video part.
// If it fails, die with an error message.
if(SDL_Init(SDL_INIT_VIDEO) == -1)
errx(1,"Could not initialize SDL: %s.\n", SDL_GetError());
}
Loading an image from a file:
SDL_Surface* load_image(char *path)
{
SDL_Surface *img;
// Load an image using SDL_image with format detection.
// If it fails, die with an error message.
img = IMG_Load(path);
if (!img)
errx(3, "can't load %s: %s", path, IMG_GetError());
return img;
}
Displaying an image:
SDL_Surface* display_image(SDL_Surface *img)
{
SDL_Surface *screen;
// Set the window to the same size as the image
screen = SDL_SetVideoMode(img->w, img->h, 0, SDL_SWSURFACE|SDL_ANYFORMAT);
if (screen == NULL)
{
// error management
errx(1, "Couldn't set %dx%d video mode: %s\n",
img->w, img->h, SDL_GetError());
}
// Blit onto the screen surface
if(SDL_BlitSurface(img, NULL, screen, NULL) < 0)
warnx("BlitSurface error: %s\n", SDL_GetError());
// Update the screen
SDL_UpdateRect(screen, 0, 0, img->w, img->h);
// return the screen for further uses
return screen;
}
Waiting for a key to be pressed.
void wait_for_keypressed()
{
SDL_Event event;
// Wait for a key to be down.
do
{
SDL_PollEvent(&event);
} while(event.type != SDL_KEYDOWN);
// Wait for a key to be up.
do
{
SDL_PollEvent(&event);
} while(event.type != SDL_KEYUP);
}
To free the allocated memory, just use the following SDL function.
void SDL_FreeSurface(SDL_Surface *surface);
Be careful, two surfaces will be created.
-
The surface when you load the image
(returned by
load_image()
). -
The surface when you display the image
(returned by
display_image()
).
So they both must be freed.
Finally, complete the display.c
file below
(replace the TODO comments only).
Two pointers are used for the surface variables,
but do not worry, you do not have to know what a pointer is
to do or to understand this practical.
For now, consider that pointers are just simple variables
(and technically, they are).
We will see them in details later on.
#include <err.h>
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
// TODO: Insert all the above functions.
int main()
{
SDL_Surface* image_surface;
SDL_Surface* screen_surface;
// TODO: Initialize the SDL
image_surface = load_image("my_image.jpg");
// TODO: Display the image.
// TODO: Wait for a key to be pressed.
// TODO: Free the image surface.
// TODO: Free the screen surface.
return 0;
}
You can compile and run your code by typing the following commands. Do not forget to put an image in the same folder as your executable file.
$ make display gc
c -Wall -Wextra -Werror -std=c99 -O3 `pk
g-config --cflags sdl` -MMD -c -o display.o display.c gc
c display.o `pk
g-config --libs sdl` -lSDL_image -o display $ ./display
Converting into Grayscale
Now that you can display an image, you are going to convert it into grayscale.
First, copy the display.c
file
to the grayscale.c
file.
$ cp display.c grayscale.c
From now on, you will modify the
grayscale.c
file only.
The two following files are given.
#ifndef PIXEL_OPERATIONS_H_
#define PIXEL_OPERATIONS_H_
#include <stdlib.h>
#include <SDL.h>
Uint32 get_pixel(SDL_Surface *surface, unsigned x, unsigned y);
void put_pixel(SDL_Surface *surface, unsigned x, unsigned y, Uint32 pixel);
void update_surface(SDL_Surface* screen, SDL_Surface* image);
#endif
// Simple get/put pixel for SDL
// Inspired by code from SDL documentation
// (http://www.libsdl.org/release/SDL-1.2.15/docs/html/guidevideo.html)
#include <err.h>
#include "pixel_operations.h"
static inline
Uint8* pixel_ref(SDL_Surface *surf, unsigned x, unsigned y)
{
int bpp = surf->format->BytesPerPixel;
return (Uint8*)surf->pixels + y * surf->pitch + x * bpp;
}
Uint32 get_pixel(SDL_Surface *surface, unsigned x, unsigned y)
{
Uint8 *p = pixel_ref(surface, x, y);
switch (surface->format->BytesPerPixel)
{
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32 *)p;
}
return 0;
}
void put_pixel(SDL_Surface *surface, unsigned x, unsigned y, Uint32 pixel)
{
Uint8 *p = pixel_ref(surface, x, y);
switch(surface->format->BytesPerPixel)
{
case 1:
*p = pixel;
break;
case 2:
*(Uint16 *)p = pixel;
break;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
{
p[0] = (pixel >> 16) & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = pixel & 0xff;
}
else
{
p[0] = pixel & 0xff;
p[1] = (pixel >> 8) & 0xff;
p[2] = (pixel >> 16) & 0xff;
}
break;
case 4:
*(Uint32 *)p = pixel;
break;
}
}
void update_surface(SDL_Surface* screen, SDL_Surface* image)
{
if (SDL_BlitSurface(image, NULL, screen, NULL) < 0)
warnx("BlitSurface error: %s\n", SDL_GetError());
SDL_UpdateRect(screen, 0, 0, image->w, image->h);
}
You do not have to understand the contents of these files. You just have to know how to use their functions.
Here are some examples that can be helpful.
If the coordinates of a pixel
are x and y,
you can get its value by using the
get_pixel()
function.
Uint32 pixel = get_pixel(image_surface, x, y);
If the coordinates of a pixel
are x and y,
you can set its value by using the
put_pixel()
function.
put_pixel(image_surface, x, y, pixel);
To get the RGB values of a pixel in the r, g, b variables, you can use the following instructions:
Uint8 r, g, b;
SDL_GetRGB(pixel, image_surface->format, &r, &g, &b);
To get a pixel value from RGB values you can use the following instruction:
Uint32 pixel = SDL_MapRGB(image_surface->format, r, g, b);
To get the width of your image, you can use the the following instruction:
int width = image_surface->w;
To get the height of your image, you can use the following instruction:
int height = image_surface->h;
To redraw the surfaces:
update_surface(screen_image, surface_image);
So now, rewrite the main function in the grayscale.c
file.
Do not modify the display.c
file.
You also have to include the pixel_operations.h
file.
Your main function should follow the following steps:
- Display the image.
- Wait for a key to be pressed.
- For each pixel of the image:
- Get the pixel value.
- Get the RGB values of the pixel.
-
Compute the weighted average of the RGB values:
average = 0.3*r + 0.59*g + 0.11*b
-
Update the RGB values by using this average
(
r = g = b = average
). - Get the new pixel value from the new RGB values.
- Put the new pixel value on the surface.
- Redraw the surfaces.
- Wait for a key to be pressed.
- Free the surfaces.
You can compile and run your code by typing the following commands. Do not forget to put an image in the same folder as your executable file.
$ make grayscale gc
c -Wall -Wextra -Werror -std=c99 -O3 `pk
g-config --cflags sdl` -MMD -c -o grayscale.o grayscale.c gc
c -Wall -Wextra -Werror -std=c99 -O3 `pk
g-config --cflags sdl` -MMD -c -o pixel_operations.o pixel_operations.c gc
c grayscale.o pixel_operations.o `pk
g-config --libs sdl` -lSDL_image -o grayscale $ ./grayscale