core_graphics/
image.rs

1use std::ptr;
2
3use crate::base::CGFloat;
4use crate::color_space::CGColorSpace;
5use crate::data_provider::{CGDataProvider, CGDataProviderRef};
6use crate::geometry::CGRect;
7use core_foundation::base::{CFRetain, CFTypeID};
8use core_foundation::data::CFData;
9use foreign_types::{foreign_type, ForeignType, ForeignTypeRef};
10
11#[repr(C)]
12pub enum CGImageAlphaInfo {
13    CGImageAlphaNone,               /* For example, RGB. */
14    CGImageAlphaPremultipliedLast,  /* For example, premultiplied RGBA */
15    CGImageAlphaPremultipliedFirst, /* For example, premultiplied ARGB */
16    CGImageAlphaLast,               /* For example, non-premultiplied RGBA */
17    CGImageAlphaFirst,              /* For example, non-premultiplied ARGB */
18    CGImageAlphaNoneSkipLast,       /* For example, RBGX. */
19    CGImageAlphaNoneSkipFirst,      /* For example, XRBG. */
20    CGImageAlphaOnly,               /* No color data, alpha data only */
21}
22
23#[repr(C)]
24pub enum CGImageByteOrderInfo {
25    CGImageByteOrderMask = 0x7000,
26    CGImageByteOrder16Little = 1 << 12,
27    CGImageByteOrder32Little = 2 << 12,
28    CGImageByteOrder16Big = 3 << 12,
29    CGImageByteOrder32Big = 4 << 12,
30}
31
32foreign_type! {
33    #[doc(hidden)]
34    pub unsafe type CGImage {
35        type CType = crate::sys::CGImage;
36        fn drop = CGImageRelease;
37        fn clone = |p| CFRetain(p as *const _) as *mut _;
38    }
39}
40
41impl CGImage {
42    pub fn new(
43        width: usize,
44        height: usize,
45        bits_per_component: usize,
46        bits_per_pixel: usize,
47        bytes_per_row: usize,
48        colorspace: &CGColorSpace,
49        bitmap_info: u32,
50        provider: &CGDataProvider,
51        should_interpolate: bool,
52        rendering_intent: u32,
53    ) -> Self {
54        unsafe {
55            let result = CGImageCreate(
56                width,
57                height,
58                bits_per_component,
59                bits_per_pixel,
60                bytes_per_row,
61                colorspace.as_ptr(),
62                bitmap_info,
63                provider.as_ptr(),
64                ptr::null_mut(),
65                should_interpolate,
66                rendering_intent,
67            );
68            assert!(!result.is_null());
69            Self::from_ptr(result)
70        }
71    }
72
73    pub fn type_id() -> CFTypeID {
74        unsafe { CGImageGetTypeID() }
75    }
76}
77
78impl CGImageRef {
79    pub fn width(&self) -> usize {
80        unsafe { CGImageGetWidth(self.as_ptr()) }
81    }
82
83    pub fn height(&self) -> usize {
84        unsafe { CGImageGetHeight(self.as_ptr()) }
85    }
86
87    pub fn bits_per_component(&self) -> usize {
88        unsafe { CGImageGetBitsPerComponent(self.as_ptr()) }
89    }
90
91    pub fn bits_per_pixel(&self) -> usize {
92        unsafe { CGImageGetBitsPerPixel(self.as_ptr()) }
93    }
94
95    pub fn bytes_per_row(&self) -> usize {
96        unsafe { CGImageGetBytesPerRow(self.as_ptr()) }
97    }
98
99    pub fn color_space(&self) -> CGColorSpace {
100        unsafe {
101            let cs = CGImageGetColorSpace(self.as_ptr());
102            CFRetain(cs as *mut _);
103            CGColorSpace::from_ptr(cs)
104        }
105    }
106
107    /// Returns the raw image bytes wrapped in `CFData`. Note, the returned `CFData` owns the
108    /// underlying buffer.
109    pub fn data(&self) -> CFData {
110        let data_provider =
111            unsafe { CGDataProviderRef::from_ptr(CGImageGetDataProvider(self.as_ptr())) };
112        data_provider.copy_data()
113    }
114
115    /// Returns a cropped image. If the `rect` specifies a rectangle which lies outside of the
116    /// image bounds, the `None` is returned.
117    pub fn cropped(&self, rect: CGRect) -> Option<CGImage> {
118        let image_ptr = unsafe { CGImageCreateWithImageInRect(self.as_ptr(), rect) };
119        if !image_ptr.is_null() {
120            Some(unsafe { CGImage::from_ptr(image_ptr) })
121        } else {
122            None
123        }
124    }
125}
126
127#[cfg_attr(feature = "link", link(name = "CoreGraphics", kind = "framework"))]
128extern "C" {
129    fn CGImageGetTypeID() -> CFTypeID;
130    fn CGImageGetWidth(image: crate::sys::CGImageRef) -> usize;
131    fn CGImageGetHeight(image: crate::sys::CGImageRef) -> usize;
132    fn CGImageGetBitsPerComponent(image: crate::sys::CGImageRef) -> usize;
133    fn CGImageGetBitsPerPixel(image: crate::sys::CGImageRef) -> usize;
134    fn CGImageGetBytesPerRow(image: crate::sys::CGImageRef) -> usize;
135    fn CGImageGetColorSpace(image: crate::sys::CGImageRef) -> crate::sys::CGColorSpaceRef;
136    fn CGImageGetDataProvider(image: crate::sys::CGImageRef) -> crate::sys::CGDataProviderRef;
137    fn CGImageRelease(image: crate::sys::CGImageRef);
138    fn CGImageCreate(
139        width: usize,
140        height: usize,
141        bitsPerComponent: usize,
142        bitsPerPixel: usize,
143        bytesPerRow: usize,
144        space: crate::sys::CGColorSpaceRef,
145        bitmapInfo: u32,
146        provider: crate::sys::CGDataProviderRef,
147        decode: *const CGFloat,
148        shouldInterpolate: bool,
149        intent: u32,
150    ) -> crate::sys::CGImageRef;
151    fn CGImageCreateWithImageInRect(
152        image: crate::sys::CGImageRef,
153        rect: CGRect,
154    ) -> crate::sys::CGImageRef;
155
156    //fn CGImageGetAlphaInfo(image: ::sys::CGImageRef) -> CGImageAlphaInfo;
157    //fn CGImageCreateCopyWithColorSpace(image: ::sys::CGImageRef, space: ::sys::CGColorSpaceRef) -> ::sys::CGImageRef
158}