1 //!
2 //! A binding for the library `SDL2_image`
3 //!
4 //!
5 //! Note that you need to build with the
6 //! feature `image` for this module to be enabled,
7 //! like so:
8 //!
9 //! ```bash
10 //! $ cargo build --features "image"
11 //! ```
12 //!
13 //! If you want to use this with from inside your own
14 //! crate, you will need to add this in your Cargo.toml
15 //!
16 //! ```toml
17 //! [dependencies.sdl2]
18 //! version = ...
19 //! default-features = false
20 //! features = ["image"]
21 //! ```
22
23 use std::os::raw::{c_int, c_char};
24 use std::ffi::CString;
25 use std::path::Path;
26 use surface::Surface;
27 use render::{TextureCreator, Texture};
28 use rwops::RWops;
29 use version::Version;
30 use get_error;
31 use sys;
32
33 /// InitFlags are passed to init() to control which subsystem
34 /// functionality to load.
35 bitflags! {
36 pub struct InitFlag : u32 {
37 const JPG = sys::image::IMG_InitFlags_IMG_INIT_JPG as u32;
38 const PNG = sys::image::IMG_InitFlags_IMG_INIT_PNG as u32;
39 const TIF = sys::image::IMG_InitFlags_IMG_INIT_TIF as u32;
40 const WEBP = sys::image::IMG_InitFlags_IMG_INIT_WEBP as u32;
41 }
42 }
43
44 // This is used for error message for init
45 impl ::std::fmt::Display for InitFlag {
fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result46 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
47 if self.contains(InitFlag::JPG) {
48 try!(f.write_str("INIT_JPG "));
49 }
50 if self.contains(InitFlag::PNG) {
51 try!(f.write_str("INIT_PNG "));
52 }
53 if self.contains(InitFlag::TIF) {
54 try!(f.write_str("INIT_TIF "));
55 }
56 if self.contains(InitFlag::WEBP) {
57 try!(f.write_str("INIT_WEBP "));
58 }
59 Ok(())
60 }
61 }
62
63
64 /// Static method extensions for creating Surfaces
65 pub trait LoadSurface: Sized {
66 // Self is only returned here to type hint to the compiler.
67 // The syntax for type hinting in this case is not yet defined.
68 // The intended return value is Result<~Surface, String>.
from_file<P: AsRef<Path>>(filename: P) -> Result<Self, String>69 fn from_file<P: AsRef<Path>>(filename: P) -> Result<Self, String>;
from_xpm_array(xpm: *const *const i8) -> Result<Self, String>70 fn from_xpm_array(xpm: *const *const i8) -> Result<Self, String>;
71 }
72
73 /// Method extensions to Surface for saving to disk
74 pub trait SaveSurface {
save<P: AsRef<Path>>(&self, filename: P) -> Result<(), String>75 fn save<P: AsRef<Path>>(&self, filename: P) -> Result<(), String>;
save_rw(&self, dst: &mut RWops) -> Result<(), String>76 fn save_rw(&self, dst: &mut RWops) -> Result<(), String>;
77 }
78
79 impl<'a> LoadSurface for Surface<'a> {
from_file<P: AsRef<Path>>(filename: P) -> Result<Surface<'a>, String>80 fn from_file<P: AsRef<Path>>(filename: P) -> Result<Surface<'a>, String> {
81 //! Loads an SDL Surface from a file
82 unsafe {
83 let c_filename = CString::new(filename.as_ref().to_str().unwrap()).unwrap();
84 let raw = sys::image::IMG_Load(c_filename.as_ptr() as *const _);
85 if (raw as *mut ()).is_null() {
86 Err(get_error())
87 } else {
88 Ok(Surface::from_ll(raw))
89 }
90 }
91 }
92
from_xpm_array(xpm: *const *const i8) -> Result<Surface<'a>, String>93 fn from_xpm_array(xpm: *const *const i8) -> Result<Surface<'a>, String> {
94 //! Loads an SDL Surface from XPM data
95 unsafe {
96 let raw = sys::image::IMG_ReadXPMFromArray(xpm as *mut *mut c_char);
97 if (raw as *mut ()).is_null() {
98 Err(get_error())
99 } else {
100 Ok(Surface::from_ll(raw))
101 }
102 }
103 }
104 }
105
106 impl<'a> SaveSurface for Surface<'a> {
save<P: AsRef<Path>>(&self, filename: P) -> Result<(), String>107 fn save<P: AsRef<Path>>(&self, filename: P) -> Result<(), String> {
108 //! Saves an SDL Surface to a file
109 unsafe {
110 let c_filename = CString::new(filename.as_ref().to_str().unwrap()).unwrap();
111 let status = sys::image::IMG_SavePNG(self.raw(), c_filename.as_ptr() as *const _);
112 if status != 0 {
113 Err(get_error())
114 } else {
115 Ok(())
116 }
117 }
118 }
119
save_rw(&self, dst: &mut RWops) -> Result<(), String>120 fn save_rw(&self, dst: &mut RWops) -> Result<(), String> {
121 //! Saves an SDL Surface to an RWops
122 unsafe {
123 let status = sys::image::IMG_SavePNG_RW(self.raw(), dst.raw(), 0);
124
125 if status != 0 {
126 Err(get_error())
127 } else {
128 Ok(())
129 }
130 }
131 }
132 }
133
134 /// Method extensions for creating Textures from a `TextureCreator`
135 pub trait LoadTexture {
load_texture<P: AsRef<Path>>(&self, filename: P) -> Result<Texture, String>136 fn load_texture<P: AsRef<Path>>(&self, filename: P) -> Result<Texture, String>;
137 }
138
139 impl<T> LoadTexture for TextureCreator<T> {
load_texture<P: AsRef<Path>>(&self, filename: P) -> Result<Texture, String>140 fn load_texture<P: AsRef<Path>>(&self, filename: P) -> Result<Texture, String> {
141 //! Loads an SDL Texture from a file
142 unsafe {
143 let c_filename = CString::new(filename.as_ref().to_str().unwrap()).unwrap();
144 let raw = sys::image::IMG_LoadTexture(self.raw(), c_filename.as_ptr() as *const _);
145 if (raw as *mut ()).is_null() {
146 Err(get_error())
147 } else {
148 Ok(self.raw_create_texture(raw))
149 }
150 }
151 }
152 }
153
154 /// Context manager for `sdl2_image` to manage quitting. Can't do much with it but
155 /// keep it alive while you are using it.
156 pub struct Sdl2ImageContext;
157
158 impl Drop for Sdl2ImageContext {
drop(&mut self)159 fn drop(&mut self) {
160 unsafe {
161 sys::image::IMG_Quit();
162 }
163 }
164 }
165
166 /// Initializes `SDL2_image` with `InitFlags`.
167 /// If not every flag is set it returns an error
init(flags: InitFlag) -> Result<Sdl2ImageContext, String>168 pub fn init(flags: InitFlag) -> Result<Sdl2ImageContext, String> {
169 let return_flags = unsafe {
170 let used = sys::image::IMG_Init(flags.bits() as c_int);
171 InitFlag::from_bits_truncate(used as u32)
172 };
173 if !flags.intersects(return_flags) {
174 // According to docs, error message text is not always set
175 let mut error = get_error();
176 if error.is_empty() {
177 let un_init_flags = return_flags ^ flags;
178 error = format!("Could not init: {}", un_init_flags);
179 let _ = ::set_error(&error);
180 }
181 Err(error)
182 } else {
183 Ok(Sdl2ImageContext)
184 }
185 }
186
187 /// Returns the version of the dynamically linked `SDL_image` library
get_linked_version() -> Version188 pub fn get_linked_version() -> Version {
189 unsafe { Version::from_ll(*sys::image::IMG_Linked_Version()) }
190 }
191
192 #[inline]
to_surface_result<'a>(raw: *mut sys::SDL_Surface) -> Result<Surface<'a>, String>193 fn to_surface_result<'a>(raw: *mut sys::SDL_Surface) -> Result<Surface<'a>, String> {
194 if (raw as *mut ()).is_null() {
195 Err(get_error())
196 } else {
197 unsafe { Ok(Surface::from_ll(raw)) }
198 }
199 }
200
201 pub trait ImageRWops {
202 /// load as a surface. except TGA
load(&self) -> Result<Surface, String>203 fn load(&self) -> Result<Surface, String>;
204 /// load as a surface. This can load all supported image formats.
load_typed(&self, _type: &str) -> Result<Surface, String>205 fn load_typed(&self, _type: &str) -> Result<Surface, String>;
206
load_cur(&self) -> Result<Surface, String>207 fn load_cur(&self) -> Result<Surface, String>;
load_ico(&self) -> Result<Surface, String>208 fn load_ico(&self) -> Result<Surface, String>;
load_bmp(&self) -> Result<Surface, String>209 fn load_bmp(&self) -> Result<Surface, String>;
load_pnm(&self) -> Result<Surface, String>210 fn load_pnm(&self) -> Result<Surface, String>;
load_xpm(&self) -> Result<Surface, String>211 fn load_xpm(&self) -> Result<Surface, String>;
load_xcf(&self) -> Result<Surface, String>212 fn load_xcf(&self) -> Result<Surface, String>;
load_pcx(&self) -> Result<Surface, String>213 fn load_pcx(&self) -> Result<Surface, String>;
load_gif(&self) -> Result<Surface, String>214 fn load_gif(&self) -> Result<Surface, String>;
load_jpg(&self) -> Result<Surface, String>215 fn load_jpg(&self) -> Result<Surface, String>;
load_tif(&self) -> Result<Surface, String>216 fn load_tif(&self) -> Result<Surface, String>;
load_png(&self) -> Result<Surface, String>217 fn load_png(&self) -> Result<Surface, String>;
load_tga(&self) -> Result<Surface, String>218 fn load_tga(&self) -> Result<Surface, String>;
load_lbm(&self) -> Result<Surface, String>219 fn load_lbm(&self) -> Result<Surface, String>;
load_xv(&self) -> Result<Surface, String>220 fn load_xv(&self) -> Result<Surface, String>;
load_webp(&self) -> Result<Surface, String>221 fn load_webp(&self) -> Result<Surface, String>;
222
is_cur(&self) -> bool223 fn is_cur(&self) -> bool;
is_ico(&self) -> bool224 fn is_ico(&self) -> bool;
is_bmp(&self) -> bool225 fn is_bmp(&self) -> bool;
is_pnm(&self) -> bool226 fn is_pnm(&self) -> bool;
is_xpm(&self) -> bool227 fn is_xpm(&self) -> bool;
is_xcf(&self) -> bool228 fn is_xcf(&self) -> bool;
is_pcx(&self) -> bool229 fn is_pcx(&self) -> bool;
is_gif(&self) -> bool230 fn is_gif(&self) -> bool;
is_jpg(&self) -> bool231 fn is_jpg(&self) -> bool;
is_tif(&self) -> bool232 fn is_tif(&self) -> bool;
is_png(&self) -> bool233 fn is_png(&self) -> bool;
is_lbm(&self) -> bool234 fn is_lbm(&self) -> bool;
is_xv(&self) -> bool235 fn is_xv(&self) -> bool;
is_webp(&self) -> bool236 fn is_webp(&self) -> bool;
237 }
238
239 impl<'a> ImageRWops for RWops<'a> {
load(&self) -> Result<Surface, String>240 fn load(&self) -> Result<Surface, String> {
241 let raw = unsafe { sys::image::IMG_Load_RW(self.raw(), 0) };
242 to_surface_result(raw)
243 }
load_typed(&self, _type: &str) -> Result<Surface, String>244 fn load_typed(&self, _type: &str) -> Result<Surface, String> {
245 let raw = unsafe {
246 let c_type = CString::new(_type.as_bytes()).unwrap();
247 sys::image::IMG_LoadTyped_RW(self.raw(), 0, c_type.as_ptr() as *const _)
248 };
249 to_surface_result(raw)
250 }
251
load_cur(&self) -> Result<Surface, String>252 fn load_cur(&self) -> Result<Surface, String> {
253 let raw = unsafe { sys::image::IMG_LoadCUR_RW(self.raw()) };
254 to_surface_result(raw)
255 }
load_ico(&self) -> Result<Surface, String>256 fn load_ico(&self) -> Result<Surface, String> {
257 let raw = unsafe { sys::image::IMG_LoadICO_RW(self.raw()) };
258 to_surface_result(raw)
259 }
load_bmp(&self) -> Result<Surface, String>260 fn load_bmp(&self) -> Result<Surface, String> {
261 let raw = unsafe { sys::image::IMG_LoadBMP_RW(self.raw()) };
262 to_surface_result(raw)
263 }
load_pnm(&self) -> Result<Surface, String>264 fn load_pnm(&self) -> Result<Surface, String> {
265 let raw = unsafe { sys::image::IMG_LoadPNM_RW(self.raw()) };
266 to_surface_result(raw)
267 }
load_xpm(&self) -> Result<Surface, String>268 fn load_xpm(&self) -> Result<Surface, String> {
269 let raw = unsafe { sys::image::IMG_LoadXPM_RW(self.raw()) };
270 to_surface_result(raw)
271 }
load_xcf(&self) -> Result<Surface, String>272 fn load_xcf(&self) -> Result<Surface, String> {
273 let raw = unsafe { sys::image::IMG_LoadXCF_RW(self.raw()) };
274 to_surface_result(raw)
275 }
load_pcx(&self) -> Result<Surface, String>276 fn load_pcx(&self) -> Result<Surface, String> {
277 let raw = unsafe { sys::image::IMG_LoadPCX_RW(self.raw()) };
278 to_surface_result(raw)
279 }
load_gif(&self) -> Result<Surface, String>280 fn load_gif(&self) -> Result<Surface, String> {
281 let raw = unsafe { sys::image::IMG_LoadGIF_RW(self.raw()) };
282 to_surface_result(raw)
283 }
load_jpg(&self) -> Result<Surface, String>284 fn load_jpg(&self) -> Result<Surface, String> {
285 let raw = unsafe { sys::image::IMG_LoadJPG_RW(self.raw()) };
286 to_surface_result(raw)
287 }
load_tif(&self) -> Result<Surface, String>288 fn load_tif(&self) -> Result<Surface, String> {
289 let raw = unsafe { sys::image::IMG_LoadTIF_RW(self.raw()) };
290 to_surface_result(raw)
291 }
load_png(&self) -> Result<Surface, String>292 fn load_png(&self) -> Result<Surface, String> {
293 let raw = unsafe { sys::image::IMG_LoadPNG_RW(self.raw()) };
294 to_surface_result(raw)
295 }
load_tga(&self) -> Result<Surface, String>296 fn load_tga(&self) -> Result<Surface, String> {
297 let raw = unsafe { sys::image::IMG_LoadTGA_RW(self.raw()) };
298 to_surface_result(raw)
299 }
load_lbm(&self) -> Result<Surface, String>300 fn load_lbm(&self) -> Result<Surface, String> {
301 let raw = unsafe { sys::image::IMG_LoadLBM_RW(self.raw()) };
302 to_surface_result(raw)
303 }
load_xv(&self) -> Result<Surface, String>304 fn load_xv(&self) -> Result<Surface, String> {
305 let raw = unsafe { sys::image::IMG_LoadXV_RW(self.raw()) };
306 to_surface_result(raw)
307 }
load_webp(&self) -> Result<Surface, String>308 fn load_webp(&self) -> Result<Surface, String> {
309 let raw = unsafe { sys::image::IMG_LoadWEBP_RW(self.raw()) };
310 to_surface_result(raw)
311 }
312
is_cur(&self) -> bool313 fn is_cur(&self) -> bool {
314 unsafe { sys::image::IMG_isCUR(self.raw()) == 1 }
315 }
is_ico(&self) -> bool316 fn is_ico(&self) -> bool {
317 unsafe { sys::image::IMG_isICO(self.raw()) == 1 }
318 }
is_bmp(&self) -> bool319 fn is_bmp(&self) -> bool {
320 unsafe { sys::image::IMG_isBMP(self.raw()) == 1 }
321 }
is_pnm(&self) -> bool322 fn is_pnm(&self) -> bool {
323 unsafe { sys::image::IMG_isPNM(self.raw()) == 1 }
324 }
is_xpm(&self) -> bool325 fn is_xpm(&self) -> bool {
326 unsafe { sys::image::IMG_isXPM(self.raw()) == 1 }
327 }
is_xcf(&self) -> bool328 fn is_xcf(&self) -> bool {
329 unsafe { sys::image::IMG_isXCF(self.raw()) == 1 }
330 }
is_pcx(&self) -> bool331 fn is_pcx(&self) -> bool {
332 unsafe { sys::image::IMG_isPCX(self.raw()) == 1 }
333 }
is_gif(&self) -> bool334 fn is_gif(&self) -> bool {
335 unsafe { sys::image::IMG_isGIF(self.raw()) == 1 }
336 }
is_jpg(&self) -> bool337 fn is_jpg(&self) -> bool {
338 unsafe { sys::image::IMG_isJPG(self.raw()) == 1 }
339 }
is_tif(&self) -> bool340 fn is_tif(&self) -> bool {
341 unsafe { sys::image::IMG_isTIF(self.raw()) == 1 }
342 }
is_png(&self) -> bool343 fn is_png(&self) -> bool {
344 unsafe { sys::image::IMG_isPNG(self.raw()) == 1 }
345 }
is_lbm(&self) -> bool346 fn is_lbm(&self) -> bool {
347 unsafe { sys::image::IMG_isLBM(self.raw()) == 1 }
348 }
is_xv(&self) -> bool349 fn is_xv(&self) -> bool {
350 unsafe { sys::image::IMG_isXV(self.raw()) == 1 }
351 }
is_webp(&self) -> bool352 fn is_webp(&self) -> bool {
353 unsafe { sys::image::IMG_isWEBP(self.raw()) == 1 }
354 }
355 }
356