extern crate image;
extern crate ocl;
use ocl::enums::{
AddressingMode, FilterMode, ImageChannelDataType, ImageChannelOrder, MemObjectType,
};
use ocl::{Context, Device, Image, Kernel, Program, Queue, Sampler};
use std::path::Path;
const SAVE_IMAGES_TO_DISK: bool = false;
static BEFORE_IMAGE_FILE_NAME: &'static str = "before_example_image.png";
static AFTER_IMAGE_FILE_NAME: &'static str = "after_example_image.png";
static KERNEL_SRC: &'static str = r#"
// Unused... here for comparison purposes:
__constant sampler_t sampler_const =
CLK_NORMALIZED_COORDS_FALSE |
CLK_ADDRESS_NONE |
CLK_FILTER_NEAREST;
__kernel void increase_blue(
sampler_t sampler_host,
read_only image2d_t src_image,
write_only image2d_t dst_image)
{
int2 coord = (int2)(get_global_id(0), get_global_id(1));
float4 pixel = read_imagef(src_image, sampler_host, coord);
pixel += (float4)(0.0, 0.0, 0.5, 0.0);
write_imagef(dst_image, coord, pixel);
}
"#;
fn generate_image() -> image::ImageBuffer<image::Rgba<u8>, Vec<u8>> {
let img = image::ImageBuffer::from_fn(512, 512, |x, y| {
let near_midline = (x + y < 536) && (x + y > 488);
if near_midline {
image::Rgba([196, 50, 50, 255u8])
} else {
image::Rgba([50, 50, 50, 255u8])
}
});
img
}
fn main() {
println!("Running 'examples/image.rs::main()'...");
let mut img = generate_image();
if SAVE_IMAGES_TO_DISK {
img.save(&Path::new(BEFORE_IMAGE_FILE_NAME)).unwrap();
}
let context = Context::builder()
.devices(Device::specifier().first())
.build()
.unwrap();
let device = context.devices()[0];
let queue = Queue::new(&context, device, None).unwrap();
let program = Program::builder()
.src(KERNEL_SRC)
.devices(device)
.build(&context)
.unwrap();
let sup_img_formats = Image::<u8>::supported_formats(
&context,
ocl::flags::MEM_READ_WRITE,
MemObjectType::Image2d,
)
.unwrap();
println!("Image formats supported: {}.", sup_img_formats.len());
let dims = img.dimensions();
let src_image = Image::<u8>::builder()
.channel_order(ImageChannelOrder::Rgba)
.channel_data_type(ImageChannelDataType::UnormInt8)
.image_type(MemObjectType::Image2d)
.dims(&dims)
.flags(
ocl::flags::MEM_READ_ONLY
| ocl::flags::MEM_HOST_WRITE_ONLY
| ocl::flags::MEM_COPY_HOST_PTR,
)
.copy_host_slice(&img)
.queue(queue.clone())
.build()
.unwrap();
let dst_image = Image::<u8>::builder()
.channel_order(ImageChannelOrder::Rgba)
.channel_data_type(ImageChannelDataType::UnormInt8)
.image_type(MemObjectType::Image2d)
.dims(&dims)
.flags(
ocl::flags::MEM_WRITE_ONLY
| ocl::flags::MEM_HOST_READ_ONLY
| ocl::flags::MEM_COPY_HOST_PTR,
)
.copy_host_slice(&img)
.queue(queue.clone())
.build()
.unwrap();
let sampler = Sampler::new(&context, true, AddressingMode::None, FilterMode::Nearest).unwrap();
let kernel = Kernel::builder()
.program(&program)
.name("increase_blue")
.queue(queue.clone())
.global_work_size(&dims)
.arg_sampler(&sampler)
.arg(&src_image)
.arg(&dst_image)
.build()
.unwrap();
println!("Printing image info:");
println!("Source {}", src_image);
print!("\n");
println!("Destination {}", src_image);
print!("\n");
println!("Printing the first pixel of the image (each value is a component, RGBA): ");
println!("Pixel before: [0..16]: {:?}", &img[(0, 0)]);
println!("Attempting to blue-ify the image...");
unsafe {
kernel.enq().unwrap();
}
dst_image.read(&mut img).enq().unwrap();
println!("Pixel after: [0..16]: {:?}", &img[(0, 0)]);
if SAVE_IMAGES_TO_DISK {
img.save(&Path::new(AFTER_IMAGE_FILE_NAME)).unwrap();
println!(
"Images saved as: '{}' and '{}'.",
BEFORE_IMAGE_FILE_NAME, AFTER_IMAGE_FILE_NAME
);
} else {
println!(
"Saving images to disk disabled. \
Enable by setting 'SAVE_IMAGES_TO_DISK' to 'true'."
);
}
}