Code Vonc

HurtelVisio

v 1.0

Win

TéléchargerDownload
Faire un donMake a donation
CommentairesComments
Le programme HurtelVisio permet de charger une image Windows Bitmap (BMP) ou Truevision Targa (TGA), d'y appliquer et enregistrer des modifications.

Exercice sur la lecture de fichiers et le traitement d'images.

Projet réalisé avec Marion Hurteau.




Manuel d'utilisation
HurtelVisio
Sommaire
Description de l'interface Formats supportés Ouverture d'un fichier Enregistrement d'un fichier Filtres graphiques Luminosité Contraste Inversion des couleurs Niveau de gris Réinitialisation Corrections de l'image Largeur & Hauteur Rogner Rotation Miroir Modes de fusion Superposition Alpha Addition Soustraction Éclaircir Obscurcir Produit Lumière Densité linéaire +
Description de l'interface
Formats supportés

HurtelVisio supporte les fonctionnalités principales des formats d'image Windows Bitmap (.BMP) et Truevision Targa (.TGA) à l'ouverture et à l'enregistrement.

Ouverture d'un fichier

La lecture d'une image s'effectue avec le bouton Ouvrir, affichant une boîte de dialogue permettant de sélectionner le fichier à ouvrir.

Windows Bitmap (*.BMP) Version 2, 3 et 4

La lecture du format Windows Bitmap prend en compte trois types de profondeurs :

32 bits par pixels

Rouge, vert, bleu, alpha, chaque composante est codée sur 8 bits.

24 bits par pixels

Rouge, vert, bleu, chaque composante est codée sur 8 bits.

8 bits par pixels

Une palette de 256 couleurs maximum 24 ou 32 bits accompagne l'image. Chaque pixel charge une valeur indexée dans la palette.

Truevision Targa (*.TGA)

La lecture du format Truevision Targa prend en compte quatre types de profondeurs et une éventuelle compression de type RLE.

32 bits par pixels

Rouge, vert, bleu, alpha, chaque composante est codée sur 8 bits.

24 bits par pixels

Rouge, vert, bleu, chaque composante est codée sur 8 bits.

16 bits par pixels

Rouge, vert, bleu, chaque composante est codée sur 5 bits.

8 bits par pixels

Une palette de 256 couleurs maximum 24 ou 32 bits accompagne l'image. Chaque pixel charge une valeur indexée dans la palette.

Compression RLE

Les pixels identiques qui se suivent de gauche à droite ne sont écrits qu'une fois.

Enregistrement d'un fichier

L'enregistrement d'une image prend en compte les modifications apportées à celle-ci et s'effectue avec le bouton Enregistrer, ouvrant une boîte de dialogue indiquant l'emplacement à choisir pour enregistrer le fichier au format désiré.

Windows Bitmap (*.BMP) Version 3

L'enregistrement du format Windows Bitmap prend en compte deux types de profondeurs :

32 bits par pixels

Rouge, vert, bleu, alpha, chaque composante est codée sur 8 bits.

24 bits par pixels

Rouge, vert, bleu, chaque composante est codée sur 8 bits.

Truevision Targa (*.TGA)

L'enregistrement du format Truevision Targa prend en compte trois types de profondeurs et une éventuelle compression de type RLE.

32 bits par pixels

Rouge, vert, bleu, alpha, chaque composante est codée sur 8 bits.

24 bits par pixels

Rouge, vert, bleu, chaque composante est codée sur 8 bits.
Note : une perte du canal alpha s'effectuera si l'image d'origine a une profondeur de 32 bits.

16 bits par pixels

Rouge, vert, bleu, chaque composante est codée sur 5 bits.
Note : une perte d'information et donc de qualité s'effectuera si l'image d'origine a une profondeur supérieure à 16 bits.

Compression RLE

Les pixels identiques qui se suivent de gauche à droite ne sont écrits qu'une fois.
Note : la compression RLE n'a d'intérêt que si l'image comporte des aplats de couleurs fréquents, le fichier enregistré sera plus léger et sans perte d'information.

Filtres graphiques

HurtelVisio propose plusieurs filtres graphiques superposables modifiant l'apparence de l'image.

Luminosité

Cliquez sur le + pour tendre l'image vers le blanc, sur le - pour la tendre vers le noir. Cliquez sur le point noir pour réinitialiser la luminosité.

Contraste

Cliquez sur le + pour augmenter le contraste de l'image, sur le - pour le baisser et tendre l'image vers le gris.
Cliquez sur le point noir pour réinitialiser le contraste.

Inversion des couleurs

Cliquez sur le bouton Inverser les couleurs pour inverser les couleurs de l'image.
Ou utilisez la touche de raccourci clavier I.

Niveau de gris

Cliquez sur le bouton Niveau de gris pour passer l'image en niveau de gris.
Ou utilisez la touche de raccourci clavier N.

Réinitialisation

Cliquez sur Reset pour réinitialiser les filtres graphiques. Cela a pour effet de recharger l'image.

Correction de l'image

HurtelVisio propose des outils de correction permettant de modifier la taille et l'orientation de l'image.

Largeur & Hauteur

Cliquez sur le + et le - pour ajuster la largeur et la hauteur de l'image. Le redimensionnement ré-échantillonne les pixels.

Rogner

Cliquez sur + (ou la touche du clavier R) pour activer l'outil de rognage. Cliquez-glissez ensuite sur l'image pour définir la zone de recadrage. Le recadrage sera appliqué à l'image à l'enregistrement du fichier, cela permet de réajuster la zone si besoin.
Recliquez sur + (ou la touche du clavier R) pour désactiver l'outil de rognage.

Rotation

Cliquez sur les flèches correspondantes pour pivoter l'image de 90° à gauche ou à droite.

Miroir

Applique une symétrie horizontale ou verticale de l'image.

Modes de fusion

Différents types de fusion d'images sont disponibles. Cliquez sur Fusionner pour charger une image à fusionner et ouvrir le menu des Fusions. Cliquez sur OK pour valider la fusion, Sans pour la désactiver.

Superposition

Calcule la moyenne de chaque pixels des deux images A et B.

Alpha

Incruste l'image B selon sa couche Alpha (sa transparence) sur l'image A.

Addition

Additionne les valeurs RVB des deux images A et B.

Soustraction

Soustrait les valeurs RVB de l'image B à l'image A.

Éclaircir

Transpose les pixels plus clairs de l'image B à l'image A.

Obscurcir

Transpose les pixels plus sombres de l'image B à l'image A.

Produit

Multiplie l'image A à l'image B divisé par 255.

Lumière

Soustrait 255 à l'image A multipliée par l'image B.

Densité linéaire +

Soustrait l'image B par l'inverse de l'image A.



Structure du programme


HurtelVisio utilise la bibliothèque SDL 2.0 pour la gestion des fenêtres et des évènements de la souris.

Le programme est constitué de la manière suivante :
• Une Image d'Origine contenant l'image chargée.
• Une Image Modifiée contenant les modifications de l'Image d'Origine.
• Une Image Fusion contenant l'image à fusionner à l'Image Modifiée.
• Une fenêtre affichant le menu.
• Une fenêtre affichant l'Image Modifiée.
• Une fenêtre affichant l'éventuelle palette de couleur de l'image.

Schéma fonctionnel :
	- Création et initialisation des fenêtres
	- Récupération des évènements souris du menu
		- Application des fonctionnalités non destructives sur l'Image d'Origine
			- Chargement
				- Ouverture dans l'Image d'Origine
			- Enregistrement
				- Application du rognage
				- Enregistrement de l'Image Modifiée
			- Réinitialisation des outils
			- Rotation
			- Miroir
			- Inversion des couleurs
			- Prévisualisation du rognage
		- Copie de l'Image d'Origine dans l'Image Modifiée
		- Application des fonctionnalités destructives sur l'Image Modifiée
			- Luminosité / Contraste
			- Niveau de gris
			- Chargement de l'Image à fusionner et application de la fusion
		- Affichage de l'Image Modifiée
	- Libération de la mémoire et fermeture des fenêtres



Codes sourcesSources code

fonctions.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <windows.h>
#include "prototypes.h"
#include <string.h>

void urlToExt(char* url, char* ext) {
    // Récup l'extension ou NULL du fichier à partir d'un lien
    char* pos = strrchr(url, '.');
    if (pos != NULL) strcpy(ext, pos+1);
    else ext[0] = '\0';
}

void urlToName(char* url, char* name) {
    // Récup le nom du fichier à partir d'un lien
    char* pos = strrchr(url, '\\');
    if (pos != NULL) strcpy(name, pos+1);
    else strcpy(name, url);
}

void urlToDir(char* url, char* dir) {
    // Récup le réperoire à partir d'un lien
    char* pos = strrchr(url, '\\');
    if (pos != NULL) {
        strncpy(dir, url, pos - url + 1);
        dir[pos - url + 1] = '\0';
    }
    else strcpy(dir, url);
}

void clearCM(Uint8* pixels) {
    if (pixels == NULL) return;
    int i;
    for (i = 0 ; i < 16 * 16 * 4 ; i++) {
         pixels[i] = 0;
    }
}

// Fonctions structure Image

int initImage(Image* image, char* title, int x, int y, int w, int h, Uint32 flags, int render) {

    image->window = NULL;
    image->renderer = NULL;
    image->pixels = NULL;
    image->width = 0;
    image->height = 0;
    image->bpp = 24;
    image->rle = 0;
    image->id = -1;

    if (title != NULL) { // Si titre, créer la fenêtre
        image->window = SDL_CreateWindow(title, x, y, w, h, flags);
        if (image->window == NULL) return 0; // Échec

        image->id = SDL_GetWindowID(image->window); // Récupère l'ID

        if (render) { // Si 1, créer le Renderer
            image->renderer = SDL_CreateRenderer(image->window, -1, SDL_RENDERER_ACCELERATED);
            if (image->renderer == NULL) return 0; // Échec
        }
    }

    return 1; // RAS
}

int initTabImage(Image* image, int q) {
    if (image->pixels == NULL) image->pixels = malloc(q);
    if (image->pixels == NULL) return 0;
    return 1;
}

void clearImage(Image* image) {
    if (image->pixels) free(image->pixels);
    if (image->window) SDL_DestroyWindow(image->window);
    if (image->renderer) SDL_DestroyRenderer(image->renderer);
}

//

void save(char* url) {
    // Boîte de dialogue Enregistrer Sous
    OPENFILENAME ofn;
    int res, extid;
    char name[1024];
    char ext[10];
    char exturl[10];
    urlToName(url, name);
    url[0] = '\0';

    ZeroMemory(&ofn, sizeof(OPENFILENAMEW));
    ofn.lStructSize = sizeof(OPENFILENAMEW);
    ofn.nMaxFileTitle = 1024;
    ofn.nMaxFile = 1024;
    ofn.lpstrFileTitle = name;
    ofn.lpstrFile = url;
    ofn.lpstrFilter = "Truevision Targa (*.TGA)\0*.TGA\0Windows Bitmap (*.BMP)\0*.BMP\0";

    res = GetSaveFileName(&ofn);
    if (!res) {
        url[0] = '\0';
    }
    else {
        // Ajoute l'extension si absente
        extid = ofn.nFilterIndex;
        urlToExt(url, exturl);
        switch (extid) {
            case 1 : strcpy(ext, "tga"); break;
            case 2 : strcpy(ext, "bmp"); break;
        }
        if (strcmpi(exturl, ext) != 0) {
            strcat(url, ".");
            strcat(url, ext);
        }
    }
}

void my_open(char* url) {
    // Boîte de dialogue Ouvrir
    OPENFILENAME ofn;
    int res;
    url[0] = '\0';

    ZeroMemory(&ofn, sizeof(OPENFILENAMEW));
    ofn.lStructSize = sizeof(OPENFILENAMEW);
    ofn.lpstrFile = url;
    ofn.nMaxFile = 1024;
    ofn.lpstrFilter = "Fichier image (*.TGA, *.BMP)\0*.TGA;*.BMP\0Truevision Targa (*.TGA)\0*.TGA\0Windows Bitmap (*.BMP)\0*.BMP\0Tous (*.*)\0*.*\0";

    res = GetOpenFileName(&ofn);
    if (!res) url[0] = '\0';
}

long ficSize(FILE* fic) {
    // Récupère la taille du fichier
    long size;
    fseek(fic, 0, SEEK_END);
    size = ftell(fic);
    fseek(fic, 0, SEEK_SET);
    return size;
}

int checkBytesOK(FILE* fic, long ficsize, long n) {
    // Vérifie si n octets peuvent être lus
    long pos = ftell(fic) + n;
    if (pos <= ficsize) return 1;
    return 0;
}

void renameWindow(Image* image, char* url) {
    if (!image || !image->window) return;
    if (url == NULL) return;
    char name[1024];
    urlToName(url, name); // Récupère le nom
    SDL_SetWindowTitle(image->window, name);
}

void loading(Image* imageO, Image* imageCM, char* url, int force) {
    // Chargement
    FILE* fic = NULL;
    char ext[10];
    char urlTmp[1024];
    long ficsize;

    strcpy(urlTmp, url);
    if (!force) my_open(url); // Boîte de dialogue
    if (url[0] == '\0') {
        strcpy(url, urlTmp);
        return;
    }

    fic = fopen(url, "rb");
    if (fic == NULL) return;

    urlToExt(url, ext); // Récupère l'extension

    ficsize = ficSize(fic); // Récupère la taille du fichier

    if (imageO->pixels) { free(imageO->pixels); imageO->pixels = NULL; } // Si pixels, vire les pixels

    if (!stricmp(ext, "tga"))
        loadTGA(fic, ficsize, imageO, imageCM);
    else if (!stricmp(ext, "bmp"))
        loadBMP(fic, ficsize, imageO, imageCM);

    fclose(fic);
}

void saving(Image* imageM, Image* imageCM, char* url, Params *params) {
    // Sauvegarde
    if (imageM->pixels == NULL) return;

    FILE* fic = NULL;
    char ext[10];
    char urlTmp[1024];

    strcpy(urlTmp, url);
    save(url);
    if (url[0] == '\0') { strcpy(url, urlTmp); return; }

    urlToExt(url, ext);
    if (ext == NULL) return;

    // Options
    if (!stricmp(ext, "tga")) {
        if (!displayMenu(1, imageM, params, NULL, NULL, NULL, NULL)) { strcpy(url, urlTmp); return; }
    }
    else if (!stricmp(ext, "bmp")) {
        if (!displayMenu(0, imageM, params, NULL, NULL, NULL, NULL)) { strcpy(url, urlTmp); return; }
    }

    // Enregistrement
    fic = fopen(url, "wb");
    if (fic == NULL) return;

    rogneApply(imageM, params->rogne);

    if (!stricmp(ext, "tga"))
        saveTGA(fic, imageM, imageCM);
    else if (!stricmp(ext, "bmp"))
        saveBMP(fic, imageM, imageCM);

    fclose(fic);
}

void resetOptions(Params* params) {
    params->lumi = 0;
    params->cont = 100;
    params->grey = 0;
    params->w = 0;
    params->h = 0;

    Rogne rogne;
    rogne.etat = 0;
    rogne.x1 = 0;
    rogne.y1 = 0;
    rogne.x2 = 0;
    rogne.y2 = 0;

    Fusion fusion;
    fusion.etat = 0;
    fusion.mode = 0;

    params->rogne = rogne;
    params->fus = fusion;
}

void display(Image* image) {
    if (image->pixels == NULL) return;
    int i, wh;
    SDL_Surface *surface;

    SDL_SetWindowSize(image->window, image->width, image->height);
    surface = SDL_GetWindowSurface(image->window);

    if (surface->w > image->width || surface->h > image->height) {
        // Si image plus petite que la fenêtre, remplir avec du noir
        SDL_FillRect(surface, NULL, 0);
        SDL_UpdateWindowSurface(image->window);

        SDL_SetWindowSize(image->window, image->width, image->height);
        surface = SDL_GetWindowSurface(image->window);
    }


    Uint8 *p = (Uint8*)surface->pixels;
    wh = surface->w * surface->h;

    for (i = 0 ; i < wh * 4 ; i++) {
        p[i] = image->pixels[i];
    }

    SDL_UpdateWindowSurface(image->window);
}

void displayCM(Image* imageCM) {
    if (imageCM->pixels == NULL) return;

    int i, imax, j, k, x, y, id, fac = 10;
    Uint8 r, b, v, a;
    SDL_Surface *surface;

    surface = SDL_GetWindowSurface(imageCM->window);
    Uint8 *p = (Uint8*)surface->pixels;
    imax = 256 * 4;

    for (i = 0 ; i < imax ; i++) {
        IDtoXY(i, 16, &x, &y);

        b = imageCM->pixels[i];
        v = imageCM->pixels[++i];
        r = imageCM->pixels[++i];
        a = imageCM->pixels[++i];

        for (j = 0 ; j < fac ; j++) {
            for (k = 0 ; k < fac ; k++) {
                id = XYtoID(x*fac+j, y*fac+k, 160); // Algo de redimensionnement vite fait
                p[id] = b;
                p[++id] = v;
                p[++id] = r;
                p[++id] = a;
            }
        }

    }
    SDL_UpdateWindowSurface(imageCM->window);
}

void displayCtrl(Image* imageCtrl) {
    SDL_Renderer* pRenderer = imageCtrl->renderer;

    if (!pRenderer) return;
    SDL_Surface* pSprite = SDL_LoadBMP("interface.bmp");

    if (pSprite) {
        SDL_Texture* pTexture = SDL_CreateTextureFromSurface(pRenderer,pSprite); // Préparation du sprite
        if (pTexture) {

            SDL_RenderCopy(pRenderer,pTexture,NULL,NULL); // Copie du sprite grâce au SDL_Renderer

            SDL_RenderPresent(pRenderer); // Affichage
            SDL_DestroyTexture(pTexture);
        }
        else {
            fprintf(stdout,"Échec de création de la texture (%s)\n",SDL_GetError());
        }

        SDL_FreeSurface(pSprite); // Libération de la ressource occupée par le sprite
    }
    else {
        fprintf(stdout,"Échec de chargement du sprite (%s)\n",SDL_GetError());
    }

    //SDL_DestroyRenderer(pRenderer); // Libération de la mémoire du SDL_Renderer
}

fonctionsBMP.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"

//-------------- Écriture --------------

void saveBMP_BVRA32(FILE* fic, Uint8* pixels, int imax, int w, int rle) {
    int i;
    for (i = 0 ; i < imax ; ) {
        fwrite(&pixels[i++], 1, 1, fic); // B
        fwrite(&pixels[i++], 1, 1, fic); // V
        fwrite(&pixels[i++], 1, 1, fic); // R
        fwrite(&pixels[i++], 1, 1, fic); // A
    }
}

void saveBMP_BVRA24(FILE* fic, Uint8* pixels, int imax, int bt, int w, int rle) {
    int i, j = 0;
    Uint8 zeros[4] = {0,0,0,0};
    for (i = 0 ; i < imax ; ) {
        fwrite(&pixels[i++], 1, 1, fic); // B
        fwrite(&pixels[i++], 1, 1, fic); // V
        fwrite(&pixels[i++], 1, 1, fic); // R
        i++;
        j++;
        if (j == w) { // Une ligne de pixel doit être un multiple de 4 octets
            fwrite(zeros, 1, bt, fic); // Écrire des 0 pour combler
            j = 0;
        }
    }
}

void saveBMP(FILE* fic, Image* imageM, Image* imageCM) {
    // BMP V3
    Uint16 word;
    Uint32 dword, bitmapStart, colormapNbCol, ficsize, wh;
    int colormap = 0, bouchetrou, renverse = 0; // int16
    long sdword; // int32

    // En-tête (14 octets)

    word = 0x4D42;
    fwrite(&word, 2, 1, fic); // BM : 4D42

    wh = imageM->width * imageM->height;
    bouchetrou = (imageM->width * (imageM->bpp/8)) % 4; // Nombre d'octets qui comblent une ligne de pixels
    if (bouchetrou) bouchetrou = 4 - bouchetrou; // 0 1 2 3 -> 0 3 2 1

    ficsize = 14 + 40 + wh*(imageM->bpp/8) + bouchetrou*imageM->height; // Taille du fichier (sans palette)
    fwrite(&ficsize, 4, 1, fic);

    word = 0;
    fwrite(&word, 2, 1, fic); // 0 (Réservé)
    fwrite(&word, 2, 1, fic); // 0 (Réservé)

    bitmapStart = 14 + 40; // Position du début des données des pixels (sans palette)
    fwrite(&bitmapStart, 4, 1, fic);


    // En-tête 2 (40 octets)

    dword = 40; // BMP V3
    fwrite(&dword, 4, 1, fic);

    sdword = (long)imageM->width;
    fwrite(&sdword, 4, 1, fic); // Largeur
    sdword = (long)imageM->height;
    if (renverse) sdword = -sdword;
    fwrite(&sdword, 4, 1, fic); // Hauteur

    word = 1;
    fwrite(&word, 2, 1, fic); // Nombre de "planes" (?) toujours 1

    word = (Uint16)imageM->bpp;
    fwrite(&word, 2, 1, fic); // Profondeur : nb de bit par pixels

    if (imageM->bpp < 16) colormap = 1; // Palette présente

    dword = 0;
    fwrite(&dword, 4, 1, fic); // Type de compression
    fwrite(&dword, 4, 1, fic); // Taille du bitmap en octet, 0 si non compressé

    sdword = 0;
    fwrite(&sdword, 4, 1, fic); // Résolution horizontale (pour impression)
    fwrite(&sdword, 4, 1, fic); // Résolution verticale (pour impression)

    colormapNbCol = 0; // Nb de couleurs de la palette pour bpp < 16.
    fwrite(&colormapNbCol, 4, 1, fic);

    dword = 0;
    fwrite(&dword, 4, 1, fic); // Nb de couleurs les plus importantes dans la palette, rangées au début de celle-ci


    // Palette de couleurs
    if (colormap) {
        // Sauvegarde de la palette à faire
    }

    // Pixels
    if (!renverse) mirror('h', imageM);
    switch (imageM->bpp) {
        case (32) : saveBMP_BVRA32(fic, imageM->pixels, wh * 4, imageM->width, imageM->rle); break;
        case (24) : saveBMP_BVRA24(fic, imageM->pixels, wh * 4, bouchetrou, imageM->width, imageM->rle); break;
        default : break;
    }
}

//-------------- Lecture --------------

void readBMP_BVRA32_CM(FILE* fic, Uint8* pixels, int imax) {
    int i;
    Uint8 byte;
    for (i = 0 ; i < imax ; ) {
        fread(&pixels[i++], 1, 1, fic); // B
        fread(&pixels[i++], 1, 1, fic); // V
        fread(&pixels[i++], 1, 1, fic); // R
        fread(&byte, 1, 1, fic); // Réservé, toujours 0
        pixels[i++] = 255; // A
    }
}

void readBMP_BVRA24_CM(FILE* fic, Uint8* pixels, int imax) {
    int i;
    for (i = 0 ; i < imax ; ) {
        fread(&pixels[i++], 1, 1, fic); // B
        fread(&pixels[i++], 1, 1, fic); // V
        fread(&pixels[i++], 1, 1, fic); // R
        pixels[i++] = 255; // A
    }
}

void readBMP_BVRA32(FILE* fic, Uint8* pixels, int imax, int w, int rle) {
    int i;
    for (i = 0 ; i < imax ; ) {
        fread(&pixels[i++], 1, 1, fic); // B
        fread(&pixels[i++], 1, 1, fic); // V
        fread(&pixels[i++], 1, 1, fic); // R
        fread(&pixels[i++], 1, 1, fic); // A
    }
}

void readBMP_BVRA24(FILE* fic, Uint8* pixels, int imax, int bt, int w, int rle) {
    int i, j = 0;
    for (i = 0 ; i < imax ; ) {
        fread(&pixels[i++], 1, 1, fic); // B
        fread(&pixels[i++], 1, 1, fic); // V
        fread(&pixels[i++], 1, 1, fic); // R
        pixels[i++] = 255; // Alpha
        j++;
        if (j == w) { // Une ligne de pixel doit être un multiple de 4 octets
            fseek(fic, bt, SEEK_CUR);// Si c'est pas le cas, on saute les valeurs bouche-trou
            j = 0;
        }
    }
}

void readBMP_CM8(FILE* fic, Uint8* pixels, int imax, Uint8* cm, int bt, int w, int rle) {
    int i, j = 0;
    Uint8 byte;
    for (i = 0 ; i < imax ; ) {
        fread(&byte, 1, 1, fic);
        pixels[i++] = cm[byte * 4 + 0];
        pixels[i++] = cm[byte * 4 + 1];
        pixels[i++] = cm[byte * 4 + 2];
        pixels[i++] = cm[byte * 4 + 3];
        j++;
        if (j == w) { // Une ligne de pixel doit être un multiple de 4 octets
            fseek(fic, bt, SEEK_CUR);// Si c'est pas le cas, on saute les valeurs bouche-trou
            j = 0;
        }
    }
}

