diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix index 178118462947..cd20d19d5c32 100644 --- a/maintainers/maintainer-list.nix +++ b/maintainers/maintainer-list.nix @@ -9834,6 +9834,12 @@ githubId = 4753752; name = "guttermonk"; }; + guylamar2006 = { + name = "guylamar2006"; + github = "guylamar2006"; + githubId = 4555064; + keys = [ { fingerprint = "0438 6FD4 D588 E32B 206F 2B49 1C4F DEA2 DB34 FEE4"; } ]; + }; guyonvarch = { github = "guyonvarch"; githubId = 6768842; @@ -9891,6 +9897,12 @@ githubId = 5190539; keys = [ { fingerprint = "AD3D 53CB A68A FEC0 8065 BCBB 416A D9E8 E372 C075"; } ]; }; + hadziqM = { + name = "Hadziq Masfuh"; + email = "dimascrazz@gmail.com"; + github = "HadziqM"; + githubId = 50319538; + }; hagl = { email = "harald@glie.be"; github = "hagl"; diff --git a/nixos/doc/manual/release-notes/rl-2511.section.md b/nixos/doc/manual/release-notes/rl-2511.section.md index 22024e12f2ee..ca694d5057e0 100644 --- a/nixos/doc/manual/release-notes/rl-2511.section.md +++ b/nixos/doc/manual/release-notes/rl-2511.section.md @@ -160,6 +160,22 @@ - `virtualisation.lxd` has been removed due to lack of Nixpkgs maintenance. Users can migrate to `virtualisation.incus`, a fork of LXD, as a replacement. See [Incus migration documentation](https://linuxcontainers.org/incus/docs/main/howto/server_migrate_lxd/) for migration information. +- `virtualisation.libvirtd` now uses OVMF images shipped with QEMU for UEFI machines. `virtualisation.libvirtd.qemu.ovmf` has been removed. + - OVMF images from underlying QEMU package are now made available under '/run/libvirt/nix-ovmf', fixing prior issues when using QEMU's automatic EFI firmware and feature handling, relied upon by GNOME Boxes, virsh, virt-manager, etc. + - Domains that rely on automatic firmware and feature handling, i.e. `` need to trigger an update to `` and `` entries. + Using `virsh edit ` and deleting aforementioned tags will cause libvirt to replace them with the new paths. + - Configurations that relied on `virtualisation.libvirtd.qemu.ovmf` and had domains that did not use automatic firmware and feature handling, require a manual change to their domain configuration, updating `` and `` entries from old path to the new path. + | Old Path | New Path | + |----------------------------------------|--------------------------------------------------| + | /run/libvirt/nix-ovmf/OVMF_CODE.fd | /run/libvirt/nix-ovmf/edk2-x86_64-code.fd | + | /run/libvirt/nix-ovmf/OVMF_VARS.fd | /run/libvirt/nix-ovmf/edk2-i386-vars.fd | + | /run/libvirt/nix-ovmf/OVMF_CODE.ms.fd | /run/libvirt/nix-ovmf/edk2-x86_64-secure-code.fd | + | /run/libvirt/nix-ovmf/OVMF_VARS.ms.fd | /run/libvirt/nix-ovmf/edk2-i386-vars.fd | + | /run/libvirt/nix-ovmf/AAVMF_CODE.fd | /run/libvirt/nix-ovmf/edk2-aarch64-code.fd | + | /run/libvirt/nix-ovmf/AAVMF_VARS.fd | /run/libvirt/nix-ovmf/edk2-arm-vars.fd | + | /run/libvirt/nix-ovmf/AAVMF_CODE.ms.fd | /run/libvirt/nix-ovmf/edk2-aarch64-code.fd | + | /run/libvirt/nix-ovmf/AAVMF_VARS.ms.fd | /run/libvirt/nix-ovmf/edk2-arm-vars.fd | + - The non-LTS Forgejo package (`forgejo`) has been updated to 12.0.0. This release contains breaking changes, see the [release blog post](https://forgejo.org/2025-07-release-v12-0/) for all the details and how to ensure smooth upgrades. @@ -281,6 +297,15 @@ - `services.nextcloud.configureRedis` now defaults to `true` in accordance with upstream recommendations to have caching for file locking. See the [upstream doc](https://docs.nextcloud.com/server/31/admin_manual/configuration_files/files_locking_transactional.html) for further details. - mate-wayland-session 1.28.4 is now using the default wayfire decorator instead of firedecor, thus `services.xserver.desktopManager.mate.enableWaylandSession` is no longer shipping firedecor. If you are experiencing broken window decorations after upgrade, backup and remove `~/.config/mate/wayfire.ini` and re-login. +- +- A new option [](#opt-boot.isNspawnContainer) has been added. This option will be used to guard nspawn-specific configuration in NixOS since [](#opt-boot.isContainer) is also used for different container-runtimes such as LXC. + - The new option is automatically set to `true` by the declarative container module and `nixos-container` when not using flakes. + - Existing setups can be migrated by running either + - `nixos-container update --config-file /path/to/the/config-file-in-use.nix` + - `nixos-container update --config '/* config code */'` + - Setting the option by hand in your configuration when using flakes. + - In all other cases, you'll need to set this option to `true` yourself. + - `boot.isNspawnContainer` being `true` implies [](#opt-boot.isContainer) being `true`. - Due to [deprecation of gnome-session X11 support](https://blogs.gnome.org/alatiera/2025/06/08/the-x11-session-removal/), `services.desktopManager.pantheon` now defaults to pantheon-wayland session. The X11 session has been removed, see [this issue](https://github.com/elementary/session-settings/issues/91) for details. @@ -333,6 +358,8 @@ - `services.netbird.server` now uses dedicated packages split out due to relicensing of server components to AGPLv3 with version `0.53.0`, +- `linux_libre` & `linux_latest_libre` have been removed due to a lack of maintenance. + - `services.pds` has been renamed to `services.bluesky-pds`. - `services.xserver.desktopManager.deepin` and associated packages have been removed due to being unmaintained. See issue [#422090](https://github.com/NixOS/nixpkgs/issues/422090) for more details. diff --git a/nixos/modules/installer/tools/nixos-generate-config.pl b/nixos/modules/installer/tools/nixos-generate-config.pl index 7c404fa25dc6..9397d06e7ae7 100644 --- a/nixos/modules/installer/tools/nixos-generate-config.pl +++ b/nixos/modules/installer/tools/nixos-generate-config.pl @@ -306,7 +306,7 @@ if ($virt eq "microsoft") { # Pull in NixOS configuration for containers. if ($virt eq "systemd-nspawn") { - push @attrs, "boot.isContainer = true;"; + push @attrs, "boot.isNspawnContainer = true;"; } diff --git a/nixos/modules/profiles/nix-builder-vm.nix b/nixos/modules/profiles/nix-builder-vm.nix index 67a134cb95fa..d75b786a6958 100644 --- a/nixos/modules/profiles/nix-builder-vm.nix +++ b/nixos/modules/profiles/nix-builder-vm.nix @@ -40,6 +40,10 @@ in default = false; internal = true; }; + options.boot.isNspawnContainer = lib.mkOption { + default = false; + internal = true; + }; } ]; diff --git a/nixos/modules/services/networking/ncps.nix b/nixos/modules/services/networking/ncps.nix index a9f16e022307..b0e821fee5b1 100644 --- a/nixos/modules/services/networking/ncps.nix +++ b/nixos/modules/services/networking/ncps.nix @@ -50,6 +50,7 @@ let ++ (lib.optional (cfg.cache.secretKeyPath != null) "--cache-secret-key-path='%d/secretKey'") ++ (lib.forEach cfg.upstream.caches (url: "--upstream-cache='${url}'")) ++ (lib.forEach cfg.upstream.publicKeys (pk: "--upstream-public-key='${pk}'")) + ++ (lib.optional (cfg.netrcFile != null) "--netrc-file='${cfg.netrcFile}'") ); isSqlite = lib.strings.hasPrefix "sqlite:" cfg.cache.databaseURL; @@ -211,6 +212,16 @@ in ''; }; }; + + netrcFile = lib.mkOption { + type = lib.types.nullOr lib.types.str; + default = null; + example = "/etc/nix/netrc"; + description = '' + The path to netrc file for upstream authentication. + When unspecified ncps will look for ``$HOME/.netrc`. + ''; + }; }; }; @@ -341,5 +352,8 @@ in }; }; - meta.maintainers = with lib.maintainers; [ kalbasit ]; + meta.maintainers = with lib.maintainers; [ + kalbasit + aciceri + ]; } diff --git a/nixos/modules/tasks/filesystems.nix b/nixos/modules/tasks/filesystems.nix index 84b66404f6f9..74b3b83f09f7 100644 --- a/nixos/modules/tasks/filesystems.nix +++ b/nixos/modules/tasks/filesystems.nix @@ -545,6 +545,30 @@ in # Sync mount options with systemd's src/core/mount-setup.c: mount_table. boot.specialFileSystems = { + # To hold secrets that shouldn't be written to disk + "/run/keys" = { + fsType = "ramfs"; + options = [ + "nosuid" + "nodev" + "mode=750" + ]; + }; + } + // optionalAttrs (!config.boot.isContainer) { + # systemd-nspawn populates /sys by itself, and remounting it causes all + # kinds of weird issues (most noticeably, waiting for host disk device + # nodes). + "/sys" = { + fsType = "sysfs"; + options = [ + "nosuid" + "noexec" + "nodev" + ]; + }; + } + // optionalAttrs (!config.boot.isNspawnContainer) { "/proc" = { fsType = "proc"; options = [ @@ -592,29 +616,6 @@ in "gid=${toString config.ids.gids.tty}" ]; }; - - # To hold secrets that shouldn't be written to disk - "/run/keys" = { - fsType = "ramfs"; - options = [ - "nosuid" - "nodev" - "mode=750" - ]; - }; - } - // optionalAttrs (!config.boot.isContainer) { - # systemd-nspawn populates /sys by itself, and remounting it causes all - # kinds of weird issues (most noticeably, waiting for host disk device - # nodes). - "/sys" = { - fsType = "sysfs"; - options = [ - "nosuid" - "noexec" - "nodev" - ]; - }; }; }; diff --git a/nixos/modules/virtualisation/libvirtd.nix b/nixos/modules/virtualisation/libvirtd.nix index d23299202b44..b4a5e1cebc49 100644 --- a/nixos/modules/virtualisation/libvirtd.nix +++ b/nixos/modules/virtualisation/libvirtd.nix @@ -17,14 +17,6 @@ let ${cfg.extraConfig} ''; qemuConfigFile = pkgs.writeText "qemu.conf" '' - ${optionalString cfg.qemu.ovmf.enable '' - nvram = [ - "/run/libvirt/nix-ovmf/AAVMF_CODE.fd:/run/libvirt/nix-ovmf/AAVMF_VARS.fd", - "/run/libvirt/nix-ovmf/AAVMF_CODE.ms.fd:/run/libvirt/nix-ovmf/AAVMF_VARS.ms.fd", - "/run/libvirt/nix-ovmf/OVMF_CODE.fd:/run/libvirt/nix-ovmf/OVMF_VARS.fd", - "/run/libvirt/nix-ovmf/OVMF_CODE.ms.fd:/run/libvirt/nix-ovmf/OVMF_VARS.ms.fd" - ] - ''} ${optionalString (!cfg.qemu.runAsRoot) '' user = "qemu-libvirtd" group = "qemu-libvirtd" @@ -38,36 +30,6 @@ let dirName = "libvirt"; subDirs = list: [ dirName ] ++ map (e: "${dirName}/${e}") list; - ovmfModule = types.submodule { - options = { - enable = mkOption { - type = types.bool; - default = true; - description = '' - Allows libvirtd to take advantage of OVMF when creating new - QEMU VMs with UEFI boot. - ''; - }; - - # mkRemovedOptionModule does not work in submodules, do it manually - package = mkOption { - type = types.nullOr types.package; - default = null; - internal = true; - }; - - packages = mkOption { - type = types.listOf types.package; - default = [ pkgs.OVMF.fd ]; - defaultText = literalExpression "[ pkgs.OVMF.fd ]"; - example = literalExpression "[ pkgs.OVMFFull.fd pkgs.pkgsCross.aarch64-multiplatform.OVMF.fd ]"; - description = '' - List of OVMF packages to use. Each listed package must contain files names FV/OVMF_CODE.fd and FV/OVMF_VARS.fd or FV/AAVMF_CODE.fd and FV/AAVMF_VARS.fd - ''; - }; - }; - }; - swtpmModule = types.submodule { options = { enable = mkOption { @@ -116,11 +78,28 @@ let }; ovmf = mkOption { - type = ovmfModule; + type = types.submodule { + options = { + enable = mkOption { + type = types.nullOr types.bool; + default = null; + internal = true; + }; + package = mkOption { + type = types.nullOr types.package; + default = null; + internal = true; + }; + packages = mkOption { + type = types.nullOr (types.listOf types.package); + default = null; + internal = true; + }; + }; + }; default = { }; - description = '' - QEMU's OVMF options. - ''; + internal = true; + description = "This submodule is deprecated and has been removed"; }; swtpm = mkOption { @@ -220,6 +199,21 @@ let }; }; }; + + qemuOvmfMetadata = pkgs.stdenv.mkDerivation { + name = "qemu-ovmf-metadata"; + version = cfg.qemu.package.version; + nativeBuildInputs = [ cfg.qemu.package ]; + dontBuild = true; + dontUnpack = true; + installPhase = '' + mkdir -p $out + cp ${cfg.qemu.package}/share/qemu/firmware/*.json $out + substituteInPlace $out/*.json \ + --replace-fail "${cfg.qemu.package}/share/qemu/" "/run/${dirName}/nix-ovmf/" + ''; + }; + in { @@ -241,17 +235,16 @@ in [ "virtualisation" "libvirtd" "qemuVerbatimConfig" ] [ "virtualisation" "libvirtd" "qemu" "verbatimConfig" ] ) - (mkRenamedOptionModule - [ "virtualisation" "libvirtd" "qemuOvmf" ] - [ "virtualisation" "libvirtd" "qemu" "ovmf" "enable" ] - ) - (mkRemovedOptionModule [ "virtualisation" "libvirtd" "qemuOvmfPackage" ] - "If this option was set to `foo`, set the option `virtualisation.libvirtd.qemu.ovmf.packages' to `[foo.fd]` instead." - ) (mkRenamedOptionModule [ "virtualisation" "libvirtd" "qemuSwtpm" ] [ "virtualisation" "libvirtd" "qemu" "swtpm" "enable" ] ) + (mkRemovedOptionModule [ "virtualisation" "libvirtd" "qemuOvmf" ] + "The 'virtualisation.libvirtd.qemuOvmf' option has been removed. All OVMF images distributed with QEMU are now available by default." + ) + (mkRemovedOptionModule [ "virtualisation" "libvirtd" "qemuOvmfPackage" ] + "The 'virtualisation.libvirtd.qemuOvmfPackage' option has been removed. All OVMF images distributed with QEMU are now available by default." + ) ]; ###### interface @@ -408,17 +401,15 @@ in config = mkIf cfg.enable { assertions = [ - { - assertion = config.virtualisation.libvirtd.qemu.ovmf.package == null; - message = '' - The option virtualisation.libvirtd.qemu.ovmf.package is superseded by virtualisation.libvirtd.qemu.ovmf.packages. - If this option was set to `foo`, set the option `virtualisation.libvirtd.qemu.ovmf.packages' to `[foo.fd]` instead. - ''; - } { assertion = config.security.polkit.enable; message = "The libvirtd module currently requires Polkit to be enabled ('security.polkit.enable = true')."; } + + { + assertion = ((lib.filterAttrs (n: v: v != null) cfg.qemu.ovmf) == { }); + message = "The 'virtualisation.libvirtd.qemu.ovmf' submodule has been removed. All OVMF images distributed with QEMU are now available by default."; + } ]; environment = { @@ -488,20 +479,12 @@ in ln -s --force ${cfg.qemu.package}/bin/qemu-pr-helper /run/${dirName}/nix-helpers/ - ${optionalString cfg.qemu.ovmf.enable ( - let - ovmfpackage = pkgs.buildEnv { - name = "qemu-ovmf"; - paths = cfg.qemu.ovmf.packages; - }; - in - '' - ln -s --force ${ovmfpackage}/FV/AAVMF_CODE{,.ms}.fd /run/${dirName}/nix-ovmf/ - ln -s --force ${ovmfpackage}/FV/OVMF_CODE{,.ms}.fd /run/${dirName}/nix-ovmf/ - ln -s --force ${ovmfpackage}/FV/AAVMF_VARS{,.ms}.fd /run/${dirName}/nix-ovmf/ - ln -s --force ${ovmfpackage}/FV/OVMF_VARS{,.ms}.fd /run/${dirName}/nix-ovmf/ - '' - )} + # Symlink to OVMF firmware code and variable template images distributed with QEMU + cp -sfv $( + ${pkgs.jq}/bin/jq -rs \ + '[.[] | .mapping.executable.filename, .mapping."nvram-template".filename] | unique | .[]' \ + ${cfg.qemu.package}/share/qemu/firmware/* \ + ) /run/${dirName}/nix-ovmf # Symlink hooks to /var/lib/libvirt ${concatStringsSep "\n" ( @@ -620,7 +603,7 @@ in in [ "L+ /var/lib/qemu/vhost-user - - - - ${vhostUserCollection}/share/qemu/vhost-user" - "L+ /var/lib/qemu/firmware - - - - ${cfg.qemu.package}/share/qemu/firmware" + "L+ /var/lib/qemu/firmware - - - - ${qemuOvmfMetadata}" ]; security.polkit = { diff --git a/nixos/modules/virtualisation/nixos-containers.nix b/nixos/modules/virtualisation/nixos-containers.nix index d95ab944acd8..b2c61f3da867 100644 --- a/nixos/modules/virtualisation/nixos-containers.nix +++ b/nixos/modules/virtualisation/nixos-containers.nix @@ -509,13 +509,25 @@ in boot.isContainer = mkOption { type = types.bool; - default = false; + default = config.boot.isNspawnContainer; + defaultText = "config.boot.isNspawnContainer"; description = '' Whether this NixOS machine is a lightweight container running in another NixOS system. ''; }; + boot.isNspawnContainer = mkOption { + type = types.bool; + default = false; + description = '' + Whether the machine is running in an nspawn container. This + option is added because [](#opt-boot.isContainer) is heavily used + for non-nspawn environments as well, hence nspawn-specific settings + are guarded by this option. + ''; + }; + boot.enableContainers = mkOption { type = types.bool; default = config.containers != { }; @@ -558,7 +570,7 @@ in { inherit (host.pkgs.stdenv) hostPlatform; } else { localSystem = host.pkgs.stdenv.hostPlatform; }; - boot.isContainer = true; + boot.isNspawnContainer = true; networking.hostName = mkDefault name; networking.useDHCP = false; assertions = [ diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 0a763fb5a5ea..4f5eb133208b 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -750,6 +750,7 @@ in iosched = runTest ./iosched.nix; ipget = runTest ./ipget.nix; ipv6 = runTest ./ipv6.nix; + irqbalance = runTest ./irqbalance.nix; iscsi-multipath-root = runTest ./iscsi-multipath-root.nix; iscsi-root = runTest ./iscsi-root.nix; isolate = runTest ./isolate.nix; diff --git a/nixos/tests/irqbalance.nix b/nixos/tests/irqbalance.nix new file mode 100644 index 000000000000..39dbf218ef7d --- /dev/null +++ b/nixos/tests/irqbalance.nix @@ -0,0 +1,29 @@ +{ pkgs, lib, ... }: +{ + name = "irqbalance"; + meta.maintainers = with lib.maintainers; [ h7x4 ]; + + nodes.machine = + { config, ... }: + { + virtualisation.cores = 2; + services.irqbalance.enable = true; + + systemd.services.irqbalance.serviceConfig.ExecStart = [ + "" + "${lib.getExe config.services.irqbalance.package} --journal --debug" + ]; + }; + + testScript = '' + machine.wait_for_unit("irqbalance.service") + + machine.wait_until_succeeds("journalctl -u irqbalance.service --grep='Package 0'") + + unmanaged_irq_count = machine.succeed("journalctl -u irqbalance.service -o cat --grep 'affinity is now unmanaged' | sort -u | wc -l") + + # The number of unmanaged IRQs is not entirely stable, but there is likely something + # wrong if any more that 2 queues are unmanaged + assert int(unmanaged_irq_count) <= 2 + ''; +} diff --git a/nixos/tests/systemd-machinectl.nix b/nixos/tests/systemd-machinectl.nix index 6a3a47d938bc..8238bcea3f3a 100644 --- a/nixos/tests/systemd-machinectl.nix +++ b/nixos/tests/systemd-machinectl.nix @@ -5,7 +5,7 @@ let { config, ... }: { # We re-use the NixOS container option ... - boot.isContainer = true; + boot.isNspawnContainer = true; # ... and revert unwanted defaults networking.useHostResolvConf = false; @@ -98,11 +98,6 @@ in serviceConfig.Environment = [ # Disable tmpfs for /tmp "SYSTEMD_NSPAWN_TMPFS_TMP=0" - - # force unified cgroup delegation, which would be the default - # if systemd could check the capabilities of the installed systemd. - # see also: https://github.com/NixOS/nixpkgs/pull/198526 - "SYSTEMD_NSPAWN_UNIFIED_HIERARCHY=1" ]; overrideStrategy = "asDropin"; }; @@ -152,7 +147,7 @@ in # Test if systemd-nspawn provides a working environment for nix to build derivations # https://nixos.org/guides/nix-pills/07-working-derivation - machine.succeed('systemd-run --pty --wait -M ${containerName} /run/current-system/sw/bin/nix-instantiate --expr \'derivation { name = "myname"; builder = "/bin/sh"; args = [ "-c" "echo foo > $out" ]; system = "${pkgs.system}"; }\' --add-root /tmp/drv') + machine.succeed('systemd-run --pty --wait -M ${containerName} /run/current-system/sw/bin/nix-instantiate --expr \'derivation { name = "myname"; builder = "/bin/sh"; args = [ "-c" "echo foo > $out" ]; system = "${pkgs.stdenv.hostPlatform.system}"; }\' --add-root /tmp/drv') machine.succeed('systemd-run --pty --wait -M ${containerName} /run/current-system/sw/bin/nix-store --option substitute false --realize /tmp/drv') # Test nss_mymachines without nscd diff --git a/pkgs/README.md b/pkgs/README.md index 409ab906f556..55c28934440f 100644 --- a/pkgs/README.md +++ b/pkgs/README.md @@ -501,6 +501,8 @@ The `meta` attribute set should always be placed last in the derivativion and an * `meta.license` must be set and match the upstream license. * If there is no upstream license, `meta.license` should default to `lib.licenses.unfree`. * If in doubt, try to contact the upstream developers for clarification. +* `meta.sourceProvenance` must be set if the package is not built from source. + * If you are repackaging a `.deb`, `.rpm`, `.whl`, or any other format provided by your upstream, this should almost always be set to `lib.sourceTypes.binaryNativeCode`. * `meta.mainProgram` must be set to the name of the executable which facilitates the primary function or purpose of the package, if there is such an executable in `$bin/bin/` (or `$out/bin/`, if there is no `"bin"` output). * Packages that only have a single executable in the applicable directory above should set `meta.mainProgram`. For example, the package `ripgrep` only has a single executable `rg` under `$out/bin/`, so `ripgrep.meta.mainProgram` is set to `"rg"`. diff --git a/pkgs/applications/audio/clementine/default.nix b/pkgs/applications/audio/clementine/default.nix index 392b95f9dc74..2e886cb44a12 100644 --- a/pkgs/applications/audio/clementine/default.nix +++ b/pkgs/applications/audio/clementine/default.nix @@ -49,13 +49,13 @@ let in stdenv.mkDerivation (finalAttrs: { pname = "clementine"; - version = "1.4.1-55-g03726250a"; + version = "1.4.1-58-gbae968a2f"; src = fetchFromGitHub { owner = "clementine-player"; repo = "Clementine"; tag = finalAttrs.version; - hash = "sha256-tfXZH3E9VZUVnGbKYIWln76fJNwDvc+H4IGDL5U+3pI="; + hash = "sha256-Ni+nbi0bADIPo9rPtt06loJ3MNU+y9bs1EZSenLfJSU="; }; nativeBuildInputs = [ diff --git a/pkgs/applications/editors/vim/plugins/generated.nix b/pkgs/applications/editors/vim/plugins/generated.nix index 6ac9e4c18997..66d1b08b4b25 100644 --- a/pkgs/applications/editors/vim/plugins/generated.nix +++ b/pkgs/applications/editors/vim/plugins/generated.nix @@ -3052,6 +3052,19 @@ final: prev: { meta.hydraPlatforms = [ ]; }; + codecompanion-lualine-nvim = buildVimPlugin { + pname = "codecompanion-lualine.nvim"; + version = "2025-07-12"; + src = fetchFromGitHub { + owner = "franco-ruggeri"; + repo = "codecompanion-lualine.nvim"; + rev = "b264433444715bf07ee9f7d5015086b927ccf7f1"; + sha256 = "1s7rr1jwgfdr6gnf26cv9pws3jkhgblrpq48yryvfyd3wc8qii93"; + }; + meta.homepage = "https://github.com/franco-ruggeri/codecompanion-lualine.nvim/"; + meta.hydraPlatforms = [ ]; + }; + codecompanion-nvim = buildVimPlugin { pname = "codecompanion.nvim"; version = "2025-10-02"; @@ -3065,6 +3078,19 @@ final: prev: { meta.hydraPlatforms = [ ]; }; + codecompanion-spinner-nvim = buildVimPlugin { + pname = "codecompanion-spinner.nvim"; + version = "2025-09-11"; + src = fetchFromGitHub { + owner = "franco-ruggeri"; + repo = "codecompanion-spinner.nvim"; + rev = "c1fa2a84ea1aed687aaed60df65e347c280f4f22"; + sha256 = "05cyf6wnzfj7jdyd2ppfs2r5i3mld2h4lwsfjm5qkn9lc70samps"; + }; + meta.homepage = "https://github.com/franco-ruggeri/codecompanion-spinner.nvim/"; + meta.hydraPlatforms = [ ]; + }; + codewindow-nvim = buildVimPlugin { pname = "codewindow.nvim"; version = "2025-05-22"; diff --git a/pkgs/applications/editors/vim/plugins/vim-plugin-names b/pkgs/applications/editors/vim/plugins/vim-plugin-names index 0d6555afa32b..4f4b8c7d5fdb 100644 --- a/pkgs/applications/editors/vim/plugins/vim-plugin-names +++ b/pkgs/applications/editors/vim/plugins/vim-plugin-names @@ -233,6 +233,8 @@ https://github.com/iamcco/coc-tailwindcss/,, https://github.com/neoclide/coc.nvim/,release, https://github.com/manicmaniac/coconut.vim/,HEAD, https://github.com/ravitemer/codecompanion-history.nvim/,HEAD, +https://github.com/franco-ruggeri/codecompanion-lualine.nvim/,HEAD, +https://github.com/franco-ruggeri/codecompanion-spinner.nvim/,HEAD, https://github.com/olimorris/codecompanion.nvim/,HEAD, https://github.com/gorbit99/codewindow.nvim/,HEAD, https://github.com/metakirby5/codi.vim/,, diff --git a/pkgs/applications/editors/vscode/extensions/default.nix b/pkgs/applications/editors/vscode/extensions/default.nix index 6496543fdad1..cf9385c81345 100644 --- a/pkgs/applications/editors/vscode/extensions/default.nix +++ b/pkgs/applications/editors/vscode/extensions/default.nix @@ -2348,8 +2348,8 @@ let mktplcRef = { name = "Ionide-fsharp"; publisher = "Ionide"; - version = "7.27.1"; - hash = "sha256-ur+/ZSewWBzLxkHVXHQJg4KzkC3Mi3E9fE3/wL6sD8g="; + version = "7.28.0"; + hash = "sha256-d6AucdoKeVAobTj1cbELce2vcXsZW5TX74mkcnHPtkA="; }; meta = { changelog = "https://marketplace.visualstudio.com/items/Ionide.Ionide-fsharp/changelog"; diff --git a/pkgs/applications/networking/cluster/terraform-providers/providers.json b/pkgs/applications/networking/cluster/terraform-providers/providers.json index ac98e9a17248..900b398c7770 100644 --- a/pkgs/applications/networking/cluster/terraform-providers/providers.json +++ b/pkgs/applications/networking/cluster/terraform-providers/providers.json @@ -99,13 +99,13 @@ "vendorHash": "sha256-YIn8akPW+DCVF0eYZxsmJxmrJuYhK4QLG/uhmmrXd4c=" }, "auth0": { - "hash": "sha256-Wv8B28h6idsni7peoKiQ7+5Uo5njw7zeNSRNq3ati8c=", + "hash": "sha256-+Kc0fXO6E4U9NdRjI1VGM7RMuBVvP/5GeU6jpEjLgr0=", "homepage": "https://registry.terraform.io/providers/auth0/auth0", "owner": "auth0", "repo": "terraform-provider-auth0", - "rev": "v1.30.0", + "rev": "v1.31.0", "spdx": "MPL-2.0", - "vendorHash": "sha256-tS+LKp4n1SjCmdrJ0kbxrcUYR53NCsODD9Yiq8B8hok=" + "vendorHash": "sha256-H1RjKU852ovkrdJrhvedbQS835hN0atDNDCtAcGJMBo=" }, "avi": { "hash": "sha256-e8yzc3nRP0ktcuuKyBXydS9NhoceYZKzJcqCWOfaPL0=", @@ -270,13 +270,13 @@ "vendorHash": "sha256-O/MSx6iZ0SkCsMLKMr1cetkPaePoVq62UTOhiPTzF6g=" }, "cloudflare": { - "hash": "sha256-nIceDw766f32yn8qfgY89OYcOtwUc3650x0NO4XUrmk=", + "hash": "sha256-Lc9bC1dM4wNe+ZN2EYFRYfoZosocBEOI9SHvxJIOQCY=", "homepage": "https://registry.terraform.io/providers/cloudflare/cloudflare", "owner": "cloudflare", "repo": "terraform-provider-cloudflare", - "rev": "v5.10.1", + "rev": "v5.11.0", "spdx": "Apache-2.0", - "vendorHash": "sha256-U2lC4d3MSkD8W4qJtrYlnHFflG0xgyPtL6OnjHwxV2U=" + "vendorHash": "sha256-N1vG3U7gxEbVbBax7g6AfHr2Aj1ypVefsEIuvZyLPYQ=" }, "cloudfoundry": { "hash": "sha256-1nYncJLVU/f9WD6Quh9IieIXgixPzbPk4zbtI1zmf9g=", diff --git a/pkgs/applications/video/kodi/addons/formula1/default.nix b/pkgs/applications/video/kodi/addons/formula1/default.nix index c05e72e93f5d..8425005bea04 100644 --- a/pkgs/applications/video/kodi/addons/formula1/default.nix +++ b/pkgs/applications/video/kodi/addons/formula1/default.nix @@ -10,11 +10,11 @@ buildKodiAddon rec { pname = "formula1"; namespace = "plugin.video.formula1"; - version = "2.0.6"; + version = "2.0.7"; src = fetchzip { url = "https://mirrors.kodi.tv/addons/${lib.toLower rel}/${namespace}/${namespace}-${version}.zip"; - sha256 = "sha256-oo5mS99fwMjMi8lUdiGNMOghVLd4dLr4SkoDzObufV4="; + sha256 = "sha256-yz9SB0hiw5JKURGNvAazxazL+bMtfziNXlOLLoGUPOU="; }; propagatedBuildInputs = [ diff --git a/pkgs/by-name/aw/awsebcli/package.nix b/pkgs/by-name/aw/awsebcli/package.nix index cd036c790fa6..951ffa898bce 100644 --- a/pkgs/by-name/aw/awsebcli/package.nix +++ b/pkgs/by-name/aw/awsebcli/package.nix @@ -25,14 +25,14 @@ in python.pkgs.buildPythonApplication rec { pname = "awsebcli"; - version = "3.25"; + version = "3.25.1"; pyproject = true; src = fetchFromGitHub { owner = "aws"; repo = "aws-elastic-beanstalk-cli"; tag = version; - hash = "sha256-RqUVG4aIZDAVuKcT41ODKkyEidmschcFaY24P1CjosU="; + hash = "sha256-objIzpYMyuFjEc85H9dXhQez3MZfNu3lWSWm6+E2iJs="; }; pythonRelaxDeps = [ diff --git a/pkgs/by-name/bi/bitmeter/package.nix b/pkgs/by-name/bi/bitmeter/package.nix deleted file mode 100644 index 98258c12a3c6..000000000000 --- a/pkgs/by-name/bi/bitmeter/package.nix +++ /dev/null @@ -1,44 +0,0 @@ -{ - lib, - stdenv, - autoreconfHook, - fetchurl, - libjack2, - gtk2, - pkg-config, -}: - -stdenv.mkDerivation rec { - pname = "bitmeter"; - version = "1.2"; - - src = fetchurl { - url = "https://devel.tlrmx.org/audio/source/${pname}-${version}.tar.gz"; - sha256 = "09ck2gxqky701dc1p0ip61rrn16v0pdc7ih2hc2sd63zcw53g2a7"; - }; - - nativeBuildInputs = [ - autoreconfHook - pkg-config - ]; - buildInputs = [ - libjack2 - gtk2 - ]; - - patches = [ - (fetchurl { - url = "https://gitweb.gentoo.org/repo/gentoo.git/plain/media-sound/bitmeter/files/bitmeter-1.2-fix-build-system.patch?id=dec60bb6900d6ebdaaa6aa1dcb845b30b739f9b5"; - sha256 = "021mz6933iw7mpk6b9cbjr8naj6smbq1hwqjszlyx72qbwrrid7k"; - }) - ]; - - meta = with lib; { - homepage = "http://devel.tlrmx.org/audio/bitmeter/"; - description = "Also known as jack bitscope. Useful to detect denormals"; - license = licenses.gpl2; - maintainers = [ maintainers.magnetophon ]; - platforms = platforms.linux; - mainProgram = "bitmeter"; - }; -} diff --git a/pkgs/by-name/br/brev-cli/package.nix b/pkgs/by-name/br/brev-cli/package.nix index 1f0a6a6f3f81..6751eabca27c 100644 --- a/pkgs/by-name/br/brev-cli/package.nix +++ b/pkgs/by-name/br/brev-cli/package.nix @@ -6,16 +6,16 @@ buildGoModule rec { pname = "brev-cli"; - version = "0.6.312"; + version = "0.6.314"; src = fetchFromGitHub { owner = "brevdev"; repo = "brev-cli"; rev = "v${version}"; - sha256 = "sha256-IeX+SvNcz0S/gdInVM8fwA7TEDTMoJO8rSwCqK2rKoE="; + sha256 = "sha256-/EzRKmpfQndZFL3c82u0w0V8EH/TFptU3zkHPvsIM6s="; }; - vendorHash = "sha256-7MXZVdpsPHfHk8hNZM2CT0FW8gTKt3oUap7CTVYMNfI="; + vendorHash = "sha256-CzGuEbq4I1ygYQsoyyXC6gDBMLg21dKQTKkrbwpAR2U="; env.CGO_ENABLED = 0; subPackages = [ "." ]; diff --git a/pkgs/by-name/bu/bundler/package.nix b/pkgs/by-name/bu/bundler/package.nix index 1789ef0c7203..07f1b71d99dc 100644 --- a/pkgs/by-name/bu/bundler/package.nix +++ b/pkgs/by-name/bu/bundler/package.nix @@ -37,7 +37,10 @@ buildRubyGem rec { homepage = "https://bundler.io"; changelog = "https://github.com/rubygems/rubygems/blob/bundler-v${version}/bundler/CHANGELOG.md"; license = lib.licenses.mit; - maintainers = with lib.maintainers; [ anthonyroussel ]; + maintainers = with lib.maintainers; [ + anthonyroussel + guylamar2006 + ]; mainProgram = "bundler"; }; } diff --git a/pkgs/by-name/ca/cage/package.nix b/pkgs/by-name/ca/cage/package.nix index af84ccaea812..842dd037d028 100644 --- a/pkgs/by-name/ca/cage/package.nix +++ b/pkgs/by-name/ca/cage/package.nix @@ -8,7 +8,7 @@ wayland-scanner, scdoc, makeWrapper, - wlroots_0_18, + wlroots_0_19, wayland, wayland-protocols, pixman, @@ -22,13 +22,13 @@ stdenv.mkDerivation (finalAttrs: { pname = "cage"; - version = "0.2.0"; + version = "0.2.1"; src = fetchFromGitHub { owner = "cage-kiosk"; repo = "cage"; tag = "v${finalAttrs.version}"; - hash = "sha256-2SFtz62z0EF8cpFTC6wGi125MD4a5mkXqP/C+7fH+3g="; + hash = "sha256-P9MhIl2YIE2hwT5Yr0Cpes5S12evb0aj9oOPLeehkw0="; }; depsBuildBuild = [ @@ -45,7 +45,7 @@ stdenv.mkDerivation (finalAttrs: { ]; buildInputs = [ - wlroots_0_18 + wlroots_0_19 wayland wayland-protocols pixman @@ -55,7 +55,7 @@ stdenv.mkDerivation (finalAttrs: { libX11 ]; - postFixup = lib.optionalString wlroots_0_18.enableXWayland '' + postFixup = lib.optionalString wlroots_0_19.enableXWayland '' wrapProgram $out/bin/cage --prefix PATH : "${xwayland}/bin" ''; diff --git a/pkgs/by-name/ci/ciel/package.nix b/pkgs/by-name/ci/ciel/package.nix index 06a3f970cb45..f0d957ed52e4 100644 --- a/pkgs/by-name/ci/ciel/package.nix +++ b/pkgs/by-name/ci/ciel/package.nix @@ -16,16 +16,16 @@ rustPlatform.buildRustPackage rec { pname = "ciel"; - version = "3.9.8"; + version = "3.9.10"; src = fetchFromGitHub { owner = "AOSC-Dev"; repo = "ciel-rs"; tag = "v${version}"; - hash = "sha256-swYIy+e+N4MVmNXSttLUWKmG2xj9TA9sWwCrIdo+gIA="; + hash = "sha256-WpP3rwiGXA5oeBZ3wQwSXPmRT5+zUOm2d1HTEdvnHFc="; }; - cargoHash = "sha256-RBtERA9CkTdW++ikHkV1X11hg49IrvVFIdTi1qQp+ok="; + cargoHash = "sha256-zby+QrzX7M714y50j2ZyfXYRhWeAwZbbHZF8KsjS/Hc="; nativeBuildInputs = [ pkg-config diff --git a/pkgs/by-name/co/colmap/openimageio.patch b/pkgs/by-name/co/colmap/openimageio.patch new file mode 100644 index 000000000000..780a3c4ba256 --- /dev/null +++ b/pkgs/by-name/co/colmap/openimageio.patch @@ -0,0 +1,4927 @@ +diff --git a/.github/workflows/build-mac.yml b/.github/workflows/build-mac.yml +index bb4b844d..dbb9eccd 100644 +--- a/.github/workflows/build-mac.yml ++++ b/.github/workflows/build-mac.yml +@@ -48,29 +48,31 @@ jobs: + - name: Setup Mac + run: | + # Fix `brew link` error. +- find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete ++ find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete + ++ brew uninstall cmake # Workaround for CI failures. + brew install \ + cmake \ + ninja \ + boost \ + eigen \ +- freeimage \ ++ openimageio \ + curl \ + metis \ + glog \ + googletest \ + ceres-solver \ +- qt5 \ ++ qt \ + glew \ + cgal \ + sqlite3 \ +- ccache ++ ccache \ ++ libomp + brew link --force libomp + + - name: Configure and build + run: | +- export PATH="/usr/local/opt/qt@5/bin:$PATH" ++ export PATH="/usr/local/opt/qt/bin:$PATH" + cmake --version + mkdir build + cd build +@@ -78,7 +80,7 @@ jobs: + -GNinja \ + -DCMAKE_BUILD_TYPE=${{ matrix.config.cmakeBuildType }} \ + -DTESTS_ENABLED=ON \ +- -DQt5_DIR="$(brew --prefix qt@5)/lib/cmake/Qt5" ++ -DQt6_DIR="$(brew --prefix qt)/lib/cmake/Qt6" + ninja + + - name: Run tests +diff --git a/.github/workflows/build-pycolmap.yml b/.github/workflows/build-pycolmap.yml +index 03cb18b4..6063c215 100644 +--- a/.github/workflows/build-pycolmap.yml ++++ b/.github/workflows/build-pycolmap.yml +@@ -21,9 +21,9 @@ jobs: + strategy: + matrix: + config: [ +- {os: ubuntu-latest}, +- {os: macos-14, arch: arm64, deploymentTarget: 14.0}, +- {os: windows-latest}, ++ {os: ubuntu-24.04}, ++ # {os: macos-14, arch: arm64, deploymentTarget: 14.0}, ++ {os: windows-2025}, + ] + env: + COMPILER_CACHE_VERSION: 1 +diff --git a/.github/workflows/build-ubuntu.yml b/.github/workflows/build-ubuntu.yml +index 617c6c0a..5f2f7fba 100644 +--- a/.github/workflows/build-ubuntu.yml ++++ b/.github/workflows/build-ubuntu.yml +@@ -23,6 +23,7 @@ jobs: + config: [ + { + os: ubuntu-24.04, ++ qtVersion: 6, + cmakeBuildType: RelWithDebInfo, + asanEnabled: false, + guiEnabled: true, +@@ -33,6 +34,7 @@ jobs: + }, + { + os: ubuntu-22.04, ++ qtVersion: 6, + cmakeBuildType: Release, + asanEnabled: false, + guiEnabled: true, +@@ -43,6 +45,7 @@ jobs: + }, + { + os: ubuntu-22.04, ++ qtVersion: 5, + cmakeBuildType: Release, + asanEnabled: false, + guiEnabled: false, +@@ -53,6 +56,7 @@ jobs: + }, + { + os: ubuntu-24.04, ++ qtVersion: 6, + cmakeBuildType: Release, + asanEnabled: true, + guiEnabled: false, +@@ -63,6 +67,7 @@ jobs: + }, + { + os: ubuntu-24.04, ++ qtVersion: 6, + cmakeBuildType: ClangTidy, + asanEnabled: false, + guiEnabled: false, +@@ -125,6 +130,12 @@ jobs: + + - name: Setup Ubuntu + run: | ++ if [ "${{ matrix.config.qtVersion }}" == "5" ]; then ++ qt_packages="qtbase5-dev libqt5opengl5-dev libcgal-qt5-dev" ++ elif [ "${{ matrix.config.qtVersion }}" == "6" ]; then ++ qt_packages="qt6-base-dev libqt6opengl6-dev libqt6openglwidgets6" ++ fi ++ + sudo apt-get update && sudo apt-get install -y \ + build-essential \ + cmake \ +@@ -134,31 +145,29 @@ jobs: + libboost-system-dev \ + libeigen3-dev \ + libceres-dev \ +- libfreeimage-dev \ ++ libopenimageio-dev \ ++ openimageio-tools \ + libmetis-dev \ + libgoogle-glog-dev \ + libgtest-dev \ + libgmock-dev \ + libsqlite3-dev \ + libglew-dev \ +- qtbase5-dev \ +- libqt5opengl5-dev \ ++ $qt_packages \ + libcgal-dev \ +- libcgal-qt5-dev \ + libgl1-mesa-dri \ + libunwind-dev \ + libcurl4-openssl-dev \ + libmkl-full-dev \ + xvfb + ++ # Fix issue in Ubuntu's openimageio CMake config. ++ # We don't depend on any of openimageio's OpenCV functionality, ++ # but it still requires the OpenCV include directory to exist. ++ sudo mkdir -p /usr/include/opencv4 ++ + if [ "${{ matrix.config.cudaEnabled }}" == "true" ]; then +- if [ "${{ matrix.config.os }}" == "ubuntu-20.04" ]; then +- sudo apt-get install -y \ +- nvidia-cuda-toolkit \ +- nvidia-cuda-toolkit-gcc +- echo "CC=/usr/bin/cuda-gcc" >> $GITHUB_ENV +- echo "CXX=/usr/bin/cuda-g++" >> $GITHUB_ENV +- elif [ "${{ matrix.config.os }}" == "ubuntu-22.04" ]; then ++ if [ "${{ matrix.config.os }}" == "ubuntu-22.04" ]; then + sudo apt-get install -y \ + nvidia-cuda-toolkit \ + nvidia-cuda-toolkit-gcc \ +diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml +index bab35e18..0d2433fe 100644 +--- a/.github/workflows/build-windows.yml ++++ b/.github/workflows/build-windows.yml +@@ -22,14 +22,14 @@ jobs: + matrix: + config: [ + { +- os: windows-2022, ++ os: windows-2025, + cmakeBuildType: Release, + cudaEnabled: true, + testsEnabled: true, + exportPackage: true, + }, + { +- os: windows-2022, ++ os: windows-2025, + cmakeBuildType: Release, + cudaEnabled: false, + testsEnabled: true, +@@ -42,7 +42,6 @@ jobs: + COMPILER_CACHE_DIR: ${{ github.workspace }}/compiler-cache + CCACHE_DIR: ${{ github.workspace }}/compiler-cache/ccache + CCACHE_BASEDIR: ${{ github.workspace }} +- VCPKG_COMMIT_ID: 0cb95c860ea83aafc1b24350510b30dec535989a + GLOG_v: 2 + GLOG_logtostderr: 1 + CUDA_MAJOR_VERSION: 12 +@@ -51,7 +50,7 @@ jobs: + + steps: + - uses: actions/checkout@v4 +- ++ + # We define the vcpkg binary sources using separate variables for read and + # write operations: + # * Read sources are defined as inline. These can be read by anyone and, +@@ -82,7 +81,7 @@ jobs: + key: v${{ env.COMPILER_CACHE_VERSION }}-${{ matrix.config.os }}-${{ matrix.config.cmakeBuildType }}-${{ matrix.config.asanEnabled }}--${{ matrix.config.cudaEnabled }}-${{ github.run_id }}-${{ github.run_number }} + restore-keys: v${{ env.COMPILER_CACHE_VERSION }}-${{ matrix.config.os }}-${{ matrix.config.cmakeBuildType }}-${{ matrix.config.asanEnabled }}--${{ matrix.config.cudaEnabled }} + path: ${{ env.COMPILER_CACHE_DIR }} +- ++ + - name: Install ccache + shell: pwsh + run: | +@@ -109,7 +108,6 @@ jobs: + cd ${{ github.workspace }} + git clone https://github.com/microsoft/vcpkg + cd vcpkg +- git reset --hard ${{ env.VCPKG_COMMIT_ID }} + ./bootstrap-vcpkg.bat + + - name: Install CMake and Ninja +@@ -166,7 +164,7 @@ jobs: + ../vcpkg/vcpkg.exe export --raw --output-dir vcpkg_export --output colmap + cp vcpkg_export/colmap/installed/x64-windows/bin/*.dll install/bin + cp vcpkg_export/colmap/installed/x64-windows-release/bin/*.dll install/bin +- cp -r vcpkg_export/colmap/installed/x64-windows/plugins install ++ cp -r vcpkg_export/colmap/installed/x64-windows/Qt6/plugins install + if ($${{ matrix.config.cudaEnabled }}) { + cp "${{ steps.cuda-toolkit.outputs.CUDA_PATH }}/bin/cudart64_*.dll" install/bin + cp "${{ steps.cuda-toolkit.outputs.CUDA_PATH }}/bin/curand64_*.dll" install/bin +diff --git a/cmake/FindDependencies.cmake b/cmake/FindDependencies.cmake +index a0c3ff41..8833f115 100644 +--- a/cmake/FindDependencies.cmake ++++ b/cmake/FindDependencies.cmake +@@ -27,7 +27,7 @@ find_package(Boost ${COLMAP_FIND_TYPE} COMPONENTS + + find_package(Eigen3 ${COLMAP_FIND_TYPE}) + +-find_package(FreeImage ${COLMAP_FIND_TYPE}) ++find_package(OpenImageIO ${COLMAP_FIND_TYPE}) + + find_package(Metis ${COLMAP_FIND_TYPE}) + +@@ -88,7 +88,7 @@ endif() + if(DOWNLOAD_ENABLED) + # The OpenSSL package in vcpkg seems broken under Windows and leads to + # missing certificate verification when connecting to SSL servers. We +- # therefore use curl[schannel] (i.e., native Windows SSL/TLS) under Windows ++ # therefore use curl[sspi] (i.e., native Windows SSL/TLS) under Windows + # and curl[openssl] otherwise. + find_package(CURL QUIET) + set(CRYPTO_FOUND FALSE) +@@ -156,7 +156,7 @@ if(CUDA_ENABLED) + + declare_imported_cuda_target(cudart ${CUDA_LIBRARIES}) + declare_imported_cuda_target(curand ${CUDA_LIBRARIES}) +- ++ + set(CUDAToolkit_VERSION "${CUDA_VERSION_STRING}") + set(CUDAToolkit_BIN_DIR "${CUDA_TOOLKIT_ROOT_DIR}/bin") + else() +@@ -198,11 +198,19 @@ else() + endif() + + if(GUI_ENABLED) +- find_package(Qt5 5.4 ${COLMAP_FIND_TYPE} COMPONENTS Core OpenGL Widgets) ++ find_package(QT NAMES Qt5 Qt6 REQUIRED) ++ set(COLMAP_QT_COMPONENTS Core OpenGL Widgets) ++ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) ++ list(APPEND COLMAP_QT_COMPONENTS OpenGLWidgets) ++ endif() ++ find_package(Qt${QT_VERSION_MAJOR} ${COLMAP_FIND_TYPE} ${COLMAP_QT_COMPONENTS}) + message(STATUS "Found Qt") +- message(STATUS " Module : ${Qt5Core_DIR}") +- message(STATUS " Module : ${Qt5OpenGL_DIR}") +- message(STATUS " Module : ${Qt5Widgets_DIR}") ++ message(STATUS " Module : ${Qt${QT_VERSION_MAJOR}Core_DIR}") ++ message(STATUS " Module : ${Qt${QT_VERSION_MAJOR}OpenGL_DIR}") ++ message(STATUS " Module : ${Qt${QT_VERSION_MAJOR}Widgets_DIR}") ++ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) ++ message(STATUS " Module : ${Qt${QT_VERSION_MAJOR}OpenGLWidgets_DIR}") ++ endif() + if(Qt5_FOUND) + # Qt5 was built with -reduce-relocations. + if(Qt5_POSITION_INDEPENDENT_CODE) +@@ -218,13 +226,15 @@ if(GUI_ENABLED) + endif() + endif() + endif() ++ endif() + ++ if(QT_FOUND) + # Enable automatic compilation of Qt resource files. + set(CMAKE_AUTORCC ON) + endif() + endif() + +-if(GUI_ENABLED AND Qt5_FOUND) ++if(GUI_ENABLED AND Qt${QT_VERSION_MAJOR}_FOUND) + list(APPEND COLMAP_COMPILE_DEFINITIONS COLMAP_GUI_ENABLED) + message(STATUS "Enabling GUI support") + else() +diff --git a/cmake/FindFreeImage.cmake b/cmake/FindFreeImage.cmake +deleted file mode 100644 +index cf213cf2..00000000 +--- a/cmake/FindFreeImage.cmake ++++ /dev/null +@@ -1,104 +0,0 @@ +-# Copyright (c), ETH Zurich and UNC Chapel Hill. +-# All rights reserved. +-# +-# Redistribution and use in source and binary forms, with or without +-# modification, are permitted provided that the following conditions are met: +-# +-# * Redistributions of source code must retain the above copyright +-# notice, this list of conditions and the following disclaimer. +-# +-# * Redistributions in binary form must reproduce the above copyright +-# notice, this list of conditions and the following disclaimer in the +-# documentation and/or other materials provided with the distribution. +-# +-# * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of +-# its contributors may be used to endorse or promote products derived +-# from this software without specific prior written permission. +-# +-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE +-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +-# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +-# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +-# POSSIBILITY OF SUCH DAMAGE. +- +- +-# Find package module for FreeImage library. +-# +-# The following variables are set by this module: +-# +-# FREEIMAGE_FOUND: TRUE if FreeImage is found. +-# freeimage::FreeImage: Imported target to link against. +-# +-# The following variables control the behavior of this module: +-# +-# FREEIMAGE_INCLUDE_DIR_HINTS: List of additional directories in which to +-# search for FreeImage includes. +-# FREEIMAGE_LIBRARY_DIR_HINTS: List of additional directories in which to +-# search for FreeImage libraries. +- +-set(FREEIMAGE_INCLUDE_DIR_HINTS "" CACHE PATH "FreeImage include directory") +-set(FREEIMAGE_LIBRARY_DIR_HINTS "" CACHE PATH "FreeImage library directory") +- +-unset(FREEIMAGE_FOUND) +- +-find_package(FreeImage CONFIG QUIET) +-if(FreeImage_FOUND) +- if(TARGET freeimage::FreeImage) +- set(FREEIMAGE_FOUND TRUE) +- message(STATUS "Found FreeImage") +- message(STATUS " Target : freeimage::FreeImage") +- endif() +-else() +- list(APPEND FREEIMAGE_CHECK_INCLUDE_DIRS +- ${FREEIMAGE_INCLUDE_DIR_HINTS} +- /usr/include +- /usr/local/include +- /opt/include +- /opt/local/include +- ) +- +- list(APPEND FREEIMAGE_CHECK_LIBRARY_DIRS +- ${FREEIMAGE_LIBRARY_DIR_HINTS} +- /usr/lib +- /usr/local/lib +- /opt/lib +- /opt/local/lib +- ) +- +- find_path(FREEIMAGE_INCLUDE_DIRS +- NAMES +- FreeImage.h +- PATHS +- ${FREEIMAGE_CHECK_INCLUDE_DIRS}) +- find_library(FREEIMAGE_LIBRARIES +- NAMES +- freeimage +- PATHS +- ${FREEIMAGE_CHECK_LIBRARY_DIRS}) +- +- if(FREEIMAGE_INCLUDE_DIRS AND FREEIMAGE_LIBRARIES) +- set(FREEIMAGE_FOUND TRUE) +- endif() +- +- if(FREEIMAGE_FOUND) +- message(STATUS "Found FreeImage") +- message(STATUS " Includes : ${FREEIMAGE_INCLUDE_DIRS}") +- message(STATUS " Libraries : ${FREEIMAGE_LIBRARIES}") +- endif() +- +- add_library(freeimage::FreeImage INTERFACE IMPORTED) +- target_include_directories( +- freeimage::FreeImage INTERFACE ${FREEIMAGE_INCLUDE_DIRS}) +- target_link_libraries( +- freeimage::FreeImage INTERFACE ${FREEIMAGE_LIBRARIES}) +-endif() +- +-if(NOT FREEIMAGE_FOUND AND FREEIMAGE_FIND_REQUIRED) +- message(FATAL_ERROR "Could not find FreeImage") +-endif() +diff --git a/cmake/colmap-config.cmake.in b/cmake/colmap-config.cmake.in +index 250dfbc6..73ff530c 100644 +--- a/cmake/colmap-config.cmake.in ++++ b/cmake/colmap-config.cmake.in +@@ -43,9 +43,6 @@ set(COLMAP_FOUND FALSE) + + # Set hints for finding dependency packages. + +-set(FREEIMAGE_INCLUDE_DIR_HINTS @FREEIMAGE_INCLUDE_DIR_HINTS@) +-set(FREEIMAGE_LIBRARY_DIR_HINTS @FREEIMAGE_LIBRARY_DIR_HINTS@) +- + set(METIS_INCLUDE_DIR_HINTS @METIS_INCLUDE_DIR_HINTS@) + set(METIS_LIBRARY_DIR_HINTS @METIS_LIBRARY_DIR_HINTS@) + +diff --git a/doc/cli.rst b/doc/cli.rst +index ce6c3068..24ed0861 100644 +--- a/doc/cli.rst ++++ b/doc/cli.rst +@@ -166,7 +166,7 @@ the available options, e.g.:: + Options can either be specified via command-line or by defining + them in a .ini project file passed to ``--project_path``. + +- -h [ --help ] ++ -h [ --help ] + --default_random_seed arg (=0) + --log_to_stderr arg (=1) + --log_level arg (=0) +@@ -187,10 +187,10 @@ the available options, e.g.:: + --ImageReader.default_focal_length_factor arg (=1.2) + --ImageReader.camera_mask_path arg + --FeatureExtraction.type arg (=SIFT) ++ --FeatureExtraction.max_image_size arg (=3200) + --FeatureExtraction.num_threads arg (=-1) + --FeatureExtraction.use_gpu arg (=1) + --FeatureExtraction.gpu_index arg (=-1) +- --SiftExtraction.max_image_size arg (=3200) + --SiftExtraction.max_num_features arg (=8192) + --SiftExtraction.first_octave arg (=-1) + --SiftExtraction.num_octaves arg (=4) +diff --git a/doc/faq.rst b/doc/faq.rst +index 4611e63f..f73b05ed 100644 +--- a/doc/faq.rst ++++ b/doc/faq.rst +@@ -121,7 +121,7 @@ Example of images.txt:: + + 4 0.698777 0.714625 -0.023996 0.021129 -0.048184 0.004529 -0.313427 2 image0004.png + +-Each image above must have the same ``image_id`` (first column) as in the database (next step). ++Each image above must have the same ``image_id`` (first column) as in the database (next step). + This database can be inspected either in the GUI (under ``Database management > Processing``), + or, one can create a reconstruction with colmap and later export it as text in order to see + the images.txt file it creates. +@@ -217,9 +217,9 @@ camera centers of a subset or all registered images. The 3D similarity + transformation between the reconstructed model and the target coordinate frame + of the geo-registration is determined from these correspondences. + +-The geo-registered 3D coordinates can either be extracted from the database +-(tvec_prior field) or from a user specified text file. +-For text-files, the geo-registered 3D coordinates of the camera centers for ++The geo-registered 3D coordinates can either be extracted from the database ++(tvec_prior field) or from a user specified text file. ++For text-files, the geo-registered 3D coordinates of the camera centers for + images must be specified with the following format:: + + image_name1.jpg X1 Y1 Z1 +@@ -232,7 +232,7 @@ In case of GPS coordinates, a conversion will be performed to turn those into + cartesian coordinates. The conversion can be done from GPS to ECEF + (Earth-Centered-Earth-Fixed) or to ENU (East-North-Up) coordinates. If ENU coordinates + are used, the first image GPS coordinates will define the origin of the ENU frame. +-It is also possible to use ECEF coordinates for alignment and then rotate the aligned ++It is also possible to use ECEF coordinates for alignment and then rotate the aligned + reconstruction into the ENU plane. + + Note that at least 3 images must be specified to estimate a 3D similarity +@@ -344,7 +344,7 @@ extraction step). But note that this might result in a significant slow-down of + the reconstruction pipeline. Please, also note that feature extraction on the + CPU can consume excessive RAM for large images in the default settings, which + might require manually reducing the maximum image size using +-``--SiftExtraction.max_image_size`` and/or setting ++``--FeatureExtraction.max_image_size`` and/or setting + ``--SiftExtraction.first_octave 0`` or by manually limiting the number of + threads using ``--FeatureExtraction.num_threads``. + +diff --git a/doc/install.rst b/doc/install.rst +index 505e2516..1cc3c6cb 100755 +--- a/doc/install.rst ++++ b/doc/install.rst +@@ -81,19 +81,30 @@ Dependencies from the default Ubuntu repositories:: + libboost-graph-dev \ + libboost-system-dev \ + libeigen3-dev \ +- libfreeimage-dev \ ++ libopenimageio-dev \ ++ openimageio-tools \ + libmetis-dev \ + libgoogle-glog-dev \ + libgtest-dev \ + libgmock-dev \ + libsqlite3-dev \ + libglew-dev \ +- qtbase5-dev \ +- libqt5opengl5-dev \ ++ qt6-base-dev \ ++ libqt6opengl6-dev \ ++ libqt6openglwidgets6 \ + libcgal-dev \ + libceres-dev \ + libcurl4-openssl-dev \ ++ libssl-dev \ + libmkl-full-dev ++ # Fix issue in Ubuntu's openimageio CMake config. ++ # We don't depend on any of openimageio's OpenCV functionality, ++ # but it still requires the OpenCV include directory to exist. ++ sudo mkdir -p /usr/include/opencv4 ++ ++Alternatively, you can also build against Qt 5 instead of Qt 6 using:: ++ ++ qtbase5-dev libqt5opengl5-dev + + To compile with **CUDA support**, also install Ubuntu's default CUDA package:: + +@@ -121,11 +132,6 @@ Run COLMAP:: + colmap -h + colmap gui + +-Under **Ubuntu 18.04**, the CMake configuration scripts of CGAL are broken and +-you must also install the CGAL Qt5 package:: +- +- sudo apt-get install libcgal-qt5-dev +- + Under **Ubuntu 22.04**, there is a problem when compiling with Ubuntu's default + CUDA package and GCC, and you must compile against GCC 10:: + +@@ -150,14 +156,14 @@ Dependencies from `Homebrew `__:: + ninja \ + boost \ + eigen \ +- freeimage \ ++ openimageio \ + curl \ + libomp \ + metis \ + glog \ + googletest \ + ceres-solver \ +- qt5 \ ++ qt \ + glew \ + cgal \ + sqlite3 +@@ -169,18 +175,15 @@ Configure and compile COLMAP:: + cd colmap + mkdir build + cd build +- cmake .. \ +- -GNinja \ +- -DQt5_DIR="$(brew --prefix qt@5)/lib/cmake/Qt5" ++ cmake -GNinja + ninja + sudo ninja install + +-If you have Qt 6 installed on your system as well, you might have to temporarily ++If you have Qt 5 installed on your system as well, you might have to temporarily + link your Qt 5 installation while configuring CMake:: + +- brew link qt5 +- cmake ... (from previous code block) +- brew unlink qt5 ++ brew unlink qt && brew link --force qt ++ cmake ... + + Run COLMAP:: + +@@ -329,7 +332,7 @@ with the source code ``hello_world.cc``:: + } + + Then compile and run your code as:: +- ++ + mkdir build + cd build + export colmap_DIR=${CMAKE_INSTALL_PREFIX}/share/colmap +diff --git a/doc/pycolmap/index.rst b/doc/pycolmap/index.rst +index f532102e..2048f78e 100644 +--- a/doc/pycolmap/index.rst ++++ b/doc/pycolmap/index.rst +@@ -27,7 +27,7 @@ from source, follow these steps: + * On Windows, after installing COLMAP via VCPKG, run in powershell:: + + python -m pip install . ` +- --cmake.define.CMAKE_TOOLCHAIN_FILE="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" ` ++ --cmake.define.CMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" ` + --cmake.define.VCPKG_TARGET_TRIPLET="x64-windows" + + Some features, such as cost functions, require that `PyCeres +diff --git a/doc/tutorial.rst b/doc/tutorial.rst +index 939b462e..70edc085 100755 +--- a/doc/tutorial.rst ++++ b/doc/tutorial.rst +@@ -163,14 +163,13 @@ Data Structure + + COLMAP assumes that all input images are in one input directory with potentially + nested sub-directories. It recursively considers all images stored in this +-directory, and it supports various different image formats (see `FreeImage +-`_). Other files are +-automatically ignored. If high performance is a requirement, then you should +-separate any files that are not images. Images are identified uniquely by their +-relative file path. For later processing, such as image undistortion or dense +-reconstruction, the relative folder structure should be preserved. COLMAP does +-not modify the input images or directory and all extracted data is stored in a +-single, self-contained SQLite database file (see :doc:`database`). ++directory, and it supports various different image formats by OpenImageIO. Other ++files are automatically ignored. If high performance is a requirement, then you ++should separate any files that are not images. Images are identified uniquely by ++their relative file path. For later processing, such as image undistortion or ++dense reconstruction, the relative folder structure should be preserved. COLMAP ++does not modify the input images or directory and all extracted data is stored ++in a single, self-contained SQLite database file (see :doc:`database`). + + The first step is to start the graphical user interface of COLMAP by running the + pre-built binaries (Windows: ``COLMAP.bat``, Mac: ``COLMAP.app``) or by executing +diff --git a/docker/Dockerfile b/docker/Dockerfile +index d1a339cc..1c62bccf 100644 +--- a/docker/Dockerfile ++++ b/docker/Dockerfile +@@ -24,20 +24,28 @@ RUN apt-get update && \ + libboost-graph-dev \ + libboost-system-dev \ + libeigen3-dev \ +- libfreeimage-dev \ ++ libopenimageio-dev \ ++ openimageio-tools \ + libmetis-dev \ + libgoogle-glog-dev \ + libgtest-dev \ + libgmock-dev \ + libsqlite3-dev \ + libglew-dev \ +- qtbase5-dev \ +- libqt5opengl5-dev \ ++ qt6-base-dev \ ++ libqt6opengl6-dev \ ++ libqt6openglwidgets6 \ + libcgal-dev \ + libceres-dev \ + libcurl4-openssl-dev \ ++ libssl-dev \ + libmkl-full-dev + ++# Fix issue in Ubuntu's openimageio CMake config. ++# We don't depend on any of openimageio's OpenCV functionality, ++# but it still requires the OpenCV include directory to exist. ++RUN mkdir -p /usr/include/opencv4 ++ + # Build and install COLMAP. + RUN git clone https://github.com/colmap/colmap.git + RUN cd colmap && \ +@@ -68,15 +76,17 @@ RUN apt-get update && \ + libopengl0 \ + libmetis5 \ + libceres4t64 \ +- libfreeimage3 \ ++ libopenimageio2.4t64 \ + libgcc-s1 \ + libgl1 \ + libglew2.2 \ + libgoogle-glog0v6t64 \ +- libqt5core5a \ +- libqt5gui5 \ +- libqt5widgets5 \ ++ libqt6core6 \ ++ libqt6gui6 \ ++ libqt6widgets6 \ ++ libqt6openglwidgets6 \ + libcurl4 \ ++ libssl3t64 \ + libmkl-locale \ + libmkl-intel-lp64 \ + libmkl-intel-thread \ +diff --git a/pyproject.toml b/pyproject.toml +index 0afede3b..9a2922d2 100644 +--- a/pyproject.toml ++++ b/pyproject.toml +@@ -1,7 +1,7 @@ + [build-system] + requires = [ + "scikit-build-core>=0.3.3", +- "pybind11==3.0.0", ++ "pybind11==3.0.1", + "pybind11_stubgen @ git+https://github.com/sarlinpe/pybind11-stubgen@sarlinpe/fix-2025-08-20", + "numpy", + "ruff==0.12.7", +@@ -44,9 +44,6 @@ archs = ["auto64"] + test-requires = "pytest mypy==1.17.0 enlighten==1.13.0" + test-command = "python -c \"import pycolmap; print(pycolmap.__version__)\" && python -m mypy --package pycolmap --implicit-optional && pytest {project}/python/examples/custom_incremental_pipeline_test.py" + +-[tool.cibuildwheel.environment] +-VCPKG_COMMIT_ID = "0cb95c860ea83aafc1b24350510b30dec535989a" +- + [tool.cibuildwheel.linux] + before-all = "{project}/python/ci/install-colmap-almalinux.sh" + +diff --git a/python/README.md b/python/README.md +index e0dfda95..6a889454 100644 +--- a/python/README.md ++++ b/python/README.md +@@ -28,7 +28,7 @@ python -m pip install . + - On Windows, after installing COLMAP [via VCPKG](https://colmap.github.io/install.html#id3), run in powershell: + ```powershell + python -m pip install . ` +- --cmake.define.CMAKE_TOOLCHAIN_FILE="$VCPKG_INSTALLATION_ROOT/scripts/buildsystems/vcpkg.cmake" ` ++ --cmake.define.CMAKE_TOOLCHAIN_FILE="$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" ` + --cmake.define.VCPKG_TARGET_TRIPLET="x64-windows" + ``` + +diff --git a/python/ci/install-colmap-almalinux.sh b/python/ci/install-colmap-almalinux.sh +index a93393b8..4adfb7e0 100755 +--- a/python/ci/install-colmap-almalinux.sh ++++ b/python/ci/install-colmap-almalinux.sh +@@ -38,7 +38,6 @@ export PATH="${COMPILER_TOOLS_DIR}:${PATH}" + # Setup vcpkg + git clone https://github.com/microsoft/vcpkg ${VCPKG_INSTALLATION_ROOT} + cd ${VCPKG_INSTALLATION_ROOT} +-git checkout ${VCPKG_COMMIT_ID} + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + +diff --git a/python/ci/install-colmap-macos.sh b/python/ci/install-colmap-macos.sh +index 7c403ce3..c688f2ba 100755 +--- a/python/ci/install-colmap-macos.sh ++++ b/python/ci/install-colmap-macos.sh +@@ -5,7 +5,7 @@ CURRDIR=$(pwd) + # Fix `brew link` error. + find /usr/local/bin -lname '*/Library/Frameworks/Python.framework/*' -delete + +-brew update ++brew uninstall cmake # Workaround for CI failures. + brew install git cmake ninja gfortran ccache libomp + brew link --force libomp + +@@ -17,7 +17,6 @@ ln -sf $(which gfortran-14) "$(dirname $(which gfortran-14))/gfortran" + # Setup vcpkg + git clone https://github.com/microsoft/vcpkg ${VCPKG_INSTALLATION_ROOT} + cd ${VCPKG_INSTALLATION_ROOT} +-git checkout ${VCPKG_COMMIT_ID} + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + +diff --git a/python/ci/install-colmap-windows.ps1 b/python/ci/install-colmap-windows.ps1 +index 7ccb763b..5653d177 100755 +--- a/python/ci/install-colmap-windows.ps1 ++++ b/python/ci/install-colmap-windows.ps1 +@@ -12,12 +12,11 @@ If (!(Test-Path -path "${COMPILER_TOOLS_DIR}/ccache.exe" -PathType Leaf)) { + cd ${CURRDIR} + git clone https://github.com/microsoft/vcpkg ${env:VCPKG_INSTALLATION_ROOT} + cd ${env:VCPKG_INSTALLATION_ROOT} +-git checkout "${env:VCPKG_COMMIT_ID}" + ./bootstrap-vcpkg.bat + + cd ${CURRDIR} + & "./scripts/shell/enter_vs_dev_shell.ps1" +-& "${env:VCPKG_INSTALLATION_ROOT}/vcpkg.exe" integrate install ++& "${env:VCPKG_ROOT}/vcpkg.exe" integrate install + + # Build COLMAP + mkdir build +diff --git a/python/ci/test-colmap-windows.ps1 b/python/ci/test-colmap-windows.ps1 +index bf1bfd67..3cfc6eed 100644 +--- a/python/ci/test-colmap-windows.ps1 ++++ b/python/ci/test-colmap-windows.ps1 +@@ -1,4 +1,4 @@ +-& "./scripts/shell/enter_vs_dev_shell.ps1" +-& "${env:VCPKG_INSTALLATION_ROOT}/vcpkg.exe" integrate install ++& "$PSScriptRoot/../../scripts/shell/enter_vs_dev_shell.ps1" ++& "${env:VCPKG_ROOT}/vcpkg.exe" integrate install + + & python -c "import pycolmap; print(pycolmap.__version__)" +diff --git a/python/examples/custom_bundle_adjustment.py b/python/examples/custom_bundle_adjustment.py +index 5e5aaed6..a43935b5 100644 +--- a/python/examples/custom_bundle_adjustment.py ++++ b/python/examples/custom_bundle_adjustment.py +@@ -4,6 +4,7 @@ C++ with equivalent logic. As a result, one can add customized residuals on top + of the exposed ceres problem from conventional bundle adjustment. + """ + ++import collections + import copy + + import pycolmap +@@ -60,6 +61,10 @@ def adjust_global_bundle(mapper, mapper_options, ba_options): + if frame_id in mapper.existing_frame_ids: + ba_config.set_constant_rig_from_world_pose(frame_id) + ++ for rig_id in mapper_options.constant_rigs: ++ for sensor_id in reconstruction.rig(rig_id).sensors: ++ ba_config.set_constant_sensor_from_rig_pose(sensor_id) ++ + for camera_id in mapper_options.constant_cameras: + ba_config.set_constant_cam_intrinsics(camera_id) + +@@ -145,24 +150,22 @@ def adjust_local_bundle( + ba_config.set_constant_rig_from_world_pose(frame_id) + + # Fix rig poses, if not all frames within the local bundle. +- num_frames_per_rig = {} ++ num_frames_per_rig = collections.defaultdict(int) + for frame_id in frame_ids: + frame = reconstruction.frame(frame_id) +- if frame.rig_id not in num_frames_per_rig: +- num_frames_per_rig[frame.rig_id] = 0 + num_frames_per_rig[frame.rig_id] += 1 + for rig_id, num_frames_local in num_frames_per_rig.items(): +- if num_frames_local < mapper.num_reg_frames_per_rig[rig_id]: +- rig = reconstruction.rig(rig_id) +- for sensor_id, _ in rig.sensors.items(): ++ if ( ++ rig_id in mapper_options.constant_rigs ++ or num_frames_local < mapper.num_reg_frames_per_rig[rig_id] ++ ): ++ for sensor_id in reconstruction.rig(rig_id).sensors: + ba_config.set_constant_sensor_from_rig_pose(sensor_id) + + # Fix camera intrinsics, if not all images within local bundle. +- num_images_per_camera = {} ++ num_images_per_camera = collections.defaultdict(int) + for image_id in ba_config.images: + image = reconstruction.images[image_id] +- if image.camera_id not in num_images_per_camera: +- num_images_per_camera[image.camera_id] = 0 + num_images_per_camera[image.camera_id] += 1 + for camera_id, num_images_local in num_images_per_camera.items(): + if ( +diff --git a/scripts/shell/build_mac_app.sh b/scripts/shell/build_mac_app.sh +index 499f5c59..ff01b88b 100755 +--- a/scripts/shell/build_mac_app.sh ++++ b/scripts/shell/build_mac_app.sh +@@ -66,7 +66,11 @@ install_name_tool -change @rpath/libtbb.dylib /usr/local/lib/libtbb.dylib $BASE_ + install_name_tool -change @rpath/libtbbmalloc.dylib /usr/local/lib/libtbbmalloc.dylib $BASE_PATH/COLMAP.app/Contents/MacOS/COLMAP + + echo "Linking dynamic libraries" +-/usr/local/opt/qt5/bin/macdeployqt "$BASE_PATH/COLMAP.app" ++if [ -d "$(brew --prefix)/opt/qt6" ]; then ++ $(brew --prefix)/opt/qt6/bin/macdeployqt "$BASE_PATH/COLMAP.app" ++else ++ $(brew --prefix)/opt/qt5/bin/macdeployqt "$BASE_PATH/COLMAP.app" ++fi + + echo "Wrapping binary" + cat <"$BASE_PATH/COLMAP.app/Contents/MacOS/colmap_gui.sh" +diff --git a/src/colmap/controllers/automatic_reconstruction.cc b/src/colmap/controllers/automatic_reconstruction.cc +index dac39310..ea0eb484 100644 +--- a/src/colmap/controllers/automatic_reconstruction.cc ++++ b/src/colmap/controllers/automatic_reconstruction.cc +@@ -96,6 +96,7 @@ AutomaticReconstructionController::AutomaticReconstructionController( + + ImageReaderOptions& reader_options = *option_manager_.image_reader; + reader_options.image_path = *option_manager_.image_path; ++ reader_options.as_rgb = option_manager_.feature_extraction->RequiresRGB(); + if (!options_.mask_path.empty()) { + reader_options.mask_path = options_.mask_path; + option_manager_.image_reader->mask_path = options_.mask_path; +diff --git a/src/colmap/controllers/feature_extraction.cc b/src/colmap/controllers/feature_extraction.cc +index dc75e29d..6b613a05 100644 +--- a/src/colmap/controllers/feature_extraction.cc ++++ b/src/colmap/controllers/feature_extraction.cc +@@ -204,7 +204,7 @@ class FeatureExtractorThread : public Thread { + &image_data.keypoints, + &image_data.descriptors); + } +- if (image_data.mask.Data()) { ++ if (!image_data.mask.IsEmpty()) { + MaskKeypoints(image_data.mask, + &image_data.keypoints, + &image_data.descriptors); +@@ -214,7 +214,9 @@ class FeatureExtractorThread : public Thread { + } + } + +- image_data.bitmap.Deallocate(); ++ // Release the memory, since it is not used afterwards. ++ image_data.bitmap = Bitmap(); ++ image_data.mask = Bitmap(); + + output_queue_->Push(std::move(image_data)); + } else { +@@ -281,7 +283,7 @@ class FeatureWriterThread : public Thread { + image_data.camera.has_prior_focal_length ? " (Prior)" : ""); + LOG(INFO) << " Features: " << image_data.keypoints.size() + << " (" << extractor_type_str_ << ")"; +- if (image_data.mask.Data()) { ++ if (!image_data.mask.IsEmpty()) { + LOG(INFO) << " Mask: Yes"; + } + +@@ -367,11 +369,12 @@ class FeatureExtractorController : public Thread { + extractor_queue_ = std::make_unique>(kQueueSize); + writer_queue_ = std::make_unique>(kQueueSize); + +- const int max_image_size = extraction_options_.MaxImageSize(); +- if (max_image_size > 0) { ++ if (extraction_options_.max_image_size > 0) { + for (int i = 0; i < num_threads; ++i) { + resizers_.emplace_back(std::make_unique( +- max_image_size, resizer_queue_.get(), extractor_queue_.get())); ++ extraction_options_.max_image_size, ++ resizer_queue_.get(), ++ extractor_queue_.get())); + } + } + +@@ -403,7 +406,8 @@ class FeatureExtractorController : public Thread { + } else { + const static FeatureExtractionOptions kDefaultExtractionOptions; + if (extraction_options_.num_threads == -1 && +- max_image_size == kDefaultExtractionOptions.MaxImageSize() && ++ extraction_options_.max_image_size == ++ kDefaultExtractionOptions.max_image_size && + extraction_options_.sift->first_octave == + kDefaultExtractionOptions.sift->first_octave) { + LOG(WARNING) +@@ -455,7 +459,7 @@ class FeatureExtractorController : public Thread { + } + } + +- const bool should_resize = extraction_options_.MaxImageSize() > 0; ++ const bool should_resize = extraction_options_.max_image_size > 0; + + while (image_reader_.NextIndex() < image_reader_.NumImages()) { + if (IsStopped()) { +@@ -475,7 +479,9 @@ class FeatureExtractorController : public Thread { + &image_data.mask); + + if (image_data.status != ImageReader::Status::SUCCESS) { +- image_data.bitmap.Deallocate(); ++ // Release the memory, since it is not used afterwards. ++ image_data.bitmap = Bitmap(); ++ image_data.mask = Bitmap(); + } + + if (should_resize) { +diff --git a/src/colmap/controllers/image_reader.cc b/src/colmap/controllers/image_reader.cc +index ae38ac93..0c6a3c12 100644 +--- a/src/colmap/controllers/image_reader.cc ++++ b/src/colmap/controllers/image_reader.cc +@@ -135,7 +135,7 @@ ImageReader::Status ImageReader::Next(Rig* rig, + // Read image. + ////////////////////////////////////////////////////////////////////////////// + +- if (!bitmap->Read(image_path, false)) { ++ if (!bitmap->Read(image_path, /*as_rgb=*/options_.as_rgb)) { + return Status::BITMAP_ERROR; + } + +diff --git a/src/colmap/controllers/image_reader.h b/src/colmap/controllers/image_reader.h +index 9527fb40..ebd04313 100644 +--- a/src/colmap/controllers/image_reader.h ++++ b/src/colmap/controllers/image_reader.h +@@ -82,6 +82,9 @@ struct ImageReaderOptions { + // value `default_focal_length_factor * max(width, height)`. + double default_focal_length_factor = 1.2; + ++ // Whether to read images as grayscale or RGB. ++ bool as_rgb = false; ++ + bool Check() const; + }; + +diff --git a/src/colmap/controllers/image_reader_test.cc b/src/colmap/controllers/image_reader_test.cc +index 5ac7c083..6bace906 100644 +--- a/src/colmap/controllers/image_reader_test.cc ++++ b/src/colmap/controllers/image_reader_test.cc +@@ -40,9 +40,8 @@ + namespace colmap { + namespace { + +-Bitmap CreateTestBitmap() { +- Bitmap bitmap; +- bitmap.Allocate(1, 3, false); ++Bitmap CreateTestBitmap(bool as_rgb) { ++ Bitmap bitmap(1, 3, as_rgb); + bitmap.SetPixel(0, 0, BitmapColor(1)); + bitmap.SetPixel(1, 0, BitmapColor(2)); + bitmap.SetPixel(2, 0, BitmapColor(3)); +@@ -50,25 +49,26 @@ Bitmap CreateTestBitmap() { + } + + class ParameterizedImageReaderTests +- : public ::testing::TestWithParam< +- std::tuple> {}; ++ : public ::testing::TestWithParam> {}; + + TEST_P(ParameterizedImageReaderTests, Nominal) { +- const auto [kNumImages, kWithMasks, kWithExistingImages] = GetParam(); ++ const auto [kNumImages, kWithMasks, kWithExistingImages, kAsRGB] = GetParam(); + + auto database = Database::Open(kInMemorySqliteDatabasePath); + + const std::string test_dir = CreateTestDir(); + ImageReaderOptions options; + options.image_path = test_dir + "/images"; ++ options.as_rgb = kAsRGB; + CreateDirIfNotExists(options.image_path); + if (kWithMasks) { + options.mask_path = test_dir + "/masks"; + CreateDirIfNotExists(options.mask_path); + } +- const Bitmap test_bitmap = CreateTestBitmap(); ++ const Bitmap test_bitmap = CreateTestBitmap(kAsRGB); + for (int i = 0; i < kNumImages; ++i) { + const std::string image_name = std::to_string(i) + ".png"; + test_bitmap.Write(options.image_path + "/" + image_name); +@@ -117,8 +117,8 @@ TEST_P(ParameterizedImageReaderTests, Nominal) { + EXPECT_EQ(camera.width, test_bitmap.Width()); + EXPECT_EQ(camera.height, test_bitmap.Height()); + EXPECT_EQ(image.Name(), std::to_string(i) + ".png"); +- EXPECT_EQ(bitmap.ConvertToRowMajorArray(), +- test_bitmap.ConvertToRowMajorArray()); ++ EXPECT_EQ(bitmap.IsRGB(), kAsRGB); ++ EXPECT_EQ(bitmap.RowMajorData(), test_bitmap.RowMajorData()); + if (kWithExistingImages) { + EXPECT_EQ(database->NumRigs(), kNumImages); + EXPECT_EQ(database->NumCameras(), kNumImages); +@@ -135,12 +135,29 @@ TEST_P(ParameterizedImageReaderTests, Nominal) { + EXPECT_EQ(database->NumCameras(), kNumImages); + } + +-INSTANTIATE_TEST_SUITE_P(ImageReaderTests, +- ParameterizedImageReaderTests, +- ::testing::Values(std::make_tuple(0, false, true), +- std::make_tuple(5, false, false), +- std::make_tuple(5, true, false), +- std::make_tuple(5, false, true))); ++INSTANTIATE_TEST_SUITE_P( ++ ImageReaderTests, ++ ParameterizedImageReaderTests, ++ ::testing::Values(std::make_tuple(/*num_images=*/0, ++ /*with_masks=*/false, ++ /*with_existing_images=*/true, ++ /*as_rgb=*/true), ++ std::make_tuple(/*num_images=*/5, ++ /*with_masks=*/false, ++ /*with_existing_images=*/false, ++ /*as_rgb=*/true), ++ std::make_tuple(/*num_images=*/5, ++ /*with_masks=*/true, ++ /*with_existing_images=*/false, ++ /*as_rgb=*/true), ++ std::make_tuple(/*num_images=*/5, ++ /*with_masks=*/true, ++ /*with_existing_images=*/false, ++ /*as_rgb=*/false), ++ std::make_tuple(/*num_images=*/5, ++ /*with_masks=*/false, ++ /*with_existing_images=*/true, ++ /*as_rgb=*/true))); + + } // namespace + } // namespace colmap +diff --git a/src/colmap/controllers/incremental_pipeline.cc b/src/colmap/controllers/incremental_pipeline.cc +index 348bd053..13654b55 100644 +--- a/src/colmap/controllers/incremental_pipeline.cc ++++ b/src/colmap/controllers/incremental_pipeline.cc +@@ -87,6 +87,7 @@ IncrementalMapper::Options IncrementalPipelineOptions::Mapper() const { + options.num_threads = num_threads; + options.local_ba_num_images = ba_local_num_images; + options.fix_existing_frames = fix_existing_frames; ++ options.constant_rigs = constant_rigs; + options.constant_cameras = constant_cameras; + options.use_prior_position = use_prior_position; + options.use_robust_loss_on_prior_position = use_robust_loss_on_prior_position; +diff --git a/src/colmap/controllers/incremental_pipeline.h b/src/colmap/controllers/incremental_pipeline.h +index bdc52e0e..9dd5d742 100644 +--- a/src/colmap/controllers/incremental_pipeline.h ++++ b/src/colmap/controllers/incremental_pipeline.h +@@ -153,6 +153,10 @@ struct IncrementalPipelineOptions { + // If reconstruction is provided as input, fix the existing frame poses. + bool fix_existing_frames = false; + ++ // List of rigs for which to fix the sensor_from_rig transformation, ++ // independent of ba_refine_sensor_from_rig. ++ std::unordered_set constant_rigs; ++ + // List of cameras for which to fix the camera parameters independent + // of refine_focal_length, refine_principal_point, and refine_extra_params. + std::unordered_set constant_cameras; +diff --git a/src/colmap/controllers/incremental_pipeline_test.cc b/src/colmap/controllers/incremental_pipeline_test.cc +index 6e8b2037..a17a1589 100644 +--- a/src/colmap/controllers/incremental_pipeline_test.cc ++++ b/src/colmap/controllers/incremental_pipeline_test.cc +@@ -30,6 +30,7 @@ + #include "colmap/controllers/incremental_pipeline.h" + + #include "colmap/estimators/alignment.h" ++#include "colmap/geometry/rigid3_matchers.h" + #include "colmap/scene/database.h" + #include "colmap/scene/synthetic.h" + #include "colmap/util/testing.h" +@@ -84,6 +85,15 @@ bool AreReconstructionsIdentical(const Reconstruction& gt, + return false; + } + ++ for (const auto& [camera_id, camera] : gt.Cameras()) { ++ if (!computed.ExistsCamera(camera_id)) { ++ return false; ++ } ++ if (camera.params != computed.Camera(camera_id).params) { ++ return false; ++ } ++ } ++ + for (const auto& [image_id, image] : computed.Images()) { + if (!gt.ExistsImage(image_id)) { + return false; +@@ -106,16 +116,6 @@ bool AreReconstructionsIdentical(const Reconstruction& gt, + return true; + } + +-void ExpectReconstructionsIdentical(const Reconstruction& gt, +- const Reconstruction& computed) { +- EXPECT_TRUE(AreReconstructionsIdentical(gt, computed)); +-} +- +-void ExpectReconstructionsDifferent(const Reconstruction& gt, +- const Reconstruction& computed) { +- EXPECT_FALSE(AreReconstructionsIdentical(gt, computed)); +-} +- + TEST(IncrementalPipeline, WithoutNoise) { + const std::string database_path = CreateTestDir() + "/database.db"; + +@@ -185,6 +185,59 @@ TEST(IncrementalPipeline, WithoutNoiseAndWithNonTrivialFrames) { + } + } + ++TEST(IncrementalPipeline, WithNonTrivialFramesAndConstantRigsAndCameras) { ++ const std::string database_path = CreateTestDir() + "/database.db"; ++ ++ auto database = Database::Open(database_path); ++ Reconstruction gt_reconstruction; ++ SyntheticDatasetOptions synthetic_dataset_options; ++ synthetic_dataset_options.num_rigs = 2; ++ synthetic_dataset_options.num_cameras_per_rig = 2; ++ synthetic_dataset_options.num_frames_per_rig = 7; ++ synthetic_dataset_options.num_points3D = 100; ++ synthetic_dataset_options.point2D_stddev = 0; ++ synthetic_dataset_options.camera_has_prior_focal_length = false; ++ synthetic_dataset_options.sensor_from_rig_translation_stddev = 0.05; ++ synthetic_dataset_options.sensor_from_rig_rotation_stddev = 30; ++ SynthesizeDataset( ++ synthetic_dataset_options, >_reconstruction, database.get()); ++ ++ constexpr int kConstantRigId = 1; ++ constexpr int kConstantCameraId = 1; ++ ++ auto reconstruction_manager = std::make_shared(); ++ auto options = std::make_shared(); ++ options->constant_rigs.insert(kConstantRigId); ++ options->constant_cameras.insert(kConstantCameraId); ++ IncrementalPipeline mapper(options, ++ /*image_path=*/"", ++ database_path, ++ reconstruction_manager); ++ mapper.Run(); ++ ++ ASSERT_EQ(reconstruction_manager->Size(), 1); ++ auto& reconstruction = *reconstruction_manager->Get(0); ++ ExpectReconstructionsNear(gt_reconstruction, ++ reconstruction, ++ /*max_rotation_error_deg=*/1e-2, ++ /*max_proj_center_error=*/1e-3, ++ /*num_obs_tolerance=*/0, ++ /*align=*/true, ++ /*check_scale=*/true); ++ ++ for (const auto& [sensor_id, sensor_from_rig] : ++ reconstruction.Rig(kConstantRigId).Sensors()) { ++ EXPECT_THAT( ++ sensor_from_rig.value(), ++ Rigid3dNear( ++ gt_reconstruction.Rig(kConstantRigId).SensorFromRig(sensor_id), ++ /*rtol=*/1e-6, ++ /*ttol=*/1e-6)); ++ } ++ EXPECT_EQ(reconstruction.Camera(kConstantCameraId).params, ++ gt_reconstruction.Camera(kConstantCameraId).params); ++} ++ + TEST(IncrementalPipeline, WithoutNoiseAndWithPanoramicNonTrivialFrames) { + const std::string database_path = CreateTestDir() + "/database.db"; + +@@ -570,6 +623,8 @@ TEST(IncrementalPipeline, GPSPriorBasedSfMWithNoise) { + } + + TEST(IncrementalPipeline, SfMWithRandomSeedStability) { ++ SetPRNGSeed(1); ++ + const std::string database_path = CreateTestDir() + "/database.db"; + + auto database = Database::Open(database_path); +@@ -577,9 +632,9 @@ TEST(IncrementalPipeline, SfMWithRandomSeedStability) { + SyntheticDatasetOptions synthetic_dataset_options; + synthetic_dataset_options.num_rigs = 2; + synthetic_dataset_options.num_cameras_per_rig = 1; +- synthetic_dataset_options.num_frames_per_rig = 7; ++ synthetic_dataset_options.num_frames_per_rig = 5; + synthetic_dataset_options.num_points3D = 100; +- synthetic_dataset_options.point2D_stddev = 2.5; ++ synthetic_dataset_options.point2D_stddev = 1; + synthetic_dataset_options.use_prior_position = false; + SynthesizeDataset( + synthetic_dataset_options, >_reconstruction, database.get()); +@@ -600,48 +655,53 @@ TEST(IncrementalPipeline, SfMWithRandomSeedStability) { + return reconstruction_manager; + }; + +- // Single-thread execution ++ // Single-threaded execution. + { ++ constexpr int kRandomSeed = 42; + auto reconstruction_manager0 = +- run_mapper(/*num_threads=*/1, /*random_seed=*/42); ++ run_mapper(/*num_threads=*/1, /*random_seed=*/kRandomSeed); + auto reconstruction_manager1 = +- run_mapper(/*num_threads=*/1, /*random_seed=*/42); +- // Same seed should produce identical reconstructions in single-thread mode +- +- ExpectReconstructionsIdentical(*reconstruction_manager0->Get(0), +- *reconstruction_manager1->Get(0)); +- +- // Different seed should produce different reconstructions +- auto reconstruction_manager2 = +- run_mapper(/*num_threads=*/1, /*random_seed=*/123); +- ExpectReconstructionsDifferent(*reconstruction_manager0->Get(0), +- *reconstruction_manager2->Get(0)); ++ run_mapper(/*num_threads=*/1, /*random_seed=*/kRandomSeed); ++ EXPECT_TRUE(AreReconstructionsIdentical(*reconstruction_manager0->Get(0), ++ *reconstruction_manager1->Get(0))); ++ ++ // Different seed should produce different reconstructions. Notice that, for ++ // some seeds, we may still get identical results, so we try a few different ++ // seeds until we get a different result. ++ bool different_result = false; ++ for (int random_seed = kRandomSeed + 1; random_seed < kRandomSeed + 10; ++ ++random_seed) { ++ auto reconstruction_manager2 = ++ run_mapper(/*num_threads=*/1, /*random_seed=*/random_seed); ++ if (!AreReconstructionsIdentical(*reconstruction_manager0->Get(0), ++ *reconstruction_manager2->Get(0))) { ++ different_result = true; ++ break; ++ } ++ } ++ EXPECT_TRUE(different_result); + } + +- // Multi-thread execution ++ // Multi-threaded execution. + { + auto reconstruction_manager0 = + run_mapper(/*num_threads=*/-1, /*random_seed=*/42); + auto reconstruction_manager1 = + run_mapper(/*num_threads=*/-1, /*random_seed=*/42); + // Same seed should produce similar results, up to floating-point variations +- // in optimization ++ // in optimization. + ExpectReconstructionsNear(*reconstruction_manager0->Get(0), + *reconstruction_manager1->Get(0), +- /*max_rotation_error_deg=*/1e-14, +- /*max_proj_center_error=*/1e-14, ++ /*max_rotation_error_deg=*/1e-10, ++ /*max_proj_center_error=*/1e-10, + /*num_obs_tolerance=*/0.01, + /*align=*/false); +- +- auto reconstruction_manager2 = +- run_mapper(/*num_threads=*/-1, /*random_seed=*/123); +- // Different seed may produce different reconstructions +- ExpectReconstructionsDifferent(*reconstruction_manager0->Get(0), +- *reconstruction_manager2->Get(0)); + } + } + + TEST(IncrementalPipeline, PriorBasedSfMWithRandomSeedStability) { ++ SetPRNGSeed(1); ++ + const std::string database_path = CreateTestDir() + "/database.db"; + + auto database = Database::Open(database_path); +@@ -651,11 +711,11 @@ TEST(IncrementalPipeline, PriorBasedSfMWithRandomSeedStability) { + synthetic_dataset_options.num_cameras_per_rig = 1; + synthetic_dataset_options.num_frames_per_rig = 7; + synthetic_dataset_options.num_points3D = 100; +- synthetic_dataset_options.point2D_stddev = 2.5; ++ synthetic_dataset_options.point2D_stddev = 1; + synthetic_dataset_options.use_prior_position = true; + SynthesizeDataset( + synthetic_dataset_options, >_reconstruction, database.get()); +- synthetic_dataset_options.prior_position_stddev = 2.0; ++ synthetic_dataset_options.prior_position_stddev = 1.0; + + auto mapper_options = std::make_shared(); + mapper_options->use_prior_position = false; +@@ -673,43 +733,48 @@ TEST(IncrementalPipeline, PriorBasedSfMWithRandomSeedStability) { + return reconstruction_manager; + }; + +- // Single-thread execution ++ // Single-threaded execution. + { ++ constexpr int kRandomSeed = 42; + auto reconstruction_manager0 = +- run_mapper(/*num_threads=*/1, /*random_seed=*/42); ++ run_mapper(/*num_threads=*/1, /*random_seed=*/kRandomSeed); + auto reconstruction_manager1 = +- run_mapper(/*num_threads=*/1, /*random_seed=*/42); +- // Same seed should produce identical reconstructions in single-thread mode +- ExpectReconstructionsIdentical(*reconstruction_manager0->Get(0), +- *reconstruction_manager1->Get(0)); +- +- // Different seed should produce different reconstructions +- auto reconstruction_manager2 = +- run_mapper(/*num_threads=*/1, /*random_seed=*/123); +- ExpectReconstructionsDifferent(*reconstruction_manager0->Get(0), +- *reconstruction_manager2->Get(0)); ++ run_mapper(/*num_threads=*/1, /*random_seed=*/kRandomSeed); ++ EXPECT_TRUE(AreReconstructionsIdentical(*reconstruction_manager0->Get(0), ++ *reconstruction_manager1->Get(0))); ++ ++ // Different seed should produce different reconstructions. Notice that, for ++ // some seeds, we may still get identical results, so we try a few different ++ // seeds until we get a different result. ++ bool different_result = false; ++ for (int random_seed = kRandomSeed + 1; random_seed < kRandomSeed + 10; ++ ++random_seed) { ++ // Different seed should produce different reconstructions. ++ auto reconstruction_manager2 = ++ run_mapper(/*num_threads=*/1, /*random_seed=*/random_seed); ++ if (!AreReconstructionsIdentical(*reconstruction_manager0->Get(0), ++ *reconstruction_manager2->Get(0))) { ++ different_result = true; ++ break; ++ } ++ } ++ EXPECT_TRUE(different_result); + } + +- // Multi-thread execution ++ // Multi-threaded execution. + { + auto reconstruction_manager0 = + run_mapper(/*num_threads=*/-1, /*random_seed=*/42); + auto reconstruction_manager1 = + run_mapper(/*num_threads=*/-1, /*random_seed=*/42); + // Same seed should produce similar results, up to floating-point variations +- // in optimization ++ // in optimization. + ExpectReconstructionsNear(*reconstruction_manager0->Get(0), + *reconstruction_manager1->Get(0), +- /*max_rotation_error_deg=*/1e-13, +- /*max_proj_center_error=*/1e-13, ++ /*max_rotation_error_deg=*/1e-10, ++ /*max_proj_center_error=*/1e-10, + /*num_obs_tolerance=*/0.01, + /*align=*/false); +- +- auto reconstruction_manager2 = +- run_mapper(/*num_threads=*/-1, /*random_seed=*/123); +- // Different seed may produce different reconstructions +- ExpectReconstructionsDifferent(*reconstruction_manager0->Get(0), +- *reconstruction_manager2->Get(0)); + } + } + +diff --git a/src/colmap/controllers/option_manager.cc b/src/colmap/controllers/option_manager.cc +index 06a5498b..14c421d4 100644 +--- a/src/colmap/controllers/option_manager.cc ++++ b/src/colmap/controllers/option_manager.cc +@@ -110,7 +110,7 @@ void OptionManager::ModifyForInternetData() { + } + + void OptionManager::ModifyForLowQuality() { +- feature_extraction->sift->max_image_size = 1000; ++ feature_extraction->max_image_size = 1000; + feature_extraction->sift->max_num_features = 2048; + sequential_pairing->loop_detection_num_images /= 2; + vocab_tree_pairing->max_num_features = 256; +@@ -131,7 +131,7 @@ void OptionManager::ModifyForLowQuality() { + } + + void OptionManager::ModifyForMediumQuality() { +- feature_extraction->sift->max_image_size = 1600; ++ feature_extraction->max_image_size = 1600; + feature_extraction->sift->max_num_features = 4096; + sequential_pairing->loop_detection_num_images /= 1.5; + vocab_tree_pairing->max_num_features = 1024; +@@ -153,7 +153,7 @@ void OptionManager::ModifyForMediumQuality() { + + void OptionManager::ModifyForHighQuality() { + feature_extraction->sift->estimate_affine_shape = true; +- feature_extraction->sift->max_image_size = 2400; ++ feature_extraction->max_image_size = 2400; + feature_extraction->sift->max_num_features = 8192; + feature_matching->guided_matching = true; + vocab_tree_pairing->max_num_features = 4096; +@@ -269,7 +269,7 @@ void OptionManager::AddFeatureExtractionOptions() { + &feature_extraction->gpu_index); + + AddAndRegisterDefaultOption("SiftExtraction.max_image_size", +- &feature_extraction->sift->max_image_size); ++ &feature_extraction->max_image_size); + AddAndRegisterDefaultOption("SiftExtraction.max_num_features", + &feature_extraction->sift->max_num_features); + AddAndRegisterDefaultOption("SiftExtraction.first_octave", +@@ -645,6 +645,8 @@ void OptionManager::AddMapperOptions() { + &mapper->mapper.local_ba_min_tri_angle); + + AddDefaultOption("Mapper.image_list_path", &mapper_image_list_path_); ++ AddDefaultOption("Mapper.constant_rig_list_path", ++ &mapper_constant_rig_list_path_); + AddDefaultOption("Mapper.constant_camera_list_path", + &mapper_constant_camera_list_path_); + +@@ -952,6 +954,12 @@ void OptionManager::Parse(const int argc, char** argv) { + if (!mapper_image_list_path_.empty()) { + mapper->image_names = ReadTextFileLines(mapper_image_list_path_); + } ++ if (!mapper_constant_rig_list_path_.empty()) { ++ for (const std::string& line : ++ ReadTextFileLines(mapper_constant_rig_list_path_)) { ++ mapper->constant_rigs.insert(std::stoi(line)); ++ } ++ } + if (!mapper_constant_camera_list_path_.empty()) { + for (const std::string& line : + ReadTextFileLines(mapper_constant_camera_list_path_)) { +diff --git a/src/colmap/controllers/option_manager.h b/src/colmap/controllers/option_manager.h +index 12bfe68a..3d5bffc6 100644 +--- a/src/colmap/controllers/option_manager.h ++++ b/src/colmap/controllers/option_manager.h +@@ -174,6 +174,7 @@ class OptionManager { + std::string feature_matching_type_; + + std::string mapper_image_list_path_; ++ std::string mapper_constant_rig_list_path_; + std::string mapper_constant_camera_list_path_; + + bool added_log_options_; +diff --git a/src/colmap/exe/feature.cc b/src/colmap/exe/feature.cc +index 59e2d8fa..122c048a 100644 +--- a/src/colmap/exe/feature.cc ++++ b/src/colmap/exe/feature.cc +@@ -106,6 +106,7 @@ int RunFeatureExtractor(int argc, char** argv) { + + ImageReaderOptions reader_options = *options.image_reader; + reader_options.image_path = *options.image_path; ++ reader_options.as_rgb = options.feature_extraction->RequiresRGB(); + + if (camera_mode >= 0) { + UpdateImageReaderOptionsFromCameraMode(reader_options, +diff --git a/src/colmap/exe/gui.cc b/src/colmap/exe/gui.cc +index 040f4427..19a35f02 100644 +--- a/src/colmap/exe/gui.cc ++++ b/src/colmap/exe/gui.cc +@@ -53,13 +53,15 @@ int RunGraphicalUserInterface(int argc, char** argv) { + options.Parse(argc, argv); + } + +-#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) +- QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +- QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); +-#endif +- + QApplication app(argc, argv); + ++#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) && \ ++ (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) ++ app.setAttribute(Qt::AA_EnableHighDpiScaling); ++ app.setAttribute(Qt::AA_UseHighDpiPixmaps); ++#endif ++ app.setAttribute(Qt::AA_DontShowIconsInMenus, false); ++ + colmap::MainWindow main_window(options); + main_window.show(); + +diff --git a/src/colmap/feature/CMakeLists.txt b/src/colmap/feature/CMakeLists.txt +index c03e3643..0f3ebea9 100644 +--- a/src/colmap/feature/CMakeLists.txt ++++ b/src/colmap/feature/CMakeLists.txt +@@ -101,5 +101,5 @@ COLMAP_ADD_TEST( + colmap_util + ) + if(TESTS_ENABLED AND GUI_ENABLED) +- target_link_libraries(colmap_feature_sift_test Qt5::Widgets) ++ target_link_libraries(colmap_feature_sift_test Qt${QT_VERSION_MAJOR}::Widgets) + endif() +diff --git a/src/colmap/feature/extractor.cc b/src/colmap/feature/extractor.cc +index 730a3da2..45dfa1d3 100644 +--- a/src/colmap/feature/extractor.cc ++++ b/src/colmap/feature/extractor.cc +@@ -46,17 +46,18 @@ void ThrowUnknownFeatureExtractorType(FeatureExtractorType type) { + FeatureExtractionOptions::FeatureExtractionOptions(FeatureExtractorType type) + : type(type), sift(std::make_shared()) {} + +-int FeatureExtractionOptions::MaxImageSize() const { ++bool FeatureExtractionOptions::RequiresRGB() const { + switch (type) { + case FeatureExtractorType::SIFT: +- return sift->max_image_size; ++ return false; + default: + ThrowUnknownFeatureExtractorType(type); + } +- return -1; ++ return false; + } + + bool FeatureExtractionOptions::Check() const { ++ CHECK_OPTION_GT(max_image_size, 0); + if (use_gpu) { + CHECK_OPTION_GT(CSVToVector(gpu_index).size(), 0); + #ifndef COLMAP_GPU_ENABLED +diff --git a/src/colmap/feature/extractor.h b/src/colmap/feature/extractor.h +index c6808a04..d2bcc7dc 100644 +--- a/src/colmap/feature/extractor.h ++++ b/src/colmap/feature/extractor.h +@@ -47,6 +47,9 @@ struct FeatureExtractionOptions { + + FeatureExtractorType type = FeatureExtractorType::SIFT; + ++ // Maximum image size, otherwise image will be down-scaled. ++ int max_image_size = 3200; ++ + // Number of threads for feature extraction. + int num_threads = -1; + +@@ -59,7 +62,8 @@ struct FeatureExtractionOptions { + + std::shared_ptr sift; + +- int MaxImageSize() const; ++ // Whether the selected extractor requires RGB (or grayscale) images. ++ bool RequiresRGB() const; + + bool Check() const; + }; +diff --git a/src/colmap/feature/sift.cc b/src/colmap/feature/sift.cc +index 9aeee62e..79265d65 100644 +--- a/src/colmap/feature/sift.cc ++++ b/src/colmap/feature/sift.cc +@@ -63,7 +63,6 @@ namespace colmap { + constexpr int kSqSiftDescriptorNorm = 512 * 512; + + bool SiftExtractionOptions::Check() const { +- CHECK_OPTION_GT(max_image_size, 0); + CHECK_OPTION_GT(max_num_features, 0); + CHECK_OPTION_GT(octave_resolution, 0); + CHECK_OPTION_GT(peak_threshold, 0.0); +@@ -157,7 +156,7 @@ class SiftCPUFeatureExtractor : public FeatureExtractor { + bool first_octave = true; + while (true) { + if (first_octave) { +- const std::vector data_uint8 = bitmap.ConvertToRowMajorArray(); ++ const std::vector& data_uint8 = bitmap.RowMajorData(); + std::vector data_float(data_uint8.size()); + for (size_t i = 0; i < data_uint8.size(); ++i) { + data_float[i] = static_cast(data_uint8[i]) / 255.0f; +@@ -346,7 +345,7 @@ class CovariantSiftCPUFeatureExtractor : public FeatureExtractor { + vl_covdet_set_edge_threshold(covdet.get(), options_.sift->edge_threshold); + + { +- const std::vector data_uint8 = bitmap.ConvertToRowMajorArray(); ++ const std::vector& data_uint8 = bitmap.RowMajorData(); + std::vector data_float(data_uint8.size()); + for (size_t i = 0; i < data_uint8.size(); ++i) { + data_float[i] = static_cast(data_uint8[i]) / 255.0f; +@@ -573,7 +572,7 @@ class SiftGPUFeatureExtractor : public FeatureExtractor { + << -std::min(0, options.sift->first_octave); + sift_gpu_args.push_back("-maxd"); + sift_gpu_args.push_back( +- std::to_string(options.sift->max_image_size * compensation_factor)); ++ std::to_string(options.max_image_size * compensation_factor)); + + // Keep the highest level features. + sift_gpu_args.push_back("-tc2"); +@@ -647,17 +646,16 @@ class SiftGPUFeatureExtractor : public FeatureExtractor { + // first octave in the pyramid (which is the 'first_octave'). + const int compensation_factor = + 1 << -std::min(0, options_.sift->first_octave); +- THROW_CHECK_EQ(options_.sift->max_image_size * compensation_factor, ++ THROW_CHECK_EQ(options_.max_image_size * compensation_factor, + sift_gpu_.GetMaxDimension()); + + std::lock_guard lock(*sift_gpu_mutexes_[sift_gpu_.gpu_index]); + + // Note, that this produces slightly different results than using SiftGPU + // directly for RGB->GRAY conversion, since it uses different weights. +- const std::vector bitmap_raw_bits = bitmap.ConvertToRawBits(); + const int code = sift_gpu_.RunSIFT(bitmap.Pitch(), + bitmap.Height(), +- bitmap_raw_bits.data(), ++ bitmap.RowMajorData().data(), + GL_LUMINANCE, + GL_UNSIGNED_BYTE); + +diff --git a/src/colmap/feature/sift.h b/src/colmap/feature/sift.h +index 017e6c32..7cdb48b6 100644 +--- a/src/colmap/feature/sift.h ++++ b/src/colmap/feature/sift.h +@@ -35,9 +35,6 @@ + namespace colmap { + + struct SiftExtractionOptions { +- // Maximum image size, otherwise image will be down-scaled. +- int max_image_size = 3200; +- + // Maximum number of features to detect, keeping larger-scale features. + int max_num_features = 8192; + +diff --git a/src/colmap/feature/sift_test.cc b/src/colmap/feature/sift_test.cc +index 5c89eb11..af493016 100644 +--- a/src/colmap/feature/sift_test.cc ++++ b/src/colmap/feature/sift_test.cc +@@ -46,19 +46,19 @@ + namespace colmap { + namespace { + +-void CreateImageWithSquare(const int size, Bitmap* bitmap) { +- bitmap->Allocate(size, size, false); +- bitmap->Fill(BitmapColor(0, 0, 0)); ++Bitmap CreateImageWithSquare(const int size) { ++ Bitmap bitmap(size, size, false); ++ bitmap.Fill(BitmapColor(0, 0, 0)); + for (int r = size / 2 - size / 8; r < size / 2 + size / 8; ++r) { + for (int c = size / 2 - size / 8; c < size / 2 + size / 8; ++c) { +- bitmap->SetPixel(r, c, BitmapColor(255)); ++ bitmap.SetPixel(r, c, BitmapColor(255)); + } + } ++ return bitmap; + } + + TEST(ExtractSiftFeaturesCPU, Nominal) { +- Bitmap bitmap; +- CreateImageWithSquare(256, &bitmap); ++ const Bitmap bitmap = CreateImageWithSquare(256); + + FeatureExtractionOptions options(FeatureExtractorType::SIFT); + options.use_gpu = false; +@@ -89,8 +89,7 @@ TEST(ExtractSiftFeaturesCPU, Nominal) { + } + + TEST(ExtractCovariantSiftFeaturesCPU, Nominal) { +- Bitmap bitmap; +- CreateImageWithSquare(256, &bitmap); ++ const Bitmap bitmap = CreateImageWithSquare(256); + + FeatureExtractionOptions options(FeatureExtractorType::SIFT); + options.use_gpu = false; +@@ -121,8 +120,7 @@ TEST(ExtractCovariantSiftFeaturesCPU, Nominal) { + } + + TEST(ExtractCovariantAffineSiftFeaturesCPU, Nominal) { +- Bitmap bitmap; +- CreateImageWithSquare(256, &bitmap); ++ const Bitmap bitmap = CreateImageWithSquare(256); + + FeatureExtractionOptions options(FeatureExtractorType::SIFT); + options.use_gpu = false; +@@ -153,8 +151,7 @@ TEST(ExtractCovariantAffineSiftFeaturesCPU, Nominal) { + } + + TEST(ExtractCovariantAffineSiftFeaturesCPU, Upright) { +- Bitmap bitmap; +- CreateImageWithSquare(256, &bitmap); ++ const Bitmap bitmap = CreateImageWithSquare(256); + + FeatureExtractionOptions options(FeatureExtractorType::SIFT); + options.use_gpu = false; +@@ -186,8 +183,7 @@ TEST(ExtractCovariantAffineSiftFeaturesCPU, Upright) { + } + + TEST(ExtractCovariantDSPSiftFeaturesCPU, Nominal) { +- Bitmap bitmap; +- CreateImageWithSquare(256, &bitmap); ++ const Bitmap bitmap = CreateImageWithSquare(256); + + FeatureExtractionOptions options(FeatureExtractorType::SIFT); + options.use_gpu = false; +@@ -218,8 +214,7 @@ TEST(ExtractCovariantDSPSiftFeaturesCPU, Nominal) { + } + + TEST(ExtractCovariantAffineDSPSiftFeaturesCPU, Nominal) { +- Bitmap bitmap; +- CreateImageWithSquare(256, &bitmap); ++ const Bitmap bitmap = CreateImageWithSquare(256); + + FeatureExtractionOptions options(FeatureExtractorType::SIFT); + options.use_gpu = false; +@@ -260,8 +255,7 @@ TEST(ExtractSiftFeaturesGPU, Nominal) { + void Run() { + opengl_context_.MakeCurrent(); + +- Bitmap bitmap; +- CreateImageWithSquare(256, &bitmap); ++ const Bitmap bitmap = CreateImageWithSquare(256); + + FeatureExtractionOptions options(FeatureExtractorType::SIFT); + options.use_gpu = true; +diff --git a/src/colmap/image/CMakeLists.txt b/src/colmap/image/CMakeLists.txt +index 1e28dc91..2bfe492b 100644 +--- a/src/colmap/image/CMakeLists.txt ++++ b/src/colmap/image/CMakeLists.txt +@@ -42,6 +42,7 @@ COLMAP_ADD_LIBRARY( + PRIVATE_LINK_LIBS + colmap_util + colmap_sensor ++ colmap_vlfeat + ) + if(LSD_ENABLED) + target_link_libraries(colmap_image PRIVATE colmap_lsd) +diff --git a/src/colmap/image/line.cc b/src/colmap/image/line.cc +index e1a13aec..b5036355 100644 +--- a/src/colmap/image/line.cc ++++ b/src/colmap/image/line.cc +@@ -49,21 +49,21 @@ struct RawDeleter { + } // namespace + + #ifdef COLMAP_LSD_ENABLED ++ + std::vector DetectLineSegments(const Bitmap& bitmap, + const double min_length) { + const double min_length_squared = min_length * min_length; + +- std::vector bitmap_data; ++ std::vector bitmap_data_double; + if (bitmap.IsGrey()) { +- bitmap_data = bitmap.ConvertToRowMajorArray(); ++ bitmap_data_double = {bitmap.RowMajorData().begin(), ++ bitmap.RowMajorData().end()}; + } else { + const Bitmap bitmap_gray = bitmap.CloneAsGrey(); +- bitmap_data = bitmap_gray.ConvertToRowMajorArray(); ++ bitmap_data_double = {bitmap_gray.RowMajorData().begin(), ++ bitmap_gray.RowMajorData().end()}; + } + +- std::vector bitmap_data_double(bitmap_data.begin(), +- bitmap_data.end()); +- + int num_segments; + std::unique_ptr segments_data( + lsd(&num_segments, +diff --git a/src/colmap/image/line_test.cc b/src/colmap/image/line_test.cc +index bfd04ada..422291ad 100644 +--- a/src/colmap/image/line_test.cc ++++ b/src/colmap/image/line_test.cc +@@ -35,9 +35,9 @@ namespace colmap { + namespace { + + #ifdef COLMAP_LSD_ENABLED ++ + TEST(DetectLineSegments, Nominal) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, false); ++ Bitmap bitmap(100, 100, false); + for (size_t i = 0; i < 100; ++i) { + bitmap.SetPixel(i, i, BitmapColor(255)); + } +@@ -57,8 +57,7 @@ TEST(DetectLineSegments, Nominal) { + } + + TEST(ClassifyLineSegmentOrientations, Nominal) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, false); ++ Bitmap bitmap(100, 100, false); + for (size_t i = 60; i < 100; ++i) { + bitmap.SetPixel(i, 50, BitmapColor(255)); + bitmap.SetPixel(50, i, BitmapColor(255)); +diff --git a/src/colmap/image/undistortion.cc b/src/colmap/image/undistortion.cc +index ec4b8a7a..839d4e80 100644 +--- a/src/colmap/image/undistortion.cc ++++ b/src/colmap/image/undistortion.cc +@@ -1084,12 +1084,12 @@ void RectifyAndUndistortStereoImages(const UndistortCameraOptions& options, + THROW_CHECK_EQ(distorted_camera2.height, distorted_image2.Height()); + + *undistorted_camera = UndistortCamera(options, distorted_camera1); +- undistorted_image1->Allocate(static_cast(undistorted_camera->width), ++ *undistorted_image1 = Bitmap(static_cast(undistorted_camera->width), + static_cast(undistorted_camera->height), + distorted_image1.IsRGB()); + distorted_image1.CloneMetadata(undistorted_image1); + +- undistorted_image2->Allocate(static_cast(undistorted_camera->width), ++ *undistorted_image2 = Bitmap(static_cast(undistorted_camera->width), + static_cast(undistorted_camera->height), + distorted_image2.IsRGB()); + distorted_image2.CloneMetadata(undistorted_image2); +diff --git a/src/colmap/image/undistortion_test.cc b/src/colmap/image/undistortion_test.cc +index be0fdee5..a7296890 100644 +--- a/src/colmap/image/undistortion_test.cc ++++ b/src/colmap/image/undistortion_test.cc +@@ -110,8 +110,7 @@ TEST(UndistortCamera, BlankPixels) { + Camera::CreateFromModelName(1, "SIMPLE_RADIAL", 100, 100, 100); + distorted_camera.params[3] = 0.5; + +- Bitmap distorted_image; +- distorted_image.Allocate(100, 100, false); ++ Bitmap distorted_image(100, 100, false); + distorted_image.Fill(BitmapColor(255)); + + Bitmap undistorted_image; +@@ -154,8 +153,7 @@ TEST(UndistortCamera, NoBlankPixels) { + Camera::CreateFromModelName(1, "SIMPLE_RADIAL", 100, 100, 100); + distorted_camera.params[3] = 0.5; + +- Bitmap distorted_image; +- distorted_image.Allocate(100, 100, false); ++ Bitmap distorted_image(100, 100, false); + distorted_image.Fill(BitmapColor(255)); + + Bitmap undistorted_image; +@@ -179,9 +177,9 @@ TEST(UndistortCamera, NoBlankPixels) { + for (int x = 0; x < undistorted_image.Width(); ++x) { + BitmapColor color; + EXPECT_TRUE(undistorted_image.GetPixel(x, y, &color)); +- EXPECT_NE(color.r, 0); +- EXPECT_EQ(color.g, 0); +- EXPECT_EQ(color.b, 0); ++ ASSERT_NE(color.r, 0); ++ ASSERT_NE(color.g, 0); ++ ASSERT_NE(color.b, 0); + } + } + } +diff --git a/src/colmap/image/warp.cc b/src/colmap/image/warp.cc +index b8a83969..11cb6605 100644 +--- a/src/colmap/image/warp.cc ++++ b/src/colmap/image/warp.cc +@@ -61,7 +61,7 @@ void WarpImageBetweenCameras(const Camera& source_camera, + THROW_CHECK_EQ(source_camera.height, source_image.Height()); + THROW_CHECK_NOTNULL(target_image); + +- target_image->Allocate(static_cast(source_camera.width), ++ *target_image = Bitmap(static_cast(source_camera.width), + static_cast(source_camera.height), + source_image.IsRGB()); + +@@ -143,7 +143,7 @@ void WarpImageWithHomographyBetweenCameras(const Eigen::Matrix3d& H, + THROW_CHECK_EQ(source_camera.height, source_image.Height()); + THROW_CHECK_NOTNULL(target_image); + +- target_image->Allocate(static_cast(source_camera.width), ++ *target_image = Bitmap(static_cast(source_camera.width), + static_cast(source_camera.height), + source_image.IsRGB()); + +diff --git a/src/colmap/image/warp_test.cc b/src/colmap/image/warp_test.cc +index 13c7feb7..0604b17f 100644 +--- a/src/colmap/image/warp_test.cc ++++ b/src/colmap/image/warp_test.cc +@@ -37,20 +37,20 @@ namespace colmap { + namespace { + namespace { + +-void GenerateRandomBitmap(const int width, +- const int height, +- const bool as_rgb, +- Bitmap* bitmap) { +- bitmap->Allocate(width, height, as_rgb); ++const Bitmap GenerateRandomBitmap(const int width, ++ const int height, ++ const bool as_rgb) { ++ Bitmap bitmap(width, height, as_rgb); + for (int x = 0; x < width; ++x) { + for (int y = 0; y < height; ++y) { + BitmapColor color; + color.r = RandomUniformInteger(0, 255); + color.g = RandomUniformInteger(0, 255); + color.b = RandomUniformInteger(0, 255); +- bitmap->SetPixel(x, y, color); ++ bitmap.SetPixel(x, y, color); + } + } ++ return bitmap; + } + + // Check that the two bitmaps are equal, ignoring a 1px boundary. +@@ -91,14 +91,12 @@ void CheckBitmapsTransposed(const Bitmap& bitmap1, const Bitmap& bitmap2) { + + TEST(Warp, IdenticalCameras) { + const Camera camera = Camera::CreateFromModelName(1, "PINHOLE", 1, 100, 100); +- Bitmap source_image_gray; +- GenerateRandomBitmap(100, 100, false, &source_image_gray); ++ const Bitmap source_image_gray = GenerateRandomBitmap(100, 100, false); + Bitmap target_image_gray; + WarpImageBetweenCameras( + camera, camera, source_image_gray, &target_image_gray); + CheckBitmapsEqual(source_image_gray, target_image_gray); +- Bitmap source_image_rgb; +- GenerateRandomBitmap(100, 100, true, &source_image_rgb); ++ const Bitmap source_image_rgb = GenerateRandomBitmap(100, 100, true); + Bitmap target_image_rgb; + WarpImageBetweenCameras(camera, camera, source_image_rgb, &target_image_rgb); + CheckBitmapsEqual(source_image_rgb, target_image_rgb); +@@ -109,8 +107,7 @@ TEST(Warp, ShiftedCameras) { + Camera::CreateFromModelName(1, "PINHOLE", 1, 100, 100); + Camera target_camera = source_camera; + target_camera.SetPrincipalPointX(0.0); +- Bitmap source_image_gray; +- GenerateRandomBitmap(100, 100, true, &source_image_gray); ++ const Bitmap source_image_gray = GenerateRandomBitmap(100, 100, true); + Bitmap target_image_gray; + WarpImageBetweenCameras( + source_camera, target_camera, source_image_gray, &target_image_gray); +@@ -132,18 +129,14 @@ TEST(Warp, ShiftedCameras) { + } + + TEST(Warp, WarpImageWithHomographyIdentity) { +- Bitmap source_image_gray; +- GenerateRandomBitmap(100, 100, false, &source_image_gray); +- Bitmap target_image_gray; +- target_image_gray.Allocate(100, 100, false); ++ const Bitmap source_image_gray = GenerateRandomBitmap(100, 100, false); ++ Bitmap target_image_gray(100, 100, false); + WarpImageWithHomography( + Eigen::Matrix3d::Identity(), source_image_gray, &target_image_gray); + CheckBitmapsEqual(source_image_gray, target_image_gray); + +- Bitmap source_image_rgb; +- GenerateRandomBitmap(100, 100, true, &source_image_rgb); +- Bitmap target_image_rgb; +- target_image_rgb.Allocate(100, 100, true); ++ const Bitmap source_image_rgb = GenerateRandomBitmap(100, 100, true); ++ Bitmap target_image_rgb(100, 100, true); + WarpImageWithHomography( + Eigen::Matrix3d::Identity(), source_image_rgb, &target_image_rgb); + CheckBitmapsEqual(source_image_rgb, target_image_rgb); +@@ -153,27 +146,21 @@ TEST(Warp, WarpImageWithHomographyTransposed) { + Eigen::Matrix3d H; + H << 0, 1, 0, 1, 0, 0, 0, 0, 1; + +- Bitmap source_image_gray; +- GenerateRandomBitmap(100, 100, false, &source_image_gray); +- Bitmap target_image_gray; +- target_image_gray.Allocate(100, 100, false); ++ const Bitmap source_image_gray = GenerateRandomBitmap(100, 100, false); ++ Bitmap target_image_gray(100, 100, false); + WarpImageWithHomography(H, source_image_gray, &target_image_gray); + CheckBitmapsTransposed(source_image_gray, target_image_gray); + +- Bitmap source_image_rgb; +- GenerateRandomBitmap(100, 100, true, &source_image_rgb); +- Bitmap target_image_rgb; +- target_image_rgb.Allocate(100, 100, true); ++ const Bitmap source_image_rgb = GenerateRandomBitmap(100, 100, true); ++ Bitmap target_image_rgb(100, 100, true); + WarpImageWithHomography(H, source_image_rgb, &target_image_rgb); + CheckBitmapsTransposed(source_image_rgb, target_image_rgb); + } + + TEST(Warp, WarpImageWithHomographyBetweenCamerasIdentity) { + const Camera camera = Camera::CreateFromModelName(1, "PINHOLE", 1, 100, 100); +- Bitmap source_image_gray; +- GenerateRandomBitmap(100, 100, false, &source_image_gray); ++ const Bitmap source_image_gray = GenerateRandomBitmap(100, 100, false); + Bitmap target_image_gray; +- target_image_gray.Allocate(100, 100, false); + WarpImageWithHomographyBetweenCameras(Eigen::Matrix3d::Identity(), + camera, + camera, +@@ -181,10 +168,8 @@ TEST(Warp, WarpImageWithHomographyBetweenCamerasIdentity) { + &target_image_gray); + CheckBitmapsEqual(source_image_gray, target_image_gray); + +- Bitmap source_image_rgb; +- GenerateRandomBitmap(100, 100, true, &source_image_rgb); ++ const Bitmap source_image_rgb = GenerateRandomBitmap(100, 100, true); + Bitmap target_image_rgb; +- target_image_rgb.Allocate(100, 100, true); + WarpImageWithHomographyBetweenCameras(Eigen::Matrix3d::Identity(), + camera, + camera, +@@ -199,18 +184,14 @@ TEST(Warp, WarpImageWithHomographyBetweenCamerasTransposed) { + Eigen::Matrix3d H; + H << 0, 1, 0, 1, 0, 0, 0, 0, 1; + +- Bitmap source_image_gray; +- GenerateRandomBitmap(100, 100, false, &source_image_gray); ++ const Bitmap source_image_gray = GenerateRandomBitmap(100, 100, false); + Bitmap target_image_gray; +- target_image_gray.Allocate(100, 100, false); + WarpImageWithHomographyBetweenCameras( + H, camera, camera, source_image_gray, &target_image_gray); + CheckBitmapsTransposed(source_image_gray, target_image_gray); + +- Bitmap source_image_rgb; +- GenerateRandomBitmap(100, 100, true, &source_image_rgb); ++ const Bitmap source_image_rgb = GenerateRandomBitmap(100, 100, true); + Bitmap target_image_rgb; +- target_image_rgb.Allocate(100, 100, true); + WarpImageWithHomographyBetweenCameras( + H, camera, camera, source_image_rgb, &target_image_rgb); + CheckBitmapsTransposed(source_image_rgb, target_image_rgb); +diff --git a/src/colmap/mvs/depth_map.cc b/src/colmap/mvs/depth_map.cc +index 1a18cc9d..fa9c6cd7 100644 +--- a/src/colmap/mvs/depth_map.cc ++++ b/src/colmap/mvs/depth_map.cc +@@ -87,8 +87,7 @@ Bitmap DepthMap::ToBitmap(const float min_percentile, + THROW_CHECK_GT(width_, 0); + THROW_CHECK_GT(height_, 0); + +- Bitmap bitmap; +- bitmap.Allocate(width_, height_, true); ++ Bitmap bitmap(width_, height_, true); + + std::vector valid_depths; + valid_depths.reserve(data_.size()); +diff --git a/src/colmap/mvs/image.cc b/src/colmap/mvs/image.cc +index efb6fb3f..952f9f89 100644 +--- a/src/colmap/mvs/image.cc ++++ b/src/colmap/mvs/image.cc +@@ -66,7 +66,7 @@ void Image::Rescale(const float factor_x, const float factor_y) { + const size_t new_width = std::round(width_ * factor_x); + const size_t new_height = std::round(height_ * factor_y); + +- if (bitmap_.Data() != nullptr) { ++ if (!bitmap_.IsEmpty()) { + bitmap_.Rescale(new_width, new_height); + } + +diff --git a/src/colmap/mvs/normal_map.cc b/src/colmap/mvs/normal_map.cc +index 47389c10..5014db54 100644 +--- a/src/colmap/mvs/normal_map.cc ++++ b/src/colmap/mvs/normal_map.cc +@@ -101,8 +101,7 @@ Bitmap NormalMap::ToBitmap() const { + THROW_CHECK_GT(height_, 0); + THROW_CHECK_EQ(depth_, 3); + +- Bitmap bitmap; +- bitmap.Allocate(width_, height_, true); ++ Bitmap bitmap(width_, height_, true); + + for (size_t y = 0; y < height_; ++y) { + for (size_t x = 0; x < width_; ++x) { +diff --git a/src/colmap/mvs/patch_match_cuda.cu b/src/colmap/mvs/patch_match_cuda.cu +index b7267318..f3080a3a 100644 +--- a/src/colmap/mvs/patch_match_cuda.cu ++++ b/src/colmap/mvs/patch_match_cuda.cu +@@ -1539,9 +1539,7 @@ void PatchMatchCuda::InitRefImage() { + + // Upload to device and filter. + ref_image_.reset(new GpuMatRefImage(ref_width_, ref_height_)); +- const std::vector ref_image_array = +- ref_image.GetBitmap().ConvertToRowMajorArray(); +- ref_image_->Filter(ref_image_array.data(), ++ ref_image_->Filter(ref_image.GetBitmap().RowMajorData().data(), + options_.window_radius, + options_.window_step, + options_.sigma_spatial, +@@ -1576,10 +1574,7 @@ void PatchMatchCuda::InitSourceImages() { + const Image& image = problem_.images->at(problem_.src_image_idxs[i]); + const Bitmap& bitmap = image.GetBitmap(); + uint8_t* dest = src_images_host_data.data() + max_width * max_height * i; +- for (size_t r = 0; r < image.GetHeight(); ++r) { +- memcpy(dest, bitmap.GetScanline(r), image.GetWidth() * sizeof(uint8_t)); +- dest += max_width; +- } ++ memcpy(dest, bitmap.RowMajorData().data(), bitmap.NumBytes()); + } + + // Create source images texture. +diff --git a/src/colmap/scene/reconstruction.cc b/src/colmap/scene/reconstruction.cc +index e7a26ed9..06e83cba 100644 +--- a/src/colmap/scene/reconstruction.cc ++++ b/src/colmap/scene/reconstruction.cc +@@ -830,7 +830,8 @@ bool Reconstruction::ExtractColorsForImage(const image_t image_id, + const class Image& image = Image(image_id); + + Bitmap bitmap; +- if (!bitmap.Read(JoinPaths(path, image.Name()))) { ++ if (!bitmap.Read(JoinPaths(path, image.Name()), ++ /*as_rgb=*/true)) { + return false; + } + +@@ -862,7 +863,8 @@ void Reconstruction::ExtractColorsForAllImages(const std::string& path) { + const std::string image_path = JoinPaths(path, image.Name()); + + Bitmap bitmap; +- if (!bitmap.Read(image_path)) { ++ if (!bitmap.Read(image_path, ++ /*as_rgb=*/true)) { + LOG(WARNING) << "Could not read image " << image.Name() << " at path " + << image_path; + continue; +diff --git a/src/colmap/sensor/CMakeLists.txt b/src/colmap/sensor/CMakeLists.txt +index d8fd80ad..a79e04b1 100644 +--- a/src/colmap/sensor/CMakeLists.txt ++++ b/src/colmap/sensor/CMakeLists.txt +@@ -44,8 +44,7 @@ COLMAP_ADD_LIBRARY( + PRIVATE_LINK_LIBS + colmap_geometry + colmap_util +- colmap_vlfeat +- freeimage::FreeImage ++ OpenImageIO::OpenImageIO + ) + + COLMAP_ADD_TEST( +@@ -53,7 +52,6 @@ COLMAP_ADD_TEST( + SRCS bitmap_test.cc + LINK_LIBS + colmap_sensor +- freeimage::FreeImage + ) + COLMAP_ADD_TEST( + NAME database_test +diff --git a/src/colmap/sensor/bitmap.cc b/src/colmap/sensor/bitmap.cc +index 7dfcc40f..1fb258c1 100644 +--- a/src/colmap/sensor/bitmap.cc ++++ b/src/colmap/sensor/bitmap.cc +@@ -35,99 +35,173 @@ + #include "colmap/util/logging.h" + #include "colmap/util/misc.h" + +-#include "thirdparty/VLFeat/imopv.h" +- +-#include +-#include +- +-#ifdef _WIN32 +-#ifndef NOMINMAX +-#define NOMINMAX +-#endif +-#include +-#endif +-#include ++#include ++#include ++#include + + namespace colmap { + namespace { + +-#ifdef FREEIMAGE_LIB // Only needed for static FreeImage. ++struct OIIOInitializer { ++ OIIOInitializer() { ++ OIIO::attribute("threads", 1); ++ OIIO::attribute("exr_threads", 1); ++ } + +-struct FreeImageInitializer { +- FreeImageInitializer() { FreeImage_Initialise(); } +- ~FreeImageInitializer() { FreeImage_DeInitialise(); } ++#if OIIO_VERSION >= OIIO_MAKE_VERSION(2, 5, 3) ++ ~OIIOInitializer() { OIIO::shutdown(); } ++#endif + }; + +-const static auto initializer = FreeImageInitializer(); ++const static auto initializer = OIIOInitializer(); + +-#endif // FREEIMAGE_LIB ++struct OIIOMetaData : public Bitmap::MetaData { ++ OIIOMetaData() = default; + +-bool ReadExifTag(FIBITMAP* ptr, +- const FREE_IMAGE_MDMODEL model, +- const std::string& tag_name, +- std::string* result) { +- FITAG* tag = nullptr; +- FreeImage_GetMetadata(model, ptr, tag_name.c_str(), &tag); +- if (tag == nullptr) { +- *result = ""; +- return false; ++ OIIO::ImageSpec image_spec; ++ ++ static OIIOMetaData* Upcast(Bitmap::MetaData* meta_data) { ++ return THROW_CHECK_NOTNULL(dynamic_cast(meta_data)); ++ } ++ ++ static std::unique_ptr Clone( ++ const std::unique_ptr& meta_data) { ++ auto cloned = std::make_unique(); ++ *cloned = *Upcast(meta_data.get()); ++ return cloned; ++ } ++}; ++ ++// For backwards compatibility with older OIIO versions without implicit ++// conversion from std::string_view. ++OIIO::string_view OIIOFromStdStringView(std::string_view value) { ++ return {value.data(), value.size()}; ++} ++ ++std::vector ConvertColorSpace(const uint8_t* src_data, ++ int width, ++ int height, ++ int channels, ++ const std::string_view& from, ++ const std::string_view& to) { ++ const OIIO::ImageSpec image_spec( ++ width, height, channels, OIIO::TypeDesc::UINT8); ++ const int pitch = width * channels; ++ const OIIO::ImageBuf src(image_spec, const_cast(src_data)); ++ std::vector tgt_data(height * pitch); ++ OIIO::ImageBuf tgt(image_spec, tgt_data.data()); ++ THROW_CHECK(OIIO::ImageBufAlgo::colorconvert( ++ tgt, src, OIIOFromStdStringView(from), OIIOFromStdStringView(to))); ++ return tgt_data; ++} ++ ++void SetImageSpecColorSpace(OIIO::ImageSpec& image_spec, ++ const OIIO::string_view& colorspace) { ++#if OIIO_VERSION >= OIIO_MAKE_VERSION(3, 0, 0) ++ image_spec.set_colorspace(colorspace); ++#else ++ // Extract logic from 3.0.0 version for backwards compatibility. ++ const OIIO::string_view oldspace = ++ image_spec.get_string_attribute("oiio:ColorSpace"); ++ if (oldspace.size() && colorspace.size() && oldspace == colorspace) { ++ return; ++ } ++ ++ if (colorspace.empty()) { ++ image_spec.erase_attribute("oiio:ColorSpace"); + } else { +- if (tag_name == "FocalPlaneXResolution") { +- // This tag seems to be in the wrong category. +- *result = std::string(FreeImage_TagToString(FIMD_EXIF_INTEROP, tag)); +- } else { +- *result = FreeImage_TagToString(model, tag); +- } +- return true; ++ image_spec.attribute("oiio:ColorSpace", colorspace); + } +-} + +-bool IsPtrGrey(FIBITMAP* ptr) { +- return FreeImage_GetColorType(ptr) == FIC_MINISBLACK && +- FreeImage_GetBPP(ptr) == 8; +-} ++ if (colorspace != "sRGB") { ++ image_spec.erase_attribute("Exif:ColorSpace"); ++ } + +-bool IsPtrRGB(FIBITMAP* ptr) { +- return FreeImage_GetColorType(ptr) == FIC_RGB && FreeImage_GetBPP(ptr) == 24; ++ image_spec.erase_attribute("tiff:ColorSpace"); ++ image_spec.erase_attribute("tiff:PhotometricInterpretation"); ++ image_spec.erase_attribute("oiio:Gamma"); ++#endif + } + +-bool IsPtrSupported(FIBITMAP* ptr) { return IsPtrGrey(ptr) || IsPtrRGB(ptr); } ++bool IsEquivalentColorSpace(const std::string_view& colorspace1, ++ const std::string_view& colorspace2) { ++#if OIIO_VERSION >= OIIO_MAKE_VERSION(3, 0, 0) ++ return OIIO::equivalent_colorspace(colorspace1, colorspace2); ++#else ++ // Poor (wo)man's version of available functionality in recent OIIO versions. ++ auto is_linear_srgb = [](const std::string_view& colorspace) { ++ return colorspace == "linear" || colorspace == "lin_srgb" || ++ colorspace == "lin_rec709P"; ++ }; ++ if (is_linear_srgb(colorspace1) && is_linear_srgb(colorspace2)) { ++ return true; ++ } else { ++ return colorspace1 == colorspace2; ++ } ++#endif ++} + + } // namespace + +-Bitmap::Bitmap() : width_(0), height_(0), channels_(0) {} ++Bitmap::Bitmap() ++ : width_(0), height_(0), channels_(0), linear_colorspace_(true) {} + +-Bitmap::Bitmap(const Bitmap& other) : Bitmap() { +- if (other.handle_.ptr != nullptr) { +- SetPtr(FreeImage_Clone(other.handle_.ptr)); +- } ++Bitmap::Bitmap(const int width, ++ const int height, ++ const bool as_rgb, ++ const bool linear_colorspace) { ++ width_ = width; ++ height_ = height; ++ channels_ = as_rgb ? 3 : 1; ++ linear_colorspace_ = linear_colorspace; ++ data_.resize(width_ * height_ * channels_); ++ auto meta_data = std::make_unique(); ++ meta_data->image_spec = ++ OIIO::ImageSpec(width_, height_, channels_, OIIO::TypeDesc::UINT8); ++ SetImageSpecColorSpace(meta_data->image_spec, ++ linear_colorspace ? "linear" : "sRGB"); ++ meta_data_ = std::move(meta_data); + } + +-Bitmap::Bitmap(Bitmap&& other) noexcept : Bitmap() { +- handle_ = std::move(other.handle_); ++Bitmap::Bitmap(const Bitmap& other) { + width_ = other.width_; + height_ = other.height_; + channels_ = other.channels_; ++ linear_colorspace_ = other.linear_colorspace_; ++ data_ = other.data_; ++ meta_data_ = OIIOMetaData::Clone(other.meta_data_); ++} ++ ++Bitmap::Bitmap(Bitmap&& other) noexcept { ++ width_ = other.width_; ++ height_ = other.height_; ++ channels_ = other.channels_; ++ linear_colorspace_ = other.linear_colorspace_; ++ data_ = std::move(other.data_); ++ meta_data_ = std::move(other.meta_data_); + other.width_ = 0; + other.height_ = 0; + other.channels_ = 0; + } + +-Bitmap::Bitmap(FIBITMAP* data) : Bitmap() { SetPtr(data); } +- + Bitmap& Bitmap::operator=(const Bitmap& other) { +- if (other.handle_.ptr != nullptr) { +- SetPtr(FreeImage_Clone(other.handle_.ptr)); +- } ++ width_ = other.width_; ++ height_ = other.height_; ++ channels_ = other.channels_; ++ linear_colorspace_ = other.linear_colorspace_; ++ data_ = other.data_; ++ meta_data_ = OIIOMetaData::Clone(other.meta_data_); + return *this; + } + + Bitmap& Bitmap::operator=(Bitmap&& other) noexcept { + if (this != &other) { +- handle_ = std::move(other.handle_); + width_ = other.width_; + height_ = other.height_; + channels_ = other.channels_; ++ linear_colorspace_ = other.linear_colorspace_; ++ data_ = std::move(other.data_); ++ meta_data_ = std::move(other.meta_data_); + other.width_ = 0; + other.height_ = 0; + other.channels_ = 0; +@@ -135,167 +209,16 @@ Bitmap& Bitmap::operator=(Bitmap&& other) noexcept { + return *this; + } + +-bool Bitmap::Allocate(const int width, const int height, const bool as_rgb) { +- width_ = width; +- height_ = height; +- if (as_rgb) { +- const int kNumBitsPerPixel = 24; +- handle_ = +- FreeImageHandle(FreeImage_Allocate(width, height, kNumBitsPerPixel)); +- channels_ = 3; +- } else { +- const int kNumBitsPerPixel = 8; +- handle_ = +- FreeImageHandle(FreeImage_Allocate(width, height, kNumBitsPerPixel)); +- channels_ = 1; +- } +- return handle_.ptr != nullptr; +-} +- +-void Bitmap::Deallocate() { +- handle_ = FreeImageHandle(); +- width_ = 0; +- height_ = 0; +- channels_ = 0; +-} +- +-size_t Bitmap::NumBytes() const { +- if (handle_.ptr != nullptr) { +- return Pitch() * height_; +- } else { +- return 0; +- } +-} +- +-unsigned int Bitmap::BitsPerPixel() const { +- return FreeImage_GetBPP(handle_.ptr); +-} +- +-unsigned int Bitmap::Pitch() const { return FreeImage_GetPitch(handle_.ptr); } +- +-std::vector Bitmap::ConvertToRowMajorArray() const { +- std::vector array(width_ * height_ * channels_); +- size_t i = 0; +- for (int y = 0; y < height_; ++y) { +- const uint8_t* line = FreeImage_GetScanLine(handle_.ptr, height_ - 1 - y); +- for (int x = 0; x < width_; ++x) { +- for (int d = 0; d < channels_; ++d) { +- array[i] = line[x * channels_ + d]; +- i += 1; +- } +- } +- } +- return array; +-} +- +-std::vector Bitmap::ConvertToColMajorArray() const { +- std::vector array(width_ * height_ * channels_); +- size_t i = 0; +- for (int d = 0; d < channels_; ++d) { +- for (int x = 0; x < width_; ++x) { +- for (int y = 0; y < height_; ++y) { +- const uint8_t* line = +- FreeImage_GetScanLine(handle_.ptr, height_ - 1 - y); +- array[i] = line[x * channels_ + d]; +- i += 1; +- } +- } +- } +- return array; +-} +- +-std::vector Bitmap::ConvertToRawBits() const { +- const unsigned int pitch = Pitch(); +- const unsigned int bpp = BitsPerPixel(); +- std::vector raw_bits(pitch * height_ * bpp / 8, 0); +- FreeImage_ConvertToRawBits(raw_bits.data(), +- handle_.ptr, +- pitch, +- bpp, +- FI_RGBA_RED_MASK, +- FI_RGBA_GREEN_MASK, +- FI_RGBA_BLUE_MASK, +- /*topdown=*/true); +- return raw_bits; +-} +- +-Bitmap Bitmap::ConvertFromRawBits( +- const uint8_t* data, int pitch, int width, int height, bool rgb) { +- const unsigned bpp = rgb ? 24 : 8; +- return Bitmap(FreeImage_ConvertFromRawBitsEx(/*copy_source=*/true, +- const_cast(data), +- FIT_BITMAP, +- width, +- height, +- pitch, +- bpp, +- FI_RGBA_RED_MASK, +- FI_RGBA_GREEN_MASK, +- FI_RGBA_BLUE_MASK, +- /*topdown=*/true)); +-} +- +-bool Bitmap::GetPixel(const int x, +- const int y, +- BitmapColor* color) const { +- if (x < 0 || x >= width_ || y < 0 || y >= height_) { +- return false; +- } +- +- const uint8_t* line = FreeImage_GetScanLine(handle_.ptr, height_ - 1 - y); +- +- if (IsGrey()) { +- color->r = line[x]; +- return true; +- } else if (IsRGB()) { +- color->r = line[3 * x + FI_RGBA_RED]; +- color->g = line[3 * x + FI_RGBA_GREEN]; +- color->b = line[3 * x + FI_RGBA_BLUE]; +- return true; +- } +- +- return false; +-} +- +-bool Bitmap::SetPixel(const int x, +- const int y, +- const BitmapColor& color) { +- if (x < 0 || x >= width_ || y < 0 || y >= height_) { +- return false; +- } +- +- uint8_t* line = FreeImage_GetScanLine(handle_.ptr, height_ - 1 - y); +- +- if (IsGrey()) { +- line[x] = color.r; +- return true; +- } else if (IsRGB()) { +- line[3 * x + FI_RGBA_RED] = color.r; +- line[3 * x + FI_RGBA_GREEN] = color.g; +- line[3 * x + FI_RGBA_BLUE] = color.b; +- return true; +- } +- +- return false; +-} +- +-const uint8_t* Bitmap::GetScanline(const int y) const { +- THROW_CHECK_GE(y, 0); +- THROW_CHECK_LT(y, height_); +- return FreeImage_GetScanLine(handle_.ptr, height_ - 1 - y); +-} +- + void Bitmap::Fill(const BitmapColor& color) { +- for (int y = 0; y < height_; ++y) { +- uint8_t* line = FreeImage_GetScanLine(handle_.ptr, height_ - 1 - y); +- for (int x = 0; x < width_; ++x) { +- if (IsGrey()) { +- line[x] = color.r; +- } else if (IsRGB()) { +- line[3 * x + FI_RGBA_RED] = color.r; +- line[3 * x + FI_RGBA_GREEN] = color.g; +- line[3 * x + FI_RGBA_BLUE] = color.b; +- } ++ if (IsGrey()) { ++ std::fill(data_.begin(), data_.end(), color.r); ++ } else { ++ THROW_CHECK_EQ(data_.size() % 3, 0); ++ size_t i = 0; ++ while (i < data_.size()) { ++ data_[i++] = color.r; ++ data_[i++] = color.g; ++ data_[i++] = color.b; + } + } + } +@@ -311,12 +234,9 @@ bool Bitmap::InterpolateNearestNeighbor(const double x, + bool Bitmap::InterpolateBilinear(const double x, + const double y, + BitmapColor* color) const { +- // FreeImage's coordinate system origin is in the lower left of the image. +- const double inv_y = height_ - 1 - y; +- + const int x0 = static_cast(std::floor(x)); + const int x1 = x0 + 1; +- const int y0 = static_cast(std::floor(inv_y)); ++ const int y0 = static_cast(std::floor(y)); + const int y1 = y0 + 1; + + if (x0 < 0 || x1 >= width_ || y0 < 0 || y1 >= height_) { +@@ -324,12 +244,13 @@ bool Bitmap::InterpolateBilinear(const double x, + } + + const double dx = x - x0; +- const double dy = inv_y - y0; ++ const double dy = y - y0; + const double dx_1 = 1 - dx; + const double dy_1 = 1 - dy; + +- const uint8_t* line0 = FreeImage_GetScanLine(handle_.ptr, y0); +- const uint8_t* line1 = FreeImage_GetScanLine(handle_.ptr, y1); ++ const int pitch = width_ * channels_; ++ const uint8_t* line0 = &data_[y0 * pitch]; ++ const uint8_t* line1 = &data_[y1 * pitch]; + + if (IsGrey()) { + // Top row, column-wise linear interpolation. +@@ -348,14 +269,14 @@ bool Bitmap::InterpolateBilinear(const double x, + const uint8_t* p11 = &line1[3 * x1]; + + // Top row, column-wise linear interpolation. +- const double v0_r = dx_1 * p00[FI_RGBA_RED] + dx * p01[FI_RGBA_RED]; +- const double v0_g = dx_1 * p00[FI_RGBA_GREEN] + dx * p01[FI_RGBA_GREEN]; +- const double v0_b = dx_1 * p00[FI_RGBA_BLUE] + dx * p01[FI_RGBA_BLUE]; ++ const double v0_r = dx_1 * p00[0] + dx * p01[0]; ++ const double v0_g = dx_1 * p00[1] + dx * p01[1]; ++ const double v0_b = dx_1 * p00[2] + dx * p01[2]; + + // Bottom row, column-wise linear interpolation. +- const double v1_r = dx_1 * p10[FI_RGBA_RED] + dx * p11[FI_RGBA_RED]; +- const double v1_g = dx_1 * p10[FI_RGBA_GREEN] + dx * p11[FI_RGBA_GREEN]; +- const double v1_b = dx_1 * p10[FI_RGBA_BLUE] + dx * p11[FI_RGBA_BLUE]; ++ const double v1_r = dx_1 * p10[0] + dx * p11[0]; ++ const double v1_g = dx_1 * p10[1] + dx * p11[1]; ++ const double v1_b = dx_1 * p10[2] + dx * p11[2]; + + // Row-wise linear interpolation. + color->r = dy_1 * v0_r + dy * v1_r; +@@ -369,120 +290,94 @@ bool Bitmap::InterpolateBilinear(const double x, + + bool Bitmap::ExifCameraModel(std::string* camera_model) const { + // Read camera make and model +- std::string make_str; +- std::string model_str; +- std::string focal_length; ++ std::string_view make_str; ++ std::string_view model_str; ++ float focal_length = 0; + *camera_model = ""; +- if (ReadExifTag(handle_.ptr, FIMD_EXIF_MAIN, "Make", &make_str)) { +- *camera_model += (make_str + "-"); ++ if (GetMetaData("Make", &make_str)) { ++ *camera_model += std::string(make_str) + "-"; + } else { + *camera_model = ""; + return false; + } +- if (ReadExifTag(handle_.ptr, FIMD_EXIF_MAIN, "Model", &model_str)) { +- *camera_model += (model_str + "-"); ++ if (GetMetaData("Model", &model_str)) { ++ *camera_model += std::string(model_str) + "-"; + } else { + *camera_model = ""; + return false; + } +- if (ReadExifTag(handle_.ptr, +- FIMD_EXIF_EXIF, +- "FocalLengthIn35mmFilm", +- &focal_length) || +- ReadExifTag(handle_.ptr, FIMD_EXIF_EXIF, "FocalLength", &focal_length)) { +- *camera_model += (focal_length + "-"); ++ if (GetMetaData("Exif:FocalLengthIn35mmFilm", "float", &focal_length) || ++ GetMetaData("Exif:FocalLength", "float", &focal_length)) { ++ *camera_model += std::to_string(focal_length) + "-"; + } else { + *camera_model = ""; + return false; + } +- *camera_model += (std::to_string(width_) + "x" + std::to_string(height_)); ++ *camera_model += std::to_string(width_) + "x" + std::to_string(height_); + return true; + } + + bool Bitmap::ExifFocalLength(double* focal_length) const { + const double max_size = std::max(width_, height_); + +- ////////////////////////////////////////////////////////////////////////////// +- // Focal length in 35mm equivalent +- ////////////////////////////////////////////////////////////////////////////// +- +- std::string focal_length_35mm_str; +- if (ReadExifTag(handle_.ptr, +- FIMD_EXIF_EXIF, +- "FocalLengthIn35mmFilm", +- &focal_length_35mm_str)) { +- static const std::regex regex(".*?([0-9.]+).*?mm.*?"); +- std::cmatch result; +- if (std::regex_search(focal_length_35mm_str.c_str(), result, regex)) { +- const double focal_length_35 = std::stold(result[1]); +- if (focal_length_35 > 0) { +- *focal_length = focal_length_35 / 35.0 * max_size; +- return true; +- } ++ float focal_length_35mm = 0; ++ if (GetMetaData("Exif:FocalLengthIn35mmFilm", "float", &focal_length_35mm)) { ++ if (focal_length_35mm > 0) { ++ // Based on https://en.wikipedia.org/wiki/35_mm_equivalent_focal_length ++ // According to CIPA guidelines, 35 mm equivalent focal length is to be ++ // calculated like this: ++ // "focal length in 35 mm camera" = ++ // (Diagonal distance of image area in the 35 mm camera (43.27 mm) / ++ // Diagonal distance of image area on the image sensor of the DSC) ++ // * focal length of the lens of the DSC. ++ const double diagonal = std::sqrt(width_ * width_ + height_ * height_); ++ *focal_length = focal_length_35mm / 43.27 * diagonal; ++ return true; + } + } + +- ////////////////////////////////////////////////////////////////////////////// +- // Focal length in mm +- ////////////////////////////////////////////////////////////////////////////// +- +- std::string focal_length_str; +- if (ReadExifTag( +- handle_.ptr, FIMD_EXIF_EXIF, "FocalLength", &focal_length_str)) { +- std::regex regex(".*?([0-9.]+).*?mm"); +- std::cmatch result; +- if (std::regex_search(focal_length_str.c_str(), result, regex)) { +- const double focal_length_mm = std::stold(result[1]); +- +- // Lookup sensor width in database. +- std::string make_str; +- std::string model_str; +- if (ReadExifTag(handle_.ptr, FIMD_EXIF_MAIN, "Make", &make_str) && +- ReadExifTag(handle_.ptr, FIMD_EXIF_MAIN, "Model", &model_str)) { +- CameraDatabase database; +- double sensor_width; +- if (database.QuerySensorWidth(make_str, model_str, &sensor_width)) { +- *focal_length = focal_length_mm / sensor_width * max_size; +- return true; ++ float focal_length_mm = 0.f; ++ if (GetMetaData("Exif:FocalLength", "float", &focal_length_mm)) { ++ float focal_x_res = 0.f; ++ int focal_x_res_unit = 0; ++ if (GetMetaData("Exif:FocalPlaneXResolution", "float", &focal_x_res) && ++ GetMetaData( ++ "Exif:FocalPlaneResolutionUnit", "int", &focal_x_res_unit)) { ++ if (focal_length_mm > 0 && focal_x_res_unit > 1 && ++ focal_x_res_unit <= 5) { ++ double pixels_per_mm = 0; ++ switch (focal_x_res_unit) { ++ case 2: // inches ++ pixels_per_mm = focal_x_res * 25.4; ++ break; ++ case 3: // cm ++ pixels_per_mm = focal_x_res * 10.0; ++ break; ++ case 4: // mm ++ pixels_per_mm = focal_x_res * 1.0; ++ break; ++ case 5: // um ++ pixels_per_mm = focal_x_res * 0.1; ++ break; ++ default: ++ LOG(FATAL) << "Unexpected FocalPlaneXResolution value"; + } ++ *focal_length = focal_length_mm / pixels_per_mm; ++ return true; + } ++ } + +- // Extract sensor width from EXIF. +- std::string pixel_x_dim_str; +- std::string x_res_str; +- std::string res_unit_str; +- if (ReadExifTag(handle_.ptr, +- FIMD_EXIF_EXIF, +- "PixelXDimension", +- &pixel_x_dim_str) && +- ReadExifTag(handle_.ptr, +- FIMD_EXIF_EXIF, +- "FocalPlaneXResolution", +- &x_res_str) && +- ReadExifTag(handle_.ptr, +- FIMD_EXIF_EXIF, +- "FocalPlaneResolutionUnit", +- &res_unit_str)) { +- regex = std::regex(".*?([0-9.]+).*?"); +- if (std::regex_search(pixel_x_dim_str.c_str(), result, regex)) { +- const double pixel_x_dim = std::stold(result[1]); +- regex = std::regex(".*?([0-9.]+).*?/.*?([0-9.]+).*?"); +- if (std::regex_search(x_res_str.c_str(), result, regex)) { +- const double x_res = std::stold(result[2]) / std::stold(result[1]); +- // Use PixelXDimension instead of actual width of image, since +- // the image might have been resized, but the EXIF data preserved. +- const double ccd_width = x_res * pixel_x_dim; +- if (ccd_width > 0 && focal_length_mm > 0) { +- if (res_unit_str == "cm") { +- *focal_length = focal_length_mm / (ccd_width * 10.0) * max_size; +- return true; +- } else if (res_unit_str == "inches") { +- *focal_length = focal_length_mm / (ccd_width * 25.4) * max_size; +- return true; +- } +- } +- } +- } ++ // Lookup sensor width in database. ++ std::string_view make_str; ++ std::string_view model_str; ++ if (GetMetaData("Make", &make_str) && GetMetaData("Model", &model_str)) { ++ CameraDatabase database; ++ double sensor_width_mm; ++ if (database.QuerySensorWidth(std::string(make_str), ++ std::string(model_str), ++ &sensor_width_mm)) { ++ *focal_length = focal_length_mm / sensor_width_mm * max_size; ++ return true; + } + } + } +@@ -491,199 +386,216 @@ bool Bitmap::ExifFocalLength(double* focal_length) const { + } + + bool Bitmap::ExifLatitude(double* latitude) const { +- std::string str; ++ std::string_view latitude_ref; + double sign = 1.0; +- if (ReadExifTag(handle_.ptr, FIMD_EXIF_GPS, "GPSLatitudeRef", &str)) { +- StringTrim(&str); +- StringToLower(&str); +- if (!str.empty() && str[0] == 's') { ++ if (GetMetaData("GPS:LatitudeRef", &latitude_ref)) { ++ if (latitude_ref == "N" || latitude_ref == "n") { ++ sign = 1.0; ++ } else if (latitude_ref == "S" || latitude_ref == "s") { + sign = -1.0; + } + } +- if (ReadExifTag(handle_.ptr, FIMD_EXIF_GPS, "GPSLatitude", &str)) { +- static const std::regex regex(".*?([0-9.]+):([0-9.]+):([0-9.]+).*?"); +- std::cmatch result; +- if (std::regex_search(str.c_str(), result, regex)) { +- const double hours = std::stold(result[1]); +- const double minutes = std::stold(result[2]); +- const double seconds = std::stold(result[3]); +- double value = hours + minutes / 60.0 + seconds / 3600.0; +- if (value > 0 && sign < 0) { +- value *= sign; +- } +- *latitude = value; +- return true; ++ float deg_min_sec[3] = {0.0}; ++ if (GetMetaData("GPS:Latitude", "point", °_min_sec)) { ++ *latitude = ++ deg_min_sec[0] + deg_min_sec[1] / 60.0 + deg_min_sec[2] / 3600.0; ++ if (*latitude > 0 && sign < 0) { ++ *latitude *= sign; + } ++ return true; + } + return false; + } + + bool Bitmap::ExifLongitude(double* longitude) const { +- std::string str; ++ std::string_view longitude_ref; + double sign = 1.0; +- if (ReadExifTag(handle_.ptr, FIMD_EXIF_GPS, "GPSLongitudeRef", &str)) { +- StringTrim(&str); +- StringToLower(&str); +- if (!str.empty() && str[0] == 'w') { ++ if (GetMetaData("GPS:LongitudeRef", &longitude_ref)) { ++ if (longitude_ref == "W" || longitude_ref == "w") { ++ sign = 1.0; ++ } else if (longitude_ref == "E" || longitude_ref == "e") { + sign = -1.0; + } + } +- if (ReadExifTag(handle_.ptr, FIMD_EXIF_GPS, "GPSLongitude", &str)) { +- static const std::regex regex(".*?([0-9.]+):([0-9.]+):([0-9.]+).*?"); +- std::cmatch result; +- if (std::regex_search(str.c_str(), result, regex)) { +- const double hours = std::stold(result[1]); +- const double minutes = std::stold(result[2]); +- const double seconds = std::stold(result[3]); +- double value = hours + minutes / 60.0 + seconds / 3600.0; +- if (value > 0 && sign < 0) { +- value *= sign; +- } +- *longitude = value; +- return true; ++ float deg_min_sec[3] = {0.0}; ++ if (GetMetaData("GPS:Longitude", "point", °_min_sec)) { ++ *longitude = ++ deg_min_sec[0] + deg_min_sec[1] / 60.0 + deg_min_sec[2] / 3600.0; ++ if (*longitude > 0 && sign < 0) { ++ *longitude *= sign; + } ++ return true; + } + return false; + } + + bool Bitmap::ExifAltitude(double* altitude) const { +- std::string str; +- if (ReadExifTag(handle_.ptr, FIMD_EXIF_GPS, "GPSAltitude", &str)) { +- static const std::regex regex(".*?([0-9.]+).*?/.*?([0-9.]+).*?"); +- std::cmatch result; +- if (std::regex_search(str.c_str(), result, regex)) { +- *altitude = std::stold(result[1]) / std::stold(result[2]); +- return true; ++ std::string_view altitude_ref; ++ double sign = 1.0; ++ if (GetMetaData("GPS:AltitudeRef", &altitude_ref)) { ++ if (altitude_ref == "0") { ++ sign = 1.0; ++ } else if (altitude_ref == "1") { ++ sign = -1.0; + } + } ++ float altitude_float = 0.f; ++ if (GetMetaData("GPS:Altitude", "float", &altitude_float)) { ++ *altitude = altitude_float; ++ if (*altitude > 0 && sign < 0) { ++ *altitude *= sign; ++ } ++ return true; ++ } + return false; + } + +-bool Bitmap::Read(const std::string& path, const bool as_rgb) { ++bool Bitmap::Read(const std::string& path, ++ const bool as_rgb, ++ const bool linearize_colorspace) { + if (!ExistsFile(path)) { ++ VLOG(3) << "Failed to read bitmap, because file does not exist"; + return false; + } + +- const FREE_IMAGE_FORMAT format = FreeImage_GetFileType(path.c_str(), 0); ++ OIIO::ImageSpec config; ++ config["oiio:reorient"] = 0; + +- if (format == FIF_UNKNOWN) { ++ const auto input = OIIO::ImageInput::open(path, &config); ++ if (!input) { ++ VLOG(3) << "Failed to read bitmap specs"; + return false; + } + +- handle_ = FreeImageHandle(FreeImage_Load(format, path.c_str())); +- if (handle_.ptr == nullptr) { ++ const OIIO::ImageSpec& image_spec = input->spec(); ++ width_ = image_spec.width; ++ height_ = image_spec.height; ++ channels_ = image_spec.nchannels; ++ if (channels_ != 1 && channels_ != 3) { ++ VLOG(3) << "Bitmap is not grayscale or RGB"; + return false; + } + +- if (!IsPtrRGB(handle_.ptr) && as_rgb) { +- FIBITMAP* converted_bitmap = FreeImage_ConvertTo24Bits(handle_.ptr); +- handle_ = FreeImageHandle(converted_bitmap); +- } else if (!IsPtrGrey(handle_.ptr) && !as_rgb) { +- if (FreeImage_GetBPP(handle_.ptr) != 24) { +- FIBITMAP* converted_bitmap_24 = FreeImage_ConvertTo24Bits(handle_.ptr); +- handle_ = FreeImageHandle(converted_bitmap_24); ++ data_.resize(width_ * height_ * channels_); ++ input->read_image(0, 0, 0, channels_, OIIO::TypeDesc::UINT8, data_.data()); ++ input->close(); ++ ++ auto meta_data = std::make_unique(); ++ meta_data->image_spec = image_spec; ++ meta_data_ = std::move(meta_data); ++ ++ if (linearize_colorspace) { ++ const std::string colorspace = image_spec["oiio:ColorSpace"]; ++ if (IsEquivalentColorSpace(colorspace, "linear")) { ++ data_ = ConvertColorSpace( ++ data_.data(), width_, height_, channels_, colorspace, "linear"); + } +- FIBITMAP* converted_bitmap = FreeImage_ConvertToGreyscale(handle_.ptr); +- handle_ = FreeImageHandle(converted_bitmap); + } + +- if (!IsPtrSupported(handle_.ptr)) { +- handle_ = FreeImageHandle(); +- return false; ++ if (as_rgb && channels_ != 3) { ++ *this = CloneAsRGB(); ++ } else if (!as_rgb && channels_ != 1) { ++ *this = CloneAsGrey(); + } + +- width_ = FreeImage_GetWidth(handle_.ptr); +- height_ = FreeImage_GetHeight(handle_.ptr); +- channels_ = as_rgb ? 3 : 1; +- + return true; + } + +-bool Bitmap::Write(const std::string& path, const int flags) const { +- FREE_IMAGE_FORMAT save_format = FreeImage_GetFIFFromFilename(path.c_str()); +- if (save_format == FIF_UNKNOWN) { +- // If format could not be deduced, save as PNG by default. +- save_format = FIF_PNG; ++bool Bitmap::Write(const std::string& path, ++ const bool delinearize_colorspace) const { ++ const auto output = OIIO::ImageOutput::create(path); ++ if (!output) { ++ std::cerr << "Could not create an ImageOutput for " << path ++ << ", error = " << OIIO::geterror() << "\n"; ++ return false; + } + +- int save_flags = flags; +- if (save_format == FIF_JPEG && flags == 0) { +- // Use superb JPEG quality by default to avoid artifacts. +- save_flags = JPEG_QUALITYSUPERB; ++ auto* meta_data = OIIOMetaData::Upcast(meta_data_.get()); ++ ++ const uint8_t* output_data_ptr = data_.data(); ++ std::vector maybe_linearized_output_data; ++ if (delinearize_colorspace && linear_colorspace_) { ++ std::string_view colorspace; ++ if (!GetMetaData("oiio:ColorSpace", &colorspace)) { ++ // Assume sRGB color space if not specified. ++ colorspace = "sRGB"; ++ SetImageSpecColorSpace(meta_data->image_spec, ++ OIIOFromStdStringView(colorspace)); ++ } ++ ++ maybe_linearized_output_data = ConvertColorSpace( ++ data_.data(), width_, height_, channels_, "linear", colorspace); ++ output_data_ptr = maybe_linearized_output_data.data(); + } + +- bool success = false; +- if (save_flags == 0) { +- success = FreeImage_Save(save_format, handle_.ptr, path.c_str()); +- } else { +- success = +- FreeImage_Save(save_format, handle_.ptr, path.c_str(), save_flags); ++ if (HasFileExtension(path, ".jpg") || HasFileExtension(path, ".jpeg")) { ++ std::string_view compression; ++ if (!GetMetaData("Compression", &compression)) { ++ // Save JPEG in superb quality by default to reduce compression artifacts. ++ meta_data->image_spec["Compression"] = "jpeg:100"; ++ } + } + +- return success; +-} ++ if (!output->open(path, meta_data->image_spec)) { ++ VLOG(3) << "Could not open " << path << ", error = " << output->geterror() ++ << "\n"; ++ return false; ++ } + +-void Bitmap::Smooth(const float sigma_x, const float sigma_y) { +- std::vector array(width_ * height_); +- std::vector array_smoothed(width_ * height_); +- for (int d = 0; d < channels_; ++d) { +- size_t i = 0; +- for (int y = 0; y < height_; ++y) { +- const uint8_t* line = FreeImage_GetScanLine(handle_.ptr, height_ - 1 - y); +- for (int x = 0; x < width_; ++x) { +- array[i] = line[x * channels_ + d]; +- i += 1; +- } +- } ++ if (!output->write_image(OIIO::TypeDesc::UINT8, output_data_ptr)) { ++ VLOG(3) << "Could not write pixels to " << path ++ << ", error = " << output->geterror() << "\n"; ++ return false; ++ } + +- vl_imsmooth_f(array_smoothed.data(), +- width_, +- array.data(), +- width_, +- height_, +- width_, +- sigma_x, +- sigma_y); +- +- i = 0; +- for (int y = 0; y < height_; ++y) { +- uint8_t* line = FreeImage_GetScanLine(handle_.ptr, height_ - 1 - y); +- for (int x = 0; x < width_; ++x) { +- line[x * channels_ + d] = +- TruncateCast(array_smoothed[i]); +- i += 1; +- } +- } ++ if (!output->close()) { ++ VLOG(3) << "Error closing " << path << ", error = " << output->geterror() ++ << "\n"; ++ return false; + } ++ ++ return true; + } + + void Bitmap::Rescale(const int new_width, + const int new_height, + RescaleFilter filter) { +- FREE_IMAGE_FILTER fi_filter = FILTER_BILINEAR; +- switch (filter) { +- case RescaleFilter::kBilinear: +- fi_filter = FILTER_BILINEAR; +- break; +- case RescaleFilter::kBox: +- fi_filter = FILTER_BOX; +- break; +- default: +- LOG(FATAL_THROW) << "Filter not implemented"; +- } +- SetPtr(FreeImage_Rescale(handle_.ptr, new_width, new_height, fi_filter)); +-} ++ const OIIO::ImageBuf buf( ++ OIIO::ImageSpec(width_, height_, channels_, OIIO::TypeDesc::UINT8), ++ data_.data()); ++ std::vector new_data(new_width * new_height * channels_); ++ OIIO::ImageBuf new_buf( ++ OIIO::ImageSpec(new_width, new_height, channels_, OIIO::TypeDesc::UINT8), ++ new_data.data()); ++ THROW_CHECK(OIIO::ImageBufAlgo::resize(new_buf, buf)); + +-Bitmap Bitmap::Clone() const { +- FIBITMAP* cloned = FreeImage_Clone(handle_.ptr); +- return Bitmap(cloned); ++ width_ = new_width; ++ height_ = new_height; ++ data_ = std::move(new_data); ++ auto* meta_data = OIIOMetaData::Upcast(meta_data_.get()); ++ meta_data->image_spec.width = new_width; ++ meta_data->image_spec.height = new_height; + } + ++Bitmap Bitmap::Clone() const { return *this; } ++ + Bitmap Bitmap::CloneAsGrey() const { + if (IsGrey()) { + return Clone(); + } else { +- return Bitmap(FreeImage_ConvertToGreyscale(handle_.ptr)); ++ Bitmap cloned; ++ cloned.width_ = width_; ++ cloned.height_ = height_; ++ cloned.channels_ = 1; ++ cloned.linear_colorspace_ = linear_colorspace_; ++ cloned.data_.resize(width_ * height_); ++ for (size_t i = 0; i < cloned.data_.size(); ++i) { ++ cloned.data_[i] = ++ std::round(.2126f * data_[3 * i + 0] + .7152f * data_[3 * i + 1] + ++ .0722f * data_[3 * i + 2]); ++ } ++ cloned.meta_data_ = OIIOMetaData::Clone(meta_data_); ++ return cloned; + } + } + +@@ -691,58 +603,72 @@ Bitmap Bitmap::CloneAsRGB() const { + if (IsRGB()) { + return Clone(); + } else { +- return Bitmap(FreeImage_ConvertTo24Bits(handle_.ptr)); ++ THROW_CHECK_EQ(channels_, 1); ++ Bitmap cloned; ++ cloned.width_ = width_; ++ cloned.height_ = height_; ++ cloned.channels_ = 3; ++ cloned.linear_colorspace_ = linear_colorspace_; ++ cloned.data_.resize(width_ * height_ * 3); ++ for (size_t i = 0; i < data_.size(); ++i) { ++ cloned.data_[3 * i + 0] = data_[i]; ++ cloned.data_[3 * i + 1] = data_[i]; ++ cloned.data_[3 * i + 2] = data_[i]; ++ } ++ cloned.meta_data_ = OIIOMetaData::Clone(meta_data_); ++ return cloned; ++ } ++} ++ ++void Bitmap::SetMetaData(const std::string_view& name, ++ const std::string_view& type, ++ const void* value) { ++ THROW_CHECK_NE(type, "string"); ++ auto* meta_data = OIIOMetaData::Upcast(meta_data_.get()); ++ OIIO::TypeDesc type_desc; ++ type_desc.fromstring(OIIOFromStdStringView(type)); ++ THROW_CHECK_NE(type_desc, OIIO::TypeDesc::UNKNOWN); ++ meta_data->image_spec.attribute( ++ OIIOFromStdStringView(name), type_desc, value); ++} ++ ++void Bitmap::SetMetaData(const std::string_view& name, ++ const std::string_view& value) { ++ auto* meta_data = OIIOMetaData::Upcast(meta_data_.get()); ++ meta_data->image_spec.attribute(OIIOFromStdStringView(name), ++ OIIOFromStdStringView(value)); ++} ++ ++bool Bitmap::GetMetaData(const std::string_view& name, ++ const std::string_view& type, ++ void* value) const { ++ THROW_CHECK_NE(type, "string"); ++ auto* meta_data = OIIOMetaData::Upcast(meta_data_.get()); ++ OIIO::TypeDesc type_desc; ++ type_desc.fromstring(OIIOFromStdStringView(type)); ++ THROW_CHECK_NE(type_desc, OIIO::TypeDesc::UNKNOWN); ++ return meta_data->image_spec.getattribute( ++ OIIOFromStdStringView(name), type_desc, value); ++} ++ ++bool Bitmap::GetMetaData(const std::string_view& name, ++ std::string_view* value) const { ++ auto* meta_data = OIIOMetaData::Upcast(meta_data_.get()); ++ OIIO::ustring ustring_value; ++ if (meta_data->image_spec.getattribute( ++ OIIOFromStdStringView(name), OIIO::TypeString, &ustring_value)) { ++ *value = std::string_view(ustring_value.data(), ustring_value.size()); ++ return true; + } ++ return false; + } + + void Bitmap::CloneMetadata(Bitmap* target) const { + THROW_CHECK_NOTNULL(target); +- THROW_CHECK_NOTNULL(target->Data()); +- FreeImage_CloneMetadata(handle_.ptr, target->Data()); +-} +- +-void Bitmap::SetPtr(FIBITMAP* ptr) { +- THROW_CHECK_NOTNULL(ptr); +- +- if (!IsPtrSupported(ptr)) { +- FreeImageHandle temp_handle(ptr); +- ptr = FreeImage_ConvertTo24Bits(temp_handle.ptr); +- THROW_CHECK(IsPtrSupported(ptr)); +- } +- +- handle_ = FreeImageHandle(ptr); +- width_ = FreeImage_GetWidth(handle_.ptr); +- height_ = FreeImage_GetHeight(handle_.ptr); +- channels_ = IsPtrRGB(handle_.ptr) ? 3 : 1; +-} +- +-Bitmap::FreeImageHandle::FreeImageHandle() : ptr(nullptr) {} +- +-Bitmap::FreeImageHandle::FreeImageHandle(FIBITMAP* ptr) : ptr(ptr) {} +- +-Bitmap::FreeImageHandle::~FreeImageHandle() { +- if (ptr != nullptr) { +- FreeImage_Unload(ptr); +- ptr = nullptr; +- } +-} +- +-Bitmap::FreeImageHandle::FreeImageHandle( +- Bitmap::FreeImageHandle&& other) noexcept { +- ptr = other.ptr; +- other.ptr = nullptr; +-} +- +-Bitmap::FreeImageHandle& Bitmap::FreeImageHandle::operator=( +- Bitmap::FreeImageHandle&& other) noexcept { +- if (this != &other) { +- if (ptr != nullptr) { +- FreeImage_Unload(ptr); +- } +- ptr = other.ptr; +- other.ptr = nullptr; +- } +- return *this; ++ target->meta_data_ = OIIOMetaData::Clone(meta_data_); ++ auto* target_meta_data = OIIOMetaData::Upcast(target->meta_data_.get()); ++ target_meta_data->image_spec.width = target->Width(); ++ target_meta_data->image_spec.height = target->Height(); + } + + std::ostream& operator<<(std::ostream& stream, const Bitmap& bitmap) { +diff --git a/src/colmap/sensor/bitmap.h b/src/colmap/sensor/bitmap.h +index 925360ba..e07d6aee 100644 +--- a/src/colmap/sensor/bitmap.h ++++ b/src/colmap/sensor/bitmap.h +@@ -36,11 +36,10 @@ + #include + #include + #include ++#include + #include + #include + +-struct FIBITMAP; +- + namespace colmap { + + // Templated bitmap color class. +@@ -65,70 +64,47 @@ struct BitmapColor { + T b; + }; + +-// Wrapper class around FreeImage bitmaps. ++// Wrapper class around bitmaps. + class Bitmap { + public: + Bitmap(); ++ Bitmap(int width, int height, bool as_rgb, bool linear_colorspace = true); + +- // Copy constructor. + Bitmap(const Bitmap& other); +- // Move constructor. + Bitmap(Bitmap&& other) noexcept; + +- // Create bitmap object from existing FreeImage bitmap object. Note that +- // this class takes ownership of the object. +- explicit Bitmap(FIBITMAP* data); +- +- // Copy assignment. + Bitmap& operator=(const Bitmap& other); +- // Move assignment. + Bitmap& operator=(Bitmap&& other) noexcept; + +- // Allocate bitmap by overwriting the existing data. +- bool Allocate(int width, int height, bool as_rgb); +- +- // Deallocate the bitmap by releasing the existing data. +- void Deallocate(); +- +- // Get pointer to underlying FreeImage object. +- inline const FIBITMAP* Data() const; +- inline FIBITMAP* Data(); +- + // Dimensions of bitmap. + inline int Width() const; + inline int Height() const; + inline int Channels() const; + +- // Number of bits per pixel. This is 8 for grey and 24 for RGB image. +- unsigned int BitsPerPixel() const; ++ // Number of bits per pixel. This is 8 for grey and 24 for RGB images. ++ inline int BitsPerPixel() const; ++ ++ // Number of bytes required to store image. ++ inline size_t NumBytes() const; ++ ++ // Scan line size in bytes, also known as stride. ++ inline int Pitch() const; + +- // Scan width of bitmap which differs from the actual image width to achieve +- // 32 bit aligned memory. Also known as stride. +- unsigned int Pitch() const; ++ // Check whether the image is empty (i.e., width/height=0). ++ inline bool IsEmpty() const; + + // Check whether image is grey- or colorscale. + inline bool IsRGB() const; + inline bool IsGrey() const; + +- // Number of bytes required to store image. +- size_t NumBytes() const; +- +- // Copy raw image data to array. +- std::vector ConvertToRowMajorArray() const; +- std::vector ConvertToColMajorArray() const; +- +- // Convert to/from raw bits. +- std::vector ConvertToRawBits() const; +- static Bitmap ConvertFromRawBits( +- const uint8_t* data, int pitch, int width, int height, bool rgb = true); ++ // Access raw image data array. ++ inline std::vector& RowMajorData(); ++ inline const std::vector& RowMajorData() const; + + // Manipulate individual pixels. For grayscale images, only the red element + // of the RGB color is used. +- bool GetPixel(int x, int y, BitmapColor* color) const; +- bool SetPixel(int x, int y, const BitmapColor& color); +- +- // Get pointer to y-th scanline, where the 0-th scanline is at the top. +- const uint8_t* GetScanline(int y) const; ++ inline bool GetPixel(int x, int y, BitmapColor* color) const; ++ inline bool SetPixel(int x, int y, const BitmapColor& color); + + // Fill entire bitmap with uniform color. For grayscale images, the first + // element of the vector is used. +@@ -148,15 +124,15 @@ class Bitmap { + bool ExifLongitude(double* longitude) const; + bool ExifAltitude(double* altitude) const; + +- // Read bitmap at given path and convert to grey- or colorscale. +- bool Read(const std::string& path, bool as_rgb = true); +- +- // Write image to file. Flags can be used to set e.g. the JPEG quality. +- // Consult the FreeImage documentation for all available flags. +- bool Write(const std::string& path, int flags = 0) const; ++ // Read bitmap at given path and convert to grey- or colorscale. Defaults to ++ // linearizing the colorspace for image processing. ++ bool Read(const std::string& path, ++ bool as_rgb = true, ++ bool linearize_colorspace = false); + +- // Smooth the image using a Gaussian kernel. +- void Smooth(float sigma_x, float sigma_y); ++ // Write bitmap to file at given path. If the bitmap is linearized, write it ++ // de-linearized to the file in sRGB. ++ bool Write(const std::string& path, bool delinearize_colorspace = true) const; + + // Rescale image to the new dimensions. + enum class RescaleFilter { +@@ -172,27 +148,30 @@ class Bitmap { + Bitmap CloneAsGrey() const; + Bitmap CloneAsRGB() const; + ++ // Access metadata information (EXIF). ++ void SetMetaData(const std::string_view& name, ++ const std::string_view& type, ++ const void* value); ++ void SetMetaData(const std::string_view& name, const std::string_view& value); ++ bool GetMetaData(const std::string_view& name, ++ const std::string_view& type, ++ void* value) const; ++ bool GetMetaData(const std::string_view& name, std::string_view* value) const; ++ + // Clone metadata from this bitmap object to another target bitmap object. + void CloneMetadata(Bitmap* target) const; + +- private: +- struct FreeImageHandle { +- FreeImageHandle(); +- explicit FreeImageHandle(FIBITMAP* ptr); +- ~FreeImageHandle(); +- FreeImageHandle(FreeImageHandle&&) noexcept; +- FreeImageHandle& operator=(FreeImageHandle&&) noexcept; +- FreeImageHandle(const FreeImageHandle&) = delete; +- FreeImageHandle& operator=(const FreeImageHandle&) = delete; +- FIBITMAP* ptr; ++ struct MetaData { ++ virtual ~MetaData() = default; + }; + +- void SetPtr(FIBITMAP* ptr); +- +- FreeImageHandle handle_; ++ private: + int width_; + int height_; + int channels_; ++ bool linear_colorspace_; ++ std::vector data_; ++ std::unique_ptr meta_data_; + }; + + std::ostream& operator<<(std::ostream& stream, const Bitmap& bitmap); +@@ -264,15 +243,70 @@ std::ostream& operator<<(std::ostream& output, const BitmapColor& color) { + return output; + } + +-FIBITMAP* Bitmap::Data() { return handle_.ptr; } +-const FIBITMAP* Bitmap::Data() const { return handle_.ptr; } +- + int Bitmap::Width() const { return width_; } ++ + int Bitmap::Height() const { return height_; } ++ + int Bitmap::Channels() const { return channels_; } + ++size_t Bitmap::NumBytes() const { return data_.size(); } ++ ++int Bitmap::BitsPerPixel() const { return channels_ * 8; } ++ ++int Bitmap::Pitch() const { return width_ * channels_; } ++ ++bool Bitmap::IsEmpty() const { return NumBytes() == 0; } ++ + bool Bitmap::IsRGB() const { return channels_ == 3; } + + bool Bitmap::IsGrey() const { return channels_ == 1; } + ++std::vector& Bitmap::RowMajorData() { return data_; } ++ ++const std::vector& Bitmap::RowMajorData() const { return data_; } ++ ++bool Bitmap::GetPixel(const int x, ++ const int y, ++ BitmapColor* color) const { ++ if (x < 0 || x >= width_ || y < 0 || y >= height_) { ++ return false; ++ } ++ ++ if (IsGrey()) { ++ color->r = data_[y * width_ + x]; ++ color->g = color->r; ++ color->b = color->r; ++ return true; ++ } else if (IsRGB()) { ++ const uint8_t* pixel = &data_[(y * width_ + x) * channels_]; ++ color->r = pixel[0]; ++ color->g = pixel[1]; ++ color->b = pixel[2]; ++ return true; ++ } ++ ++ return false; ++} ++ ++bool Bitmap::SetPixel(const int x, ++ const int y, ++ const BitmapColor& color) { ++ if (x < 0 || x >= width_ || y < 0 || y >= height_) { ++ return false; ++ } ++ ++ if (IsGrey()) { ++ data_[y * width_ + x] = color.r; ++ return true; ++ } else if (IsRGB()) { ++ uint8_t* pixel = &data_[(y * width_ + x) * channels_]; ++ pixel[0] = color.r; ++ pixel[1] = color.g; ++ pixel[2] = color.b; ++ return true; ++ } ++ ++ return false; ++} ++ + } // namespace colmap +diff --git a/src/colmap/sensor/bitmap_test.cc b/src/colmap/sensor/bitmap_test.cc +index 0a1c787a..09998aac 100644 +--- a/src/colmap/sensor/bitmap_test.cc ++++ b/src/colmap/sensor/bitmap_test.cc +@@ -31,7 +31,7 @@ + + #include "colmap/util/testing.h" + +-#include ++#include + #include + + namespace colmap { +@@ -53,6 +53,13 @@ TEST(Bitmap, BitmapGrayColor) { + EXPECT_EQ(color.b, 5); + } + ++TEST(Bitmap, BitmapRGBColor) { ++ BitmapColor color(1, 2, 3); ++ EXPECT_EQ(color.r, 1); ++ EXPECT_EQ(color.g, 2); ++ EXPECT_EQ(color.b, 3); ++} ++ + TEST(Bitmap, BitmapColorCast) { + BitmapColor color1(1.1f, 2.9f, -3.0f); + BitmapColor color2 = color1.Cast(); +@@ -68,285 +75,125 @@ TEST(Bitmap, Empty) { + EXPECT_EQ(bitmap.Channels(), 0); + EXPECT_FALSE(bitmap.IsRGB()); + EXPECT_FALSE(bitmap.IsGrey()); ++ EXPECT_TRUE(bitmap.IsEmpty()); + } + + TEST(Bitmap, Print) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, true); ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); + std::ostringstream stream; + stream << bitmap; +- EXPECT_EQ(stream.str(), "Bitmap(width=100, height=100, channels=3)"); ++ EXPECT_EQ(stream.str(), "Bitmap(width=100, height=80, channels=3)"); + } + + TEST(Bitmap, AllocateRGB) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, true); ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); + EXPECT_EQ(bitmap.Width(), 100); +- EXPECT_EQ(bitmap.Height(), 100); ++ EXPECT_EQ(bitmap.Height(), 80); + EXPECT_EQ(bitmap.Channels(), 3); + EXPECT_TRUE(bitmap.IsRGB()); + EXPECT_FALSE(bitmap.IsGrey()); ++ EXPECT_FALSE(bitmap.IsEmpty()); + } + + TEST(Bitmap, AllocateGrey) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, false); ++ Bitmap bitmap(100, 80, /*as_rgb=*/false); + EXPECT_EQ(bitmap.Width(), 100); +- EXPECT_EQ(bitmap.Height(), 100); ++ EXPECT_EQ(bitmap.Height(), 80); + EXPECT_EQ(bitmap.Channels(), 1); + EXPECT_FALSE(bitmap.IsRGB()); + EXPECT_TRUE(bitmap.IsGrey()); +-} +- +-TEST(Bitmap, Deallocate) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, false); +- bitmap.Deallocate(); +- EXPECT_EQ(bitmap.Width(), 0); +- EXPECT_EQ(bitmap.Height(), 0); +- EXPECT_EQ(bitmap.Channels(), 0); +- EXPECT_EQ(bitmap.NumBytes(), 0); +- EXPECT_FALSE(bitmap.IsRGB()); +- EXPECT_FALSE(bitmap.IsGrey()); ++ EXPECT_FALSE(bitmap.IsEmpty()); + } + + TEST(Bitmap, MoveConstruct) { +- Bitmap bitmap; +- bitmap.Allocate(2, 1, true); +- const auto* data = bitmap.Data(); ++ Bitmap bitmap(2, 1, /*as_rgb=*/true); + Bitmap moved_bitmap(std::move(bitmap)); + EXPECT_EQ(moved_bitmap.Width(), 2); + EXPECT_EQ(moved_bitmap.Height(), 1); + EXPECT_EQ(moved_bitmap.Channels(), 3); +- EXPECT_EQ(moved_bitmap.Data(), data); + // NOLINTBEGIN(bugprone-use-after-move,clang-analyzer-cplusplus.Move) + EXPECT_EQ(bitmap.Width(), 0); + EXPECT_EQ(bitmap.Height(), 0); + EXPECT_EQ(bitmap.Channels(), 0); + EXPECT_EQ(bitmap.NumBytes(), 0); +- EXPECT_EQ(bitmap.Data(), nullptr); + // NOLINTEND(bugprone-use-after-move,clang-analyzer-cplusplus.Move) + } + + TEST(Bitmap, MoveAssign) { +- Bitmap bitmap; +- bitmap.Allocate(2, 1, true); +- const auto* data = bitmap.Data(); ++ Bitmap bitmap(2, 1, /*as_rgb=*/true); + Bitmap moved_bitmap = std::move(bitmap); + EXPECT_EQ(moved_bitmap.Width(), 2); + EXPECT_EQ(moved_bitmap.Height(), 1); + EXPECT_EQ(moved_bitmap.Channels(), 3); +- EXPECT_EQ(moved_bitmap.Data(), data); + // NOLINTBEGIN(bugprone-use-after-move,clang-analyzer-cplusplus.Move) + EXPECT_EQ(bitmap.Width(), 0); + EXPECT_EQ(bitmap.Height(), 0); + EXPECT_EQ(bitmap.Channels(), 0); + EXPECT_EQ(bitmap.NumBytes(), 0); +- EXPECT_EQ(bitmap.Data(), nullptr); + // NOLINTEND(bugprone-use-after-move,clang-analyzer-cplusplus.Move) + } + + TEST(Bitmap, BitsPerPixel) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, true); ++ Bitmap bitmap(1, 1, /*as_rgb=*/true); + EXPECT_EQ(bitmap.BitsPerPixel(), 24); +- bitmap.Allocate(100, 100, false); ++ bitmap = Bitmap(1, 1, /*as_rgb=*/false); + EXPECT_EQ(bitmap.BitsPerPixel(), 8); + } + + TEST(Bitmap, NumBytes) { + Bitmap bitmap; + EXPECT_EQ(bitmap.NumBytes(), 0); +- bitmap.Allocate(100, 100, true); +- EXPECT_EQ(bitmap.NumBytes(), 3 * 100 * 100); +- bitmap.Allocate(100, 100, false); +- EXPECT_EQ(bitmap.NumBytes(), 100 * 100); ++ bitmap = Bitmap(100, 80, /*as_rgb=*/true); ++ EXPECT_EQ(bitmap.NumBytes(), 3 * 100 * 80); ++ bitmap = Bitmap(100, 80, /*as_rgb=*/false); ++ EXPECT_EQ(bitmap.NumBytes(), 100 * 80); + } + +-TEST(Bitmap, ConvertToRowMajorArrayRGB) { +- Bitmap bitmap; +- bitmap.Allocate(2, 2, true); ++TEST(Bitmap, RowMajorDataRGB) { ++ Bitmap bitmap(2, 3, /*as_rgb=*/true); + bitmap.SetPixel(0, 0, BitmapColor(0, 0, 0)); + bitmap.SetPixel(0, 1, BitmapColor(1, 0, 0)); +- bitmap.SetPixel(1, 0, BitmapColor(2, 0, 0)); +- bitmap.SetPixel(1, 1, BitmapColor(3, 0, 0)); +- const std::vector array = bitmap.ConvertToRowMajorArray(); +- ASSERT_EQ(array.size(), 12); +- EXPECT_EQ(array[0], 0); +- EXPECT_EQ(array[1], 0); +- EXPECT_EQ(array[2], 0); +- EXPECT_EQ(array[3], 0); +- EXPECT_EQ(array[4], 0); +- EXPECT_EQ(array[5], 2); +- EXPECT_EQ(array[6], 0); +- EXPECT_EQ(array[7], 0); +- EXPECT_EQ(array[8], 1); +- EXPECT_EQ(array[9], 0); +- EXPECT_EQ(array[10], 0); +- EXPECT_EQ(array[11], 3); +-} +- +-TEST(Bitmap, ConvertToRowMajorArrayGrey) { +- Bitmap bitmap; +- bitmap.Allocate(2, 2, false); +- bitmap.SetPixel(0, 0, BitmapColor(0, 0, 0)); +- bitmap.SetPixel(0, 1, BitmapColor(1, 0, 0)); +- bitmap.SetPixel(1, 0, BitmapColor(2, 0, 0)); +- bitmap.SetPixel(1, 1, BitmapColor(3, 0, 0)); +- const std::vector array = bitmap.ConvertToRowMajorArray(); +- ASSERT_EQ(array.size(), 4); +- EXPECT_EQ(array[0], 0); +- EXPECT_EQ(array[1], 2); +- EXPECT_EQ(array[2], 1); +- EXPECT_EQ(array[3], 3); ++ bitmap.SetPixel(0, 2, BitmapColor(2, 0, 0)); ++ bitmap.SetPixel(1, 0, BitmapColor(3, 0, 0)); ++ bitmap.SetPixel(1, 1, BitmapColor(4, 0, 0)); ++ bitmap.SetPixel(1, 2, BitmapColor(5, 0, 0)); ++ EXPECT_THAT(bitmap.RowMajorData(), ++ testing::ElementsAre( ++ 0, 0, 0, 3, 0, 0, 1, 0, 0, 4, 0, 0, 2, 0, 0, 5, 0, 0)); + } + +-TEST(Bitmap, ConvertToColMajorArrayRGB) { +- Bitmap bitmap; +- bitmap.Allocate(2, 2, true); ++TEST(Bitmap, RowMajorDataGrey) { ++ Bitmap bitmap(2, 3, /*as_rgb=*/false); + bitmap.SetPixel(0, 0, BitmapColor(0, 0, 0)); + bitmap.SetPixel(0, 1, BitmapColor(1, 0, 0)); +- bitmap.SetPixel(1, 0, BitmapColor(2, 0, 0)); +- bitmap.SetPixel(1, 1, BitmapColor(3, 0, 0)); +- const std::vector array = bitmap.ConvertToColMajorArray(); +- ASSERT_EQ(array.size(), 12); +- EXPECT_EQ(array[0], 0); +- EXPECT_EQ(array[1], 0); +- EXPECT_EQ(array[2], 0); +- EXPECT_EQ(array[3], 0); +- EXPECT_EQ(array[4], 0); +- EXPECT_EQ(array[5], 0); +- EXPECT_EQ(array[6], 0); +- EXPECT_EQ(array[7], 0); +- EXPECT_EQ(array[8], 0); +- EXPECT_EQ(array[9], 1); +- EXPECT_EQ(array[10], 2); +- EXPECT_EQ(array[11], 3); +-} +- +-TEST(Bitmap, ConvertToColMajorArrayGrey) { +- Bitmap bitmap; +- bitmap.Allocate(2, 2, false); +- bitmap.SetPixel(0, 0, BitmapColor(0, 0, 0)); +- bitmap.SetPixel(0, 1, BitmapColor(1, 0, 0)); +- bitmap.SetPixel(1, 0, BitmapColor(2, 0, 0)); +- bitmap.SetPixel(1, 1, BitmapColor(3, 0, 0)); +- const std::vector array = bitmap.ConvertToColMajorArray(); +- ASSERT_EQ(array.size(), 4); +- EXPECT_EQ(array[0], 0); +- EXPECT_EQ(array[1], 1); +- EXPECT_EQ(array[2], 2); +- EXPECT_EQ(array[3], 3); +-} +- +-TEST(Bitmap, ConvertToFromRawBitsGrey) { +- Bitmap bitmap; +- bitmap.Allocate(3, 2, false); +- bitmap.SetPixel(0, 0, BitmapColor(0)); +- bitmap.SetPixel(0, 1, BitmapColor(1)); +- bitmap.SetPixel(1, 0, BitmapColor(2)); +- bitmap.SetPixel(1, 1, BitmapColor(3)); +- +- std::vector raw_bits = bitmap.ConvertToRawBits(); +- ASSERT_EQ(raw_bits.size(), bitmap.Pitch() * bitmap.Height()); +- +- const std::vector raw_bits_copy = raw_bits; +- Bitmap bitmap_copy = Bitmap::ConvertFromRawBits(raw_bits.data(), +- bitmap.Pitch(), +- bitmap.Width(), +- bitmap.Height(), +- /*rgb=*/false); +- EXPECT_EQ(bitmap.Width(), bitmap_copy.Width()); +- EXPECT_EQ(bitmap.Height(), bitmap_copy.Height()); +- EXPECT_EQ(bitmap.Channels(), bitmap_copy.Channels()); +- bitmap.SetPixel(0, 1, BitmapColor(5)); +- bitmap_copy.SetPixel(0, 1, BitmapColor(5)); +- EXPECT_EQ(raw_bits_copy, raw_bits); +- EXPECT_EQ(bitmap.ConvertToRowMajorArray(), +- bitmap_copy.ConvertToRowMajorArray()); +-} +- +-TEST(Bitmap, ConvertToFromRawBitsRGB) { +- Bitmap bitmap; +- bitmap.Allocate(3, 2, true); +- bitmap.SetPixel(0, 0, BitmapColor(0, 0, 0)); +- bitmap.SetPixel(0, 1, BitmapColor(1, 0, 0)); +- bitmap.SetPixel(1, 0, BitmapColor(2, 0, 0)); +- bitmap.SetPixel(1, 1, BitmapColor(3, 0, 0)); +- +- std::vector raw_bits = bitmap.ConvertToRawBits(); +- ASSERT_EQ(raw_bits.size(), bitmap.Pitch() * bitmap.Height() * 3); +- +- const std::vector raw_bits_copy = raw_bits; +- Bitmap bitmap_copy = Bitmap::ConvertFromRawBits(raw_bits.data(), +- bitmap.Pitch(), +- bitmap.Width(), +- bitmap.Height(), +- /*rgb=*/true); +- EXPECT_EQ(bitmap.Width(), bitmap_copy.Width()); +- EXPECT_EQ(bitmap.Height(), bitmap_copy.Height()); +- EXPECT_EQ(bitmap.Channels(), bitmap_copy.Channels()); +- bitmap.SetPixel(0, 1, BitmapColor(5, 0, 0)); +- bitmap_copy.SetPixel(0, 1, BitmapColor(5, 0, 0)); +- EXPECT_EQ(raw_bits_copy, raw_bits); +- EXPECT_EQ(bitmap.ConvertToRowMajorArray(), +- bitmap_copy.ConvertToRowMajorArray()); ++ bitmap.SetPixel(0, 2, BitmapColor(2, 0, 0)); ++ bitmap.SetPixel(1, 0, BitmapColor(3, 0, 0)); ++ bitmap.SetPixel(1, 1, BitmapColor(4, 0, 0)); ++ bitmap.SetPixel(1, 2, BitmapColor(5, 0, 0)); ++ EXPECT_THAT(bitmap.RowMajorData(), testing::ElementsAre(0, 3, 1, 4, 2, 5)); + } + + TEST(Bitmap, GetAndSetPixelRGB) { +- Bitmap bitmap; +- bitmap.Allocate(1, 1, true); +- bitmap.SetPixel(0, 0, BitmapColor(1, 2, 3)); ++ Bitmap bitmap(2, 3, /*as_rgb=*/true); ++ bitmap.SetPixel(1, 1, BitmapColor(1, 2, 3)); + BitmapColor color; +- EXPECT_TRUE(bitmap.GetPixel(0, 0, &color)); ++ EXPECT_TRUE(bitmap.GetPixel(1, 1, &color)); + EXPECT_EQ(color, BitmapColor(1, 2, 3)); + } + + TEST(Bitmap, GetAndSetPixelGrey) { +- Bitmap bitmap; +- bitmap.Allocate(1, 1, false); +- bitmap.SetPixel(0, 0, BitmapColor(0, 2, 3)); ++ Bitmap bitmap(2, 3, /*as_rgb=*/false); ++ bitmap.SetPixel(1, 1, BitmapColor(0, 2, 3)); + BitmapColor color; +- EXPECT_TRUE(bitmap.GetPixel(0, 0, &color)); ++ EXPECT_TRUE(bitmap.GetPixel(1, 1, &color)); + EXPECT_EQ(color, BitmapColor(0, 0, 0)); +- bitmap.SetPixel(0, 0, BitmapColor(1, 2, 3)); +- EXPECT_TRUE(bitmap.GetPixel(0, 0, &color)); +- EXPECT_EQ(color, BitmapColor(1, 0, 0)); +-} +- +-TEST(Bitmap, GetScanlineRGB) { +- Bitmap bitmap; +- bitmap.Allocate(3, 3, true); +- bitmap.Fill(BitmapColor(1, 2, 3)); +- for (size_t r = 0; r < 3; ++r) { +- const uint8_t* scanline = bitmap.GetScanline(r); +- for (size_t c = 0; c < 3; ++c) { +- BitmapColor color; +- EXPECT_TRUE(bitmap.GetPixel(r, c, &color)); +- EXPECT_EQ(scanline[c * 3 + FI_RGBA_RED], color.r); +- EXPECT_EQ(scanline[c * 3 + FI_RGBA_GREEN], color.g); +- EXPECT_EQ(scanline[c * 3 + FI_RGBA_BLUE], color.b); +- } +- } +-} +- +-TEST(Bitmap, GetScanlineGrey) { +- Bitmap bitmap; +- bitmap.Allocate(3, 3, false); +- bitmap.Fill(BitmapColor(1, 2, 3)); +- for (size_t r = 0; r < 3; ++r) { +- const uint8_t* scanline = bitmap.GetScanline(r); +- for (size_t c = 0; c < 3; ++c) { +- BitmapColor color; +- EXPECT_TRUE(bitmap.GetPixel(r, c, &color)); +- EXPECT_EQ(scanline[c], color.r); +- } +- } ++ bitmap.SetPixel(1, 1, BitmapColor(1, 2, 3)); ++ EXPECT_TRUE(bitmap.GetPixel(1, 1, &color)); ++ EXPECT_EQ(color, BitmapColor(1, 1, 1)); + } + + TEST(Bitmap, Fill) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, true); ++ Bitmap bitmap(100, 100, /*as_rgb=*/true); + bitmap.Fill(BitmapColor(1, 2, 3)); + for (int y = 0; y < bitmap.Height(); ++y) { + for (int x = 0; x < bitmap.Width(); ++x) { +@@ -358,76 +205,35 @@ TEST(Bitmap, Fill) { + } + + TEST(Bitmap, InterpolateNearestNeighbor) { +- Bitmap bitmap; +- bitmap.Allocate(11, 11, true); ++ Bitmap bitmap(11, 10, /*as_rgb=*/true); + bitmap.Fill(BitmapColor(0, 0, 0)); +- bitmap.SetPixel(5, 5, BitmapColor(1, 2, 3)); ++ bitmap.SetPixel(5, 4, BitmapColor(1, 2, 3)); + BitmapColor color; +- EXPECT_TRUE(bitmap.InterpolateNearestNeighbor(5, 5, &color)); ++ EXPECT_TRUE(bitmap.InterpolateNearestNeighbor(5, 4, &color)); + EXPECT_EQ(color, BitmapColor(1, 2, 3)); +- EXPECT_TRUE(bitmap.InterpolateNearestNeighbor(5.4999, 5.4999, &color)); ++ EXPECT_TRUE(bitmap.InterpolateNearestNeighbor(5.4999, 4.4999, &color)); + EXPECT_EQ(color, BitmapColor(1, 2, 3)); +- EXPECT_TRUE(bitmap.InterpolateNearestNeighbor(5.5, 5.5, &color)); ++ EXPECT_TRUE(bitmap.InterpolateNearestNeighbor(5.5, 4.5, &color)); + EXPECT_EQ(color, BitmapColor(0, 0, 0)); +- EXPECT_TRUE(bitmap.InterpolateNearestNeighbor(4.5, 5.4999, &color)); ++ EXPECT_TRUE(bitmap.InterpolateNearestNeighbor(4.5, 4.4999, &color)); + EXPECT_EQ(color, BitmapColor(1, 2, 3)); + } + + TEST(Bitmap, InterpolateBilinear) { +- Bitmap bitmap; +- bitmap.Allocate(11, 11, true); ++ Bitmap bitmap(11, 10, /*as_rgb=*/true); + bitmap.Fill(BitmapColor(0, 0, 0)); +- bitmap.SetPixel(5, 5, BitmapColor(1, 2, 3)); ++ bitmap.SetPixel(5, 4, BitmapColor(1, 2, 3)); + BitmapColor color; +- EXPECT_TRUE(bitmap.InterpolateBilinear(5, 5, &color)); ++ EXPECT_TRUE(bitmap.InterpolateBilinear(5, 4, &color)); + EXPECT_EQ(color, BitmapColor(1, 2, 3)); +- EXPECT_TRUE(bitmap.InterpolateBilinear(5.5, 5, &color)); ++ EXPECT_TRUE(bitmap.InterpolateBilinear(5.5, 4, &color)); + EXPECT_EQ(color, BitmapColor(0.5, 1, 1.5)); +- EXPECT_TRUE(bitmap.InterpolateBilinear(5.5, 5.5, &color)); ++ EXPECT_TRUE(bitmap.InterpolateBilinear(5.5, 4.5, &color)); + EXPECT_EQ(color, BitmapColor(0.25, 0.5, 0.75)); + } + +-TEST(Bitmap, SmoothRGB) { +- Bitmap bitmap; +- bitmap.Allocate(50, 50, true); +- for (int x = 0; x < 50; ++x) { +- for (int y = 0; y < 50; ++y) { +- bitmap.SetPixel( +- x, y, BitmapColor(y * 50 + x, y * 50 + x, y * 50 + x)); +- } +- } +- bitmap.Smooth(1, 1); +- EXPECT_EQ(bitmap.Width(), 50); +- EXPECT_EQ(bitmap.Height(), 50); +- EXPECT_EQ(bitmap.Channels(), 3); +- for (int x = 0; x < 50; ++x) { +- for (int y = 0; y < 50; ++y) { +- BitmapColor color; +- EXPECT_TRUE(bitmap.GetPixel(x, y, &color)); +- EXPECT_EQ(color.r, color.g); +- EXPECT_EQ(color.r, color.b); +- } +- } +-} +- +-TEST(Bitmap, SmoothGrey) { +- Bitmap bitmap; +- bitmap.Allocate(50, 50, false); +- for (int x = 0; x < 50; ++x) { +- for (int y = 0; y < 50; ++y) { +- bitmap.SetPixel( +- x, y, BitmapColor(y * 50 + x, y * 50 + x, y * 50 + x)); +- } +- } +- bitmap.Smooth(1, 1); +- EXPECT_EQ(bitmap.Width(), 50); +- EXPECT_EQ(bitmap.Height(), 50); +- EXPECT_EQ(bitmap.Channels(), 1); +-} +- + TEST(Bitmap, RescaleRGB) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, true); ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); + Bitmap bitmap1 = bitmap.Clone(); + bitmap1.Rescale(50, 25); + EXPECT_EQ(bitmap1.Width(), 50); +@@ -441,8 +247,7 @@ TEST(Bitmap, RescaleRGB) { + } + + TEST(Bitmap, RescaleGrey) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, false); ++ Bitmap bitmap(100, 80, /*as_rgb=*/false); + Bitmap bitmap1 = bitmap.Clone(); + bitmap1.Rescale(50, 25); + EXPECT_EQ(bitmap1.Width(), 50); +@@ -456,38 +261,191 @@ TEST(Bitmap, RescaleGrey) { + } + + TEST(Bitmap, Clone) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, true); ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); ++ bitmap.Fill(BitmapColor(0, 0, 0)); ++ bitmap.SetPixel(0, 0, BitmapColor(10, 20, 30)); + const Bitmap cloned_bitmap = bitmap.Clone(); + EXPECT_EQ(cloned_bitmap.Width(), 100); +- EXPECT_EQ(cloned_bitmap.Height(), 100); ++ EXPECT_EQ(cloned_bitmap.Height(), 80); + EXPECT_EQ(cloned_bitmap.Channels(), 3); +- EXPECT_NE(bitmap.Data(), cloned_bitmap.Data()); ++ BitmapColor color; ++ EXPECT_TRUE(cloned_bitmap.GetPixel(0, 0, &color)); ++ EXPECT_EQ(color, BitmapColor(10, 20, 30)); + } + + TEST(Bitmap, CloneAsRGB) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, false); ++ Bitmap bitmap(100, 80, /*as_rgb=*/false); ++ bitmap.Fill(BitmapColor(0, 0, 0)); ++ bitmap.SetPixel(0, 0, BitmapColor(10, 0, 0)); + const Bitmap cloned_bitmap = bitmap.CloneAsRGB(); + EXPECT_EQ(cloned_bitmap.Width(), 100); +- EXPECT_EQ(cloned_bitmap.Height(), 100); ++ EXPECT_EQ(cloned_bitmap.Height(), 80); + EXPECT_EQ(cloned_bitmap.Channels(), 3); +- EXPECT_NE(bitmap.Data(), cloned_bitmap.Data()); ++ BitmapColor color; ++ EXPECT_TRUE(cloned_bitmap.GetPixel(0, 0, &color)); ++ EXPECT_EQ(color, BitmapColor(10, 10, 10)); + } + + TEST(Bitmap, CloneAsGrey) { +- Bitmap bitmap; +- bitmap.Allocate(100, 100, true); ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); ++ bitmap.Fill(BitmapColor(0, 0, 0)); ++ bitmap.SetPixel(0, 0, BitmapColor(10, 20, 30)); + const Bitmap cloned_bitmap = bitmap.CloneAsGrey(); + EXPECT_EQ(cloned_bitmap.Width(), 100); +- EXPECT_EQ(cloned_bitmap.Height(), 100); ++ EXPECT_EQ(cloned_bitmap.Height(), 80); + EXPECT_EQ(cloned_bitmap.Channels(), 1); +- EXPECT_NE(bitmap.Data(), cloned_bitmap.Data()); ++ BitmapColor color; ++ EXPECT_TRUE(cloned_bitmap.GetPixel(0, 0, &color)); ++ EXPECT_EQ(color, BitmapColor(19, 19, 19)); ++} ++ ++TEST(Bitmap, SetGetMetaData) { ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); ++ const float kValue = 1.f; ++ bitmap.SetMetaData("foobar", "float", &kValue); ++ float value = 0.f; ++ EXPECT_TRUE(bitmap.GetMetaData("foobar", "float", &value)); ++ EXPECT_EQ(value, kValue); ++ EXPECT_FALSE(bitmap.GetMetaData("does_not_exist", "float", &value)); ++ EXPECT_FALSE(bitmap.GetMetaData("foobar", "int8", &value)); ++} ++ ++TEST(Bitmap, CloneMetaData) { ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); ++ const float kValue = 1.f; ++ bitmap.SetMetaData("foobar", "float", &kValue); ++ ++ Bitmap bitmap2(100, 80, /*as_rgb=*/true); ++ float value = 0.f; ++ EXPECT_FALSE(bitmap2.GetMetaData("foobar", "float", &value)); ++ bitmap.CloneMetadata(&bitmap2); ++ EXPECT_TRUE(bitmap2.GetMetaData("foobar", "float", &value)); ++ EXPECT_EQ(value, kValue); ++} ++ ++TEST(Bitmap, ExifCameraModel) { ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); ++ ++ std::string camera_model; ++ EXPECT_FALSE(bitmap.ExifCameraModel(&camera_model)); ++ ++ bitmap.SetMetaData("Make", "make"); ++ bitmap.SetMetaData("Model", "model"); ++ const float focal_length_in_35mm_film = 50.f; ++ bitmap.SetMetaData( ++ "Exif:FocalLengthIn35mmFilm", "float", &focal_length_in_35mm_film); ++ ++ EXPECT_TRUE(bitmap.ExifCameraModel(&camera_model)); ++ EXPECT_EQ(camera_model, "make-model-50.000000-100x80"); ++} ++ ++TEST(Bitmap, ExifFocalLengthIn35mm) { ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); ++ ++ double focal_length = 0.0; ++ EXPECT_FALSE(bitmap.ExifFocalLength(&focal_length)); ++ ++ const float focal_length_in_35mm_film = 70.f; ++ bitmap.SetMetaData( ++ "Exif:FocalLengthIn35mmFilm", "float", &focal_length_in_35mm_film); ++ ++ EXPECT_TRUE(bitmap.ExifFocalLength(&focal_length)); ++ EXPECT_NEAR(focal_length, 207.17, 0.1); ++} ++ ++TEST(Bitmap, ExifFocalLengthWithPlane) { ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); ++ ++ double focal_length = 0.0; ++ EXPECT_FALSE(bitmap.ExifFocalLength(&focal_length)); ++ ++ const float kFocalLengthVal = 72.f; ++ bitmap.SetMetaData("Exif:FocalLength", "float", &kFocalLengthVal); ++ bitmap.SetMetaData("Make", "canon"); ++ bitmap.SetMetaData("Model", "eos1dsmarkiii"); ++ ++ EXPECT_TRUE(bitmap.ExifFocalLength(&focal_length)); ++ EXPECT_EQ(focal_length, 200); ++} ++ ++TEST(Bitmap, ExifFocalLengthWithDatabaseLookup) { ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); ++ ++ double focal_length = 0.0; ++ EXPECT_FALSE(bitmap.ExifFocalLength(&focal_length)); ++ ++ const float kFocalLengthVal = 120.f; ++ bitmap.SetMetaData("Exif:FocalLength", "float", &kFocalLengthVal); ++ const int kPixelXDim = 100; ++ bitmap.SetMetaData("Exif:PixelXDimension", "int", &kPixelXDim); ++ const float kPlaneXRes = 1.f; ++ bitmap.SetMetaData("Exif:FocalPlaneXResolution", "float", &kPlaneXRes); ++ const int kPlanResUnit = 4; ++ bitmap.SetMetaData("Exif:FocalPlaneResolutionUnit", "int", &kPlanResUnit); ++ ++ EXPECT_TRUE(bitmap.ExifFocalLength(&focal_length)); ++ EXPECT_EQ(focal_length, 120); ++} ++ ++TEST(Bitmap, ExifLatitude) { ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); ++ ++ double latitude = 0.0; ++ EXPECT_FALSE(bitmap.ExifLatitude(&latitude)); ++ ++ bitmap.SetMetaData("GPS:LatitudeRef", "N"); ++ const float kDegMinSec[3] = {46, 30, 900}; ++ bitmap.SetMetaData("GPS:Latitude", "point", kDegMinSec); ++ ++ EXPECT_TRUE(bitmap.ExifLatitude(&latitude)); ++ EXPECT_EQ(latitude, 46.75); ++ ++ bitmap.SetMetaData("GPS:LatitudeRef", "S"); ++ ++ EXPECT_TRUE(bitmap.ExifLatitude(&latitude)); ++ EXPECT_EQ(latitude, -46.75); ++} ++ ++TEST(Bitmap, ExifLongitude) { ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); ++ ++ double longitude = 0.0; ++ EXPECT_FALSE(bitmap.ExifLongitude(&longitude)); ++ ++ bitmap.SetMetaData("GPS:LongitudeRef", "W"); ++ const float kDegMinSec[3] = {92, 30, 900}; ++ bitmap.SetMetaData("GPS:Longitude", "point", kDegMinSec); ++ ++ EXPECT_TRUE(bitmap.ExifLongitude(&longitude)); ++ EXPECT_EQ(longitude, 92.75); ++ ++ bitmap.SetMetaData("GPS:LongitudeRef", "E"); ++ ++ EXPECT_TRUE(bitmap.ExifLongitude(&longitude)); ++ EXPECT_EQ(longitude, -92.75); ++} ++ ++TEST(Bitmap, ExifAltitude) { ++ Bitmap bitmap(100, 80, /*as_rgb=*/true); ++ ++ double altitude = 0.0; ++ EXPECT_FALSE(bitmap.ExifAltitude(&altitude)); ++ ++ bitmap.SetMetaData("GPS:AltitudeRef", "0"); ++ const float kAltitudeVal = 123.456; ++ bitmap.SetMetaData("GPS:Altitude", "float", &kAltitudeVal); ++ ++ EXPECT_TRUE(bitmap.ExifAltitude(&altitude)); ++ EXPECT_EQ(altitude, kAltitudeVal); ++ ++ bitmap.SetMetaData("GPS:AltitudeRef", "1"); ++ ++ EXPECT_TRUE(bitmap.ExifAltitude(&altitude)); ++ EXPECT_EQ(altitude, -kAltitudeVal); + } + + TEST(Bitmap, ReadWriteAsRGB) { +- Bitmap bitmap; +- bitmap.Allocate(2, 3, true); ++ Bitmap bitmap(2, 3, /*as_rgb=*/true); + bitmap.SetPixel(0, 0, BitmapColor(0, 0, 0)); + bitmap.SetPixel(0, 1, BitmapColor(1, 0, 0)); + bitmap.SetPixel(1, 0, BitmapColor(2, 0, 0)); +@@ -501,30 +459,23 @@ TEST(Bitmap, ReadWriteAsRGB) { + EXPECT_TRUE(bitmap.Write(filename)); + + Bitmap read_bitmap; +- +- // Allocate bitmap with different size to test read overwrites existing data. +- read_bitmap.Allocate(bitmap.Width() + 1, bitmap.Height() + 2, true); +- + EXPECT_TRUE(read_bitmap.Read(filename)); + EXPECT_EQ(read_bitmap.Width(), bitmap.Width()); + EXPECT_EQ(read_bitmap.Height(), bitmap.Height()); + EXPECT_EQ(read_bitmap.Channels(), 3); + EXPECT_EQ(read_bitmap.BitsPerPixel(), 24); +- EXPECT_EQ(read_bitmap.ConvertToRowMajorArray(), +- bitmap.ConvertToRowMajorArray()); ++ EXPECT_EQ(read_bitmap.RowMajorData(), bitmap.RowMajorData()); + + EXPECT_TRUE(read_bitmap.Read(filename, /*as_rgb=*/false)); + EXPECT_EQ(read_bitmap.Width(), bitmap.Width()); + EXPECT_EQ(read_bitmap.Height(), bitmap.Height()); + EXPECT_EQ(read_bitmap.Channels(), 1); + EXPECT_EQ(read_bitmap.BitsPerPixel(), 8); +- EXPECT_EQ(read_bitmap.ConvertToRowMajorArray(), +- bitmap.CloneAsGrey().ConvertToRowMajorArray()); ++ EXPECT_EQ(read_bitmap.RowMajorData(), bitmap.CloneAsGrey().RowMajorData()); + } + + TEST(Bitmap, ReadWriteAsGrey) { +- Bitmap bitmap; +- bitmap.Allocate(2, 3, false); ++ Bitmap bitmap(2, 3, /*as_rgb=*/false); + bitmap.SetPixel(0, 0, BitmapColor(0)); + bitmap.SetPixel(0, 1, BitmapColor(1)); + bitmap.SetPixel(1, 0, BitmapColor(2)); +@@ -538,73 +489,92 @@ TEST(Bitmap, ReadWriteAsGrey) { + EXPECT_TRUE(bitmap.Write(filename)); + + Bitmap read_bitmap; +- +- // Allocate bitmap with different size to test read overwrites existing data. +- read_bitmap.Allocate(bitmap.Width() + 1, bitmap.Height() + 2, true); +- + EXPECT_TRUE(read_bitmap.Read(filename)); + EXPECT_EQ(read_bitmap.Width(), bitmap.Width()); + EXPECT_EQ(read_bitmap.Height(), bitmap.Height()); + EXPECT_EQ(read_bitmap.Channels(), 3); + EXPECT_EQ(read_bitmap.BitsPerPixel(), 24); +- EXPECT_EQ(read_bitmap.ConvertToRowMajorArray(), +- bitmap.CloneAsRGB().ConvertToRowMajorArray()); ++ EXPECT_EQ(read_bitmap.RowMajorData(), bitmap.CloneAsRGB().RowMajorData()); + + EXPECT_TRUE(read_bitmap.Read(filename, /*as_rgb=*/false)); + EXPECT_EQ(read_bitmap.Width(), bitmap.Width()); + EXPECT_EQ(read_bitmap.Height(), bitmap.Height()); + EXPECT_EQ(read_bitmap.Channels(), 1); + EXPECT_EQ(read_bitmap.BitsPerPixel(), 8); +- EXPECT_EQ(read_bitmap.ConvertToRowMajorArray(), +- bitmap.ConvertToRowMajorArray()); ++ EXPECT_EQ(read_bitmap.RowMajorData(), bitmap.RowMajorData()); + } + +-TEST(Bitmap, ReadRGB16AsGrey) { +- Bitmap bitmap; +- bitmap.Allocate(2, 3, true); +- bitmap.SetPixel(0, 0, BitmapColor(0, 0, 0)); +- bitmap.SetPixel(0, 1, BitmapColor(1, 0, 0)); +- bitmap.SetPixel(1, 0, BitmapColor(2, 0, 0)); +- bitmap.SetPixel(1, 1, BitmapColor(3, 0, 0)); +- bitmap.SetPixel(0, 2, BitmapColor(4, 2, 0)); +- bitmap.SetPixel(1, 2, BitmapColor(5, 2, 1)); ++TEST(Bitmap, ReadWriteAsGreyNonLinear) { ++ Bitmap bitmap(2, 3, /*as_rgb=*/false, /*linear_colorspace=*/false); ++ bitmap.SetPixel(0, 0, BitmapColor(0)); ++ bitmap.SetPixel(0, 1, BitmapColor(1)); ++ bitmap.SetPixel(1, 0, BitmapColor(2)); ++ bitmap.SetPixel(1, 1, BitmapColor(3)); ++ bitmap.SetPixel(0, 2, BitmapColor(4)); ++ bitmap.SetPixel(1, 2, BitmapColor(5)); + + const std::string test_dir = CreateTestDir(); + const std::string filename = test_dir + "/bitmap.png"; + +- // Bitmap class does not support 16 bit color depth +- FIBITMAP* converted_rgb16 = FreeImage_ConvertToType(bitmap.Data(), FIT_RGB16); +- EXPECT_TRUE(converted_rgb16); +- EXPECT_TRUE(FreeImage_Save(FIF_PNG, converted_rgb16, filename.c_str())); +- FreeImage_Unload(converted_rgb16); +- +- // Assert the file was written correctly with 16 bit color depth +- FIBITMAP* written_image = FreeImage_Load(FIF_PNG, filename.c_str()); +- EXPECT_TRUE(written_image); +- EXPECT_EQ(FreeImage_GetBPP(written_image), 48); +- FreeImage_Unload(written_image); ++ EXPECT_TRUE(bitmap.Write(filename, /*delinearize_colorspace=*/false)); + + Bitmap read_bitmap; +- +- // Allocate bitmap with different size to test read overwrites existing data. +- read_bitmap.Allocate(bitmap.Width() + 1, bitmap.Height() + 2, true); +- +- EXPECT_TRUE(read_bitmap.Read(filename)); +- EXPECT_EQ(read_bitmap.Width(), bitmap.Width()); +- EXPECT_EQ(read_bitmap.Height(), bitmap.Height()); +- EXPECT_EQ(read_bitmap.Channels(), 3); +- EXPECT_EQ(read_bitmap.BitsPerPixel(), 24); +- EXPECT_EQ(read_bitmap.ConvertToRowMajorArray(), +- bitmap.ConvertToRowMajorArray()); +- +- EXPECT_TRUE(read_bitmap.Read(filename, /*as_rgb=*/false)); ++ EXPECT_TRUE(read_bitmap.Read( ++ filename, /*as_rgb=*/false, /*linearize_colorspace=*/false)); + EXPECT_EQ(read_bitmap.Width(), bitmap.Width()); + EXPECT_EQ(read_bitmap.Height(), bitmap.Height()); + EXPECT_EQ(read_bitmap.Channels(), 1); + EXPECT_EQ(read_bitmap.BitsPerPixel(), 8); +- EXPECT_EQ(read_bitmap.ConvertToRowMajorArray(), +- bitmap.CloneAsGrey().ConvertToRowMajorArray()); +-} ++ EXPECT_EQ(read_bitmap.RowMajorData(), bitmap.RowMajorData()); ++} ++ ++// TEST(Bitmap, ReadRGB16AsGrey) { ++// Bitmap bitmap; ++// bitmap.Allocate(2, 3, /*as_rgb=*/true); ++// bitmap.SetPixel(0, 0, BitmapColor(0, 0, 0)); ++// bitmap.SetPixel(0, 1, BitmapColor(1, 0, 0)); ++// bitmap.SetPixel(1, 0, BitmapColor(2, 0, 0)); ++// bitmap.SetPixel(1, 1, BitmapColor(3, 0, 0)); ++// bitmap.SetPixel(0, 2, BitmapColor(4, 2, 0)); ++// bitmap.SetPixel(1, 2, BitmapColor(5, 2, 1)); ++ ++// const std::string test_dir = CreateTestDir(); ++// const std::string filename = test_dir + "/bitmap.png"; ++ ++// // Bitmap class does not support 16 bit color depth ++// FIBITMAP* converted_rgb16 = FreeImage_ConvertToType(bitmap.Data(), ++// FIT_RGB16); EXPECT_TRUE(converted_rgb16); ++// EXPECT_TRUE(FreeImage_Save(FIF_PNG, converted_rgb16, filename.c_str())); ++// FreeImage_Unload(converted_rgb16); ++ ++// // Assert the file was written correctly with 16 bit color depth ++// FIBITMAP* written_image = FreeImage_Load(FIF_PNG, filename.c_str()); ++// EXPECT_TRUE(written_image); ++// EXPECT_EQ(FreeImage_GetBPP(written_image), 48); ++// FreeImage_Unload(written_image); ++ ++// Bitmap read_bitmap; ++ ++// // Allocate bitmap with different size to test read overwrites existing ++// data. read_bitmap.Allocate(bitmap.Width() + 1, bitmap.Height() + 2, ++// /*as_rgb=*/true); ++ ++// EXPECT_TRUE(read_bitmap.Read(filename)); ++// EXPECT_EQ(read_bitmap.Width(), bitmap.Width()); ++// EXPECT_EQ(read_bitmap.Height(), bitmap.Height()); ++// EXPECT_EQ(read_bitmap.Channels(), 3); ++// EXPECT_EQ(read_bitmap.BitsPerPixel(), 24); ++// EXPECT_EQ(read_bitmap.RowMajorData(), ++// bitmap.RowMajorData()); ++ ++// EXPECT_TRUE(read_bitmap.Read(filename, /*as_rgb=*/false)); ++// EXPECT_EQ(read_bitmap.Width(), bitmap.Width()); ++// EXPECT_EQ(read_bitmap.Height(), bitmap.Height()); ++// EXPECT_EQ(read_bitmap.Channels(), 1); ++// EXPECT_EQ(read_bitmap.BitsPerPixel(), 8); ++// EXPECT_EQ(read_bitmap.RowMajorData(), ++// bitmap.CloneAsGrey().RowMajorData()); ++// } + + } // namespace + } // namespace colmap +diff --git a/src/colmap/sensor/database.cc b/src/colmap/sensor/database.cc +index ab83c83e..03de6e9c 100644 +--- a/src/colmap/sensor/database.cc ++++ b/src/colmap/sensor/database.cc +@@ -37,7 +37,7 @@ const camera_specs_t CameraDatabase::specs_ = InitializeCameraSpecs(); + + bool CameraDatabase::QuerySensorWidth(const std::string& make, + const std::string& model, +- double* sensor_width) { ++ double* sensor_width_mm) { + // Clean the strings from all separators. + std::string cleaned_make = make; + std::string cleaned_model = model; +@@ -60,7 +60,7 @@ bool CameraDatabase::QuerySensorWidth(const std::string& make, + for (const auto& model_elem : make_elem.second) { + if (StringContains(cleaned_model, model_elem.first) || + StringContains(model_elem.first, cleaned_model)) { +- *sensor_width = model_elem.second; ++ *sensor_width_mm = model_elem.second; + if (cleaned_model == model_elem.first) { + // Model exactly matches, return immediately. + return true; +diff --git a/src/colmap/sensor/database.h b/src/colmap/sensor/database.h +index 93af5226..08a86102 100644 +--- a/src/colmap/sensor/database.h ++++ b/src/colmap/sensor/database.h +@@ -45,7 +45,7 @@ struct CameraDatabase { + + bool QuerySensorWidth(const std::string& make, + const std::string& model, +- double* sensor_width); ++ double* sensor_width_mm); + + private: + static const camera_specs_t specs_; +diff --git a/src/colmap/sfm/incremental_mapper.cc b/src/colmap/sfm/incremental_mapper.cc +index 2a054cdd..671f2a8c 100644 +--- a/src/colmap/sfm/incremental_mapper.cc ++++ b/src/colmap/sfm/incremental_mapper.cc +@@ -693,9 +693,8 @@ IncrementalMapper::AdjustLocalBundle( + num_frames_per_rig[frame.RigId()] += 1; + } + for (const auto& [rig_id, num_frames] : num_frames_per_rig) { +- const size_t num_reg_frames_for_rig = +- reg_stats_.num_reg_frames_per_rig.at(rig_id); +- if (num_frames < num_reg_frames_for_rig) { ++ if (options.constant_rigs.count(rig_id) || ++ num_frames < reg_stats_.num_reg_frames_per_rig.at(rig_id)) { + const Rig& rig = reconstruction_->Rig(rig_id); + for (const auto& [sensor_id, _] : rig.Sensors()) { + ba_config.SetConstantSensorFromRigPose(sensor_id); +@@ -708,14 +707,11 @@ IncrementalMapper::AdjustLocalBundle( + num_images_per_camera.reserve(ba_config.NumImages()); + for (const image_t image_id : ba_config.Images()) { + const Image& image = reconstruction_->Image(image_id); +- num_frames_per_rig[image.FramePtr()->RigId()] += 1; + num_images_per_camera[image.CameraId()] += 1; + } + for (const auto& [camera_id, num_images] : num_images_per_camera) { +- const size_t num_reg_images_for_camera = +- reg_stats_.num_reg_images_per_camera.at(camera_id); + if (options.constant_cameras.count(camera_id) || +- num_images < num_reg_images_for_camera) { ++ num_images < reg_stats_.num_reg_images_per_camera.at(camera_id)) { + ba_config.SetConstantCamIntrinsics(camera_id); + } + } +@@ -812,6 +808,13 @@ bool IncrementalMapper::AdjustGlobalBundle( + } + } + ++ for (const auto& rig_id : options.constant_rigs) { ++ const Rig& rig = reconstruction_->Rig(rig_id); ++ for (const auto& [sensor_id, _] : rig.Sensors()) { ++ ba_config.SetConstantSensorFromRigPose(sensor_id); ++ } ++ } ++ + for (const auto& camera_id : options.constant_cameras) { + ba_config.SetConstantCamIntrinsics(camera_id); + } +diff --git a/src/colmap/sfm/incremental_mapper.h b/src/colmap/sfm/incremental_mapper.h +index f56cdc96..20fd0f46 100644 +--- a/src/colmap/sfm/incremental_mapper.h ++++ b/src/colmap/sfm/incremental_mapper.h +@@ -118,6 +118,10 @@ class IncrementalMapper { + // If reconstruction is provided as input, fix the existing image poses. + bool fix_existing_frames = false; + ++ // List of rigs for which to fix the sensor_from_rig transformation, ++ // independent of ba_refine_sensor_from_rig. ++ std::unordered_set constant_rigs; ++ + // List of cameras for which to fix the camera parameters independent + // of refine_focal_length, refine_principal_point, and refine_extra_params. + std::unordered_set constant_cameras; +diff --git a/src/colmap/ui/CMakeLists.txt b/src/colmap/ui/CMakeLists.txt +index 591f3682..38e923ee 100644 +--- a/src/colmap/ui/CMakeLists.txt ++++ b/src/colmap/ui/CMakeLists.txt +@@ -30,6 +30,17 @@ + + set(FOLDER_NAME "ui") + ++set(COLMAP_UI_QT_LIBS ++ Qt${QT_VERSION_MAJOR}::Core ++ Qt${QT_VERSION_MAJOR}::OpenGL ++ Qt${QT_VERSION_MAJOR}::Widgets ++) ++ ++if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) ++ list(APPEND COLMAP_UI_QT_LIBS ++ Qt${QT_VERSION_MAJOR}::OpenGLWidgets) ++endif() ++ + COLMAP_ADD_LIBRARY( + NAME colmap_ui + SRCS +@@ -67,7 +78,5 @@ COLMAP_ADD_LIBRARY( + colmap_image + colmap_scene + colmap_controllers +- Qt5::Core +- Qt5::OpenGL +- Qt5::Widgets ++ ${COLMAP_UI_QT_LIBS} + ) +diff --git a/src/colmap/ui/feature_extraction_widget.cc b/src/colmap/ui/feature_extraction_widget.cc +index 0357a677..b9a6369b 100644 +--- a/src/colmap/ui/feature_extraction_widget.cc ++++ b/src/colmap/ui/feature_extraction_widget.cc +@@ -79,12 +79,12 @@ SIFTExtractionWidget::SIFTExtractionWidget(QWidget* parent, + AddOptionFilePath(&options->image_reader->camera_mask_path, + "camera_mask_path"); + ++ AddOptionInt(&options->feature_extraction->max_image_size, "max_image_size"); + AddOptionInt(&options->feature_extraction->num_threads, "num_threads", -1); + AddOptionBool(&options->feature_extraction->use_gpu, "use_gpu"); + AddOptionText(&options->feature_extraction->gpu_index, "gpu_index"); + + SiftExtractionOptions& sift_options = *options->feature_extraction->sift; +- AddOptionInt(&sift_options.max_image_size, "sift.max_image_size"); + AddOptionInt(&sift_options.max_num_features, "sift.max_num_features"); + AddOptionInt(&sift_options.first_octave, "sift.first_octave", -5); + AddOptionInt(&sift_options.num_octaves, "sift.num_octaves"); +@@ -115,6 +115,7 @@ void SIFTExtractionWidget::Run() { + + ImageReaderOptions reader_options = *options_->image_reader; + reader_options.image_path = *options_->image_path; ++ reader_options.as_rgb = options_->feature_extraction->RequiresRGB(); + + auto extractor = CreateFeatureExtractorController( + *options_->database_path, reader_options, *options_->feature_extraction); +diff --git a/src/colmap/ui/image_viewer_widget.cc b/src/colmap/ui/image_viewer_widget.cc +index c743351c..9b86723a 100644 +--- a/src/colmap/ui/image_viewer_widget.cc ++++ b/src/colmap/ui/image_viewer_widget.cc +@@ -120,8 +120,9 @@ void ImageViewerWidget::ShowPixmap(const QPixmap& pixmap) { + + void ImageViewerWidget::ReadAndShow(const std::string& path) { + Bitmap bitmap; +- if (!bitmap.Read(path, true)) { ++ if (!bitmap.Read(path, /*as_rgb=*/true, /*linearize=*/false)) { + LOG(ERROR) << "Cannot read image at path " << path; ++ return; + } + + ShowBitmap(bitmap); +@@ -167,14 +168,14 @@ FeatureImageViewerWidget::FeatureImageViewerWidget( + this, + &FeatureImageViewerWidget::ShowOrHide); + } +- + void FeatureImageViewerWidget::ReadAndShowWithKeypoints( + const std::string& path, + const FeatureKeypoints& keypoints, + const std::vector& tri_mask) { + Bitmap bitmap; +- if (!bitmap.Read(path, true)) { ++ if (!bitmap.Read(path, /*as_rgb=*/true, /*linearize=*/false)) { + LOG(ERROR) << "Cannot read image at path " << path; ++ return; + } + + image1_ = QPixmap::fromImage(BitmapToQImageRGB(bitmap)); +@@ -215,7 +216,8 @@ void FeatureImageViewerWidget::ReadAndShowWithMatches( + const FeatureMatches& matches) { + Bitmap bitmap1; + Bitmap bitmap2; +- if (!bitmap1.Read(path1, true) || !bitmap2.Read(path2, true)) { ++ if (!bitmap1.Read(path1, /*as_rgb=*/true, /*linearize=*/false) || ++ !bitmap2.Read(path2, /*as_rgb=*/true, /*linearize=*/false)) { + LOG(ERROR) << "Cannot read images at paths " << path1 << " and " << path2; + return; + } +diff --git a/src/colmap/ui/match_matrix_widget.cc b/src/colmap/ui/match_matrix_widget.cc +index 07dcab5f..7298ca60 100644 +--- a/src/colmap/ui/match_matrix_widget.cc ++++ b/src/colmap/ui/match_matrix_widget.cc +@@ -52,8 +52,7 @@ void MatchMatrixWidget::Show() { + }); + + // Allocate the match matrix image. +- Bitmap match_matrix; +- match_matrix.Allocate(images.size(), images.size(), true); ++ Bitmap match_matrix(images.size(), images.size(), true); + match_matrix.Fill(BitmapColor(255)); + + // Map image identifiers to match matrix locations. +diff --git a/src/colmap/ui/model_viewer_widget.cc b/src/colmap/ui/model_viewer_widget.cc +index c7015c91..a51e9d7f 100644 +--- a/src/colmap/ui/model_viewer_widget.cc ++++ b/src/colmap/ui/model_viewer_widget.cc +@@ -734,7 +734,11 @@ QImage ModelViewerWidget::GrabImage() { + + EnableCoordinateGrid(); + ++#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0) ++ return image.flipped(Qt::Orientation::Vertical); ++#else + return image.mirrored(); ++#endif + } + + void ModelViewerWidget::GrabMovie() { movie_grabber_widget_->show(); } +diff --git a/src/colmap/ui/model_viewer_widget.h b/src/colmap/ui/model_viewer_widget.h +index e2a64715..b56618cd 100644 +--- a/src/colmap/ui/model_viewer_widget.h ++++ b/src/colmap/ui/model_viewer_widget.h +@@ -44,6 +44,9 @@ + #include + #include + #include ++#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) ++#include ++#endif + + namespace colmap { + +diff --git a/src/colmap/ui/options_widget.cc b/src/colmap/ui/options_widget.cc +index 2ea0ea84..17cd1b6d 100644 +--- a/src/colmap/ui/options_widget.cc ++++ b/src/colmap/ui/options_widget.cc +@@ -93,6 +93,7 @@ QSpinBox* OptionsWidget::AddOptionInt(int* option, + QSpinBox* spinbox = new QSpinBox(this); + spinbox->setMinimum(min); + spinbox->setMaximum(max); ++ spinbox->setValue(*option); + + AddOptionRow(label_text, spinbox, option); + +@@ -112,6 +113,7 @@ QDoubleSpinBox* OptionsWidget::AddOptionDouble(double* option, + spinbox->setMaximum(max); + spinbox->setSingleStep(step); + spinbox->setDecimals(decimals); ++ spinbox->setValue(*option); + + AddOptionRow(label_text, spinbox, option); + +@@ -131,6 +133,7 @@ QDoubleSpinBox* OptionsWidget::AddOptionDoubleLog(double* option, + spinbox->setMaximum(max); + spinbox->setSingleStep(step); + spinbox->setDecimals(decimals); ++ spinbox->setValue(*option); + + AddOptionRow(label_text, spinbox, option); + +@@ -142,6 +145,7 @@ QDoubleSpinBox* OptionsWidget::AddOptionDoubleLog(double* option, + QCheckBox* OptionsWidget::AddOptionBool(bool* option, + const std::string& label_text) { + QCheckBox* checkbox = new QCheckBox(this); ++ checkbox->setChecked(*option); + + AddOptionRow(label_text, checkbox, option); + +@@ -153,6 +157,7 @@ QCheckBox* OptionsWidget::AddOptionBool(bool* option, + QLineEdit* OptionsWidget::AddOptionText(std::string* option, + const std::string& label_text) { + QLineEdit* line_edit = new QLineEdit(this); ++ line_edit->setText(QString::fromStdString(*option)); + + AddOptionRow(label_text, line_edit, option); + +@@ -164,6 +169,7 @@ QLineEdit* OptionsWidget::AddOptionText(std::string* option, + QLineEdit* OptionsWidget::AddOptionFilePath(std::string* option, + const std::string& label_text) { + QLineEdit* line_edit = new QLineEdit(this); ++ line_edit->setText(QString::fromStdString(*option)); + + AddOptionRow(label_text, line_edit, option); + +@@ -184,6 +190,7 @@ QLineEdit* OptionsWidget::AddOptionFilePath(std::string* option, + QLineEdit* OptionsWidget::AddOptionDirPath(std::string* option, + const std::string& label_text) { + QLineEdit* line_edit = new QLineEdit(this); ++ line_edit->setText(QString::fromStdString(*option)); + + AddOptionRow(label_text, line_edit, option); + +diff --git a/src/colmap/ui/point_viewer_widget.cc b/src/colmap/ui/point_viewer_widget.cc +index dbb08051..2ce58fa0 100644 +--- a/src/colmap/ui/point_viewer_widget.cc ++++ b/src/colmap/ui/point_viewer_widget.cc +@@ -192,7 +192,7 @@ void PointViewerWidget::Show(const point3D_t point3D_id) { + + Bitmap bitmap; + const std::string path = JoinPaths(*options_->image_path, image.Name()); +- if (!bitmap.Read(path, true)) { ++ if (!bitmap.Read(path, /*as_rgb=*/true, /*linearize=*/false)) { + LOG(ERROR) << "Cannot read image at path " << path; + continue; + } +diff --git a/src/colmap/ui/qt_utils.cc b/src/colmap/ui/qt_utils.cc +index 340da967..86f2e8e2 100644 +--- a/src/colmap/ui/qt_utils.cc ++++ b/src/colmap/ui/qt_utils.cc +@@ -57,7 +57,7 @@ QMatrix4x4 EigenToQMatrix(const Eigen::Matrix4f& matrix) { + QImage BitmapToQImageRGB(const Bitmap& bitmap) { + QImage image(bitmap.Width(), bitmap.Height(), QImage::Format_RGB32); + for (int y = 0; y < image.height(); ++y) { +- QRgb* image_line = (QRgb*)image.scanLine(y); ++ QRgb* image_line = reinterpret_cast(image.scanLine(y)); + for (int x = 0; x < image.width(); ++x) { + BitmapColor color; + if (bitmap.GetPixel(x, y, &color)) { +diff --git a/src/colmap/util/CMakeLists.txt b/src/colmap/util/CMakeLists.txt +index 6399bbbb..49260dba 100644 +--- a/src/colmap/util/CMakeLists.txt ++++ b/src/colmap/util/CMakeLists.txt +@@ -79,7 +79,15 @@ if(DOWNLOAD_ENABLED) + endif() + endif() + if(GUI_ENABLED) +- target_link_libraries(colmap_util PUBLIC Qt5::Core Qt5::OpenGL OpenGL::GL) ++ set(COLMAP_UTIL_QT_LIBS ++ Qt${QT_VERSION_MAJOR}::Core ++ Qt${QT_VERSION_MAJOR}::OpenGL ++ ) ++ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) ++ list(APPEND COLMAP_UTIL_QT_LIBS ++ Qt${QT_VERSION_MAJOR}::OpenGLWidgets) ++ endif() ++ target_link_libraries(colmap_util PUBLIC ${COLMAP_UTIL_QT_LIBS} OpenGL::GL) + endif() + + if(CUDA_ENABLED) +diff --git a/src/pycolmap/feature/extraction.cc b/src/pycolmap/feature/extraction.cc +index c5d228c8..481b6710 100644 +--- a/src/pycolmap/feature/extraction.cc ++++ b/src/pycolmap/feature/extraction.cc +@@ -44,9 +44,9 @@ class Sift { + "settings, explicitly specify them, because the defaults " + "will change in the next major release.", + 1); ++ options_.max_image_size = 7000; + options_.sift->peak_threshold = 0.01; + options_.sift->first_octave = 0; +- options_.sift->max_image_size = 7000; + } + options_.use_gpu = use_gpu_; + THROW_CHECK(options_.Check()); +@@ -54,15 +54,11 @@ class Sift { + } + + sift_output_t Extract(const Eigen::Ref>& image) { +- THROW_CHECK_LE(image.rows(), options_.sift->max_image_size); +- THROW_CHECK_LE(image.cols(), options_.sift->max_image_size); ++ THROW_CHECK_LE(image.rows(), options_.max_image_size); ++ THROW_CHECK_LE(image.cols(), options_.max_image_size); + +- const Bitmap bitmap = +- Bitmap::ConvertFromRawBits(const_cast(image.data()), +- /*pitch=*/image.cols(), +- /*width=*/image.cols(), +- /*height=*/image.rows(), +- /*rgb=*/false); ++ Bitmap bitmap(image.cols(), image.rows(), /*as_rgb=*/false); ++ std::memcpy(bitmap.RowMajorData().data(), image.data(), bitmap.NumBytes()); + + FeatureKeypoints keypoints_; + FeatureDescriptors descriptors_; +@@ -117,10 +113,6 @@ void BindFeatureExtraction(py::module& m) { + auto PySiftExtractionOptions = + py::classh(m, "SiftExtractionOptions") + .def(py::init<>()) +- .def_readwrite( +- "max_image_size", +- &SiftExtractionOptions::max_image_size, +- "Maximum image size, otherwise image will be down-scaled.") + .def_readwrite("max_num_features", + &SiftExtractionOptions::max_num_features, + "Maximum number of features to detect, keeping " +@@ -173,6 +165,10 @@ void BindFeatureExtraction(py::module& m) { + auto PyFeatureExtractionOptions = + py::classh(m, "FeatureExtractionOptions") + .def(py::init<>()) ++ .def_readwrite( ++ "max_image_size", ++ &FeatureExtractionOptions::max_image_size, ++ "Maximum image size, otherwise image will be down-scaled.") + .def_readwrite("num_threads", + &FeatureExtractionOptions::num_threads, + "Number of threads for feature matching and " +diff --git a/src/pycolmap/sensor/bitmap.cc b/src/pycolmap/sensor/bitmap.cc +index 7e28ea9d..42d4873b 100644 +--- a/src/pycolmap/sensor/bitmap.cc ++++ b/src/pycolmap/sensor/bitmap.cc +@@ -36,28 +36,8 @@ void BindBitmap(pybind11::module& m) { + py::buffer_info output_into = output.request(); + uint8_t* output_row_ptr = + reinterpret_cast(output.request().ptr); +- const size_t output_pitch = output_into.shape[1] * channels; +- for (ssize_t y = 0; y < output_into.shape[0]; ++y) { +- if (is_rgb) { +- for (ssize_t x = 0; x < output_into.shape[1]; ++x) { +- // Notice that the underlying FreeImage buffer may order +- // the channels as BGR or in any other format and with +- // different striding, so we have to set each pixel +- // separately. +- // We always return the array in the order R, G, B. +- BitmapColor color; +- THROW_CHECK(self.GetPixel(x, y, &color)); +- output_row_ptr[3 * x] = color.r; +- output_row_ptr[3 * x + 1] = color.g; +- output_row_ptr[3 * x + 2] = color.b; +- } +- } else { +- // Copy (guaranteed contiguous) row memory directly. +- std::memcpy( +- output_row_ptr, self.GetScanline(y), output_into.shape[1]); +- } +- output_row_ptr += output_pitch; +- } ++ std::memcpy( ++ output_row_ptr, self.RowMajorData().data(), self.NumBytes()); + return output; + }) + .def_static( +@@ -75,47 +55,23 @@ void BindBitmap(pybind11::module& m) { + const int height = array.shape(0); + if (width == 0 || height == 0) { + throw std::runtime_error( +- "Input array must have positive width and height"); ++ "Input array must have positive width and height!"); + } + +- if (channels != 1 && channels != 3 && channels != 4) { ++ if (channels != 1 && channels != 3) { + throw std::runtime_error( +- "Input array must have 1, 3, or 4 channels!"); ++ "Input array must have 1 or 3 channels!"); + } + + const bool is_rgb = channels != 1; +- const size_t pitch = width * channels; + +- Bitmap output; +- output.Allocate(width, height, is_rgb); ++ Bitmap output(width, height, is_rgb); + + const uint8_t* input_row_ptr = + static_cast(array.request().ptr); + +- for (int y = 0; y < height; ++y) { +- if (is_rgb) { +- for (int x = 0; x < width; ++x) { +- // We assume that provided array dimensions are R, G, B. +- // Notice that the underlying FreeImage buffer may order +- // the channels as BGR or in any other format and with +- // different striding, so we have to set each pixel +- // separately. +- output.SetPixel( +- x, +- y, +- BitmapColor(input_row_ptr[channels * x], +- input_row_ptr[channels * x + 1], +- input_row_ptr[channels * x + 2])); +- } +- } else { +- // Copy (guaranteed contiguous) row memory directly. +- std::memcpy(const_cast(output.GetScanline(y)), +- input_row_ptr, +- width); +- } +- +- input_row_ptr += pitch; +- } ++ std::memcpy( ++ output.RowMajorData().data(), input_row_ptr, output.NumBytes()); + + return output; + }, +@@ -126,7 +82,7 @@ void BindBitmap(pybind11::module& m) { + .def("write", + &Bitmap::Write, + "path"_a, +- "flags"_a = 0, ++ "delinearize_colorspace"_a, + "Write bitmap to file.") + .def("__repr__", &CreateRepresentation) + .def_static( +diff --git a/src/pycolmap/sfm/incremental_mapper.cc b/src/pycolmap/sfm/incremental_mapper.cc +index e31c9ac8..6b80b1ef 100644 +--- a/src/pycolmap/sfm/incremental_mapper.cc ++++ b/src/pycolmap/sfm/incremental_mapper.cc +@@ -183,6 +183,11 @@ void BindIncrementalPipeline(py::module& m) { + &Opts::fix_existing_frames, + "If reconstruction is provided as input, fix the existing " + "frame poses.") ++ .def_readwrite( ++ "constant_rigs", ++ &Opts::constant_rigs, ++ "List of rigs for which to fix the sensor_from_rig transformation, " ++ "independent of ba_refine_sensor_from_rig.") + .def_readwrite("constant_cameras", + &Opts::constant_cameras, + "List of cameras for which to fix the camera parameters " +@@ -344,6 +349,11 @@ void BindIncrementalMapperOptions(py::module& m) { + &Opts::fix_existing_frames, + "If reconstruction is provided as input, fix the existing " + "frame poses.") ++ .def_readwrite( ++ "constant_rigs", ++ &Opts::constant_rigs, ++ "List of rigs for which to fix the sensor_from_rig transformation, " ++ "independent of ba_refine_sensor_from_rig.") + .def_readwrite("constant_cameras", + &Opts::constant_cameras, + "List of cameras for which to fix the camera parameters " +diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json +new file mode 100644 +index 00000000..ce7d86ba +--- /dev/null ++++ b/vcpkg-configuration.json +@@ -0,0 +1,7 @@ ++{ ++ "default-registry": { ++ "kind": "git", ++ "repository": "https://github.com/Microsoft/vcpkg", ++ "baseline": "912567f6fdd1883e07b070dcc0aa67cec072042a" ++ } ++} +diff --git a/vcpkg.json b/vcpkg.json +index 6adbe3a6..dfc330a2 100644 +--- a/vcpkg.json ++++ b/vcpkg.json +@@ -20,7 +20,6 @@ + ] + }, + "eigen3", +- "freeimage", + "gflags", + "glog", + { +@@ -28,6 +27,7 @@ + "default-features": false + }, + "metis", ++ "openimageio", + "sqlite3", + { + "name": "vcpkg-cmake", +@@ -38,6 +38,16 @@ + "host": true + } + ], ++ "overrides": [ ++ { ++ "name": "metis", ++ "version": "2022-07-27" ++ }, ++ { ++ "name": "gklib", ++ "version": "2023-03-27" ++ } ++ ], + "default-features": [ + "gui", + "download" +@@ -60,7 +70,7 @@ + "description": "Build with GUI support.", + "dependencies": [ + "glew", +- "qt5-base" ++ "qtbase" + ] + }, + "cgal": { +@@ -75,7 +85,7 @@ + { + "name": "curl", + "features": [ +- "schannel" ++ "sspi" + ], + "platform": "windows" + }, +@@ -97,4 +107,4 @@ + ] + } + } +-} +\ No newline at end of file ++} diff --git a/pkgs/applications/science/misc/colmap/default.nix b/pkgs/by-name/co/colmap/package.nix similarity index 51% rename from pkgs/applications/science/misc/colmap/default.nix rename to pkgs/by-name/co/colmap/package.nix index 70f359b545d7..ed97fb1b4e5d 100644 --- a/pkgs/applications/science/misc/colmap/default.nix +++ b/pkgs/by-name/co/colmap/package.nix @@ -1,19 +1,22 @@ { lib, fetchFromGitHub, + fetchpatch, + gitUpdater, cmake, boost, ceres-solver, eigen, - freeimage, + openimageio, glog, libGLU, glew, - qtbase, flann, cgal, gmp, mpfr, + poselib, + lz4, autoAddDriverRunpath, config, stdenv, @@ -22,71 +25,115 @@ cudaSupport ? config.cudaSupport, cudaCapabilities ? cudaPackages.flags.cudaCapabilities, cudaPackages, + faiss, + sqlite, + llvmPackages, + gtest, }: assert cudaSupport -> cudaPackages != { }; let - boost_static = boost.override { enableStatic = true; }; stdenv' = if cudaSupport then cudaPackages.backendStdenv else stdenv; + depsAlsoForPycolmap = [ + boost + eigen + ceres-solver + openimageio + glog + libGLU + glew + cgal + poselib + faiss + sqlite + gmp + mpfr + lz4 + qt5.qtbase + ] + ++ lib.optionals cudaSupport [ + cudatoolkit + cudaPackages.cuda_cudart.static + ] + ++ lib.optional stdenv'.cc.isClang llvmPackages.openmp; + # TODO: migrate to redist packages inherit (cudaPackages) cudatoolkit; in stdenv'.mkDerivation rec { - version = "3.9.1"; + version = "unstable-3.12.5-openimageio"; pname = "colmap"; src = fetchFromGitHub { owner = "colmap"; repo = "colmap"; - rev = version; - hash = "sha256-Xb4JOttCMERwPYs5DyGKHw+f9Wik1/rdJQKbgVuygH8="; + rev = "f8edccaa36909713b9d3930e1ca65cb364a38b26"; + hash = "sha256-0lD7ywM48ODe11u9D3XSk9btqQ4gs/APBFf9IyiXe6g="; }; - cmakeFlags = lib.optionals cudaSupport [ - (lib.cmakeBool "CUDA_ENABLED" true) + # TODO: remove this when https://github.com/colmap/colmap/pull/3459 is in a release + # This was produced with: + # git diff f8edccaa36909713b9d3930e1ca65cb364a38b26 e40c0730020938587c9d4eb7634cbff93cbc2f81 + patches = [ ./openimageio.patch ]; + + cmakeFlags = [ + (lib.cmakeBool "DOWNLOAD_ENABLED" false) + (lib.cmakeBool "UNINSTALL_ENABLED" false) + (lib.cmakeBool "FETCH_POSELIB" false) + (lib.cmakeBool "FETCH_FAISS" false) + (lib.cmakeBool "TESTS_ENABLED" true) + ] + ++ lib.optionals cudaSupport [ + (lib.cmakeBool "CUDA_ENABLED" cudaSupport) (lib.cmakeFeature "CMAKE_CUDA_ARCHITECTURES" ( lib.strings.concatStringsSep ";" (map cudaPackages.flags.dropDots cudaCapabilities) )) ]; buildInputs = [ - boost_static + boost ceres-solver eigen - freeimage + openimageio glog libGLU glew - qtbase + qt5.qtbase flann + lz4 cgal gmp mpfr xorg.libSM ] - ++ lib.optionals cudaSupport [ - cudatoolkit - cudaPackages.cuda_cudart.static - ]; + ++ depsAlsoForPycolmap; nativeBuildInputs = [ cmake qt5.wrapQtAppsHook + gtest ] ++ lib.optionals cudaSupport [ autoAddDriverRunpath ]; + passthru.depsAlsoForPycolmap = depsAlsoForPycolmap; + meta = with lib; { description = "Structure-From-Motion and Multi-View Stereo pipeline"; longDescription = '' COLMAP is a general-purpose Structure-from-Motion (SfM) and Multi-View Stereo (MVS) pipeline with a graphical and command-line interface. ''; + mainProgram = "colmap"; homepage = "https://colmap.github.io/index.html"; license = licenses.bsd3; - platforms = platforms.linux; - maintainers = with maintainers; [ lebastr ]; + platforms = platforms.unix; + maintainers = with maintainers; [ + lebastr + usertam + chpatrick + ]; }; } diff --git a/pkgs/by-name/co/confluent-cli/package.nix b/pkgs/by-name/co/confluent-cli/package.nix index 80cfa2b85278..c545f2e0aecb 100644 --- a/pkgs/by-name/co/confluent-cli/package.nix +++ b/pkgs/by-name/co/confluent-cli/package.nix @@ -7,7 +7,7 @@ stdenv.mkDerivation (finalAttrs: { pname = "confluent-cli"; - version = "4.38.0"; + version = "4.39.1"; # To get the latest version: # curl -L https://cnfl.io/cli | sh -s -- -l | grep -v latest | sort -V | tail -n1 @@ -26,10 +26,10 @@ stdenv.mkDerivation (finalAttrs: { fetchurl { url = "https://s3-us-west-2.amazonaws.com/confluent.cloud/confluent-cli/archives/${finalAttrs.version}/confluent_${finalAttrs.version}_${system}.tar.gz"; hash = selectSystem { - x86_64-linux = "sha256-NetkaNbUCbNyajtwLUVW5KpFhkyngYoWxJJxDK42QCQ="; - aarch64-linux = "sha256-xzMpG7BknzOdFoUZnnlCjsCxuFCkJMzGi+yH4+0QvtQ="; - x86_64-darwin = "sha256-UP5+tnLuYore8t/qi2d3iLf47OMxwF51mfJzgfLnK7s="; - aarch64-darwin = "sha256-IV0zEL4ApRZug0C0A0jQm9Vp78z/kk8MwcaXNOE3Agk="; + x86_64-linux = "sha256-8KhsFMQXoIPp1oZR5Q6u1yNoNvrCulbWq/rb6pMLhTU="; + aarch64-linux = "sha256-gLsNOAd9xzSbmenXhUN9nDGyFObtB2IG2z+OxHjrMSM="; + x86_64-darwin = "sha256-t0PcZd3n2Bayct4/h/JtCJwyKYjtMaXmOvvrlJ6LzGc="; + aarch64-darwin = "sha256-sSJd87dzsYLCdpP3tw4cMTyhnxmku70g1rCqhxGImGA="; }; }; diff --git a/pkgs/by-name/co/container-structure-test/package.nix b/pkgs/by-name/co/container-structure-test/package.nix index d932b48b9464..40cec99e3a31 100644 --- a/pkgs/by-name/co/container-structure-test/package.nix +++ b/pkgs/by-name/co/container-structure-test/package.nix @@ -8,13 +8,13 @@ container-structure-test, }: buildGoModule rec { - version = "1.20.0"; + version = "1.21.1"; pname = "container-structure-test"; src = fetchFromGitHub { owner = "GoogleContainerTools"; repo = "container-structure-test"; rev = "v${version}"; - sha256 = "sha256-7/RTWpj/W+W4mhQL2HX/6KuMbDFsjh9GGRCGZZ9sNHQ="; + sha256 = "sha256-B2/fe3hfP2UCxxxHAdvxdjT+npB6u4OrxO7XyBDZuqw="; }; vendorHash = "sha256-pBq76HJ+nluOMOs9nqBKp1mr1LuX2NERXo48g8ezE9k="; diff --git a/pkgs/by-name/co/cosmic-reader/package.nix b/pkgs/by-name/co/cosmic-reader/package.nix index 07f21969120e..3c22a4c13562 100644 --- a/pkgs/by-name/co/cosmic-reader/package.nix +++ b/pkgs/by-name/co/cosmic-reader/package.nix @@ -19,13 +19,13 @@ }: rustPlatform.buildRustPackage (finalAttrs: { pname = "cosmic-reader"; - version = "0-unstable-2025-09-21"; + version = "0-unstable-2025-10-02"; src = fetchFromGitHub { owner = "pop-os"; repo = "cosmic-reader"; - rev = "a5b1b5c0583deacafde19de4ee936cdd126b25df"; - hash = "sha256-yXY1t67ws2PvK7IubNHT0jp+xnfDAdyK5H7LCMGcMQI="; + rev = "2fa9595999cb654b5e6bb688035ea9ec0717b8db"; + hash = "sha256-7/nes4zMcvTtGWFABikcA1NM+LxWrin0POE76BbYgKE="; }; cargoHash = "sha256-4ofAtZN3FpYwNahinldALbdEJA5lDwa+CUsVIISnSTc="; diff --git a/pkgs/by-name/cy/cyme/package.nix b/pkgs/by-name/cy/cyme/package.nix index 09f133e94272..e97ab969eec9 100644 --- a/pkgs/by-name/cy/cyme/package.nix +++ b/pkgs/by-name/cy/cyme/package.nix @@ -12,16 +12,16 @@ rustPlatform.buildRustPackage rec { pname = "cyme"; - version = "2.2.5"; + version = "2.2.6"; src = fetchFromGitHub { owner = "tuna-f1sh"; repo = "cyme"; rev = "v${version}"; - hash = "sha256-1a+8e9sVij9o1G/XlSf7tTECZOHTwqO9rORcYsVjp6Y="; + hash = "sha256-OXwph3dV6gUAanlwzEL0CRjSOfqEvYDXdhs60MkMfcE="; }; - cargoHash = "sha256-HMPjsaHrd3UdazPiAyrHs9Emh0XdjQ/qkaZm6kxOyq4="; + cargoHash = "sha256-THNcrBD5GBorVsuFZ/XN91c1Zlc5NAbTnjWf7/td74o="; nativeBuildInputs = [ pkg-config diff --git a/pkgs/by-name/da/dar/package.nix b/pkgs/by-name/da/dar/package.nix index a882fca7e8cf..9669c586f8c5 100644 --- a/pkgs/by-name/da/dar/package.nix +++ b/pkgs/by-name/da/dar/package.nix @@ -21,12 +21,12 @@ }: stdenv.mkDerivation rec { - version = "2.8.0"; + version = "2.8.1"; pname = "dar"; src = fetchzip { url = "mirror://sourceforge/dar/${pname}-${version}.tar.gz"; - sha256 = "sha256-dmUNKhVEz5CpEVzKcDYPSKtYfOMXyXpzGJDJEebwLqU="; + sha256 = "sha256-Fow1dIRugYjz0S4lxeW33k2Lt/+xS/HXBsXF5SvX4wU="; }; outputs = [ diff --git a/pkgs/by-name/da/darklua/package.nix b/pkgs/by-name/da/darklua/package.nix index a8e9c9ccbcd2..c4b4b13a72bb 100644 --- a/pkgs/by-name/da/darklua/package.nix +++ b/pkgs/by-name/da/darklua/package.nix @@ -6,16 +6,16 @@ rustPlatform.buildRustPackage rec { pname = "darklua"; - version = "0.17.1"; + version = "0.17.2"; src = fetchFromGitHub { owner = "seaofvoices"; repo = "darklua"; rev = "v${version}"; - hash = "sha256-Jcq6zZ0KaDHXkIapPd38BR+ikVQAha3Bq5HuPEnKV0o="; + hash = "sha256-RNm2d0VeLgHEawvZQYUcXesNwLc2m9Q6R6kNZhZDslg="; }; - cargoHash = "sha256-yF+h7IiirvLw3WqqyCmcXbRa+fnsOpHrrmxkwl4lIG4="; + cargoHash = "sha256-WfXIMuqO1KTiWeqMOnsylNlJKv1cKNZvp8qhalPlcnc="; # error: linker `aarch64-linux-gnu-gcc` not found postPatch = '' diff --git a/pkgs/by-name/di/diamond/package.nix b/pkgs/by-name/di/diamond/package.nix index 2ae68a476cc0..b6dcebe7ede1 100644 --- a/pkgs/by-name/di/diamond/package.nix +++ b/pkgs/by-name/di/diamond/package.nix @@ -14,7 +14,7 @@ stdenv.mkDerivation rec { owner = "bbuchfink"; repo = "diamond"; rev = "v${version}"; - sha256 = "sha256-w6+lSc2YZ1PwPj3p6ieI/yTkoiSLWH2Za863n4BTClo="; + sha256 = "sha256-nTMfWpXTsdcas0VwZzyU6ix4reNQX7EoyYRZ1wUN2pM="; }; nativeBuildInputs = [ cmake ]; diff --git a/pkgs/by-name/do/do-agent/package.nix b/pkgs/by-name/do/do-agent/package.nix index b0a6fc087218..6d54338fe946 100644 --- a/pkgs/by-name/do/do-agent/package.nix +++ b/pkgs/by-name/do/do-agent/package.nix @@ -6,13 +6,13 @@ buildGoModule rec { pname = "do-agent"; - version = "3.18.2"; + version = "3.18.3"; src = fetchFromGitHub { owner = "digitalocean"; repo = "do-agent"; rev = version; - sha256 = "sha256-+UoQhJkwxazfe6LwqNF4zn4jnc3ZQia0ZOL3GX27r3w="; + sha256 = "sha256-YYckleFnWt7Wttmkb20g5fs9DOoL9VNDmOWdP3qNstU="; }; ldflags = [ diff --git a/pkgs/by-name/do/docker-credential-helpers/package.nix b/pkgs/by-name/do/docker-credential-helpers/package.nix index a16781dcafec..a262b00423e3 100644 --- a/pkgs/by-name/do/docker-credential-helpers/package.nix +++ b/pkgs/by-name/do/docker-credential-helpers/package.nix @@ -11,13 +11,13 @@ buildGoModule rec { pname = "docker-credential-helpers"; - version = "0.9.3"; + version = "0.9.4"; src = fetchFromGitHub { owner = "docker"; repo = "docker-credential-helpers"; rev = "v${version}"; - sha256 = "sha256-5KrBiihpWY04PjI9M7NRS5fRu+ochzqRLvX+ZBj/wq8="; + sha256 = "sha256-cDpo3hw0yP9QnFvlGUIpjfMzni57KNkY+S+SIYOKBKQ="; }; vendorHash = null; diff --git a/pkgs/by-name/do/doh-proxy-rust/package.nix b/pkgs/by-name/do/doh-proxy-rust/package.nix index 7fcb4e3dcb97..67843e810ec1 100644 --- a/pkgs/by-name/do/doh-proxy-rust/package.nix +++ b/pkgs/by-name/do/doh-proxy-rust/package.nix @@ -9,15 +9,15 @@ rustPlatform.buildRustPackage rec { pname = "doh-proxy-rust"; - version = "0.9.12"; + version = "0.9.15"; src = fetchCrate { inherit version; crateName = "doh-proxy"; - hash = "sha256-Q+SjUB9XQlT+r1bjKJooqJ095yp5PMqMAQhoo+kp238="; + hash = "sha256-uqFqDaq5a9wW46pTLfVN+5WuyYGvm3ZYQCtC6jkG1kg="; }; - cargoHash = "sha256-XEHeGduKsIFW0tXto8DcghzNYMGE/zkWY2cTg8ZcPcU="; + cargoHash = "sha256-eYhax+TM3N75qj0tyHioUeUt159ZfkuFFIZK1jUbojw="; buildInputs = lib.optionals stdenv.hostPlatform.isDarwin [ libiconv diff --git a/pkgs/by-name/fe/fetchit/package.nix b/pkgs/by-name/fe/fetchit/package.nix index 04842d497869..752acf9cc877 100644 --- a/pkgs/by-name/fe/fetchit/package.nix +++ b/pkgs/by-name/fe/fetchit/package.nix @@ -81,7 +81,7 @@ buildGoModule rec { homepage = "https://fetchit.readthedocs.io"; changelog = "https://github.com/containers/fetchit/releases/tag/${src.rev}"; license = licenses.agpl3Plus; - maintainers = [ ]; + maintainers = with lib.maintainers; [ guylamar2006 ]; platforms = platforms.linux; }; } diff --git a/pkgs/by-name/fl/fluidsynth/package.nix b/pkgs/by-name/fl/fluidsynth/package.nix index fbc52c9cf68c..28c8b9ef066f 100644 --- a/pkgs/by-name/fl/fluidsynth/package.nix +++ b/pkgs/by-name/fl/fluidsynth/package.nix @@ -53,7 +53,10 @@ stdenv.mkDerivation (finalAttrs: { description = "Real-time software synthesizer based on the SoundFont 2 specifications"; homepage = "https://www.fluidsynth.org"; license = lib.licenses.lgpl21Plus; - maintainers = with lib.maintainers; [ lovek323 ]; + maintainers = with lib.maintainers; [ + lovek323 + guylamar2006 + ]; platforms = lib.platforms.unix; mainProgram = "fluidsynth"; }; diff --git a/pkgs/by-name/fo/forgejo-runner/package.nix b/pkgs/by-name/fo/forgejo-runner/package.nix index 8175f086deb8..e25f348ef2ce 100644 --- a/pkgs/by-name/fo/forgejo-runner/package.nix +++ b/pkgs/by-name/fo/forgejo-runner/package.nix @@ -41,14 +41,14 @@ let in buildGoModule rec { pname = "forgejo-runner"; - version = "11.1.1"; + version = "11.1.2"; src = fetchFromGitea { domain = "code.forgejo.org"; owner = "forgejo"; repo = "runner"; rev = "v${version}"; - hash = "sha256-gItynq665YLHdSXcUrtgIp282t/TBjThDgAYyVYesx0="; + hash = "sha256-/rkBrG8hRn52M1ybjbWtSDFYsJ4fHzw9qAoc5325g9A="; }; vendorHash = "sha256-eVOmUozNLHRiNwIhbf7ebVNdRiMAtLMdYI7pnALvl8U="; diff --git a/pkgs/by-name/fz/fzf-make/package.nix b/pkgs/by-name/fz/fzf-make/package.nix index f72c8de6ed37..b73491eb7788 100644 --- a/pkgs/by-name/fz/fzf-make/package.nix +++ b/pkgs/by-name/fz/fzf-make/package.nix @@ -11,16 +11,16 @@ rustPlatform.buildRustPackage rec { pname = "fzf-make"; - version = "0.61.0"; + version = "0.62.0"; src = fetchFromGitHub { owner = "kyu08"; repo = "fzf-make"; rev = "v${version}"; - hash = "sha256-XDYJ+R/cQuzSfJyOYHKbbd+jrmAzumDs/wp5aoYEr80="; + hash = "sha256-WUQW3I/dFO510v5JzShydMO3N8QYrKqDAJUzDdUZg0U="; }; - cargoHash = "sha256-700KyKqrtZ9HuMBZVUbazrGyqzLE4s0ZyrWqLc8Y5WY="; + cargoHash = "sha256-8V++82edFMJ8/B1aLAK2MhW2g1usg3eBt60SIUuKong="; nativeBuildInputs = [ makeBinaryWrapper ]; diff --git a/pkgs/by-name/gl/gl3w/package.nix b/pkgs/by-name/gl/gl3w/package.nix index 5ae67c5f4b54..d1137a0c780e 100644 --- a/pkgs/by-name/gl/gl3w/package.nix +++ b/pkgs/by-name/gl/gl3w/package.nix @@ -11,13 +11,13 @@ stdenv.mkDerivation { pname = "gl3w"; - version = "0-unstable-2025-08-02"; + version = "0-unstable-2025-09-23"; src = fetchFromGitHub { owner = "skaslev"; repo = "gl3w"; - rev = "96ebe5eded05aa699e8feb25f7bbc9f1c821a207"; - hash = "sha256-Juv1LI8bw/dU/SKmtoOqu8TrCf68uqkpesQ1leRox+E="; + rev = "97a85e153d7f43c8d2de8b776a33721e238ddb96"; + hash = "sha256-cpB/8qo9dDyKPxD6mRriKGZf7N7ei1oL5JtM4jgXsAw="; }; nativeBuildInputs = [ diff --git a/pkgs/by-name/go/go-camo/package.nix b/pkgs/by-name/go/go-camo/package.nix index 32cb089b4da3..5534cd613f22 100644 --- a/pkgs/by-name/go/go-camo/package.nix +++ b/pkgs/by-name/go/go-camo/package.nix @@ -9,16 +9,16 @@ buildGo125Module rec { pname = "go-camo"; - version = "2.6.5"; + version = "2.7.0"; src = fetchFromGitHub { owner = "cactus"; repo = "go-camo"; tag = "v${version}"; - hash = "sha256-+EHJIohHSWg12Tmn6hu1XUSVRyYWu3aFI7MF7+PnfFg="; + hash = "sha256-CuEnJcbLcehmAj+TCx3VbRLWhYhbzYaXfV6qweuoooA="; }; - vendorHash = "sha256-rKdBAu0tNsxw7I66qjZhtrA2hs1qpBtOSuzq34paziw="; + vendorHash = "sha256-3Yl0x02KcYG5+FVuON54NlO+ehvgvywep4Hu9sQ6nN4="; nativeBuildInputs = [ installShellFiles diff --git a/pkgs/by-name/go/google-java-format/package.nix b/pkgs/by-name/go/google-java-format/package.nix index 6c8bad9571e4..c8d8e3c90269 100644 --- a/pkgs/by-name/go/google-java-format/package.nix +++ b/pkgs/by-name/go/google-java-format/package.nix @@ -8,11 +8,11 @@ stdenv.mkDerivation rec { pname = "google-java-format"; - version = "1.28.0"; + version = "1.29.0"; src = fetchurl { url = "https://github.com/google/google-java-format/releases/download/v${version}/google-java-format-${version}-all-deps.jar"; - sha256 = "sha256-MjQufBtGAPgN80cdpGrugBLT4URdXqG+H7cSibB8xzU="; + sha256 = "sha256-rrThgx1WAR5+BvM5PE4XNAx8yg/XupB2q43AYkdZ9/A="; }; dontUnpack = true; diff --git a/pkgs/by-name/go/goose/package.nix b/pkgs/by-name/go/goose/package.nix index 6515c478c06f..0410e217b7b9 100644 --- a/pkgs/by-name/go/goose/package.nix +++ b/pkgs/by-name/go/goose/package.nix @@ -7,13 +7,13 @@ buildGoModule rec { pname = "goose"; - version = "3.25.0"; + version = "3.26.0"; src = fetchFromGitHub { owner = "pressly"; repo = "goose"; rev = "v${version}"; - hash = "sha256-ouyvxlnJQIMqRZt4nsR01+9p227FGBlHoCMAq6Ufh7A="; + hash = "sha256-3F9dnlu7fJ08Pcr64q6V3oRkDpm+N0Ot8drRp9m5YhU="; }; proxyVendor = true; diff --git a/pkgs/by-name/h2/h2/package.nix b/pkgs/by-name/h2/h2/package.nix index d060e2465b79..38144b2abc98 100644 --- a/pkgs/by-name/h2/h2/package.nix +++ b/pkgs/by-name/h2/h2/package.nix @@ -9,7 +9,7 @@ maven.buildMavenPackage rec { pname = "h2"; - version = "2.3.232"; + version = "2.4.240"; outputs = [ "out" @@ -20,7 +20,7 @@ maven.buildMavenPackage rec { owner = "h2database"; repo = "h2database"; tag = "version-${version}"; - hash = "sha256-voqQ4JqYkHRxVdxMGsHmKirQXMP7s44rTXeasWWW2Jw="; + hash = "sha256-Cy6MoumJBhhcYT6dCHWeOfmhjGRkdNvSONdIiZaf6uU="; }; mvnParameters = "-f h2/pom.xml"; diff --git a/pkgs/by-name/hx/hx-lsp/package.nix b/pkgs/by-name/hx/hx-lsp/package.nix new file mode 100644 index 000000000000..3d2a23d3883c --- /dev/null +++ b/pkgs/by-name/hx/hx-lsp/package.nix @@ -0,0 +1,29 @@ +{ + lib, + rustPlatform, + fetchFromGitHub, + versionCheckHook, +}: +rustPlatform.buildRustPackage (finalAttrs: { + pname = "hx-lsp"; + version = "0.2.11"; + + src = fetchFromGitHub { + owner = "erasin"; + repo = "hx-lsp"; + tag = finalAttrs.version; + hash = "sha256-wTilbEK3BZehklAd+3SS2tW/vc8WEeMPUsYdDVRC/Ho="; + }; + + cargoHash = "sha256-dcGInrfWftClvzrxYZvrazm+IWWRfOZmxDJPKwu7GwM="; + + nativeInstallCheckInputs = [ versionCheckHook ]; + meta = { + description = "LSP tool providing custom code snippets and Code Actions for Helix Editor"; + homepage = "https://github.com/erasin/hx-lsp"; + changelog = "https://github.com/erasin/hx-lsp/releases/tag/${finalAttrs.version}"; + mainProgram = "hx-lsp"; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ hadziqM ]; + }; +}) diff --git a/pkgs/by-name/if/ifstate/package.nix b/pkgs/by-name/if/ifstate/package.nix index e27f08bd0a80..e4ff233e07da 100644 --- a/pkgs/by-name/if/ifstate/package.nix +++ b/pkgs/by-name/if/ifstate/package.nix @@ -14,13 +14,13 @@ }: let - version = "2.0.1"; + version = "2.0.2"; src = fetchFromGitea { domain = "codeberg.org"; owner = "liske"; repo = "ifstate"; tag = version; - hash = "sha256-QxjziDlkbTxAVd3qA8u4+JT8NWJxBMVAp7G5Zma9d10="; + hash = "sha256-ghl2EVSum8KOh9wpFkrLGeIii2cj0a2+yOa48/JwFRk="; }; docs = stdenv.mkDerivation { pname = "ifstate-docs"; diff --git a/pkgs/by-name/im/immich-cli/package.nix b/pkgs/by-name/im/immich-cli/package.nix index d36d125f031c..4f1669b5c024 100644 --- a/pkgs/by-name/im/immich-cli/package.nix +++ b/pkgs/by-name/im/immich-cli/package.nix @@ -12,7 +12,7 @@ let in stdenv.mkDerivation rec { pname = "immich-cli"; - version = "2.2.95"; + version = "2.2.96"; inherit (immich) src pnpmDeps; postPatch = '' diff --git a/pkgs/by-name/im/immich/package.nix b/pkgs/by-name/im/immich/package.nix index c5e047a40758..10ef5f0ed50f 100644 --- a/pkgs/by-name/im/immich/package.nix +++ b/pkgs/by-name/im/immich/package.nix @@ -34,7 +34,7 @@ }: let pnpm = pnpm_10; - version = "2.0.0"; + version = "2.0.1"; esbuild' = buildPackages.esbuild.override { buildGoModule = @@ -108,7 +108,7 @@ let owner = "immich-app"; repo = "immich"; tag = "v${version}"; - hash = "sha256-N9/vDOZzx4BQvWQBPE6ANCJ9RhWmytw8j1BgDU6ob+g="; + hash = "sha256-lpFUjjS7Q2F/Uhog1NdJ8vaVIGjmZM9ZWxW5d0zoQsc="; }; pnpmDeps = pnpm.fetchDeps { diff --git a/pkgs/by-name/ir/irqbalance/package.nix b/pkgs/by-name/ir/irqbalance/package.nix index 926001b76e8c..acea2ce20da7 100644 --- a/pkgs/by-name/ir/irqbalance/package.nix +++ b/pkgs/by-name/ir/irqbalance/package.nix @@ -9,6 +9,7 @@ libcap_ng, enableSystemd ? lib.meta.availableOn stdenv.hostPlatform systemdMinimal, systemdMinimal, + nixosTests, }: stdenv.mkDerivation rec { @@ -48,6 +49,8 @@ stdenv.mkDerivation rec { --replace-fail ' $IRQBALANCE_ARGS' "" ''; + passthru.tests.nixos = nixosTests.irqbalance; + meta = { homepage = "https://github.com/Irqbalance/irqbalance"; changelog = lib.strings.optionalString ( @@ -57,5 +60,6 @@ stdenv.mkDerivation rec { license = lib.licenses.gpl2Only; platforms = lib.platforms.linux; maintainers = with lib.maintainers; [ moni ]; + mainProgram = "irqbalance"; }; } diff --git a/pkgs/by-name/ja/jawiki-all-titles-in-ns0/package.nix b/pkgs/by-name/ja/jawiki-all-titles-in-ns0/package.nix index 87214369a26e..dfe3bdd3e2be 100644 --- a/pkgs/by-name/ja/jawiki-all-titles-in-ns0/package.nix +++ b/pkgs/by-name/ja/jawiki-all-titles-in-ns0/package.nix @@ -7,13 +7,13 @@ stdenvNoCC.mkDerivation { pname = "jawiki-all-titles-in-ns0"; - version = "0-unstable-2025-09-01"; + version = "0-unstable-2025-10-01"; src = fetchFromGitHub { owner = "musjj"; repo = "jawiki-archive"; - rev = "bcb0ee245aee3ba7769ceec6caf9696c8bae1624"; - hash = "sha256-Vb+8XE9FFEJfp6++WWr5fT6oWkF8eUtvYLz9ouRHWHA="; + rev = "81e6379ffeb292a5ff6db4302347d80ba053fb1e"; + hash = "sha256-jbfJ+Vf7jkCjjePbwHP0BTFA/J1NcIQkhFK1jqD4bPE="; }; installPhase = '' diff --git a/pkgs/by-name/ku/kubefirst/package.nix b/pkgs/by-name/ku/kubefirst/package.nix index 3578c7ff9724..5f5161b6aa61 100644 --- a/pkgs/by-name/ku/kubefirst/package.nix +++ b/pkgs/by-name/ku/kubefirst/package.nix @@ -6,13 +6,13 @@ buildGoModule rec { pname = "kubefirst"; - version = "2.9.1"; + version = "2.10.1"; src = fetchFromGitHub { owner = "konstructio"; repo = "kubefirst"; tag = "v${version}"; - hash = "sha256-llWJTBI0MBVDG2zgersQM7F5RM5ZhpbkF67QxcSeAU0="; + hash = "sha256-/DmYPxnqAoCPXjkaYTj1iYliNfqyqrDrChU6fCbbCkk="; }; vendorHash = "sha256-1u34cuPUY/5fYd073UhRUu/5/1nhPadTI06+3o+uE7w="; diff --git a/pkgs/by-name/li/libtoxcore/package.nix b/pkgs/by-name/li/libtoxcore/package.nix index 334d8e85b8c5..d595aea51a90 100644 --- a/pkgs/by-name/li/libtoxcore/package.nix +++ b/pkgs/by-name/li/libtoxcore/package.nix @@ -1,7 +1,7 @@ { lib, stdenv, - fetchurl, + fetchFromGitHub, cmake, libsodium, ncurses, @@ -15,22 +15,23 @@ let buildToxAV = !stdenv.hostPlatform.isAarch32; in -stdenv.mkDerivation rec { +stdenv.mkDerivation (finalAttrs: { pname = "libtoxcore"; - version = "0.2.20"; + version = "0.2.21"; - src = - # We need the prepared sources tarball. - fetchurl { - url = "https://github.com/TokTok/c-toxcore/releases/download/v${version}/c-toxcore-${version}.tar.gz"; - hash = "sha256-qciaja6nRdU+XXjnqsuZx7R5LEQApaaccSOPRdYWT0w="; - }; + src = fetchFromGitHub { + owner = "TokTok"; + repo = "c-toxcore"; + tag = "v${finalAttrs.version}"; + hash = "sha256-0lWUKW09JvHa0QDX7v4n5B2ckQrKU9TDkjKegDLTIUw="; + fetchSubmodules = true; + }; cmakeFlags = [ - "-DDHT_BOOTSTRAP=ON" - "-DBOOTSTRAP_DAEMON=ON" + (lib.cmakeBool "DHT_BOOTSTRAP" true) + (lib.cmakeBool "BOOTSTRAP_DAEMON" true) ] - ++ lib.optional buildToxAV "-DMUST_BUILD_TOXAV=ON"; + ++ lib.optional buildToxAV (lib.cmakeBool "MUST_BUILD_TOXAV" true); buildInputs = [ libsodium @@ -64,7 +65,8 @@ stdenv.mkDerivation rec { license = lib.licenses.gpl3Plus; maintainers = with lib.maintainers; [ peterhoeg + zatm8 ]; platforms = lib.platforms.all; }; -} +}) diff --git a/pkgs/by-name/li/lighthouse-steamvr/package.nix b/pkgs/by-name/li/lighthouse-steamvr/package.nix index 1b0c18fad7ff..62fd08cca424 100644 --- a/pkgs/by-name/li/lighthouse-steamvr/package.nix +++ b/pkgs/by-name/li/lighthouse-steamvr/package.nix @@ -8,16 +8,16 @@ rustPlatform.buildRustPackage rec { pname = "Lighthouse"; - version = "1.3.1"; + version = "1.3.2"; src = fetchFromGitHub { owner = "ShayBox"; repo = "Lighthouse"; rev = version; - hash = "sha256-FiS+jB5l5xtFIVISA6+K/jbyJZFPwLvy7G+dA+78kZU="; + hash = "sha256-GgKY7HDu6e/hpYNOZdcjLvaNfQOZMl+H6CmKTbd1LNE="; }; - cargoHash = "sha256-5IrY1ohG5oJF+LvrcHrHYT2nslICQPZptJYrrwMEmwQ="; + cargoHash = "sha256-oC5HA6diRlRWoeeQQgWR32yxZ2BLyFmKbaSkFBLdrXc="; nativeBuildInputs = [ pkg-config ]; diff --git a/pkgs/by-name/ll/llama-cpp/package.nix b/pkgs/by-name/ll/llama-cpp/package.nix index b1a82164129d..626336395493 100644 --- a/pkgs/by-name/ll/llama-cpp/package.nix +++ b/pkgs/by-name/ll/llama-cpp/package.nix @@ -75,13 +75,13 @@ let in effectiveStdenv.mkDerivation (finalAttrs: { pname = "llama-cpp"; - version = "6479"; + version = "6670"; src = fetchFromGitHub { owner = "ggml-org"; repo = "llama.cpp"; tag = "b${finalAttrs.version}"; - hash = "sha256-wgfYjG9m/ainCI85FlCb12Dz01R+pZfFeDX613M4xpQ="; + hash = "sha256-B4Qog7RLcre8KB9N+aVUZSJwlkHIIcCxR8jySoxbXoQ="; leaveDotGit = true; postFetch = '' git -C "$out" rev-parse --short HEAD > $out/COMMIT diff --git a/pkgs/by-name/mi/micronaut/package.nix b/pkgs/by-name/mi/micronaut/package.nix index b41b4f3b7a0c..812b6b323be5 100644 --- a/pkgs/by-name/mi/micronaut/package.nix +++ b/pkgs/by-name/mi/micronaut/package.nix @@ -9,11 +9,11 @@ stdenv.mkDerivation rec { pname = "micronaut"; - version = "4.9.3"; + version = "4.9.4"; src = fetchzip { url = "https://github.com/micronaut-projects/micronaut-starter/releases/download/v${version}/micronaut-cli-${version}.zip"; - sha256 = "sha256-y4ktyf/ydkL20k8ifgQfHJqZ2NhhNzPM0qWgEjbnZnI="; + sha256 = "sha256-zsC8hMXHRi8xJro/IhihGzw8Nx8loaMh4Y8xlmtTyMQ="; }; nativeBuildInputs = [ diff --git a/pkgs/by-name/mu/museeks/package.nix b/pkgs/by-name/mu/museeks/package.nix index a4ab04904132..4e22223b448a 100644 --- a/pkgs/by-name/mu/museeks/package.nix +++ b/pkgs/by-name/mu/museeks/package.nix @@ -16,11 +16,11 @@ stdenv.mkDerivation (finalAttrs: { pname = "museeks"; - version = "0.23.0"; + version = "0.23.1"; src = fetchurl { url = "https://github.com/martpie/museeks/releases/download/${finalAttrs.version}/Museeks_${finalAttrs.version}_amd64.deb"; - hash = "sha256-CT/P6tVgS7KD401ZktJBz1rk9CAz6gCm5zefud+prqQ="; + hash = "sha256-bji49ncJriDGrYoC0VYfblcGPDU66Ep+c/z9FNEXnkI="; }; nativeBuildInputs = [ diff --git a/pkgs/by-name/my/mydumper/package.nix b/pkgs/by-name/my/mydumper/package.nix index 7ee3f0b750e8..b283d864ecbc 100644 --- a/pkgs/by-name/my/mydumper/package.nix +++ b/pkgs/by-name/my/mydumper/package.nix @@ -6,7 +6,6 @@ installShellFiles, pkg-config, glib, - pcre, pcre2, util-linux, libsysprof-capture, @@ -52,7 +51,6 @@ stdenv.mkDerivation rec { buildInputs = [ glib - pcre pcre2 util-linux libmysqlclient diff --git a/pkgs/by-name/nc/ncps/package.nix b/pkgs/by-name/nc/ncps/package.nix index 2c2a1c8e18bd..01138fed0746 100644 --- a/pkgs/by-name/nc/ncps/package.nix +++ b/pkgs/by-name/nc/ncps/package.nix @@ -40,7 +40,10 @@ let homepage = "https://github.com/kalbasit/ncps"; license = lib.licenses.mit; mainProgram = "ncps"; - maintainers = [ lib.maintainers.kalbasit ]; + maintainers = with lib.maintainers; [ + kalbasit + aciceri + ]; }; }; in diff --git a/pkgs/by-name/nh/nhost-cli/package.nix b/pkgs/by-name/nh/nhost-cli/package.nix index dcdc9cd65158..81c51a2a3191 100644 --- a/pkgs/by-name/nh/nhost-cli/package.nix +++ b/pkgs/by-name/nh/nhost-cli/package.nix @@ -6,13 +6,13 @@ buildGoModule rec { pname = "nhost-cli"; - version = "1.31.2"; + version = "1.31.3"; src = fetchFromGitHub { owner = "nhost"; repo = "cli"; tag = "v${version}"; - hash = "sha256-RzLnhnnEDUIlRq89/CmhH7+o4Mt6GiXbGXDObSIk4tY="; + hash = "sha256-hUltJCehmlIDRLdJNGC/Oyjl6rnQHzjxSjrQEaDCdAo="; }; vendorHash = null; diff --git a/pkgs/by-name/ni/nixos-container/nixos-container.pl b/pkgs/by-name/ni/nixos-container/nixos-container.pl index c499a31da0cf..9cc5176b4f44 100755 --- a/pkgs/by-name/ni/nixos-container/nixos-container.pl +++ b/pkgs/by-name/ni/nixos-container/nixos-container.pl @@ -8,6 +8,11 @@ use Fcntl ':flock'; use Getopt::Long qw(:config gnu_getopt no_bundling); use Cwd 'abs_path'; use Time::HiRes; +use IPC::Run 'run'; + +# Version::Compare et al. don't work because they do the wrong thing on e.g. +# 25.11pre-git. +my $nixpkgsLib = "@lib@"; my $nsenter = "@util-linux@/bin/nsenter"; my $su = "@su@"; @@ -171,7 +176,7 @@ sub writeNixOSConfig { my $nixosConfig = <", \my $result; + chomp $result; + $result =~ s/^"([^"]+)"$/$1/g; + return $result; +} + +sub evalAttributeFlake { + my ($attribute) = @_; + run [ + "nix", "eval", "$flake#nixosConfigurations.\"$flakeAttr\".$attribute" + ], ">", \my $result; + chomp $result; + $result =~ s/^"([^"]+)"$/$1/g; + return $result; +} + +sub isAtLeast2511 { + my ($version) = @_; + run [ + "nix-instantiate", "--eval", "-E", "with import $nixpkgsLib; versionAtLeast \"$version\" \"25.11pre-git\"" + ], ">", \my $result; + chomp $result; + return $result eq "true"; +} + # Remove a directory while recursively unmounting all mounted filesystems within # that directory and unmounting/removing that directory afterwards as well. # @@ -426,6 +460,10 @@ elsif ($action eq "update") { } if (defined $flake) { + my $nixpkgsVersion = evalAttributeFlake "lib.version"; + if (isAtLeast2511($nixpkgsVersion) && evalAttributeFlake("config.boot.isNspawnContainer") ne "true") { + die "$0: on 25.11 and newer, containers require boot.isNspawnContainer=true. Please set this in $flake"; + } buildFlake(); system("nix-env", "-p", "$profileDir/system", "--set", $systemPath) == 0 or die "$0: failed to set container configuration\n"; @@ -441,6 +479,14 @@ elsif ($action eq "update") { } my $nixenvF = $nixosPath // ""; + + my $nixpkgsVersion = evalAttribute "pkgs.lib.version", $nixenvF, $nixosConfigFile; + if (isAtLeast2511($nixpkgsVersion) + && evalAttribute("config.boot.isNspawnContainer", $nixenvF, $nixosConfigFile) ne "true" + ) { + die "$0: on 25.11 and newer, containers require boot.isNspawnContainer=true. Refresh your configuration (or check the 25.11 release notes on how to correctly do that)"; + } + system("nix-env", "-p", "$profileDir/system", "-I", "nixos-config=$nixosConfigFile", "-f", $nixenvF, "--set", "-A", "system", @nixFlags) == 0 diff --git a/pkgs/by-name/ni/nixos-container/package.nix b/pkgs/by-name/ni/nixos-container/package.nix index 16341e0cb70e..cd6da383696b 100644 --- a/pkgs/by-name/ni/nixos-container/package.nix +++ b/pkgs/by-name/ni/nixos-container/package.nix @@ -7,6 +7,7 @@ configurationDirectory ? "/etc/nixos-containers", stateDirectory ? "/var/lib/nixos-containers", nixosTests, + path, }: replaceVarsWith { name = "nixos-container"; @@ -15,8 +16,12 @@ replaceVarsWith { src = ./nixos-container.pl; replacements = { - perl = perl.withPackages (p: [ p.FileSlurp ]); + perl = perl.withPackages (p: [ + p.FileSlurp + p.IPCRun + ]); su = "${shadow.su}/bin/su"; + lib = "${path + "/lib"}"; inherit configurationDirectory stateDirectory util-linux; }; diff --git a/pkgs/by-name/nv/nvidia-modprobe/package.nix b/pkgs/by-name/nv/nvidia-modprobe/package.nix index 59df6a1cfff9..f259ba6e9fd4 100644 --- a/pkgs/by-name/nv/nvidia-modprobe/package.nix +++ b/pkgs/by-name/nv/nvidia-modprobe/package.nix @@ -6,13 +6,13 @@ }: stdenv.mkDerivation rec { pname = "nvidia-modprobe"; - version = "580.82.09"; + version = "580.95.05"; src = fetchFromGitHub { owner = "NVIDIA"; repo = "nvidia-modprobe"; rev = version; - hash = "sha256-ZWQfl0hlbJELPRjjPef3AyTUIN/8T0J82i1NM8iYUvY="; + hash = "sha256-2guTV77XY8yV9TmwbM17zQGYygv7kgzkX4cyGWqSuV4="; }; nativeBuildInputs = [ gnum4 ]; diff --git a/pkgs/by-name/on/onedrive/package.nix b/pkgs/by-name/on/onedrive/package.nix index 312f23b3eebe..64a0077d23b1 100644 --- a/pkgs/by-name/on/onedrive/package.nix +++ b/pkgs/by-name/on/onedrive/package.nix @@ -89,6 +89,7 @@ stdenv.mkDerivation (finalAttrs: { maintainers = with lib.maintainers; [ peterhoeg bertof + guylamar2006 ]; platforms = lib.platforms.linux; }; diff --git a/pkgs/by-name/op/opentofu/package.nix b/pkgs/by-name/op/opentofu/package.nix index 67bb63b137a9..eed5a19636f1 100644 --- a/pkgs/by-name/op/opentofu/package.nix +++ b/pkgs/by-name/op/opentofu/package.nix @@ -42,7 +42,7 @@ let patches = [ ./provider-path-0_15.patch ]; passthru = { - inherit full plugins withPlugins; + inherit plugins; tests = { inherit opentofu_plugins_test; }; @@ -73,8 +73,6 @@ let }; }; - full = withPlugins (p: lib.filter lib.isDerivation (lib.attrValues p.actualProviders)); - opentofu_plugins_test = let mainTf = writeText "main.tf" '' @@ -88,7 +86,7 @@ let resource "random_id" "test" {} ''; - opentofu = package.withPlugins (p: [ p.random ]); + opentofu = (pluggable package).withPlugins (p: [ p.random ]); test = runCommand "opentofu-plugin-test" { buildInputs = [ opentofu ]; } '' # make it fail outside of sandbox export HTTP_PROXY=http://127.0.0.1:0 HTTPS_PROXY=https://127.0.0.1:0 @@ -105,89 +103,95 @@ let "recurseForDerivations" ]; - withPlugins = - plugins: + pluggable = + opentofu: let - actualPlugins = plugins package.plugins; + withPlugins = + plugins: + let + actualPlugins = plugins opentofu.plugins; - # Wrap PATH of plugins propagatedBuildInputs, plugins may have runtime dependencies on external binaries - wrapperInputs = lib.unique ( - lib.flatten (lib.catAttrs "propagatedBuildInputs" (builtins.filter (x: x != null) actualPlugins)) - ); + # Wrap PATH of plugins propagatedBuildInputs, plugins may have runtime dependencies on external binaries + wrapperInputs = lib.unique ( + lib.flatten (lib.catAttrs "propagatedBuildInputs" (builtins.filter (x: x != null) actualPlugins)) + ); - passthru = { - withPlugins = newplugins: withPlugins (x: newplugins x ++ actualPlugins); + passthru = { + withPlugins = newplugins: withPlugins (x: newplugins x ++ actualPlugins); + full = withPlugins (p: lib.filter lib.isDerivation (lib.attrValues p.actualProviders)); - # Expose wrappers around the override* functions of the terraform - # derivation. - # - # Note that this does not behave as anyone would expect if plugins - # are specified. The overrides are not on the user-visible wrapper - # derivation but instead on the function application that eventually - # generates the wrapper. This means: - # - # 1. When using overrideAttrs, only `passthru` attributes will - # become visible on the wrapper derivation. Other overrides that - # modify the derivation *may* still have an effect, but it can be - # difficult to follow. - # - # 2. Other overrides may work if they modify the terraform - # derivation, or they may have no effect, depending on what - # exactly is being changed. - # - # 3. Specifying overrides on the wrapper is unsupported. - # - # See nixpkgs#158620 for details. - overrideDerivation = f: (package.overrideDerivation f).withPlugins plugins; - overrideAttrs = f: (package.overrideAttrs f).withPlugins plugins; - override = x: (package.override x).withPlugins plugins; - }; + # Expose wrappers around the override* functions of the terraform + # derivation. + # + # Note that this does not behave as anyone would expect if plugins + # are specified. The overrides are not on the user-visible wrapper + # derivation but instead on the function application that eventually + # generates the wrapper. This means: + # + # 1. When using overrideAttrs, only `passthru` attributes will + # become visible on the wrapper derivation. Other overrides that + # modify the derivation *may* still have an effect, but it can be + # difficult to follow. + # + # 2. Other overrides may work if they modify the terraform + # derivation, or they may have no effect, depending on what + # exactly is being changed. + # + # 3. Specifying overrides on the wrapper is unsupported. + # + # See nixpkgs#158620 for details. + overrideDerivation = f: (pluggable (opentofu.overrideDerivation f)).withPlugins plugins; + overrideAttrs = f: (pluggable (opentofu.overrideAttrs f)).withPlugins plugins; + override = x: (pluggable (opentofu.override x)).withPlugins plugins; + }; + in + # Don't bother wrapping unless we actually have plugins, since the wrapper will stop automatic downloading + # of plugins, which might be counterintuitive if someone just wants a vanilla Terraform. + if actualPlugins == [ ] then + opentofu.overrideAttrs (orig: { + passthru = orig.passthru // passthru; + }) + else + lib.appendToName "with-plugins" ( + stdenv.mkDerivation { + inherit (opentofu) meta pname version; + nativeBuildInputs = [ makeWrapper ]; + + # Expose the passthru set with the override functions + # defined above, as well as any passthru values already + # set on `terraform` at this point (relevant in case a + # user overrides attributes). + passthru = opentofu.passthru // passthru; + + buildCommand = '' + # Create wrappers for terraform plugins because OpenTofu only + # walks inside of a tree of files. + # Also replace registry.terraform.io dir with registry.opentofu.org, + # so OpenTofu can find the plugins. + for providerDir in ${toString actualPlugins} + do + for file in $(find $providerDir/libexec/terraform-providers -type f) + do + relFile=''${file#$providerDir/} + relFile=''${relFile/registry.terraform.io/registry.opentofu.org} + mkdir -p $out/$(dirname $relFile) + cat < $out/$relFile + #!${runtimeShell} + exec "$file" "$@" + WRAPPER + chmod +x $out/$relFile + done + done + + # Create a wrapper for opentofu to point it to the plugins dir. + mkdir -p $out/bin/ + makeWrapper "${opentofu}/bin/tofu" "$out/bin/tofu" \ + --set NIX_TERRAFORM_PLUGIN_DIR $out/libexec/terraform-providers \ + --prefix PATH : "${lib.makeBinPath wrapperInputs}" + ''; + } + ); in - # Don't bother wrapping unless we actually have plugins, since the wrapper will stop automatic downloading - # of plugins, which might be counterintuitive if someone just wants a vanilla Terraform. - if actualPlugins == [ ] then - package.overrideAttrs (orig: { - passthru = orig.passthru // passthru; - }) - else - lib.appendToName "with-plugins" ( - stdenv.mkDerivation { - inherit (package) meta pname version; - nativeBuildInputs = [ makeWrapper ]; - - # Expose the passthru set with the override functions - # defined above, as well as any passthru values already - # set on `terraform` at this point (relevant in case a - # user overrides attributes). - passthru = package.passthru // passthru; - - buildCommand = '' - # Create wrappers for terraform plugins because OpenTofu only - # walks inside of a tree of files. - # Also replace registry.terraform.io dir with registry.opentofu.org, - # so OpenTofu can find the plugins. - for providerDir in ${toString actualPlugins} - do - for file in $(find $providerDir/libexec/terraform-providers -type f) - do - relFile=''${file#$providerDir/} - relFile=''${relFile/registry.terraform.io/registry.opentofu.org} - mkdir -p $out/$(dirname $relFile) - cat < $out/$relFile - #!${runtimeShell} - exec "$file" "$@" - WRAPPER - chmod +x $out/$relFile - done - done - - # Create a wrapper for opentofu to point it to the plugins dir. - mkdir -p $out/bin/ - makeWrapper "${package}/bin/tofu" "$out/bin/tofu" \ - --set NIX_TERRAFORM_PLUGIN_DIR $out/libexec/terraform-providers \ - --prefix PATH : "${lib.makeBinPath wrapperInputs}" - ''; - } - ); + withPlugins (_: [ ]); in -package +pluggable package diff --git a/pkgs/by-name/po/poselib/package.nix b/pkgs/by-name/po/poselib/package.nix new file mode 100644 index 000000000000..b4478e30e8de --- /dev/null +++ b/pkgs/by-name/po/poselib/package.nix @@ -0,0 +1,39 @@ +{ + lib, + stdenv, + fetchFromGitHub, + gitUpdater, + cmake, + eigen, + pkg-config, +}: + +stdenv.mkDerivation (final: { + pname = "poselib"; + version = "2.0.5"; + + src = fetchFromGitHub { + owner = "PoseLib"; + repo = "PoseLib"; + rev = "v${final.version}"; + hash = "sha256-fARRKT2UoPuuk9FOOsBdrACwGiGXWg/mLV4R0QIjeak="; + }; + + buildInputs = [ eigen ]; + + nativeBuildInputs = [ + cmake + pkg-config + ]; + + passthru.updateScript = gitUpdater { rev-prefix = "v"; }; + + meta = with lib; { + description = "A collection of minimal solvers for camera pose estimation"; + homepage = "https://github.com/PoseLib/PoseLib"; + changelog = "https://github.com/PoseLib/PoseLib/releases/tag/v${final.version}"; + license = licenses.bsd3; + platforms = platforms.unix; + maintainers = with maintainers; [ usertam ]; + }; +}) diff --git a/pkgs/by-name/po/posting/package.nix b/pkgs/by-name/po/posting/package.nix index 37c874d33ae4..707e4c5bca3d 100644 --- a/pkgs/by-name/po/posting/package.nix +++ b/pkgs/by-name/po/posting/package.nix @@ -6,14 +6,14 @@ }: python3Packages.buildPythonApplication rec { pname = "posting"; - version = "2.9.0"; + version = "2.9.1"; pyproject = true; src = fetchFromGitHub { owner = "darrenburns"; repo = "posting"; tag = version; - hash = "sha256-JkYcLh3S+vLfSCgIpiRu9tKPMjjDSdHtO8faeMlgbe8="; + hash = "sha256-YaN7kuGRZ6UJTuf2vYDnIinyzMzsKDQEA4B5SmmggA4="; }; pythonRelaxDeps = true; diff --git a/pkgs/by-name/pw/pwmenu/package.nix b/pkgs/by-name/pw/pwmenu/package.nix new file mode 100644 index 000000000000..3634c1bc92c8 --- /dev/null +++ b/pkgs/by-name/pw/pwmenu/package.nix @@ -0,0 +1,44 @@ +{ + fetchFromGitHub, + lib, + pipewire, + pkg-config, + rustPlatform, +}: + +rustPlatform.buildRustPackage rec { + pname = "pwmenu"; + version = "0.3.0"; + + src = fetchFromGitHub { + owner = "e-tho"; + repo = "pwmenu"; + tag = "v${version}"; + hash = "sha256-Q02kOMC6oQ3fNyDWW9ztLgMs3wR4cA53/wmkbecTr/o="; + }; + + cargoHash = "sha256-jX4D4Xv2WYTcWnYO2cNsu7L9ppIw//Tkxl+Y7tflk+A="; + + nativeBuildInputs = [ + pkg-config + rustPlatform.bindgenHook + ]; + + buildInputs = [ + pipewire + ]; + + meta = { + homepage = "https://github.com/e-tho/pwmenu"; + description = "Launcher-driven audio manager for Linux"; + longDescription = '' + Use `pwmenu --launcher ` + Supported launchers are: `dmenu`, `fuzzel`, `rofi`, `walker` and `custom` with `stdin` + for details refer to https://github.com/e-tho/pwmenu/blob/main/README.md#usage + ''; + mainProgram = "pwmenu"; + platforms = lib.platforms.linux; + license = lib.licenses.gpl3Plus; + maintainers = with lib.maintainers; [ vuimuich ]; + }; +} diff --git a/pkgs/by-name/qa/qadwaitadecorations/package.nix b/pkgs/by-name/qa/qadwaitadecorations/package.nix index 6dad24c390b4..7a1f1abb2037 100644 --- a/pkgs/by-name/qa/qadwaitadecorations/package.nix +++ b/pkgs/by-name/qa/qadwaitadecorations/package.nix @@ -21,13 +21,13 @@ let in stdenv.mkDerivation (finalAttrs: { pname = "qadwaitadecorations"; - version = "0.1.6"; + version = "0.1.7"; src = fetchFromGitHub { owner = "FedoraQt"; repo = "QAdwaitaDecorations"; rev = finalAttrs.version; - hash = "sha256-ZU3cwFwQECh4Z6YcTzD2WooZmJ2nSUABYft3dfakSuY="; + hash = "sha256-Zg2G3vuRD/kK5C2fFq6Cft218uFyBvfXtO1DHKQECFQ="; }; nativeBuildInputs = [ diff --git a/pkgs/applications/radio/qradiolink/default.nix b/pkgs/by-name/qr/qradiolink/package.nix similarity index 61% rename from pkgs/applications/radio/qradiolink/default.nix rename to pkgs/by-name/qr/qradiolink/package.nix index ccdb9ffe3df6..5294232fe854 100644 --- a/pkgs/applications/radio/qradiolink/default.nix +++ b/pkgs/by-name/qr/qradiolink/package.nix @@ -1,8 +1,10 @@ { lib, fetchFromGitHub, + fetchpatch, libpulseaudio, libconfig, + pkg-config, # Needs a gnuradio built with qt gui support gnuradio, log4cpp, @@ -24,30 +26,41 @@ uhd, }: -gnuradio.pkgs.mkDerivation { +gnuradio.pkgs.mkDerivation rec { pname = "qradiolink"; - # https://github.com/qradiolink/qradiolink/tree/gr_3.10 - version = "0.9.0-1-unstable-2024-08-29"; + version = "0.9.1-3"; src = fetchFromGitHub { owner = "qradiolink"; repo = "qradiolink"; - rev = "f1006a20e0a642d0ac20aab18b19fa97567f2621"; - sha256 = "sha256-9AYFO+mmwLAH8gEpZn6qcENabc/KBMcg/0wCTKsInNY="; + tag = version; + hash = "sha256-0inXfeOSVmJYtNhD6WBExjT43STfBjePomKILxoHO6Q="; }; + patches = [ + # dmr: add explicit cstdint import + (fetchpatch { + url = "https://github.com/qradiolink/qradiolink/pull/131/commits/bdd3b47708edf42b281fb9e5507d356d475f3df9.patch"; + hash = "sha256-Uoi8/IK8yBmfPL7RAkCGuyHdcdJZ+YMxccviY7Z+hXs="; + }) + # qmake: find protobuf via pkg-config + (fetchpatch { + url = "https://github.com/qradiolink/qradiolink/pull/132/commits/cd3e4bc188a60bc85693fe3de4540c48f325deb4.patch"; + hash = "sha256-ufSStm0pyDkCUIx0SjVVHZhA4gW7Ip6PiexPg34DsCo="; + }) + ]; + preBuild = '' cd src/ext protoc --cpp_out=. Mumble.proto protoc --cpp_out=. QRadioLink.proto - cd ../.. - qmake + cd - ''; installPhase = '' - install -D qradiolink $out/bin/qradiolink + install -Dm755 qradiolink -t $out/bin + install -Dm644 qradiolink.desktop -t $out/share/applications install -Dm644 src/res/icon.png $out/share/pixmaps/qradiolink.png - install -Dm644 qradiolink.desktop $out/share/applications/qradiolink.desktop ''; buildInputs = [ @@ -77,23 +90,30 @@ gnuradio.pkgs.mkDerivation { cppzmq gnuradio.qwt uhd + protobuf ] ++ lib.optionals (gnuradio.hasFeature "gr-ctrlport") [ thrift gnuradio.unwrapped.python.pkgs.thrift ]; nativeBuildInputs = [ + pkg-config protobuf gnuradio.qt.qmake gnuradio.qt.wrapQtAppsHook ]; - meta = with lib; { + meta = { description = "SDR transceiver application for analog and digital modes"; mainProgram = "qradiolink"; homepage = "http://qradiolink.org/"; - license = licenses.agpl3Plus; - maintainers = [ maintainers.markuskowa ]; - platforms = platforms.linux; + license = with lib.licenses; [ + bsd2 + gpl3Only + lgpl3Only + mit + ]; + maintainers = with lib.maintainers; [ markuskowa ]; + platforms = lib.platforms.linux; }; } diff --git a/pkgs/by-name/ra/railway/package.nix b/pkgs/by-name/ra/railway/package.nix index 9aade72c2cc8..371267663137 100644 --- a/pkgs/by-name/ra/railway/package.nix +++ b/pkgs/by-name/ra/railway/package.nix @@ -7,16 +7,16 @@ }: rustPlatform.buildRustPackage rec { pname = "railway"; - version = "4.8.0"; + version = "4.10.0"; src = fetchFromGitHub { owner = "railwayapp"; repo = "cli"; rev = "v${version}"; - hash = "sha256-zZiEhXVIffYALiXiKwLlPpr8XchGii/i6VmDnoZTeq0="; + hash = "sha256-fvasxm9BjoHvSS5qqlYdCFN7j4E/MAsGhaKxt2y8Bhw="; }; - cargoHash = "sha256-Khk4D7xSfm4q3EWR9UHSzrf+m6NHo74wrPYYAh6tG4g="; + cargoHash = "sha256-yQtsL4FHEuA2Ji5HW4LYoYoY1CDQf8LO0E1en04JpOA="; nativeBuildInputs = [ pkg-config ]; diff --git a/pkgs/by-name/ri/river-classic/package.nix b/pkgs/by-name/ri/river-classic/package.nix index 584b31d40412..408e3c67ff70 100644 --- a/pkgs/by-name/ri/river-classic/package.nix +++ b/pkgs/by-name/ri/river-classic/package.nix @@ -25,7 +25,7 @@ stdenv.mkDerivation (finalAttrs: { pname = "river-classic"; - version = "0.3.12"; + version = "0.3.13"; outputs = [ "out" ] ++ lib.optionals withManpages [ "man" ]; @@ -33,7 +33,7 @@ stdenv.mkDerivation (finalAttrs: { domain = "codeberg.org"; owner = "river"; repo = "river-classic"; - hash = "sha256-ZYJYQINv6aNj8jyPOtMh5kf/HweIweTztWUStbr/9Zc="; + hash = "sha256-XLWvxSChYN5wyhr8R8/3Pfykw61k451XmvgoM45zkEk="; tag = "v${finalAttrs.version}"; }; diff --git a/pkgs/by-name/rs/rs-tftpd/package.nix b/pkgs/by-name/rs/rs-tftpd/package.nix index ba0ea94b2a8f..e136008eb6e8 100644 --- a/pkgs/by-name/rs/rs-tftpd/package.nix +++ b/pkgs/by-name/rs/rs-tftpd/package.nix @@ -5,18 +5,18 @@ nix-update-script, }: -rustPlatform.buildRustPackage rec { +rustPlatform.buildRustPackage (finalAttrs: { pname = "rs-tftpd"; - version = "0.4.0"; + version = "0.5.0"; src = fetchFromGitHub { owner = "altugbakan"; repo = "rs-tftpd"; - rev = version; - hash = "sha256-iUoIBQTMC+oXsuZcnSp1K4uFuETKTcfaW6+fBa5PQw8="; + tag = finalAttrs.version; + hash = "sha256-YxXUwbzkuxnRrri49DhjvO/LJRWWtFutLbg151GnT5M="; }; - cargoHash = "sha256-ZED5+WnOALLXAW/l/QMFKWco6kJnz4rFv8nfp00HS78="; + cargoHash = "sha256-FKwQr4u7lVN12XPyDus7QoIpthYbT84SFkMJvLTqXRU="; buildFeatures = [ "client" ]; @@ -25,6 +25,7 @@ rustPlatform.buildRustPackage rec { meta = with lib; { description = "TFTP Server Daemon implemented in Rust"; homepage = "https://github.com/altugbakan/rs-tftpd"; + changelog = "https://github.com/altugbakan/rs-tftpd/releases/tag/${finalAttrs.version}"; license = licenses.mit; maintainers = with maintainers; [ adamcstephens @@ -32,4 +33,4 @@ rustPlatform.buildRustPackage rec { ]; mainProgram = "tftpd"; }; -} +}) diff --git a/pkgs/by-name/rs/rsop/package.nix b/pkgs/by-name/rs/rsop/package.nix index b88fa64b2e7b..add5e3d6308b 100644 --- a/pkgs/by-name/rs/rsop/package.nix +++ b/pkgs/by-name/rs/rsop/package.nix @@ -11,17 +11,17 @@ rustPlatform.buildRustPackage rec { pname = "rsop"; - version = "0.7.2"; + version = "0.8.0"; src = fetchFromGitea { domain = "codeberg.org"; owner = "heiko"; repo = "rsop"; rev = "rsop/v${version}"; - hash = "sha256-6vP+epxsDid3M7cpfpOY29VWeIbuCB30qtmotPhzShc="; + hash = "sha256-bbB2IefXauVV6LjpJxSNy4RVYjAGH0osTpUZGGscGec="; }; - cargoHash = "sha256-BSsqI3zo7eC4zGIsU1xScnjWNwt4iTqs4SWzbOUt7Iw="; + cargoHash = "sha256-P27PnFNArKn3CQtik6TaV7eW/8bQiOZ57ZbMth2pNiY="; nativeBuildInputs = [ pkg-config ]; diff --git a/pkgs/by-name/sc/schemacrawler/package.nix b/pkgs/by-name/sc/schemacrawler/package.nix index 4ddcb0ca363d..a15836673f6f 100644 --- a/pkgs/by-name/sc/schemacrawler/package.nix +++ b/pkgs/by-name/sc/schemacrawler/package.nix @@ -8,11 +8,11 @@ stdenv.mkDerivation (finalAttrs: { pname = "schemacrawler"; - version = "16.28.2"; + version = "16.28.3"; src = fetchzip { url = "https://github.com/schemacrawler/SchemaCrawler/releases/download/v${finalAttrs.version}/schemacrawler-${finalAttrs.version}-bin.zip"; - hash = "sha256-TF6VCnAQBXnxO9h28Q93rSeYs4GaABxb6lxjk6x6nA4="; + hash = "sha256-OtQYAJe5eHoEis8Azy1LPxJdZR4HlKn8UhlDglqarto="; }; nativeBuildInputs = [ makeWrapper ]; diff --git a/pkgs/by-name/si/simplenes/package.nix b/pkgs/by-name/si/simplenes/package.nix index 6a58fa8619d9..74ee84a47edd 100644 --- a/pkgs/by-name/si/simplenes/package.nix +++ b/pkgs/by-name/si/simplenes/package.nix @@ -33,7 +33,7 @@ stdenv.mkDerivation { homepage = "https://github.com/amhndu/SimpleNES"; description = "NES emulator written in C++"; license = lib.licenses.gpl3; - maintainers = [ ]; + maintainers = with lib.maintainers; [ guylamar2006 ]; platforms = lib.platforms.linux; mainProgram = "SimpleNES"; }; diff --git a/pkgs/by-name/sn/snapweb/package.nix b/pkgs/by-name/sn/snapweb/package.nix index a18ca6a44d15..7cd686fd14b9 100644 --- a/pkgs/by-name/sn/snapweb/package.nix +++ b/pkgs/by-name/sn/snapweb/package.nix @@ -8,16 +8,16 @@ buildNpmPackage rec { pname = "snapweb"; - version = "0.9.1"; + version = "0.9.2"; src = fetchFromGitHub { owner = "badaix"; repo = "snapweb"; rev = "v${version}"; - hash = "sha256-vrPmN06dLEoz7vFrH8kOdudg9FQcd1BpMWKpU6kZrzE="; + hash = "sha256-7W7rvJPVcRtXcQt+wWAvrl0DOIh7zEfXZdFDcH23/ls="; }; - npmDepsHash = "sha256-VDGoZ6XgVtr7xePXmfW4Vk6iTZv1HRx7bjsS+Qauz3U="; + npmDepsHash = "sha256-STZ/+vmiUAOZ8+yeaFg+428pZ/iZZXXUeGx6gLmnDQ8="; # For 'sharp' dependency, otherwise it will try to build it nativeBuildInputs = [ pkg-config ]; diff --git a/pkgs/by-name/so/sonar-scanner-cli/package.nix b/pkgs/by-name/so/sonar-scanner-cli/package.nix index f2aac188a641..b9a0f9e4ef04 100644 --- a/pkgs/by-name/so/sonar-scanner-cli/package.nix +++ b/pkgs/by-name/so/sonar-scanner-cli/package.nix @@ -11,16 +11,16 @@ maven.buildMavenPackage rec { pname = "sonar-scanner-cli"; - version = "7.2.0.5079"; + version = "7.3.0.5189"; src = fetchFromGitHub { owner = "SonarSource"; repo = "sonar-scanner-cli"; tag = version; - hash = "sha256-ndpOjFE7RvGoQ32iTupC0RORFeUMikjWnDdty5XRApE="; + hash = "sha256-Vbd+vQKFQo/wzGF4ekcCiEczlyuTD41Liz+nePR9lVA="; }; - mvnHash = "sha256-fS5Hbt0p+DxFpB2x1ot/FGG1R0OdVIys+BbyDTtTLQQ="; + mvnHash = "sha256-1SPpGu6uQ1Xa0U/DUjfZAXi6SQN/8LImU6THv4e9CSo="; mvnParameters = "-Dproject.build.outputTimestamp=1980-01-01T00:00:02Z"; diff --git a/pkgs/by-name/te/temporal/package.nix b/pkgs/by-name/te/temporal/package.nix index 4563b01153a0..eeff38ecea96 100644 --- a/pkgs/by-name/te/temporal/package.nix +++ b/pkgs/by-name/te/temporal/package.nix @@ -9,16 +9,16 @@ buildGoModule rec { pname = "temporal"; - version = "1.28.1"; + version = "1.29.0"; src = fetchFromGitHub { owner = "temporalio"; repo = "temporal"; rev = "v${version}"; - hash = "sha256-I1Xh9F9c/h6GZxyE75Q3WN7BPN79QuKlB0XKR30vuwg="; + hash = "sha256-oxn/78nQCvlEkSqabVV47siWSSnz32tpDOweqScPYvY="; }; - vendorHash = "sha256-T90mj+EVqlHJVGaUOGwD8acHTbYH6g8NEzKGFwjKu4M="; + vendorHash = "sha256-HW2j8swbaWwU1i3udqlT8VyFreML6ZH14zWxF8L5NTQ="; excludedPackages = [ "./build" ]; diff --git a/pkgs/by-name/th/thermald/package.nix b/pkgs/by-name/th/thermald/package.nix index 77909a2c5c72..1f218981af0b 100644 --- a/pkgs/by-name/th/thermald/package.nix +++ b/pkgs/by-name/th/thermald/package.nix @@ -19,7 +19,7 @@ stdenv.mkDerivation rec { pname = "thermald"; - version = "2.5.9"; + version = "2.5.10"; outputs = [ "out" @@ -30,7 +30,7 @@ stdenv.mkDerivation rec { owner = "intel"; repo = "thermal_daemon"; rev = "v${version}"; - sha256 = "sha256-ydv6wZ3r2QxVji9bSx0sgpaOQNtgN+Y4rPZ44XtxNh8="; + sha256 = "sha256-+dk3lOlI8kaf8NvcWQSvTxSqVGPCgvVnTB9nltqQHrU="; }; nativeBuildInputs = [ diff --git a/pkgs/by-name/tr/trdl-client/package.nix b/pkgs/by-name/tr/trdl-client/package.nix index af666b429166..bce2583cba1e 100644 --- a/pkgs/by-name/tr/trdl-client/package.nix +++ b/pkgs/by-name/tr/trdl-client/package.nix @@ -6,13 +6,13 @@ }: buildGoModule (finalAttrs: { pname = "trdl-client"; - version = "0.11.1"; + version = "0.12.0"; src = fetchFromGitHub { owner = "werf"; repo = "trdl"; tag = "v${finalAttrs.version}"; - hash = "sha256-/rhRsKlkRYQwN5IrFcOXiU12nEQMN75o2DPku5YPFe0="; + hash = "sha256-CVJdnGrQRaenQ8/1EzUr6BNc0DtfAL1fLVfqJzy5A3Q="; }; sourceRoot = "${finalAttrs.src.name}/client"; diff --git a/pkgs/by-name/tr/treedome/package.nix b/pkgs/by-name/tr/treedome/package.nix index c9575d0d0b80..dcb7ab920818 100644 --- a/pkgs/by-name/tr/treedome/package.nix +++ b/pkgs/by-name/tr/treedome/package.nix @@ -19,20 +19,20 @@ rustPlatform.buildRustPackage rec { pname = "treedome"; - version = "0.5.4"; + version = "0.6.1"; src = fetchgit { url = "https://codeberg.org/solver-orgz/treedome"; rev = version; - hash = "sha256-fJnrM9I11JKqzrprXa51mJiz9oO5hDp6u69FqJs5l8o="; + hash = "sha256-qa87pgNHGRhP1G4TEFHYrkiJ9AHWG7PUdgxEF4X9EM8="; fetchLFS = true; }; - cargoHash = "sha256-scCF4xpc1COdlg57/eNTPdgY7/cJkdcc2s1YNraXzXk="; + cargoHash = "sha256-Rg65BiHQF7bBBCtc5F+gY31yhcuI0+IDfxr3pFmxT+w="; offlineCache = fetchYarnDeps { yarnLock = "${src}/yarn.lock"; - hash = "sha256-in1A1XcfZK5F/EV5CYgfqig+8vKsxd6XhzfSv7Z0nNQ="; + hash = "sha256-Q0xsi1xymQne6qN0oxm4YkaDLnGL17iuj70CTdQlxzM="; }; postPatch = '' diff --git a/pkgs/by-name/tr/trimmomatic/package.nix b/pkgs/by-name/tr/trimmomatic/package.nix index c3285d2be4bd..740282aa9ce9 100644 --- a/pkgs/by-name/tr/trimmomatic/package.nix +++ b/pkgs/by-name/tr/trimmomatic/package.nix @@ -1,70 +1,49 @@ { lib, - stdenv, fetchFromGitHub, - ant, - jdk21_headless, jre_minimal, makeWrapper, stripJavaArchivesHook, + maven, + nix-update-script, }: -let - jdk = jdk21_headless; - # Reduce closure size - jre = jre_minimal.override { - modules = [ - "java.base" - "java.logging" - ]; - jdk = jdk21_headless; - }; -in -stdenv.mkDerivation (finalAttrs: { + +maven.buildMavenPackage rec { pname = "trimmomatic"; - version = "0.39"; + version = "0.40"; src = fetchFromGitHub { owner = "usadellab"; repo = "Trimmomatic"; - rev = "v${finalAttrs.version}"; - hash = "sha256-u+ubmacwPy/vsEi0YQCv0fTnVDesQvqeQDEwCbS8M6I="; + rev = "v${version}"; + hash = "sha256-pLUjSVePN++G2XZrdKEdobgBO+UD0PZ9wlhSUlZ7na8="; }; - # Remove jdk version requirement - postPatch = '' - substituteInPlace ./build.xml \ - --replace 'source="1.5" target="1.5"' "" - ''; + mvnHash = "sha256-1XnVdud8nI2SuEPXnwEmbudM+QAeoSVTn0UZ8PKJH44="; nativeBuildInputs = [ - ant - jdk makeWrapper stripJavaArchivesHook ]; - buildPhase = '' - runHook preBuild - - ant - - runHook postBuild - ''; - installPhase = '' runHook preInstall - install -Dm644 dist/jar/trimmomatic-*.jar -t $out/share/trimmomatic + install -Dm644 target/trimmomatic-${version}.jar -t $out/share/trimmomatic cp -r adapters $out/share/trimmomatic - makeWrapper ${jre}/bin/java $out/bin/trimmomatic \ - --add-flags "-jar $out/share/trimmomatic/trimmomatic-*.jar" + makeWrapper ${lib.getBin jre_minimal}/bin/java $out/bin/trimmomatic \ + --add-flags "-jar $out/share/trimmomatic/trimmomatic-${version}.jar" runHook postInstall ''; + passthru = { + updateScript = nix-update-script { }; + }; + meta = { - changelog = "https://github.com/usadellab/Trimmomatic/blob/main/versionHistory.txt"; + changelog = "https://github.com/usadellab/Trimmomatic/releases/tag/v${version}"; description = "Flexible read trimming tool for Illumina NGS data"; longDescription = '' Trimmomatic performs a variety of useful trimming tasks for illumina @@ -82,4 +61,4 @@ stdenv.mkDerivation (finalAttrs: { mainProgram = "trimmomatic"; maintainers = [ lib.maintainers.kupac ]; }; -}) +} diff --git a/pkgs/by-name/va/valum/package.nix b/pkgs/by-name/va/valum/package.nix deleted file mode 100644 index e2dec1824b57..000000000000 --- a/pkgs/by-name/va/valum/package.nix +++ /dev/null @@ -1,51 +0,0 @@ -{ - lib, - stdenv, - meson, - ninja, - pkg-config, - fetchFromGitHub, - glib, - vala, - ctpl, - libgee, - libsoup_2_4, - fcgi, -}: - -stdenv.mkDerivation rec { - pname = "valum"; - version = "0.3.18"; - - src = fetchFromGitHub { - owner = "valum-framework"; - repo = "valum"; - rev = "v${version}"; - sha256 = "sha256-baAv83YiX8HdBm/t++ktB7pmTVlt4aWZ5xnsAs/NrTI="; - }; - - nativeBuildInputs = [ - meson - ninja - pkg-config - ]; - buildInputs = [ - glib - vala - ctpl - libgee - libsoup_2_4 - fcgi - ]; - - meta = with lib; { - homepage = "https://github.com/valum-framework/valum"; - description = "Web micro-framework written in Vala"; - license = licenses.lgpl3; - platforms = platforms.linux; - maintainers = [ ]; - # Likely broken by GLib 2.74 switch to PCRE 2. - # https://github.com/valum-framework/valum/issues/238 - broken = true; - }; -} diff --git a/pkgs/by-name/ve/vencord/package.nix b/pkgs/by-name/ve/vencord/package.nix index 7b9297b40416..2bb5378dd97a 100644 --- a/pkgs/by-name/ve/vencord/package.nix +++ b/pkgs/by-name/ve/vencord/package.nix @@ -18,13 +18,13 @@ stdenv.mkDerivation (finalAttrs: { pname = "vencord"; - version = "1.13.0"; + version = "1.13.1"; src = fetchFromGitHub { owner = "Vendicated"; repo = "Vencord"; tag = "v${finalAttrs.version}"; - hash = "sha256-MdbO74vAbsZyB6seOqxHvQL0HT4IdVnDjd+N3a9XAns="; + hash = "sha256-FqRRpsS1NPpxJr6iaDvQJ3fuX07oo08lZ6f+oEQb3MM="; }; pnpmDeps = pnpm_10.fetchDeps { diff --git a/pkgs/by-name/vo/volatility3/package.nix b/pkgs/by-name/vo/volatility3/package.nix index aa64c2923a3a..750892fc96ce 100644 --- a/pkgs/by-name/vo/volatility3/package.nix +++ b/pkgs/by-name/vo/volatility3/package.nix @@ -6,14 +6,14 @@ python3.pkgs.buildPythonApplication rec { pname = "volatility3"; - version = "2.26.0"; + version = "2.26.2"; pyproject = true; src = fetchFromGitHub { owner = "volatilityfoundation"; repo = "volatility3"; tag = "v${version}"; - hash = "sha256-O12w1NM2Hdp3UeeHpvibYfqLlXdQ+baqWX1qrr6SxSE="; + hash = "sha256-B7S66/HpXuMOXvKzrnQCskbDQ0kjwBXN85VLr90w+c4="; }; build-system = with python3.pkgs; [ diff --git a/pkgs/by-name/wo/wootility/package.nix b/pkgs/by-name/wo/wootility/package.nix index 4a99436a85ed..9cce172a8c13 100644 --- a/pkgs/by-name/wo/wootility/package.nix +++ b/pkgs/by-name/wo/wootility/package.nix @@ -7,10 +7,10 @@ let pname = "wootility"; - version = "5.1.0"; + version = "5.1.1"; src = fetchurl { url = "https://wootility-updates.ams3.cdn.digitaloceanspaces.com/wootility-linux/Wootility-${version}.AppImage"; - sha256 = "sha256-y65aqHBAGkzjobUMoBPQNkfh19rNVarPctcxmNFxlho="; + sha256 = "sha256-NDTRsrOZljvFOkvBN40CmH4GD6szT3c9qoFdFGpZ5Oc="; }; in diff --git a/pkgs/by-name/xr/xrandr-invert-colors/package.nix b/pkgs/by-name/xr/xrandr-invert-colors/package.nix index ecc75ba4c2b4..8cbf313d8540 100644 --- a/pkgs/by-name/xr/xrandr-invert-colors/package.nix +++ b/pkgs/by-name/xr/xrandr-invert-colors/package.nix @@ -3,33 +3,37 @@ stdenv, fetchFromGitHub, libXrandr, + libxcb, }: -stdenv.mkDerivation rec { +stdenv.mkDerivation (finalAttrs: { pname = "xrandr-invert-colors"; version = "0.02"; src = fetchFromGitHub { owner = "zoltanp"; repo = "xrandr-invert-colors"; - rev = "v${version}"; - sha256 = "sha256-MIbHNJFDQsvjPUbperTKKbHY5GSgItvRyV5OsfpzYT4="; + tag = "v${finalAttrs.version}"; + hash = "sha256-MIbHNJFDQsvjPUbperTKKbHY5GSgItvRyV5OsfpzYT4="; }; - buildInputs = [ libXrandr ]; + buildInputs = [ + libXrandr + libxcb + ]; installPhase = '' - mkdir -p $out/bin - mv xrandr-invert-colors.bin xrandr-invert-colors - install xrandr-invert-colors $out/bin + runHook preInstall + install -Dm755 xrandr-invert-colors.bin $out/bin/xrandr-invert-colors + runHook postInstall ''; - meta = with lib; { - description = "Inverts the colors of your screen"; + meta = { + description = "Invert colors on all screens, using XRandR"; license = lib.licenses.gpl3Plus; homepage = "https://github.com/zoltanp/xrandr-invert-colors"; maintainers = [ lib.maintainers.magnetophon ]; - platforms = platforms.linux; + platforms = lib.platforms.linux; mainProgram = "xrandr-invert-colors"; }; -} +}) diff --git a/pkgs/development/beam-modules/default.nix b/pkgs/development/beam-modules/default.nix index c27feb625885..2c6dd9cc15dc 100644 --- a/pkgs/development/beam-modules/default.nix +++ b/pkgs/development/beam-modules/default.nix @@ -45,7 +45,6 @@ let fetchMixDeps = callPackage ./fetch-mix-deps.nix { }; mixRelease = callPackage ./mix-release.nix { }; - erlang-ls = callPackage ./erlang-ls { }; erlfmt = callPackage ./erlfmt { }; elvis-erlang = callPackage ./elvis-erlang { }; diff --git a/pkgs/development/beam-modules/erlang-ls/1576.diff b/pkgs/development/beam-modules/erlang-ls/1576.diff deleted file mode 100644 index 175ff980b09e..000000000000 --- a/pkgs/development/beam-modules/erlang-ls/1576.diff +++ /dev/null @@ -1,12 +0,0 @@ -diff --git a/apps/els_lsp/test/els_completion_SUITE.erl b/apps/els_lsp/test/els_completion_SUITE.erl -index b610b1d4..9c8614f0 100644 ---- a/apps/els_lsp/test/els_completion_SUITE.erl -+++ b/apps/els_lsp/test/els_completion_SUITE.erl -@@ -711,6 +711,7 @@ exported_types(Config) -> - <<"filename_all">>, - <<"io_device">> - ] ++ -+ [<<"io_server">> || OtpRelease >= 27] ++ - [<<"location">> || OtpRelease >= 26] ++ - [ - <<"mode">>, diff --git a/pkgs/development/beam-modules/erlang-ls/default.nix b/pkgs/development/beam-modules/erlang-ls/default.nix deleted file mode 100644 index 8372aaccbafb..000000000000 --- a/pkgs/development/beam-modules/erlang-ls/default.nix +++ /dev/null @@ -1,102 +0,0 @@ -{ - erlang, - fetchFromGitHub, - fetchgit, - fetchHex, - rebar3Relx, - buildRebar3, - rebar3-proper, - stdenv, - writeScript, - lib, -}: -let - version = "1.1.0"; - owner = "erlang-ls"; - repo = "erlang_ls"; - - deps = import ./rebar-deps.nix { - inherit fetchHex fetchFromGitHub fetchgit; - builder = buildRebar3; - overrides = ( - self: super: { - proper = super.proper.overrideAttrs (_: { - configurePhase = "true"; - }); - redbug = super.redbug.overrideAttrs (_: { - patchPhase = '' - substituteInPlace rebar.config --replace ", warnings_as_errors" "" - ''; - }); - json_polyfill = super.json_polyfill.overrideAttrs (_: { - # When compiling with erlang >= 27, the json_polyfill rebar script will - # delete the json.beam file as it's not needed. However, we need to - # adjust this path as the nix build will put the beam file under `ebin` - # instead of `$REBAR_DEPS_DIR/json_polyfill/ebin`. - postPatch = '' - substituteInPlace rebar.config.script --replace "{erlc_compile, \"rm \\\"\$REBAR_DEPS_DIR/json_polyfill/ebin/json.beam\\\"\"}" "{erlc_compile, \"rm \\\"ebin/json.beam\\\"\"}" - ''; - }); - } - ); - }; -in -rebar3Relx { - pname = "erlang-ls"; - - inherit version; - - src = fetchFromGitHub { - inherit owner repo; - hash = "sha256-MSDBU+blsAdeixaHMMXmeMJ+9Yrzn3HekE8KbIc/Guo="; - rev = version; - }; - - # remove when fixed upstream https://github.com/erlang-ls/erlang_ls/pull/1576 - patches = lib.optionals (lib.versionAtLeast erlang.version "27") [ ./1576.diff ]; - - releaseType = "escript"; - beamDeps = builtins.attrValues deps; - - buildPlugins = [ rebar3-proper ]; - buildPhase = "HOME=. make"; - # based on https://github.com/erlang-ls/erlang_ls/blob/main/.github/workflows/build.yml - # these tests are excessively long and we should probably skip them - checkPhase = '' - HOME=. epmd -daemon - HOME=. rebar3 ct - HOME=. rebar3 proper --constraint_tries 100 - ''; - installFlags = [ "PREFIX=$(out)" ]; - - # tests seem to be a bit flaky on darwin, skip them for now - doCheck = !stdenv.hostPlatform.isDarwin; - - passthru.updateScript = writeScript "update.sh" '' - #!/usr/bin/env nix-shell - #! nix-shell -i bash -p common-updater-scripts coreutils git gnused gnutar gzip "rebar3WithPlugins { globalPlugins = [ beamPackages.rebar3-nix ]; }" - - set -ox errexit - latest=$(list-git-tags | sed -n '/[\d\.]\+/p' | sort -V | tail -1) - if [[ "$latest" != "${version}" ]]; then - nixpkgs="$(git rev-parse --show-toplevel)" - nix_path="$nixpkgs/pkgs/development/beam-modules/erlang-ls" - update-source-version erlang-ls "$latest" --version-key=version --print-changes --file="$nix_path/default.nix" - tmpdir=$(mktemp -d) - cp -R $(nix-build $nixpkgs --no-out-link -A erlang-ls.src)/* "$tmpdir" - DEBUG=1 - (cd "$tmpdir" && HOME=. rebar3 as test nix lock -o "$nix_path/rebar-deps.nix") - nixfmt "$nix_path/rebar-deps.nix" - else - echo "erlang-ls is already up-to-date" - fi - ''; - - meta = with lib; { - homepage = "https://github.com/erlang-ls/erlang_ls"; - description = "Erlang Language Server"; - platforms = platforms.unix; - license = licenses.asl20; - mainProgram = "erlang_ls"; - }; -} diff --git a/pkgs/development/beam-modules/erlang-ls/rebar-deps.nix b/pkgs/development/beam-modules/erlang-ls/rebar-deps.nix deleted file mode 100644 index b468a39edcd7..000000000000 --- a/pkgs/development/beam-modules/erlang-ls/rebar-deps.nix +++ /dev/null @@ -1,242 +0,0 @@ -# Generated by rebar3_nix -let - fetchOnly = { src, ... }: src; -in -{ - builder ? fetchOnly, - fetchHex, - fetchgit, - fetchFromGitHub, - overrides ? (x: y: { }), -}: -let - self = packages // (overrides self packages); - packages = with self; { - getopt = builder { - name = "getopt"; - version = "1.0.1"; - src = fetchHex { - pkg = "getopt"; - version = "1.0.1"; - sha256 = "sha256-U+Grg7nOtlyWctPno1uAkum9ybPugHIUcaFhwQxZlZw="; - }; - beamDeps = [ ]; - }; - zipper = builder { - name = "zipper"; - version = "1.0.1"; - src = fetchHex { - pkg = "zipper"; - version = "1.0.1"; - sha256 = "sha256-ah/T4fDMHR31ZCyaDOIXgDZBGwpclkKFHR2idr1zfC0="; - }; - beamDeps = [ ]; - }; - quickrand = builder { - name = "quickrand"; - version = "2.0.7"; - src = fetchHex { - pkg = "quickrand"; - version = "2.0.7"; - sha256 = "sha256-uKy/iaIkvCF8MHDKi+vG6yNtvn+XZ5k7J0CE6gRNNfA="; - }; - beamDeps = [ ]; - }; - providers = builder { - name = "providers"; - version = "1.8.1"; - src = fetchHex { - pkg = "providers"; - version = "1.8.1"; - sha256 = "sha256-5FdFrenEdqmkaeoIQOQYqxk2DcRPAaIzME4RikRIa6A="; - }; - beamDeps = [ getopt ]; - }; - katana_code = builder { - name = "katana_code"; - version = "2.1.1"; - src = fetchHex { - pkg = "katana_code"; - version = "2.1.1"; - sha256 = "sha256-BoDzNSW5qILm9NMCJRixXEb2SL17Db6GkAmA/hwpFAQ="; - }; - beamDeps = [ ]; - }; - bucs = builder { - name = "bucs"; - version = "1.0.16"; - src = fetchHex { - pkg = "bucs"; - version = "1.0.16"; - sha256 = "sha256-/2pccqUArXrsHuO6FkrjxFDq3uiYsNFR4frKGKyNDWI="; - }; - beamDeps = [ ]; - }; - yamerl = builder { - name = "yamerl"; - version = "git"; - src = fetchFromGitHub { - owner = "erlang-ls"; - repo = "yamerl"; - rev = "9a9f7a2e84554992f2e8e08a8060bfe97776a5b7"; - sha256 = "1gb44v27paxwxm443m5f554wiziqi2kd300hgjjdg6fyvy3mvhss"; - }; - beamDeps = [ ]; - }; - uuid = builder { - name = "uuid"; - version = "2.0.1"; - src = fetchHex { - pkg = "uuid_erl"; - version = "2.0.1"; - sha256 = "sha256-q1fKzNUfFwAR5fREzoZfhLQWBeSDqe/MRowa+uyHVTs="; - }; - beamDeps = [ quickrand ]; - }; - tdiff = builder { - name = "tdiff"; - version = "0.1.2"; - src = fetchHex { - pkg = "tdiff"; - version = "0.1.2"; - sha256 = "sha256-4MLhaPmSUqWIl2jVyPHmUQoYRZLUz6BrIneKGNM9eHU="; - }; - beamDeps = [ ]; - }; - redbug = builder { - name = "redbug"; - version = "2.0.6"; - src = fetchHex { - pkg = "redbug"; - version = "2.0.6"; - sha256 = "sha256-qtlJhnH0q5HqylCZ/oWmFhgVimNuYoaJLE989K8XHQQ="; - }; - beamDeps = [ ]; - }; - rebar3_format = builder { - name = "rebar3_format"; - version = "0.8.2"; - src = fetchHex { - pkg = "rebar3_format"; - version = "0.8.2"; - sha256 = "sha256-yo/ydjjCFpWT0USdrL6IlWNBk+0zNOkGtU/JfwgfUhM="; - }; - beamDeps = [ katana_code ]; - }; - json_polyfill = builder { - name = "json_polyfill"; - version = "0.1.4"; - src = fetchHex { - pkg = "json_polyfill"; - version = "0.1.4"; - sha256 = "sha256-SMOX7iVH+kWe3gGjDsDoVxer7TAQhnpj7qrF8gMnQwM="; - }; - beamDeps = [ ]; - }; - jsx = builder { - name = "jsx"; - version = "2.10.0"; - src = fetchHex { - pkg = "jsx"; - version = "2.10.0"; - sha256 = "sha256-moPjcEgHKYAWlo21Bvn60PAn3jdUbrg4s64QZMOgrWI="; - }; - beamDeps = [ ]; - }; - gradualizer = builder { - name = "gradualizer"; - version = "git"; - src = fetchFromGitHub { - owner = "josefs"; - repo = "gradualizer"; - rev = "3021d29d82741399d131e3be38d2a8db79d146d4"; - sha256 = "052f8x9x93yy00pbkl1745ffnwj3blcm39j12i4k166y1zbnwy00"; - }; - beamDeps = [ ]; - }; - erlfmt = builder { - name = "erlfmt"; - version = "1.5.0"; - src = fetchHex { - pkg = "erlfmt"; - version = "1.5.0"; - sha256 = "sha256-OTOkDPvnkK2U5bZQs2iB3nBFYxkmPBR5tVbpr9vYDHU="; - }; - beamDeps = [ ]; - }; - ephemeral = builder { - name = "ephemeral"; - version = "2.0.4"; - src = fetchHex { - pkg = "ephemeral"; - version = "2.0.4"; - sha256 = "sha256-Syk9gPdfnEV1/0ucjoiaVoAvQLAYv1fnTxlkTv7myFA="; - }; - beamDeps = [ bucs ]; - }; - elvis_core = builder { - name = "elvis_core"; - version = "3.2.5"; - src = fetchHex { - pkg = "elvis_core"; - version = "3.2.5"; - sha256 = "sha256-NNkhjwuAclEZA79sy/WesXZd7Pxz/MaDO6XIlZ2384M="; - }; - beamDeps = [ - katana_code - zipper - ]; - }; - docsh = builder { - name = "docsh"; - version = "0.7.2"; - src = fetchHex { - pkg = "docsh"; - version = "0.7.2"; - sha256 = "sha256-Tn20YbsHVA0rw9NmuFE/AZdxLQSVu4V0TzZ9OBUHYTQ="; - }; - beamDeps = [ providers ]; - }; - proper_contrib = builder { - name = "proper_contrib"; - version = "0.2.0"; - src = fetchHex { - pkg = "proper_contrib"; - version = "0.2.0"; - sha256 = "sha256-jFRRL1zr9JKaG1eqMDfcKk2xe93uOrXUenB14icVCBU="; - }; - beamDeps = [ proper ]; - }; - proper = builder { - name = "proper"; - version = "1.3.0"; - src = fetchHex { - pkg = "proper"; - version = "1.3.0"; - sha256 = "sha256-SqGS/M3dA/2+UP72IL6dTS+SY1tU9V+4OuwYWZRAPLw="; - }; - beamDeps = [ ]; - }; - meck = builder { - name = "meck"; - version = "0.9.0"; - src = fetchHex { - pkg = "meck"; - version = "0.9.0"; - sha256 = "sha256-+BPpDdC4myUWoCAaNV6EsavHi1dRqgy/ZpqdhagQrGM="; - }; - beamDeps = [ ]; - }; - coveralls = builder { - name = "coveralls"; - version = "2.2.0"; - src = fetchHex { - pkg = "coveralls"; - version = "2.2.0"; - sha256 = "sha256-zVTbCqjGS1OSgBicVhns7hOkaiiw8ct3RUTdzBZiBKM="; - }; - beamDeps = [ jsx ]; - }; - }; -in -self diff --git a/pkgs/development/interpreters/php/8.3.nix b/pkgs/development/interpreters/php/8.3.nix index da589dc17fb8..2dcebdc9e65b 100644 --- a/pkgs/development/interpreters/php/8.3.nix +++ b/pkgs/development/interpreters/php/8.3.nix @@ -4,8 +4,8 @@ let base = callPackage ./generic.nix ( _args // { - version = "8.3.25"; - hash = "sha256-BuVHkeERkvCJ5NIMcW8lvdzr3elRtXC1Ve37WYiotxo="; + version = "8.3.26"; + hash = "sha256-chtj1TSfEx9Ql1N7O+a6aAHi2Ob6uh8fLqlbT9YudSU="; } ); in diff --git a/pkgs/development/python-modules/adax-local/default.nix b/pkgs/development/python-modules/adax-local/default.nix index 8db965d1da77..4ad2c20d07f0 100644 --- a/pkgs/development/python-modules/adax-local/default.nix +++ b/pkgs/development/python-modules/adax-local/default.nix @@ -5,24 +5,24 @@ buildPythonPackage, fetchFromGitHub, async-timeout, - pythonOlder, + setuptools, }: buildPythonPackage rec { pname = "adax-local"; - version = "0.1.5"; - format = "setuptools"; - - disabled = pythonOlder "3.8"; + version = "0.2.0"; + pyproject = true; src = fetchFromGitHub { owner = "Danielhiversen"; repo = "pyAdaxLocal"; tag = version; - hash = "sha256-V3jSBdYDo32oTAGNTvHJi+GSwlL3keSDhXpNpMoCkWs="; + hash = "sha256-HdhatjlN4oUzBV1cf/PfgOJbEks4KBdw4vH8Y/z6efQ="; }; - propagatedBuildInputs = [ + build-system = [ setuptools ]; + + dependencies = [ aiohttp bleak async-timeout @@ -36,7 +36,8 @@ buildPythonPackage rec { meta = with lib; { description = "Module for local access to Adax"; homepage = "https://github.com/Danielhiversen/pyAdaxLocal"; - license = with licenses; [ mit ]; + changelog = "https://github.com/Danielhiversen/pyAdaxLocal/releases/tag/${src.tag}"; + license = licenses.mit; maintainers = with maintainers; [ fab ]; }; } diff --git a/pkgs/development/python-modules/aiohomekit/default.nix b/pkgs/development/python-modules/aiohomekit/default.nix index 41821c246834..93c9dd8f7f8d 100644 --- a/pkgs/development/python-modules/aiohomekit/default.nix +++ b/pkgs/development/python-modules/aiohomekit/default.nix @@ -22,7 +22,7 @@ buildPythonPackage rec { pname = "aiohomekit"; - version = "3.2.18"; + version = "3.2.19"; pyproject = true; disabled = pythonOlder "3.10"; @@ -31,7 +31,7 @@ buildPythonPackage rec { owner = "Jc2k"; repo = "aiohomekit"; tag = version; - hash = "sha256-0RCKJqhD/SMMB21ZwrR81jmb6yenZxGPQOQ+TkXb0Uo="; + hash = "sha256-ML7j5OBbQyF+2Q1WHBwJfnRUnG8kf+cog1nMRp6fOSE="; }; build-system = [ poetry-core ]; diff --git a/pkgs/development/python-modules/azure-mgmt-storage/default.nix b/pkgs/development/python-modules/azure-mgmt-storage/default.nix index 33d28d122754..0176d99e4bf2 100644 --- a/pkgs/development/python-modules/azure-mgmt-storage/default.nix +++ b/pkgs/development/python-modules/azure-mgmt-storage/default.nix @@ -11,7 +11,7 @@ buildPythonPackage rec { pname = "azure-mgmt-storage"; - version = "23.0.1"; + version = "23.1.0"; pyproject = true; disabled = pythonOlder "3.8"; @@ -19,7 +19,7 @@ buildPythonPackage rec { src = fetchPypi { pname = "azure_mgmt_storage"; inherit version; - hash = "sha256-w6sqyTUtHAHYW1bWcW3M4eRoD5ILFIoktDabuRuSI7Q="; + hash = "sha256-K92SL5DJL4+QHnMtNGPZDO5mF8f3leDLRyROzQrpiyA="; }; build-system = [ setuptools ]; diff --git a/pkgs/development/python-modules/boto3-stubs/default.nix b/pkgs/development/python-modules/boto3-stubs/default.nix index 9f9f0d50d90c..a8872e3953c2 100644 --- a/pkgs/development/python-modules/boto3-stubs/default.nix +++ b/pkgs/development/python-modules/boto3-stubs/default.nix @@ -359,7 +359,7 @@ buildPythonPackage rec { pname = "boto3-stubs"; - version = "1.40.43"; + version = "1.40.44"; pyproject = true; disabled = pythonOlder "3.7"; @@ -367,7 +367,7 @@ buildPythonPackage rec { src = fetchPypi { pname = "boto3_stubs"; inherit version; - hash = "sha256-AdaNfweoWVM+3ArpQHOjvpOGBQ+ZzTGBzD6BSkEQx9k="; + hash = "sha256-xJAw08ih9xni6ig9fv+DQDdAbvQeytR0kNeArooV/1w="; }; build-system = [ setuptools ]; diff --git a/pkgs/development/python-modules/cma/default.nix b/pkgs/development/python-modules/cma/default.nix index 82b689d06ddd..829d15efad6b 100644 --- a/pkgs/development/python-modules/cma/default.nix +++ b/pkgs/development/python-modules/cma/default.nix @@ -2,19 +2,22 @@ lib, buildPythonPackage, fetchFromGitHub, - numpy, - python, - pythonOlder, + + # build-system setuptools, + + # dependencies + numpy, + + # tests + python, }: buildPythonPackage rec { pname = "cma"; - version = "4.3.0"; + version = "4.4.0"; pyproject = true; - disabled = pythonOlder "3.7"; - src = fetchFromGitHub { owner = "CMA-ES"; repo = "pycma"; @@ -22,22 +25,33 @@ buildPythonPackage rec { hash = "sha256-2uCn5CZma9RLK8zaaPhiQCqnK+2dWgLNr5+Ck2cV6vI="; }; + # setuptools.errors.PackageDiscoveryError: + # Multiple top-level packages discovered in a flat-layout: ['cma', 'notebooks']. + postPatch = '' + rm -rf notebooks + ''; + build-system = [ setuptools ]; dependencies = [ numpy ]; - checkPhase = '' - # At least one doctest fails, thus only limited amount of files is tested - ${python.executable} -m cma.test interfaces.py purecma.py logger.py optimization_tools.py transformations.py - ''; - pythonImportsCheck = [ "cma" ]; - meta = with lib; { + # At least one doctest fails, thus only limited amount of files is tested + checkPhase = '' + ${python.executable} -m cma.test \ + interfaces.py \ + purecma.py \ + logger.py \ + optimization_tools.py \ + transformations.py + ''; + + meta = { description = "Library for Covariance Matrix Adaptation Evolution Strategy for non-linear numerical optimization"; homepage = "https://github.com/CMA-ES/pycma"; - changelog = "https://github.com/CMA-ES/pycma/releases/tag/r${src.tag}"; - license = licenses.bsd3; + changelog = "https://github.com/CMA-ES/pycma/releases/tag/${src.tag}"; + license = lib.licenses.bsd3; maintainers = [ ]; }; } diff --git a/pkgs/development/python-modules/datafusion/default.nix b/pkgs/development/python-modules/datafusion/default.nix index 9695272f7a6a..fb8e804edde4 100644 --- a/pkgs/development/python-modules/datafusion/default.nix +++ b/pkgs/development/python-modules/datafusion/default.nix @@ -22,7 +22,7 @@ buildPythonPackage rec { pname = "datafusion"; - version = "49.0.0"; + version = "50.0.0"; pyproject = true; src = fetchFromGitHub { @@ -32,12 +32,12 @@ buildPythonPackage rec { tag = version; # Fetch arrow-testing and parquet-testing (tests assets) fetchSubmodules = true; - hash = "sha256-U3LRZQMjL8sNa5yQmwfhw9NRGC0299TRODylzZkvFh4="; + hash = "sha256-to1GJQqI4aJOW8pGhWvU44ePrRo0cgeNwEGRJlb9grM="; }; cargoDeps = rustPlatform.fetchCargoVendor { inherit pname src version; - hash = "sha256-lCbqy6kZK+LSLvr+Odxt167ACnDap2enH/J4ILcPtOc="; + hash = "sha256-ZACp7bBLYKmuZVAWEa2YxoCbQqwALv2bWf+zz6jbV9w="; }; nativeBuildInputs = with rustPlatform; [ diff --git a/pkgs/development/python-modules/django-pghistory/default.nix b/pkgs/development/python-modules/django-pghistory/default.nix index daac8859f440..acdbe30965b1 100644 --- a/pkgs/development/python-modules/django-pghistory/default.nix +++ b/pkgs/development/python-modules/django-pghistory/default.nix @@ -9,14 +9,14 @@ buildPythonPackage rec { pname = "django-pghistory"; - version = "3.8.2"; + version = "3.8.3"; pyproject = true; src = fetchFromGitHub { owner = "Opus10"; repo = "django-pghistory"; tag = version; - hash = "sha256-zQqa4rBhjt2+kaCT4PvGXyTJ63JR3YM50GBQkqnWUKE="; + hash = "sha256-Sx2dR5l86D+2t+1DViW1PfI74zyLmgwNm81zVmZ7IH8="; }; build-system = [ diff --git a/pkgs/development/python-modules/fontbakery/default.nix b/pkgs/development/python-modules/fontbakery/default.nix index 38210d8004ae..e00fac68a9a9 100644 --- a/pkgs/development/python-modules/fontbakery/default.nix +++ b/pkgs/development/python-modules/fontbakery/default.nix @@ -47,12 +47,12 @@ buildPythonPackage rec { pname = "fontbakery"; - version = "1.0.1"; + version = "1.1.0"; pyproject = true; src = fetchPypi { inherit pname version; - hash = "sha256-OPOUNKy70sm/kqrxRi61MjfQp74AdqZh6Gt93LdlmU0="; + hash = "sha256-cLQNjrpk8m3Rm1VBC4FNGB7e/E+hjIqcStFSDqfVIk4="; }; env.PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION = "python"; diff --git a/pkgs/development/python-modules/iamdata/default.nix b/pkgs/development/python-modules/iamdata/default.nix index 21c4f8f75bb1..08ed1a38d1c7 100644 --- a/pkgs/development/python-modules/iamdata/default.nix +++ b/pkgs/development/python-modules/iamdata/default.nix @@ -8,14 +8,14 @@ buildPythonPackage rec { pname = "iamdata"; - version = "0.1.202510021"; + version = "0.1.202510031"; pyproject = true; src = fetchFromGitHub { owner = "cloud-copilot"; repo = "iam-data-python"; tag = "v${version}"; - hash = "sha256-irM3NCm+TtNbHIAsc9Qh8RneJYig/SUJ40jsPy3c07Q="; + hash = "sha256-TOTnu8oRXBVgemst9QK9skwsZ5TMR9WzeoQ9288pVDc="; }; build-system = [ hatchling ]; diff --git a/pkgs/development/python-modules/junos-eznc/default.nix b/pkgs/development/python-modules/junos-eznc/default.nix index 76f464366c2d..0e1110e2e5ec 100644 --- a/pkgs/development/python-modules/junos-eznc/default.nix +++ b/pkgs/development/python-modules/junos-eznc/default.nix @@ -24,7 +24,7 @@ buildPythonPackage rec { pname = "junos-eznc"; - version = "2.7.4"; + version = "2.7.5"; pyproject = true; disabled = pythonOlder "3.8"; @@ -33,7 +33,7 @@ buildPythonPackage rec { owner = "Juniper"; repo = "py-junos-eznc"; tag = version; - hash = "sha256-iuCVfzS8k/TZ58v/OPJfSpIMYwwKRj1zyd4FF/KLjjI="; + hash = "sha256-1OOXhhY3fBG00PptUSfIPI906YLgludr9PRMoWBbPnU="; }; build-system = [ setuptools ]; diff --git a/pkgs/development/python-modules/kfactory/default.nix b/pkgs/development/python-modules/kfactory/default.nix index 1d4bde2fd9fc..0e10841be1d9 100644 --- a/pkgs/development/python-modules/kfactory/default.nix +++ b/pkgs/development/python-modules/kfactory/default.nix @@ -33,14 +33,14 @@ buildPythonPackage rec { pname = "kfactory"; - version = "1.14.3"; + version = "1.14.4"; pyproject = true; src = fetchFromGitHub { owner = "gdsfactory"; repo = "kfactory"; tag = "v${version}"; - hash = "sha256-dwJqKl6o2w8fxcNMQAvt5dI1k89yoy/PiIH9eo3JQbA="; + hash = "sha256-el3bGv57mAfxYG9tdLX5N6R76F+9GY9jdZaIUjMqcVU="; }; build-system = [ diff --git a/pkgs/development/python-modules/lerobot/default.nix b/pkgs/development/python-modules/lerobot/default.nix new file mode 100644 index 000000000000..2dbf6c1196ce --- /dev/null +++ b/pkgs/development/python-modules/lerobot/default.nix @@ -0,0 +1,145 @@ +{ + lib, + buildPythonPackage, + fetchFromGitHub, + + # build-system + cmake, + setuptools, + + # dependencies + av, + datasets, + deepdiff, + diffusers, + draccus, + einops, + flask, + gymnasium, + huggingface-hub, + imageio, + jsonlines, + opencv-python-headless, + packaging, + pynput, + pyserial, + rerun-sdk, + termcolor, + torch, + torchvision, + wandb, + + # tests + pytestCheckHook, + writableTmpDirAsHomeHook, +}: + +buildPythonPackage rec { + pname = "lerobot"; + version = "0.3.3"; + pyproject = true; + + src = fetchFromGitHub { + owner = "huggingface"; + repo = "lerobot"; + tag = "v${version}"; + hash = "sha256-JaspLUuSupmk6QD+mUVLuCSczTNjy0w+nsLBcy7tXnE="; + }; + + # ValueError: mutable default for field value is not allowed: use default_factory + postPatch = '' + substituteInPlace tests/processor/test_pipeline.py \ + --replace-fail \ + "from dataclasses import dataclass" \ + "from dataclasses import dataclass, field" \ + --replace-fail \ + "value: PolicyFeature = PolicyFeature(type=FeatureType.STATE, shape=(1,))" \ + "value: PolicyFeature = field(default_factory=lambda: PolicyFeature(type=FeatureType.STATE, shape=(1,)))" + ''; + + build-system = [ + cmake + setuptools + ]; + dontUseCmakeConfigure = true; + + pythonRelaxDeps = [ + "datasets" + "draccus" + "gymnasium" + "rerun-sdk" + "torch" + "torchvision" + ]; + + dependencies = [ + av + datasets + deepdiff + diffusers + draccus + einops + flask + gymnasium + huggingface-hub + imageio + jsonlines + opencv-python-headless + packaging + pynput + pyserial + rerun-sdk + termcolor + torch + torchvision + wandb + ]; + + pythonImportsCheck = [ "lerobot" ]; + + nativeCheckInputs = [ + pytestCheckHook + writableTmpDirAsHomeHook + ]; + + disabledTests = [ + # RuntimeError: OpenCVCamera(/build/source/tests/artifacts/cameras/image_480x270.png) read failed + "test_async_read" + "test_read" + "test_rotation" + + # Require internet access + "test_act_backbone_lr" + "test_backward_compatibility" + "test_dataset_initialization" + "test_factory" + "test_policy_defaults" + "test_save_and_load_pretrained" + + # TypeError: stack(): argument 'tensors' (position 1) must be tuple of Tensors, not Column + "test_check_timestamps_sync_slightly_off" + "test_check_timestamps_sync_synced" + "test_check_timestamps_sync_unsynced" + "test_check_timestamps_sync_unsynced_no_exception" + "test_compute_sampler_weights_drop_n_last_frames" + "test_compute_sampler_weights_nontrivial_ratio" + "test_compute_sampler_weights_nontrivial_ratio_and_drop_last_n" + "test_compute_sampler_weights_trivial" + "test_record_and_replay" + "test_record_and_resume" + "test_same_attributes_defined" + + # AssertionError between two dicts. One has an extra `'_is_initial': False` entry. + "test_cosine_decay_with_warmup_scheduler" + "test_diffuser_scheduler" + "test_vqbet_scheduler" + ]; + + meta = { + description = "Making AI for Robotics more accessible with end-to-end learning"; + homepage = "https://github.com/huggingface/lerobot"; + changelog = "https://github.com/huggingface/lerobot/releases/tag/v${version}"; + license = lib.licenses.asl20; + maintainers = with lib.maintainers; [ GaetanLepage ]; + }; +} diff --git a/pkgs/development/python-modules/meross-iot/default.nix b/pkgs/development/python-modules/meross-iot/default.nix index 823a87c580c8..73f0b3220105 100644 --- a/pkgs/development/python-modules/meross-iot/default.nix +++ b/pkgs/development/python-modules/meross-iot/default.nix @@ -11,14 +11,14 @@ buildPythonPackage rec { pname = "meross-iot"; - version = "0.4.9.2"; + version = "0.4.10.3"; pyproject = true; src = fetchFromGitHub { owner = "albertogeniola"; repo = "MerossIot"; tag = version; - hash = "sha256-l0mw/V965JqX/pgcs9ek9dMLzUCGnam0E5Cu8W/HfEU="; + hash = "sha256-VxwOigIyLTeP1P9uyiavsu14zTjuLCZuka+2cLqJDUw="; }; build-system = [ setuptools ]; diff --git a/pkgs/development/python-modules/msticpy/default.nix b/pkgs/development/python-modules/msticpy/default.nix index d6a9c59f4c66..2284c91ac90a 100644 --- a/pkgs/development/python-modules/msticpy/default.nix +++ b/pkgs/development/python-modules/msticpy/default.nix @@ -50,7 +50,7 @@ buildPythonPackage rec { pname = "msticpy"; - version = "2.17.0"; + version = "2.17.1"; pyproject = true; disabled = pythonOlder "3.8"; @@ -59,7 +59,7 @@ buildPythonPackage rec { owner = "microsoft"; repo = "msticpy"; tag = "v${version}"; - hash = "sha256-f2aCVD3EPRFjbpN+HcM3be46fPbVXkIFUFw/xoRzGfg="; + hash = "sha256-2p06WKqs0lApEjWhSrq2BL95OxbyBg0Jn2ziwxsNEEE="; }; pythonRelaxDeps = [ diff --git a/pkgs/development/python-modules/mypy-boto3/default.nix b/pkgs/development/python-modules/mypy-boto3/default.nix index ac1a14cc12e3..dfca70d12f95 100644 --- a/pkgs/development/python-modules/mypy-boto3/default.nix +++ b/pkgs/development/python-modules/mypy-boto3/default.nix @@ -226,8 +226,8 @@ rec { "sha256-fFnHwgB8r239cpVnWSfeiGO1MNOxkXn9MNMUA5ohm04="; mypy-boto3-cloudformation = - buildMypyBoto3Package "cloudformation" "1.40.24" - "sha256-4rAK/GqrExGyWMkxSO7qWz7q2UxyA+KP+f046fzihIg="; + buildMypyBoto3Package "cloudformation" "1.40.44" + "sha256-PYL1UEOCyGrRlaG4CiqC9zWHw34bY2hk67hd1DvXmls="; mypy-boto3-cloudfront = buildMypyBoto3Package "cloudfront" "1.40.23" @@ -350,8 +350,8 @@ rec { "sha256-nAOKVy+aH2gw8NZ8cNSYqQ0kFWV4Gb4oU6y1vHz3fpI="; mypy-boto3-connectcases = - buildMypyBoto3Package "connectcases" "1.40.42" - "sha256-DJcEbPyJZVRVF1FnTSQpuUZlBTEYcOXJ42yN1o4yUwU="; + buildMypyBoto3Package "connectcases" "1.40.44" + "sha256-T4E5rin+Y0DJWARRqzA7agLwcF11v4CGy/Fe/x/F7vY="; mypy-boto3-connectparticipant = buildMypyBoto3Package "connectparticipant" "1.40.18" @@ -434,8 +434,8 @@ rec { "sha256-gKzshS6Q6O/lTAsrkuXOvKkGz+ECRlmSeb5NxNCBim8="; mypy-boto3-dynamodb = - buildMypyBoto3Package "dynamodb" "1.40.20" - "sha256-L0JDFdKZzPCztOOysjAPkPCc0LfGn8Rz0M3Atr5sMNY="; + buildMypyBoto3Package "dynamodb" "1.40.44" + "sha256-WPo6Y4scrvVkS2D1iU4RgqKVH+swo9xt7bNOGwyd7Zk="; mypy-boto3-dynamodbstreams = buildMypyBoto3Package "dynamodbstreams" "1.40.40" @@ -593,8 +593,8 @@ rec { "sha256-/LlMFYC7cJWb9C5JIt0dTEPtl2sPsalSq7mYaFSf3c4="; mypy-boto3-guardduty = - buildMypyBoto3Package "guardduty" "1.40.29" - "sha256-G5d3++tcszwfPxeBmPA+1akV4lIVC85MT/5mXBtJekE="; + buildMypyBoto3Package "guardduty" "1.40.44" + "sha256-vOTVkra2RG5DPgcegpDij+6tjWkY01b6zXoSIze8AZ8="; mypy-boto3-health = buildMypyBoto3Package "health" "1.40.0" @@ -1345,8 +1345,8 @@ rec { "sha256-qkE3rF32WkR56WB5pu3dKJLCLY5e1rvMDPYAruyj9O8="; mypy-boto3-synthetics = - buildMypyBoto3Package "synthetics" "1.40.16" - "sha256-E7spYXuGbWE7BrOPNP/f8kUakXjTLGf1JAZuhd6m0Yg="; + buildMypyBoto3Package "synthetics" "1.40.44" + "sha256-777DKmK4DKxIWhXp+Mu7TQ8wNdfnzz4+0fJyPVGx0R0="; mypy-boto3-textract = buildMypyBoto3Package "textract" "1.40.0" diff --git a/pkgs/development/python-modules/onnxslim/default.nix b/pkgs/development/python-modules/onnxslim/default.nix index da1756d7a772..a231ec0254e7 100644 --- a/pkgs/development/python-modules/onnxslim/default.nix +++ b/pkgs/development/python-modules/onnxslim/default.nix @@ -15,14 +15,14 @@ buildPythonPackage rec { pname = "onnxslim"; - version = "0.1.69"; + version = "0.1.70"; pyproject = true; src = fetchFromGitHub { owner = "inisis"; repo = "OnnxSlim"; tag = "v${version}"; - hash = "sha256-UwuZDAPTwIVJTseu8iIO2Q8OOaFcwiwLS/auWOpIpnQ="; + hash = "sha256-xShmJR0GWuGmuM0LZ0nBLDoC0m7c0iSWolUGUscVotA="; }; build-system = [ diff --git a/pkgs/development/python-modules/ovoenergy/default.nix b/pkgs/development/python-modules/ovoenergy/default.nix index c7ae4e2cb65d..13ade4e3f38d 100644 --- a/pkgs/development/python-modules/ovoenergy/default.nix +++ b/pkgs/development/python-modules/ovoenergy/default.nix @@ -5,30 +5,23 @@ click, fetchFromGitHub, incremental, - pythonOlder, setuptools, + pyjwt, typer, }: buildPythonPackage rec { pname = "ovoenergy"; - version = "2.0.1"; + version = "3.0.2"; pyproject = true; - disabled = pythonOlder "3.11"; - src = fetchFromGitHub { owner = "timmo001"; repo = "ovoenergy"; tag = version; - hash = "sha256-7SXnOyvBsBPQ+4tC6pcEXGtcLdqKjzlB2xDZmw/uWcM="; + hash = "sha256-oWJxpiC83C/ghs/Ik8+DrPWtP/j5jWEZ3+9Nqg4ARKU="; }; - postPatch = '' - substituteInPlace requirements_setup.txt \ - --replace-fail "==" ">=" - ''; - build-system = [ incremental setuptools @@ -39,6 +32,7 @@ buildPythonPackage rec { dependencies = [ aiohttp click + pyjwt typer ]; diff --git a/pkgs/development/python-modules/pymoo/default.nix b/pkgs/development/python-modules/pymoo/default.nix index 350e7b5144d3..2af107eb9b5e 100644 --- a/pkgs/development/python-modules/pymoo/default.nix +++ b/pkgs/development/python-modules/pymoo/default.nix @@ -52,11 +52,6 @@ buildPythonPackage rec { "ProgressBar() if progress else None" \ "print('Missing alive_progress needed for progress=True!') if progress else None" - substituteInPlace pymoo/algorithms/soo/nonconvex/es.py \ - --replace-fail "np.math.ceil" "np.ceil" - substituteInPlace pymoo/util/mnn.py \ - --replace-fail "np.product" "np.prod" - substituteInPlace pymoo/config.py \ --replace-fail \ "https://raw.githubusercontent.com/anyoptimization/pymoo-data/main/" \ @@ -81,9 +76,9 @@ buildPythonPackage rec { scipy ]; + # Some tests require a grad backend to be configured, this is a hacky way to do so. + # The choice must be either "jax.numpy" or "autograd.numpy" preCheck = '' - # Some tests require a grad backend to be configured, this is a hacky way to do so. - # The choice must be either "jax.numpy" or "autograd.numpy" echo 'from pymoo.gradient import activate; activate("autograd.numpy")' >> tests/conftest.py ''; nativeCheckInputs = [ @@ -103,6 +98,11 @@ buildPythonPackage rec { # sensitive to float precision "test_cd_and_pcd" + # AssertionError: + # Not equal to tolerance rtol=0, atol=0.0001 + # Mismatched elements: 1200 / 1200 (100%) + "test_pf" + # TypeError: 'NoneType' object is not subscriptable "test_dascomp" "test_mw" diff --git a/pkgs/development/python-modules/pyngrok/default.nix b/pkgs/development/python-modules/pyngrok/default.nix index ca3239256c06..9006101f4278 100644 --- a/pkgs/development/python-modules/pyngrok/default.nix +++ b/pkgs/development/python-modules/pyngrok/default.nix @@ -9,14 +9,14 @@ buildPythonPackage rec { pname = "pyngrok"; - version = "7.3.0"; + version = "7.4.0"; pyproject = true; disabled = pythonOlder "3.9"; src = fetchPypi { inherit pname version; - hash = "sha256-8iQOSbneybJ+ugDxREzTzOesRdG8xJOpt27mPC2piCw="; + hash = "sha256-H3hv7Y0Va5m//XEwlqfsjIEYH5Scj1ySD2gg6S1rmHY="; }; build-system = [ diff --git a/pkgs/development/python-modules/reolink-aio/default.nix b/pkgs/development/python-modules/reolink-aio/default.nix index 25875dcb3ae9..10603b5b59bb 100644 --- a/pkgs/development/python-modules/reolink-aio/default.nix +++ b/pkgs/development/python-modules/reolink-aio/default.nix @@ -13,7 +13,7 @@ buildPythonPackage rec { pname = "reolink-aio"; - version = "0.16.0"; + version = "0.16.1"; pyproject = true; disabled = pythonOlder "3.11"; @@ -22,7 +22,7 @@ buildPythonPackage rec { owner = "starkillerOG"; repo = "reolink_aio"; tag = version; - hash = "sha256-pxU3QuBH/xV77YLp0JqfYTJPVIbLvRKuaWnH5YU6vsE="; + hash = "sha256-CLn/aojExLQa3yMqbzLWYAAc4pLKHZ8Nrm4vbjn/ZTM="; }; build-system = [ setuptools ]; diff --git a/pkgs/development/python-modules/std-uritemplate/default.nix b/pkgs/development/python-modules/std-uritemplate/default.nix index bba85820bd68..552dd798a71f 100644 --- a/pkgs/development/python-modules/std-uritemplate/default.nix +++ b/pkgs/development/python-modules/std-uritemplate/default.nix @@ -8,7 +8,7 @@ buildPythonPackage rec { pname = "std-uritemplate"; - version = "2.0.5"; + version = "2.0.6"; pyproject = true; disabled = pythonOlder "3.8"; @@ -16,7 +16,7 @@ buildPythonPackage rec { src = fetchPypi { pname = "std_uritemplate"; inherit version; - hash = "sha256-dwOohszlnRVcIbWs8a2NSNufMyLemPp4OoOW+/NcvAY="; + hash = "sha256-czU9og88fXOk57wOwKzb1ReHl4BIYyKAoaM3MZFvuUc="; }; build-system = [ poetry-core ]; diff --git a/pkgs/development/python-modules/tagoio-sdk/default.nix b/pkgs/development/python-modules/tagoio-sdk/default.nix index b7f8944e682e..3e462be12678 100644 --- a/pkgs/development/python-modules/tagoio-sdk/default.nix +++ b/pkgs/development/python-modules/tagoio-sdk/default.nix @@ -15,14 +15,14 @@ buildPythonPackage rec { pname = "tagoio-sdk"; - version = "5.0.3"; + version = "5.0.4"; pyproject = true; src = fetchFromGitHub { owner = "tago-io"; repo = "sdk-python"; tag = "v${version}"; - hash = "sha256-PNPG1FUniwZhOKjynp4ba6kjGJmB/OW0F5b2ZOYaYwY="; + hash = "sha256-a+cwDPYLfDgMiWf7jpFszwdueFbnfNgwZLWQrffjBqU="; }; pythonRelaxDeps = [ "requests" ]; diff --git a/pkgs/development/python-modules/transformers/default.nix b/pkgs/development/python-modules/transformers/default.nix index d0b12c8e8cd3..5bcecf117e90 100644 --- a/pkgs/development/python-modules/transformers/default.nix +++ b/pkgs/development/python-modules/transformers/default.nix @@ -59,14 +59,14 @@ buildPythonPackage rec { pname = "transformers"; - version = "4.56.2"; + version = "4.57.0"; pyproject = true; src = fetchFromGitHub { owner = "huggingface"; repo = "transformers"; tag = "v${version}"; - hash = "sha256-epq0a+QjZvXdAuwC/KjoCuAyJLewCaZq4whLSMkAkDI="; + hash = "sha256-S89WMCwo0LRMT7EnRKPZwNqZlpFNilr7nqhhLc+7SgQ="; }; build-system = [ setuptools ]; diff --git a/pkgs/development/python-modules/xdxf2html/default.nix b/pkgs/development/python-modules/xdxf2html/default.nix index 4c31e36ff128..f61edcbc6966 100644 --- a/pkgs/development/python-modules/xdxf2html/default.nix +++ b/pkgs/development/python-modules/xdxf2html/default.nix @@ -8,12 +8,12 @@ buildPythonPackage rec { pname = "xdxf2html"; - version = "0.1.0"; + version = "0.2.0"; pyproject = true; src = fetchPypi { inherit pname version; - hash = "sha256-u2UaEALzD583+hbgwTItQOdGQ6GIhdVy79C2gfJwzlI="; + hash = "sha256-ux622mch+sc6LzaYxbt35JGRL5mrnn/Tk7nrO5Z03xU="; }; build-system = [ setuptools ]; diff --git a/pkgs/os-specific/linux/kernel/linux-libre.nix b/pkgs/os-specific/linux/kernel/linux-libre.nix deleted file mode 100644 index e5e2b8aee674..000000000000 --- a/pkgs/os-specific/linux/kernel/linux-libre.nix +++ /dev/null @@ -1,65 +0,0 @@ -{ - stdenv, - lib, - fetchsvn, - linux, - scripts ? fetchsvn { - url = "https://www.fsfla.org/svn/fsfla/software/linux-libre/releases/branches/"; - rev = "19872"; - hash = "sha256-zbs5iWCaDtwovJLHnBlHfDBZ2DbggToRj3YZ5Nbx/RM="; - }, - ... -}@args: - -let - majorMinor = lib.versions.majorMinor linux.modDirVersion; - - major = lib.versions.major linux.modDirVersion; - minor = lib.versions.minor linux.modDirVersion; - patch = lib.versions.patch linux.modDirVersion; - - # See http://linux-libre.fsfla.org/pub/linux-libre/releases - versionPrefix = if linux.kernelOlder "5.14" then "gnu1" else "gnu"; -in -linux.override { - argsOverride = { - modDirVersion = "${linux.modDirVersion}-${versionPrefix}"; - isLibre = true; - pname = "linux-libre"; - - src = stdenv.mkDerivation { - name = "${linux.name}-libre-src"; - src = linux.src; - - buildPhase = '' - runHook preBuild - - # --force flag to skip empty files after deblobbing - ${scripts}/${majorMinor}/deblob-${majorMinor} --force ${major} ${minor} ${patch} - - runHook postBuild - ''; - - checkPhase = '' - runHook preCheck - - ${scripts}/deblob-check - - runHook postCheck - ''; - - installPhase = '' - runHook preInstall - - cp -r . "$out" - - runHook postInstall - ''; - }; - - extraPassthru.updateScript = ./update-libre.sh; - - maintainers = with lib.maintainers; [ qyliss ]; - }; -} -// (args.argsOverride or { }) diff --git a/pkgs/os-specific/linux/kernel/update-libre.sh b/pkgs/os-specific/linux/kernel/update-libre.sh deleted file mode 100755 index c1b98ee0d7b6..000000000000 --- a/pkgs/os-specific/linux/kernel/update-libre.sh +++ /dev/null @@ -1,33 +0,0 @@ -#! /usr/bin/env nix-shell -#! nix-shell -i bash -p nix-prefetch-svn git curl -set -euo pipefail - -nixpkgs="$(git rev-parse --show-toplevel)" -path="$nixpkgs/pkgs/os-specific/linux/kernel/linux-libre.nix" - -old_rev="$(grep -o 'rev = ".*"' "$path" | awk -F'"' '{print $2}')" - -svn_url=https://www.fsfla.org/svn/fsfla/software/linux-libre/releases/branches/ -rev="$(curl -s "$svn_url" | grep -Em 1 -o 'Revision [0-9]+' | awk '{print $2}')" - -if [ "$old_rev" = "$rev" ]; then - echo "No updates for linux-libre" - exit 0 -fi - -old_hash="$(grep -o 'hash = ".*"' "$path" | awk -F'"' '{print $2}')" -sha256="$(QUIET=1 nix-prefetch-svn "$svn_url" "$rev" | tail -1)" -new_hash="$(nix --extra-experimental-features nix-command hash convert --to sri --hash-algo sha256 "$sha256")" - -if [ "$old_hash" = "$new_hash" ]; then - echo "No updates for linux-libre" - exit 0 -fi - -sed -i -e "s,rev = \".*\",rev = \"$rev\",; s,hash = \".*\",hash = \"$new_hash\"," "$path" - -if [ -n "${COMMIT-}" ]; then - git commit -qm "linux_latest-libre: $old_rev -> $rev" "$path" \ - $nixpkgs/pkgs/os-specific/linux/kernel/linux-libre.nix - echo "Updated linux_latest-libre $old_rev -> $rev" -fi diff --git a/pkgs/os-specific/linux/kernel/update.sh b/pkgs/os-specific/linux/kernel/update.sh index 37e1cc1a5cd4..f803e8cb6d20 100755 --- a/pkgs/os-specific/linux/kernel/update.sh +++ b/pkgs/os-specific/linux/kernel/update.sh @@ -7,8 +7,5 @@ COMMIT=1 ./update-mainline.py || echo "update-mainline failed with exit code $?" echo "Update linux-rt" COMMIT=1 ./update-rt.sh || echo "update-rt failed with exit code $?" -echo "Update linux-libre" -COMMIT=1 ./update-libre.sh || echo "update-libre failed with exit code $?" - echo "Update linux-hardened" COMMIT=1 ./hardened/update.py || echo "update-hardened failed with exit code $?" diff --git a/pkgs/os-specific/linux/mcelog/default.nix b/pkgs/os-specific/linux/mcelog/default.nix index 67876c2ce885..3856ce1a95cd 100644 --- a/pkgs/os-specific/linux/mcelog/default.nix +++ b/pkgs/os-specific/linux/mcelog/default.nix @@ -7,13 +7,13 @@ stdenv.mkDerivation (finalAttrs: { pname = "mcelog"; - version = "206"; + version = "207"; src = fetchFromGitHub { owner = "andikleen"; repo = "mcelog"; tag = "v${finalAttrs.version}"; - hash = "sha256-hBdi/rokSJMI6GQZd7apT5Jd2/WRMNgBMbDx8tLfeKc="; + hash = "sha256-ZHhY7pqDuez3QtbhjDr2D/isw+gsoVdfB5WRRchdh6E="; }; postPatch = '' diff --git a/pkgs/os-specific/linux/nvidia-x11/default.nix b/pkgs/os-specific/linux/nvidia-x11/default.nix index e10e803b0159..3b271044f183 100644 --- a/pkgs/os-specific/linux/nvidia-x11/default.nix +++ b/pkgs/os-specific/linux/nvidia-x11/default.nix @@ -101,16 +101,14 @@ rec { # Vulkan developer beta driver # See here for more information: https://developer.nvidia.com/vulkan-driver vulkan_beta = generic rec { - version = "570.123.19"; - persistencedVersion = "570.169"; - settingsVersion = "570.169"; - sha256_64bit = "sha256-K1ElpoTBjlLUG7slBrAhKqnEjUFwupiF7TS/8ogCf7c="; - openSha256 = "sha256-uGH2lnnADf5AGl5ShcbCOULsCIWtJlbxgHiz7I2efVE="; - settingsSha256 = "sha256-0E3UnpMukGMWcX8td6dqmpakaVbj4OhhKXgmqz77XZc="; - persistencedSha256 = "sha256-dttFu+TmbFI+mt1MbbmJcUnc1KIJ20eHZDR7YzfWmgE="; + version = "580.94.02"; + persistencedVersion = "580.95.05"; + settingsVersion = "580.95.05"; + sha256_64bit = "sha256-fhN062tzZq7OwkeRr1lRjhwkX6CH7fJ+oAKXdRTapGE="; + openSha256 = "sha256-MbxIJNBGYMesnero5VauMt5cKiNLw3cM9GxD4PnXM/o="; + settingsSha256 = "sha256-F2wmUEaRrpR1Vz0TQSwVK4Fv13f3J9NJLtBe4UP2f14="; + persistencedSha256 = "sha256-QCwxXQfG/Pa7jSTBB0xD3lsIofcerAWWAHKvWjWGQtg="; url = "https://developer.nvidia.com/downloads/vulkan-beta-${lib.concatStrings (lib.splitVersion version)}-linux"; - - broken = kernel.kernelAtLeast "6.15"; }; # data center driver compatible with current default cudaPackages diff --git a/pkgs/servers/home-assistant/custom-lovelace-modules/mini-media-player/package.nix b/pkgs/servers/home-assistant/custom-lovelace-modules/mini-media-player/package.nix index ebfca7e42437..1779b31937af 100644 --- a/pkgs/servers/home-assistant/custom-lovelace-modules/mini-media-player/package.nix +++ b/pkgs/servers/home-assistant/custom-lovelace-modules/mini-media-player/package.nix @@ -6,16 +6,16 @@ buildNpmPackage rec { pname = "mini-media-player"; - version = "1.16.9"; + version = "1.16.10"; src = fetchFromGitHub { owner = "kalkih"; repo = "mini-media-player"; rev = "v${version}"; - hash = "sha256-tEG8xmqsPDssXmsCobHJoNK3qdRvBRe6FcTfm16r6+g="; + hash = "sha256-nUZL+zYZoWjhs0Xc/3EeuwewryEl4/g3Dv70Q/85bQc="; }; - npmDepsHash = "sha256-pN6Hq0ECnmSZgKPoSfdAQsqNykUakLqRCTyLGVK57KQ="; + npmDepsHash = "sha256-GkkrPeBADjabLiCPvehR6p4Z9LRNgSPInaESd2rLC6U="; installPhase = '' runHook preInstall diff --git a/pkgs/top-level/aliases.nix b/pkgs/top-level/aliases.nix index 6742de3491c8..0b2fc16e2988 100644 --- a/pkgs/top-level/aliases.nix +++ b/pkgs/top-level/aliases.nix @@ -529,6 +529,7 @@ mapAliases { bitcoind-unlimited = throw "bitcoind-unlimited has been removed as it was broken and unmaintained"; # Added 2024-07-15 bird = throw "The bird alias was ambiguous and has been removed for the time being. Please explicitly choose bird2 or bird3."; # Added 2025-01-11 bisq-desktop = throw "bisq-desktop has been removed because OpenJFX 11 was removed"; # Added 2024-11-17 + bitmeter = throw "bitmeter has been removed because it relies on gtk2 and upstream is abandoned since 2006"; # Aded 2025-10-03 bitwarden = bitwarden-desktop; # Added 2024-02-25 blender-with-packages = args: @@ -872,6 +873,7 @@ mapAliases { erlangR26_javac = throw "erlangR26_javac has been removed in favor of erlang_26_javac"; # added 2024-05-24 erlangR26_odbc_javac = throw "erlangR26_odbc_javac has been removed in favor of erlang_26_odbc_javac"; # added 2024-05-24 + erlang-ls = throw "'erlang-ls' has been removed as it has been archived upstream. Consider using 'erlang-language-platform' instead"; # Added 2025-10-02 erlang_language_platform = throw "erlang_language_platform has been renamed erlang-language-platform"; # added 2025-04-04 est-sfs = throw "'est-sfs' has been removed as it was unmaintained in Nixpkgs"; # Added 2025-05-18 ethabi = throw "ethabi has been removed due to lack of maintainence upstream and no updates in Nixpkgs"; # Added 2024-07-16 @@ -1500,6 +1502,11 @@ mapAliases { linuxPackages_testing_bcachefs = throw "'linuxPackages_testing_bcachefs' has been removed, please use 'linuxPackages_latest', any kernel version at least 6.7, or any other linux kernel with bcachefs support"; # Converted to throw 2024-01-09 linux_testing_bcachefs = throw "'linux_testing_bcachefs' has been removed, please use 'linux_latest', any kernel version at least 6.7, or any other linux kernel with bcachefs support"; # Converted to throw 2024-01-09 + linuxPackages-libre = linuxKernel.packages.linux_libre; + linux-libre = linuxPackages-libre.kernel; + linuxPackages_latest-libre = linuxKernel.packages.linux_latest_libre; + linux_latest-libre = linuxPackages_latest-libre.kernel; + linuxstopmotion = stopmotion; # Added 2024-11-01 lixVersions = lixPackageSets.renamedDeprecatedLixVersions; # Added 2025-03-20, warning in ../tools/package-management/lix/default.nix @@ -2627,6 +2634,7 @@ mapAliases { }; vaapiIntel = intel-vaapi-driver; # Added 2023-05-31 vaapiVdpau = libva-vdpau-driver; # Added 2024-06-05 + valum = throw "'valum' has been removed because it has been marked as broken since at least November 2024."; # Added 2025-10-01 vaultwarden-vault = vaultwarden.webvault; # Added 2022-12-13 varnish74 = throw "varnish 7.4 is EOL. Either use the LTS or upgrade."; # Added 2024-10-31 varnish74Packages = throw "varnish 7.4 is EOL. Either use the LTS or upgrade."; # Added 2024-10-31 diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index e51a0acf3e29..a6a57f555744 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -4533,9 +4533,6 @@ with pkgs; inherit (llvmPackages) lld stdenv; }; - colmap = libsForQt5.callPackage ../applications/science/misc/colmap { - inherit (config) cudaSupport; - }; colmapWithCuda = colmap.override { cudaSupport = true; }; opensplatWithCuda = opensplat.override { cudaSupport = true; }; @@ -5835,7 +5832,6 @@ with pkgs; ; inherit (beam.packages.erlang) - erlang-ls ex_doc erlfmt elvis-erlang @@ -8666,10 +8662,6 @@ with pkgs; nodejs = nodejs_22; }; - qradiolink = callPackage ../applications/radio/qradiolink { - protobuf = protobuf_21; - }; - qadwaitadecorations-qt6 = callPackage ../by-name/qa/qadwaitadecorations/package.nix { useQt6 = true; }; @@ -10282,12 +10274,6 @@ with pkgs; linux-rt = linuxPackages-rt.kernel; linux-rt_latest = linuxPackages-rt_latest.kernel; - # GNU Linux-libre kernels - linuxPackages-libre = linuxKernel.packages.linux_libre; - linux-libre = linuxPackages-libre.kernel; - linuxPackages_latest-libre = linuxKernel.packages.linux_latest_libre; - linux_latest-libre = linuxPackages_latest-libre.kernel; - # zen-kernel linuxPackages_zen = linuxKernel.packages.linux_zen; linux_zen = linuxPackages_zen.kernel; diff --git a/pkgs/top-level/linux-kernels.nix b/pkgs/top-level/linux-kernels.nix index 9e76135f3b81..e99677265b8c 100644 --- a/pkgs/top-level/linux-kernels.nix +++ b/pkgs/top-level/linux-kernels.nix @@ -16,18 +16,11 @@ # When adding a kernel: # - Update packageAliases.linux_latest to the latest version -# - Update the rev in ../os-specific/linux/kernel/linux-libre.nix to the latest one. # - Update linux_latest_hardened when the patches become available with linuxKernel; let - deblobKernel = - kernel: - callPackage ../os-specific/linux/kernel/linux-libre.nix { - linux = kernel; - }; - markBroken = drv: drv.overrideAttrs ( @@ -290,15 +283,14 @@ in ]; }; - linux_libre = deblobKernel packageAliases.linux_default.kernel; - - linux_latest_libre = deblobKernel packageAliases.linux_latest.kernel; - linux_6_12_hardened = hardenedKernelFor kernels.linux_6_12 { }; linux_hardened = hardenedKernelFor packageAliases.linux_default.kernel { }; } // lib.optionalAttrs config.allowAliases { + linux_libre = throw "linux_libre has been removed due to lack of maintenance"; + linux_latest_libre = throw "linux_latest_libre has been removed due to lack of maintenance"; + linux_4_19 = throw "linux 4.19 was removed because it will reach its end of life within 24.11"; linux_6_9 = throw "linux 6.9 was removed because it has reached its end of life upstream"; linux_6_10 = throw "linux 6.10 was removed because it has reached its end of life upstream"; @@ -791,12 +783,10 @@ in linux_xanmod = recurseIntoAttrs (packagesFor kernels.linux_xanmod); linux_xanmod_stable = recurseIntoAttrs (packagesFor kernels.linux_xanmod_stable); linux_xanmod_latest = recurseIntoAttrs (packagesFor kernels.linux_xanmod_latest); - - linux_libre = recurseIntoAttrs (packagesFor kernels.linux_libre); - - linux_latest_libre = recurseIntoAttrs (packagesFor kernels.linux_latest_libre); } // lib.optionalAttrs config.allowAliases { + linux_libre = throw "linux_libre has been removed due to lack of maintenance"; + linux_latest_libre = throw "linux_latest_libre has been removed due to lack of maintenance"; linux_5_10_hardened = throw "linux_hardened on nixpkgs only contains latest stable and latest LTS"; linux_5_15_hardened = throw "linux_hardened on nixpkgs only contains latest stable and latest LTS"; diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix index 049e3ac66f0d..04bcfe863e82 100644 --- a/pkgs/top-level/python-packages.nix +++ b/pkgs/top-level/python-packages.nix @@ -8135,6 +8135,8 @@ self: super: with self; { lektricowifi = callPackage ../development/python-modules/lektricowifi { }; + lerobot = callPackage ../development/python-modules/lerobot { }; + letpot = callPackage ../development/python-modules/letpot { }; leveldb = callPackage ../development/python-modules/leveldb { };