20171002:Practical:C:SDL:Arrays

De wiki-prog
Aller à : navigation, rechercher

Introduction

This session will introduce some array manipulations and simple image loading and manipulation using the SDL library.

For this session, you must (after setting-up your GIT) create a directory in your GIT repository for tutorials named 20171002_tuto01 with the following architectures:

  • 20171002_tuto01/
    • Arrays/
      • this directory will contains code for the first series of exercises (arrays)
    • SDL/
      • this directory will contains code for the last series of exercises (SDL introduction)

Submission

  • S3: You must have commit and push your code before next monday (the 9th of october) at 2pm.
  • S3#: It is due on Friday, February 23, 2018 at 2pm (this session spans across two weeks).

GIT set-up

In case you still got issues with your GIT set-up check (again) Practical:GIT.

You need GIT in order to submit the code of your tutorial sessions and your project.

Arrays

The following serie of exercises introduces basic array manipulation.

Provided code

We provide some helper code (for testing) in the form of a header (tests_tools.h), a Makefile and for each exercise functions and main for testing.

This part describes the code common to all exercises, specific files will be provided in exercises parts.

/* tests_tools.h */
/* 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_ */
# 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 array

Your goal in this part is to implement the following functions:

/*
 * array_min(array, len): returns min value of array
 */
int array_min(int array[], size_t len);
/*
 * array_max(array, len): returns max value of array
 */
int array_max(int array[], size_t len);
 
/*
 * array_min_index(array, len): returns the index of the min value of array
 */
size_t array_min_index(int array[], size_t len);
 
/*
 * array_max_index(array, len): returns the index of the max value of array
 */
size_t array_max_index(int array[], size_t len);
  • array_min(array, len): find the minimal value of array (of size len) and returns it.
  • array_max(array, len): find the maximal value of array (of size len) and returns it.
  • array_min_index(array, len): find the minimal value of array (of size len) and returns its index.
  • array_max_index(array, len): find the maximal value of array (of size len) and returns its index.

You'll put your code in the file array_min_max.c (look for FIX ME comments) with some provided tests:

/* 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)
{
  // FIX ME
}
 
/*
 * array_max(array, len): returns max value of array
 */
int array_max(int array[], size_t len)
{
  // FIX ME
}
 
/*
 * 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)
{
  // FIX ME
}
 
/*
 * array_max_index(array, len): returns the index of the max value of array
 */
size_t array_max_index(int array[], size_t len)
{
  // FIX ME
}
 
/*
 * 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;
 
}

You can compile and test your code with:

shell> make array_min_max
gcc -fsanitize=address -Wall -Wextra -std=c99 -O2 -MMD   array_min_max.c   -o array_min_max
shell> ./array_min_max 10
...

Searching in an array

For this exercise, you need to implement two searching functions: a basic linear search and a binary search in a sorted array.

Here are the prototype for this functions:

/*
 * 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);
 
/*
 * 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);
  • array_find(array, len, x) returns the position of x in array or len if not present
  • 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

The binary search algorithm (you should know it) works as follow:

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 transform it into a loop … Note also that the binary search should return, if x is not present, the insertion position of x: that is where we should insert it if we want to preserve order in our array.

Like the previous exercise, here is the main file with test code (array_searching.c):

/* 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)
{
 // FIX ME
}
 
/*
 * 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)
{
 // FIX ME
}
 
/*
 * 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;
 
}

Selection sort

We, now, want to implement a selection sort. Select sort works as follow:

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 find 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 check 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 position with: array_min_index(array + i, len - i) but beware that you need to shift the resulting index by i again) or write a specific version or simply include the code in the sort function.

Here are the prototypes for the expected functions:

/*
 * array_is_sorted(array, len): returns true (not 0) if array is sorted in
 * increasing order
 */
int array_is_sorted(int array[], size_t len);
 
/*
 * array_swap(array, i, j): swap cell value at position i and j
 */
void array_swap(int array[], size_t i, size_t j);
 
 
/* Selection sort */
 
/*
 * array_select_sort(array, len): sort array using select sort
 */
void array_select_sort(int array[], size_t len);

And like the other exercises, the code for testing:

/* 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)
{
  // FIX ME
}
 
/*
 * array_swap(array, i, j): swap cell value at position i and j
 */
void array_swap(int array[], size_t i, size_t j)
{
  // FIX ME
}
 
/* Selection sort */
 
/*
 * array_select_sort(array, len): sort array using select sort
 */
void array_select_sort(int array[], size_t len)
{
  // FIX ME
}
 
