Loading s5obj_lang_labo_2...
class Image { }
Type[] tab_name;
namespace ImageProcessing;
using ImageProcessing;
public Image(int width, int height, string name = "NoName") { ... }
Image img1 = new Image(100, 200); Image img2 = new Image(100, 200, "MyImage");
class Image { private int width; private int height; ...
public Image(int width, int height, string name = "NoName") { if (width <= 0 || height <= 0) throw new ArgumentException("Invalid image size"); } ... } }
Image img = new Image(100, -200);
public override string ToString() { string s = $"{name}:({width}x{height})\n"; for(int i=0; i<width*height; i++) s += pixels[i].ToString() + "\n"; return s; }
img.width = 100; img.height = 200; img.pixels = new Color[10];
// ou encore
img.pixels = null;
public Color[] GetPixels() { return pixels; }
Color[] pixels = img.GetPixels(); pixels[0] = new Color(1.0f, 0.0f, 0.0f);
Color[] pixels = img.GetPixels(); pixels[100] = new Color(0.0f, 1.0f, 0.5f);
public Color[] GetPixelsCopy() { Color[] tab = new Color[width*height]; int i=0; for(int i=0; i<width*height; i++) tab[i] = pixels[i]; return tab; }
static void TestDefensiveCopy() { Console.WriteLine("~~~~~~ in function TestDefensiveCopy() ~~~~~~"); Image img = new Image(2,3); Color[] tab = img.GetPixelsCopy(); tab[4] = new Color(0.5f, 0.5f, 0.5f); Console.WriteLine(img); }
using System.Diagnostics;
Stopwatch sw = Stopwatch.StartNew();
// code à mesurer Color[] tab = img.GetPixelsCopy();
sw.Stop();
Console.WriteLine($"Temps : {sw.ElapsedMilliseconds} ms");
Color GetPixel(int index) void SetPixel(int index, Color color)
Color GetPixel(int x, int y) void SetPixel(int x, int y, Color color)
private int Index(int x, int y) { if (x < 0 || x >= width || y < 0 || y >= height) { throw new ArgumentOutOfRangeException(); }
return y * width + x; }
Image img1 = img; Console.WriteLine($"img={img}"); Console.WriteLine($"img1={img1}");
img.SetPixel(0, 0, new Color(1f, 1f, 1f)); Console.WriteLine($"after modification of img :"); Console.WriteLine($"img={img}"); Console.WriteLine($"img1={img1}");
static void TestReferenceSemantics(Image img) { Console.WriteLine("~~~~~~ in TestReferenceSemantics() ~~~~~~"); Console.WriteLine(img);
img.SetPixel(0,0,new Color(1f, 1f, 1f));
Console.WriteLine("after modification:"); Console.WriteLine(img); }
Program.TestReferenceSemantics(img);
Console.WriteLine("~~~~~~ after TestReferenceSemantics() ~~~~~~"); Console.WriteLine(img);
public Image(int width, int height, string name = "NoName") { ... }
public Image(string path) { ... }
using System.IO;
public Image(string path) { var tokens = File.ReadLines(path) .Where(line => !line.TrimStart().StartsWith("#")) .SelectMany(line => line.Split( new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries)) .ToList();
// Ici le reste du code }
P3 largeur hauteur valeur_max R G B R G B R G B ...
P3 2 1 255 255 0 0 0 255 0
tokens[0] = "P3" tokens[1] = "2" tokens[2] = "1" tokens[3] = "255" tokens[4] = "255" tokens[5] = "0" tokens[6] = "0" tokens[7] = "0" tokens[8] = "255" tokens[9] = "0"
name = Path.GetFileNameWithoutExtension(path);
string s = "15"; int i = int.Parse(s);
public void Save(string path) { StreamWriter writer = new StreamWriter(path);
//Ici le reste du code }
writer.WriteLine("Something");
P3
largeur hauteur
255
writer.Close();
cargo new image_lib
//main.rs
pub mod image; use image::{Color, Image};
fn test_copy(mut c: Color) { println!("~~~~~~ in function test_copy() ~~~~~~"); println!("{:?}", c);
c.set_r(0.8);
println!("~~~~~~ after modification of c ~~~~~~"); println!("{:?}", c); }
fn test_color() { let mut c = Color::new(1.0, 0.0, 0.0);
println!("{:?}", c);
// Test getters and setters println!("R={} G={} B={}", c.r(), c.g(), c.b());
c.set_b(1.0); println!("B={}", c.b());
println!("Gray={}", c.gray());
// ---------- ownership ---------- // // This test only compiles if Color implements Copy. // let c1 = c;
println!("c={:?}", c); println!("c1={:?}", c1);
c.set_r(0.5);
println!("~~~~~~ after modification of c ~~~~~~"); println!("c={:?}", c); println!("c1={:?}", c1);
test_copy(c);
println!("~~~~~~ after function test_copy() ~~~~~~"); println!("c={:?}", c); println!("c1={:?}", c1); }
fn test_borrowing(img: &mut Image) { println!("~~~~~~ in function test_borrowing() ~~~~~~"); println!("{:?}", img);
img.set_pixel(0, 0, Color::new(1.0, 1.0, 1.0));
println!("~~~~~~ after modification ~~~~~~"); println!("{:?}", img); }
fn test_image() { let mut img = Image::new(2, 3, "Small".to_string());
img.set_pixel(0, 0, Color::new(1.0, 0.0, 0.0));
println!("{:?}", img);
// ---------- ownership ---------- // // This test demonstrates the transfer of ownership (borrowing). // let img1 = img;
println!("img={:?}", img1);
// println!("{:?}", img); // This doesn't compile
// ---------- borrowing ---------- // let mut img = img1;
test_borrowing(&mut img);
println!("~~~~~~ after function test_borrowing() ~~~~~~"); println!("{:?}", img);
// Test load and save PPM image let image = Image::from_file("data/Lena.ppm"); image.save("results/Lena.ppm"); }
fn main() { test_color(); test_image(); }
//image.rs
use std::fs::File; use std::io::{BufRead, BufReader, BufWriter, Write}; use std::path::Path;
#[derive(Debug, Clone, Copy)] pub struct Color { r: f32, g: f32, b: f32, }
impl Color { pub fn new( mut r: f32, mut g: f32, mut b: f32, ) -> Self { if r < 0.0 { r = 0.0; } if r > 1.0 { r = 1.0; } if g < 0.0 { g = 0.0; } if g > 1.0 { g = 1.0; } if b < 0.0 { b = 0.0; } if b > 1.0 { b = 1.0; } Self { r, g, b } }
pub fn r(&self) -> f32 { self.r }
pub fn g(&self) -> f32 { self.g }
pub fn b(&self) -> f32 { self.b }
pub fn set_r( &mut self, r: f32, ) { self.r = r.clamp(0.0, 1.0); }
pub fn set_g( &mut self, g: f32, ) { self.g = g.clamp(0.0, 1.0); }
pub fn set_b( &mut self, b: f32, ) { self.b = b.clamp(0.0, 1.0); }
pub fn gray(&self) -> f32 { 0.299 * self.r + 0.587 * self.g + 0.114 * self.b } }
#[derive(Debug, Clone)] pub struct Image { name: String, width: usize, height: usize, pixels: Vec<Color>, }
impl Image { pub fn new( width: usize, height: usize, name: String, ) -> Self { assert!(width > 0 && height > 0, "Invalid image dimensions");
Self { name, width, height, pixels: vec![Color::new(0.0, 0.0, 0.0); width * height], } }
fn index( &self, x: usize, y: usize, ) -> usize { assert!(x < self.width && y < self.height, "Pixel coordinates out of bounds");
y * self.width + x }
pub fn name(&self) -> &str { &self.name }
pub fn width(&self) -> usize { self.width }
pub fn height(&self) -> usize { self.height }
pub fn pixel( &self, x: usize, y: usize, ) -> Color { self.pixels[self.index(x, y)] }
pub fn set_pixel( &mut self, x: usize, y: usize, c: Color, ) { let i = self.index(x, y); self.pixels[i] = c; }
pub fn from_file(path: &str) -> Self { let file = File::open(path).unwrap(); let reader = BufReader::new(file);
let mut tokens = Vec::new();
for line in reader.lines() { let line = line.unwrap(); if line.trim_start().starts_with('#') { continue; } for token in line.split_whitespace() { tokens.push(token.to_string()); } } println!("{}", tokens.len());
println!("Tokens loaded");
assert!(tokens[0] == "P3");
let width = tokens[1].parse::<usize>().unwrap(); let height = tokens[2].parse::<usize>().unwrap();
println!("width={} height={}", width, height);
let mut pixels = Vec::with_capacity(width * height);
let mut index = 4;
println!("Reading pixels...");
while index < tokens.len() { let r = tokens[index].parse::<f32>().unwrap() / 255.0; let g = tokens[index + 1].parse::<f32>().unwrap() / 255.0; let b = tokens[index + 2].parse::<f32>().unwrap() / 255.0;
pixels.push(Color::new(r, g, b));
index += 3; }
println!("Pixels read");
Self { name: Path::new(path) .file_stem() .unwrap() .to_str() .unwrap() .to_string(), width, height, pixels, } }
pub fn save( &self, path: &str, ) { let file = File::create(path).unwrap(); let mut writer = BufWriter::new(file);
writeln!(writer, "P3").unwrap(); writeln!(writer, "{} {}", self.width, self.height).unwrap(); writeln!(writer, "255").unwrap();
for c in &self.pixels { writeln!( writer, "{} {} {}", (c.r() * 255.0) as u8, (c.g() * 255.0) as u8, (c.b() * 255.0) as u8 ) .unwrap(); } } }
pub struct Color { r: f32, g: f32, b: f32, }
pub struct Image { name: String, width: usize, height: usize, pixels: Vec<Color>, }
pub struct Color { mut r: f32, mut g: f32, mutb: f32, }
impl Color { pub fn new(mut r: f32, mut g: f32, mut b: f32) -> Self { // Same validation as in the C# version. Self { r, g, b } } }
pub struct Image { name: String, width: usize, height: usize, pixels: Vec<Color>, }
impl Image { pub fn new(name: String, width: usize, height: usize) -> Self { // Same validation as in the C# version. Self { name, width, height, pixels: vec![Color::new(0.0, 0.0, 0.0); width * height], } } }
Self { name, width, height, pixels: vec![Color::new(0.0, 0.0, 0.0); width * height], }
Self { name : name, width : width, height : height, pixels: vec![Color::new(0.0, 0.0, 0.0); width * height], }
pub fn width(&self) -> usize { self.width }
pub fn set_pixel(&mut self, x: usize, y: usize, color: Color) { ... }
let img = Image::new("Black", 100, 100); println!("{:?}", img);
let img1 = img;
println!("{:?}", img); println!("{:?}", img1);
let img1 = img;
#[derive(Debug, Clone, Copy)] pub struct Color { ... }
fn test_borrowing(img: Image) { println!("~~~~~~ in test_borrowing() ~~~~~~"); println!("{:?}", img);
img.set_pixel(0, 0, Color::new(1.0, 1.0, 1.0));
println!("~~~~~~ after modification ~~~~~~"); println!("{:?}", img); }
let img = Image::new("Black", 100, 100); test_borrowing(img);
println!("~~~~~~ after function test_borrowing() ~~~~~~"); println!("{:?}", img);
fn test_borrowing(img: &mut Image) { ... }
... test_borrowing(&mut img); ...
| Paramètre | Effet |
|---|---|
| Image | la propriété est transférée à la fonction |
| &Image | la fonction emprunte l'objet en lecture |
| &mut Image | la fonction emprunte l'objet en lecture et en écriture |
using System.Diagnostics; using ImageProcessing;
class Program { static void TestDefensiveCopy() { Console.WriteLine("~~~~~~ in function TestDefensiveCopy() ~~~~~~"); Image img = new Image(2,3, "Small");
Stopwatch sw = Stopwatch.StartNew(); Color[] tab = img.GetPixelsCopy(); sw.Stop();
Console.WriteLine($"Temps : {sw.ElapsedMilliseconds} ms");
tab[4] = new Color(0.5f, 0.5f, 0.5f); Console.WriteLine(img); }
static void TestReferenceSemantics(Image img) { Console.WriteLine("~~~~~~ in TestReferenceSemantics() ~~~~~~"); Console.WriteLine(img);
img.SetPixel(0,0,new Color(1f, 1f, 1f));
Console.WriteLine("~~~~~~ after modification ~~~~~~"); Console.WriteLine(img); }
static void TestImage() { Image img = new Image(2,3);
// Test on bad access to pixels array Color[] pixels = img.GetPixels(); pixels[0] = new Color(1.0f, 0.0f, 0.0f); // Really bad access (out of boundary) //img.pixels[100] = new Color(0.0f, 1.0f, 0.5f);
// Test on Defensive Copy TestDefensiveCopy();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Test on reference semantics Image img1 = img; Console.WriteLine($"img={img}"); Console.WriteLine($"img1={img1}"); img.SetPixel(0, 0, new Color(1f, 1f, 1f)); Console.WriteLine($"~~~~~~ after modification of img ~~~~~~"); Console.WriteLine($"img={img}"); Console.WriteLine($"img1={img1}");
TestReferenceSemantics(img); Console.WriteLine("~~~~~~ after function TestReferenceSemantics() ~~~~~~"); Console.WriteLine(img);
// Test load and save PPM image Image image = new Image("data/Lena.ppm"); image.Save("results/" + image.GetName() + ".ppm"); }
static void Main() { // ~~~~~~~~~ test class Image ~~~~~~~~~~ TestImage(); } }
using System.IO;
namespace ImageProcessing;
public struct Color { .... }
public class Image { private String name; private int width; private int height; private Color[] pixels;
public Image(int width, int height, String name = "NoName") { if (width <= 0 || height <= 0) throw new ArgumentException("Invalid image size");
this.name = name; this.width = width; this.height = height; this.pixels = new Color[width * height]; }
public string GetName() { return name; } public int GetWidth() { return width; } public int GetHeight() { return height; }
/* Tests to access pixels Comment these two functions when tests are over */ public Color[] GetPixels() { return pixels; }
public Color[] GetPixelsCopy() { Color[] tab = new Color[width*height]; for(int i=0; i<width*height; i++) tab[i] = pixels[i]; return tab; } /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
private int Index(int x, int y) { if (x < 0 || x >= width || y < 0 || y >= height) throw new ArgumentOutOfRangeException();
return y * width + x; }
public Color GetPixel(int x, int y) { return pixels[Index(x, y)]; }
public void SetPixel(int x, int y, Color c) { pixels[Index(x, y)] = c; }
public override string ToString() { string s = $"{name}:({width}x{height})\n"; for(int i=0; i<width*height; i++) s += pixels[i].ToString() + "\n"; return s; }
public Image(string path) { var tokens = File.ReadLines(path) .Where(line => !line.TrimStart().StartsWith("#")) .SelectMany(line => line.Split( new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries)) .ToList();
if (tokens[0] != "P3") throw new Exception("Invalid PPM");
name = Path.GetFileNameWithoutExtension(path); width = int.Parse(tokens[1]); height = int.Parse(tokens[2]);
int max = int.Parse(tokens[3]);
pixels = new Color[width * height];
int index = 4;
for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int r = int.Parse(tokens[index++]); int g = int.Parse(tokens[index++]); int b = int.Parse(tokens[index++]);
pixels[y * width + x] = new Color(r / 255f, g / 255f, b / 255f); } } }
public void Save(string path) { StreamWriter writer = new StreamWriter(path);
writer.WriteLine("P3"); writer.WriteLine($"{width} {height}"); writer.WriteLine("255");
for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { Color c = GetPixel(x, y);
int r = (int)(c.GetR() * 255); int g = (int)(c.GetG() * 255); int b = (int)(c.GetB() * 255);
writer.WriteLine($"{r} {g} {b}"); } } writer.Close(); } }