1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
// Aldaron's Format Interface
// Copyright (c) 2017 Plop Grizzly, Jeron Lau <jeron.lau@plopgrizzly.com>
// Licensed under the MIT LICENSE
//
// src/graphic.rs

use ami::Vec;

/// The errors that can be returned if `decode()` fails when loading graphics.
#[derive(Debug)]
pub enum GraphicDecodeErr {
	/// Not correct format. (bad header)
	IncorrectFormat,
	/// Dimensions are not numbers
	BadNum,
	/// Not yet implemented
	GrayscaleNYI,
	/// Not yet implemented
	IndexedNYI,
	/// Not yet implemented
	AGrayscaleNYI,
	/// Bits NYI
	BitsNYI,
}

impl ::core::fmt::Display for GraphicDecodeErr {
	fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
		write!(f, "Couldn't parse PNG because: {}", match *self {
			GraphicDecodeErr::IncorrectFormat => "Bad header",
			GraphicDecodeErr::BadNum => "Dimensions aren't numbers",
			GraphicDecodeErr::GrayscaleNYI => "NYI: Grayscale",
			GraphicDecodeErr::IndexedNYI => "NYI: Indexed",
			GraphicDecodeErr::AGrayscaleNYI => "NYI: AGrayscale",
			GraphicDecodeErr::BitsNYI => "NYI: bad bits",
		})
	}
}

/// Builder for `Graphic`
pub struct GraphicBuilder;

impl GraphicBuilder {
	/// Create a new `GraphicBuilder`
	pub fn new() -> GraphicBuilder {
		GraphicBuilder
	}

	/// Create an RGBA graphic.
	pub fn rgba(self, w: u32, h: u32, data: Vec<u32>) -> Graphic {
		let bgra = false;
		assert!(data.len() as u32 / w == h
			&& data.len() as u32 % w == 0);
		Graphic { bgra, w, h, data }
	}

	/// Create a BGRA graphic.
	pub fn bgra(self, w: u32, h: u32, data: Vec<u32>) -> Graphic {
		let bgra = true;
		assert!(data.len() as u32 / w == h
			&& data.len() as u32 % w == 0);
		Graphic { bgra, w, h, data }
	}
}

/// A graphic (image)
pub struct Graphic {
	bgra: bool,
	w: u32,
	h: u32,
	data: Vec<u32>,
}

impl Graphic {
	/// Convert `self` into a BGRA graphic.
	pub fn bgra(&mut self) {
		if !self.bgra {
			for i in self.data.as_mut_slice() {
				*i = i.swap_bytes().rotate_right(8);
			}
		}

		self.bgra = true;
	}

	/// Convert `self` into a RGBA graphic.
	pub fn rgba(&mut self) {
		if self.bgra {
			for i in self.data.as_mut_slice() {
				*i = i.swap_bytes().rotate_right(8);
			}
		}

		self.bgra = false;
	}

	/// Get the graphic as a slice `(w, h, [pixels])`
	pub fn as_slice(&self) -> (u32, u32, &[u32]) {
		(self.w, self.h, self.data.as_slice())
	}
}