void loadBMP(FILE* fic, long ficsize, Image* imageO, Image* imageCM) {
    // BMP V2 et +
    Uint16 word;
    Uint32 dword, bitmapStart, compressType, colormapNbCol;
    int sword; // int16
    long sdword; // int32
    int wh, colormap = 0, renverse = 0, bmpVersion = 2, bouchetrou;

    // En-tête (14 octets)
    if (!checkBytesOK(fic, ficsize, 14)) return;

    fread(&word, 2, 1, fic); // BM : 4D42
    if (word != 0x4D42) return;

    fread(&dword, 4, 1, fic); // Taille du fichier
    if (dword != ficsize) return;

    fread(&word, 2, 1, fic); // 0 (Réservé)
    fread(&word, 2, 1, fic); // 0 (Réservé)

    fread(&bitmapStart, 4, 1, fic); // Position du début des données des pixels

    // En-tête 2 (12 ou 40 octets)
    fread(&dword, 4, 1, fic); // Taille de second en-tête : 12 = BMP v2, 40 = v3, 108 = v4
    if (dword != 12 && dword != 40 && dword != 108) return;
    if (dword == 40) bmpVersion = 3;
    if (dword == 108) bmpVersion = 4;

    if (!checkBytesOK(fic, ficsize, dword)) return;

    if (bmpVersion == 2) { // V2 Largeur hauteur sur 2 octets}
        fread(&sword, 2, 1, fic); // Largeur
        imageO->width = (int)sword;
        fread(&sword, 2, 1, fic); // Hauteur
        imageO->height = (int)sword;
    }
    else { // V3 ou V4 Largeur hauteur sur 4 octets
        fread(&sdword, 4, 1, fic); // Largeur
        imageO->width = (int)sdword;
        fread(&sdword, 4, 1, fic); // Hauteur
        imageO->height = (int)sdword;
    }

    if (imageO->height < 0) { // Si hauteur négative, renverser l'image
        imageO->height = -(imageO->height);
        renverse = 1;
    }

    wh = (imageO->width) * (imageO->height);

    fread(&word, 2, 1, fic); // Nombre de "planes" (?) toujours 1

    fread(&word, 2, 1, fic); // Profondeur : nb de bit par pixels
    imageO->bpp = (int)word;
    if (imageO->bpp < 16) colormap = 1; // Palette présente

    if (bmpVersion >= 3) { // V3 ou V4
        // Type de compression
        // 0 = sans, 1 = rle 8 bits, 2 = rle 4 bits, 3 = bitfields (pour 16 à 32 bpp)
        fread(&compressType, 4, 1, fic);
        imageO->rle = (int)compressType;
        fread(&dword, 4, 1, fic); // Taille du bitmap en octet, 0 si non compressé
        fread(&sdword, 4, 1, fic); // Résolution horizontale (pour impression)
        fread(&sdword, 4, 1, fic); // Résolution verticale (pour impression)
        // Nb de couleurs de la palette pour bpp < 16.
        // Si 0 et bpp < 16, alors = 1 << bpp (taille max possible de la palette en fonction de bpp)
        fread(&colormapNbCol, 4, 1, fic);
        if (colormapNbCol == 0 && imageO->bpp < 16) colormapNbCol = 1 << (imageO->bpp);
        // Nb de couleurs les plus importantes dans la palette, rangées au début de celle-ci
        // Sert pour les affichages au bpp inférieur au bpp de l'image et avoir un rendu moins dégueux
        fread(&dword, 4, 1, fic);
    }
    else if (bmpVersion == 2) { // V2
        colormapNbCol = 1 << (imageO->bpp); // Nb de couleurs de la palette = 2^bpp
    }

    if (bmpVersion == 4) { // V4
        // (non pris en compte)
        fread(&dword, 4, 1, fic); // Masque RVBA
        fread(&dword, 4, 1, fic);
        fread(&dword, 4, 1, fic);
        fread(&dword, 4, 1, fic);
        fread(&dword, 4, 1, fic); // Type de "color space"
        fread(&sdword, 4, 1, fic); // Coordonnées XYZ RVB
        fread(&sdword, 4, 1, fic);
        fread(&sdword, 4, 1, fic);
        fread(&sdword, 4, 1, fic);
        fread(&sdword, 4, 1, fic);
        fread(&sdword, 4, 1, fic);
        fread(&sdword, 4, 1, fic);
        fread(&sdword, 4, 1, fic);
        fread(&sdword, 4, 1, fic);
        fread(&dword, 4, 1, fic); // Gamma RVB
        fread(&dword, 4, 1, fic);
        fread(&dword, 4, 1, fic);
    }

    // Palette de couleurs
    clearCM(imageCM->pixels);
    if (colormap) {
        if (bmpVersion == 2) { // V2
            readBMP_BVRA24_CM(fic, imageCM->pixels, colormapNbCol * 4);
        }
        else { // V3 ou V4
            readBMP_BVRA32_CM(fic, imageCM->pixels, colormapNbCol * 4);
        }
    }

    // Pixels
    bouchetrou = (imageO->width * (imageO->bpp / 8)) % 4;
    if (bouchetrou) bouchetrou = 4 - bouchetrou; // 0 1 2 3 -> 0 3 2 1

    fseek(fic, bitmapStart, SEEK_SET);
    imageO->pixels = malloc(sizeof(Uint8) * wh * 4);
    if (imageO->pixels == NULL) return;

    switch (imageO->bpp) {
        case (32) : readBMP_BVRA32(fic, imageO->pixels, wh * 4, imageO->width, imageO->rle); break;
        case (24) : readBMP_BVRA24(fic, imageO->pixels, wh * 4, bouchetrou, imageO->width, imageO->rle); break;
        case (8) : readBMP_CM8(fic, imageO->pixels, wh * 4, imageCM->pixels, bouchetrou, imageO->width, imageO->rle); break;
        default : break;
    }

    if (!renverse) mirror('h', imageO);

}

fonctionsFiltres.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"

void actionLumi(Params* params, int val, int def) {
    if (def) params->lumi = limlum(val);                // Définir
    else params->lumi = limlum(params->lumi + val);     // Ajouter
}

void actionCont(Params* params, int val, int def) {
    if (def) params->cont = limcont(val);               // Définir
    else params->cont = limcont(params->cont + val);    // Ajouter
}

void actionGrey(Params* params) {
    params->grey = !params->grey;
}

void contrast(Image* imageM, int cont, int lumi) {
    if (!imageM->pixels) return; // No picture
    if (cont == 0 && lumi == 0) return; // No change

    int i, wh4;
    Uint8* p = imageM->pixels;

    wh4 = imageM->width * imageM->height * 4; // 4 pour R+G+B+A
    for(i = 0; i < wh4; i+=4){
        p[i] = lim((p[i] - 127) * (cont/100.0) + 127 + lumi);
        p[i+1] = lim((p[i+1] - 127) * (cont/100.0) + 127 + lumi);
        p[i+2] = lim((p[i+2] - 127) * (cont/100.0) + 127 + lumi);
        p[i+3] += 0;
    }
}

void invert(Image * imageO){
    if (!imageO->pixels) return; // No picture
    Uint8* p = imageO->pixels;
    int i, wh4 = imageO->width * imageO->height * 4.0;
    for(i = 0; i < wh4; i+=4){
        p[i] = 255 - p[i];
        p[i+1] = 255 - p[i+1];
        p[i+2] = 255 - p[i+2];
        p[i+3] = p[i+3];
    }
}

void greylevel(Image * imageO, Image * imageM, int grey){
    if (!imageO->pixels) return;
    if (!imageM->pixels) return; // No picture
    if(!grey) return;
    else{
        Uint8* p = imageM->pixels;
        int i, j, maxi, wh4 = imageM->width * imageM->height * 4.0;

        for(i = 0; i < wh4; i+=4){
            maxi = greymax(p[i], p[i+1], p[i+2]);
            for(j = 0; j < 3; j++){
                p[i+j] = maxi;
            }
            p[i+3] = p[i+3];
        }
    }
}

int greymax(int a, int b, int c){
    if(a > b && a > c) return a;
    if(b > a && b > c) return b;
    return c;
}

void alpha(Image* imageM) {
    if (!imageM->pixels) return; // No picture

    int fr = 255, fv = 255, fb = 255;
    long wh4, i;
    Uint8 alp=0;
    Uint8* p = imageM->pixels;

    wh4 = imageM->width * imageM->height * 4;

    for (i = 0 ; i < wh4 ; i++) {
        alp = p[i+3];
        p[i] = mixer(p[i], fr, alp);
        i++;
        p[i] = mixer(p[i], fv, alp);
        i++;
        p[i] = mixer(p[i], fb, alp);
        i++;
    }

}


fonctionsFusion.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"

void actionsFus(Image* imageM, Uint8* pixelsTmp, Image* imageF, int action, SDL_Renderer* renderer, SDL_Texture* textureEntoure, Image* imageCM, char* urlf, Params* param){
    //loading(imageF, imageCM, urlf, 1);
    if(!imageM->pixels) return;// printf("\nPas d'image M");
    if(!imageF->pixels) return;// printf("\nPas d'image F");

    switch (action){
        case 1 : superposition(imageM, imageF, pixelsTmp);
            param->fus.mode = 1;
            break;
        case 2 : fusalpha(imageM, imageF,  pixelsTmp);
            param->fus.mode = 2;
            break;
        case 3 : addition(imageM, imageF, pixelsTmp);
            param->fus.mode = 3;
            break;
        case 4 : soustraction(imageM, imageF, pixelsTmp);
            param->fus.mode = 4;
            break;
        case 5 : eclaircir(imageM, imageF, pixelsTmp);
            param->fus.mode = 5;
            break;
        case 6 : obscurcir(imageM, imageF, pixelsTmp);
            param->fus.mode = 6;
            break;
        case 7 : produit(imageM, imageF, pixelsTmp);
            param->fus.mode = 7;
            break;
        case 8 : lumiere(imageM, imageF, pixelsTmp);
            param->fus.mode = 8;
            break;
        case 9 : densite(imageM, imageF, pixelsTmp);
            param->fus.mode = 9;
            break;
    }
    if(param->fus.mode == 1) traceTexture(renderer, textureEntoure, 2, 7, 193, 41);
    if(param->fus.mode == 2) traceTexture(renderer, textureEntoure, 204, 7, 83, 41);
    if(param->fus.mode == 3) traceTexture(renderer, textureEntoure, 12, 56, 114, 41);
    if(param->fus.mode == 4) traceTexture(renderer, textureEntoure, 130, 56, 162, 41);
    if(param->fus.mode == 5) traceTexture(renderer, textureEntoure, 10, 101, 103, 41);
    if(param->fus.mode == 6) traceTexture(renderer, textureEntoure, 150, 101, 152, 41);
    if(param->fus.mode == 7) traceTexture(renderer, textureEntoure, 10, 152, 103, 41);
    if(param->fus.mode == 8) traceTexture(renderer, textureEntoure, 165, 152, 127, 41);
    if(param->fus.mode == 9) traceTexture(renderer, textureEntoure, 10, 198, 220, 41);
}

void superposition(Image * imageM, Image * imageF, Uint8* pt){
    if (!imageF->pixels) return;
    if (!imageM->pixels) return; // No picture
    Uint8 * p = imageM->pixels;
    Uint8 * f = imageF->pixels;
    int i, j;
    long hh = imageM->height, ww = (imageM->width) * 4.0, h = imageF->height, w = (imageF->width) * 4.0;

    long smallh, smallw;
    if(ww > w) smallw = w;
    else smallw = ww;
    if(hh > h) smallh = h;
    else smallh = hh;

    for(i = 0; i < smallh; i++){
        for(j = 0; j < smallw; j+=4){
            p[i*ww+j] = (pt[i*ww+j]+f[i*w+j])/2;
            p[i*ww+j+1] = (pt[i*ww+j+1]+f[i*w+j+1])/2;
            p[i*ww+j+2] = (pt[i*ww+j+2]+f[i*w+j+2])/2;
            p[i*ww+j+3] = pt[i*ww+j+3];
        }
    }
}

void fusalpha(struct Image * imageM, struct Image * imageF,  Uint8* pt){
    if (!imageF->pixels) return;
    if (!imageM->pixels) return; // No picture
    Uint8 * p = imageM->pixels;
    Uint8 * f = imageF->pixels;
    int i, j;
    long hh = imageM->height, ww = (imageM->width) * 4.0, h = imageF->height, w = (imageF->width) * 4.0;

    long smallh, smallw;
    if(ww > w) smallw = w;
    else smallw = ww;
    if(hh > h) smallh = h;
    else smallh = hh;

    for(i = 0; i < smallh; i++){
        for(j = 0; j < smallw; j+=4){
            p[i*ww+j] = mixer(f[i*w+j], pt[i*ww+j], f[i*w+j+3]);
            p[i*ww+j+1] = mixer(f[i*w+j+1], pt[i*ww+j+1], f[i*w+j+3]);
            p[i*ww+j+2] = mixer(f[i*w+j+2], pt[i*ww+j+2], f[i*w+j+3]);
            p[i*ww+j+3] = pt[i*ww+j+3];
        }
    }
}