/*
 * 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;
 
}

Using SDL

Checking for the libs

Check if you got all you need: pkg-config give you option for your compiler, among which you'll find the installation path of the lib. You should get similar input to mine:

> 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

Simple Makefile

Here is a simple Makefile for the exercises using SDL:

## Simple SDL mini code
 
CC=gcc
 
CPPFLAGS= `pkg-config --cflags sdl` -MMD
CFLAGS= -Wall -Wextra -Werror -std=c99 -O3
LDFLAGS=
LDLIBS= `pkg-config --libs sdl` -lSDL_image
 
OBJ= pixel_operations.o main.o
DEP= ${OBJ:.o=.d}
 
all: main
 
main: ${OBJ}
 
clean:
	${RM} ${OBJ} ${DEP} *~
	${RM} main
 
-include ${DEP}
 
# END

Start-up code

First, we need to init SDL, open a window, load an image, display it and wait for a pressed key. This part of the code is not really interesting, I'll just give the code with some comments.

Waiting for a key:

void wait_for_keypressed(void) {
  SDL_Event             event;
  // Infinite loop, waiting for event
  for (;;) {
    // Take an event
    SDL_PollEvent( &event );
    // Switch on event type
    switch (event.type) {
    // Someone pressed a key -> leave the function
    case SDL_KEYDOWN: return;
    default: break;
    }
  // Loop until we got the expected event
  }
}

Initializing SDL:

void init_sdl(void) {
  // Init only the video part
  if( SDL_Init(SDL_INIT_VIDEO)==-1 ) {
    // If it fails, die with an error message
    errx(1,"Could not initialize SDL: %s.\n", SDL_GetError());
  }
  // We don't really need a function for that ...
}

Loading an image from a file:

SDL_Surface* load_image(char *path) {
  SDL_Surface          *img;
  // Load an image using SDL_image with format detection
  img = IMG_Load(path);
  if (!img)
    // If it fails, die with an error message
    errx(3, "can't load %s: %s", path, IMG_GetError());
  return img;
}

Now, we can write a function that take the surface corresponding to a loaded image and open a window with the same dimension, display the image on it and wait for a key:

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);
 
  // wait for a key
  wait_for_keypressed();
 
  // return the screen for further uses
  return screen;
}

Once you're finished with your image, you should free it using SDL_FreeSurface().

  • Put everything into a file main.c add the headers SDL/SDL.h and SDL/SDL_image.h and write the main function.

Pixel operations

These functions, derived from SDL documentation, are used to get a pixel value or to set it in a surface. They manage all image formats and return a unified type for a pixel that can be used with SDL_GetRGB and SDL_MapRGB to map the pixel to RGB component.

First, the header:

// pixel_operations.h
 
# ifndef PIXEL_OPERATIONS_H_
# define PIXEL_OPERATIONS_H_
 
# include <stdlib.h>
# include <SDL.h>
 
Uint32 getpixel(SDL_Surface *surface, unsigned x, unsigned y);
void putpixel(SDL_Surface *surface, unsigned x, unsigned y, Uint32 pixel);
 
# endif

Then the code:

// pixel_operations.c
 
// 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 "pixel_operations.h"
 
static inline
Uint8* pixelref(SDL_Surface *surf, unsigned x, unsigned y) {
  int bpp = surf->format->BytesPerPixel;
  return (Uint8*)surf->pixels + y * surf->pitch + x * bpp;
}
 
Uint32 getpixel(SDL_Surface *surface, unsigned x, unsigned y) {
  Uint8 *p = pixelref(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 putpixel(SDL_Surface *surface, unsigned x, unsigned y, Uint32 pixel) {
  Uint8 *p = pixelref(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;
  }
}

Converting an image to grey level

As an application will now iterate over the image in order to transform it into a grey image. Our conversion will use one of the classical conversion based on luminance definition. The basic version compute the average of the RGB components and then set all component to this value. While this is supposed to be correct, human perception of colors are slightly different: green appears brighter than red which is also brighter than blue. Thus, we'll compute a pondered average using the following coefficient: 0.3 for red, 0.59 for green and 0.11 for blue.

In order to convert the image you first need to be able to convert a given pixel:

  • from the Uint32 pixel value, you can obtain three Uint8 value using SDL_GetRGB(pixel, img->format, &r, &g, &b) where pixel is the pixel value, img is the surface corresponding to your image and r, g, b are three Uint8 variable that will contains the RGB components.
  • Using the previous coefficients compute the average value for the luminance (using a floating point variable to store the result)
  • Set r, g, b to the luminance
  • Get the new pixel value with SDL_MapRGB(img->format, r, g, b)

Once ready, you need to iterate over the pixel of the image: the surface provides img->w which is the width of the image and img->h which the height, just need a double for loop, the get and put pixel operations and this is it.

  • Extend the previous code (in main.c) so that after displaying the original image, it transforms the surface in grey level and blit it (take a look at the provided code) to the screen once again, then wait for a key and leave.