And I noticed that in debug mode, it takes a minute to load the jpeg files, so I wanted to do it with mozjpeg instead.
As a first step, I rewrote the image loading code to use this load_jpeg function:
fn load_jpeg(path: &str) -> io::Result<(Vec<u8>, u32, u32)> {
let r = BufReader::new(File::open(path)?);
let image = image::load(r, image::JPEG).unwrap().to_rgba();
let (w, h) = image.dimensions();
Ok((image.into_raw(), w, h))
}
// ...
let (image, w, h) = load_jpeg("images/posx.jpg").unwrap();
let image = glium::texture::RawImage2d::from_raw_rgba/*_reversed*/(image, (w, h));
let tex_posx = glium::Texture2d::new(&display, image).unwrap();
let (image, w, h) = load_jpeg("images/negx.jpg").unwrap();
let image = glium::texture::RawImage2d::from_raw_rgba/*_reversed*/(image, (w, h));
let tex_negx = glium::Texture2d::new(&display, image).unwrap();
let (image, w, h) = load_jpeg("images/posy.jpg").unwrap();
let image = glium::texture::RawImage2d::from_raw_rgba/*_reversed*/(image, (w, h));
let tex_posy = glium::Texture2d::new(&display, image).unwrap();
let (image, w, h) = load_jpeg("images/negy.jpg").unwrap();
let image = glium::texture::RawImage2d::from_raw_rgba/*_reversed*/(image, (w, h));
let tex_negy = glium::Texture2d::new(&display, image).unwrap();
let (image, w, h) = load_jpeg("images/posz.jpg").unwrap();
let image = glium::texture::RawImage2d::from_raw_rgba/*_reversed*/(image, (w, h));
let tex_posz = glium::Texture2d::new(&display, image).unwrap();
let (image, w, h) = load_jpeg("images/negz.jpg").unwrap();
let image = glium::texture::RawImage2d::from_raw_rgba/*_reversed*/(image, (w, h));
let tex_negz = glium::Texture2d::new(&display, image).unwrap();
Then I replaced the calls to load_jpeg with calls to load_jpeg_fast, using mozjpeg:
fn load_jpeg_fast(path: &str) -> io::Result<(Vec<u8>, u32, u32)> {
use std::mem;
use std::ffi::CString;
use libc;
use mozjpeg_sys::*;
unsafe {
let mut err: jpeg_error_mgr = mem::zeroed();
let mut dinfo: jpeg_decompress_struct = mem::zeroed();
dinfo.common.err = jpeg_std_error(&mut err);
jpeg_create_decompress(&mut dinfo);
let path = CString::new(path.as_bytes()).unwrap();
let mode = CString::new("rb").unwrap();
let fh = libc::fopen(path.as_ptr(), mode.as_ptr());
jpeg_stdio_src(&mut dinfo, fh);
jpeg_read_header(&mut dinfo, true as boolean);
let width = dinfo.image_width;
let height = dinfo.image_height;
println!("Image size {}x{}", width, height);
dinfo.out_color_space = J_COLOR_SPACE::JCS_RGB;
jpeg_start_decompress(&mut dinfo);
let row_stride = dinfo.image_width as usize * dinfo.output_components as usize;
let buffer_size = row_stride * dinfo.image_height as usize;
let mut buffer = vec![0u8; buffer_size];
while dinfo.output_scanline < dinfo.output_height {
let offset = dinfo.output_scanline as usize * row_stride;
let mut jsamparray = [buffer[offset..].as_mut_ptr()];
jpeg_read_scanlines(&mut dinfo, jsamparray.as_mut_ptr(), 1);
}
println!("Decoded into {} raw pixel bytes", buffer.len());
jpeg_finish_decompress(&mut dinfo);
jpeg_destroy_decompress(&mut dinfo);
libc::fclose(fh);
Ok((buffer, width, height))
}
}
But it's not working, now the program crashes with:
Image size 2048x2048
Decoded into 12582912 raw pixel bytes
thread 'main' panicked at 'Texture data size mismatch', C:\Users\me\.cargo\regis
try\src\github.com-1ecc6299db9ec823\glium-0.16.0\src\texture\any.rs:147:13
stack backtrace:
0: std::sys::windows::backtrace::unwind_backtrace
at C:\projects\rust\src\libstd\sys\windows\backtrace\mod.rs:65
1: std::sys_common::backtrace::_print
at C:\projects\rust\src\libstd\sys_common\backtrace.rs:71
2: std::sys_common::backtrace::print
at C:\projects\rust\src\libstd\sys_common\backtrace.rs:59
3: std::panicking::default_hook::{{closure}}
at C:\projects\rust\src\libstd\panicking.rs:207
4: std::panicking::default_hook
at C:\projects\rust\src\libstd\panicking.rs:223
5: std::panicking::rust_panic_with_hook
at C:\projects\rust\src\libstd\panicking.rs:402
6: std::panicking::begin_panic<str*>
at C:\projects\rust\src\libstd\panicking.rs:365
7: glium::texture::any::new_texture<glium::backend::glutin_backend::GlutinFac
ade,u8>
at \<panic macros>:3
8: glium::texture::texture2d::Texture2d::new_impl<glium::backend::glutin_back
end::GlutinFacade,glium::texture::RawImage2d<u8>>
at .\target\debug\build\glium-fc3f792f7cd57a36\out\textures.rs:2899
9: glium::texture::texture2d::Texture2d::new<glium::backend::glutin_backend::
GlutinFacade,glium::texture::RawImage2d<u8>>
at .\target\debug\build\glium-fc3f792f7cd57a36\out\textures.rs:2862
10: glium_cubemap::main
at .\src\main.rs:128
11: std::rt::lang_start::{{closure}}<()>
at C:\projects\rust\src\libstd\rt.rs:74
12: std::rt::lang_start_internal::{{closure}}
at C:\projects\rust\src\libstd\rt.rs:59
13: std::panicking::try::do_call<closure,i32>
at C:\projects\rust\src\libstd\panicking.rs:306
14: panic_unwind::__rust_maybe_catch_panic
at C:\projects\rust\src\libpanic_unwind\lib.rs:102
15: std::panicking::try
at C:\projects\rust\src\libstd\panicking.rs:285
16: std::panic::catch_unwind
at C:\projects\rust\src\libstd\panic.rs:361
17: std::rt::lang_start_internal
at C:\projects\rust\src\libstd\rt.rs:58
18: std::rt::lang_start<()>
at C:\projects\rust\src\libstd\rt.rs:74
19: main
20: invoke_main
at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:64
21: __scrt_common_main_seh
at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:253
22: BaseThreadInitThunk
23: RtlUserThreadStart
error: process didn't exit successfully: `target\debug\glium-cubemap.exe` (exit
code: 101)
I was trying out this example of rendering cubemaps with glium: http://onagat.hatenablog.com/entry/2017/03/24/235635
And I noticed that in
debug
mode, it takes a minute to load the jpeg files, so I wanted to do it with mozjpeg instead.As a first step, I rewrote the image loading code to use this
load_jpeg
function:Then I replaced the calls to
load_jpeg
with calls toload_jpeg_fast
, using mozjpeg:But it's not working, now the program crashes with:
Any idea what I'm doing wrong? :)