void eclaircir(struct Image * imageM, struct Image * imageF, Uint8 * pt){
    if (!imageF->pixels) return;
    if (!imageM->pixels) return; // No picture
    Uint8 * p = imageM->pixels;
    Uint8 * f = imageF->pixels;
    int i, j;
    long hh = imageM->height, ww = (imageM->width) * 4.0, h = imageF->height, w = (imageF->width) * 4.0;

    long smallh, smallw;
    if(ww > w) smallw = w;
    else smallw = ww;
    if(hh > h) smallh = h;
    else smallh = hh;

    for(i = 0; i < smallh; i++){
        for(j = 0; j < smallw; j+=4){			// inverser "<" pour obtenir l'autre
            if((pt[i*ww+j] + pt[i*ww+j+1] + pt[i*ww+j+2]) < (f[i*w+j] + f[i*w+j+1] + f[i*w+j+2])){
                p[i*ww+j] = f[i*w+j];
                p[i*ww+j+1] = f[i*w+j+1];
                p[i*ww+j+2] = f[i*w+j+2];
            }else{
                p[i*ww+j] = pt[i*ww+j];
                p[i*ww+j+1] = pt[i*ww+j+1];
                p[i*ww+j+2] = pt[i*ww+j+2];
            }
            p[i*ww+j+3] = pt[i*ww+j+3];
        }
    }
}

void obscurcir(struct Image * imageM, struct Image * imageF, Uint8 * pt){
    if (!imageF->pixels) return;
    if (!imageM->pixels) return; // No picture
    Uint8 * p = imageM->pixels;
    Uint8 * f = imageF->pixels;
    int i, j;
    long hh = imageM->height, ww = (imageM->width) * 4.0, h = imageF->height, w = (imageF->width) * 4.0;

    long smallh, smallw;
    if(ww > w) smallw = w;
    else smallw = ww;
    if(hh > h) smallh = h;
    else smallh = hh;

    for(i = 0; i < smallh; i++){
        for(j = 0; j < smallw; j+=4){			// inverser "<" pour obtenir l'autre
            if((pt[i*ww+j] + pt[i*ww+j+1] + pt[i*ww+j+2]) > (f[i*w+j] + f[i*w+j+1] + f[i*w+j+2])){
                p[i*ww+j] = f[i*w+j];
                p[i*ww+j+1] = f[i*w+j+1];
                p[i*ww+j+2] = f[i*w+j+2];
            }else{
                p[i*ww+j] = pt[i*ww+j];
                p[i*ww+j+1] = pt[i*ww+j+1];
                p[i*ww+j+2] = pt[i*ww+j+2];
            }
            p[i*ww+j+3] = p[i*ww+j+3];
        }
    }
}

void addition(struct Image * imageM, struct Image * imageF, Uint8 * pt){
    if (!imageF->pixels) return;
    if (!imageM->pixels) return; // No picture
    Uint8 * p = imageM->pixels;
    Uint8 * f = imageF->pixels;
    int i, j;
    long hh = imageM->height, ww = (imageM->width) * 4.0, h = imageF->height, w = (imageF->width) * 4.0;

    long smallh, smallw;
    if(ww > w) smallw = w;
    else smallw = ww;
    if(hh > h) smallh = h;
    else smallh = hh;

    for(i = 0; i < smallh; i++){
        for(j = 0; j < smallw; j+=4){
            p[i*ww+j] = lim(pt[i*ww+j] + f[i*w+j]);
            p[i*ww+j+1] = lim(pt[i*ww+j+1] + f[i*w+j+1]);
            p[i*ww+j+2] = lim(pt[i*ww+j+2] + f[i*w+j+2]);
            p[i*ww+j+3] = pt[i*ww+j+3];
        }
    }
}

void soustraction(struct Image * imageM, struct Image * imageF, Uint8 * pt){
    if (!imageF->pixels) return;
    if (!imageM->pixels) return; // No picture
    Uint8 * p = imageM->pixels;
    Uint8 * f = imageF->pixels;
    int i, j;
    long hh = imageM->height, ww = (imageM->width) * 4.0, h = imageF->height, w = (imageF->width) * 4.0;

    long smallh, smallw;
    if(ww > w) smallw = w;
    else smallw = ww;
    if(hh > h) smallh = h;
    else smallh = hh;

    for(i = 0; i < smallh; i++){
        for(j = 0; j < smallw; j+=4){
            p[i*ww+j] = lim(255 - lim(255-pt[i*ww+j]) - f[i*w+j]);
            p[i*ww+j+1] = lim(255 - lim(255-pt[i*ww+j+1]) - f[i*w+j+1]);
            p[i*ww+j+2] = lim(255 - lim(255-pt[i*ww+j+2]) - f[i*w+j+2]);
            p[i*ww+j+3] = pt[i*ww+j+3];
        }
    }
}

void produit(struct Image * imageM, struct Image * imageF, Uint8 * pt){
    if (!imageF->pixels) return;
    if (!imageM->pixels) return; // No picture
    Uint8 * p = imageM->pixels;
    Uint8 * f = imageF->pixels;
    int i, j;
    long hh = imageM->height, ww = (imageM->width) * 4.0, h = imageF->height, w = (imageF->width) * 4.0;

    long smallh, smallw;
    if(ww > w) smallw = w;
    else smallw = ww;
    if(hh > h) smallh = h;
    else smallh = hh;

    for(i = 0; i < smallh; i++){
        for(j = 0; j < smallw; j+=4){
            // p[i] - p[i] + 255 - p[i]
            p[i*ww+j] = lim(f[i*w+j] * pt[i*ww+j] / 255);
            p[i*ww+j+1] = lim(f[i*w+j+1] * pt[i*ww+j+1] / 255);
            p[i*ww+j+2] = lim(f[i*w+j+2] * pt[i*ww+j+2] / 255);
            p[i*ww+j+3] = pt[i*ww+j+3];
        }
    }
}

void lumiere(struct Image * imageM, struct Image * imageF, Uint8 * pt){
    if (!imageF->pixels) return;
    if (!imageM->pixels) return; // No picture
    Uint8 * p = imageM->pixels;
    Uint8 * f = imageF->pixels;
    int i, j;
    long hh = imageM->height, ww = (imageM->width) * 4.0, h = imageF->height, w = (imageF->width) * 4.0;

    long smallh, smallw;
    if(ww > w) smallw = w;
    else smallw = ww;
    if(hh > h) smallh = h;
    else smallh = hh;

    for(i = 0; i < smallh; i++){
        for(j = 0; j < smallw; j+=4){
            p[i*ww+j] = 255 - lim((255 - pt[i*ww+j]) * (255 - f[i*w+j]) / 255.);
            p[i*ww+j+1] = 255 - lim((255 - pt[i*ww+j+1]) * (255 - f[i*w+j+1]) / 255.);
            p[i*ww+j+2] = 255 - lim((255 - pt[i*ww+j+2]) * (255 - f[i*w+j+2]) / 255.);
            p[i*ww+j+3] = pt[i*ww+j+3];
        }
    }
}


void densite(struct Image * imageM, struct Image * imageF, Uint8 * pt){
    if (!imageF->pixels) return;
    if (!imageM->pixels) return; // No picture
    Uint8 * p = imageM->pixels;
    Uint8 * f = imageF->pixels;
    int i, j, invpt;
    long hh = imageM->height, ww = (imageM->width) * 4.0, h = imageF->height, w = (imageF->width) * 4.0;

    long smallh, smallw;
    if(ww > w) smallw = w;
    else smallw = ww;
    if(hh > h) smallh = h;
    else smallh = hh;

    for(i = 0; i < smallh; i++){
        for(j = 0; j < smallw; j+=4){
            invpt = lim(255 - pt[i*ww+j]);
            p[i*ww+j] = lim(-invpt + f[i*w+j]);
            invpt = lim(255 - pt[i*ww+j+1]);
            p[i*ww+j+1] = lim(-invpt + f[i*w+j+1]);
            invpt = lim(255 - pt[i*ww+j+2]);
            p[i*ww+j+2] = lim(-invpt + f[i*w+j+2]);
            p[i*ww+j+3] = pt[i*ww+j+3];
        }
    }
}

fonctionsImage.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"

int XYtoID(int x, int y, int width) {
    return ((y * width + x) * 4);
}

void IDtoXY(int id, int width, int* x, int* y) {
    int id4 = id / 4;
    *x = id4 % width;
    *y = id4 / width;
}

void permut(Uint8* pixels, int a, int b) {
    Uint8 tmp = pixels[a];
    pixels[a] = pixels[b];
    pixels[b] = tmp;
}

double lim(int a) {
    return a > 255 ? 255 : a < 0 ? 0 : a;
}

int limcont(int a) {
    return a >= 200 ? 200 : a <= 10 ? 10 : a;
}

int limlum(int a) {
    return a >= 250 ? 250 : a <= -240 ? -240 : a;
}

Uint8 mixer(Uint8 a, Uint8 b, Uint8 c) {
    Uint8 ret;
    double fac = c / 255.;
    ret = (1 - fac) * b + fac * a;
    return ret;
}

void copyPixels(Uint8* pixelsO, Uint8** pixelsM, long widthO, long heightO, long *widthM, long *heightM) {
    // Copie un tableau de pixels vers un autre d'une autre dimension
    if (pixelsO == NULL) return;
    long wh4, i;

    if (*pixelsM) { // Vide le tableau de destination
        free(*pixelsM);
        *pixelsM = NULL;
    }

    // Copie la largeur et hauteur
    *widthM = widthO;
    *heightM = heightO;
    wh4 = widthO * heightO * 4; // 4 pour R+V+B+A

    // Créé et copie les données
    *pixelsM = malloc(sizeof(Uint8) * wh4);

    for (i = 0 ; i < wh4 ; i++) {
        (*pixelsM)[i] = pixelsO[i];
    }
}



fonctionsMenu.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"
#include <string.h>

int keyboard(SDL_Event event, int idImg, int idCtrl) {
    switch (event.key.keysym.sym) {
        case SDLK_ESCAPE    : return 0;     // Quitter
        case SDLK_LEFT      : return 24;    // Précédent
        case SDLK_RIGHT     : return 25;    // Suivant
        case SDLK_SPACE     : return 3;     // Reset
        case SDLK_r         : return 16;    // Rogner
        case SDLK_i         : return 21;    // Inversion des couleurs
        case SDLK_g         : return 22;    // Niveau de gris
        case SDLK_f         : return 23;    // Fusion
    }
    return -1;
}

int buttons(SDL_Event event, int idImg, int idCtrl) {
    if (event.button.windowID == idCtrl) { // Contrôles
        if (event.button.button == SDL_BUTTON_LEFT) {
            int x = event.button.x;
            int y = event.button.y;
            //printf("\n%d %d   ", x, y);
            if (x > 23 && x < 112 && y > 24 && y <51) return 1; // Open
            else if (x > 139 && x < 264 && y > 24 && y < 51) return 2; // Save
            else if (x > 24 && x < 75 && y > 60 && y < 78) return 3; // Reset
            else if (x > 180 && x < 204 && y > 90 && y < 114) return 4; // Luminosite -
            else if (x > 214 && x < 222 && y > 102 && y < 112) return 5;   // Reset lum
            else if (x > 225 && x < 246 && y > 90 && y < 114) return 6; // Luminosite +
            else if (x > 180 && x < 204 && y > 124 && y < 148) return 7; // Contrast -
            else if (x > 214 && x < 222 && y > 136 && y < 146) return 8;  // Reset cont
            else if (x > 225 && x < 246 && y > 124 && y < 148) return 9;  // Contrast +
            else if (x > 180 && x < 204 && y > 190 && y < 213) return 10;   // Width -
            else if (x > 214 && x < 222 && y > 202 && y < 212) return 11;   // Reset width
            else if (x > 225 && x < 246 && y > 190 && y < 213) return 12;   // Width +
            else if (x > 180 && x < 204 && y > 225 && y < 245) return 13;   // Height -
            else if (x > 214 && x < 222 && y > 236 && y < 246) return 14;   // Reset height
            else if (x > 225 && x < 246 && y > 225 && y < 245) return 15;   // Height +
            else if (x > 180 && x < 201 && y > 257 && y < 277) return 16;   // Rogner
            else if (x > 170 && x < 201 && y > 314 && y < 343) return 17; // Rot H
            else if (x > 223 && x < 253 && y > 314 && y < 343) return 18; // Rot AH
            else if (x > 174 && x < 202 && y > 349 && y < 373) return 19; // Mirror V
            else if (x > 223 && x < 246 && y > 350 && y < 375) return 20; // Mirror H
            else if (x > 34 && x < 258 && y > 411 && y < 438) return 21;    // Invert colors
            else if (x > 34 && x < 258 && y > 450 && y < 478) return 22;   // Grey
            else if (x > 34 && x < 258 && y > 491 && y < 511) return 23;   // Fusion
            else if (x > 62 && x < 114 && y > 545 && y < 605) return 24;    // Prev
            else if (x > 178 && x < 227 && y > 545 && y < 605) return 25;   // Next
        }
    }
    else if (event.button.windowID == idImg) {
        if (event.button.button == SDL_BUTTON_LEFT) {
            return 100; // Image rogner XY
        }
    }
    return -1; // Aucune action
}

int buttonsUP(SDL_Event event, int idImg, int idCtrl) {
    if (event.button.windowID == idImg) {
        if (event.button.button == SDL_BUTTON_LEFT) {
            return 101; // Image rogner Largeur hauteur
        }
    }
    return -1; // Aucune action
}

