simple_term_renderer/
img.rs

1/*
2
3    MIT License
4    
5    Copyright (c) 2022 Siandfrance
6    
7    Permission is hereby granted, free of charge, to any person obtaining a copy
8    of this software and associated documentation files (the "Software"), to deal
9    in the Software without restriction, including without limitation the rights
10    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11    copies of the Software, and to permit persons to whom the Software is
12    furnished to do so, subject to the following conditions:
13    
14    The above copyright notice and this permission notice shall be included in all
15    copies or substantial portions of the Software.
16    
17    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23    SOFTWARE.
24
25*/
26
27
28use crate::buffer2d::Buffer2D;
29use crate::math::{Vec2, Vec3f};
30
31use std::ops::{Index, IndexMut};
32use std::fmt;
33use std::path::Path;
34
35
36use image::io::Reader as ImageReader;
37use image::{Pixel, RgbImage};
38use palette::{LinSrgb, Okhsl, Srgb};
39use palette::convert::FromColor;
40
41
42#[derive(Clone, Copy, Debug, PartialEq, Eq)]
43pub enum BlendMode {
44    Add
45}
46
47
48/// RGB Color struct.
49/// 
50/// Fields:
51/// ```
52/// Color.r
53/// Color.g
54/// Color.b
55/// ```
56#[derive(Clone, Copy, Debug, PartialEq, Eq)]
57pub struct Color {
58    pub r: u8,
59    pub g: u8,
60    pub b: u8
61}
62
63
64impl Color {
65
66    pub const ALICE_BLUE         : Color = Color::hex(0xeff7ff);
67    pub const ANTIQUE_WHITE      : Color = Color::hex(0xf9ebd6);
68    pub const AQUA               : Color = Color::hex(0x00ffff);
69    pub const AQUAMARINE         : Color = Color::hex(0x7effd4);
70    pub const AZURE              : Color = Color::hex(0xefffff);
71    pub const BEIGE              : Color = Color::hex(0xf4f4db);
72    pub const BISQUE             : Color = Color::hex(0xffe4c3);
73    pub const BLACK              : Color = Color::hex(0x000000);
74    pub const BLANCHED_ALMOND    : Color = Color::hex(0xffebcd);
75    pub const BLUE               : Color = Color::hex(0x0000ff);
76    pub const BLUE_VIOLET        : Color = Color::hex(0x892ae2);
77    pub const BROWN              : Color = Color::hex(0xa52a2a);
78    pub const BURLYWOOD          : Color = Color::hex(0xddb887);
79    pub const CADET_BLUE         : Color = Color::hex(0x5e9ea0);
80    pub const CHARTREUSE         : Color = Color::hex(0x7eff00);
81    pub const CHOCOLATE          : Color = Color::hex(0xd1691d);
82    pub const CORAL              : Color = Color::hex(0xff7e50);
83    pub const CORNFLOWER_BLUE    : Color = Color::hex(0x6495ed);
84    pub const CORNSILK           : Color = Color::hex(0xfff7db);
85    pub const CRIMSON            : Color = Color::hex(0xdb143b);
86    pub const CYAN               : Color = Color::hex(0x00ffff);
87    pub const DARK_BLUE          : Color = Color::hex(0x00008a);
88    pub const DARK_CYAN          : Color = Color::hex(0x008a8a);
89    pub const DARK_GOLDENROD     : Color = Color::hex(0xb8850b);
90    pub const DARK_GRAY          : Color = Color::hex(0xa8a8a8);
91    pub const DARK_GREEN         : Color = Color::hex(0x006400);
92    pub const DARK_KHAKI         : Color = Color::hex(0xbcb66b);
93    pub const DARK_MAGENTA       : Color = Color::hex(0x8a008a);
94    pub const DARK_OLIVE_GREEN   : Color = Color::hex(0x546b2f);
95    pub const DARK_ORANGE        : Color = Color::hex(0xff8c00);
96    pub const DARK_ORCHID        : Color = Color::hex(0x9931cc);
97    pub const DARK_RED           : Color = Color::hex(0x8a0000);
98    pub const DARK_SALMON        : Color = Color::hex(0xe89579);
99    pub const DARK_SEA_GREEN     : Color = Color::hex(0x8ebc8e);
100    pub const DARK_SLATE_BLUE    : Color = Color::hex(0x483d8a);
101    pub const DARK_SLATE_GRAY    : Color = Color::hex(0x2f4f4f);
102    pub const DARK_TURQUOISE     : Color = Color::hex(0x00cdd1);
103    pub const DARK_VIOLET        : Color = Color::hex(0x9300d3);
104    pub const DEEP_PINK          : Color = Color::hex(0xff1493);
105    pub const DEEP_SKY_BLUE      : Color = Color::hex(0x00bfff);
106    pub const DIM_GRAY           : Color = Color::hex(0x696969);
107    pub const DODGER_BLUE        : Color = Color::hex(0x1d90ff);
108    pub const FIREBRICK          : Color = Color::hex(0xb12121);
109    pub const FLORAL_WHITE       : Color = Color::hex(0xfff9ef);
110    pub const FOREST_GREEN       : Color = Color::hex(0x218a21);
111    pub const FUCHSIA            : Color = Color::hex(0xff00ff);
112    pub const GAINSBORO          : Color = Color::hex(0xdbdbdb);
113    pub const GHOST_WHITE        : Color = Color::hex(0xf7f7ff);
114    pub const GOLD               : Color = Color::hex(0xffd600);
115    pub const GOLDENROD          : Color = Color::hex(0xdaa51f);
116    pub const GRAY               : Color = Color::hex(0xbdbdbd);
117    pub const GREEN              : Color = Color::hex(0x00ff00);
118    pub const GREEN_YELLOW       : Color = Color::hex(0xacff2f);
119    pub const HONEYDEW           : Color = Color::hex(0xefffef);
120    pub const HOT_PINK           : Color = Color::hex(0xff69b3);
121    pub const INDIAN_RED         : Color = Color::hex(0xcd5b5b);
122    pub const INDIGO             : Color = Color::hex(0x4b0082);
123    pub const IVORY              : Color = Color::hex(0xffffef);
124    pub const KHAKI              : Color = Color::hex(0xefe68c);
125    pub const LAVENDER           : Color = Color::hex(0xe6e6f9);
126    pub const LAVENDER_BLUSH     : Color = Color::hex(0xffeff4);
127    pub const LAWN_GREEN         : Color = Color::hex(0x7cfb00);
128    pub const LEMON_CHIFFON      : Color = Color::hex(0xfff9cd);
129    pub const LIGHT_BLUE         : Color = Color::hex(0xacd8e6);
130    pub const LIGHT_CORAL        : Color = Color::hex(0xef8080);
131    pub const LIGHT_CYAN         : Color = Color::hex(0xdfffff);
132    pub const LIGHT_GOLDENROD    : Color = Color::hex(0xf9f9d1);
133    pub const LIGHT_GRAY         : Color = Color::hex(0xd3d3d3);
134    pub const LIGHT_GREEN        : Color = Color::hex(0x90ed90);
135    pub const LIGHT_PINK         : Color = Color::hex(0xffb6c1);
136    pub const LIGHT_SALMON       : Color = Color::hex(0xffa079);
137    pub const LIGHT_SEA_GREEN    : Color = Color::hex(0x1fb1aa);
138    pub const LIGHT_SKY_BLUE     : Color = Color::hex(0x87cdf9);
139    pub const LIGHT_SLATE_GRAY   : Color = Color::hex(0x778799);
140    pub const LIGHT_STEEL_BLUE   : Color = Color::hex(0xafc3dd);
141    pub const LIGHT_YELLOW       : Color = Color::hex(0xffffdf);
142    pub const LIME               : Color = Color::hex(0x00ff00);
143    pub const LIME_GREEN         : Color = Color::hex(0x31cd31);
144    pub const LINEN              : Color = Color::hex(0xf9efe6);
145    pub const MAGENTA            : Color = Color::hex(0xff00ff);
146    pub const MAROON             : Color = Color::hex(0xaf2f60);
147    pub const MEDIUM_AQUAMARINE  : Color = Color::hex(0x66cdaa);
148    pub const MEDIUM_BLUE        : Color = Color::hex(0x0000cd);
149    pub const MEDIUM_ORCHID      : Color = Color::hex(0xba54d3);
150    pub const MEDIUM_PURPLE      : Color = Color::hex(0x9370db);
151    pub const MEDIUM_SEA_GREEN   : Color = Color::hex(0x3bb370);
152    pub const MEDIUM_SLATE_BLUE  : Color = Color::hex(0x7b67ed);
153    pub const MEDIUM_SPRING_GREEN: Color = Color::hex(0x00f99a);
154    pub const MEDIUM_TURQUOISE   : Color = Color::hex(0x48d1cc);
155    pub const MEDIUM_VIOLET_RED  : Color = Color::hex(0xc61485);
156    pub const MIDNIGHT_BLUE      : Color = Color::hex(0x181870);
157    pub const MINT_CREAM         : Color = Color::hex(0xf4fff9);
158    pub const MISTY_ROSE         : Color = Color::hex(0xffe4e1);
159    pub const MOCCASIN           : Color = Color::hex(0xffe4b5);
160    pub const NAVAJO_WHITE       : Color = Color::hex(0xffddac);
161    pub const NAVY_BLUE          : Color = Color::hex(0x000080);
162    pub const OLD_LACE           : Color = Color::hex(0xfdf4e6);
163    pub const OLIVE              : Color = Color::hex(0x808000);
164    pub const OLIVE_DRAB         : Color = Color::hex(0x6b8e23);
165    pub const ORANGE             : Color = Color::hex(0xffa500);
166    pub const ORANGE_RED         : Color = Color::hex(0xff4400);
167    pub const ORCHID             : Color = Color::hex(0xda70d6);
168    pub const PALE_GOLDENROD     : Color = Color::hex(0xede8aa);
169    pub const PALE_GREEN         : Color = Color::hex(0x97fb97);
170    pub const PALE_TURQUOISE     : Color = Color::hex(0xafeded);
171    pub const PALE_VIOLET_RED    : Color = Color::hex(0xdb7093);
172    pub const PAPAYA_WHIP        : Color = Color::hex(0xffefd4);
173    pub const PEACH_PUFF         : Color = Color::hex(0xffdab8);
174    pub const PERU               : Color = Color::hex(0xcd853f);
175    pub const PINK               : Color = Color::hex(0xffbfca);
176    pub const PLUM               : Color = Color::hex(0xdda0dd);
177    pub const POWDER_BLUE        : Color = Color::hex(0xafdfe6);
178    pub const PURPLE             : Color = Color::hex(0xa01fef);
179    pub const REBECCA_PURPLE     : Color = Color::hex(0x663399);
180    pub const RED                : Color = Color::hex(0xff0000);
181    pub const ROSY_BROWN         : Color = Color::hex(0xbc8e8e);
182    pub const ROYAL_BLUE         : Color = Color::hex(0x4169e1);
183    pub const SADDLE_BROWN       : Color = Color::hex(0x8a4412);
184    pub const SALMON             : Color = Color::hex(0xf98072);
185    pub const SANDY_BROWN        : Color = Color::hex(0xf4a360);
186    pub const SEA_GREEN          : Color = Color::hex(0x2d8a56);
187    pub const SEASHELL           : Color = Color::hex(0xfff4ed);
188    pub const SIENNA             : Color = Color::hex(0xa0522d);
189    pub const SILVER             : Color = Color::hex(0xbfbfbf);
190    pub const SKY_BLUE           : Color = Color::hex(0x87cdeb);
191    pub const SLATE_BLUE         : Color = Color::hex(0x6959cd);
192    pub const SLATE_GRAY         : Color = Color::hex(0x708090);
193    pub const SNOW               : Color = Color::hex(0xfff9f9);
194    pub const SPRING_GREEN       : Color = Color::hex(0x00ff7e);
195    pub const STEEL_BLUE         : Color = Color::hex(0x4682b3);
196    pub const TAN                : Color = Color::hex(0xd1b38c);
197    pub const TEAL               : Color = Color::hex(0x008080);
198    pub const THISTLE            : Color = Color::hex(0xd8bfd8);
199    pub const TOMATO             : Color = Color::hex(0xff6246);
200    pub const TRANSPARENT        : Color = Color::hex(0xffffff);
201    pub const TURQUOISE          : Color = Color::hex(0x3fdfcf);
202    pub const VIOLET             : Color = Color::hex(0xed82ed);
203    pub const WEB_GRAY           : Color = Color::hex(0x808080);
204    pub const WEB_GREEN          : Color = Color::hex(0x008000);
205    pub const WEB_MAROON         : Color = Color::hex(0x800000);
206    pub const WEB_PURPLE         : Color = Color::hex(0x800080);
207    pub const WHEAT              : Color = Color::hex(0xf4ddb3);
208    pub const WHITE              : Color = Color::hex(0xffffff);
209    pub const WHITE_SMOKE        : Color = Color::hex(0xf4f4f4);
210    pub const YELLOW             : Color = Color::hex(0xffff00);
211    pub const YELLOW_GREEN       : Color = Color::hex(0x9acd31);
212
213
214    /// Creates a color.
215    pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
216        Self {
217            r: r,
218            g: g,
219            b: b
220        }
221    }
222
223
224    /// Creates a color.
225    pub const fn hex(h: u32) -> Self {
226        Self {
227            r: ((h & 0x00FF0000) / 0x00010000) as u8,
228            g: ((h & 0x0000FF00) / 0x00000100) as u8,
229            b: ((h & 0x000000FF) / 0x00000001) as u8
230        }
231    }
232
233
234    pub fn raw_rgb(r: f32, g: f32, b: f32) -> Self {
235        Self {
236            r: (r * 255.0).clamp(0.0, 255.0) as u8,
237            g: (g * 255.0).clamp(0.0, 255.0) as u8,
238            b: (b * 255.0).clamp(0.0, 255.0) as u8
239        }
240    }
241
242
243    pub fn raw_vec3_rgb(c: Vec3f) -> Self {
244        Self::raw_rgb(c.x, c.y, c.z)
245    }
246
247
248    pub fn okhsl(h: f32, s: f32, l: f32) -> Self {
249        let okhsl = Okhsl::new(h, s, l);
250        let srgb = Srgb::from_color(okhsl);
251        let rgb = srgb.into_linear();
252        Self::raw_rgb(rgb.red, rgb.green, rgb.blue)
253    }
254
255
256    pub fn get_raw(&self) -> (f32, f32, f32) {
257        (self.r as f32 / 255.0, self.g as f32 / 255.0, self.b as f32 / 255.0)
258    }
259
260
261    pub fn get_raw_vec3f(&self) -> Vec3f {
262        let (r, g, b) = self.get_raw();
263        Vec3f::new(r, g, b)
264    }
265
266
267    pub fn get_okhsl(&self) -> (f32, f32, f32) {
268        let (r, g, b) = self.get_raw();
269        let okhsl: Okhsl = Okhsl::from_color(LinSrgb::new(r, g, b));
270        (okhsl.hue.into_inner(), okhsl.saturation, okhsl.lightness)
271    }
272
273
274    pub fn blend(a: Color, b: Color, mode: BlendMode) -> Self {
275        match mode {
276            BlendMode::Add => {
277                Self::raw_vec3_rgb((a.get_raw_vec3f() + b.get_raw_vec3f()) / 2.0)
278            }
279        }
280    }
281}
282
283
284impl fmt::Display for Color {
285
286    /// Writes the CSI to set background or color (respectively when using {:-} or {:+}) to `f`.
287    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
288        // We don't need to do any transformation as the terminal's color space is RGB (and not sRGB)
289        if f.sign_minus() {
290            write!(f, "\x1b[48;2;{};{};{}m", self.r, self.g, self.b)
291        } else {
292            write!(f, "\x1b[38;2;{};{};{}m", self.r, self.g, self.b)
293        }
294    }
295}
296
297
298#[derive(Clone)]
299/// Image struct. This is a Color buffer.
300/// Pixels can be accessed by indexing with the pixel coordinates.
301pub struct Image {
302    data: Buffer2D<Color>
303}
304
305
306impl Image {
307
308    /// Creates an image of size (`w`, `h`). All the pixels are set to black.
309    pub fn new<V>(size: V) -> Self
310        where V: AsRef<Vec2>
311    {
312        Self {
313            data: Buffer2D::new(*size.as_ref(), Color::BLACK)
314        }
315    }
316
317
318    /// Loads an image from a file.
319    pub fn load<P>(path: P) -> Result<Self, String>
320            where P: AsRef<Path> {
321        let img = match ImageReader::open(path) {
322            Ok(s) => match s.decode() {
323                Ok(img) => img,
324                Err(e) => return Err(format!("{}", e))
325            }
326            Err(e) => return Err(format!("{}", e))
327        }.to_rgb8();
328        let mut result = Image::new(vec2!(img.width(), img.height()));
329        for i in 0..img.width() {
330            for j in 0..img.height() {
331                let px = img.get_pixel(i, j).channels();
332                result[vec2!(i as i32, j as i32)] = Color::rgb(px[0], px[1], px[2]);
333            }
334        }
335        Ok(result)
336    }
337
338
339    /// Saves an image to a file.
340    pub fn save<P>(&self, path: P) -> Result<(), String>
341            where P: AsRef<Path> {
342        let mut img = RgbImage::new(self.size().x as u32, self.size().y as u32);
343        for i in 0..self.size().x {
344            for j in 0..self.size().y {
345                let pix = img.get_pixel_mut(i as u32, j as u32);
346                let c = self[vec2!(i, j)];
347                pix.0 = [c.r, c.g, c.b];
348            }
349        }
350        match img.save(path) {
351            Ok(_) => Ok(()),
352            Err(e) => Err(format!("{}", e))
353        }
354    }
355
356
357
358    /// Returns the size of the image.
359    pub fn size(&self) -> Vec2 {
360        self.data.size()
361    }
362
363
364    /// Resizes the image. New pixels are set to black.
365    /// It corrupts the image (pixel position is misinterpreted, but it is faster than Image::resize).
366    pub fn raw_resize<A>(&mut self, new_size: A) 
367        where A: AsRef<Vec2>
368    {
369        self.data.raw_resize(*new_size.as_ref(), Color::BLACK);
370    }
371
372
373    /// NOT IMPLEMENTED Resizes the image keeping the top left part of the image
374    pub fn resize<A>(&mut self, new_size: A) 
375        where A: AsRef<Vec2>
376    {
377        self.data.resize(*new_size.as_ref(), Color::BLACK);
378    }
379
380
381    fn is_out_of_range<A>(&self, p: A) -> bool
382        where A: AsRef<Vec2> 
383    {
384        let p = p.as_ref();
385        p.x < 0 || p.y < 0 || p.x >= self.size().x || p.y >= self.size().y
386    }
387
388
389    /// Sets the pixel color at `p` to `c`.
390    pub fn point<A>(&mut self, p: A, c: Color)
391        where A: AsRef<Vec2>
392    {
393        self[*p.as_ref()] = c;
394    }
395
396
397    /// Draws a line of color `c` between `p1` and `p2`.
398    pub fn line<A, B>(&mut self, p1: A, p2: B, c: Color)
399        where A: AsRef<Vec2>, B: AsRef<Vec2> 
400    {
401        let mut p1 = *p1.as_ref();
402        let p2 = p2.as_ref();
403
404        let dx = (p2.x - p1.x).abs();
405        let sx = if p1.x < p2.x {1} else {-1};
406        let dy = -(p2.y - p1.y).abs();
407        let sy = if p1.y < p2.y {1} else {-1};
408
409        let mut err = dx + dy;
410
411        self[p1] = c;
412
413        while (p1.x != p2.x || p1.y != p2.y)
414             && ((p1.x < self.size().x && sx > 0) || (p1.x >= 0 && sx < 0))
415             && ((p1.y < self.size().y && sy > 0) || (p1.y >= 0 && sy < 0))
416        {
417            let e2 = 2 * err;
418            if e2 >= dy {
419                err += dy;
420                p1.x += sx;
421            }
422            if e2 <= dx {
423                err += dx;
424                p1.y += sy;
425            }
426
427            self[p1] = c;
428        }
429    }
430
431
432    /// Same as `rect` but draws only the four sides of the rectangle.
433    pub fn rect_boudary<A, B>(&mut self, p: A, s: B, c: Color)
434        where A: AsRef<Vec2>, B: AsRef<Vec2>
435    {
436        let p = p.as_ref();
437        let s = s.as_ref();
438        self.line((p.x      , p.y      ), (p.x + s.x, p.y      ), c);
439        self.line((p.x + s.x, p.y      ), (p.x + s.x, p.y + s.y), c);
440        self.line((p.x + s.x, p.y + s.y), (p.x      , p.y + s.y), c);
441        self.line((p.x      , p.y + s.y), (p.x      , p.y      ), c);
442    }
443
444
445    /// Draws a rectangle of color `c` and of size `s`. 
446    /// `p` is the coordinate of the top left corner of the rectangle.
447    pub fn rect<A, B>(&mut self, p: A, s: B, c: Color) 
448        where A: AsRef<Vec2>, B: AsRef<Vec2>
449    {
450        let mut p = *p.as_ref();
451        let mut s = *s.as_ref();
452
453        if p.x < 0 {
454            s.x += p.x - 1;
455            p.x = 0;
456        }
457        if p.y < 0 {
458            s.y += p.y - 1;
459            p.y = 0;
460        }
461
462        let dx = if s.x > 0 {1} else {-1};
463        let dy = if s.y > 0 {1} else {-1};
464
465        for j in 0..(s.y.abs()) {
466            let y = p.y + j * dy;
467            if y >= self.size().y {break}
468            for i in 0..(s.x.abs()) {
469                let x = p.x + i * dx;
470                if x >= self.size().x {break}
471
472                self[(x, y)] = c;
473            }
474        }
475    }
476
477
478    /// Sets all the pixels' color in the screen to `c`.
479    pub fn clear(&mut self, c: Color) {
480        self.data.fill(c);
481    }
482
483
484    fn plot_ellipse_points<A, B>(&mut self, center: A, pos: B, c: Color) 
485        where A: AsRef<Vec2>, B: AsRef<Vec2>
486    {
487        let center = center.as_ref();
488        let pos    = pos.as_ref();
489        self[(center.x + pos.x, center.y + pos.y)] = c;
490        self[(center.x + pos.x, center.y - pos.y)] = c;
491        self[(center.x - pos.x, center.y + pos.y)] = c;
492        self[(center.x - pos.x, center.y - pos.y)] = c;
493    }
494
495
496    /// Draws an ellipse of color `col`. `c` is the center of the ellipse and `s` is the size of the rectangle
497    /// in which the ellipse is inscribed.
498    pub fn ellipse_boundary<A, B>(&mut self, center: A, size: B, c: Color) 
499        where A: AsRef<Vec2>, B: AsRef<Vec2>
500    {
501        let center = center.as_ref();
502        let size   = size.as_ref();
503
504        let a = size.x / 2;
505        let b = size.y / 2;
506
507        //prepare to plot in the first region
508        let mut x = 0;
509        let mut y = b;
510        let mut p    = b * b + (a * a * (1 - 4*b) - 2) / 4;
511        let mut dpe  = 3 * b * b;
512        let mut dpse  = dpe - 2 * a * a * (b - 1);
513        let d2pe  = 2 * b * b;
514        let d2pse = d2pe + 2 * a * a;
515
516        //plot in the first region
517        self.plot_ellipse_points(center, (x, y), c);
518        while dpse < 2 * a * a + 3 * b * b {
519            if p < 0 { //east
520                p    += dpe;
521                dpe  += d2pe;
522                dpse += d2pe;
523            } else {     //south-east
524                p    += dpse;
525                dpe  += d2pe;
526                dpse += d2pse;
527                y -= 1;
528            }
529            x += 1;
530            self.plot_ellipse_points(center, (x, y), c);
531        }
532
533        //prepare to plot in the second region
534        let mut p    = p - (a * a * (4 * y - 3) + b * b * (4 * x + 3) + 2) / 4;
535        let mut dpse = 2 * b * b + 3 * a * a;
536        let dps  = a * a * (3 - 2 * y);
537        let d2ps = 2 * a * a;
538
539        //plot in the second region
540        while y > 0 {
541            if p > 0 { //south
542                p    += dps;
543                dpe  += d2ps;
544                dpse += d2ps;
545            } else {     //south-east
546                p    += dpse;
547                dpe  += d2ps;
548                dpse += d2pse;
549                x += 1;
550            }
551            y -= 1;
552            self.plot_ellipse_points(center, (x, y), c);
553        }
554    }
555
556
557    /// Draws an image at position `pos`. 
558    /// 
559    /// Negative size results in flipped image. Alpha is used to ignore a given color while drawing.
560    pub fn image<A, B, C>(&mut self, img: &Image, pos: A, size: B, offset: C, alpha: Option<Color>) 
561        where A: AsRef<Vec2>, B: AsRef<Vec2>, C: AsRef<Vec2>
562    {
563        let offset = offset.as_ref();
564        let mut p = *pos.as_ref();
565        let mut s = *size.as_ref();
566
567        if p.x < 0 {
568            s.x += p.x - 1;
569            p.x = 0;
570        }
571        if p.y < 0 {
572            s.y += p.y - 1;
573            p.y = 0;
574        }
575
576
577        let dx = if s.x > 0 {1} else {-1};
578        let dy = if s.y > 0 {1} else {-1};
579
580
581        for j in 0..(s.y.abs()) {
582            let y = p.y + j * dy;
583            let src_y = offset.y + j;
584            if y >= self.size().y {break}
585            if src_y >= img.size().y {break}
586            for i in 0..(s.x.abs()) {
587                let x = p.x + i * dx;
588                let src_x = offset.x + i;
589                if x >= self.size().x {break}
590                if src_x >= img.size().x {break}
591
592                let pos = vec2!(x, y);
593                let src_pos = vec2!(src_x, src_y);
594
595                if let Some(acolor) = alpha {
596                    if acolor == img[src_pos] {
597                        continue;
598                    }
599                }
600                self[pos] = img[src_pos];
601            }
602        }
603    }
604
605
606    /// Draws the whole image at `pos`, ignoring the color `alpha`.
607    /// 
608    /// Literally:
609    /// ```
610    /// <image>.image(img, pos, img.size(), Vec2::ZERO, Some(alpha));
611    /// ```
612    pub fn whole_image_alpha<A>(&mut self, img: &Image, pos: A, alpha: Color) 
613        where A: AsRef<Vec2>
614    {
615        self.image(img, pos, img.size(), Vec2::ZERO, Some(alpha));
616    }
617
618
619    /// Draws the whole image at `pos`.
620    /// 
621    /// Literally:
622    /// ```
623    /// <image>.image(img, pos, img.size(), Vec2::ZERO, None);
624    /// ```
625    pub fn whole_image<A>(&mut self, img: &Image, pos: A) 
626        where A: AsRef<Vec2>
627    {
628        self.image(img, pos, img.size(), Vec2::ZERO, None);
629    }
630}
631
632
633impl<A: AsRef<Vec2>> Index<A> for Image {
634    type Output = Color;
635
636    fn index(&self, p: A) -> &Self::Output {
637        let p = *p.as_ref();
638        if !self.is_out_of_range(p) {
639            &self.data[p]
640        } else {
641            &Color::BLACK
642        }
643    }
644}
645
646
647impl<A: AsRef<Vec2>> IndexMut<A> for Image {
648
649    fn index_mut(&mut self, p: A) -> &mut Self::Output {
650        static mut TEMP: Color = Color::BLACK;
651        let p = *p.as_ref();
652
653        if !self.is_out_of_range(p) {
654            &mut self.data[p]
655        } else {
656            unsafe { &mut TEMP } // NOT GOOD, ignore index out of range
657        }
658    }
659}