Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
lilith committed Sep 30, 2024
1 parent c0746d4 commit 41b7e69
Show file tree
Hide file tree
Showing 11 changed files with 420 additions and 115 deletions.
243 changes: 136 additions & 107 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ opt-level = 2
[patch.crates-io]
libwebp-sys = { git = "https://github.com/lilith/libwebp-sys" }
libpng-sys = { git = "https://github.com/lilith/rust-libpng-sys" }
rgb.git = "https://github.com/kornelski/rust-rgb"

#bennch with cpu native
[profile.bench]
Expand Down
2 changes: 1 addition & 1 deletion c_components/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub struct flow_decoder_frame_info {
pub h: i32,
pub format: flow_pixel_format,
}
extern "C" {
extern "C-unwind" {
#[no_mangle]
fn flow_pixel_format_bytes_per_pixel(format: flow_pixel_format) -> u32;
#[no_mangle]
Expand Down
3 changes: 2 additions & 1 deletion imageflow_core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@ daggy = "0.8" # Upgrade to
smallvec = "1"
itertools = "0.13"
imgref = "1.4.1"
png = "0.17.8"
slotmap = "1"
base64 = "0.22"
hex = "0.4"
gif = "0.13.1"
rgb = { version = "0.8", features = ["argb"] }
rgb = { version = "0.8.90", features = ["bytemuck"] }
imagequant = "4"
lodepng = "3"
flate2 = { version = "1.0", features = ["zlib"], default-features = false }
Expand Down
161 changes: 161 additions & 0 deletions imageflow_core/src/codecs/image_png_decoder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
use std::io::Read;

use crate::{Context, Result, FlowError, ErrorKind};
use crate::io::IoProxy;
use crate::graphics::bitmaps::{BitmapKey, ColorSpace, BitmapCompositing};
use crate::codecs::Decoder;
use imageflow_types as s;
use imageflow_helpers::preludes::from_std::*;
//use crate::for_other_imageflow_crates::preludes::external_without_std::*;
use crate::graphics::bitmaps::BitmapRowAccess;

use png;
use rgb;

pub struct ImagePngDecoder {
reader: png::Reader<IoProxy>,
info: png::Info<'static>,
}

impl ImagePngDecoder {
pub fn create(c: &Context, io: IoProxy, io_id: i32) -> Result<ImagePngDecoder> {
// Wrap IoProxy in a Box<dyn Read>
//let read_io = Box::new(io) as Box<dyn Read>;
let mut decoder = png::Decoder::new(io);
//decoder.set_transformations(png::Transformations::EXPAND);
decoder.set_transformations(png::Transformations::normalize_to_color8());

let reader = decoder.read_info()
.map_err(|e| FlowError::from_png_decoder(e).at(here!()))?;

let info = reader.info().clone();

Ok(ImagePngDecoder {
reader,
info,
})
}
}
impl Decoder for ImagePngDecoder {
fn initialize(&mut self, c: &Context) -> Result<()> {
Ok(())
}

fn get_unscaled_image_info(&mut self, c: &Context) -> Result<s::ImageInfo> {
Ok(s::ImageInfo {
frame_decodes_into: s::PixelFormat::Bgra32,
image_width: self.info.width as i32,
image_height: self.info.height as i32,
preferred_mime_type: "image/png".to_owned(),
preferred_extension: "png".to_owned(),
})
}

fn get_scaled_image_info(&mut self, c: &Context) -> Result<s::ImageInfo> {
self.get_unscaled_image_info(c)
}

fn get_exif_rotation_flag(&mut self, c: &Context) -> Result<Option<i32>> {
Ok(None)
}

fn tell_decoder(&mut self, c: &Context, tell: s::DecoderCommand) -> Result<()> {
Ok(())
}

fn read_frame(&mut self, c: &Context) -> Result<BitmapKey> {
let mut bitmaps = c.borrow_bitmaps_mut().map_err(|e| e.at(here!()))?;
let info = self.reader.info();

let canvas_key = bitmaps.create_bitmap_u8(
info.width,
info.height,
imageflow_types::PixelLayout::BGRA,
false,
true,
ColorSpace::StandardRGB,
BitmapCompositing::ReplaceSelf,
).map_err(|e| e.at(here!()))?;

let mut bitmap =
bitmaps.try_borrow_mut(canvas_key)
.map_err(|e| e.at(here!()))?;

let mut canvas = bitmap.get_window_u8().unwrap();


let mut buffer = vec![0; self.reader.output_buffer_size()];
let output_info = self.reader.next_frame(&mut buffer).map_err(|e| FlowError::from_png_decoder(e).at(here!()))?;

let h = output_info.height as usize;
let stride = output_info.line_size;
let w = output_info.width as usize;
if output_info.bit_depth != png::BitDepth::Eight{
return Err(nerror!(ErrorKind::ImageDecodingError, "image/png decoder did not expand to 8-bit channels").at(here!()));
}
match output_info.color_type{
png::ColorType::Rgb =>{
for row_ix in 0..h{
let from = buffer.row_mut_rgb8(row_ix, stride).unwrap();
let to = canvas.row_mut_bgra(row_ix as u32).unwrap();
from.into_iter().zip(to.iter_mut()).for_each(|(from, to)| {
to.r = from.r;
to.g = from.g;
to.b = from.b;
to.a = 255;
});
}
},
png::ColorType::Rgba => {
for row_ix in 0..h{
let from = buffer.row_mut_rgba8(row_ix, stride).unwrap();
let to = canvas.row_mut_bgra(row_ix as u32).unwrap();
from.into_iter().zip(to.iter_mut()).for_each(|(from, to)| {
to.r = from.r;
to.g = from.g;
to.b = from.b;
to.a = from.a;
});
}
},

png::ColorType::Grayscale => {
for row_ix in 0..h{
let from = buffer.row_mut_gray8(row_ix, stride).unwrap();
let to = canvas.row_mut_bgra(row_ix as u32).unwrap();
from.into_iter().zip(to.iter_mut()).for_each(|(f, to)| {
to.r = f.v;
to.g = f.v;
to.b = f.v;
to.a = 255;
});
}

},
png::ColorType::GrayscaleAlpha => {
for row_ix in 0..h{
let from = buffer.row_mut_grayalpha8(row_ix, stride).unwrap();
let to = canvas.row_mut_bgra(row_ix as u32).unwrap();
from.into_iter().zip(to.iter_mut()).for_each(|(from, to)| {
to.r = from.v;
to.g = from.v;
to.b = from.v;
to.a = from.a;
});
}
}

_ => panic!("png decoder bug: indexed image was not expanded despite flags.")
}

Ok(canvas_key)
}

fn has_more_frames(&mut self) -> Result<bool> {
Ok(false)
}

fn as_any(&self) -> &dyn std::any::Any {
self as &dyn std::any::Any
}
}
7 changes: 6 additions & 1 deletion imageflow_core/src/codecs/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ mod mozjpeg_decoder;
mod libpng_decoder;
mod libpng_encoder;
mod mozjpeg_decoder_helpers;
mod image_png_decoder;
mod jpeg_decoder;
mod webp;
mod color_transform_cache;
Expand Down Expand Up @@ -69,6 +70,7 @@ pub enum NamedDecoders{
MozJpegRsDecoder,
WICJpegDecoder,
ImageRsJpegDecoder,
ImageRsPngDecoder,
LibPngRsDecoder,
GifRsDecoder,
WebPDecoder,
Expand All @@ -82,7 +84,7 @@ impl NamedDecoders{
NamedDecoders::GifRsDecoder => {
bytes.starts_with(b"GIF89a") || bytes.starts_with(b"GIF87a")
},
NamedDecoders::LibPngRsDecoder => {
NamedDecoders::LibPngRsDecoder | NamedDecoders::ImageRsPngDecoder => {
bytes.starts_with( b"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
},
NamedDecoders::WebPDecoder => {
Expand All @@ -97,6 +99,7 @@ impl NamedDecoders{
NamedDecoders::LibPngRsDecoder => Ok(Box::new(libpng_decoder::LibPngDecoder::create(c, io, io_id)?)),
NamedDecoders::GifRsDecoder => Ok(Box::new(gif::GifDecoder::create(c, io, io_id)?)),
NamedDecoders::ImageRsJpegDecoder => Ok(Box::new(jpeg_decoder::JpegDecoder::create(c, io, io_id)?)),
NamedDecoders::ImageRsPngDecoder => Ok(Box::new(image_png_decoder::ImagePngDecoder::create(c, io, io_id)?)),
NamedDecoders::WebPDecoder => Ok(Box::new(webp::WebPDecoder::create(c, io, io_id)?)),
NamedDecoders::WICJpegDecoder => {
panic!("WIC Jpeg Decoder not implemented"); //TODO, use actual error for this
Expand All @@ -123,6 +126,8 @@ impl Default for EnabledCodecs {
EnabledCodecs{
decoders: smallvec::SmallVec::from_slice(
&[NamedDecoders::MozJpegRsDecoder,

NamedDecoders::ImageRsPngDecoder,
NamedDecoders::LibPngRsDecoder,
NamedDecoders::GifRsDecoder,
NamedDecoders::WebPDecoder]),
Expand Down
7 changes: 7 additions & 0 deletions imageflow_core/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,13 @@ impl FlowError {
}

}
pub fn from_png_decoder(e: png::DecodingError) -> Self{
match e{
png::DecodingError::IoError(e) => FlowError::without_location(ErrorKind::DecodingIoError, format!("{:?}", e)),
png::DecodingError::Format(e) => FlowError::without_location(ErrorKind::ImageDecodingError, format!("{:?}", e)),
_ => FlowError::without_location(ErrorKind::ImageDecodingError, format!("{:?}", e)),
}
}
}


Expand Down
103 changes: 102 additions & 1 deletion imageflow_core/src/graphics/bitmaps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use std::cell::{RefCell, RefMut};
use std;
use std::ops::DerefMut;
use crate::ErrorKind::BitmapPointerNull;
use bytemuck::{Pod, try_cast_slice, try_cast_slice_mut};
use rgb::{RGBA8, RGB8, BGRA8, BGR8, GrayA, Gray_v09 as Gray};



Expand Down Expand Up @@ -181,7 +183,11 @@ impl<'a> BitmapWindowMut<'a, u8> {
}

}
impl<'a,T> BitmapWindowMut<'a, T> {




impl<'a,T: bytemuck::NoUninit + rgb::Pod> BitmapWindowMut<'a, T> {

pub unsafe fn to_bitmap_float(&mut self) -> Result<BitmapFloat, FlowError>{
if std::mem::size_of::<T>() != 4{
Expand Down Expand Up @@ -282,6 +288,13 @@ impl<'a,T> BitmapWindowMut<'a, T> {
}
}

pub fn row_mut_bgra(&mut self, index: u32) -> Option<&mut [rgb::Bgra<T>]>{
if self.info.pixel_layout() != PixelLayout::BGRA{
return None;
}
self.row_mut(index).map(|r| bytemuck::cast_slice_mut::<T, rgb::Bgra<T>>(r) )
}

pub fn row(&self, index: u32) -> Option<&[T]>{
if index >= self.info.h {
None
Expand Down Expand Up @@ -632,4 +645,92 @@ impl Bitmap{
}
}

pub trait BitmapRowAccess {
fn row_bgra8(&self, row_ix: usize, stride: usize) -> Option<&[BGRA8]>;
fn row_rgba8(&self, row_ix: usize, stride: usize) -> Option<&[RGBA8]>;
fn row_bgr8(&self, row_ix: usize, stride: usize) -> Option<&[BGR8]>;
fn row_rgb8(&self, row_ix: usize, stride: usize) -> Option<&[RGB8]>;
fn row_gray8(&self, row_ix: usize, stride: usize) -> Option<&[Gray<u8>]>;
fn row_grayalpha8(&self, row_ix: usize, stride: usize) -> Option<&[GrayA<u8>]>;

fn row_mut_bgra8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [BGRA8]>;
fn row_mut_rgba8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [RGBA8]>;
fn row_mut_bgr8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [BGR8]>;
fn row_mut_rgb8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [RGB8]>;
fn row_mut_gray8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [Gray<u8>]>;
fn row_mut_grayalpha8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [GrayA<u8>]>;
}

impl BitmapRowAccess for Vec<u8> {
fn row_bgra8(&self, row_ix: usize, stride: usize) -> Option<&[BGRA8]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get(start..start.checked_add(stride)?)?;
try_cast_slice(row).ok()
}

fn row_rgba8(&self, row_ix: usize, stride: usize) -> Option<&[RGBA8]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get(start..start.checked_add(stride)?)?;
try_cast_slice(row).ok()
}

fn row_bgr8(&self, row_ix: usize, stride: usize) -> Option<&[BGR8]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get(start..start.checked_add(stride)?)?;
try_cast_slice(row).ok()
}

fn row_rgb8(&self, row_ix: usize, stride: usize) -> Option<&[RGB8]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get(start..start.checked_add(stride)?)?;
try_cast_slice(row).ok()
}

fn row_gray8(&self, row_ix: usize, stride: usize) -> Option<&[Gray<u8>]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get(start..start.checked_add(stride)?)?;
try_cast_slice(row).ok()
}

fn row_grayalpha8(&self, row_ix: usize, stride: usize) -> Option<&[GrayA<u8>]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get(start..start.checked_add(stride)?)?;
try_cast_slice(row).ok()
}

fn row_mut_bgra8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [BGRA8]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get_mut(start..start.checked_add(stride)?)?;
try_cast_slice_mut(row).ok()
}

fn row_mut_rgba8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [RGBA8]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get_mut(start..start.checked_add(stride)?)?;
try_cast_slice_mut(row).ok()
}

fn row_mut_bgr8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [BGR8]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get_mut(start..start.checked_add(stride)?)?;
try_cast_slice_mut(row).ok()
}

fn row_mut_rgb8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [RGB8]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get_mut(start..start.checked_add(stride)?)?;
try_cast_slice_mut(row).ok()
}

fn row_mut_gray8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [Gray<u8>]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get_mut(start..start.checked_add(stride)?)?;
try_cast_slice_mut(row).ok()
}

fn row_mut_grayalpha8(&mut self, row_ix: usize, stride: usize) -> Option<&mut [GrayA<u8>]> {
let start = row_ix.checked_mul(stride)?;
let row = self.get_mut(start..start.checked_add(stride)?)?;
try_cast_slice_mut(row).ok()
}
}
4 changes: 2 additions & 2 deletions imageflow_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ mod codecs;
mod io;
pub mod graphics;

pub use crate::context::{Context};
pub use crate::context::Context;
pub use crate::io::IoProxy;
pub use crate::ffi::{IoDirection};
pub use crate::ffi::IoDirection;
pub use crate::flow::definitions::Graph;
pub use crate::json::JsonResponse;
pub use crate::json::MethodRouter;
Expand Down
2 changes: 1 addition & 1 deletion imageflow_core/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ impl<'a> ResultKind<'a>{
}
}

fn get_imgref_bgra32(b: &mut BitmapBgra) -> imgref::ImgVec<rgb::RGBA<f32>> {
fn get_imgref_bgra32(b: &mut BitmapBgra) -> imgref::ImgVec<rgb::Rgba<f32>> {
use self::dssim::*;

match b.fmt {
Expand Down
Loading

0 comments on commit 41b7e69

Please sign in to comment.