int mousemove(SDL_Event event, int idImg, int idCtrl) {
    if (event.button.windowID == idImg) {
        if (event.button.button == SDL_BUTTON_LEFT) {
            return 101; // Image rogner Largeur hauteur
        }
    }
    return -1; // Aucune action
}

void rogneDefine(Params* params, int x, int y, int val) {
    if (val == 0) { // Désactive
        params->rogne.etat = 0;
        params->rogne.x1 = x;
        params->rogne.y1 = y;
        params->rogne.x2 = x;
        params->rogne.y2 = y;
    }
    else if (val == 1) { // Initialise ou désactive (permute)
        params->rogne.etat = !params->rogne.etat;
    }

    if (params->rogne.etat == 0) return; // Non initialisé

    if (val == 2) { // Définit X et Y
        params->rogne.x1 = x;
        params->rogne.y1 = y;
        params->rogne.x2 = x;
        params->rogne.y2 = y;
    }
    else if (val == 3) { // Définit X2 Y2
        params->rogne.x2 = x;
        params->rogne.y2 = y;
    }
}

int evenements(int idImg, int idCtrl, int idCM, int* x, int* y) {
    SDL_Event event;

    while (SDL_PollEvent(&event)) {

        *x = event.button.x;
        *y = event.button.y;

        switch (event.type) {

            case SDL_WINDOWEVENT:
                switch(event.window.event) {
                    case SDL_WINDOWEVENT_CLOSE:
                        return 0;
                }
                break;

            case SDL_QUIT:
                return 0;

            case SDL_KEYDOWN: {
                return keyboard(event, idImg, idCtrl);
            }

            case SDL_MOUSEBUTTONDOWN:
                return buttons(event, idImg, idCtrl);

            case SDL_MOUSEBUTTONUP:
                return buttonsUP(event, idImg, idCtrl);

            case SDL_MOUSEMOTION:
                return mousemove(event, idImg, idCtrl);

        }
    }
    return -1; // Aucune action
}

void actionOpen(Image* imageO, Image* imageCM, char* url, Params* params) {
    loading(imageO, imageCM, url, 0);
    resetOptions(params);
}

void actionReset(Image* imageO, Image* imageCM, char* url, Params* params) {
    loading(imageO, imageCM, url, 1);
    resetOptions(params);
}

void actionArgument(Image* imageO, Image* imageM, Image* imageCM, Image* imageF, char* url, char* urlf, int argc, char** argv) {

    if (argc > 1) { // Charge l'image de l'argument
        strcpy(url, argv[1]);
        loading(imageO, imageCM, url, 1);
        copyPixels(imageO->pixels, &(imageM->pixels), imageO->width, imageO->height, &(imageM->width), &(imageM->height));
        display(imageM);
        renameWindow(imageM, url);
    }

    if(argc > 2){
        loading(imageF, imageCM, argv[2], 1);
    }
}

void actionLoop(Image* imageO, Image* imageM, Image* imageCM, Image* imageCtrl, Image* imageF, char* url, char* urlf) {

    int action = 1, x, y;
    Params params;
    resetOptions(&params);

    while (action) {
        action = evenements(imageM->id, imageCtrl->id, imageCM->id, &x, &y);

        // FONCTIONS NON DESTRUCTIVES : Modifient pixelsO
        switch (action) {

            case 1 : // Open
                actionOpen(imageO, imageCM, url, &params);
                break;
            case 2 : // Save
                saving(imageM, imageCM, url, &params);
                break;
            case 3 : // Reset
                actionReset(imageM, imageCM, url, &params);
                break;
            case 4 : // Luminosité -
                actionLumi(&params, -10, 0);
                break;
            case 5 : // Reset lum
                actionLumi(&params, 0, 1);
                break;
            case 6 : // Luminosité +
                actionLumi(&params, 10, 0);
                break;
            case 7 : // Contraste -
                actionCont(&params, -5, 0);
                break;
            case 8 : // Reset cont
                actionCont(&params, 100, 1);
                break;
            case 9 : // Contraste +
                actionCont(&params, 5, 0);
                break;
            case 10 : // Width -
                actionResize(&params, -10, 0);
                break;
            case 11 : // Reset width
                actionResize(&params, 99, 0);
                break;
            case 12 : // Width +
                actionResize(&params, 10, 0);
                break;
            case 13 : // Height -
                actionResize(&params, 0, -10);
                break;
            case 14 : // Reset height
                actionResize(&params, 0, 99);
                break;
            case 15 : // Height +
                actionResize(&params, 0, 10);
                break;
            case 16 : // Rogner
                rogneDefine(&params, 0, 0, 1);
                break;
            case 17 : // Rotation horaire
                actionRot(&params, imageO, imageF, 1);
                break;
            case 18 : // Rotation anti-horaire
                actionRot(&params, imageO, imageF, -1);
                break;
            case 19 : // Miroir vertical
                actionMirror(&params, imageO, imageF, 'v');
                break;
            case 20 : // Miroir horizontal
                actionMirror(&params, imageO, imageF, 'h');
                break;
            case 21 : // Invert colors
                invert(imageO);
                break;
            case 22 : // Grey
                actionGrey(&params);
                break;
            case 23 : // Fusion
                if (params.fus.mode == 0) loading(imageF, imageCM, urlf, 0);
                params.fus.etat = 1;
                break;
            case 24 : // Prev
                actionNextPrev(imageO, imageCM, url, &params, -1);
                break;
            case 25 : // Next
                actionNextPrev(imageO, imageCM, url, &params, 1);
                break;
            case 100 : // Rogner premier clic
                rogneDefine(&params, x, y, 2);
                break;
            case 101 : // Rogner déclic
                rogneDefine(&params, x, y, 3);
                break;
        }

        // FONCTIONS DESTRUCTIVES : Modifient pixelsM
        if (action > 0) { // Action sur l'image : nécessite un recalcul et un réaffichage

            // Si autre action que rognage, rognage désactivé
            if (action != 16 && action != 100 && action != 101) params.rogne.etat = 0;

            // Copie pixelsO vers pixelsM
            copyPixels(imageO->pixels, &(imageM->pixels), imageO->width, imageO->height, &(imageM->width), &(imageM->height));

            // Traitements
            contrast(imageM, params.cont, params.lumi);
            greylevel(imageO, imageM, params.grey);

            // Fusion
            if (displayMenu(3, imageM, &params, imageO, imageF, imageCM, urlf) == 0)
                actionsFus(imageM, imageM->pixels, imageF, params.fus.mode, NULL, NULL, imageCM, urlf, &params);

            // Redimensionne
            resizePixels(imageM, &params);

            // Rogne
            rognePreview(imageM, params.rogne);

            //alpha(imageM); // Mélange l'alpha avec un fond blanc

            renameWindow(imageM, url);
            display(imageM);
            displayCM(imageCM);
        }
    }
}

fonctionsMiroir.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"

void actionMirror(Params* params, Image* imageO, Image* imageF, char dir) {
    mirrorRogne(params, imageO->width, imageO->height, dir);
    mirror(dir, imageO);
    mirror(dir, imageF);
}

void mirrorRogne(Params* params, int w, int h, char dir) {
    if (params == NULL) return;
    if (dir == 'v') {
        params->rogne.x1 = w - params->rogne.x1;
        params->rogne.x2 = w - params->rogne.x2;
    }
    else if (dir == 'h') {
        params->rogne.y1 = h - params->rogne.y1;
        params->rogne.y2 = h - params->rogne.y2;
    }
}

void mirror(char dir, Image* image) {
    if (!image->pixels) return; // Aucune image

    Uint8* pixelsM;
    int i, j, k;
    int a, b, w, h;

    w = image->width;
    h = image->height;
    pixelsM = image->pixels;

    if(dir == 'v'){     // vertical
        for(i = 0; i < h; i++){    // browse line per line
            for(j = 0; j < w/2; j++){  // column to the half
                for(k = 0; k < 4; k++) {
                    a = i * w * 4 + j * 4 + k;
                    b = i * w * 4 + (w - j - 1) * 4+ k;
                    permut(pixelsM, a, b);
                }
            }
        }
    }else if(dir == 'h'){    // horizontal
        for(i = 0; i < h/2; i++){
            for(j = 0; j < w; j++){
                for (k = 0; k < 4; k++){
                    a = i * w * 4 + j * 4 + k;
                    b = (h - i - 1) * w * 4 + j * 4 + k;
                    permut(pixelsM, a, b);
                }
            }
        }
    }
}



fonctionsNextPrev.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include <windows.h>
#include <sys/types.h>
#include <dirent.h>
#include "prototypes.h"

void actionNextPrev(Image* imageO, Image* imageCM, char* url, Params* params, int sens) {
    parcourir(url, sens);
    loading(imageO, imageCM, url, 1);
    resetOptions(params);
}

void parcourir(char* url, int sens) {
    struct dirent *lecture;
    DIR *rep;
    char dir[1024];
    char name[1024];
    char name_prem[1024]; name_prem[0] = '\0';
    char name_prec[1024]; name_prec[0] = '\0';
    char name_actu[1024]; name_actu[0] = '\0';
    char name_suiv[1024]; name_suiv[0] = '\0';
    char name_dern[1024]; name_dern[0] = '\0';
    char ext[10];
    int trouve = 0, i = 0;

    urlToName(url, name);
    urlToDir(url, dir);

    // Ouvre le dossier
    rep = opendir(dir);
    if (rep == NULL) return;

    // Parcourt les fichiers
    while ((lecture = readdir(rep))) {

        // Cherche les TGA et BMP uniquement
        urlToExt(lecture->d_name, ext);
        if (strcmp(ext, "tga") && strcmp(ext, "bmp")) continue;

        // Premier fichier
        if (!i) strcpy(name_prem, lecture->d_name);

        // Fichier suivant
        if (trouve == 1) {
            strcpy(name_suiv, lecture->d_name);
            trouve++;
        }

        // Fichier actuel trouvé
        if (strcmp(lecture->d_name, name) == 0) {
            strcpy(name_actu, lecture->d_name);
            trouve = 1;
        }

        // Fichier précédent
        if (!trouve) strcpy(name_prec, lecture->d_name);

        // Dernier fichier
        strcpy(name_dern, lecture->d_name);

        i++;
    }

    if (name_prec[0] == '\0') strcpy(name_prec, name_dern);
    if (name_suiv[0] == '\0') strcpy(name_suiv, name_prem);

    if (sens == -1) strcpy(url, strcat(dir, name_prec));
    else strcpy(url, strcat(dir, name_suiv));

    closedir(rep);
}


fonctionsResize.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"

void actionResize(Params* params, int w, int h) {
    if (params == NULL) return;

    if (w == 99) params->w = 0;
    else {
        if (params->w + w > 0) params->w += w; // Limite à 1 px max
    }

    if (h == 99) params->h = 0;
    else {
        if (params->h + h > 0) params->h += h; // Limite à 1 px max
    }

}
/* marche pas
void resizeMix(Uint8* pt, Uint8* p, int i, int x, int y, double ratioX, double ratioY, long w) {
    int v = 0;//p[j*4];
    double vd = 0, fac;
    int j;

    //ratioX = 1. / ratioX;

    // ratioX = 1.5
    // On prend 1 * le pixel + 0.5 * le pixel X suivant

    while (ratioX > 0) {

        fac = (ratioX < 1) ? ratioX : 1.;

        j = XYtoID(x, y, w);

        vd += p[j*4];// * fac;

        ratioX--;
        x++;
    }

    v = (int)vd;
    //v = (int) ( vd / ratioX );


    pt[i*4] = v;
    pt[i*4+1] = v;//p[j*4+1];
    pt[i*4+2] = v;//p[j*4+2];
    pt[i*4+3] = p[j*4+3];
}*/

void resizePixels(Image* image, Params* params) {
    if (image == NULL || image->pixels == NULL) return;
    int i, j, x, y;
    double rx, ry;
    //long wh4 = image->width * image->height * 4;
    long whr, w, h;
    double ratioX, ratioY;

    if (params->w <= 0) params->w = image->width;
    if (params->h <= 0) params->h = image->height;

    if (params->w == image->width && params->h == image->height) return;

    w = params->w;
    h = params->h;
    whr = w * h;

    Uint8* p = image->pixels;
    Uint8* pt = NULL; // Tableau de pixels temporaire

    pt = malloc(sizeof(Uint8) * whr*4); // Pixels tmp qui contiendra l'image redimensionnée
    if (pt == NULL) return;

    ratioX = image->width / (double)w;
    ratioY = image->height / (double)h;

    for (i = 0 ; i < whr ; i++) {
        IDtoXY(i, w, &x, &y);

        rx = x * ratioX;
        ry = y * ratioY;

        j = XYtoID((int)rx, (int)ry, image->width);

        pt[i*4] = p[j*4];
        pt[i*4+1] = p[j*4+1];
        pt[i*4+2] = p[j*4+2];
        pt[i*4+3] = p[j*4+3];

    }

    copyPixels(pt, &(image->pixels), w, h, &(image->width), &(image->height)); // Copie pixelsTmp vers pixelsM
}

