Commit 24ab992d authored by BORNON Théophile's avatar BORNON Théophile

merge

parents c6ed9768 c43bd2bc
......@@ -5,10 +5,6 @@ VisualStudioVersion = 15.0.27004.2010
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessing", "S04_Projet\ImageProcessing.csproj", "{229D3602-654B-498B-9478-5CC3982C358C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessing_Benchmark", "ImageProcessing_Benchmark\ImageProcessing_Benchmark.csproj", "{54D04E0E-009D-4928-BEF8-B2FF464536CC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageProcessing_Test", "ImageProcessing_Test\ImageProcessing_Test.csproj", "{F0906169-0946-4552-A06C-1D57C52B1C10}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -19,14 +15,6 @@ Global
{229D3602-654B-498B-9478-5CC3982C358C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{229D3602-654B-498B-9478-5CC3982C358C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{229D3602-654B-498B-9478-5CC3982C358C}.Release|Any CPU.Build.0 = Release|Any CPU
{54D04E0E-009D-4928-BEF8-B2FF464536CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{54D04E0E-009D-4928-BEF8-B2FF464536CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{54D04E0E-009D-4928-BEF8-B2FF464536CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{54D04E0E-009D-4928-BEF8-B2FF464536CC}.Release|Any CPU.Build.0 = Release|Any CPU
{F0906169-0946-4552-A06C-1D57C52B1C10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F0906169-0946-4552-A06C-1D57C52B1C10}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F0906169-0946-4552-A06C-1D57C52B1C10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F0906169-0946-4552-A06C-1D57C52B1C10}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
This diff is collapsed.
......@@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace S04_Projet
{
class Filter
public class Filter
{
public static string[] Noms = new string[] {
"Augmenter le contraste",
......
......@@ -47,11 +47,11 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Filter.cs" />
<Compile Include="Menu.cs" />
<Compile Include="MultiThreadedTask.cs" />
<Compile Include="MyImage.cs" />
<Compile Include="Display.cs" />
<Compile Include="Options.cs" />
<Compile Include="Pixel.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace S04_Projet
{
class Menu
{
private string[] menuItems;
public Menu(string[] menuItems)
{
this.menuItems = menuItems;
}
public int ShowMenu(int xOffset, int yOffset)
{
int choosenItem = 0;
Console.SetCursorPosition(xOffset, yOffset);
for (int i = 0; i < menuItems.Length; i++)
{
Console.WriteLine(((choosenItem == i) ? ">> " : " ") + menuItems[i]);
}
ConsoleKeyInfo key;
do
{
key = Console.ReadKey();
Console.SetCursorPosition(xOffset, yOffset + choosenItem);
Console.Write(" ");
if (key.Key == ConsoleKey.DownArrow)
{
choosenItem++;
if (choosenItem == menuItems.Length) choosenItem = 0;
}
else if (key.Key == ConsoleKey.UpArrow)
{
choosenItem--;
if (choosenItem == -1) choosenItem = menuItems.Length - 1;
}
Console.SetCursorPosition(xOffset, yOffset + choosenItem);
Console.Write(">>");
} while (key.Key != ConsoleKey.Escape && key.Key != ConsoleKey.Enter);
if (key.Key == ConsoleKey.Escape) Environment.Exit(0);
return choosenItem;
}
}
}
......@@ -3,13 +3,14 @@ using System.Threading;
namespace S04_Projet
{
class MultiThreadedTask
unsafe class MultiThreadedTask
{
#region Attributs
public enum Operation
{
Load,
Filter
Filter,
Save
}
private enum RGB
......@@ -20,52 +21,83 @@ namespace S04_Projet
}
private byte[] file;
private byte[] NewRMatrix, NewGMatrix, NewBMatrix;
byte* rPixelPtr, gPixelPtr, bPixelPtr;
byte* filePtr;
private int nbPixel;
private int nbProcessors;
private Pixel[,] Pixels;
private Pixel[,] NewPixels;
private Options opt;
private short[,] filter;
private double factor;
private int size;
private Operation ToDo;
#endregion
public void setNbPixel(int nbPixel) => this.nbPixel = nbPixel;
public void setFile(byte[] file) => this.file = file;
public void SetNbPixel(int nbPixel) => this.nbPixel = nbPixel;
private Operation ToDo;
public void SetFile(byte[] file) => this.file = file;
public MultiThreadedTask(Operation ToDo, byte[] file, Options opt)
/// <summary>
/// Constructeur pour l'opération Filter
/// </summary>
/// <param name="ToDo"></param>
/// <param name="rPixelPtr"></param>
/// <param name="gPixelPtr"></param>
/// <param name="bPixelPtr"></param>
/// <param name="opt"></param>
/// <param name="filter"></param>
/// <param name="factor"></param>
public unsafe MultiThreadedTask(Operation ToDo, byte* rPixelPtr, byte* gPixelPtr, byte* bPixelPtr, Options opt, short[,] filter, double factor)
{
this.ToDo = ToDo;
this.opt = opt;
this.file = file;
nbPixel = opt.width * opt.height;
nbProcessors = Environment.ProcessorCount;
}
public MultiThreadedTask(Operation ToDo, Pixel[,] Pixels, Options opt, short[,] filter, double factor)
if (ToDo == Operation.Filter)
{
this.ToDo = ToDo;
this.opt = opt;
this.Pixels = Pixels;
this.filter = filter;
this.factor = factor;
this.rPixelPtr = rPixelPtr;
this.gPixelPtr = gPixelPtr;
this.bPixelPtr = bPixelPtr;
nbPixel = opt.width * opt.height;
size = filter.GetLength(0);
if (Program.MULTITHREADING)
nbProcessors = Program.MAX_THREADS;
else
nbProcessors = 1;
}
else throw new Exception("Impossible d'utiliser ce constructeur pour ce type d'opération");
}
public void Start()
/// <summary>
/// Constructeur pour l'opération Load
/// </summary>
/// <param name="ToDo"></param>
/// <param name="opt"></param>
/// <param name="rPixelPtr"></param>
/// <param name="gPixelPtr"></param>
/// <param name="bPixelPtr"></param>
/// <param name="filePtr"></param>
public unsafe MultiThreadedTask(Operation ToDo, Options opt, byte* rPixelPtr, byte* gPixelPtr, byte* bPixelPtr, byte* filePtr)
{
if (ToDo == Operation.Load) LoadImage();
else if (ToDo == Operation.Filter) ApplyFilter();
if (ToDo == Operation.Load || ToDo == Operation.Save)
{
this.rPixelPtr = rPixelPtr;
this.gPixelPtr = gPixelPtr;
this.bPixelPtr = bPixelPtr;
this.ToDo = ToDo;
this.opt = opt;
this.filePtr = filePtr;
nbPixel = opt.width * opt.height;
nbProcessors = Math.Min(Environment.ProcessorCount, 8);
}
else throw new Exception("Impossible d'utiliser ce constructeur pour ce type d'opération");
}
#region LoadImage
public void LoadImage()
#region Load
public unsafe void LoadImage()
{
Pixels = new Pixel[opt.width, opt.height];
Thread[] threads = new Thread[nbProcessors];
for (int i = 0; i < nbProcessors; i++)
{
threads[i] = new Thread(new ParameterizedThreadStart(LoadImageTask));
......@@ -76,38 +108,38 @@ namespace S04_Projet
threads[i].Join();
}
public void LoadImageTask(object i)
{
if (file != null && Pixels != null)
private unsafe void LoadImageTask(object i)
{
int start = nbPixel / nbProcessors * (int)i;
int end = nbPixel / nbProcessors * ((int)i + 1);
int x, y;
byte r, g, b;
for (int j = start; j < end; j++)
{
x = j % opt.width;
y = j / opt.width;
b = file[j * 3 + opt.padding * y + opt.offset];
g = file[j * 3 + opt.padding * y + opt.offset + 1];
r = file[j * 3 + opt.padding * y + opt.offset + 2];
Pixels[x, y] = new Pixel(r, g, b);
}
*(bPixelPtr + j) = *(filePtr + opt.offset + opt.padding * y + j * 3);
*(gPixelPtr + j) = *(filePtr + opt.offset + opt.padding * y + j * 3 + 1);
*(rPixelPtr + j) = *(filePtr + opt.offset + opt.padding * y + j * 3 + 2);
}
}
#endregion
#region Filter
public void ApplyFilter()
public MyImage ApplyFilter()
{
NewPixels = new Pixel[opt.width, opt.height];
int pixelNumber = opt.width * opt.height;
nbProcessors = Environment.ProcessorCount;
int pixelPerThread = pixelNumber / nbProcessors;
int nbPixel = opt.width * opt.height;
int pixelPerThread = nbPixel / nbProcessors;
NewRMatrix = new byte[nbPixel];
NewGMatrix = new byte[nbPixel];
NewBMatrix = new byte[nbPixel];
Thread[] threads = new Thread[nbProcessors];
Console.WriteLine("Creating {0} thread(s)", nbProcessors);
for (int i = 0; i < nbProcessors; i++)
{
threads[i] = new Thread(new ParameterizedThreadStart(ApplyFilterTask));
......@@ -118,13 +150,17 @@ namespace S04_Projet
{
threads[i].Join();
}
return new MyImage(opt, NewRMatrix, NewGMatrix, NewBMatrix);
}
public unsafe void ApplyFilterTask(object i)
private unsafe void ApplyFilterTask(object i)
{
int x, y;
int start = opt.width * opt.height / nbProcessors * (int)i;
int end = opt.width * opt.height / nbProcessors * ((int)i + 1);
int nbPixel = opt.width * opt.height;
int start = nbPixel / nbProcessors * (int)i;
int end = nbPixel / nbProcessors * ((int)i + 1);
byte[,] rMatrix = new byte[size, size];
byte[,] gMatrix = new byte[size, size];
byte[,] bMatrix = new byte[size, size];
......@@ -146,7 +182,9 @@ namespace S04_Projet
g = ConvolutionalResult(gMatrixPtr, filterPtr, size, factor);
b = ConvolutionalResult(bMatrixPtr, filterPtr, size, factor);
NewPixels[x, y] = new Pixel(r, g, b);
NewRMatrix[j] = r;
NewGMatrix[j] = g;
NewBMatrix[j] = b;
}
}
}
......@@ -173,11 +211,11 @@ namespace S04_Projet
else if (y >= opt.height) y = opt.height - 1;
if (rgb == RGB.R)
*(matrixPtr + i) = Pixels[x, y].r;
*(matrixPtr + i) = *(rPixelPtr + x + y * opt.width);
else if (rgb == RGB.G)
*(matrixPtr + i) = Pixels[x, y].g;
*(matrixPtr + i) = *(gPixelPtr + x + y * opt.width);
else if (rgb == RGB.B)
*(matrixPtr + i) = Pixels[x, y].b;
*(matrixPtr + i) = *(bPixelPtr + x + y * opt.width);
}
}
......@@ -203,14 +241,38 @@ namespace S04_Projet
}
#endregion
public Pixel[,] getPixelMatrix()
#region Save
public unsafe void SaveImage()
{
return Pixels;
Thread[] threads = new Thread[nbProcessors];
for (int i = 0; i < nbProcessors; i++)
{
threads[i] = new Thread(new ParameterizedThreadStart(SaveImageTask));
threads[i].Start(i);
}
for (int i = 0; i < nbProcessors; i++)
threads[i].Join();
}
public Pixel[,] getFilteredMatrix()
private unsafe void SaveImageTask(object i)
{
return NewPixels;
int start = nbPixel / nbProcessors * (int)i;
int end = nbPixel / nbProcessors * ((int)i + 1);
int x, y;
for (int j = start; j < end; j++)
{
x = j % opt.width;
y = j / opt.width;
*(filePtr + opt.offset + opt.padding * y + j * 3) = *(bPixelPtr + j);
*(filePtr + opt.offset + opt.padding * y + j * 3 + 1) = *(gPixelPtr + j);
*(filePtr + opt.offset + opt.padding * y + j * 3 + 2) = *(rPixelPtr + j);
}
}
#endregion
}
}
This diff is collapsed.
......@@ -24,7 +24,7 @@ namespace S04_Projet
public int fileSize;
public int offset;
public Options() { }
public Options() {}
/// <summary>
/// Return a new instance of Options with the same parameters
......@@ -32,22 +32,24 @@ namespace S04_Projet
/// <returns>New option instance</returns>
public Options Copy()
{
Options options = new Options();
options.fileInfoHeaderSize = fileInfoHeaderSize;
options.width = width;
options.height = height;
options.padding = padding;
options.colorPlanesNb = colorPlanesNb;
options.bitsPerPixel = bitsPerPixel;
options.compressionMethod = compressionMethod;
options.imgSize = imgSize;
options.horizontalRes = horizontalRes;
options.VerticalRes = VerticalRes;
options.nbColor = nbColor;
options.nbImportantColor = nbImportantColor;
options.format = format;
options.fileSize = fileSize;
options.offset = offset;
Options options = new Options
{
fileInfoHeaderSize = fileInfoHeaderSize,
width = width,
height = height,
padding = padding,
colorPlanesNb = colorPlanesNb,
bitsPerPixel = bitsPerPixel,
compressionMethod = compressionMethod,
imgSize = imgSize,
horizontalRes = horizontalRes,
VerticalRes = VerticalRes,
nbColor = nbColor,
nbImportantColor = nbImportantColor,
format = format,
fileSize = fileSize,
offset = offset
};
return options;
}
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace S04_Projet
{
public class Pixel
{
public byte r { get; private set; }
public byte g { get; private set; }
public byte b { get; private set; }
public double H { get; private set; }
public double S { get; private set; }
public double L { get; private set; }
public void SetR(byte r) => this.r = r;
public void SetG(byte g) => this.g = g;
public void SetB(byte b) => this.b = b;
/// <summary>
/// Prend les trois couleurs en paramètres
/// </summary>
/// <param name="r">Rouge</param>
/// <param name="g">Vert</param>
/// <param name="b">Bleu</param>
public Pixel(byte r, byte g, byte b)
{
this.r = r;
this.g = g;
this.b = b;
}
public unsafe Pixel(byte* r, byte* g, byte* b)
{
this.r = *r;
this.g = *g;
this.b = *b;
}
/// <summary>
/// Assigne une même valeur à toutes les couleurs
/// </summary>
/// <param name="unifiedColors">Valeur souhaitée pour toutes les couleurs</param>
public Pixel(byte unifiedColors)
{
r = unifiedColors;
g = unifiedColors;
b = unifiedColors;
}
/// <summary>
/// Créer un pixel à partir d'un tableau contenant les couleurs rouge, vert, bleu (respectivement)
/// </summary>
/// <param name="rgb">Tableau composé dans cet ordre des couleurs rouge, vert, bleu</param>
public Pixel(byte[] rgb)
{
r = rgb[0];
g = rgb[1];
b = rgb[2];
}
/// <summary>
/// Créer un pixel à partir d'un tableau contenant les couleurs rouge, vert, bleu (respectivement)
/// </summary>
/// <param name="rgb">Tableau composé dans cet ordre des couleurs rouge, vert, bleu</param>
public Pixel(int[] rgb)
{
r = (byte)rgb[0];
g = (byte)rgb[1];
b = (byte)rgb[2];
}
/// <summary>
/// Retourne un tableau contenant les valeurs RGB du pixel
/// </summary>
/// <returns>Composantes rouge, verte et bleue du pixel</returns>
public byte[] getRGB()
{
return new byte[] { r, g, b };
}
public unsafe byte* getRGBPtr()
{
unsafe
{
fixed (byte* ptr = new byte[] { r, g, b })
return ptr;
}
}
public byte[] getBGR()
{
return new byte[] { b, g, r };
}
/// <summary>
/// Retourne l'équavalent gris d'un pixel
/// </summary>
/// <param name="scale">Nombre de nuances de gris</param>
/// <returns>Pixel en échelle de gris</returns>
public Pixel getGrayScale(byte scale)
{
byte total = (byte)((r + g + b) / 3);
total = (byte)(Math.Round((double)total / (255 / (scale - 1))) * (255 / (scale - 1)));
return new Pixel(total);
}
/// <summary>
/// Retourne l'équivalent gris d'un pixel en prenant en compte les coefficients de luminosité
/// des couleurs RGB
/// </summary>
/// <param name="scale"></param>
/// <returns></returns>
public Pixel getGrayScaleLuminosity(byte scale)
{
byte total = (byte)(0.21 * r + 0.72 * g + 0.07 * b);
total = (byte)(Math.Round((double)total / (255 / (scale - 1))) * (255 / (scale - 1)));
return new Pixel(total);
}
/// <summary>
/// Calcul les valeurs de variables HSL (Hue, Saturation, Lightness)
/// </summary>
private void computeHSL()
{
double rH = r / 255.0;
double gH = g / 255.0;
double bH = b / 255.0;
double Cmax = Math.Max(Math.Max(rH, gH), bH);
double Cmin = Math.Min(Math.Min(rH, gH), bH);
double delta = Cmax - Cmin;
L = (Cmin + Cmax) / 2.0;
if (delta == 0) S = 0;
else S = delta / (1.0 - Math.Abs(2.0 * L - 1));
if (delta == 0) H = 0;
else if (Cmax == rH) H = 60 * (((gH - bH) / delta) % 6);
else if (Cmax == gH) H = 60 * (((bH - rH) / delta) + 2);
else H = 60 * (((rH - gH) / delta) + 4);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Drawing;
using System.Diagnostics;
using System.IO;
......@@ -11,16 +6,64 @@ namespace S04_Projet
{
class Program
{
public static bool MULTITHREADING_LOAD = false;
//public static bool MULTITHREADING_LOAD = false;
public static bool MULTITHREADING = false;
public static int MAX_THREADS = Environment.ProcessorCount;
public static bool DEBUG = false;
public static MyImage img;
public static Stopwatch sw = new Stopwatch();
private static string[] menuItems = new string[] { "Charger une image", "Créer une image" };
private static Menu welcomeMenu = new Menu(menuItems);
private static MyImage img;
private static Stopwatch sw = new Stopwatch();
static void Main(string[] args)
{
#region Arguments
if (args.Length > 0)
{
Arguments(args, 0);
}
#endregion
#region Display
else
{
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("#############################################################");
Console.WriteLine("### Bienvenue ###");
Console.WriteLine("#############################################################");
Console.WriteLine();
int choice = welcomeMenu.ShowMenu(0, 5); // 0 pour charger une image, 1 pour la créer
if (choice == 0)
{
Console.Clear();
img = Display.LoadImage();
}
else
{
Console.Clear();
img = Display.CreateImageOperation();
Display.fileInfos = img.ToString();
}
Display.Operation ToDo = Display.AskForOperation();
MyImage newImg = Display.PerformOperation(ToDo, img);
while (newImg != null)
{
ToDo = Display.AskForOperation();
newImg = Display.PerformOperation(ToDo, newImg);
}
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Image sauvegardée en {0}ms!", Display.elapsedTime);
Console.Read();
}
#endregion
}
private static void Arguments(string[] args, int i)
{
......@@ -45,7 +88,7 @@ namespace S04_Projet
{
increment = 2;
int choix = 0;
switch (args[i + 1].ToLower())
switch(args[i+1].ToLower())
{
case "flou":
case "blur":
......@@ -68,13 +111,18 @@ namespace S04_Projet
choix = 0;
break;
}
img = img.ApplyConvFilter(Filter.Filtres[choix], Filter.Facteurs[choix]);
};
img = img.Filter(Filter.Filtres[choix], Filter.Facteurs[choix]);
}
else if (args[i] == "--threads" || args[i] == "-t")
{
MAX_THREADS = int.Parse(args[i + 1]);
increment = 2;
}
if (DEBUG)
{
sw.Stop();
File.AppendAllText("debug.csv", args[i].Replace("-", "") + ";" + sw.ElapsedMilliseconds + ";\n");
File.AppendAllText("debug.csv", args[i].Replace("-","") + ";" + sw.ElapsedMilliseconds + ";\n");
}
if (i + increment < args.Length) Arguments(args, i + increment);
}
......
@echo off
FOR /L %%i IN (1,1,100) DO (
ECHO %%i
ImageProcessing.exe -d -i img\flocon.bmp -f flou
)
\ No newline at end of file
@echo off
FOR /L %%i IN (1,1,100) DO (
ECHO %%i
ImageProcessing.exe -d -MT -i img\flocon.bmp -f flou
)
\ No newline at end of file
S04_Projet/bin/Debug/img/coco.bmp

188 KB | W: | H:

S04_Projet/bin/Debug/img/coco.bmp

188 KB | W: | H:

S04_Projet/bin/Debug/img/coco.bmp
S04_Projet/bin/Debug/img/coco.bmp
S04_Projet/bin/Debug/img/coco.bmp
S04_Projet/bin/Debug/img/coco.bmp
  • 2-up
  • Swipe
  • Onion skin
This image diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
@echo off
FOR /L %%i IN (1,1,100) DO (
ECHO %%i
ImageProcessing.exe -d -i img\flocon.bmp
)
\ No newline at end of file
@echo off
FOR /L %%i IN (1,1,100) DO (
ECHO %%i
ImageProcessing.exe -d -MT -i img\flocon.bmp
)
\ No newline at end of file
@echo off
FOR /L %%i IN (1,1,100) DO (
ECHO %%i
ImageProcessing.exe -d -i img\flocon.bmp -o output.bmp
)
\ No newline at end of file
@echo off
FOR /L %%i IN (1,1,100) DO (
ECHO %%i
ImageProcessing.exe -d -MT -i img\flocon.bmp -o output.bmp
)
\ No newline at end of file
@echo off
FOR /L %%i IN (1,1,30) DO (
ECHO i : %%i
FOR /L %%j IN (1,1,20) DO (
ECHO j : %%j
ImageProcessing.exe -d -MT -t %%i -i img\flocon.bmp -f flou
)
)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment