Dev Log September 2024

A long overdue dev log. The last one was for September 2023. That's a year. Stuff in life has happened.

Compiano

In November I switched Compiano to use pipewire directly for sound. This mean removing bits of UI too.

I should look at a release, but I have a few blockers I need to tackle. One key element is that there is a mechanism to download the soundbanks and for now it doesn't ask consent to do so. I don't want a release without this.

Raw thumbnailer

I already posted about it.

libopenraw

Lot has happened on that front. I want it to be a foundation of Niepce and others.

First adding it to glycin triggered an alpha release on crates.io. There started a long cycle of alpha release, we are at alpha 8 as of now. Various changes:

  • Added the mp4parse crate directly as a module. A key reason is that I already used a fork so it complicate things. Maybe I should make these few bits upstreamable and use upstream.
  • Added a mime types API
  • Save up a lot of RAM when doing colour interpolation: it's done in place instead of allocating a new buffer. This is significant as this is done using a 64-bit float per component.
  • Fixed the rendering in many ways. The only thing it needs it to apply the colour balance.
  • Fixed unpack or decompression of Olympus and Fuji files.
  • Got an external contribution: Panasonic decompression. This made me fix the loading of uncompressed Panasonic raw too. The more recent Panasonic cameras are still failing though, there is a subtle variant that needs to be handled.

Still missing from rendering: recent Nikon and all their exotic variants and compression scheme, Canon CR3, GoPro, Sony.

Niepce

Not so much work directly done on Niepce in the last few month, but still.

Ongoing features

Started a while ago some work towards the import and a rework of the catalog (the main data storage).

The former is the implementation of a workflow that allow immporting images into the catalog.

The latter involve reworking the catalog to become a self contained storage as a sqlite3 database. One step I already did was to use it to store the catalog preferences instead of a separate file. This should also include fixing the UI open, creating, switching.

This big two things are user visible and are a stop forward what I want to happen as an internal milestone. Then I can start pluging the library import and maybe import my picture vault. A good starting point towards managing the collection, but not really for photo editing yet. Gotta make choices.

Images

Implemented support for HEIF which is being adopted by camera manufacturers.

I updated the RT engine to 5.11 which came with RawTherapee 5.11. This is still a soft work of the code base to use strip out Gtk3 and a more recent version of glibmm. The latter patch might no longer be needed as I have since removed gtkmm from Niepce.

I also implemented the GEGL pipeline using gegl-rs, which I took over to make it useful. At one I shall try to figure out how to write a loader in Rust to use libopenraw with GEGL.

Cleanups

The UI is slowly moving to use blueprint, and I removed all the first-party C++ code outside of bindings, no more Gtkmm and Glibmm is only here because RT engine needs it.

Other

Stuff I contributed to.

STF

I took part to the STF effort and worked on fixing issues with the desktop portal. The big chunk of the work related to the USB portal, taking over code by Georges that is itself based on code by Ryan. It spreads through multiple component of the stack: flatpak, xdg-desktop-portal, xdg-desktop-portal-gnome, libportal and ashpd.

I also did a bunch of bug fixes, crashes, memory leaks, etc in flatpak, flatpak-builder, and the rest of the stack.

I also implemented issue #1 for flatpak-builder: easy renaming of MIME files and icons, and also properly fixing the id in the appstream file, a common problem in flatpak.

Glycin

Glycin is a sandboxed image loader. I did implement the raw camera loader using libopenraw. It's written in Rust, so is libopenraw now. Thank you Sophie for merging it.

Poppler

Jeff was complaining about a file being super slow, with sysprof flamegraph. That picked my curiosity and looked at it. The peculiarity of the document is that it has 16000 pages and a lot of cross references.