fonctionsRogne.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"

void rogneMinMax(int* vmin, int* vmax, int v1, int v2) {
    if (v1 < v2) {
        *vmin = v1;
        *vmax = v2;
    }
    else {
        *vmin = v2;
        *vmax = v1;
    }
}

void rognePreview(Image* imageM, Rogne rogne) {
    if (!imageM->pixels) return; // No picture
    if (rogne.x1 == rogne.x2 && rogne.y1 == rogne.y2) return; // Pas de rognage

    long wh4, i;
    int x, y, xmin, ymin, xmax, ymax; // Coordonnées des pixels
    Uint8* p = imageM->pixels;

    wh4 = imageM->width * imageM->height * 4;
    rogneMinMax(&xmin, &xmax, rogne.x1, rogne.x2);
    rogneMinMax(&ymin, &ymax, rogne.y1, rogne.y2);

    for (i = 0 ; i < wh4 ; i++) {
        IDtoXY(i, imageM->width, &x, &y); // Coordonnées du pixel

        if (x < xmin || x > xmax || y < ymin || y > ymax) {
            p[i] = lim(p[i] - 120);
            i++;
            p[i] = lim(p[i] - 120);
            i++;
            p[i] = lim(p[i] - 120);
            i++;
            p[i] = 255;
        }
        else {
            i += 3;
        }
    }
}

void rogneApply(Image* imageM, Rogne rogne) {
    if (!imageM->pixels) return; // No picture
    if (rogne.x1 == rogne.x2 && rogne.y1 == rogne.y2) return; // Pas de rognage

    long wh4, i, j;
    int x, y, xmin, ymin, xmax, ymax, w, h; // Coordonnées des pixels
    Uint8* p = imageM->pixels;
    Uint8* pixelsTmp = NULL; // Tableau de pixels temporaire

    wh4 = imageM->width * imageM->height * 4;
    rogneMinMax(&xmin, &xmax, rogne.x1, rogne.x2); // Met dans xmin le plus petit de x1 et x2, et dans xmax le plus grand.
    rogneMinMax(&ymin, &ymax, rogne.y1, rogne.y2);

    w = xmax - xmin + 1; // Largeur, hauteur de l'image rognée
    h = ymax - ymin + 1;

    pixelsTmp = malloc(sizeof(Uint8) * w*h*4); // Pixels tmp qui contiendra l'image rognée
    if (pixelsTmp == NULL) return;

    for (i = 0, j = 0 ; i < wh4 ; i++) {
        IDtoXY(i, imageM->width, &x, &y); // Coordonnées du pixel

        if (x < xmin || x > xmax || y < ymin || y > ymax) {
            i += 3; // On passe les pixels hors de la zone de rognage
        }
        else {
            pixelsTmp[j++] = p[i++];
            pixelsTmp[j++] = p[i++];
            pixelsTmp[j++] = p[i++];
            pixelsTmp[j++] = p[i];
        }
    }

    copyPixels(pixelsTmp, &(imageM->pixels), w, h, &(imageM->width), &(imageM->height)); // Copie pixelsTmp vers pixelsM

    free(pixelsTmp);
}

fonctionsRot.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"

void actionRot(Params* params, Image* imageO, Image* imageF, int dir) {
    rotRogne(params, imageO->width, imageO->height, 1); // Rotation du rognage
    rot(dir, imageO);
    rot(dir, imageF);
}

void rotRogne(Params* params, int w, int h, int dir) {
    int tmp;
    if (dir == 1) {
        tmp = params->rogne.x1;
        params->rogne.x1 = h - params->rogne.y1;
        params->rogne.y1 = tmp;

        tmp = params->rogne.x2;
        params->rogne.x2 = h - params->rogne.y2;
        params->rogne.y2 = tmp;
    }
    else if (dir == -1) {
        tmp = params->rogne.y1;
        params->rogne.y1 = w - params->rogne.x1;
        params->rogne.x1 = tmp;

        tmp = params->rogne.y2;
        params->rogne.y2 = w - params->rogne.x2;
        params->rogne.x2 = tmp;
    }

    tmp = params->w;
    params->w = params->h;
    params->h = tmp;
}

void rot(int dir, Image* image) {
    if (!image->pixels) return; // Aucune image
    long i, j, k, width, height;

    Uint8* pixelsM = image->pixels;
    Uint8* pixelsTmp = NULL; // Tableau de pixels temporaire

    width = image->width;
    height = image->height;

    copyPixels(pixelsM, &pixelsTmp, width, height, &width, &height); // Copie pixelsM vers pixelsTmp
    if (pixelsTmp == NULL) return;

    if(dir == 1) {   // rotation horaire
        for(i=0; i<height; i++){
            for(j=0; j<width; j++){
                for(k = 0; k < 4; k++) {
                   pixelsM[((j+1)*height-i-1)*4+k] = pixelsTmp[(i*width+j)*4+k];
                }
            }
        }
    }
    else if(dir == -1) { // rotat° anti-horaire
        for(i=0; i<width; i++){
            for(j=0; j<height; j++){
                for(k = 0; k < 4; k++) {
                   pixelsM[(i*height+j)*4+k] = pixelsTmp[((j+1)*width-i-1)*4+k];
                }
            }
        }
    }

    image->width = height; // Intervertit la largeur et hauteur
    image->height = width;
    if (pixelsTmp) free(pixelsTmp);
}

fonctionsSousMenus.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"

int buttonsTGA(SDL_Event event) {
    if (event.button.button == SDL_BUTTON_LEFT) {
        int x = event.button.x;
        int y = event.button.y;
        //printf("\n%d %d   ", x, y);
        if (x > 15 && x < 218 && y > 9 && y < 40) return 1; // 16 bits
        else if (x > 15 && x < 218 && y > 48 && y < 85) return 2; // 24 bits
        else if (x > 15 && x < 218 && y > 95 && y < 126) return 3; // 32 bits
        else if (x > 15 && x < 218 && y > 136 && y < 174) return 4; // RLE
        else if (x > 44 && x < 92 && y > 194 && y < 220) return 99; // OK
        else if (x > 95 && x < 181 && y > 192 && y < 220) return 0; // Annuler
    }
    return -1;
}

int buttonsBMP(SDL_Event event) {
    if (event.button.button == SDL_BUTTON_LEFT) {
        int x = event.button.x;
        int y = event.button.y;
        //printf("\n%d %d   ", x, y);
        if (x > 27 && x < 114 && y > 15 && y < 51) return 1; // 24 bits
        else if (x > 26 && x < 115 && y > 53 && y < 82) return 2; // 32 bits
        else if (x > 3 && x < 52 && y > 112 && y < 137) return 99; // OK
        else if (x > 56 && x < 137 && y > 112 && y < 139) return 0; // Annuler
    }
    return -1; // Aucune action
}

int buttonsFus(SDL_Event event) {
    if (event.button.button == SDL_BUTTON_LEFT) {
        int x = event.button.x;
        int y = event.button.y;
        if (x > 22 && x < 175 && y > 16 && y < 37) return 1; // Superposition
        else if (x > 213 && x < 276 && y > 16 && y < 37) return 2; // Alpha
        else if (x > 22 && x < 116 && y > 66 && y < 84) return 3; // Addition
        else if (x > 137 && x < 279 && y > 66 && y < 84) return 4; // Soustraction
        else if (x > 22 && x < 105 && y > 111 && y < 133) return 5; // Eclaircir
        else if (x > 171 && x < 276 && y > 111 && y < 133) return 6; // Obscurcir
        else if (x > 22 && x < 101 && y > 162 && y < 184) return 7; // Produit
        else if (x > 185 && x < 278 && y > 162 && y < 181) return 8; // Lumire
        else if (x > 22 && x < 210 && y > 208 && y < 228) return 9; // DensitŽ
        else if (x > 64 && x < 115 && y > 263 && y < 290) return 99; // OK
        else if (x > 133 && x < 237 && y > 263 && y < 290) return 0; // Annuler
    }
    return -1; // Aucune action
}

int evenementsMenu(int id, int ext, Params* params) {
    SDL_Event event;

    while (SDL_PollEvent(&event)) {
        if (event.window.windowID != id) continue; // Limite à une fenêtre

        switch (event.type) {
            case SDL_WINDOWEVENT:
                if (event.window.event == SDL_WINDOWEVENT_CLOSE) return 0;
                break;

            case SDL_QUIT: return 0;

            case SDL_KEYDOWN: {
                if (event.key.keysym.sym == SDLK_ESCAPE)  return 0;
                break;
            }

            case SDL_MOUSEBUTTONDOWN:
                if (ext == 0) return buttonsBMP(event);
                else if (ext == 1) return buttonsTGA(event);
                else if (params->fus.etat) return buttonsFus(event);
                break;
        }
    }
    return -1; // Aucune action
}

void traceTexture(SDL_Renderer* renderer, SDL_Texture* texture, int x, int y, int w, int h) {
    SDL_Rect bmpPos;
    bmpPos.x = x;
    bmpPos.y = y;
    bmpPos.w = w;
    bmpPos.h = h;
    SDL_RenderCopy(renderer, texture, NULL, &bmpPos);
}

void actionsBMP(Image* image, int action, SDL_Renderer* renderer, SDL_Texture* textureEntoure) {
    if (action < 0) return;

    switch (action) {
        case 1 :
            image->bpp = 24;
            break;
        case 2 :
            image->bpp = 32;
            break;
        default :
            break;
    }
    if (image->bpp == 24) traceTexture(renderer, textureEntoure, 5, 12, 130, 45);
    if (image->bpp == 32) traceTexture(renderer, textureEntoure, 5, 47, 130, 45);
}

void actionsTGA(Image* image, int action, SDL_Renderer* renderer, SDL_Texture* textureEntoure, SDL_Texture* textureEntoureC, SDL_Texture* textureRaye) {
    if (action < 0) return;

    switch (action) {
        case 1 :
            image->bpp = 16;
            break;
        case 2 :
            image->bpp = 24;
            break;
        case 3 :
            image->bpp = 32;
            break;
        case 4 :
            image->rle = !(image->rle);
            break;
        default :
            break;
    }
    if (image->bpp == 16) traceTexture(renderer, textureEntoure, 47, 7, 130, 45);
    if (image->bpp == 24) traceTexture(renderer, textureEntoure, 47, 46, 130, 45);
    if (image->bpp == 32) traceTexture(renderer, textureEntoure, 47, 87, 130, 45);
    if (image->rle) traceTexture(renderer, textureEntoureC, 7, 135, 210, 45);
    else traceTexture(renderer, textureRaye, 7, 135, 210, 45);
}

int displayMenu(int ext, Image* image, Params* params, Image* imageO, Image* imageF, Image* imageCM, char* urlf) {
    SDL_Window* window = NULL;
    Uint8* pixelsTmp = NULL; // Tableau de pixels temporaire
    if (ext == 0) window = SDL_CreateWindow("BMP", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 143, 143, SDL_WINDOW_SHOWN);
    else if (ext == 1) window = SDL_CreateWindow("TGA", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 226, 226, SDL_WINDOW_SHOWN);
    else if (params->fus.etat) window = SDL_CreateWindow("FUSIONS", 200, 50, 300, 300, SDL_WINDOW_SHOWN);
    if (window == NULL) return 0;

    int ret = 0, id = SDL_GetWindowID(window), action = 1;

    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);

    if (renderer) {
        id = SDL_GetWindowID(window);
        SDL_Surface* surface = NULL;
        SDL_Surface* surfaceEntoure = SDL_LoadBMP("interfaceEntoure.bmp");
        SDL_Surface* surfaceEntoureC = SDL_LoadBMP("interfaceEntoureC.bmp");
        SDL_Surface* surfaceRaye = SDL_LoadBMP("interfaceRaye.bmp");

        if (ext == 0) surface = SDL_LoadBMP("interfaceBMP.bmp");
        else if (ext == 1) surface = SDL_LoadBMP("interfaceTGA.bmp");
        else if (params->fus.etat) {
            surface = SDL_LoadBMP("interfaceFusion.bmp");
            copyPixels(image->pixels, &pixelsTmp, image->width, image->height, &(image->width), &(image->height));
            if (pixelsTmp == NULL) return 0;
        }

        if (surface && surfaceEntoure && surfaceEntoureC && surfaceRaye) {
            SDL_Texture* texture = SDL_CreateTextureFromSurface(renderer, surface);
            SDL_Texture* textureEntoure = SDL_CreateTextureFromSurface(renderer, surfaceEntoure);
            SDL_Texture* textureEntoureC = SDL_CreateTextureFromSurface(renderer, surfaceEntoureC);
            SDL_Texture* textureRaye = SDL_CreateTextureFromSurface(renderer, surfaceRaye);

            if (texture && textureEntoure && textureEntoureC && textureRaye) {

                if (params->fus.etat && params->fus.mode) action = params->fus.mode;

                while (action) {

                    if (action == 99) { // OK
                        ret = 1;
                        params->fus.etat = 0;
                        break;
                    }
                    if (action == 0) { // Annuler
                        params->fus.etat = 0;
                        break;
                    }
                    if (action > 0) {
                        SDL_RenderCopy(renderer, texture, NULL, NULL);
                        if (ext == 0) actionsBMP(image, action, renderer, textureEntoure);
                        else if (ext == 1) actionsTGA(image, action, renderer, textureEntoure, textureEntoureC, textureRaye);
                        else if (params->fus.etat) {
                            actionsFus(image, pixelsTmp, imageF, action, renderer, textureEntoure, imageCM, urlf, params);
                            display(image);
                        }

                        SDL_RenderPresent(renderer);

                    }

                    action = evenementsMenu(id, ext, params);

                }
                if (params->fus.etat) {
                    params->fus.etat = 0;
                    if (!action) {
                        params->fus.mode = 0;
                        copyPixels(pixelsTmp, &image->pixels, image->width, image->height, &(image->width), &(image->height));
                    }

                }

            }
            if (texture) SDL_DestroyTexture(texture);
            if (textureEntoure) SDL_DestroyTexture(textureEntoure);
            if (textureEntoureC) SDL_DestroyTexture(textureEntoureC);
            if (textureRaye) SDL_DestroyTexture(textureRaye);
        }
        if (surface) SDL_FreeSurface(surface);
        if (surfaceEntoure) SDL_FreeSurface(surfaceEntoure);
        if (surfaceEntoureC) SDL_FreeSurface(surfaceEntoureC);
        if (surfaceRaye) SDL_FreeSurface(surfaceRaye);
    }

    SDL_DestroyWindow(window);
    return ret;
}


