aboutsummaryrefslogtreecommitdiff
path: root/source/src/wanda/wallpaper.cpp
blob: 7d4c7d549db1adb62ddc3c37048fbfc93edfbfe1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <wanda/logging.hpp>
#include <wanda/magic.hpp>
#include <wanda/optional.hpp>
#include <wanda/setting.hpp>
#include <wanda/wallpaper.hpp>

#include <boost/gil.hpp>
#include <boost/gil/extension/io/jpeg.hpp>
#include <boost/gil/extension/io/png.hpp>
#include <boost/gil/extension/numeric/resample.hpp>
#include <boost/gil/extension/numeric/sampler.hpp>

#include <fmt/format.h>

#include <algorithm>
#include <cmath>
#include <memory>

namespace wanda
{
  namespace
  {
    auto magic_instance = magic{};

    auto load_image(std::filesystem::path wallpaper)
    {
      auto image = boost::gil::rgb8_image_t{};

      switch (magic_instance.type(wallpaper))
      {
        case magic::mime_type::image_jpeg:
          boost::gil::read_and_convert_image(wallpaper.native(), image, boost::gil::jpeg_tag{});
          break;
        case magic::mime_type::image_png:
          boost::gil::read_and_convert_image(wallpaper.native(), image, boost::gil::png_tag{});
          break;
      }

      return image;

      // // auto source_view = ;

      // return fmt::format("#{:02X}{:02X}{:02X}",
      //                    static_cast<uint8_t>(std::sqrt((at_c<0>(pixel64) / image.size()))),
      //                    static_cast<uint8_t>(std::sqrt((at_c<1>(pixel64) / image.size()))),
      //                    static_cast<uint8_t>(std::sqrt((at_c<2>(pixel64) / image.size()))));
    }

    auto average_colors(boost::gil::rgb8_image_t image)
    {
      auto accumulator = boost::gil::rgb64f_pixel_t{};
      auto view = const_view(image);

      std::ranges::for_each(view, [&](auto const & source_pixel) {
        at_c<0>(accumulator) += std::pow(boost::gil::at_c<0>(source_pixel), 2);
        at_c<1>(accumulator) += std::pow(boost::gil::at_c<1>(source_pixel), 2);
        at_c<2>(accumulator) += std::pow(boost::gil::at_c<2>(source_pixel), 2);
      });

      at_c<0>(accumulator) = std::sqrt(at_c<0>(accumulator) / view.size());
      at_c<1>(accumulator) = std::sqrt(at_c<1>(accumulator) / view.size());
      at_c<2>(accumulator) = std::sqrt(at_c<2>(accumulator) / view.size());

      return accumulator;
    }

    //
  }  // namespace

  void set_wallpaper(std::filesystem::path wallpaper)
  {
    using namespace wanda::literals;
    using namespace wanda::std_ext;
    using namespace std::string_literals;

    auto image = load_image(wallpaper);
    auto color = average_colors(std::move(image));
    auto hexstring = fmt::format("#{:02X}{:02X}{:02X}",
                                 static_cast<std::uint8_t>(at_c<0>(color)),
                                 static_cast<std::uint8_t>(at_c<1>(color)),
                                 static_cast<std::uint8_t>(at_c<2>(color)));

    with("org.gnome.desktop.background"_setting, [&](auto & setting) {
      with(setting["primary-color"_key], [&](auto & value) {
        value = hexstring;
      });
      with(setting["picture-uri"_key], [&](auto & value) {
        value = "file://" + wallpaper.native();
      }) ||
          [&] { get_logger()->error("invalid settings key"); };
    }) ||
        [&] { get_logger()->error("invalid setting"); };
  }

}  // namespace wanda