ggstd/image/image.rs
1// Copyright 2023 The rust-ggstd authors. All rights reserved.
2// Copyright 2009 The Go Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6use super::color::{self, ColorTrait};
7use super::geom::{Point, Rectangle};
8
9/// Config holds an image's color model and dimensions.
10#[derive(Debug)]
11pub struct Config {
12 pub color_model: color::Model,
13 pub width: usize,
14 pub height: usize,
15}
16
17/// Image is a finite rectangular grid of color::Color values taken from a color
18/// model.
19pub trait Image {
20 /// color_model returns the Image's color model.
21 fn color_model(&self) -> color::Model;
22 /// bounds returns the domain for which At can return non-zero color::
23 /// The bounds do not necessarily contain the point (0, 0).
24 fn bounds(&self) -> &Rectangle;
25 /// at returns the color of the pixel at (x, y).
26 /// at(bounds().min.x, bounds().min.y) returns the upper-left pixel of the grid.
27 /// at(bounds().max.x-1, bounds().max.y-1) returns the lower-right one.
28 fn at(&self, x: isize, y: isize) -> color::Color;
29 // set color of the give pixel. The color will be converted to the color model
30 // of the image if necessary. The conversion may be lossy.
31 fn set(&mut self, x: isize, y: isize, c: &color::Color);
32 /// opaque scans the entire image and reports whether it is fully opaque.
33 fn opaque(&self) -> bool;
34 /// stride returns the pix stride (in bytes) between vertically adjacent pixels.
35 fn stride(&self) -> usize;
36 /// pix returns the image pixel data. Format of the data depends on the image type.
37 fn pix(&self) -> &Vec<u8>;
38 /// bytes_per_pixel return how many bytes is used per pixel
39 fn bytes_per_pixel(&self) -> usize;
40
41 /// get_pix_mutable returns the image data for editing.
42 /// Format of the data depends on the image type.
43 fn get_pix_mutable(&mut self) -> &mut Vec<u8>;
44
45 /// deep_equal checks that two images are exactly the same
46 fn deep_equal(&self, other: &dyn Image) -> bool {
47 self.color_model() == other.color_model()
48 && self.bounds() == other.bounds()
49 && self.pix() == other.pix()
50 }
51
52 /// get_line_data returns data that encode one line of pixels.
53 fn get_line_data(&self, y: isize) -> &[u8] {
54 let b = self.bounds();
55 let offset = (y - b.min.y) as usize * self.stride();
56 &self.pix()[offset..offset + b.dx() * self.bytes_per_pixel()]
57 }
58}
59
60// // RGBA64Image is an Image whose pixels can be converted directly to a
61// // color::RGBA64.
62// type RGBA64Image interface {
63// // RGBA64At returns the RGBA64 color of the pixel at (x, y). It is
64// // equivalent to calling At(x, y).rgba() and converting the resulting
65// // 32-bit return values to a color::RGBA64, but it can avoid allocations
66// // from converting concrete color types to the color::Color interface type.
67// RGBA64At(x: isize, y: isize) color::RGBA64
68// Image
69// }
70
71// // PalettedImage is an image whose colors may come from a limited palette.
72// // If m is a PalettedImage and m.color_model() returns a color::Palette p,
73// // undefined.
74// type PalettedImage interface {
75// Image
76// }
77
78/// pixel_buffer_length returns the length of the [u8] typed pix slice field
79/// for the NewXxx functions.
80// Conceptually, this is just (bpp * width * height),
81// but this function panics if at least one of those is negative or if the
82// computation would overflow the isize type.
83//
84// This panics instead of returning an error because of backwards
85// compatibility. The NewXxx functions do not return an error.
86fn pixel_buffer_length(bytes_per_pixel: usize, r: &Rectangle, _image_type_name: &str) -> usize {
87 bytes_per_pixel * r.dx() * r.dy()
88}
89
90/// RGBA is an in-memory image whose At method returns color::RGBA values.
91#[derive(Debug)]
92pub struct RGBA {
93 /// pix holds the image's pixels, in R, G, B, A order. The pixel at
94 /// (x, y) starts at pix[(y-Rect.min.y)*stride + (x-Rect.min.x)*4].
95 pub pix: Vec<u8>,
96 /// stride is the pix stride (in bytes) between vertically adjacent pixels.
97 pub stride: usize,
98 /// rect is the image's bounds.
99 pub rect: Rectangle,
100}
101
102impl Image for RGBA {
103 fn color_model(&self) -> color::Model {
104 color::Model::RGBAModel
105 }
106
107 fn bounds(&self) -> &Rectangle {
108 &self.rect
109 }
110
111 fn opaque(&self) -> bool {
112 if self.rect.empty() {
113 return true;
114 }
115 let mut i0 = 3;
116 let mut i1 = self.rect.dx() * 4;
117 for _y in self.rect.min.y..self.rect.max.y {
118 let mut i = i0;
119 while i < i1 {
120 if self.pix[i] != 0xff {
121 return false;
122 }
123 i += 4;
124 }
125 i0 += self.stride;
126 i1 += self.stride;
127 }
128 true
129 }
130
131 fn stride(&self) -> usize {
132 self.stride
133 }
134
135 fn pix(&self) -> &Vec<u8> {
136 &self.pix
137 }
138
139 fn get_pix_mutable(&mut self) -> &mut Vec<u8> {
140 &mut self.pix
141 }
142
143 fn at(&self, x: isize, y: isize) -> color::Color {
144 color::Color::RGBA(self.rgba_at(x, y))
145 }
146
147 fn set(&mut self, x: isize, y: isize, c: &color::Color) {
148 if let color::Color::RGBA(c) = c {
149 self.set_rbga(x, y, c);
150 } else {
151 self.set_rbga(x, y, &color::RGBA::new_from(c));
152 };
153 }
154
155 fn bytes_per_pixel(&self) -> usize {
156 4
157 }
158
159 // fn (p *RGBA) RGBA64At(x: isize, y: isize) color::RGBA64 {
160 // if !Point::new(x, y).inside(&self.rect) {
161 // return color::RGBA64{}
162 // }
163 // let i = self.pix_offset(x, y);
164 // s := self.pix[i..i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
165 // r := uint16(s[0])
166 // g := uint16(s[1])
167 // b := uint16(s[2])
168 // a := uint16(s[3])
169 // return color::RGBA64{
170 // (r << 8) | r,
171 // (g << 8) | g,
172 // (b << 8) | b,
173 // (a << 8) | a,
174 // }
175 // }
176}
177
178impl RGBA {
179 /// new returns a new RGBA image with the given bounds.
180 pub fn new(r: &Rectangle) -> Self {
181 Self {
182 pix: vec![0; pixel_buffer_length(4, r, "RGBA")],
183 stride: 4 * r.dx(),
184 rect: *r,
185 }
186 }
187
188 pub fn rgba_at(&self, x: isize, y: isize) -> color::RGBA {
189 if !(Point::new(x, y).inside(&self.rect)) {
190 return color::RGBA::new(0, 0, 0, 0);
191 }
192 let i = self.pix_offset(x, y);
193 let s = &self.pix[i..i + 4];
194 color::RGBA::new(s[0], s[1], s[2], s[3])
195 }
196
197 // fn (p *RGBA) SetRGBA64(x: isize, y: isize, c color::RGBA64) {
198 // if !Point::new(x, y).inside(&self.rect) {
199 // return
200 // }
201 // let i = self.pix_offset(x, y);
202 // s := self.pix[i..i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
203 // s[0] = u8(c.r >> 8)
204 // s[1] = u8(c.g >> 8)
205 // s[2] = u8(c.b >> 8)
206 // s[3] = u8(c.a >> 8)
207 // }
208
209 pub fn set_rbga(&mut self, x: isize, y: isize, c: &color::RGBA) {
210 if !(Point::new(x, y).inside(&self.rect)) {
211 return;
212 }
213 let i = self.pix_offset(x, y);
214 let s = &mut self.pix[i..i + 4];
215 s[0] = c.r;
216 s[1] = c.g;
217 s[2] = c.b;
218 s[3] = c.a;
219 }
220
221 // // SubImage returns an image representing the portion of the image p visible
222 // // through r. The returned value shares pixels with the original image.
223 // fn (p *RGBA) SubImage(r Rectangle) Image {
224 // r = r.intersect(self.rect)
225 // // If r1 and r2 are Rectangles, r1.intersect(r2) is not guaranteed to be inside
226 // // either r1 or r2 if the intersection is empty. Without explicitly checking for
227 // // this, the pix[i:] expression below can panic.
228 // if r.Empty() {
229 // return &RGBA{}
230 // }
231 // let i = self.pix_offset(r.min.x, r.min.y)
232 // return &RGBA{
233 // pix: self.pix[i:],
234 // stride: self.stride,
235 // Rect: r,
236 // }
237 // }
238
239 /// pix_offset returns the index of the first element of pix that corresponds to
240 /// the pixel at (x, y).
241 pub fn pix_offset(&self, x: isize, y: isize) -> usize {
242 (y - self.rect.min.y) as usize * self.stride + (x - self.rect.min.x) as usize * 4
243 }
244}
245
246/// RGBA64 is an in-memory image whose At method returns color::RGBA64 values.
247#[derive(Debug)]
248pub struct RGBA64 {
249 // pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
250 // (x, y) starts at pix[(y-Rect.min.y)*stride + (x-Rect.min.x)*8].
251 pub pix: Vec<u8>,
252 /// stride is the pix stride (in bytes) between vertically adjacent pixels.
253 pub stride: usize,
254 /// rect is the image's bounds.
255 rect: Rectangle,
256}
257
258impl Image for RGBA64 {
259 fn color_model(&self) -> color::Model {
260 color::Model::RGBA64Model
261 }
262
263 fn bounds(&self) -> &Rectangle {
264 &self.rect
265 }
266
267 fn at(&self, x: isize, y: isize) -> color::Color {
268 color::Color::RGBA64(self.rgba64_at(x, y))
269 }
270
271 fn set(&mut self, x: isize, y: isize, c: &color::Color) {
272 if let color::Color::RGBA64(c) = c {
273 self.set_rgba64(x, y, c);
274 } else {
275 self.set_rgba64(x, y, &color::RGBA64::new_from(c));
276 };
277 }
278
279 // opaque scans the entire image and reports whether it is fully opaque.
280 fn opaque(&self) -> bool {
281 if self.rect.empty() {
282 return true;
283 }
284 let (mut i0, mut i1) = (6, self.rect.dx() * 8);
285 for _y in self.rect.min.y..self.rect.max.y {
286 let mut i = i0;
287 while i < i1 {
288 if self.pix[i] != 0xff || self.pix[i + 1] != 0xff {
289 return false;
290 }
291 i += 8;
292 }
293 i0 += self.stride;
294 i1 += self.stride;
295 }
296 true
297 }
298
299 fn stride(&self) -> usize {
300 self.stride
301 }
302
303 fn pix(&self) -> &Vec<u8> {
304 &self.pix
305 }
306
307 fn get_pix_mutable(&mut self) -> &mut Vec<u8> {
308 &mut self.pix
309 }
310
311 fn bytes_per_pixel(&self) -> usize {
312 8
313 }
314}
315
316impl RGBA64 {
317 /// new returns a new RGBA64 image with the given bounds.
318 pub fn new(r: &Rectangle) -> Self {
319 Self {
320 pix: vec![0; pixel_buffer_length(8, r, "RGBA64")],
321 stride: 8 * r.dx(),
322 rect: *r,
323 }
324 }
325
326 /// pix_offset returns the index of the first element of pix that corresponds to
327 /// the pixel at (x, y).
328 pub fn pix_offset(&self, x: isize, y: isize) -> usize {
329 (y - self.rect.min.y) as usize * self.stride + (x - self.rect.min.x) as usize * 8
330 }
331
332 fn rgba64_at(&self, x: isize, y: isize) -> color::RGBA64 {
333 if !(Point::new(x, y).inside(&self.rect)) {
334 return color::RGBA64::new(0, 0, 0, 0);
335 }
336 let i = self.pix_offset(x, y);
337 let s = &self.pix[i..i + 8];
338 color::RGBA64::new(
339 ((s[0] as u16) << 8) | (s[1] as u16),
340 ((s[2] as u16) << 8) | (s[3] as u16),
341 ((s[4] as u16) << 8) | (s[5] as u16),
342 ((s[6] as u16) << 8) | (s[7] as u16),
343 )
344 }
345
346 fn set_rgba64(&mut self, x: isize, y: isize, c: &color::RGBA64) {
347 if !(Point::new(x, y).inside(&self.rect)) {
348 return;
349 }
350 let i = self.pix_offset(x, y);
351 let s = &mut self.pix[i..i + 8];
352 s[0] = (c.r >> 8) as u8;
353 s[1] = c.r as u8;
354 s[2] = (c.g >> 8) as u8;
355 s[3] = c.g as u8;
356 s[4] = (c.b >> 8) as u8;
357 s[5] = c.b as u8;
358 s[6] = (c.a >> 8) as u8;
359 s[7] = c.a as u8;
360 }
361}
362
363// // SubImage returns an image representing the portion of the image p visible
364// // through r. The returned value shares pixels with the original image.
365// fn (p *RGBA64) SubImage(r Rectangle) Image {
366// r = r.intersect(self.rect)
367// // If r1 and r2 are Rectangles, r1.intersect(r2) is not guaranteed to be inside
368// // either r1 or r2 if the intersection is empty. Without explicitly checking for
369// // this, the pix[i:] expression below can panic.
370// if r.Empty() {
371// return &RGBA64{}
372// }
373// let i = self.pix_offset(r.min.x, r.min.y)
374// return &RGBA64{
375// pix: self.pix[i:],
376// stride: self.stride,
377// Rect: r,
378// }
379// }
380
381/// NRGBA is an in-memory image whose At method returns color::NRGBA values.
382#[derive(Debug)]
383pub struct NRGBA {
384 /// pix holds the image's pixels, in R, G, B, A order. The pixel at
385 /// (x, y) starts at pix[(y-Rect.min.y)*stride + (x-Rect.min.x)*4].
386 pub pix: Vec<u8>,
387 /// stride is the pix stride (in bytes) between vertically adjacent pixels.
388 pub stride: usize,
389 /// rect is the image's bounds.
390 pub rect: Rectangle,
391}
392
393impl Image for NRGBA {
394 fn color_model(&self) -> color::Model {
395 color::Model::NRGBAModel
396 }
397
398 fn bounds(&self) -> &Rectangle {
399 &self.rect
400 }
401
402 /// opaque scans the entire image and reports whether it is fully opaque.
403 fn opaque(&self) -> bool {
404 if self.rect.empty() {
405 return true;
406 }
407 let mut i0 = 3;
408 let mut i1 = self.rect.dx() * 4;
409 for _y in self.rect.min.y..self.rect.max.y {
410 let mut i = i0;
411 while i < i1 {
412 if self.pix[i] != 0xff {
413 return false;
414 }
415 i += 4;
416 }
417 i0 += self.stride;
418 i1 += self.stride;
419 }
420 true
421 }
422
423 fn stride(&self) -> usize {
424 self.stride
425 }
426
427 fn pix(&self) -> &Vec<u8> {
428 &self.pix
429 }
430
431 fn get_pix_mutable(&mut self) -> &mut Vec<u8> {
432 &mut self.pix
433 }
434
435 fn at(&self, x: isize, y: isize) -> color::Color {
436 color::Color::NRGBA(self.nrgba_at(x, y))
437 }
438
439 fn set(&mut self, x: isize, y: isize, c: &color::Color) {
440 if let color::Color::NRGBA(c) = c {
441 self.set_nrgba(x, y, c);
442 } else {
443 self.set_nrgba(x, y, &color::NRGBA::new_from(c));
444 };
445 }
446
447 fn bytes_per_pixel(&self) -> usize {
448 4
449 }
450}
451
452impl NRGBA {
453 /// new returns a new NRGBA image with the given bounds.
454 pub fn new(r: &Rectangle) -> Self {
455 Self {
456 pix: vec![0; pixel_buffer_length(4, r, "NRGBA")],
457 stride: 4 * r.dx(),
458 rect: *r,
459 }
460 }
461
462 // fn RGBA64At(&self, x: isize, y: isize) color::RGBA64 {
463 // r, g, b, a := self.nrgba_at(x, y).rgba()
464 // return color::RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
465 // }
466
467 fn nrgba_at(&self, x: isize, y: isize) -> color::NRGBA {
468 if !(Point::new(x, y).inside(&self.rect)) {
469 return color::NRGBA::new(0, 0, 0, 0);
470 }
471 let i = self.pix_offset(x, y);
472 let s = &self.pix[i..i + 4];
473 color::NRGBA::new(s[0], s[1], s[2], s[3])
474 }
475
476 /// pix_offset returns the index of the first element of pix that corresponds to
477 /// the pixel at (x, y).
478 pub fn pix_offset(&self, x: isize, y: isize) -> usize {
479 (y - self.rect.min.y) as usize * self.stride + (x - self.rect.min.x) as usize * 4
480 }
481
482 pub fn set_nrgba(&mut self, x: isize, y: isize, c: &color::NRGBA) {
483 if !(Point::new(x, y).inside(&self.rect)) {
484 return;
485 }
486 let i = self.pix_offset(x, y);
487 self.pix[i] = c.r;
488 self.pix[i + 1] = c.g;
489 self.pix[i + 2] = c.b;
490 self.pix[i + 3] = c.a;
491 }
492 // fn SetRGBA64(&self, x: isize, y: isize, c color::RGBA64) {
493 // if !Point::new(x, y).inside(&self.rect) {
494 // return
495 // }
496 // r, g, b, a := uint32(c.r), uint32(c.g), uint32(c.b), uint32(c.a)
497 // if (a != 0) && (a != 0xffff) {
498 // r = (r * 0xffff) / a
499 // g = (g * 0xffff) / a
500 // b = (b * 0xffff) / a
501 // }
502 // let i = self.pix_offset(x, y);
503 // s := self.pix[i..i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
504 // s[0] = u8(r >> 8)
505 // s[1] = u8(g >> 8)
506 // s[2] = u8(b >> 8)
507 // s[3] = u8(a >> 8)
508 // }
509
510 // // SubImage returns an image representing the portion of the image p visible
511 // // through r. The returned value shares pixels with the original image.
512 // fn SubImage(&self, r Rectangle) Image {
513 // r = r.intersect(self.rect)
514 // // If r1 and r2 are Rectangles, r1.intersect(r2) is not guaranteed to be inside
515 // // either r1 or r2 if the intersection is empty. Without explicitly checking for
516 // // this, the pix[i:] expression below can panic.
517 // if r.Empty() {
518 // return &NRGBA{}
519 // }
520 // let i = self.pix_offset(r.min.x, r.min.y)
521 // return &NRGBA{
522 // pix: self.pix[i:],
523 // stride: self.stride,
524 // Rect: r,
525 // }
526 // }
527}
528
529/// NRGBA64 is an in-memory image whose At method returns color::NRGBA64 values.
530#[derive(Debug)]
531pub struct NRGBA64 {
532 // pix holds the image's pixels, in R, G, B, A order and big-endian format. The pixel at
533 // (x, y) starts at pix[(y-Rect.min.y)*stride + (x-Rect.min.x)*8].
534 pub pix: Vec<u8>,
535 /// stride is the pix stride (in bytes) between vertically adjacent pixels.
536 pub stride: usize,
537 /// rect is the image's bounds.
538 rect: Rectangle,
539}
540
541impl Image for NRGBA64 {
542 fn color_model(&self) -> color::Model {
543 color::Model::NRGBA64Model
544 }
545
546 fn bounds(&self) -> &Rectangle {
547 &self.rect
548 }
549
550 // fn at(&self, x: isize, y: isize) -> color::Color {
551 // color::Color::RGBA64(self.rgba64_at(x, y))
552 // }
553
554 fn set(&mut self, x: isize, y: isize, c: &color::Color) {
555 if let color::Color::NRGBA64(c) = c {
556 self.set_nrgba64(x, y, c);
557 } else {
558 self.set_nrgba64(x, y, &color::NRGBA64::new_from(c));
559 };
560 }
561
562 // // opaque scans the entire image and reports whether it is fully opaque.
563 // fn opaque(&self) -> bool {
564 // if self.rect.empty() {
565 // return true;
566 // }
567 // let (mut i0, mut i1) = (6, self.rect.dx() * 8);
568 // for _y in self.rect.min.y..self.rect.max.y {
569 // let mut i = i0;
570 // while i < i1 {
571 // if self.pix[i ] != 0xff || self.pix[i + 1] != 0xff {
572 // return false;
573 // }
574 // i += 8;
575 // }
576 // i0 += self.stride;
577 // i1 += self.stride;
578 // }
579 // return true;
580 // }
581
582 fn stride(&self) -> usize {
583 self.stride
584 }
585
586 fn pix(&self) -> &Vec<u8> {
587 &self.pix
588 }
589
590 fn get_pix_mutable(&mut self) -> &mut Vec<u8> {
591 &mut self.pix
592 }
593
594 fn at(&self, x: isize, y: isize) -> color::Color {
595 color::Color::NRGBA64(self.nrgba64_at(x, y))
596 }
597
598 fn opaque(&self) -> bool {
599 if self.rect.empty() {
600 return true;
601 }
602 let (mut i0, mut i1) = (6, self.rect.dx() * 8);
603 for _y in self.rect.min.y..self.rect.max.y {
604 let mut i = i0;
605 while i < i1 {
606 if self.pix[i] != 0xff || self.pix[i + 1] != 0xff {
607 return false;
608 }
609 i += 8;
610 }
611 i0 += self.stride;
612 i1 += self.stride;
613 }
614 true
615 }
616
617 fn bytes_per_pixel(&self) -> usize {
618 8
619 }
620}
621
622impl NRGBA64 {
623 /// new returns a new NRGBA64 image with the given bounds.
624 pub fn new(r: &Rectangle) -> Self {
625 Self {
626 pix: vec![0; pixel_buffer_length(8, r, "NRGBA64")],
627 stride: 8 * r.dx(),
628 rect: *r,
629 }
630 }
631
632 fn set_nrgba64(&mut self, x: isize, y: isize, c: &color::NRGBA64) {
633 if !(Point::new(x, y).inside(&self.rect)) {
634 return;
635 }
636 let i = self.pix_offset(x, y);
637 let s = &mut self.pix[i..i + 8];
638 s[0] = (c.r >> 8) as u8;
639 s[1] = c.r as u8;
640 s[2] = (c.g >> 8) as u8;
641 s[3] = c.g as u8;
642 s[4] = (c.b >> 8) as u8;
643 s[5] = c.b as u8;
644 s[6] = (c.a >> 8) as u8;
645 s[7] = c.a as u8;
646 }
647
648 /// pix_offset returns the index of the first element of pix that corresponds to
649 /// the pixel at (x, y).
650 pub fn pix_offset(&self, x: isize, y: isize) -> usize {
651 (y - self.rect.min.y) as usize * self.stride + (x - self.rect.min.x) as usize * 8
652 }
653
654 // fn (p *NRGBA64) RGBA64At(x: isize, y: isize) color::RGBA64 {
655 // r, g, b, a := self.nrgba64_at(x, y).rgba()
656 // return color::RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
657 // }
658
659 fn nrgba64_at(&self, x: isize, y: isize) -> color::NRGBA64 {
660 if !(Point::new(x, y).inside(&self.rect)) {
661 return color::NRGBA64::new(0, 0, 0, 0);
662 }
663 let i = self.pix_offset(x, y);
664 let s = &self.pix[i..i + 8];
665 color::NRGBA64::new(
666 (s[0] as u16) << 8 | (s[1] as u16),
667 (s[2] as u16) << 8 | (s[3] as u16),
668 (s[4] as u16) << 8 | (s[5] as u16),
669 (s[6] as u16) << 8 | (s[7] as u16),
670 )
671 }
672
673 // fn (p *NRGBA64) SetRGBA64(x: isize, y: isize, c color::RGBA64) {
674 // if !Point::new(x, y).inside(&self.rect) {
675 // return
676 // }
677 // r, g, b, a := uint32(c.r), uint32(c.g), uint32(c.b), uint32(c.a)
678 // if (a != 0) && (a != 0xffff) {
679 // r = (r * 0xffff) / a
680 // g = (g * 0xffff) / a
681 // b = (b * 0xffff) / a
682 // }
683 // let i = self.pix_offset(x, y);
684 // s := self.pix[i..i+8 : i+8] // Small cap improves performance, see https://golang.org/issue/27857
685 // s[0] = u8(r >> 8)
686 // s[1] = u8(r)
687 // s[2] = u8(g >> 8)
688 // s[3] = u8(g)
689 // s[4] = u8(b >> 8)
690 // s[5] = u8(b)
691 // s[6] = u8(a >> 8)
692 // s[7] = u8(a)
693 // }
694
695 // // SubImage returns an image representing the portion of the image p visible
696 // // through r. The returned value shares pixels with the original image.
697 // fn (p *NRGBA64) SubImage(r Rectangle) Image {
698 // r = r.intersect(self.rect)
699 // // If r1 and r2 are Rectangles, r1.intersect(r2) is not guaranteed to be inside
700 // // either r1 or r2 if the intersection is empty. Without explicitly checking for
701 // // this, the pix[i:] expression below can panic.
702 // if r.Empty() {
703 // return &NRGBA64{}
704 // }
705 // let i = self.pix_offset(r.min.x, r.min.y)
706 // return &NRGBA64{
707 // pix: self.pix[i:],
708 // stride: self.stride,
709 // Rect: r,
710 // }
711 // }
712}
713
714/// Alpha is an in-memory image whose At method returns color::Alpha values.
715#[derive(Debug)]
716pub struct Alpha {
717 // pix holds the image's pixels, as alpha values. The pixel at
718 // (x, y) starts at pix[(y-Rect.min.y)*stride + (x-Rect.min.x)*1].
719 pub pix: Vec<u8>,
720 /// stride is the pix stride (in bytes) between vertically adjacent pixels.
721 pub stride: usize,
722 /// rect is the image's bounds.
723 rect: Rectangle,
724}
725
726impl Image for Alpha {
727 fn color_model(&self) -> color::Model {
728 color::Model::AlphaModel
729 }
730
731 fn bounds(&self) -> &Rectangle {
732 &self.rect
733 }
734
735 fn at(&self, x: isize, y: isize) -> color::Color {
736 color::Color::Alpha(self.alpha_at(x, y))
737 }
738
739 fn set(&mut self, x: isize, y: isize, c: &color::Color) {
740 if let color::Color::Alpha(c) = c {
741 self.set_alpha(x, y, c);
742 } else {
743 self.set_alpha(x, y, &color::Alpha::new_from(c));
744 };
745 }
746
747 fn opaque(&self) -> bool {
748 if self.rect.empty() {
749 return true;
750 }
751 let (mut i0, mut i1) = (0, self.rect.dx());
752 for _y in self.rect.min.y..self.rect.max.y {
753 for i in i0..i1 {
754 if self.pix[i] != 0xff {
755 return false;
756 }
757 }
758 i0 += self.stride;
759 i1 += self.stride;
760 }
761 true
762 }
763
764 fn stride(&self) -> usize {
765 self.stride
766 }
767
768 fn pix(&self) -> &Vec<u8> {
769 &self.pix
770 }
771
772 fn get_pix_mutable(&mut self) -> &mut Vec<u8> {
773 &mut self.pix
774 }
775
776 fn bytes_per_pixel(&self) -> usize {
777 1
778 }
779}
780
781impl Alpha {
782 /// new returns a new Alpha image with the given bounds.
783 pub fn new(r: &Rectangle) -> Self {
784 Self {
785 pix: vec![0; pixel_buffer_length(1, r, "Alpha")],
786 stride: r.dx(),
787 rect: *r,
788 }
789 }
790
791 fn alpha_at(&self, x: isize, y: isize) -> color::Alpha {
792 if !(Point::new(x, y).inside(&self.rect)) {
793 return color::Alpha::new(0);
794 }
795 let i = self.pix_offset(x, y);
796 color::Alpha::new(self.pix[i])
797 }
798
799 /// pix_offset returns the index of the first element of pix that corresponds to
800 /// the pixel at (x, y).
801 pub fn pix_offset(&self, x: isize, y: isize) -> usize {
802 (y - self.rect.min.y) as usize * self.stride + (x - self.rect.min.x) as usize
803 }
804
805 // fn RGBA64At(&self, x: isize, y: isize) color::RGBA64 {
806 // a := uint16(self.alpha_at(x, y).a)
807 // a |= a << 8
808 // return color::RGBA64{a, a, a, a}
809 // }
810
811 // fn SetRGBA64(&self, x: isize, y: isize, c color::RGBA64) {
812 // if !Point::new(x, y).inside(&self.rect) {
813 // return
814 // }
815 // let i = self.pix_offset(x, y);
816 // self.pix[i] = u8(c.a >> 8)
817 // }
818
819 fn set_alpha(&mut self, x: isize, y: isize, c: &color::Alpha) {
820 if !(Point::new(x, y).inside(&self.rect)) {
821 return;
822 }
823 let i = self.pix_offset(x, y);
824 self.pix[i] = c.a;
825 }
826
827 // // SubImage returns an image representing the portion of the image p visible
828 // // through r. The returned value shares pixels with the original image.
829 // fn SubImage(&self, r Rectangle) Image {
830 // r = r.intersect(self.rect)
831 // // If r1 and r2 are Rectangles, r1.intersect(r2) is not guaranteed to be inside
832 // // either r1 or r2 if the intersection is empty. Without explicitly checking for
833 // // this, the pix[i:] expression below can panic.
834 // if r.Empty() {
835 // return &Alpha{}
836 // }
837 // let i = self.pix_offset(r.min.x, r.min.y)
838 // return &Alpha{
839 // pix: self.pix[i:],
840 // stride: self.stride,
841 // Rect: r,
842 // }
843 // }
844}
845
846/// Alpha16 is an in-memory image whose At method returns color::Alpha16 values.
847#[derive(Debug)]
848pub struct Alpha16 {
849 // pix holds the image's pixels, as alpha values. The pixel at
850 // (x, y) starts at pix[(y-Rect.min.y)*stride + (x-Rect.min.x)*1].
851 pub pix: Vec<u8>,
852 /// stride is the pix stride (in bytes) between vertically adjacent pixels.
853 pub stride: usize,
854 /// rect is the image's bounds.
855 rect: Rectangle,
856}
857
858impl Image for Alpha16 {
859 fn color_model(&self) -> color::Model {
860 color::Model::Alpha16Model
861 }
862
863 fn bounds(&self) -> &Rectangle {
864 &self.rect
865 }
866
867 fn at(&self, x: isize, y: isize) -> color::Color {
868 color::Color::Alpha16(self.alpha16_at(x, y))
869 }
870
871 fn set(&mut self, x: isize, y: isize, c: &color::Color) {
872 if let color::Color::Alpha16(c) = c {
873 self.set_alpha16(x, y, c);
874 } else {
875 self.set_alpha16(x, y, &color::Alpha16::new_from(c));
876 };
877 }
878
879 fn opaque(&self) -> bool {
880 if self.rect.empty() {
881 return true;
882 }
883 let (mut i0, mut i1) = (0, self.rect.dx() * 2);
884 for _y in self.rect.min.y..self.rect.max.y {
885 let mut i = i0;
886 while i < i1 {
887 if self.pix[i] != 0xff || self.pix[i + 1] != 0xff {
888 return false;
889 }
890 i += 2;
891 }
892 i0 += self.stride;
893 i1 += self.stride;
894 }
895 true
896 }
897
898 fn stride(&self) -> usize {
899 self.stride
900 }
901
902 fn pix(&self) -> &Vec<u8> {
903 &self.pix
904 }
905
906 fn get_pix_mutable(&mut self) -> &mut Vec<u8> {
907 &mut self.pix
908 }
909
910 fn bytes_per_pixel(&self) -> usize {
911 2
912 }
913}
914
915impl Alpha16 {
916 /// new returns a new Alpha16 image with the given bounds.
917 pub fn new(r: &Rectangle) -> Self {
918 Self {
919 pix: vec![0; pixel_buffer_length(2, r, "Alpha16")],
920 stride: 2 * r.dx(),
921 rect: *r,
922 }
923 }
924
925 fn alpha16_at(&self, x: isize, y: isize) -> color::Alpha16 {
926 if !(Point::new(x, y).inside(&self.rect)) {
927 return color::Alpha16::new(0);
928 }
929 let i = self.pix_offset(x, y);
930 color::Alpha16::new((self.pix[i] as u16) << 8 | (self.pix[i + 1] as u16))
931 }
932
933 /// pix_offset returns the index of the first element of pix that corresponds to
934 /// the pixel at (x, y).
935 pub fn pix_offset(&self, x: isize, y: isize) -> usize {
936 (y - self.rect.min.y) as usize * self.stride + (x - self.rect.min.x) as usize * 2
937 }
938
939 // fn (p *Alpha16) RGBA64At(x: isize, y: isize) color::RGBA64 {
940 // a := self.Alpha16At(x, y).a
941 // return color::RGBA64{a, a, a, a}
942 // }
943
944 // fn (p *Alpha16) SetRGBA64(x: isize, y: isize, c color::RGBA64) {
945 // if !Point::new(x, y).inside(&self.rect) {
946 // return
947 // }
948 // let i = self.pix_offset(x, y);
949 // self.pix[i+0] = u8(c.a >> 8)
950 // self.pix[i+1] = u8(c.a)
951 // }
952
953 fn set_alpha16(&mut self, x: isize, y: isize, c: &color::Alpha16) {
954 if !(Point::new(x, y).inside(&self.rect)) {
955 return;
956 }
957 let i = self.pix_offset(x, y);
958 self.pix[i] = (c.a >> 8) as u8;
959 self.pix[i + 1] = (c.a) as u8;
960 }
961
962 // // SubImage returns an image representing the portion of the image p visible
963 // // through r. The returned value shares pixels with the original image.
964 // fn (p *Alpha16) SubImage(r Rectangle) Image {
965 // r = r.intersect(self.rect)
966 // // If r1 and r2 are Rectangles, r1.intersect(r2) is not guaranteed to be inside
967 // // either r1 or r2 if the intersection is empty. Without explicitly checking for
968 // // this, the pix[i:] expression below can panic.
969 // if r.Empty() {
970 // return &Alpha16{}
971 // }
972 // let i = self.pix_offset(r.min.x, r.min.y)
973 // return &Alpha16{
974 // pix: self.pix[i:],
975 // stride: self.stride,
976 // Rect: r,
977 // }
978 // }
979}
980
981/// Gray is an in-memory image whose At method returns color::Gray values.
982#[derive(Debug)]
983pub struct Gray {
984 /// pix holds the image's pixels, as gray values. The pixel at
985 /// (x, y) starts at pix[(y-Rect.min.y)*stride + (x-Rect.min.x)*1].
986 pub pix: Vec<u8>,
987 /// stride is the pix stride (in bytes) between vertically adjacent pixels.
988 pub stride: usize,
989 /// rect is the image's bounds.
990 rect: Rectangle,
991}
992
993impl Image for Gray {
994 fn color_model(&self) -> color::Model {
995 color::Model::GrayModel
996 }
997
998 fn bounds(&self) -> &Rectangle {
999 &self.rect
1000 }
1001
1002 /// opaque scans the entire image and reports whether it is fully opaque.
1003 fn opaque(&self) -> bool {
1004 true
1005 }
1006
1007 fn stride(&self) -> usize {
1008 self.stride
1009 }
1010
1011 fn pix(&self) -> &Vec<u8> {
1012 &self.pix
1013 }
1014
1015 fn get_pix_mutable(&mut self) -> &mut Vec<u8> {
1016 &mut self.pix
1017 }
1018
1019 fn at(&self, x: isize, y: isize) -> color::Color {
1020 color::Color::Gray(self.gray_at(x, y))
1021 }
1022
1023 fn set(&mut self, x: isize, y: isize, c: &color::Color) {
1024 if let color::Color::Gray(c) = c {
1025 self.set_gray(x, y, c);
1026 } else {
1027 self.set_gray(x, y, &color::Gray::new_from(c));
1028 };
1029 }
1030
1031 fn bytes_per_pixel(&self) -> usize {
1032 1
1033 }
1034}
1035
1036impl Gray {
1037 /// new returns a new Gray image with the given bounds.
1038 pub fn new(r: &Rectangle) -> Self {
1039 Self {
1040 pix: vec![0; pixel_buffer_length(1, r, "Gray")],
1041 stride: r.dx(),
1042 rect: *r,
1043 }
1044 }
1045
1046 // fn (p *Gray) RGBA64At(x: isize, y: isize) color::RGBA64 {
1047 // gray := uint16(self.GrayAt(x, y).y)
1048 // gray |= gray << 8
1049 // return color::RGBA64{gray, gray, gray, 0xffff}
1050 // }
1051
1052 pub fn gray_at(&self, x: isize, y: isize) -> color::Gray {
1053 if !(Point::new(x, y).inside(&self.rect)) {
1054 return color::Gray::new(0);
1055 }
1056 let i = self.pix_offset(x, y);
1057 color::Gray::new(self.pix[i])
1058 }
1059
1060 // pix_offset returns the index of the first element of pix that corresponds to
1061 // the pixel at (x, y).
1062 pub fn pix_offset(&self, x: isize, y: isize) -> usize {
1063 (y - self.rect.min.y) as usize * self.stride + (x - self.rect.min.x) as usize
1064 }
1065
1066 fn set_gray(&mut self, x: isize, y: isize, c: &color::Gray) {
1067 if !(Point::new(x, y).inside(&self.rect)) {
1068 return;
1069 }
1070 let i = self.pix_offset(x, y);
1071 self.pix[i] = c.y;
1072 }
1073
1074 // fn (p *Gray) SetRGBA64(x: isize, y: isize, c color::RGBA64) {
1075 // if !Point::new(x, y).inside(&self.rect) {
1076 // return
1077 // }
1078 // // This formula is the same as in color::grayModel.
1079 // gray := (19595*uint32(c.r) + 38470*uint32(c.g) + 7471*uint32(c.b) + 1<<15) >> 24
1080 // let i = self.pix_offset(x, y);
1081 // self.pix[i] = u8(gray)
1082 // }
1083
1084 // // SubImage returns an image representing the portion of the image p visible
1085 // // through r. The returned value shares pixels with the original image.
1086 // fn (p *Gray) SubImage(r Rectangle) Image {
1087 // r = r.intersect(self.rect)
1088 // // If r1 and r2 are Rectangles, r1.intersect(r2) is not guaranteed to be inside
1089 // // either r1 or r2 if the intersection is empty. Without explicitly checking for
1090 // // this, the pix[i:] expression below can panic.
1091 // if r.Empty() {
1092 // return &Gray{}
1093 // }
1094 // let i = self.pix_offset(r.min.x, r.min.y)
1095 // return &Gray{
1096 // pix: self.pix[i:],
1097 // stride: self.stride,
1098 // Rect: r,
1099 // }
1100 // }
1101}
1102
1103/// Gray16 is an in-memory image whose At method returns color::Gray16 values.
1104#[derive(Debug)]
1105pub struct Gray16 {
1106 /// pix holds the image's pixels, as gray values in big-endian format. The pixel at
1107 /// (x, y) starts at pix[(y-Rect.min.y)*stride + (x-Rect.min.x)*2].
1108 pub pix: Vec<u8>,
1109 /// stride is the pix stride (in bytes) between vertically adjacent pixels.
1110 pub stride: usize,
1111 /// rect is the image's bounds.
1112 rect: Rectangle,
1113}
1114
1115impl Image for Gray16 {
1116 fn color_model(&self) -> color::Model {
1117 color::Model::Gray16Model
1118 }
1119
1120 fn bounds(&self) -> &Rectangle {
1121 &self.rect
1122 }
1123
1124 /// opaque scans the entire image and reports whether it is fully opaque.
1125 fn opaque(&self) -> bool {
1126 true
1127 }
1128
1129 fn stride(&self) -> usize {
1130 self.stride
1131 }
1132
1133 fn pix(&self) -> &Vec<u8> {
1134 &self.pix
1135 }
1136
1137 fn get_pix_mutable(&mut self) -> &mut Vec<u8> {
1138 &mut self.pix
1139 }
1140
1141 fn at(&self, x: isize, y: isize) -> color::Color {
1142 color::Color::Gray16(self.gray16_at(x, y))
1143 }
1144
1145 fn set(&mut self, x: isize, y: isize, c: &color::Color) {
1146 if let color::Color::Gray16(c) = c {
1147 self.set_gray16(x, y, c);
1148 } else {
1149 self.set_gray16(x, y, &color::Gray16::new_from(c));
1150 };
1151 }
1152
1153 fn bytes_per_pixel(&self) -> usize {
1154 2
1155 }
1156}
1157
1158impl Gray16 {
1159 /// new returns a new Gray16 image with the given bounds.
1160 pub fn new(r: &Rectangle) -> Self {
1161 Self {
1162 pix: vec![0; pixel_buffer_length(2, r, "Gray16")],
1163 stride: 2 * r.dx(),
1164 rect: *r,
1165 }
1166 }
1167
1168 pub fn gray16_at(&self, x: isize, y: isize) -> color::Gray16 {
1169 if !(Point::new(x, y).inside(&self.rect)) {
1170 return color::Gray16::new(0);
1171 }
1172 let i = self.pix_offset(x, y);
1173 color::Gray16::new(((self.pix[i] as u16) << 8) | (self.pix[i + 1] as u16))
1174 }
1175
1176 // pix_offset returns the index of the first element of pix that corresponds to
1177 // the pixel at (x, y).
1178 pub fn pix_offset(&self, x: isize, y: isize) -> usize {
1179 (y - self.rect.min.y) as usize * self.stride + (x - self.rect.min.x) as usize * 2
1180 }
1181
1182 fn set_gray16(&mut self, x: isize, y: isize, c: &color::Gray16) {
1183 if !(Point::new(x, y).inside(&self.rect)) {
1184 return;
1185 }
1186 let i = self.pix_offset(x, y);
1187 self.pix[i] = (c.y >> 8) as u8;
1188 self.pix[i + 1] = (c.y) as u8;
1189 }
1190
1191 // fn (p *Gray16) color_model() color::Model { return color::Gray16Model }
1192
1193 // fn (p *Gray16) bounds() Rectangle { return self.rect }
1194
1195 // fn (p *Gray16) At(x: isize, y: isize) color::Color {
1196 // return self.Gray16At(x, y)
1197 // }
1198
1199 // fn (p *Gray16) RGBA64At(x: isize, y: isize) color::RGBA64 {
1200 // gray := self.Gray16At(x, y).y
1201 // return color::RGBA64{gray, gray, gray, 0xffff}
1202 // }
1203
1204 // // pix_offset returns the index of the first element of pix that corresponds to
1205 // // the pixel at (x, y).
1206 // fn (p *Gray16) pix_offset(x: isize, y: isize) isize {
1207 // return (y-self.rect.min.y)*self.stride + (x-self.rect.min.x)*2
1208 // }
1209
1210 // fn (p *Gray16) SetRGBA64(x: isize, y: isize, c color::RGBA64) {
1211 // if !Point::new(x, y).inside(&self.rect) {
1212 // return
1213 // }
1214 // // This formula is the same as in color::gray16Model.
1215 // gray := (19595*uint32(c.r) + 38470*uint32(c.g) + 7471*uint32(c.b) + 1<<15) >> 16
1216 // let i = self.pix_offset(x, y);
1217 // self.pix[i+0] = u8(gray >> 8)
1218 // self.pix[i+1] = u8(gray)
1219 // }
1220
1221 // fn (p *Gray16) SetGray16(x: isize, y: isize, c color::Gray16) {
1222 // if !Point::new(x, y).inside(&self.rect) {
1223 // return
1224 // }
1225 // let i = self.pix_offset(x, y);
1226 // self.pix[i+0] = u8(c.y >> 8)
1227 // self.pix[i+1] = u8(c.y)
1228 // }
1229
1230 // // SubImage returns an image representing the portion of the image p visible
1231 // // through r. The returned value shares pixels with the original image.
1232 // fn (p *Gray16) SubImage(r Rectangle) Image {
1233 // r = r.intersect(self.rect)
1234 // // If r1 and r2 are Rectangles, r1.intersect(r2) is not guaranteed to be inside
1235 // // either r1 or r2 if the intersection is empty. Without explicitly checking for
1236 // // this, the pix[i:] expression below can panic.
1237 // if r.Empty() {
1238 // return &Gray16{}
1239 // }
1240 // let i = self.pix_offset(r.min.x, r.min.y)
1241 // return &Gray16{
1242 // pix: self.pix[i:],
1243 // stride: self.stride,
1244 // Rect: r,
1245 // }
1246 // }
1247
1248 // // opaque scans the entire image and reports whether it is fully opaque.
1249 // fn (p *Gray16) opaque() bool {
1250 // return true
1251 // }
1252}
1253
1254// // CMYK is an in-memory image whose At method returns color::CMYK values.
1255// type CMYK struct {
1256// // pix holds the image's pixels, in C, M, Y, K order. The pixel at
1257// // (x, y) starts at pix[(y-Rect.min.y)*stride + (x-Rect.min.x)*4].
1258// pix [u8]
1259// // stride is the pix stride (in bytes) between vertically adjacent pixels.
1260// stride isize
1261// // Rect is the image's bounds.
1262// Rect Rectangle
1263// }
1264
1265// fn (p *CMYK) color_model() color::Model { return color::CMYKModel }
1266
1267// fn (p *CMYK) bounds() Rectangle { return self.rect }
1268
1269// fn (p *CMYK) At(x: isize, y: isize) color::Color {
1270// return self.CMYKAt(x, y)
1271// }
1272
1273// fn (p *CMYK) RGBA64At(x: isize, y: isize) color::RGBA64 {
1274// r, g, b, a := self.CMYKAt(x, y).rgba()
1275// return color::RGBA64{uint16(r), uint16(g), uint16(b), uint16(a)}
1276// }
1277
1278// fn (p *CMYK) CMYKAt(x: isize, y: isize) color::CMYK {
1279// if !Point::new(x, y).inside(&self.rect) {
1280// return color::CMYK{}
1281// }
1282// let i = self.pix_offset(x, y);
1283// s := self.pix[i..i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
1284// return color::CMYK{s[0], s[1], s[2], s[3]}
1285// }
1286
1287// // pix_offset returns the index of the first element of pix that corresponds to
1288// // the pixel at (x, y).
1289// fn (p *CMYK) pix_offset(x: isize, y: isize) isize {
1290// return (y-self.rect.min.y)*self.stride + (x-self.rect.min.x)*4
1291// }
1292
1293// fn (p *CMYK) Set(x: isize, y: isize, c color::Color) {
1294// if !Point::new(x, y).inside(&self.rect) {
1295// return
1296// }
1297// let i = self.pix_offset(x, y);
1298// c1 := color::CMYKModel.Convert(c).(color::CMYK)
1299// s := self.pix[i..i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
1300// s[0] = c1.C
1301// s[1] = c1.M
1302// s[2] = c1.y
1303// s[3] = c1.K
1304// }
1305
1306// fn (p *CMYK) SetRGBA64(x: isize, y: isize, c color::RGBA64) {
1307// if !Point::new(x, y).inside(&self.rect) {
1308// return
1309// }
1310// cc, mm, yy, kk := color::RGBToCMYK(u8(c.r>>8), u8(c.g>>8), u8(c.b>>8))
1311// let i = self.pix_offset(x, y);
1312// s := self.pix[i..i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
1313// s[0] = cc
1314// s[1] = mm
1315// s[2] = yy
1316// s[3] = kk
1317// }
1318
1319// fn (p *CMYK) SetCMYK(x: isize, y: isize, c color::CMYK) {
1320// if !Point::new(x, y).inside(&self.rect) {
1321// return
1322// }
1323// let i = self.pix_offset(x, y);
1324// s := self.pix[i..i+4 : i+4] // Small cap improves performance, see https://golang.org/issue/27857
1325// s[0] = c.C
1326// s[1] = c.M
1327// s[2] = c.y
1328// s[3] = c.K
1329// }
1330
1331// // SubImage returns an image representing the portion of the image p visible
1332// // through r. The returned value shares pixels with the original image.
1333// fn (p *CMYK) SubImage(r Rectangle) Image {
1334// r = r.intersect(self.rect)
1335// // If r1 and r2 are Rectangles, r1.intersect(r2) is not guaranteed to be inside
1336// // either r1 or r2 if the intersection is empty. Without explicitly checking for
1337// // this, the pix[i:] expression below can panic.
1338// if r.Empty() {
1339// return &CMYK{}
1340// }
1341// let i = self.pix_offset(r.min.x, r.min.y)
1342// return &CMYK{
1343// pix: self.pix[i:],
1344// stride: self.stride,
1345// Rect: r,
1346// }
1347// }
1348
1349// // opaque scans the entire image and reports whether it is fully opaque.
1350// fn (p *CMYK) opaque() bool {
1351// return true
1352// }
1353
1354// // NewCMYK returns a new CMYK image with the given bounds.
1355// fn NewCMYK(r Rectangle) *CMYK {
1356// return &CMYK{
1357// pix: make([u8], pixel_buffer_length(4, r, "CMYK")),
1358// stride: 4 * r.dx(),
1359// Rect: r,
1360// }
1361// }
1362
1363/// Paletted is an in-memory image of u8 indices into a given palette.
1364#[derive(Debug)]
1365pub struct Paletted {
1366 /// pix holds the image's pixels, as palette indices. The pixel at
1367 /// (x, y) starts at pix[(y-Rect.min.y)*stride + (x-Rect.min.x)*1].
1368 pub pix: Vec<u8>,
1369 /// stride is the pix stride (in bytes) between vertically adjacent pixels.
1370 pub stride: usize,
1371 /// rect is the image's bounds.
1372 rect: Rectangle,
1373 /// palette is the image's palette.
1374 pub(super) palette: color::Palette,
1375}
1376
1377impl Image for Paletted {
1378 fn color_model(&self) -> color::Model {
1379 color::Model::Paletted(self.palette.clone())
1380 }
1381
1382 fn bounds(&self) -> &Rectangle {
1383 &self.rect
1384 }
1385
1386 fn at(&self, x: isize, y: isize) -> color::Color {
1387 if self.palette.colors.is_empty() {
1388 return color::Color::new_rgba(0, 0, 0, 0);
1389 }
1390 if !(Point::new(x, y).inside(&self.rect)) {
1391 return self.palette.colors[0];
1392 }
1393 let i = self.pix_offset(x, y);
1394 self.palette.colors[self.pix[i] as usize]
1395 }
1396
1397 fn set(&mut self, x: isize, y: isize, c: &color::Color) {
1398 if !(Point::new(x, y).inside(&self.rect)) {
1399 return;
1400 }
1401 let i = self.pix_offset(x, y);
1402 self.pix[i] = self.palette.index(c) as u8;
1403 }
1404
1405 // opaque scans the entire image and reports whether it is fully opaque.
1406 fn opaque(&self) -> bool {
1407 let mut present = [false; 256];
1408 let (mut i0, mut i1) = (0, self.rect.dx());
1409 for _y in self.rect.min.y..self.rect.max.y {
1410 for c in &self.pix[i0..i1] {
1411 present[*c as usize] = true;
1412 }
1413 i0 += self.stride;
1414 i1 += self.stride;
1415 }
1416 for (i, c) in self.palette.colors.iter().enumerate() {
1417 if !present[i] {
1418 continue;
1419 }
1420 let (_, _, _, a) = c.rgba();
1421 if a != 0xffff {
1422 return false;
1423 }
1424 }
1425 true
1426 }
1427
1428 fn stride(&self) -> usize {
1429 self.stride
1430 }
1431
1432 fn pix(&self) -> &Vec<u8> {
1433 &self.pix
1434 }
1435
1436 fn get_pix_mutable(&mut self) -> &mut Vec<u8> {
1437 &mut self.pix
1438 }
1439
1440 fn bytes_per_pixel(&self) -> usize {
1441 1
1442 }
1443}
1444
1445impl Paletted {
1446 /// new returns a new Paletted image with the given width, height and
1447 /// palette.
1448 pub fn new(r: &Rectangle, p: color::Palette) -> Self {
1449 Self {
1450 pix: vec![0; pixel_buffer_length(1, r, "Paletted")],
1451 stride: r.dx(),
1452 rect: *r,
1453 palette: p,
1454 }
1455 }
1456
1457 // fn RGBA64At(&self, x: isize, y: isize) color::RGBA64 {
1458 // if self.palette.colors.len() == 0 {
1459 // return color::RGBA64{}
1460 // }
1461 // c := color::Color(nil)
1462 // if !Point::new(x, y).inside(&self.rect) {
1463 // c = self.palette.colors[0]
1464 // } else {
1465 // i := self.pix_offset(x, y)
1466 // c = self.palette.colors[self.pix[i]]
1467 // }
1468 // r, g, b, a := c.rgba()
1469 // return color::RGBA64{
1470 // uint16(r),
1471 // uint16(g),
1472 // uint16(b),
1473 // uint16(a),
1474 // }
1475 // }
1476
1477 /// pix_offset returns the index of the first element of pix that corresponds to
1478 /// the pixel at (x, y).
1479 pub fn pix_offset(&self, x: isize, y: isize) -> usize {
1480 (y - self.rect.min.y) as usize * self.stride + (x - self.rect.min.x) as usize
1481 }
1482
1483 // fn SetRGBA64(&self, x: isize, y: isize, c color::RGBA64) {
1484 // if !Point::new(x, y).inside(&self.rect) {
1485 // return
1486 // }
1487 // let i = self.pix_offset(x, y);
1488 // self.pix[i] = u8(self.palette.Index(c))
1489 // }
1490
1491 pub fn color_index_at(&self, x: isize, y: isize) -> u8 {
1492 if !(Point::new(x, y).inside(&self.rect)) {
1493 return 0;
1494 }
1495 let i = self.pix_offset(x, y);
1496 self.pix[i]
1497 }
1498
1499 pub fn set_color_index(&mut self, x: isize, y: isize, index: u8) {
1500 if !Point::new(x, y).inside(&self.rect) {
1501 return;
1502 }
1503 let i = self.pix_offset(x, y);
1504 self.pix[i] = index;
1505 }
1506
1507 // // SubImage returns an image representing the portion of the image p visible
1508 // // through r. The returned value shares pixels with the original image.
1509 // fn SubImage(&self, r Rectangle) Image {
1510 // r = r.intersect(self.rect)
1511 // // If r1 and r2 are Rectangles, r1.intersect(r2) is not guaranteed to be inside
1512 // // either r1 or r2 if the intersection is empty. Without explicitly checking for
1513 // // this, the pix[i:] expression below can panic.
1514 // if r.Empty() {
1515 // return &Paletted{
1516 // Palette: self.palette,
1517 // }
1518 // }
1519 // let i = self.pix_offset(r.min.x, r.min.y)
1520 // return &Paletted{
1521 // pix: self.pix[i:],
1522 // stride: self.stride,
1523 // Rect: self.rect.intersect(r),
1524 // Palette: self.palette,
1525 // }
1526 // }
1527}
1528
1529/// Img is a combination of all possible image types.
1530#[derive(Debug)]
1531pub enum Img {
1532 Alpha(Alpha),
1533 Alpha16(Alpha16),
1534 Gray(Gray),
1535 Gray16(Gray16),
1536 NRGBA(NRGBA),
1537 NRGBA64(NRGBA64),
1538 Paletted(Paletted),
1539 RGBA(RGBA),
1540 RGBA64(RGBA64),
1541}
1542
1543impl Img {
1544 /// new_rgba creates a new RGBA image.
1545 pub fn new_rgba(r: &Rectangle) -> Self {
1546 Self::RGBA(RGBA::new(r))
1547 }
1548 /// new_nrgba creates a new NRGBA image.
1549 pub fn new_nrgba(r: &Rectangle) -> Self {
1550 Self::NRGBA(NRGBA::new(r))
1551 }
1552 /// new_nrgba64 creates a new NRGBA64 image.
1553 pub fn new_nrgba64(r: &Rectangle) -> Img {
1554 Img::NRGBA64(NRGBA64::new(r))
1555 }
1556 /// new_rgba64 creates a new RGBA64 image.
1557 pub fn new_rgba64(r: &Rectangle) -> Img {
1558 Img::RGBA64(RGBA64::new(r))
1559 }
1560}
1561
1562impl Image for Img {
1563 fn bytes_per_pixel(&self) -> usize {
1564 match self {
1565 Img::Paletted(img) => img.bytes_per_pixel(),
1566 Img::RGBA(img) => img.bytes_per_pixel(),
1567 Img::NRGBA(img) => img.bytes_per_pixel(),
1568 Img::RGBA64(img) => img.bytes_per_pixel(),
1569 Img::NRGBA64(img) => img.bytes_per_pixel(),
1570 Img::Alpha(img) => img.bytes_per_pixel(),
1571 Img::Alpha16(img) => img.bytes_per_pixel(),
1572 Img::Gray(img) => img.bytes_per_pixel(),
1573 Img::Gray16(img) => img.bytes_per_pixel(),
1574 }
1575 }
1576 fn stride(&self) -> usize {
1577 match self {
1578 Img::Paletted(img) => img.stride(),
1579 Img::RGBA(img) => img.stride(),
1580 Img::NRGBA(img) => img.stride(),
1581 Img::RGBA64(img) => img.stride(),
1582 Img::NRGBA64(img) => img.stride(),
1583 Img::Alpha(img) => img.stride(),
1584 Img::Alpha16(img) => img.stride(),
1585 Img::Gray(img) => img.stride(),
1586 Img::Gray16(img) => img.stride(),
1587 }
1588 }
1589 fn bounds(&self) -> &Rectangle {
1590 match self {
1591 Img::Paletted(img) => img.bounds(),
1592 Img::RGBA(img) => img.bounds(),
1593 Img::NRGBA(img) => img.bounds(),
1594 Img::RGBA64(img) => img.bounds(),
1595 Img::NRGBA64(img) => img.bounds(),
1596 Img::Alpha(img) => img.bounds(),
1597 Img::Alpha16(img) => img.bounds(),
1598 Img::Gray(img) => img.bounds(),
1599 Img::Gray16(img) => img.bounds(),
1600 }
1601 }
1602 fn pix(&self) -> &Vec<u8> {
1603 match self {
1604 Img::Paletted(img) => img.pix(),
1605 Img::RGBA(img) => img.pix(),
1606 Img::NRGBA(img) => img.pix(),
1607 Img::RGBA64(img) => img.pix(),
1608 Img::NRGBA64(img) => img.pix(),
1609 Img::Alpha(img) => img.pix(),
1610 Img::Alpha16(img) => img.pix(),
1611 Img::Gray(img) => img.pix(),
1612 Img::Gray16(img) => img.pix(),
1613 }
1614 }
1615 fn get_pix_mutable(&mut self) -> &mut Vec<u8> {
1616 match self {
1617 Img::Paletted(img) => img.get_pix_mutable(),
1618 Img::RGBA(img) => img.get_pix_mutable(),
1619 Img::NRGBA(img) => img.get_pix_mutable(),
1620 Img::RGBA64(img) => img.get_pix_mutable(),
1621 Img::NRGBA64(img) => img.get_pix_mutable(),
1622 Img::Alpha(img) => img.get_pix_mutable(),
1623 Img::Alpha16(img) => img.get_pix_mutable(),
1624 Img::Gray(img) => img.get_pix_mutable(),
1625 Img::Gray16(img) => img.get_pix_mutable(),
1626 }
1627 }
1628
1629 fn color_model(&self) -> color::Model {
1630 match self {
1631 Img::Paletted(img) => img.color_model(),
1632 Img::RGBA(img) => img.color_model(),
1633 Img::NRGBA(img) => img.color_model(),
1634 Img::RGBA64(img) => img.color_model(),
1635 Img::NRGBA64(img) => img.color_model(),
1636 Img::Alpha(img) => img.color_model(),
1637 Img::Alpha16(img) => img.color_model(),
1638 Img::Gray(img) => img.color_model(),
1639 Img::Gray16(img) => img.color_model(),
1640 }
1641 }
1642
1643 fn at(&self, x: isize, y: isize) -> color::Color {
1644 match self {
1645 Img::Paletted(img) => img.at(x, y),
1646 Img::RGBA(img) => img.at(x, y),
1647 Img::NRGBA(img) => img.at(x, y),
1648 Img::RGBA64(img) => img.at(x, y),
1649 Img::NRGBA64(img) => img.at(x, y),
1650 Img::Alpha(img) => img.at(x, y),
1651 Img::Alpha16(img) => img.at(x, y),
1652 Img::Gray(img) => img.at(x, y),
1653 Img::Gray16(img) => img.at(x, y),
1654 }
1655 }
1656
1657 fn set(&mut self, x: isize, y: isize, c: &color::Color) {
1658 match self {
1659 Img::Paletted(img) => img.set(x, y, c),
1660 Img::RGBA(img) => img.set(x, y, c),
1661 Img::NRGBA(img) => img.set(x, y, c),
1662 Img::RGBA64(img) => img.set(x, y, c),
1663 Img::NRGBA64(img) => img.set(x, y, c),
1664 Img::Alpha(img) => img.set(x, y, c),
1665 Img::Alpha16(img) => img.set(x, y, c),
1666 Img::Gray(img) => img.set(x, y, c),
1667 Img::Gray16(img) => img.set(x, y, c),
1668 }
1669 }
1670
1671 fn opaque(&self) -> bool {
1672 match self {
1673 Img::Paletted(img) => img.opaque(),
1674 Img::RGBA(img) => img.opaque(),
1675 Img::NRGBA(img) => img.opaque(),
1676 Img::RGBA64(img) => img.opaque(),
1677 Img::NRGBA64(img) => img.opaque(),
1678 Img::Alpha(img) => img.opaque(),
1679 Img::Alpha16(img) => img.opaque(),
1680 Img::Gray(img) => img.opaque(),
1681 Img::Gray16(img) => img.opaque(),
1682 }
1683 }
1684}