fonctionsTGA.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"

//-------------- Écriture --------------

void saveTGA_RLE(FILE* fic, Uint8* pixels, int* i, int* m) {

    if (*m == 0) { // S'il n'y a plus de pixels non encodés à écrire
        Uint8 byte, b, v, r, a, b2, v2, r2, a2;
        int n = 0;

        // Compte le nb de pixels identiques qui se suivent

        // Tant que les deux prochains pixels sont égaux
        while (1) {
            b = pixels[(*i)]; // Premier pixel
            v = pixels[(*i)+1];
            r = pixels[(*i)+2];
            a = pixels[(*i)+3];

            b2 = pixels[(*i)+4]; // Second pixel
            v2 = pixels[(*i)+5];
            r2 = pixels[(*i)+6];
            a2 = pixels[(*i)+7];

            if (b == b2 && v == v2 && r == r2 && a == a2) {
                (*i) += 4; // On passe le pixel sans l'écrire
                n++; // Nb de pixels égaux

                if (n == 127) break; // 127 max (7 bits)
            }
            else break;
        }

        if (n == 0) { // Si aucun pixel égaux
            // Compte le nb de pixels différents qui se suivent
            int j = 0;
            while (1) {
                b = pixels[(*i)+j]; // Premier pixel
                v = pixels[(*i)+j+1];
                r = pixels[(*i)+j+2];
                a = pixels[(*i)+j+3];

                b2 = pixels[(*i)+j+4]; // Second pixel
                v2 = pixels[(*i)+j+5];
                r2 = pixels[(*i)+j+6];
                a2 = pixels[(*i)+j+7];

                if (b != b2 || v != v2 || r != r2 || a != a2) {
                    j += 4; // On passe le pixel sans l'écrire
                    (*m)++; // Nb de pixels différents

                    if (*m == 127) break; // 127 max (7 bits)
                }
                else break;
            }
        }

        if (n) byte = n | 128; // Met le dernier bit à 1;
        else byte = (*m);

        fwrite(&byte, 1, 1, fic);
    }
    else {
        (*m)--;
    }
}

void saveTGA_BVRA32(FILE* fic, Uint8* pixels, int imax, int rle) {
    if (!rle) fwrite(pixels, 1, imax, fic);
    else {
        int i, m = 0;
        for (i = 0 ; i < imax ; ) {
            saveTGA_RLE(fic, pixels, &i, &m);
            fwrite(&pixels[i++], 1, 1, fic); // B
            fwrite(&pixels[i++], 1, 1, fic); // V
            fwrite(&pixels[i++], 1, 1, fic); // R
            fwrite(&pixels[i++], 1, 1, fic); // A
        }
    }
}

void saveTGA_BVR24(FILE* fic, Uint8* pixels, int imax, int rle) {
    int i, m = 0;
    for (i = 0 ; i < imax ; ) {
        if (rle) saveTGA_RLE(fic, pixels, &i, &m);
        fwrite(&pixels[i++], 1, 1, fic); // B
        fwrite(&pixels[i++], 1, 1, fic); // V
        fwrite(&pixels[i++], 1, 1, fic); // R
        i++; // A
    }
}

void saveTGA_BVR16(FILE* fic, Uint8* pixels, int imax, int rle) {
    int i, m = 0;
    Uint16 word;
    double fac = 255./31.;
    for (i = 0 ; i < imax ; ) {
        if (rle) saveTGA_RLE(fic, pixels, &i, &m);
        word = (Uint8) (pixels[i++] / fac);                     // 0000 0000 0001 1111
        word = word | (((Uint8) (pixels[i++] / fac)) << 5) ;    // 0000 0011 1110 0000
        word = word | (((Uint8) (pixels[i++] / fac)) << 10) ;   // 0111 1100 0000 0000
        i++; // A
        fwrite(&word, 2, 1, fic); // BVR chacun sur 5 bits
    }
}

void saveTGA(FILE* fic, Image* imageM, Image* imageCM) {
    Uint8 byte, colormapDepth;
    Uint16 word, colormapStart, colormapSize;
    Uint32 dword;
    int colormap = 0, wh;
    char signature[18] = "TRUEVISION-XFILE.";

    if (imageM->bpp <= 8) colormap = 1;

    byte = 0;
    fwrite(&byte, 1, 1, fic); // 00

    fwrite(&colormap, 1, 1, fic); // Palette (bool) si 8 bits par pixels

    if (!imageM->rle) byte = 1;
    else byte = 9;
    if (!colormap) byte += 1;
    fwrite(&byte, 1, 1, fic); // Type d'image

    colormapStart = 0;
    colormapSize = 0;
    colormapDepth = 0;
    fwrite(&colormapStart, 2, 1, fic); // Début Palette
    fwrite(&colormapSize, 2, 1, fic); // Taille Palette
    fwrite(&colormapDepth, 1, 1, fic); // Profondeur Palette

    word = 0;
    fwrite(&word, 2, 1, fic); // Pos X
    fwrite(&word, 2, 1, fic); // Pos Y

    word = (Uint16)imageM->width;
    fwrite(&word, 2, 1, fic); // Largeur
    word = (Uint16)imageM->height;
    fwrite(&word, 2, 1, fic); // Hauteur
    wh = imageM->width * imageM->height;

    byte = (Uint8)imageM->bpp;
    fwrite(&byte, 1, 1, fic); // Profondeur : nb de bit par pixels

    byte = 0;
    fwrite(&byte, 1, 1, fic); // Attributs*/

    if (colormap) {

    }

    mirror('h', imageM);
    switch (imageM->bpp) {
        //case (8) : saveTGA_CM8(fic, pixels, wh * 4, pixelsCM, rle); break;
        case (16) : saveTGA_BVR16(fic, imageM->pixels, wh * 4, imageM->rle); break;
        case (24) : saveTGA_BVR24(fic, imageM->pixels, wh * 4, imageM->rle); break;
        case (32) : saveTGA_BVRA32(fic, imageM->pixels, wh * 4, imageM->rle); break;
        default : break;
    }

    // Pied

    dword = 0;
    fwrite(&dword, 4, 1, fic); // Taille de l'extension
    fwrite(&dword, 4, 1, fic); // Taille de lu dico de dev (?)
    fwrite(signature, 1, 18, fic);


}

//-------------- Lecture --------------

void readTGA_RLE(FILE* fic, Uint8* pixels, int* i, int* n, int* m) {
    if (*n) { // Pixels encodés à copier n fois
        Uint8 b = pixels[(*i)-4];
        Uint8 v = pixels[(*i)-3]; // Dernier pixel lu
        Uint8 r = pixels[(*i)-2];
        Uint8 a = pixels[(*i)-1];
        while (*n > 0) {
            pixels[(*i)++] = b;
            pixels[(*i)++] = v;
            pixels[(*i)++] = r;
            pixels[(*i)++] = a;
            (*n)--;
        }
        *m = 0;
        *n = 0;
    }

    if (*m == 0) { // S'il n'y a plus de pixels non encodés à lire
        Uint8 byte;
        fread(&byte, 1, 1, fic);
        int cpt = (int)(byte & 0x7F); // Nb de pixels à lire (encodés ou non) (7 premiers bits)

        if ((byte >> 7) == 0) { // Pixels non encodés ? (dernier bit)
            *m = cpt; // m pixels non encodés à lire directement en plus du prochain
            *n = 0;
        }
        else { // Pixels encodés
            *m = 0;
            *n = cpt; // Prochain pixel à copier n fois
        }
    }
    else {
        (*m)--;
    }
}

void readTGA_BVRA32(FILE* fic, Uint8* pixels, int imax, int rle) {
    if (!rle) fread(pixels, 1, imax, fic);
    else {
        int i, n = 0, m = 0;
        for (i = 0 ; i < imax ; ) {
            readTGA_RLE(fic, pixels, &i, &n, &m);
            fread(&pixels[i++], 1, 1, fic); // B
            fread(&pixels[i++], 1, 1, fic); // V
            fread(&pixels[i++], 1, 1, fic); // R
            fread(&pixels[i++], 1, 1, fic); // A
        }
    }
}

void readTGA_BVR24(FILE* fic, Uint8* pixels, int imax, int rle) {
    int i, n = 0, m = 0;
    for (i = 0 ; i < imax ; ) {
        if (rle) readTGA_RLE(fic, pixels, &i, &n, &m);
        fread(&pixels[i++], 1, 1, fic); // B
        fread(&pixels[i++], 1, 1, fic); // V
        fread(&pixels[i++], 1, 1, fic); // R
        pixels[i++] = 255; // Alpha
    }
}

void readTGA_BVR16(FILE* fic, Uint8* pixels, int imax, int rle) {
    int i, n = 0, m = 0;
    Uint16 word;
    double fac = 255./31.;
    for (i = 0 ; i < imax ; ) {
        if (rle) readTGA_RLE(fic, pixels, &i, &n, &m);
        fread(&word, 2, 1, fic); // BVR chacun sur 5 bits
        pixels[i++] = (Uint8)((word & 0x001F) * fac); // 0000 0000 0001 1111 = 001F
        pixels[i++] = (Uint8)((word >> 5 & 0x001F) * fac); // 0000 0011 1110 0000
        pixels[i++] = (Uint8)((word >> 10) * fac); // 0111 1100 0000 0000
        pixels[i++] = 255; // Alpha
    }
}

void readTGA_CM8(FILE* fic, Uint8* pixels, int imax, Uint8* cm, int rle) {
    Uint8 byte;
    int i, n = 0, m = 0;
    for (i = 0 ; i < imax ; ) {
        if (rle) readTGA_RLE(fic, pixels, &i, &n, &m);
        fread(&byte, 1, 1, fic);
        pixels[i++] = cm[byte * 4 + 0];
        pixels[i++] = cm[byte * 4 + 1];
        pixels[i++] = cm[byte * 4 + 2];
        pixels[i++] = cm[byte * 4 + 3];
    }
}

void readTGA_TypeImage(FILE* fic, Image* imageO, int* colormap) {
    Uint8 byte;

    fread(&byte, 1, 1, fic); // Type d'image
    switch(byte) {
        case (0)  : return;
        case (1)  : *colormap = 1; imageO->rle = 0; break;
        case (2)  : *colormap = 0; imageO->rle = 0; break;
        case (3)  : *colormap = 0; imageO->rle = 0; break;
        case (9)  : *colormap = 1; imageO->rle = 1; break;
        case (10) : *colormap = 0; imageO->rle = 1; break;
        case (11) : *colormap = 0; imageO->rle = 1; break;
        default   : *colormap = 0; imageO->rle = 0; break;
    }
}

void readTGA_Header(FILE* fic, long ficsize, Image* imageO, Uint8* colormapDepth, Uint16* colormapStart, Uint16* colormapSize, int* colormap) {
    Uint8 byte, colormapType;
    Uint16 word;

    // En-tête (18 octets)
    if (!checkBytesOK(fic, ficsize, 18)) return;

    fread(&byte, 1, 1, fic); // 00
    if (byte != 0) return;
    fread(&colormapType, 1, 1, fic); // Palette (bool) (+ valeurs fac. pour dev)

    readTGA_TypeImage(fic, imageO, colormap); // Type d'image

    fread(colormapStart, 2, 1, fic); // Début Palette
    fread(colormapSize, 2, 1, fic); // Taille Palette
    fread(colormapDepth, 1, 1, fic); // Profondeur Palette

    fread(&word, 2, 1, fic); // Pos X
    fread(&word, 2, 1, fic); // Pos Y

    fread(&word, 2, 1, fic); // Largeur
    imageO->width = (long)word;
    fread(&word, 2, 1, fic); // Hauteur
    imageO->height = (long)word;

    fread(&byte, 1, 1, fic); // Profondeur : nb de bit par pixels
    imageO->bpp = (int)byte;

    fread(&byte, 1, 1, fic); // Attributs
}

