//////////////////////////////////////////////////////////////////////
//                                                                  //
//  effets01.cpp : Ce fichier contient l'implémentation des effets  //
//                 les plus simples                                 //
//                                                                  //
//////////////////////////////////////////////////////////////////////

#include <cmath>
#include "type_image.h"


// Inversion horizontale de l'image

void type_image::Eff01FlipH(void)
{
	float Temp;

	for (int i = 0; i < Width / 2; i++)
		for (int j = 0; j < Height; j++)
		{
			Temp = (*this)(i,j, ROUGE);
			(*this)(i,j, ROUGE) = (*this)(Width - 1 - i, j, ROUGE);
			(*this)(Width - 1 - i, j, ROUGE) = Temp;

			Temp = (*this)(i,j, VERT);
			(*this)(i,j, VERT) = (*this)(Width - 1 - i, j, VERT);
			(*this)(Width - 1 - i, j, VERT) = Temp;

			Temp = (*this)(i,j, BLEU);
			(*this)(i,j, BLEU) = (*this)(Width - 1 - i, j, BLEU);
			(*this)(Width - 1 - i, j, BLEU) = Temp;
		}
}


// Inversion verticale de l'image

void type_image::Eff01FlipV(void)
{
	float Temp;

	for (int i = 0; i < Width; i++)
		for (int j = 0; j < Height / 2; j++)
		{
			Temp = (*this)(i,j, ROUGE);
			(*this)(i,j, ROUGE) = (*this)(i, Height - 1 - j, ROUGE);
			(*this)(i, Height - 1 - j, ROUGE) = Temp;

			Temp = (*this)(i,j, VERT);
			(*this)(i,j, VERT) = (*this)(i, Height - 1 - j, VERT);
			(*this)(i, Height - 1 - j, VERT) = Temp;

			Temp = (*this)(i,j, BLEU);
			(*this)(i,j, BLEU) = (*this)(i, Height - 1 - j, BLEU);
			(*this)(i, Height - 1 - j, BLEU) = Temp;
		}
}


// Rotation vers la droite (clock-wise) d'un quart de tour

void type_image::Eff01RotCW(void)
{
	float *PtrNouveau = new float[Width*Height*3];

	for (int i = 0; i < Width; i++)
		for (int j = 0; j < Height; j++)
		{
			PtrNouveau[(j + i*Height)*3 + int(ROUGE)] = (*this)(i, Height - 1 - j, ROUGE);
			PtrNouveau[(j + i*Height)*3 + int(VERT)] = (*this)(i, Height - 1 - j, VERT);
			PtrNouveau[(j + i*Height)*3 + int(BLEU)] = (*this)(i, Height - 1 - j, BLEU);
		}

	delete [] PtrImage;

	PtrImage = PtrNouveau;

	// Permutation
	Width ^= Height ^= Width ^= Height;
}


// Rotation vers la gauche (counter-clock-wise) d'un quart de tour

void type_image::Eff01RotCCW(void)
{
	float *PtrNouveau = new float[Width*Height*3];

	for (int i = 0; i < Width; i++)
		for (int j = 0; j < Height; j++)
		{
			PtrNouveau[(j + i*Height)*3 + int(ROUGE)] = (*this)(Width - 1 - i, j, ROUGE);
			PtrNouveau[(j + i*Height)*3 + int(VERT)] = (*this)(Width - 1 - i, j, VERT);
			PtrNouveau[(j + i*Height)*3 + int(BLEU)] = (*this)(Width - 1 - i, j, BLEU);
		}

	delete [] PtrImage;

	PtrImage = PtrNouveau;

	// Permutation
	Width ^= Height ^= Width ^= Height;
}


// Élimination de la couleur rouge

void type_image::Eff01KillRouge(void)
{
	for (int i = 0; i < Width; i++)
		for (int j = 0; j < Height; j++)
			(*this)(i, j, ROUGE) = 0;
}


// Élimination de la couleur vert

void type_image::Eff01KillVert(void)
{
	for (int i = 0; i < Width; i++)
		for (int j = 0; j < Height; j++)
			(*this)(i, j, VERT) = 0;
}


// Élimination de la couleur bleu

void type_image::Eff01KillBleu(void)
{
	for (int i = 0; i < Width; i++)
		for (int j = 0; j < Height; j++)
			(*this)(i, j, BLEU) = 0;
}


// Intensité lumineuse

void type_image::Eff01Intensite(float Facteur)
{
	for (int i = 0; i < Width*Height*3; i++)
	{
		PtrImage[i] *= Facteur;
		if (PtrImage[i] > 1)
			PtrImage[i] = 1;
	}
}


// Inversion de l'image: négatif

// Pour chaque pixel, on prend le complément à un.

void type_image::Eff01Negatif(void)
{
	for (int i = 0; i < Width*Height*3; i++)
		PtrImage[i] = 1 - PtrImage[i];
}


// Transformation de l'image en ton de gris

// On fait la moyenne de chacune des composantes de la couleur et on l'assigne à chaque couleur

void type_image::Eff01TonGris(void)
{
	for(int i = 0; i < Width; i++)
		for (int j = 0; j < Height; j++)
		{
			(*this)(i, j, ROUGE) = (*this)(i, j, VERT) = (*this)(i, j, BLEU) =
				( (*this)(i, j, ROUGE) + (*this)(i, j, VERT) + (*this)(i, j, BLEU) )/ 3;
		}
}


// Contour #1

// On prend la différence entre la valeur de droite et le pixel, puis celle de gauche, 
// du haut et du bas, et la couleur du nouveau pixel est la moyenne de tout ça.

void type_image::Eff01Contour1(float Facteur)
{
	float *PtrNouveau = new float[Width*Height*3];

	for (int i = 1; i < Width - 1; i++)
		for (int j = 1; j < Height - 1; j++)
			for (enum_type_couleur k = ROUGE; k <= BLEU; k = enum_type_couleur(k + 1))
			{
				
				PtrNouveau[(i + j*Width)*3 + int(k)] =
					(fabs((*this)(i-1, j, k) - (*this)(i+1, j, k)) +
					 fabs((*this)(i, j-1, k) - (*this)(i, j+1, k)) ) / Facteur;
				
				Valide(PtrNouveau[(i + j*Width)*3 + k]);
			}

	delete [] PtrImage;

	PtrImage = PtrNouveau;
}