This lead to two patches:

  • The first one is in 24.06. There was a loop, calling for the length of the container at each iteration. Turns out this is protected by a mutex and that's a lot of time spend for nothing since the value is immutable. Call it once before the loop and voila.

  • The other one, merged for 24.09 change that loop to be a hash table lookup. The problem is that it want to locate the page by object reference, but iterate through the page list. Lots of ref and lots of a page mean even more iterator. The more complex approach is when building the page cache (it's done on demand), we build a reference to page index map. And the slow code is no longer slow and almost disappear from the flamegraphs.

This make Evince and Okular faster to open that document and any presenting similar attribute: a lot of bookmarks.

read more →

New raw thumbnailer

I have resurrected my camera old raw thumbnailer so that I can browse directories full of of camera raw images in Nautilus. This is version 47.0.1, because GNOME 47 is out.

Like the old one, it uses libopenraw to extract the previews from the raw files.

But, it now supports more raw formats, and if needed will render the raw image to generate a preview, like it has to for my old Ricoh GR Digital II images (the one from 2007). This leverage libopenraw 0.4.0 (still in alpha stage) that has been rewritten in Rust.

Sadly to get is in the hands of users the only good solution is a distribution package. At the time of writing there is none, but I put together smething that allowed me to build a package for Fedora 40 to install on my big rig.

If you feel like it you can download the source code from GNOME, and the repository is on GNOME gitlab.

This is how it looks with Nautilus 46 with a bunch of images from my old Olympus E-P1:

Nautilus directory view with ORF images thumbnails

read more →

Dev Log September 2023

It's October 2023.

Niepce

Really very little.

Fixed a cosmetic issues with icons in the workspace. The short version is that for symbolic icons to work, they must be in a "standard" path even if they are loaded from resources.

Also some minor dependency checks, etc.

lrcat-extractor

lrcat-extractor is my Rust crate to export Lightroom™ catalogs. It's used in Niepce. Just a few bits of maintenance, like replacing docopt with clap for the dumper tool, and using thiserror.

aplib-extractor

aplib-extractor is the sibling of lrcat-extractor, a crate to export Aperture™ libraries. This is actually the oldest and one of my first projects in Rust, which really shows. I worked on adding missing features so that I can implement the importer in Niepce, including listing the volumes.

The reasoning in implementing the import is to help refine the data model in Niepce to be able to handle the structure of an Aperture™ library as it offer organizational features that Ligthroom™ doesn't. This actually might lead to deeper changes in Niepce internal design.

Once the importer works, I will release the crate officially as I'll know the API is sound.

Dia on Gtk3

Two years after I started it, and mostly drop the ball, the GTK 3 port of Dia has been merged.

I also fixed a few other small issues, including some memory leaks.

read more →

Dia with GTK 3

If you are running Dia from the nigthly GNOME flatpak, the last update brought a big change: it is now a GTK 3 app. The UI shouldn't be much different, just some cosmetic adjustments due to theming and other like widget spacing. Also it now work with Wayland and HiDPI.

It is something I started over two years ago, and that for some reason I left on the back burner. So I did a final push and many thanks to Zander for reviewing and merging it. Now we shall hunt for regression. I already have a fix for the touchpad scrolling.

The version is numbered starting 0.98. So if it is Dia 0.98 or higher, then it's GTK 3.

There is still some more stuff to do. Fix a regression in the navigator widget, build without deprecation post GTK 3.8, etc.

read more →

Dev Log August 2023

Didn't really do anything on Niepce in August, so no updates on that front. However I worked on a few other things.

libopenraw

A lot of work done on it. See my other wlog post. The short version is that I should look towards releasing 0.4.0 sometime soon.

Since that last post, I have added a long standing to-do item: code to generate test cases so I can run a non regression test suite on existing files. However I get hit with flaws in the various XML serde crates.

AbiWord

Did some work on AbiWord. Nothing ground breaking, but I have a goal to try to release the next 3.0.x with one or two bug fixes (UI), and then what I call 3.next (likely 3.2) that will focus on internal changes (stability) and UI fixes (anything back-portable to 3.0.x will get back-ported).

Done

  • Some code cleanup.
  • Removed the use of boost in many places where the standard C++ library would work.
  • Use C++17 more.
  • Making the build system less recursive. It's less complex and should be more parallel.
  • Removed some Gtk3 construct that are deprecated in provision of a future Gtk4 port.
  • More removal of the legacy containers.
  • Rewrote the toolbars to use plain buttons and a GtkBox instead of GtkToolItem. The look is slightly different.
  • Fixing some Gtk3 bug: the table creation widget was not behaving properly. Will be on stable too (3.0.x)
  • Fixing some bugs with styling. (also on 3.0.x)
read more →

libopenraw Rust with C API

As I previously talked about, I started porting libopenraw to Rust. It is now in a state where it has more feature than the original.

When I started writing this post, I didn't have 100% of the code Rust, but since I have removed the last bit of C++, for which I had cut corners to make sure to have a functional API for C.

The only C++ code left is the various utilities and the C++ test suite to validate.

The goal

The goal of the Rust rewrite is to have the digital camera raw parsing library written in Rust instead of C++, while still being available with a C API.

The goal of the updated C API is to be close to the original API. However it's also a good time to do some breaking changes. Notably most of the "objects" are now immutable.

Rewrite

I did the rewrite in a branch, aiming to provide the same level of functionality as the C++ code. One of the first step was to rewrite the test suite to use the same data set. Doing so did allow verifying the consistency in behaviour, a progressively implement all the features and formats.

The C++ code use inheritance a bit to override some of the behaviours based on which file format it was. One of the thing most camera raw file have in common is that they are mostly a TIFF file. However Rust doesn't do object-oriented. It has traits that allow implementing some level of polymorphism, but in that case the concept had to be rethought a little bit.

Benefits

This is where Rust shines.

First there are a lot of things Rust, or the ecosystem around, did for me. In C++ I had re-implemented a stream system to allow IO on buffers and handling endianess. In Rust you can just read from a slice (a fixed size array of data) with the Read trait, and there are built-in functions to read endian-specific values. I still have the memory of trying to figure out which include to add depending on the UNIX flavour, between Linux, macOS and the BSD.

Second, the Debug trait. Just derive Debug (it's a simple macro) and you can "print" an type like that, using string formats. In C++, well, it's a lot of work. And on enum types it will print a human readable value, ie the one you write in code.

Third, the safety. A lot of the safety feature of Rust prevent mistake. And at runtime, the bounds checking catch of a lot of things too. Being required to use Option<> or Result<> to handle cases where in C++ you'd get some null value.

At that point, a few bugs I identified porting / rewriting the code made their way to the 0.3.x series in C++.

Drawbacks

libopenraw requires a Rust compiler (technically it already did, but I know some packagers that did disable Rust. This mean that non current architecture might not be supported. To me it's not a big issue, I target modern computers.

Testing

As mentioned I rewrote the test suite with the same data set. This is an essential part of making sure the features work as previously.

I also rewrote ordiag and the dumper ordumper. The dumper allow analyzing the structure of the file, and I didn't have this one in C++ (instead I had a more primitive exifdump). The dumper is heavily inspired from exifprobe that has served me well and that I forked. Really I can see the amount of work I didn't need to do with Rust.

To add to this I wrote libopenraw-viewer, a small Rust application to view the content of camera raw files. This allow much more easily to see the output. This has helped me to find fundamental bugs in some of the parsing that led to some fixes "upstream", namely into the C++ version (0.3.x branch). I should have done that a long time ago. This also allow me to test the Rust API.

C API adaptation

Last but not least I had to provide a C API. This allow using the library.

Rust to C ffi has limitations. You can basically pass numbers, pointers, and eventually simple structures.

The libopenraw API did return several types of "ref" which are just pointers to opaque types. The idea was always to only have opaque types through the API, which internally were C++ instances.

One of the key change is that the only object that can be explicitly be created with the API is ORRawFileRef, because it's the entry point. Very few need to be released, most are held by the containing objects.

Some other constraints of the C API directed some choices in the Rust API.

  • Raw files are no longer Box<> but Rc<> due to the need to retain them for the iterator.
  • Metadata::String() contain a Vec<u8> instead of a String to allow for the NUL terminated strings in the C API. They are maybe not NUL terminated but ASCII.

New features

Meanwhile I added a few new features:

  • extracting the white balance on most files (saveral Nikon are not yet handled).
  • color converting from the camera space to sRGB on rendering.
  • a multi stage processing pipeline.

This is still not enough to have a complete processing pipeline, but it's a start. It's going towards the only two issue left in the issue tracker. Not that I don't expect more but it's a nice goal post.

Integration

I submitted a PR for Miniaturo to use the Rust version of the library. This is not ready to be merged, but this actually allowed me to fix a few API bits. The new Rust API is relatively close to the old API that was the Rust to C bindings.

1

See issue 13

2

This is likely to change when I make libopenraw multi-thread compatible.

read more →

Niepce July 2023 updates

This is the July 2023 update for Niepce.

The importer

Where we left, the workspace tree view didn't display the hierarchy.

First, I discovered bug in the SQL triggers for folder path update. I was missing the AFTER keyword to have it run after the update.

Workspace

Second, I need to specify a parent when adding items to the model, then locate the parent, add to it. The problem is that we get a list of folders in some order (I can order by any of the SQL columns). The problem is adding an item to a parent that is not yet int the model. There are few ways to go about it.

  1. Sort the folder list in order of a flattened tree. To be fair my SQL skills are not good enough, and I'm not even sure I can do that in sqlite. This would solve most of the problems.
  2. Sort the folder list once received. But this might not always work.
  3. Handle the case in the model: add with a placeholder parent and re-parent as needed when the parent is added.

For now I chose 3. The risk is that if the parent doesn't exist then the tree will stay lingering. It's just the view though.

Here is the result:

read more →

Niepce June 2023 updates

This is the June 2023 update for Niepce.

The importer

Back where we left, still working on the import.

It looks like there is more work than anticipated to be able to import a tree a files.

read more →

Life update

If you are looking for a Software Engineer with strong skills in C, C++, Rust and JavaScript, with a strong FLOSS background, I am available to hire.

My résumé

read more →

Niepce May 2023 updates

This is the May 2023 update for Niepce.

Life comes at you fast. And hit hard. tl;dr not as much progress as I wished: I had to put this project a bit more on the sideline.

This will be a short update.

The importer

Some small bits:

Some fixing in the metadata processing on import, notably a better handling of raw files. Turns out the previous logic broke getting metadata from video files.

Also fixing some rexiv2 / gexiv2-sys bugs that are mostly memory leaks.

I am pondering directly binding Exiv2 now that 0.28 got rid of auto_ptr<> that had been deprecated for over a decade. cxx should make this easier. This would automatically resolve the problem above, and I don't need to bind all the API, just what I need.

Forecast

To move forward the importer, I need to fix the recursive creation of folders (it currently flatten them to a single level).

Misc

There are always the other fixes.

Fedora 38

I pulled the trigger and updated to Fedora 38. And Niepce failed to build because of a bug with bindgen with clang 16, that was already fixed, triggered by libgphoto2-sys. Submitted the PR for the crate and we are good to go. The short version is that clang 16 sent different data for anonymous enums, that bindgen 0.60 couldn't handle. But at that bindgen 0.65 was fine.

This is the reason why I always check into git the generated bindings and update them as needed, instead of doing it at build time.

Application ID

I have been using org.gnome.Niepce as an application ID. While it is hosted in the main namespace repositories (it was back in the days of Subversion, to which I am thankful), Niepce is not a core app. Policies with the GNOME project do not allow using that namespace for non core apps. So I had a perform a global change rename. Not a big deal, and it doesn't change anything for users since there is no release. I just needed to get this out of the way.

libopenraw

Pushed a bit on the Rust port to implement metadata extraction. This is driven by the goal of not having three different libraries. Still some parity gaps with the C++ code, but it's closing in. I hope to be able to release 0.4.0 based on the Rust code.

Thanks you for reading.

read more →