extern crate rand;
use num::FromPrimitive;
use sys::pixels as ll;
use SdlResult;
use get_error;
pub struct Palette {
raw: *mut ll::SDL_Palette
}
impl_raw_accessors!((Palette, *mut ll::SDL_Palette));
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum Color {
RGB(u8, u8, u8),
RGBA(u8, u8, u8, u8)
}
impl Color {
pub fn to_u32(&self, format: &PixelFormat) -> u32 {
match self {
&Color::RGB(r, g, b) => {
unsafe { ll::SDL_MapRGB(format.raw, r, g, b) }
}
&Color::RGBA(r, g, b, a) => {
unsafe { ll::SDL_MapRGBA(format.raw, r, g, b, a) }
}
}
}
pub fn from_u32(format: &PixelFormat, pixel: u32) -> Color {
let (mut r, mut g, mut b, mut a) = (0, 0, 0, 0);
unsafe {
ll::SDL_GetRGBA(pixel, format.raw, &mut r, &mut g, &mut b, &mut a)
};
Color::RGBA(r, g, b, a)
}
pub fn rgb(&self) -> (u8, u8, u8) {
match self {
&Color::RGB(r, g, b) => (r, g, b),
&Color::RGBA(r, g, b, _) => (r, g, b)
}
}
}
impl rand::Rand for Color {
fn rand<R: rand::Rng>(rng: &mut R) -> Color {
if rng.gen() { Color::RGBA(rng.gen(), rng.gen(), rng.gen(), rng.gen()) }
else { Color::RGB(rng.gen(), rng.gen(), rng.gen()) }
}
}
pub struct PixelMasks {
pub bpp: u8,
pub rmask: u32,
pub gmask: u32,
pub bmask: u32,
pub amask: u32
}
pub struct PixelFormat {
raw: *mut ll::SDL_PixelFormat
}
impl_raw_accessors!((PixelFormat, *mut ll::SDL_PixelFormat));
impl_raw_constructor!((PixelFormat, PixelFormat (raw: *mut ll::SDL_PixelFormat)));
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum PixelFormatEnum {
Unknown = ll::SDL_PIXELFORMAT_UNKNOWN as isize,
Index1LSB = ll::SDL_PIXELFORMAT_INDEX1LSB as isize,
Index1MSB = ll::SDL_PIXELFORMAT_INDEX1MSB as isize,
Index4LSB = ll::SDL_PIXELFORMAT_INDEX4LSB as isize,
Index4MSB = ll::SDL_PIXELFORMAT_INDEX4MSB as isize,
Index8 = ll::SDL_PIXELFORMAT_INDEX8 as isize,
RGB332 = ll::SDL_PIXELFORMAT_RGB332 as isize,
RGB444 = ll::SDL_PIXELFORMAT_RGB444 as isize,
RGB555 = ll::SDL_PIXELFORMAT_RGB555 as isize,
BGR555 = ll::SDL_PIXELFORMAT_BGR555 as isize,
ARGB4444 = ll::SDL_PIXELFORMAT_ARGB4444 as isize,
RGBA4444 = ll::SDL_PIXELFORMAT_RGBA4444 as isize,
ABGR4444 = ll::SDL_PIXELFORMAT_ABGR4444 as isize,
BGRA4444 = ll::SDL_PIXELFORMAT_BGRA4444 as isize,
ARGB1555 = ll::SDL_PIXELFORMAT_ARGB1555 as isize,
RGBA5551 = ll::SDL_PIXELFORMAT_RGBA5551 as isize,
ABGR1555 = ll::SDL_PIXELFORMAT_ABGR1555 as isize,
BGRA5551 = ll::SDL_PIXELFORMAT_BGRA5551 as isize,
RGB565 = ll::SDL_PIXELFORMAT_RGB565 as isize,
BGR565 = ll::SDL_PIXELFORMAT_BGR565 as isize,
RGB24 = ll::SDL_PIXELFORMAT_RGB24 as isize,
BGR24 = ll::SDL_PIXELFORMAT_BGR24 as isize,
RGB888 = ll::SDL_PIXELFORMAT_RGB888 as isize,
RGBX8888 = ll::SDL_PIXELFORMAT_RGBX8888 as isize,
BGR888 = ll::SDL_PIXELFORMAT_BGR888 as isize,
BGRX8888 = ll::SDL_PIXELFORMAT_BGRX8888 as isize,
ARGB8888 = ll::SDL_PIXELFORMAT_ARGB8888 as isize,
RGBA8888 = ll::SDL_PIXELFORMAT_RGBA8888 as isize,
ABGR8888 = ll::SDL_PIXELFORMAT_ABGR8888 as isize,
BGRA8888 = ll::SDL_PIXELFORMAT_BGRA8888 as isize,
ARGB2101010 = ll::SDL_PIXELFORMAT_ARGB2101010 as isize,
YV12 = ll::SDL_PIXELFORMAT_YV12 as isize,
IYUV = ll::SDL_PIXELFORMAT_IYUV as isize,
YUY2 = ll::SDL_PIXELFORMAT_YUY2 as isize,
UYVY = ll::SDL_PIXELFORMAT_UYVY as isize,
YVYU = ll::SDL_PIXELFORMAT_YVYU as isize
}
impl PixelFormatEnum {
pub fn from_masks(masks: PixelMasks) -> PixelFormatEnum {
unsafe {
let format = ll::SDL_MasksToPixelFormatEnum(masks.bpp as i32, masks.rmask, masks.gmask, masks.bmask, masks.amask);
PixelFormatEnum::from_u64(format as u64).unwrap()
}
}
pub fn into_masks(self) -> SdlResult<PixelMasks> {
let format: u32 = self as u32;
let mut bpp = 0;
let mut rmask = 0;
let mut gmask = 0;
let mut bmask = 0;
let mut amask = 0;
let result = unsafe {
ll::SDL_PixelFormatEnumToMasks(format, &mut bpp, &mut rmask, &mut gmask, &mut bmask, &mut amask)
};
if result == 0 {
Err(get_error())
} else {
Ok(PixelMasks {
bpp: bpp as u8,
rmask: rmask,
gmask: gmask,
bmask: bmask,
amask: amask
})
}
}
pub fn byte_size_from_pitch_and_height(&self, pitch: usize, height: usize) -> usize {
match *self {
PixelFormatEnum::YV12 | PixelFormatEnum::IYUV => {
pitch * height + 2 * (pitch / 2 * height / 2)
},
_ => pitch * height
}
}
pub fn byte_size_of_pixels(&self, num_of_pixels: usize) -> usize {
match *self {
PixelFormatEnum::RGB332
=> num_of_pixels * 1,
PixelFormatEnum::RGB444 | PixelFormatEnum::RGB555 |
PixelFormatEnum::BGR555 | PixelFormatEnum::ARGB4444 |
PixelFormatEnum::RGBA4444 | PixelFormatEnum::ABGR4444 |
PixelFormatEnum::BGRA4444 | PixelFormatEnum::ARGB1555 |
PixelFormatEnum::RGBA5551 | PixelFormatEnum::ABGR1555 |
PixelFormatEnum::BGRA5551 | PixelFormatEnum::RGB565 |
PixelFormatEnum::BGR565
=> num_of_pixels * 2,
PixelFormatEnum::RGB24 | PixelFormatEnum::BGR24
=> num_of_pixels * 3,
PixelFormatEnum::RGB888 | PixelFormatEnum::RGBX8888 |
PixelFormatEnum::BGR888 | PixelFormatEnum::BGRX8888 |
PixelFormatEnum::ARGB8888 | PixelFormatEnum::RGBA8888 |
PixelFormatEnum::ABGR8888 | PixelFormatEnum::BGRA8888 |
PixelFormatEnum::ARGB2101010
=> num_of_pixels * 4,
PixelFormatEnum::YV12 | PixelFormatEnum::IYUV
=> num_of_pixels / 2 * 3,
PixelFormatEnum::YUY2 | PixelFormatEnum::UYVY |
PixelFormatEnum::YVYU
=> num_of_pixels * 2,
PixelFormatEnum::Index8
=> num_of_pixels * 1,
PixelFormatEnum::Unknown | PixelFormatEnum::Index1LSB |
PixelFormatEnum::Index1MSB | PixelFormatEnum::Index4LSB |
PixelFormatEnum::Index4MSB
=> panic!("not supported format: {:?}", *self),
}
}
pub fn byte_size_per_pixel(&self) -> usize {
match *self {
PixelFormatEnum::RGB332
=> 1,
PixelFormatEnum::RGB444 | PixelFormatEnum::RGB555 |
PixelFormatEnum::BGR555 | PixelFormatEnum::ARGB4444 |
PixelFormatEnum::RGBA4444 | PixelFormatEnum::ABGR4444 |
PixelFormatEnum::BGRA4444 | PixelFormatEnum::ARGB1555 |
PixelFormatEnum::RGBA5551 | PixelFormatEnum::ABGR1555 |
PixelFormatEnum::BGRA5551 | PixelFormatEnum::RGB565 |
PixelFormatEnum::BGR565
=> 2,
PixelFormatEnum::RGB24 | PixelFormatEnum::BGR24
=> 3,
PixelFormatEnum::RGB888 | PixelFormatEnum::RGBX8888 |
PixelFormatEnum::BGR888 | PixelFormatEnum::BGRX8888 |
PixelFormatEnum::ARGB8888 | PixelFormatEnum::RGBA8888 |
PixelFormatEnum::ABGR8888 | PixelFormatEnum::BGRA8888 |
PixelFormatEnum::ARGB2101010
=> 4,
PixelFormatEnum::YV12 | PixelFormatEnum::IYUV
=> 2,
PixelFormatEnum::YUY2 | PixelFormatEnum::UYVY |
PixelFormatEnum::YVYU
=> 2,
PixelFormatEnum::Index8
=> 1,
PixelFormatEnum::Unknown | PixelFormatEnum::Index1LSB |
PixelFormatEnum::Index1MSB | PixelFormatEnum::Index4LSB |
PixelFormatEnum::Index4MSB
=> panic!("not supported format: {:?}", *self),
}
}
}
impl FromPrimitive for PixelFormatEnum {
fn from_i64(n: i64) -> Option<PixelFormatEnum> {
use self::PixelFormatEnum::*;
Some( match n as ll::SDL_PixelFormatEnum {
ll::SDL_PIXELFORMAT_UNKNOWN => Unknown,
ll::SDL_PIXELFORMAT_INDEX1LSB => Index1LSB,
ll::SDL_PIXELFORMAT_INDEX1MSB => Index1MSB,
ll::SDL_PIXELFORMAT_INDEX4LSB => Index4LSB,
ll::SDL_PIXELFORMAT_INDEX4MSB => Index4MSB,
ll::SDL_PIXELFORMAT_INDEX8 => Index8,
ll::SDL_PIXELFORMAT_RGB332 => RGB332,
ll::SDL_PIXELFORMAT_RGB444 => RGB444,
ll::SDL_PIXELFORMAT_RGB555 => RGB555,
ll::SDL_PIXELFORMAT_BGR555 => BGR555,
ll::SDL_PIXELFORMAT_ARGB4444 => ARGB4444,
ll::SDL_PIXELFORMAT_RGBA4444 => RGBA4444,
ll::SDL_PIXELFORMAT_ABGR4444 => ABGR4444,
ll::SDL_PIXELFORMAT_BGRA4444 => BGRA4444,
ll::SDL_PIXELFORMAT_ARGB1555 => ARGB1555,
ll::SDL_PIXELFORMAT_RGBA5551 => RGBA5551,
ll::SDL_PIXELFORMAT_ABGR1555 => ABGR1555,
ll::SDL_PIXELFORMAT_BGRA5551 => BGRA5551,
ll::SDL_PIXELFORMAT_RGB565 => RGB565,
ll::SDL_PIXELFORMAT_BGR565 => BGR565,
ll::SDL_PIXELFORMAT_RGB24 => RGB24,
ll::SDL_PIXELFORMAT_BGR24 => BGR24,
ll::SDL_PIXELFORMAT_RGB888 => RGB888,
ll::SDL_PIXELFORMAT_RGBX8888 => RGBX8888,
ll::SDL_PIXELFORMAT_BGR888 => BGR888,
ll::SDL_PIXELFORMAT_BGRX8888 => BGRX8888,
ll::SDL_PIXELFORMAT_ARGB8888 => ARGB8888,
ll::SDL_PIXELFORMAT_RGBA8888 => RGBA8888,
ll::SDL_PIXELFORMAT_ABGR8888 => ABGR8888,
ll::SDL_PIXELFORMAT_BGRA8888 => BGRA8888,
ll::SDL_PIXELFORMAT_ARGB2101010 => ARGB2101010,
ll::SDL_PIXELFORMAT_YV12 => YV12,
ll::SDL_PIXELFORMAT_IYUV => IYUV,
ll::SDL_PIXELFORMAT_YUY2 => YUY2,
ll::SDL_PIXELFORMAT_UYVY => UYVY,
ll::SDL_PIXELFORMAT_YVYU => YVYU,
_ => return None,
})
}
fn from_u64(n: u64) -> Option<PixelFormatEnum> { FromPrimitive::from_i64(n as i64) }
}