extern crate image;
use image::{GenericImage, GenericImageView};
use std::f64;
extern crate imageproc;
use imageproc::drawing::draw_filled_rect_mut;
use imageproc::rect::Rect;
extern crate rusttype;
use crate::{PhotonImage, Rgb};
use crate::helpers;
use wasm_bindgen::prelude::*;
use image::{Rgba};
#[wasm_bindgen]
pub fn offset(photon_image: &mut PhotonImage, channel_index: usize, offset: u32) {
if channel_index > 2 {
panic!("Invalid channel index passed. Channel1 must be equal to 0, 1, or 2.");
}
let mut img = helpers::dyn_image_from_raw(&photon_image);
let (width, height) = img.dimensions();
for x in 0..width - 10 {
for y in 0..height - 10 {
let mut px = img.get_pixel(x, y);
if x + offset < width - 1 && y + offset < height - 1 {
let offset_px = img.get_pixel(x + offset, y + offset);
px.data[channel_index] = offset_px.data[channel_index];
}
img.put_pixel(x, y, px);
}
}
let raw_pixels = img.raw_pixels();
photon_image.raw_pixels = raw_pixels;
}
#[wasm_bindgen]
pub fn offset_red(img: &mut PhotonImage, offset_amt: u32) {
offset(img, 0, offset_amt)
}
#[wasm_bindgen]
pub fn offset_green(img: &mut PhotonImage, offset_amt: u32) {
offset(img, 1, offset_amt)
}
#[wasm_bindgen]
pub fn offset_blue(img: &mut PhotonImage, offset_amt: u32) {
offset(img, 2, offset_amt)
}
#[wasm_bindgen]
pub fn multiple_offsets(mut photon_image: &mut PhotonImage, offset: u32, channel_index: usize, channel_index2: usize) {
if channel_index > 2 {
panic!("Invalid channel index passed. Channel1 must be equal to 0, 1, or 2.");
}
if channel_index2 > 2 {
panic!("Invalid channel index passed. Channel2 must be equal to 0, 1, or 2.");
}
let mut img = helpers::dyn_image_from_raw(&photon_image);
let (width, height) = img.dimensions();
for x in 0..width {
for y in 0..height {
let mut px = img.get_pixel(x, y);
if x + offset < width - 1 && y + offset < height - 1 {
let offset_px = img.get_pixel(x + offset, y);
px.data[channel_index] = offset_px.data[channel_index];
}
if x as i32 - offset as i32 > 0 && y as i32 - offset as i32 > 0 {
let offset_px2 = img.get_pixel(x - offset, y );
px.data[channel_index2] = offset_px2.data[channel_index2];
}
img.put_pixel(x, y, px);
}
}
let raw_pixels = img.raw_pixels();
photon_image.raw_pixels = raw_pixels;
}
pub fn halftone(mut photon_image: PhotonImage) {
let mut img = helpers::dyn_image_from_raw(&photon_image);
let (width, height) = img.dimensions();
for x in (0..width).step_by(2 as usize) {
for y in (0..height).step_by(2 as usize) {
let mut px1 = img.get_pixel(x, y);
let mut px2 = img.get_pixel(x, y + 1);
let mut px3 = img.get_pixel(x + 1, y);
let mut px4 = img.get_pixel(x + 1, y + 1);
let gray1 = (px1[0] as f64 * 0.299) + (px1[1] as f64 * 0.587) + (px1[2] as f64 * 0.114);
let gray2 = (px2[0] as f64 * 0.299) + (px2[1] as f64 * 0.587) + (px2[2] as f64 * 0.114);
let gray3 = (px3[0] as f64 * 0.299) + (px3[1] as f64 * 0.587) + (px3[2] as f64 * 0.114);
let gray4 = (px4[0] as f64 * 0.299) + (px4[1] as f64 * 0.587) + (px4[2] as f64 * 0.114);
let sat = (gray1 + gray2 + gray3 + gray4) / 4.0;
if sat > 200.0 {
px1.data[0] = 255;
px1.data[1] = 255;
px1.data[2] = 255;
px2.data[0] = 255;
px2.data[1] = 255;
px2.data[2] = 255;
px3.data[0] = 255;
px3.data[1] = 255;
px3.data[2] = 255;
px4.data[0] = 255;
px4.data[1] = 255;
px4.data[2] = 255;
}
else if sat > 159.0 {
px1.data[0] = 255;
px1.data[1] = 255;
px1.data[2] = 255;
px2.data[0] = 0;
px2.data[1] = 0;
px2.data[2] = 0;
px3.data[0] = 255;
px3.data[1] = 255;
px3.data[2] = 255;
px4.data[0] = 255;
px4.data[1] = 255;
px4.data[2] = 255;
}
else if sat > 95.0 {
px1.data[0] = 255;
px1.data[1] = 255;
px1.data[2] = 255;
px2.data[0] = 0;
px2.data[1] = 0;
px2.data[2] = 0;
px3.data[0] = 0;
px3.data[1] = 0;
px3.data[2] = 0;
px4.data[0] = 255;
px4.data[1] = 255;
px4.data[2] = 255;
}
else if sat > 32.0 {
px1.data[0] = 0;
px1.data[1] = 0;
px1.data[2] = 0;
px2.data[0] = 255;
px2.data[0] = 255;
px2.data[0] = 255;
px3.data[0] = 0;
px3.data[1] = 0;
px3.data[2] = 0;
px4.data[0] = 0;
px4.data[1] = 0;
px4.data[2] = 0;
}
else {
px1.data[0] = 0;
px1.data[1] = 0;
px1.data[2] = 0;
px2.data[0] = 0;
px2.data[1] = 0;
px2.data[2] = 0;
px3.data[0] = 0;
px3.data[1] = 0;
px3.data[2] = 0;
px4.data[0] = 0;
px4.data[1] = 0;
px4.data[2] = 0;
}
img.put_pixel(x, y, px1);
}
}
let raw_pixels = img.raw_pixels();
photon_image.raw_pixels = raw_pixels;
}
#[wasm_bindgen]
pub fn primary(mut photon_image: &mut PhotonImage) {
let mut img = helpers::dyn_image_from_raw(&photon_image);
let (width, height) = img.dimensions();
for x in 0..width{
for y in 0..height {
let mut px = img.get_pixel(x, y);
let mut r_val = px.data[0];
let mut g_val = px.data[1];
let mut b_val = px.data[2];
if r_val > 128 {
r_val = 255;
}
else {
r_val = 0;
}
if g_val > 128 {
g_val = 255;
}
else {
g_val = 0;
}
if b_val > 128 {
g_val = 255;
}
else {
b_val = 0;
}
px.data[0] = r_val;
px.data[1] = g_val;
px.data[2] = b_val;
img.put_pixel(x, y, px);
}
}
let raw_pixels = img.raw_pixels();
photon_image.raw_pixels = raw_pixels;
}
#[wasm_bindgen]
pub fn colorize(mut photon_image: &mut PhotonImage) {
let mut img = helpers::dyn_image_from_raw(&photon_image);
let threshold = 220;
let (width, height) = img.dimensions();
for x in 0..width {
for y in 0..height {
let mut px = img.get_pixel(x, y);
let px_as_rgb = Rgb{r: px.data[0], g: px.data[1], b: px.data[2]};
let baseline_color = Rgb{r: 0, g: 255, b: 255};
let square_distance = crate::helpers::square_distance(baseline_color, px_as_rgb);
let mut r = px.data[0] as f32;
let mut g = px.data[1] as f32;
let mut b = px.data[2] as f32;
if square_distance < i32::pow(threshold, 2) {
r = r * 0.5;
g = g * 1.25;
b = b * 0.5;
}
px.data[0] = r as u8;
px.data[1] = g as u8;
px.data[2] = b as u8;
img.put_pixel(x, y, px);
}
}
let raw_pixels = img.raw_pixels();
photon_image.raw_pixels = raw_pixels;
}
#[wasm_bindgen]
pub fn solarize(mut photon_image: &mut PhotonImage) {
let mut img = helpers::dyn_image_from_raw(&photon_image);
let (width, height) = img.dimensions();
for x in 0..width {
for y in 0..height {
let mut px = img.get_pixel(x, y);
if 200 as i32 - px.data[0] as i32 > 0 {
px.data[0] = 200 - px.data[0];
}
img.put_pixel(x, y, px);
}
}
let raw_pixels = img.raw_pixels();
photon_image.raw_pixels = raw_pixels;
}
#[wasm_bindgen]
pub fn inc_brightness(mut photon_image: &mut PhotonImage, brightness: u8) {
let mut img = helpers::dyn_image_from_raw(&photon_image);
let (width, height) = img.dimensions();
for x in 0..width {
for y in 0..height {
let mut px = img.get_pixel(x, y);
if px.data[0] <= 255 - brightness {
px.data[0] += brightness;
}
else {
px.data[0] = 255;
}
if px.data[1] <= 255 - brightness {
px.data[1] += brightness;
}
else {
px.data[1] = 255
}
if px.data[2] <= 255 - brightness {
px.data[2] += brightness;
}
else {
px.data[2] = 255
}
img.put_pixel(x, y, px);
}
}
photon_image.raw_pixels = img.raw_pixels();
}
#[wasm_bindgen]
pub fn tint(mut photon_image: &mut PhotonImage, r_offset: u32, g_offset: u32, b_offset: u32) {
let mut img = helpers::dyn_image_from_raw(&photon_image);
let (width, height) = img.dimensions();
for x in 0..width {
for y in 0..height {
let mut px = img.get_pixel(x, y);
let (r_val, g_val, b_val) = (px.data[0] as u32, px.data[1] as u32, px.data[2] as u32);
px.data[0] = if r_val as u32 + r_offset < 255 { r_val as u8 + r_offset as u8} else { 255 };
px.data[1] = if g_val as u32 + g_offset < 255 { g_val as u8 + g_offset as u8} else { 255 };
px.data[2] = if b_val as u32 + b_offset < 255 { b_val as u8 + b_offset as u8} else { 255 };
img.put_pixel(x, y, px);
}
}
let raw_pixels = img.raw_pixels();
photon_image.raw_pixels = raw_pixels;
}
#[wasm_bindgen]
pub fn horizontal_strips(mut photon_image: &mut PhotonImage, num_strips: u8) {
let mut img = helpers::dyn_image_from_raw(&photon_image);
let (width, height) = img.dimensions();
let total_strips = (num_strips * 2) - 1;
let height_strip = height / total_strips as u32;
let background_color = Rgb { r: 255, g: 255, b: 255};
let mut y_pos: u32 = 0;
for i in 1..num_strips {
draw_filled_rect_mut(&mut img,
Rect::at(0, (y_pos + height_strip) as i32).of_size(width, height_strip),
Rgba([background_color.r, background_color.g,
background_color.b, 255u8]));
y_pos = i as u32 * (height_strip * 2);
}
let raw_pixels = img.raw_pixels();
photon_image.raw_pixels = raw_pixels;
}
#[wasm_bindgen]
pub fn vertical_strips(mut photon_image: &mut PhotonImage, num_strips: u8) {
let mut img = helpers::dyn_image_from_raw(&photon_image);
let (width, height) = img.dimensions();
let total_strips = (num_strips * 2) - 1;
let width_strip = width / total_strips as u32;
let background_color = Rgb { r: 255, g: 255, b: 255};
let mut x_pos: u32 = 0;
for i in 1..num_strips {
draw_filled_rect_mut(&mut img,
Rect::at((x_pos + width_strip) as i32, 0).of_size(width_strip, height),
Rgba([background_color.r, background_color.g,
background_color.b, 255u8]));
x_pos = i as u32 * (width_strip * 2);
}
let raw_pixels = img.raw_pixels();
photon_image.raw_pixels = raw_pixels;
}