Commit 65408c09 for libheif

commit 65408c09ddd0bc48587f791231ead65c959cc278
Author: Dirk Farin <dirk.farin@gmail.com>
Date:   Fri Feb 27 10:36:09 2026 +0100

    heif-gen-bayer: allow the input of any arbitrary 2x2 or 4x4 RGB pattern

diff --git a/examples/heif_gen_bayer.cc b/examples/heif_gen_bayer.cc
index 9a6e69dc..a9841908 100644
--- a/examples/heif_gen_bayer.cc
+++ b/examples/heif_gen_bayer.cc
@@ -32,6 +32,7 @@
 #include <iomanip>
 #include <iostream>
 #include <memory>
+#include <optional>
 #include <regex>
 #include <sstream>
 #include <string>
@@ -46,7 +47,7 @@

 struct PatternDefinition
 {
-  const char* name;
+  std::string name;
   uint16_t width;
   uint16_t height;
   std::vector<heif_bayer_pattern_pixel> cpat;
@@ -67,19 +68,6 @@ static const PatternDefinition patterns[] = {
     }
   },

-  // GBRG
-  //   G B
-  //   R G
-  {
-    "gbrg", 2, 2,
-    {
-      {heif_uncompressed_component_type_green, 1.0f},
-      {heif_uncompressed_component_type_blue,  1.0f},
-      {heif_uncompressed_component_type_red,   1.0f},
-      {heif_uncompressed_component_type_green, 1.0f},
-    }
-  },
-
   // RGBW (Red-Green-Blue-White) — 4×4
   //   W G W R
   //   G W B W
@@ -148,7 +136,7 @@ static constexpr int num_patterns = sizeof(patterns) / sizeof(patterns[0]);
 static const PatternDefinition* find_pattern(const char* name)
 {
   for (int i = 0; i < num_patterns; i++) {
-    if (strcasecmp(patterns[i].name, name) == 0) {
+    if (strcasecmp(patterns[i].name.c_str(), name) == 0) {
       return &patterns[i];
     }
   }
@@ -156,6 +144,31 @@ static const PatternDefinition* find_pattern(const char* name)
 }


+static std::optional<PatternDefinition> parse_pattern_string(const char* str)
+{
+  std::string s(str);
+  size_t len = s.size();
+  if (len != 4 && len != 16) {
+    return {};
+  }
+
+  uint16_t dim = (len == 4) ? 2 : 4;
+  std::vector<heif_bayer_pattern_pixel> cpat;
+  cpat.reserve(len);
+
+  for (char c : s) {
+    switch (std::tolower(c)) {
+      case 'r': cpat.push_back({heif_uncompressed_component_type_red, 1.0f}); break;
+      case 'g': cpat.push_back({heif_uncompressed_component_type_green, 1.0f}); break;
+      case 'b': cpat.push_back({heif_uncompressed_component_type_blue, 1.0f}); break;
+      default: return {};
+    }
+  }
+
+  return PatternDefinition{str, dim, dim, std::move(cpat)};
+}
+
+
 static std::vector<std::string> deflate_input_filenames(const std::string& filename_example)
 {
   std::regex pattern(R"((.*\D)?(\d+)(\..+)$)");
@@ -229,6 +242,7 @@ static void print_usage()
               << (i == 0 ? "  [default]" : "")
               << "\n";
   }
+  std::cerr << "  Or specify a custom R/G/B string of length 4 (2x2) or 16 (4x4), e.g. -p BGGR\n";
 }


@@ -484,6 +498,7 @@ static int encode_sequence(const std::vector<std::string>& filenames,

 int main(int argc, char* argv[])
 {
+  PatternDefinition custom_pattern;
   const PatternDefinition* pat = &patterns[0]; // default: RGGB
   int output_bit_depth = 8;
   bool sequence_mode = false;
@@ -512,9 +527,16 @@ int main(int argc, char* argv[])
       case 'p':
         pat = find_pattern(optarg);
         if (!pat) {
-          std::cerr << "Unknown pattern: " << optarg << "\n";
-          print_usage();
-          return 1;
+          auto custom = parse_pattern_string(optarg);
+          if (custom) {
+            custom_pattern = std::move(*custom);
+            pat = &custom_pattern;
+          }
+          else {
+            std::cerr << "Unknown pattern: " << optarg << "\n";
+            print_usage();
+            return 1;
+          }
         }
         break;