void loadTGA(FILE* fic, long ficsize, Image* imageO, Image* imageCM) {
    Uint8 colormapDepth;
    Uint16 colormapStart, colormapSize;
    int wh, colormap;

    // En-tête
    readTGA_Header(fic, ficsize, imageO, &colormapDepth, &colormapStart, &colormapSize, &colormap);

    // Palette de couleurs
    // Une palette de 16 peut être stockée sur une palette de 256, d'où le déplacement
    fseek(fic, colormapStart, SEEK_CUR);

    clearCM(imageCM->pixels); // Nettoie la palette
    if (colormap) {
        switch (colormapDepth) {
            case (16) : readTGA_BVR16(fic, imageCM->pixels, ((int)colormapSize) * 4, 0); break;
            case (24) : readTGA_BVR24(fic, imageCM->pixels, ((int)colormapSize) * 4, 0); break;
            case (32) : readTGA_BVRA32(fic, imageCM->pixels, ((int)colormapSize) * 4, 0); break;
            default : break;
        }
    }

    // Création du tableau contenant les pixels de l'image
    wh = (imageO->width) * (imageO->height);
    imageO->pixels = malloc(sizeof(Uint8) * wh * 4);
    if (imageO->pixels == NULL) return;

    switch (imageO->bpp) {
        case (8) : readTGA_CM8(fic, imageO->pixels, wh * 4, imageCM->pixels, imageO->rle); break;
        case (16) : readTGA_BVR16(fic, imageO->pixels, wh * 4, imageO->rle); break;
        case (24) : readTGA_BVR24(fic, imageO->pixels, wh * 4, imageO->rle); break;
        case (32) : readTGA_BVRA32(fic, imageO->pixels, wh * 4, imageO->rle); break;
        default : break;
    }

    mirror('h', imageO);

}

main.c

#include <stdlib.h>
#include <stdio.h>
#include <SDL2/SDL.h>
#include "prototypes.h"

int main(int argc, char** argv)
{
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        fprintf(stdout,"Echec de l'initialisation de la SDL (%s)\n", SDL_GetError());
        return -1;
    }

    Image imageO; // Image d'origine, sans fenêtre
    Image imageM; // Image modifiée, affichée, avec fenêtre
    Image imageF;    // Image à fusionner
    Image imageCtrl; // Fenêtre de contrôle, avec fenêtre et Renderer
    Image imageCM; // Palette de couleur, avec fenêtre

    if (!initImage(&imageO, NULL, 0, 0, 0, 0, 0, 0)) return 0;
    if (!initImage(&imageM, "Hurtel Visio", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 300, 300, SDL_WINDOW_SHOWN, 0)) return 0;
    if (!initImage(&imageCM, "Palette", 50, 600, 160, 160, SDL_WINDOW_SHOWN, 0)) return 0;
    if (!initImage(&imageF, NULL, 0, 0, 0, 0, 0, 0)) return 0;
    if (!initImage(&imageCtrl, "Hurtel Visio", 50, 50, 291, 627, SDL_WINDOW_SHOWN, 1)) return 0;

    if (!initTabImage(&imageCM, 256*4)) return 0; // Palette toujours de 256 couleurs max

    char url[1024]; url[0] = '\0';
    char urlf[1024]; urlf[0] = '\0';

    displayCtrl(&imageCtrl);

    actionArgument(&imageO, &imageM, &imageCM, &imageF, url, urlf, argc, argv);

    actionLoop(&imageO, &imageM, &imageCM, &imageCtrl, &imageF, url, urlf);

    clearImage(&imageO);
    clearImage(&imageM);
    clearImage(&imageF);
    clearImage(&imageCtrl);
    clearImage(&imageCM);
    SDL_Quit();

    return 0;
}

prototypes.h

// En-tête TGA
/*typedef struct {
    uint8_t   head;           // 00
    uint8_t   colormapType;   // Palette (bool) (+ valeurs fac. pour dev)
    uint8_t   type;           // Type d'image
    uint16_t  colormapStart;  // Début Palette (pos relative)
    uint16_t  colormapSize;   // Taille Palette
    uint8_t   colormapDepth;  // Profondeur Palette
    uint16_t  posX;           // Pos X
    uint16_t  posY;           // Pos Y
    uint16_t  width;          // Largeur
    uint16_t  height;         // Hauteur
    uint8_t   bpp;            // Profondeur : nb de bit par pixels
    uint8_t   attr;           // Attributs
} TGAHeader;
*/

typedef struct Image {
    SDL_Window*     window;
    SDL_Renderer*   renderer;
    int             id;
    Uint8*          pixels;
    long            width;
    long            height;
    int             bpp;
    int             rle;
} Image;

typedef struct Rogne {
    int etat;
    long x1;
    long x2;
    long y1;
    long y2;
} Rogne;

typedef struct Fusion {
    int etat;   // de la fenetre menu
    int mode;   // fusion choisie
} Fusion;

typedef struct Params {
    int lumi;
    int cont;
    int grey;
    int w;
    int h;
    Fusion fus;
    Rogne rogne;
} Params;


// F O N C T I O N S
void urlToExt(char* url, char* ext);
void urlToName(char* url, char* name);
void urlToDir(char* url, char* dir);
void clearCM(Uint8* pixels);
// Fonctions structure Image
int initImage(Image* image, char* title, int x, int y, int w, int h, Uint32 flags, int render);
int initTabImage(Image* image, int q);
void clearImage(Image* image);
void save(char* url);
void my_open(char* url);
long ficSize(FILE* fic);
int checkBytesOK(FILE* fic, long ficsize, long n);
void renameWindow(Image* image, char* url);
void loading(Image* imageO, Image* imageCM, char* url, int force);
void saving(Image* imageM, Image* imageCM, char* url, Params *params);
void resetOptions(Params* params);
void display(Image* image);
void displayCM(Image* imageCM);
void displayCtrl(Image* imageCtrl);


// F O N C T I O N S   I M A G E S
int XYtoID(int x, int y, int width);
void IDtoXY(int id, int width, int* x, int* y);
void permut(Uint8* pixels, int a, int b);
double lim(int a);
int limcont(int a);
int limlum(int a);
Uint8 mixer(Uint8 a, Uint8 b, Uint8 c);
void copyPixels(Uint8* pixelsO, Uint8** pixelsM, long widthO, long heightO, long *widthM, long *heightM);


// F O N C T I O N S   R E S I Z E
void actionResize(Params* params, int w, int h);
void resizePixels(Image* image, Params* params);


// F O N C T I O N S   R O G N E
void rogneMinMax(int* vmin, int* vmax, int v1, int v2);
void rognePreview(Image* imageM, Rogne rogne);
void rogneApply(Image* imageM, Rogne rogne);


// F O N C T I O N S   R O T
void actionRot(Params* params, Image* imageO, Image* imageF, int dir);
void rotRogne(Params* params, int w, int h, int dir);
void rot(int dir, Image* image);


// F O N C T I O N S   M I R O I R
void actionMirror(Params* params, Image* imageO, Image* imageF, char dir) ;
void mirrorRogne(Params* params, int w, int h, char dir);
void mirror(char dir, Image* image);


// F O N C T I O N S   F I L T R E S
void actionLumi(Params* params, int val, int def);
void actionCont(Params* params, int val, int def);
void actionGrey(Params* params);
void contrast(Image* imageM, int cont, int lumi);
void invert(Image * imageO);
void greylevel(Image * imageO, Image * imageM, int grey);
int greymax(int a, int b, int c);
void alpha(Image* imageM);


// F O N C T I O N S   N E X T P R E V
void actionNextPrev(Image* imageO, Image* imageCM, char* url, Params* params, int sens);
void parcourir(char* url, int sens);


// F O N C T I O N S   F U S I O N;
void actionsFus(Image* imageM, Uint8* pixelsTmp, Image* imageF, int action, SDL_Renderer* renderer, SDL_Texture* textureEntoure, Image* imageCM, char* urlf, Params* param);
void superposition(Image * imageM, Image * imageF, Uint8* pt);
void fusalpha(struct Image * imageM, struct Image * imageF,  Uint8* pt);
void eclaircir(struct Image * imageM, struct Image * imageF, Uint8 * pt);
void obscurcir(struct Image * imageM, struct Image * imageF, Uint8 * pt);
void addition(struct Image * imageM, struct Image * imageF, Uint8 * pt);
void soustraction(struct Image * imageM, struct Image * imageF, Uint8 * pt);
void produit(struct Image * imageM, struct Image * imageF, Uint8 * pt);
void lumiere(struct Image * imageM, struct Image * imageF, Uint8 * pt);
void densite(struct Image * imageM, struct Image * imageF, Uint8 * pt);


// F O N C T I O N S   M E N U
int buttons(SDL_Event event, int idImg, int idCtrl);
void rogneDefine(Params* params, int x, int y, int etat);
int evenements(int idImg, int idCtrl, int idCM, int* x, int* y);
void actionOpen(Image* imageO, Image* imageCM, char* url, Params* params);
void actionReset(Image* imageO, Image* imageCM, char* url, Params* params);
void actionArgument(Image* imageO, Image* imageM, Image* imageCM, Image* imageF, char* url, char* urlf, int argc, char** argv);
void actionLoop(Image* imageO, Image* imageM, Image* imageCM, Image* imageCtrl, Image* imageF, char* url, char* urlf);


// F O N C T I O N S   T G A
//-------------- Ecriture --------------
void saveTGA_RLE(FILE* fic, Uint8* pixels, int* i, int* m);
void saveTGA_BVRA32(FILE* fic, Uint8* pixels, int imax, int rle);
void saveTGA_BVR24(FILE* fic, Uint8* pixels, int imax, int rle);
void saveTGA_BVR16(FILE* fic, Uint8* pixels, int imax, int rle);
void saveTGA(FILE* fic, Image* imageM, Image* imageCM);
//-------------- Lecture --------------
void readTGA_RLE(FILE* fic, Uint8* pixels, int* i, int* n, int* m);
void readTGA_BVRA32(FILE* fic, Uint8* pixels, int imax, int rle);
void readTGA_BVR24(FILE* fic, Uint8* pixels, int imax, int rle);
void readTGA_BVR16(FILE* fic, Uint8* pixels, int imax, int rle);
void readTGA_CM8(FILE* fic, Uint8* pixels, int imax, Uint8* cm, int rle);
void readTGA_TypeImage(FILE* fic, Image* imageO, int* colormap);
void readTGA_Header(FILE* fic, long ficsize, Image* imageO, Uint8* colormapDepth, Uint16* colormapStart, Uint16* colormapSize, int* colormap);
void loadTGA(FILE* fic, long ficsize, Image* imageO, Image* imageCM);


// F O N C T I O N S   S O U S   M E N U S
int buttonsTGA(SDL_Event event);
int buttonsBMP(SDL_Event event);
int buttonsFus(SDL_Event event);
int evenementsMenu(int id, int ext, Params* params);
void traceTexture(SDL_Renderer* renderer, SDL_Texture* texture, int x, int y, int w, int h);
void actionsBMP(Image* image, int action, SDL_Renderer* renderer, SDL_Texture* textureEntoure);
void actionsTGA(Image* image, int action, SDL_Renderer* renderer, SDL_Texture* textureEntoure, SDL_Texture* textureEntoureC, SDL_Texture* textureRaye);
int displayMenu(int ext, Image* image, Params* params, Image* imageO, Image* imageF, Image* imageCM, char* urlf);


// F O N C T I O N S   B M P
//-------------- Écriture --------------
void saveBMP_BVRA32(FILE* fic, Uint8* pixels, int imax, int w, int rle);
void saveBMP_BVRA24(FILE* fic, Uint8* pixels, int imax, int bt, int w, int rle);
void saveBMP(FILE* fic, Image* imageM, Image* imageCM);
//-------------- Lecture --------------
void readBMP_BVRA32_CM(FILE* fic, Uint8* pixels, int imax);
void readBMP_BVRA24_CM(FILE* fic, Uint8* pixels, int imax);
void readBMP_BVRA32(FILE* fic, Uint8* pixels, int imax, int w, int rle);
void readBMP_BVRA24(FILE* fic, Uint8* pixels, int imax, int bt, int w, int rle);
void readBMP_CM8(FILE* fic, Uint8* pixels, int imax, Uint8* cm, int bt, int w, int rle);
void loadBMP(FILE* fic, long ficsize, Image* imageO, Image* imageCM);