[graphics/digikam] /: Update Libraw to last 20072026 snapshot: add support of Sony ARW6 CRAW HQ, Sony ILCE-7M5, and Canon R50 V camera.
Gilles Caulier <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit a153fdc1257207416a5db61de0d3840aeac2b680 by Gilles Caulier.
Committed on 20/07/2026 at 09:14.
Pushed by cgilles into branch 'master'.
Update Libraw to last 20072026 snapshot: add support of Sony ARW6 CRAW HQ, Sony ILCE-7M5, and Canon R50 V camera.
M +2 -1 NEWS
M +2 -2 core/app/views/stack/welcomepageview_features.cpp
M +1 -0 core/libs/rawengine/CMakeLists.txt
M +2 -0 core/libs/rawengine/libraw/internal/libraw_cameraids.h
M +1 -0 core/libs/rawengine/libraw/internal/libraw_internal_funcs.h
M +2 -2 core/libs/rawengine/libraw/libraw_manifest.txt
A +1618 -0 core/libs/rawengine/libraw/src/decoders/sony_arw6.cpp *
M +2 -1 core/libs/rawengine/libraw/src/metadata/canon.cpp
M +1 -1 core/libs/rawengine/libraw/src/metadata/identify.cpp
M +2 -0 core/libs/rawengine/libraw/src/metadata/normalize_model.cpp
M +4 -1 core/libs/rawengine/libraw/src/metadata/sony.cpp
M +11 -0 core/libs/rawengine/libraw/src/metadata/tiff.cpp
M +2 -0 core/libs/rawengine/libraw/src/tables/cameralist.cpp
M +5 -1 core/libs/rawengine/libraw/src/tables/colordata.cpp
M +5 -0 core/libs/rawengine/libraw/src/utils/decoder_info.cpp
M +11 -0 core/libs/rawengine/libraw/src/utils/open.cpp
The files marked with a * at the end have a non valid license. Please read: https://community.kde.org/Policies/Licensing_Policy and use the headers which are listed at that page.
https://invent.kde.org/graphics/digikam/-/commit/a153fdc1257207416a5db61de0d3840aeac2b680
diff --git a/NEWS b/NEWS
index fac3e1a8a8..f0fdeaf6fe 100644
--- a/NEWS
+++ b/NEWS
@@ -16,7 +16,8 @@ Bundles component versions:
| macOS Qt5 | 5.15.18 | 5.116 | 4.13 | 8.0.1 | 1.20.2 | 13.59 (*) | 0.28.8 | 20260716 (*) | 20260405 | Monterey + Macports |
| macOS Qt6 | 6.11.0 | 6.26.0 | 4.13 | 8.1.0 | 1.21.2 | 13.59 (*) | 0.28.8 | 20260716 (*) | - | Tathoe + Macports |
-Icon-View: Improve filename matching for timelapse/burst grouping items.
+Icon-View : Improve filename matching for timelapse/burst grouping items.
+Raw Support: Add support of Sony ARW6 CRAW HQ, Sony ILCE-7M5, and Canon R50 V.
*****************************************************************************************************
diff --git a/core/app/views/stack/welcomepageview_features.cpp b/core/app/views/stack/welcomepageview_features.cpp
index b18b558b0a..5e252f4d2b 100644
--- a/core/app/views/stack/welcomepageview_features.cpp
+++ b/core/app/views/stack/welcomepageview_features.cpp
@@ -90,7 +90,7 @@ QString WelcomePageView::featuresTabContent() const
newFeatures << i18n("Update internal RAW engine to last Libraw snapshot 2026-04-06.");
newFeatures << i18n("New RAW camera supported:")
+ appendSubList(QStringList()
- << i18n("Canon EOS R1, EOS R5 Mark II, EOS R5 C, EOS R6 Mark II, EOS R8, EOS R50, EOS R100, EOS Ra Canon EOS Kiss M2;")
+ << i18n("Canon R50 V, Canon EOS R1, EOS R5 Mark II, EOS R5 C, EOS R6 Mark II, EOS R8, EOS R50, EOS R100, EOS Ra Canon EOS Kiss M2;")
<< i18n("Fujifilm X-T50, GFX 100S II, GFX100-II, X-T5, X-S20, X-H2, X-H2S ;")
<< i18n("Hasselblad CFV-50c, CFV-100c, X2D-100c ;")
<< i18n("Leica Q3 43, D-Lux8, SL3, Q3, M11 Monochrom ;")
@@ -98,7 +98,7 @@ QString WelcomePageView::featuresTabContent() const
<< i18n("Olympus/OM System OM-1 Mark II, TG-7, OM-5 ;")
<< i18n("Panasonic GH7, S9, DC-G9 II, DC-ZS200D / ZS220D, DC-TZ200D / TZ202D / TZ220D, DC-S5-II, DC-GH6 ;")
<< i18n("Pentax KF, K III Monochrome ;")
- << i18n("Sony ZV-E10M2, UMC-R10C, A9-III, ILX-LR1, A7C-II, A7CR, ILCE-6700, ZV-1M2, ZV-E1, ILCE-7RM5 (A7R-V), ILME-FX30, A1 ;")
+ << i18n("Sony Sony ARW6 CRAW HQ, Sony ILCE-7M, VZV-E10M2, UMC-R10C, A9-III, ILX-LR1, A7C-II, A7CR, ILCE-6700, ZV-1M2, ZV-E1, ILCE-7RM5 (A7R-V), ILME-FX30, A1 ;")
<< i18n("Multiple DJI and Skydio drones ;")
<< i18n("Multiple smartphones with DNG format recorded.")
);
diff --git a/core/libs/rawengine/CMakeLists.txt b/core/libs/rawengine/CMakeLists.txt
index 4f2f2e6abc..e048855c34 100644
--- a/core/libs/rawengine/CMakeLists.txt
+++ b/core/libs/rawengine/CMakeLists.txt
@@ -104,6 +104,7 @@ set(libraw_LIB_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/libraw/src/decoders/pana8.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libraw/src/decoders/decoders_dcraw.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libraw/src/decoders/sonycc.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/libraw/src/decoders/sony_arw6.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libraw/src/decompressors/losslessjpeg.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libraw/src/decoders/decoders_libraw_dcrdefs.cpp
${CMAKE_CURRENT_SOURCE_DIR}/libraw/src/decoders/decoders_libraw.cpp
diff --git a/core/libs/rawengine/libraw/internal/libraw_cameraids.h b/core/libs/rawengine/libraw/internal/libraw_cameraids.h
index 4a55db346b..0367ef3a9f 100644
--- a/core/libs/rawengine/libraw/internal/libraw_cameraids.h
+++ b/core/libs/rawengine/libraw/internal/libraw_cameraids.h
@@ -94,6 +94,7 @@ it under the terms of the one of two licenses as you choose:
#define CanonID_EOS_R7 (0x80000000ULL + 0x464ULL)
#define CanonID_EOS_R10 (0x80000000ULL + 0x465ULL)
#define CanonID_EOS_M50_Mark_II (0x80000000ULL + 0x468ULL)
+#define CanonID_EOS_R50_V (0x80000000ULL + 0x516ULL)
#define CanonID_EOS_R50 (0x80000000ULL + 0x480ULL)
#define CanonID_EOS_R6m2 (0x80000000ULL + 0x481ULL)
#define CanonID_EOS_R8 (0x80000000ULL + 0x487ULL)
@@ -344,4 +345,5 @@ it under the terms of the one of two licenses as you choose:
#define SonyID_ZV_E10M2 0x18fULL
#define SonyID_ILME_FX2 0x196ULL
#define SonyID_ILCE_1M2 0x190ULL
+#define SonyID_ILCE_7M5 0x197ULL
#endif
diff --git a/core/libs/rawengine/libraw/internal/libraw_internal_funcs.h b/core/libs/rawengine/libraw/internal/libraw_internal_funcs.h
index 7cb2aa780d..f30c6365d8 100644
--- a/core/libs/rawengine/libraw/internal/libraw_internal_funcs.h
+++ b/core/libs/rawengine/libraw/internal/libraw_internal_funcs.h
@@ -282,6 +282,7 @@ it under the terms of the one of two licenses as you choose:
void sony_load_raw();
void sony_arw_load_raw();
void sony_arw2_load_raw();
+ void sony_arw6_load_raw();
void sony_arq_load_raw();
void sony_ljpeg_load_raw();
void sony_ycbcr_load_raw();
diff --git a/core/libs/rawengine/libraw/libraw_manifest.txt b/core/libs/rawengine/libraw/libraw_manifest.txt
index 86783bba78..b392fcc00f 100644
--- a/core/libs/rawengine/libraw/libraw_manifest.txt
+++ b/core/libs/rawengine/libraw/libraw_manifest.txt
@@ -1,2 +1,2 @@
-+LIBRAW Snapshot 2026-07-16
-libraw:87241b45d8c8178247faca4aa8e6a1896b0b1eeb
++LIBRAW Snapshot 2026-07-20
+libraw:e419de08001de28ae6988ecb22df47e52b9c5eaa
diff --git a/core/libs/rawengine/libraw/src/decoders/sony_arw6.cpp b/core/libs/rawengine/libraw/src/decoders/sony_arw6.cpp
new file mode 100644
index 0000000000..1c47a7390a
--- /dev/null
+++ b/core/libs/rawengine/libraw/src/decoders/sony_arw6.cpp
@@ -0,0 +1,1618 @@
+/* -*- C++ -*-
+ * Copyright 2026 LibRaw LLC ([email protected])
+ * Copyright (C) 2026 Jiang Yaogeng (Sony ARW6 CRAW HQ decoder;
+ * code generated with assistance from GLM-5)
+ *
+ LibRaw is free software; you can redistribute it and/or modify
+ it under the terms of the one of two licenses as you choose:
+
+1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
+ (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
+
+2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+ (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
+
+ */
+
+#include "../../internal/dcraw_defs.h"
+
+#include <algorithm>
+#include <stdint.h>
+#include <string.h>
+#include <vector>
+
+namespace
+{
+const int SONY_ARW6_STREAM_OFFSET = 0x200;
+const int SONY_ARW6_INTERNAL_BIAS = 2048;
+const size_t SONY_ARW6_MAX_PLANE_SAMPLES = size_t(128) * 1024 * 1024;
+const INT64 SONY_ARW6_WORKING_BYTES_PER_TILE_PIXEL = 24;
+
+static inline int sony_arw6_align_up(int value, int multiple)
+{
+ return ((value + multiple - 1) / multiple) * multiple;
+}
+
+static inline INT64 sony_arw6_memory_limit_bytes(unsigned max_raw_memory_mb)
+{
+ return INT64(max_raw_memory_mb) * INT64(1024 * 1024);
+}
+
+static inline uint16_t sony_arw6_be16(const uchar *p)
+{
+ return uint16_t((uint16_t(p[0]) << 8) | p[1]);
+}
+
+static inline uint32_t sony_arw6_be32(const uchar *p)
+{
+ return (uint32_t(p[0]) << 24) | (uint32_t(p[1]) << 16) |
+ (uint32_t(p[2]) << 8) | uint32_t(p[3]);
+}
+
+static inline uint32_t sony_arw6_le32(const uchar *p)
+{
+ return (uint32_t(p[3]) << 24) | (uint32_t(p[2]) << 16) |
+ (uint32_t(p[1]) << 8) | uint32_t(p[0]);
+}
+
+static inline void sony_arw6_require(bool cond)
+{
+ if (!cond)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+}
+
+static inline int32_t sony_arw6_floor_shift(int64_t x, int bits)
+{
+ if (bits <= 0)
+ return int32_t(x);
+ const int64_t d = int64_t(1) << bits;
+ return int32_t(x >= 0 ? x >> bits : -(((-x) + d - 1) >> bits));
+}
+
+static inline int32_t sony_arw6_sign16(int32_t x)
+{
+ x &= 0xffff;
+ return x >= 0x8000 ? x - 0x10000 : x;
+}
+
+static inline int32_t sony_arw6_edge_detail(int32_t x, bool odd_mode)
+{
+ const int32_t signed_half_step = x > 0 ? 1 : (x < 0 ? -1 : 0);
+ const bool is_odd = (x % 2) != 0;
+ const bool use_half_step =
+ odd_mode ? is_odd : (x != 0 && !is_odd);
+ return 2 * x + (use_half_step ? signed_half_step : 0);
+}
+
+static const ushort sony_arw6_llvc3_curve[4096] = {
+ 0, 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,
+ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
+ 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127,
+ 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
+ 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159,
+ 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
+ 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191,
+ 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
+ 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223,
+ 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
+ 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
+ 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271,
+ 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287,
+ 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303,
+ 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319,
+ 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335,
+ 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351,
+ 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367,
+ 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383,
+ 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399,
+ 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415,
+ 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431,
+ 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447,
+ 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463,
+ 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479,
+ 480, 481, 482, 483, 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495,
+ 496, 497, 498, 499, 500, 501, 502, 503, 504, 505, 506, 507, 508, 509, 510, 511,
+ 512, 513, 514, 515, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 527,
+ 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 540, 541, 542, 543,
+ 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557, 558, 559,
+ 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 574, 575,
+ 576, 577, 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591,
+ 592, 593, 594, 595, 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607,
+ 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, 620, 621, 622, 623,
+ 624, 625, 626, 627, 628, 629, 630, 631, 632, 633, 634, 635, 636, 637, 638, 639,
+ 640, 641, 642, 643, 644, 645, 646, 647, 648, 649, 650, 651, 652, 653, 654, 655,
+ 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669, 670, 671,
+ 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687,
+ 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703,
+ 704, 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719,
+ 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735,
+ 736, 737, 738, 739, 740, 741, 742, 743, 744, 745, 746, 747, 748, 749, 750, 751,
+ 752, 753, 754, 755, 756, 757, 758, 759, 760, 761, 762, 763, 764, 765, 766, 767,
+ 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779, 780, 781, 782, 783,
+ 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 799,
+ 800, 801, 802, 803, 804, 805, 806, 807, 808, 809, 810, 811, 812, 813, 814, 815,
+ 816, 817, 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, 830, 831,
+ 832, 833, 834, 835, 836, 837, 838, 839, 840, 841, 842, 843, 844, 845, 846, 847,
+ 848, 849, 850, 851, 852, 853, 854, 855, 856, 857, 858, 859, 860, 861, 862, 863,
+ 864, 865, 866, 867, 868, 869, 870, 871, 872, 873, 874, 875, 876, 877, 878, 879,
+ 880, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890, 891, 892, 893, 894, 895,
+ 896, 897, 898, 899, 900, 901, 902, 903, 904, 905, 906, 907, 908, 909, 910, 911,
+ 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922, 923, 924, 925, 926, 927,
+ 928, 929, 930, 931, 932, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 943,
+ 944, 945, 946, 947, 948, 949, 950, 951, 952, 953, 954, 955, 956, 957, 958, 959,
+ 960, 961, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 974, 975,
+ 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, 990, 991,
+ 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007,
+ 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020, 1021, 1022, 1023,
+ 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039,
+ 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055,
+ 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066, 1067, 1068, 1069, 1070, 1071,
+ 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087,
+ 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1100, 1101, 1102, 1103,
+ 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113, 1114, 1115, 1116, 1117, 1118, 1119,
+ 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129, 1130, 1131, 1132, 1133, 1134, 1135,
+ 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149, 1150, 1151,
+ 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161, 1162, 1163, 1164, 1165, 1166, 1167,
+ 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183,
+ 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199,
+ 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210, 1211, 1212, 1213, 1214, 1215,
+ 1216, 1217, 1218, 1219, 1220, 1221, 1222, 1223, 1224, 1225, 1226, 1227, 1228, 1229, 1230, 1231,
+ 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247,
+ 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260, 1261, 1262, 1263,
+ 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277, 1278, 1279,
+ 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295,
+ 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1310, 1311,
+ 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, 1322, 1323, 1324, 1325, 1326, 1327,
+ 1328, 1329, 1330, 1331, 1332, 1333, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343,
+ 1344, 1345, 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359,
+ 1360, 1361, 1362, 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375,
+ 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1391,
+ 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399, 1400, 1401, 1402, 1403, 1404, 1405, 1406, 1407,
+ 1408, 1409, 1410, 1411, 1412, 1413, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, 1423,
+ 1424, 1425, 1426, 1427, 1429, 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1438, 1439, 1440, 1441,
+ 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449, 1450, 1451, 1452, 1453, 1455, 1456, 1457, 1458,
+ 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1470, 1471, 1472, 1473, 1474,
+ 1475, 1476, 1477, 1478, 1480, 1481, 1482, 1483, 1484, 1485, 1486, 1487, 1489, 1490, 1491, 1492,
+ 1493, 1494, 1495, 1496, 1497, 1498, 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508,
+ 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1522, 1523, 1524, 1525,
+ 1526, 1527, 1529, 1530, 1531, 1532, 1534, 1535, 1536, 1537, 1538, 1539, 1541, 1542, 1543, 1544,
+ 1545, 1546, 1548, 1549, 1550, 1551, 1553, 1554, 1555, 1556, 1558, 1559, 1561, 1562, 1563, 1565,
+ 1566, 1567, 1568, 1569, 1571, 1572, 1573, 1574, 1575, 1576, 1578, 1579, 1580, 1581, 1583, 1584,
+ 1585, 1586, 1588, 1589, 1590, 1591, 1593, 1594, 1595, 1596, 1598, 1599, 1601, 1602, 1603, 1605,
+ 1606, 1607, 1608, 1609, 1611, 1612, 1613, 1614, 1615, 1616, 1618, 1619, 1621, 1622, 1623, 1625,
+ 1626, 1627, 1629, 1630, 1631, 1632, 1634, 1635, 1636, 1637, 1639, 1640, 1641, 1642, 1644, 1645,
+ 1646, 1647, 1649, 1650, 1651, 1652, 1654, 1655, 1656, 1657, 1659, 1660, 1662, 1663, 1664, 1666,
+ 1667, 1668, 1670, 1671, 1673, 1674, 1675, 1677, 1678, 1680, 1681, 1683, 1685, 1686, 1688, 1689,
+ 1691, 1692, 1694, 1695, 1697, 1698, 1699, 1701, 1702, 1704, 1705, 1707, 1709, 1710, 1712, 1713,
+ 1715, 1716, 1718, 1719, 1720, 1721, 1723, 1724, 1725, 1727, 1728, 1730, 1731, 1733, 1734, 1736,
+ 1737, 1739, 1740, 1742, 1743, 1745, 1746, 1748, 1749, 1750, 1752, 1753, 1755, 1756, 1757, 1759,
+ 1760, 1762, 1763, 1765, 1767, 1768, 1770, 1771, 1773, 1774, 1776, 1777, 1779, 1780, 1781, 1783,
+ 1784, 1786, 1787, 1789, 1791, 1792, 1794, 1795, 1797, 1799, 1801, 1802, 1804, 1806, 1808, 1809,
+ 1811, 1813, 1814, 1816, 1818, 1819, 1821, 1822, 1824, 1826, 1827, 1829, 1831, 1832, 1834, 1835,
+ 1837, 1839, 1841, 1842, 1844, 1846, 1848, 1849, 1851, 1853, 1854, 1856, 1858, 1859, 1861, 1862,
+ 1864, 1866, 1868, 1869, 1871, 1873, 1875, 1876, 1878, 1880, 1881, 1883, 1885, 1886, 1888, 1889,
+ 1891, 1893, 1894, 1896, 1898, 1899, 1901, 1902, 1904, 1906, 1908, 1909, 1911, 1913, 1915, 1916,
+ 1918, 1920, 1922, 1924, 1926, 1927, 1929, 1931, 1933, 1935, 1937, 1938, 1940, 1942, 1944, 1945,
+ 1947, 1949, 1951, 1953, 1955, 1957, 1959, 1961, 1963, 1965, 1967, 1968, 1970, 1972, 1974, 1975,
+ 1977, 1979, 1981, 1983, 1985, 1986, 1988, 1990, 1992, 1994, 1996, 1998, 2000, 2001, 2003, 2005,
+ 2007, 2009, 2011, 2013, 2015, 2016, 2018, 2020, 2022, 2024, 2026, 2027, 2029, 2031, 2033, 2034,
+ 2036, 2038, 2040, 2042, 2044, 2046, 2048, 2050, 2052, 2054, 2056, 2058, 2060, 2062, 2064, 2066,
+ 2068, 2070, 2072, 2074, 2076, 2078, 2080, 2082, 2084, 2086, 2088, 2090, 2092, 2094, 2096, 2098,
+ 2100, 2102, 2104, 2106, 2109, 2111, 2113, 2115, 2117, 2119, 2121, 2123, 2125, 2127, 2129, 2131,
+ 2133, 2135, 2137, 2139, 2141, 2143, 2145, 2147, 2149, 2151, 2153, 2155, 2157, 2159, 2161, 2163,
+ 2165, 2167, 2170, 2172, 2175, 2177, 2179, 2182, 2184, 2186, 2188, 2190, 2193, 2195, 2197, 2199,
+ 2201, 2203, 2206, 2208, 2210, 2212, 2215, 2217, 2219, 2221, 2224, 2226, 2228, 2230, 2233, 2235,
+ 2237, 2239, 2242, 2244, 2247, 2249, 2251, 2254, 2256, 2258, 2261, 2263, 2265, 2267, 2270, 2272,
+ 2274, 2276, 2279, 2281, 2283, 2285, 2288, 2290, 2292, 2294, 2297, 2299, 2302, 2304, 2306, 2309,
+ 2311, 2314, 2316, 2319, 2321, 2324, 2326, 2329, 2331, 2333, 2336, 2338, 2340, 2342, 2345, 2347,
+ 2349, 2352, 2354, 2357, 2359, 2362, 2364, 2367, 2369, 2371, 2374, 2376, 2379, 2381, 2383, 2386,
+ 2388, 2390, 2393, 2395, 2398, 2400, 2402, 2405, 2407, 2410, 2412, 2415, 2417, 2420, 2422, 2425,
+ 2427, 2430, 2432, 2435, 2438, 2440, 2443, 2445, 2448, 2451, 2453, 2456, 2459, 2461, 2464, 2466,
+ 2469, 2472, 2475, 2477, 2480, 2483, 2486, 2488, 2491, 2494, 2496, 2499, 2501, 2504, 2506, 2509,
+ 2511, 2514, 2517, 2519, 2522, 2525, 2528, 2530, 2533, 2536, 2538, 2541, 2543, 2546, 2548, 2551,
+ 2553, 2556, 2559, 2561, 2564, 2567, 2570, 2572, 2575, 2578, 2581, 2584, 2587, 2589, 2592, 2595,
+ 2598, 2601, 2604, 2606, 2609, 2612, 2615, 2617, 2620, 2623, 2626, 2629, 2632, 2634, 2637, 2640,
+ 2643, 2646, 2649, 2652, 2655, 2657, 2660, 2663, 2666, 2669, 2672, 2675, 2678, 2680, 2683, 2686,
+ 2689, 2692, 2695, 2698, 2701, 2704, 2707, 2710, 2713, 2716, 2719, 2722, 2725, 2727, 2730, 2733,
+ 2736, 2739, 2742, 2745, 2749, 2752, 2755, 2758, 2761, 2764, 2767, 2770, 2773, 2776, 2779, 2782,
+ 2785, 2788, 2791, 2794, 2798, 2801, 2804, 2807, 2810, 2813, 2816, 2819, 2823, 2826, 2829, 2832,
+ 2835, 2838, 2841, 2844, 2848, 2851, 2854, 2857, 2860, 2863, 2867, 2870, 2873, 2876, 2880, 2883,
+ 2886, 2889, 2893, 2896, 2899, 2902, 2906, 2909, 2912, 2915, 2919, 2922, 2925, 2928, 2932, 2935,
+ 2938, 2941, 2945, 2948, 2952, 2955, 2958, 2962, 2965, 2968, 2972, 2975, 2979, 2982, 2985, 2989,
+ 2992, 2995, 2999, 3002, 3006, 3009, 3012, 3016, 3019, 3023, 3026, 3030, 3033, 3037, 3040, 3044,
+ 3047, 3051, 3054, 3058, 3061, 3065, 3068, 3072, 3075, 3079, 3082, 3086, 3089, 3093, 3096, 3100,
+ 3103, 3107, 3110, 3114, 3118, 3121, 3125, 3128, 3132, 3136, 3139, 3143, 3146, 3150, 3153, 3157,
+ 3160, 3164, 3168, 3171, 3175, 3179, 3183, 3186, 3190, 3194, 3197, 3201, 3205, 3208, 3212, 3215,
+ 3219, 3223, 3227, 3231, 3235, 3238, 3242, 3246, 3250, 3254, 3258, 3261, 3265, 3269, 3273, 3276,
+ 3280, 3284, 3288, 3292, 3296, 3299, 3303, 3307, 3311, 3315, 3319, 3323, 3327, 3331, 3335, 3339,
+ 3343, 3347, 3351, 3354, 3358, 3362, 3366, 3369, 3373, 3377, 3381, 3385, 3389, 3393, 3397, 3401,
+ 3405, 3409, 3413, 3417, 3422, 3426, 3430, 3434, 3438, 3442, 3446, 3450, 3455, 3459, 3463, 3467,
+ 3471, 3475, 3479, 3483, 3487, 3491, 3495, 3499, 3503, 3507, 3512, 3516, 3520, 3524, 3529, 3533,
+ 3537, 3541, 3546, 3550, 3554, 3558, 3563, 3567, 3571, 3575, 3580, 3584, 3589, 3593, 3597, 3602,
+ 3606, 3610, 3615, 3619, 3624, 3628, 3632, 3637, 3641, 3645, 3650, 3654, 3658, 3662, 3667, 3671,
+ 3675, 3680, 3684, 3689, 3693, 3698, 3702, 3707, 3711, 3716, 3720, 3725, 3729, 3734, 3738, 3743,
+ 3747, 3752, 3756, 3761, 3766, 3770, 3775, 3779, 3784, 3789, 3793, 3798, 3802, 3807, 3811, 3816,
+ 3820, 3825, 3830, 3834, 3839, 3844, 3849, 3853, 3858, 3863, 3868, 3872, 3877, 3882, 3887, 3891,
+ 3896, 3901, 3906, 3910, 3915, 3920, 3925, 3929, 3934, 3939, 3944, 3949, 3954, 3958, 3963, 3968,
+ 3973, 3978, 3983, 3988, 3993, 3997, 4002, 4007, 4012, 4017, 4022, 4027, 4032, 4037, 4042, 4047,
+ 4052, 4057, 4062, 4067, 4072, 4077, 4082, 4087, 4092, 4097, 4102, 4107, 4113, 4118, 4123, 4128,
+ 4133, 4138, 4143, 4148, 4154, 4159, 4164, 4169, 4174, 4179, 4185, 4190, 4195, 4200, 4206, 4211,
+ 4216, 4221, 4227, 4232, 4237, 4242, 4248, 4253, 4258, 4263, 4269, 4274, 4280, 4285, 4290, 4296,
+ 4301, 4306, 4312, 4317, 4323, 4328, 4333, 4339, 4344, 4350, 4355, 4361, 4366, 4372, 4377, 4383,
+ 4388, 4394, 4399, 4405, 4410, 4416, 4421, 4427, 4432, 4438, 4444, 4449, 4455, 4461, 4467, 4472,
+ 4478, 4484, 4489, 4495, 4500, 4506, 4511, 4517, 4522, 4528, 4534, 4540, 4546, 4551, 4557, 4563,
+ 4569, 4575, 4581, 4586, 4592, 4598, 4604, 4609, 4615, 4621, 4627, 4633, 4639, 4644, 4650, 4656,
+ 4662, 4668, 4674, 4680, 4686, 4692, 4698, 4704, 4710, 4716, 4722, 4728, 4734, 4740, 4746, 4752,
+ 4758, 4764, 4771, 4777, 4783, 4789, 4796, 4802, 4808, 4814, 4820, 4826, 4832, 4838, 4844, 4850,
+ 4856, 4862, 4869, 4875, 4882, 4888, 4894, 4901, 4907, 4913, 4920, 4926, 4933, 4939, 4945, 4952,
+ 4958, 4964, 4971, 4977, 4983, 4989, 4996, 5002, 5008, 5015, 5021, 5028, 5034, 5041, 5047, 5054,
+ 5060, 5067, 5073, 5080, 5087, 5093, 5100, 5106, 5113, 5120, 5126, 5133, 5140, 5146, 5153, 5159,
+ 5166, 5173, 5180, 5186, 5193, 5200, 5207, 5213, 5220, 5227, 5234, 5240, 5247, 5254, 5261, 5267,
+ 5274, 5281, 5288, 5295, 5302, 5309, 5316, 5323, 5330, 5337, 5344, 5351, 5358, 5365, 5372, 5379,
+ 5386, 5393, 5400, 5407, 5414, 5421, 5428, 5435, 5442, 5449, 5456, 5463, 5471, 5478, 5485, 5492,
+ 5499, 5506, 5514, 5521, 5528, 5535, 5543, 5550, 5557, 5564, 5572, 5579, 5587, 5594, 5601, 5609,
+ 5616, 5623, 5631, 5638, 5646, 5653, 5660, 5668, 5675, 5683, 5690, 5698, 5705, 5713, 5720, 5728,
+ 5735, 5743, 5751, 5758, 5766, 5774, 5782, 5789, 5797, 5805, 5812, 5820, 5828, 5835, 5843, 5850,
+ 5858, 5866, 5874, 5881, 5889, 5897, 5905, 5912, 5920, 5928, 5936, 5944, 5952, 5959, 5967, 5975,
+ 5983, 5991, 5999, 6007, 6015, 6023, 6031, 6039, 6047, 6055, 6063, 6071, 6079, 6087, 6095, 6103,
+ 6111, 6119, 6128, 6136, 6144, 6152, 6161, 6169, 6177, 6185, 6194, 6202, 6210, 6218, 6227, 6235,
+ 6243, 6251, 6260, 6268, 6277, 6285, 6293, 6302, 6310, 6319, 6327, 6336, 6344, 6353, 6361, 6370,
+ 6378, 6387, 6395, 6404, 6412, 6421, 6429, 6438, 6446, 6455, 6464, 6472, 6481, 6490, 6499, 6507,
+ 6516, 6525, 6534, 6543, 6552, 6560, 6569, 6578, 6587, 6596, 6605, 6613, 6622, 6631, 6640, 6648,
+ 6657, 6666, 6675, 6684, 6694, 6703, 6712, 6721, 6730, 6739, 6748, 6757, 6767, 6776, 6785, 6794,
+ 6803, 6812, 6822, 6831, 6840, 6849, 6859, 6868, 6877, 6886, 6896, 6905, 6914, 6923, 6933, 6942,
+ 6951, 6961, 6970, 6980, 6989, 6999, 7008, 7018, 7027, 7037, 7046, 7056, 7065, 7075, 7084, 7094,
+ 7103, 7113, 7123, 7132, 7142, 7152, 7162, 7171, 7181, 7191, 7201, 7210, 7220, 7230, 7240, 7249,
+ 7259, 7269, 7279, 7289, 7299, 7309, 7319, 7329, 7339, 7349, 7359, 7369, 7379, 7389, 7399, 7409,
+ 7419, 7429, 7440, 7450, 7460, 7470, 7481, 7491, 7501, 7511, 7522, 7532, 7543, 7553, 7563, 7574,
+ 7584, 7594, 7605, 7615, 7626, 7636, 7646, 7657, 7667, 7678, 7688, 7699, 7709, 7720, 7730, 7741,
+ 7751, 7762, 7772, 7783, 7794, 7804, 7815, 7825, 7836, 7847, 7858, 7869, 7880, 7890, 7901, 7912,
+ 7923, 7934, 7945, 7956, 7967, 7977, 7988, 7999, 8010, 8021, 8032, 8043, 8055, 8066, 8077, 8088,
+ 8099, 8110, 8122, 8133, 8144, 8155, 8167, 8178, 8189, 8200, 8212, 8223, 8234, 8245, 8257, 8268,
+ 8279, 8291, 8302, 8314, 8326, 8337, 8349, 8360, 8372, 8384, 8395, 8407, 8418, 8430, 8441, 8453,
+ 8464, 8476, 8488, 8500, 8512, 8523, 8535, 8547, 8559, 8571, 8583, 8595, 8607, 8618, 8630, 8642,
+ 8654, 8666, 8678, 8690, 8702, 8714, 8726, 8738, 8750, 8762, 8775, 8787, 8799, 8811, 8824, 8836,
+ 8848, 8860, 8873, 8885, 8898, 8910, 8922, 8935, 8947, 8960, 8972, 8985, 8997, 9010, 9022, 9035,
+ 9047, 9060, 9072, 9085, 9098, 9110, 9123, 9135, 9148, 9161, 9174, 9187, 9200, 9212, 9225, 9238,
+ 9251, 9264, 9277, 9290, 9303, 9316, 9329, 9342, 9355, 9368, 9381, 9394, 9408, 9421, 9434, 9447,
+ 9460, 9473, 9487, 9500, 9513, 9526, 9540, 9553, 9566, 9580, 9593, 9607, 9620, 9634, 9647, 9661,
+ 9674, 9688, 9701, 9715, 9728, 9742, 9755, 9769, 9782, 9796, 9810, 9824, 9838, 9851, 9865, 9879,
+ 9893, 9907, 9921, 9935, 9949, 9963, 9977, 9991, 10005, 10019, 10033, 10047, 10061, 10075, 10089, 10103,
+ 10117, 10131, 10146, 10160, 10175, 10189, 10203, 10218, 10232, 10247, 10261, 10276, 10290, 10305, 10319, 10334,
+ 10348, 10363, 10377, 10392, 10407, 10421, 10436, 10450, 10465, 10480, 10495, 10509, 10524, 10539, 10554, 10568,
+ 10583, 10598, 10613, 10628, 10643, 10658, 10673, 10688, 10703, 10718, 10734, 10749, 10764, 10779, 10795, 10810,
+ 10825, 10840, 10856, 10871, 10887, 10902, 10917, 10933, 10948, 10964, 10979, 10995, 11010, 11026, 11041, 11057,
+ 11072, 11088, 11104, 11120, 11136, 11151, 11167, 11183, 11199, 11215, 11231, 11247, 11263, 11278, 11294, 11310,
+ 11326, 11342, 11358, 11374, 11391, 11407, 11423, 11439, 11455, 11471, 11488, 11504, 11521, 11537, 11553, 11570,
+ 11586, 11603, 11619, 11636, 11652, 11669, 11685, 11702, 11718, 11735, 11752, 11768, 11785, 11802, 11819, 11835,
+ 11852, 11869, 11886, 11903, 11920, 11937, 11954, 11971, 11988, 12005, 12022, 12039, 12057, 12074, 12091, 12108,
+ 12125, 12142, 12160, 12177, 12195, 12212, 12229, 12247, 12264, 12282, 12299, 12317, 12335, 12352, 12370, 12387,
+ 12405, 12423, 12441, 12458, 12476, 12494, 12512, 12529, 12547, 12565, 12583, 12601, 12619, 12637, 12655, 12673,
+ 12691, 12709, 12728, 12746, 12764, 12782, 12801, 12819, 12837, 12855, 12874, 12892, 12911, 12929, 12947, 12966,
+ 12984, 13003, 13022, 13040, 13059, 13078, 13097, 13115, 13134, 13153, 13172, 13191, 13210, 13228, 13247, 13266,
+ 13285, 13304, 13323, 13342, 13362, 13381, 13400, 13419, 13438, 13457, 13477, 13496, 13516, 13535, 13554, 13574,
+ 13593, 13613, 13632, 13652, 13672, 13691, 13711, 13730, 13750, 13770, 13790, 13810, 13830, 13849, 13869, 13889,
+ 13909, 13929, 13949, 13969, 13990, 14010, 14030, 14050, 14070, 14090, 14111, 14131, 14151, 14171, 14192, 14212,
+ 14232, 14253, 14273, 14294, 14315, 14335, 14356, 14376, 14397, 14418, 14439, 14460, 14481, 14501, 14522, 14543,
+ 14564, 14585, 14606, 14627, 14648, 14669, 14690, 14711, 14732, 14753, 14775, 14796, 14818, 14839, 14860, 14882,
+ 14903, 14925, 14946, 14968, 14990, 15011, 15033, 15054, 15076, 15098, 15120, 15142, 15164, 15185, 15207, 15229,
+ 15251, 15273, 15295, 15317, 15340, 15362, 15384, 15406, 15428, 15450, 15473, 15495, 15518, 15540, 15562, 15585,
+ 15607, 15630, 15653, 15675, 15698, 15721, 15744, 15766, 15789, 15812, 15835, 15858, 15881, 15903, 15926, 15949,
+ 15972, 15995, 16019, 16042, 16065, 16088, 16112, 16135, 16158, 16182, 16205, 16229, 16253, 16276, 16300, 16323,
+ 16347, 16371, 16395, 16418, 16442, 16466, 16490, 16513, 16537, 16561, 16585, 16609, 16634, 16658, 16682, 16706,
+ 16730, 16754, 16779, 16803, 16828, 16852, 16876, 16901, 16925, 16950, 16975, 16999, 17024, 17049, 17074, 17098,
+ 17123, 17148, 17173, 17198, 17223, 17248, 17273, 17298, 17323, 17348, 17374, 17399, 17424, 17449, 17475, 17500,
+ 17525, 17551, 17576, 17602, 17628, 17653, 17679, 17704, 17730, 17756, 17782, 17808, 17834, 17860, 17886, 17912,
+ 17938, 17964, 17991, 18017, 18043, 18069, 18096, 18122, 18148, 18175, 18201, 18228, 18254, 18281, 18307, 18334,
+ 18360, 18387, 18414, 18441, 18468, 18494, 18521, 18548, 18575, 18602, 18630, 18657, 18684, 18711, 18739, 18766,
+ 18793, 18821, 18848, 18876, 18904, 18931, 18959, 18986, 19014, 19042, 19070, 19097, 19125, 19153, 19181, 19208,
+ 19236, 19264, 19293, 19321, 19349, 19377, 19406, 19434, 19462, 19491, 19519, 19548, 19577, 19605, 19634, 19662,
+ 19691, 19720, 19749, 19778, 19807, 19835, 19864, 19893, 19922, 19951, 19981, 20010, 20040, 20069, 20098, 20128,
+ 20157, 20187, 20216, 20246, 20276, 20305, 20335, 20364, 20394, 20424, 20454, 20484, 20514, 20544, 20574, 20604,
+ 20634, 20664, 20695, 20725, 20756, 20786, 20816, 20847, 20877, 20908, 20939, 20969, 21000, 21031, 21062, 21092,
+ 21123, 21154, 21185, 21216, 21247, 21278, 21309, 21340, 21371, 21403, 21434, 21466, 21497, 21529, 21560, 21592,
+ 21623, 21655, 21687, 21719, 21751, 21782, 21814, 21846, 21878, 21910, 21943, 21975, 22007, 22039, 22072, 22104,
+ 22136, 22169, 22202, 22234, 22267, 22300, 22333, 22365, 22398, 22431, 22464, 22497, 22530, 22563, 22596, 22629,
+ 22662, 22696, 22729, 22763, 22796, 22830, 22863, 22897, 22930, 22964, 22998, 23032, 23066, 23099, 23133, 23167,
+ 23201, 23235, 23270, 23304, 23338, 23372, 23407, 23441, 23475, 23510, 23545, 23579, 23614, 23649, 23684, 23718,
+ 23753, 23788, 23823, 23858, 23894, 23929, 23964, 23999, 24034, 24070, 24105, 24141, 24176, 24212, 24247, 24283,
+ 24318, 24354, 24390, 24426, 24462, 24498, 24534, 24570, 24606, 24643, 24679, 24716, 24752, 24789, 24825, 24862,
+ 24898, 24935, 24972, 25009, 25046, 25082, 25119, 25156, 25193, 25230, 25268, 25305, 25342, 25379, 25417, 25454,
+ 25491, 25529, 25567, 25605, 25643, 25680, 25718, 25756, 25794, 25832, 25871, 25909, 25947, 25985, 26024, 26062,
+ 26100, 26139, 26178, 26216, 26255, 26294, 26333, 26371, 26410, 26449, 26488, 26527, 26567, 26606, 26645, 26684,
+ 26723, 26763, 26802, 26842, 26882, 26921, 26961, 27000, 27040, 27080, 27121, 27161, 27201, 27241, 27282, 27322,
+ 27362, 27403, 27443, 27484, 27525, 27565, 27606, 27646, 27687, 27728, 27769, 27810, 27852, 27893, 27934, 27975,
+ 28016, 28058, 28099, 28141, 28183, 28224, 28266, 28307, 28349, 28391, 28433, 28475, 28518, 28560, 28602, 28644,
+ 28686, 28729, 28772, 28814, 28857, 28900, 28943, 28985, 29028, 29071, 29114, 29157, 29201, 29244, 29287, 29330,
+ 29373, 29417, 29461, 29504, 29548, 29592, 29636, 29679, 29723, 29767, 29812, 29856, 29900, 29944, 29989, 30033,
+ 30077, 30122, 30167, 30211, 30256, 30301, 30346, 30390, 30435, 30480, 30526, 30571, 30617, 30662, 30707, 30753,
+ 30798, 30844, 30890, 30936, 30982, 31027, 31073, 31119, 31165, 31212, 31258, 31305, 31351, 31398, 31444, 31491,
+ 31537, 31584, 31631, 31678, 31725, 31772, 31819, 31866, 31913, 31961, 32008, 32056, 32104, 32151, 32199, 32246,
+ 32294, 32342, 32390, 32438, 32487, 32535, 32583, 32631, 32679, 32766, 32777, 32825, 32874, 32923, 32972, 33020,
+ 33069, 33118, 33168, 33217, 33267, 33316, 33365, 33415, 33464, 33514, 33564, 33614, 33664, 33714, 33764, 33814,
+ 33864, 33915, 33965, 34016, 34067, 34117, 34168, 34218, 34269, 34320, 34371, 34422, 34474, 34525, 34576, 34627,
+ 34678, 34730, 34782, 34834, 34886, 34937, 34989, 35041, 35093, 35146, 35198, 35251, 35303, 35356, 35408, 35461,
+ 35513, 35566, 35619, 35672, 35725, 35778, 35831, 35884, 35937, 35991, 36045, 36098, 36152, 36206, 36260, 36313,
+ 36367, 36422, 36476, 36531, 36585, 36640, 36694, 36749, 36803, 36858, 36913, 36968, 37023, 37078, 37133, 37188,
+ 37243, 37299, 37355, 37410, 37466, 37522, 37578, 37633, 37689, 37746, 37802, 37859, 37915, 37972, 38028, 38085,
+ 38141, 38198, 38255, 38312, 38369, 38426, 38483, 38540, 38597, 38655, 38713, 38771, 38829, 38886, 38944, 39002
+};
+
+static inline ushort sony_arw6_llvc3_lut_value(int code)
+{
+ if (code < 0)
+ code = 0;
+ if (code > 4095)
+ code = 4095;
+ return sony_arw6_llvc3_curve[code];
+}
+
+static size_t sony_arw6_checked_plane_samples(int rows, int cols)
+{
+ sony_arw6_require(rows >= 0 && cols >= 0);
+ const uint64_t r = uint64_t(rows);
+ const uint64_t c = uint64_t(cols);
+ sony_arw6_require(c == 0 || r <= uint64_t(~size_t(0)) / c);
+ const uint64_t samples = r * c;
+ sony_arw6_require(samples <= uint64_t(SONY_ARW6_MAX_PLANE_SAMPLES));
+ return size_t(samples);
+}
+
+struct SonyArw6Plane
+{
+ int rows;
+ int cols;
+ std::vector<int32_t> data;
+
+ SonyArw6Plane() : rows(0), cols(0) {}
+ SonyArw6Plane(int r, int c)
+ : rows(r), cols(c), data(sony_arw6_checked_plane_samples(r, c))
+ {
+ }
+
+ int32_t &at(int r, int c) { return data[size_t(r) * size_t(cols) + c]; }
+ const int32_t &at(int r, int c) const
+ {
+ return data[size_t(r) * size_t(cols) + c];
+ }
+ int32_t *row(int r) { return &data[size_t(r) * size_t(cols)]; }
+ const int32_t *row(int r) const { return &data[size_t(r) * size_t(cols)]; }
+};
+
+struct SonyArw6DirectoryEntry
+{
+ int group;
+ int index;
+ uint32_t start;
+ uint32_t length;
+};
+
+struct SonyArw6StreamInfo
+{
+ int index;
+ uint32_t offset;
+ uint32_t length;
+ int tile_x;
+ int tile_y;
+ int tile_w;
+ int tile_h;
+ int coded_width;
+ int coded_half_height;
+ int logical_height;
+};
+
+struct SonyArw6PacketRecord
+{
+ uint32_t byte_length;
+ uchar selectors[3];
+ uint32_t payload_offset;
+};
+
+struct SonyArw6Packet
+{
+ int type;
+ int block_count;
+ uint32_t control_bytes;
+ uint32_t total_bytes;
+ const uchar *data;
+ uint32_t length;
+ std::vector<SonyArw6PacketRecord> records;
+};
+
+static uint32_t sony_arw6_stream_payload_length(const uchar *stream,
+ uint32_t stream_size)
+{
+ sony_arw6_require(stream_size >= 0x80);
+ uint32_t payload = 0;
+ const int offs[5] = {0, 3, 6, 9, 12};
+ for (int g = 0; g < 5; g++)
+ payload +=
+ ((sony_arw6_be32(stream + 0x10 + offs[g]) >> 4) & 0x0ffffff0);
+ sony_arw6_require(payload <= stream_size - 0x80);
+ return 0x80 + payload;
+}
+
+static bool sony_arw6_parse_stream_header(const uchar *stream,
+ uint32_t stream_size,
+ SonyArw6StreamInfo &info)
+{
+ if (stream_size < 0x80 ||
+ (memcmp(stream, "A000", 4) && memcmp(stream, "0000", 4)))
+ return false;
+ const uint16_t word_c = sony_arw6_be16(stream + 0x0c);
+ const uint16_t word_e = sony_arw6_be16(stream + 0x0e);
+ const int decoded_bits = (word_c >> 4) & 0x3f;
+ const int components = word_e >> 13;
+ const int mode = (word_e >> 10) & 0x03;
+ if (decoded_bits != 16 || components != 3 || mode != 3)
+ return false;
+ info.coded_width = sony_arw6_be16(stream + 8);
+ info.coded_half_height = sony_arw6_be16(stream + 0x0a);
+ info.logical_height = info.coded_half_height * 2;
+ if (info.coded_width <= 0 || info.coded_half_height <= 0 ||
+ (info.coded_width & 15))
+ return false;
+ return true;
+}
+
+static std::vector<SonyArw6StreamInfo>
+sony_arw6_find_streams(const std::vector<uchar> &strip, int full_width,
+ int full_height)
+{
+ std::vector<SonyArw6StreamInfo> streams;
+ if (full_width <= 0 || full_height <= 0)
+ return streams;
+ const uint32_t strip_size = uint32_t(strip.size());
+ const uchar *base = strip_size ? &strip[0] : 0;
+ if (!base || strip_size < SONY_ARW6_STREAM_OFFSET + 0x80)
+ return streams;
+
+ const uint32_t count = sony_arw6_le32(base);
+ if (count >= 1 && count <= 16)
+ {
+ for (uint32_t index = 0; index < count; index++)
+ {
+ const uint32_t entry = 0x08 + index * 0x18;
+ if (entry + 0x18 > strip_size)
+ {
+ streams.clear();
+ break;
+ }
+ const uint32_t table_offset = sony_arw6_le32(base + entry);
+ const int tile_x = int(sony_arw6_le32(base + entry + 0x08));
+ const int tile_y = int(sony_arw6_le32(base + entry + 0x0c));
+ const int entry_tile_w = int(sony_arw6_le32(base + entry + 0x10));
+ const int entry_tile_h = int(sony_arw6_le32(base + entry + 0x14));
+ const uint32_t start = table_offset ? table_offset : SONY_ARW6_STREAM_OFFSET;
+ if (start > strip_size - 0x80)
+ {
+ streams.clear();
+ break;
+ }
+ const uint32_t search_end =
+ std::min(strip_size - 0x80,
+ start > UINT32_MAX - uint32_t(0x1000)
+ ? UINT32_MAX
+ : start + uint32_t(0x1000));
+ bool found = false;
+ SonyArw6StreamInfo info;
+ for (uint32_t candidate = start; candidate <= search_end;
+ candidate += 0x10)
+ {
+ if (!sony_arw6_parse_stream_header(base + candidate,
+ strip_size - candidate, info))
+ continue;
+ uint32_t length =
+ sony_arw6_stream_payload_length(base + candidate,
+ strip_size - candidate);
+ if (length <= 0x80 || candidate + length > strip_size)
+ continue;
+ info.index = int(index);
+ info.offset = candidate;
+ info.length = length;
+ info.tile_x = tile_x;
+ info.tile_y = tile_y;
+ info.tile_w = entry_tile_w ? entry_tile_w : info.coded_width;
+ info.tile_h = entry_tile_h ? entry_tile_h : info.logical_height;
+ if (info.tile_x < 0 || info.tile_y < 0 ||
+ info.tile_w != info.coded_width ||
+ info.tile_h != info.logical_height ||
+ info.tile_x > full_width - info.tile_w ||
+ info.tile_y > full_height - info.tile_h)
+ continue;
+ streams.push_back(info);
+ found = true;
+ break;
+ }
+ if (!found)
+ {
+ streams.clear();
+ break;
+ }
+ }
+ if (streams.size() == count)
+ return streams;
+ }
+
+ SonyArw6StreamInfo info;
+ if (sony_arw6_parse_stream_header(base + SONY_ARW6_STREAM_OFFSET,
+ strip_size - SONY_ARW6_STREAM_OFFSET,
+ info))
+ {
+ info.index = 0;
+ info.offset = SONY_ARW6_STREAM_OFFSET;
+ info.length =
+ sony_arw6_stream_payload_length(base + info.offset,
+ strip_size - info.offset);
+ info.tile_x = 0;
+ info.tile_y = 0;
+ info.tile_w = info.coded_width;
+ info.tile_h = info.logical_height;
+ if (info.coded_width == full_width && info.logical_height == full_height)
+ streams.push_back(info);
+ }
+ return streams;
+}
+
+class SonyArw6HeaderBits
+{
+ const uchar *data_;
+ uint32_t size_;
+ uint32_t bitpos_;
+
+public:
+ SonyArw6HeaderBits(const uchar *data, uint32_t size)
+ : data_(data), size_(size), bitpos_(0)
+ {
+ }
+
+ uint32_t read(int nbits)
+ {
+ sony_arw6_require(nbits >= 0 && nbits <= 32);
+ sony_arw6_require(uint64_t(bitpos_) + uint32_t(nbits) <=
+ uint64_t(size_) * 8U);
+ uint32_t out = 0;
+ for (int i = 0; i < nbits; i++)
+ {
+ const uchar byte = data_[bitpos_ >> 3];
+ const uint32_t bit = (byte >> (7 - (bitpos_ & 7))) & 1;
+ out = (out << 1) | bit;
+ bitpos_++;
+ }
+ return out;
+ }
+};
+
+class SonyArw6NativeBits
+{
+ const uchar *data_;
+ uint32_t size_;
+ int64_t ptr_;
+ uint64_t cur_;
+ int bit_;
+ int words_left_;
+
+public:
+ int status;
+
+ SonyArw6NativeBits(const uchar *packet, uint32_t packet_len,
+ uint32_t payload_offset, uint32_t byte_length)
+ : data_(packet), size_(packet_len), ptr_(int64_t(payload_offset) - 8),
+ cur_(0), bit_(0),
+ words_left_(((((int)byte_length + 7) / 8) + 1) & ~1), status(0)
+ {
+ }
+
+ void load_next_word()
+ {
+ words_left_--;
+ if (words_left_ < 0)
+ {
+ status = 2;
+ return;
+ }
+ ptr_ += 8;
+ uint64_t x = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ x <<= 8;
+ const int64_t pos = ptr_ + i;
+ if (pos >= 0 && pos < int64_t(size_))
+ x |= data_[pos];
+ }
+ cur_ = x;
+ bit_ = 64;
+ }
+
+ uint32_t read_bits(int nbits)
+ {
+ sony_arw6_require(nbits >= 0 && nbits <= 32);
+ uint32_t out = 0;
+ int remaining = nbits;
+ while (remaining > 0)
+ {
+ if (bit_ <= 0)
+ {
+ load_next_word();
+ if (status)
+ return out << remaining;
+ }
+ const int take = std::min(remaining, bit_);
+ bit_ -= take;
+ out = (out << take) |
+ uint32_t((cur_ >> bit_) & ((uint64_t(1) << take) - 1));
+ remaining -= take;
+ }
+ return out;
+ }
+
+ int read_unary_zeros_plus_one()
+ {
+ int zeros = 0;
+ while (!status)
+ {
+ const uint32_t bit = read_bits(1);
+ if (status)
+ break;
+ if (bit)
+ return zeros + 1;
+ zeros++;
+ }
+ return zeros + 1;
+ }
+};
+
+static int sony_arw6_update_width(SonyArw6NativeBits &br, int wstate)
+{
+ if (br.read_bits(1) == 0 || br.status)
+ return wstate;
+ if (br.read_bits(1) == 0 || br.status)
+ return wstate + br.read_unary_zeros_plus_one();
+
+ for (int zeros = 0; zeros < std::max(0, wstate - 1); zeros++)
+ {
+ if (br.read_bits(1))
+ return wstate - (zeros + 1);
+ }
+ return 0;
+}
+
+static int sony_arw6_read_zero_run(SonyArw6NativeBits &br, int remaining)
+{
+ if (remaining <= 1)
+ return remaining;
+ int max_prefix = 0;
+ for (int x = remaining - 1; x; x >>= 1)
+ max_prefix++;
+ int zeros = 0;
+ while (zeros < max_prefix)
+ {
+ if (br.read_bits(1))
+ break;
+ if (br.status)
+ return remaining;
+ zeros++;
+ }
+ if (zeros >= max_prefix)
+ return remaining;
+ const int base = 1 << zeros;
+ if (base >= remaining)
+ return remaining;
+ const int extra = zeros ? int(br.read_bits(zeros)) : 0;
+ return std::min(base + extra, remaining);
+}
+
+static void sony_arw6_decode_coeff_group(SonyArw6NativeBits &br, int nbits,
+ int shift, int32_t vals[4])
+{
+ for (int i = 0; i < 4; i++)
+ {
+ uint32_t x = nbits > 0 ? br.read_bits(nbits) : 0;
+ int32_t v = int32_t(x);
+ if (shift > 0 && x > 0)
+ v = int32_t(((uint64_t(2) * x + 1) << (shift - 1)) - (x & 1));
+ vals[i] = v;
+ }
+}
+
+static void sony_arw6_apply_signs(SonyArw6NativeBits &br, int32_t vals[4])
+{
+ for (int i = 0; i < 4; i++)
+ if (vals[i] > 0)
+ {
+ const uint32_t bit = br.read_bits(1);
+ vals[i] = vals[i] - 2 * vals[i] * int32_t(bit);
+ }
+}
+
+static void sony_arw6_decode_component(SonyArw6NativeBits &br, int groups,
+ int shift, int32_t *dst, int row_width)
+{
+ int width_state = sony_arw6_update_width(br, 0);
+ int gi = 0;
+ int out = 0;
+ while (gi < groups)
+ {
+ if (br.status || width_state > 0x13)
+ {
+ br.status = br.status ? br.status : 1;
+ while (out < row_width)
+ dst[out++] = 0;
+ return;
+ }
+ if (width_state == 0)
+ {
+ const int run = sony_arw6_read_zero_run(br, groups - gi);
+ for (int r = 0; r < run; r++)
+ for (int k = 0; k < 4 && out < row_width; k++)
+ dst[out++] = 0;
+ gi += run;
+ if (gi >= groups)
+ break;
+ width_state = br.read_unary_zeros_plus_one();
+ continue;
+ }
+
+ int32_t vals[4];
+ sony_arw6_decode_coeff_group(br, width_state, shift, vals);
+ const int next_width =
+ gi + 1 < groups ? sony_arw6_update_width(br, width_state) : width_state;
+ sony_arw6_apply_signs(br, vals);
+ for (int k = 0; k < 4 && out < row_width; k++)
+ dst[out++] = vals[k];
+ width_state = next_width;
+ gi++;
+ }
+ while (out < row_width)
+ dst[out++] = 0;
+}
+
+static int sony_arw6_row_multiplier(int group)
+{
+ if (group == 4)
+ return 8;
+ if (group == 0)
+ return 1;
+ return 1 << (group - 1);
+}
+
+static int sony_arw6_infer_packet_width(int group, int packet_type,
+ int mosaic_width)
+{
+ sony_arw6_require(mosaic_width > 0 && (mosaic_width & 15) == 0);
+ if (packet_type == 1)
+ return group == 4 ? mosaic_width / 2 : mosaic_width / 16;
+ if (packet_type == 3 && group >= 1 && group <= 3)
+ return mosaic_width / (1 << (5 - group));
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+}
+
+static int sony_arw6_expected_packet_rows(int group, int coded_height)
+{
+ sony_arw6_require(group >= 0 && group <= 4);
+ sony_arw6_require(coded_height > 0 && coded_height <= 0x7fff);
+ const int padded_height = sony_arw6_align_up(coded_height, 16);
+ return (padded_height / 16 + 1) * sony_arw6_row_multiplier(group);
+}
+
+static std::vector<SonyArw6DirectoryEntry>
+sony_arw6_parse_directory(const uchar *stream, uint32_t stream_size)
+{
+ sony_arw6_require(stream_size >= 0x80);
+ std::vector<SonyArw6DirectoryEntry> entries;
+ uint32_t group_lengths[5];
+ const int offs[5] = {0, 3, 6, 9, 12};
+ for (int g = 0; g < 5; g++)
+ group_lengths[g] =
+ ((sony_arw6_be32(stream + 0x10 + offs[g]) >> 4) & 0x0ffffff0);
+
+ uint32_t pos = 0x30;
+ uint32_t base = 0;
+ for (int group = 0; group < 5; group++)
+ {
+ sony_arw6_require(pos + 0x10 <= stream_size);
+ const int n_entries = stream[pos] & 0x0f;
+ sony_arw6_require(n_entries >= 0 && n_entries <= 9);
+ uint32_t values[9] = {0};
+ for (int i = 0; i < 5; i++)
+ values[i] = (sony_arw6_be32(stream + pos + offs[i]) & 0x00ffffff) << 4;
+ uint32_t consumed = 0x10;
+ if (n_entries >= 5)
+ {
+ sony_arw6_require(pos + 0x20 <= stream_size);
+ for (int i = 0; i < 4; i++)
+ values[5 + i] =
+ (sony_arw6_be32(stream + pos + 0x10 + offs[i]) & 0x00ffffff)
+ << 4;
+ consumed = 0x20;
+ }
+
+ uint32_t local = 0;
+ for (int index = 0; index < n_entries; index++)
+ {
+ SonyArw6DirectoryEntry e;
+ e.group = group;
+ e.index = index;
+ sony_arw6_require(base <= UINT32_MAX - local &&
+ 0x80 <= UINT32_MAX - base - local);
+ e.start = 0x80 + base + local;
+ e.length = values[index];
+ sony_arw6_require(e.start <= stream_size &&
+ e.length <= stream_size - e.start);
+ entries.push_back(e);
+ sony_arw6_require(local <= UINT32_MAX - e.length);
+ local += e.length;
+ }
+ sony_arw6_require(local <= group_lengths[group]);
+ sony_arw6_require(base <= UINT32_MAX - group_lengths[group]);
+ base += group_lengths[group];
+ pos += consumed;
+ }
+ return entries;
+}
+
+static SonyArw6DirectoryEntry
+sony_arw6_find_entry(const std::vector<SonyArw6DirectoryEntry> &entries,
+ int group, int index)
+{
+ for (size_t i = 0; i < entries.size(); i++)
+ if (entries[i].group == group && entries[i].index == index)
+ return entries[i];
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+}
+
+static SonyArw6Packet sony_arw6_parse_packet(const uchar *data, uint32_t length)
+{
+ sony_arw6_require(length >= 16);
+ SonyArw6HeaderBits br(data, length);
+ const uint32_t control_count = br.read(16);
+ const uint32_t extra_count = br.read(24);
+ const uint32_t tag4 = br.read(4);
+ const uint32_t reserved4 = br.read(4);
+ const uint32_t type2 = br.read(2);
+ const uint32_t control_words = br.read(6);
+ const uint32_t block_count = br.read(16);
+ const uint32_t width_marker = br.read(8);
+ const uint32_t reserved8 = br.read(8);
+ for (int i = 0; i < 5; i++)
+ sony_arw6_require(br.read(8) == 0);
+
+ sony_arw6_require(tag4 == 4 && reserved4 == 0 && control_words == 0);
+ sony_arw6_require(type2 == 1 || type2 == 3);
+ sony_arw6_require(block_count > 0 && block_count <= 30000);
+ sony_arw6_require(width_marker == 0x10 && reserved8 == 0);
+
+ SonyArw6Packet packet;
+ packet.type = int(type2);
+ packet.block_count = int(block_count);
+ const uint64_t control_bytes = (uint64_t(control_count) + 1U) << 4;
+ const uint64_t total_bytes =
+ (uint64_t(control_count) + 1U + extra_count) << 4;
+ sony_arw6_require(control_bytes <= UINT32_MAX &&
+ total_bytes <= UINT32_MAX);
+ packet.control_bytes = uint32_t(control_bytes);
+ packet.total_bytes = uint32_t(total_bytes);
+ packet.data = data;
+ packet.length = length;
+ sony_arw6_require(packet.total_bytes == length);
+ sony_arw6_require(packet.control_bytes <= length);
+
+ uint32_t cursor = packet.control_bytes;
+ packet.records.reserve(block_count);
+ for (uint32_t i = 0; i < block_count; i++)
+ {
+ SonyArw6PacketRecord rec;
+ rec.byte_length = br.read(16);
+ memset(rec.selectors, 0, sizeof(rec.selectors));
+ for (uint32_t j = 0; j < type2; j++)
+ rec.selectors[j] = uchar(br.read(4));
+ rec.payload_offset = cursor;
+ sony_arw6_require(rec.byte_length <= length &&
+ cursor <= length - rec.byte_length);
+ cursor += rec.byte_length;
+ packet.records.push_back(rec);
+ }
+ sony_arw6_require(cursor <= packet.total_bytes);
+ return packet;
+}
+
+static std::vector<SonyArw6Plane>
+sony_arw6_decode_packet_arrays(const uchar *stream, uint32_t stream_size,
+ const std::vector<SonyArw6DirectoryEntry> &dir,
+ int mosaic_width, int coded_height, int group,
+ int index)
+{
+ const SonyArw6DirectoryEntry e = sony_arw6_find_entry(dir, group, index);
+ const SonyArw6Packet p = sony_arw6_parse_packet(stream + e.start, e.length);
+ const int components = p.type == 1 ? 1 : 3;
+ const int row_width = sony_arw6_infer_packet_width(group, p.type, mosaic_width);
+ const int row_multiplier = sony_arw6_row_multiplier(group);
+ const int rows = p.block_count * row_multiplier;
+ const int expected_rows = sony_arw6_expected_packet_rows(group, coded_height);
+ const int groups_per_row = (row_width + 3) / 4;
+ sony_arw6_require(row_width > 0 && groups_per_row > 0 && rows > 0);
+ if (rows != expected_rows)
+ sony_arw6_require((coded_height & 15) &&
+ expected_rows - rows == row_multiplier);
+ sony_arw6_require(size_t(p.block_count) <=
+ (stream_size / 16U + 1U)); /* weak corruption guard */
+
+ std::vector<SonyArw6Plane> planes;
+ planes.reserve(components);
+ for (int c = 0; c < components; c++)
+ planes.push_back(SonyArw6Plane(expected_rows, row_width));
+
+ for (int ri = 0; ri < p.block_count; ri++)
+ {
+ const SonyArw6PacketRecord &rec = p.records[ri];
+ SonyArw6NativeBits bits(p.data, p.length, rec.payload_offset,
+ rec.byte_length);
+ for (int ci = 0; ci < components; ci++)
+ {
+ const int shift = ci < p.type ? rec.selectors[ci] : 0;
+ for (int rm = 0; rm < row_multiplier; rm++)
+ {
+ int32_t *dst = planes[ci].row(ri * row_multiplier + rm);
+ if (rec.byte_length <= 0)
+ memset(dst, 0, sizeof(int32_t) * size_t(row_width));
+ else
+ sony_arw6_decode_component(bits, groups_per_row, shift, dst, row_width);
+ }
+ }
+ }
+ return planes;
+}
+
+static SonyArw6Plane sony_arw6_integrate_type1(const SonyArw6Plane &coeffs,
+ int rows, int dc_offset)
+{
+ sony_arw6_require(rows > 0 && rows <= coeffs.rows);
+ SonyArw6Plane out(rows, coeffs.cols);
+ for (int y = 0; y < rows; y++)
+ {
+ int32_t acc = sony_arw6_sign16(coeffs.at(y, 0)) * 2;
+ out.at(y, 0) = acc / 2 + dc_offset;
+ for (int x = 1; x < coeffs.cols; x++)
+ {
+ acc += sony_arw6_sign16(coeffs.at(y, x)) * 2;
+ out.at(y, x) = acc / 2 + dc_offset;
+ }
+ }
+ return out;
+}
+
+static SonyArw6Plane sony_arw6_head_rows(const SonyArw6Plane &src, int rows)
+{
+ sony_arw6_require(rows >= 0 && rows <= src.rows);
+ SonyArw6Plane out(rows, src.cols);
+ if (rows)
+ memcpy(&out.data[0], &src.data[0],
+ sizeof(int32_t) * size_t(rows) * size_t(src.cols));
+ return out;
+}
+
+static SonyArw6Plane sony_arw6_inv53_axis0(const SonyArw6Plane &low,
+ const SonyArw6Plane &high)
+{
+ sony_arw6_require(low.rows == high.rows && low.cols == high.cols);
+ SonyArw6Plane lo2(low.rows, low.cols);
+ for (int y = 0; y < low.rows; y++)
+ for (int x = 0; x < low.cols; x++)
+ {
+ const int32_t hp = high.at(y ? y - 1 : 0, x);
+ const int32_t hc = high.at(y, x);
+ lo2.at(y, x) = low.at(y, x) - sony_arw6_floor_shift(hp + hc + 2, 2);
+ }
+
+ SonyArw6Plane out(low.rows * 2, low.cols);
+ for (int y = 0; y < low.rows; y++)
+ for (int x = 0; x < low.cols; x++)
+ {
+ const int32_t ln = lo2.at(y + 1 < low.rows ? y + 1 : y, x);
+ const int32_t hi2 =
+ high.at(y, x) + sony_arw6_floor_shift(lo2.at(y, x) + ln, 1);
+ out.at(y * 2, x) = lo2.at(y, x);
+ out.at(y * 2 + 1, x) = hi2;
+ }
+ return out;
+}
+
+static SonyArw6Plane sony_arw6_inv53_axis1(const SonyArw6Plane &low,
+ const SonyArw6Plane &high)
+{
+ sony_arw6_require(low.rows == high.rows && low.cols == high.cols);
+ SonyArw6Plane lo2(low.rows, low.cols);
+ for (int y = 0; y < low.rows; y++)
+ for (int x = 0; x < low.cols; x++)
+ {
+ const int32_t hp = high.at(y, x ? x - 1 : 0);
+ const int32_t hc = high.at(y, x);
+ lo2.at(y, x) = low.at(y, x) - sony_arw6_floor_shift(hp + hc + 2, 2);
+ }
+
+ SonyArw6Plane out(low.rows, low.cols * 2);
+ for (int y = 0; y < low.rows; y++)
+ for (int x = 0; x < low.cols; x++)
+ {
+ const int32_t ln = lo2.at(y, x + 1 < low.cols ? x + 1 : x);
+ const int32_t hi2 =
+ high.at(y, x) + sony_arw6_floor_shift(lo2.at(y, x) + ln, 1);
+ out.at(y, x * 2) = lo2.at(y, x);
+ out.at(y, x * 2 + 1) = hi2;
+ }
+ return out;
+}
+
+static SonyArw6Plane sony_arw6_inv53_axis0_high_leading(
+ const SonyArw6Plane &low, const SonyArw6Plane &high)
+{
+ sony_arw6_require(low.cols == high.cols);
+ sony_arw6_require(high.rows == low.rows || high.rows == low.rows + 1);
+ SonyArw6Plane lo2(low.rows, low.cols);
+ SonyArw6Plane hi2(high.rows, high.cols);
+
+ if (high.rows == low.rows + 1)
+ {
+ for (int y = 0; y < low.rows; y++)
+ for (int x = 0; x < low.cols; x++)
+ lo2.at(y, x) =
+ low.at(y, x) -
+ sony_arw6_floor_shift(high.at(y, x) + high.at(y + 1, x) + 2, 2);
+
+ for (int x = 0; x < high.cols; x++)
+ {
+ hi2.at(0, x) = high.at(0, x) + lo2.at(0, x);
+ hi2.at(high.rows - 1, x) = high.at(high.rows - 1, x) +
+ lo2.at(low.rows - 1, x);
+ }
+ for (int y = 1; y < high.rows - 1; y++)
+ for (int x = 0; x < high.cols; x++)
+ hi2.at(y, x) = high.at(y, x) +
+ sony_arw6_floor_shift(lo2.at(y - 1, x) +
+ lo2.at(y, x),
+ 1);
+
+ SonyArw6Plane out(low.rows * 2 + 1, low.cols);
+ for (int y = 0; y < low.rows; y++)
+ {
+ memcpy(out.row(y * 2), hi2.row(y), sizeof(int32_t) * size_t(low.cols));
+ memcpy(out.row(y * 2 + 1), lo2.row(y),
+ sizeof(int32_t) * size_t(low.cols));
+ }
+ memcpy(out.row(out.rows - 1), hi2.row(hi2.rows - 1),
+ sizeof(int32_t) * size_t(low.cols));
+ return out;
+ }
+
+ for (int y = 0; y < low.rows; y++)
+ for (int x = 0; x < low.cols; x++)
+ {
+ const int next_y = y + 1 < high.rows ? y + 1 : y;
+ lo2.at(y, x) =
+ low.at(y, x) -
+ sony_arw6_floor_shift(high.at(y, x) + high.at(next_y, x) + 2, 2);
+ }
+ for (int x = 0; x < high.cols; x++)
+ hi2.at(0, x) = high.at(0, x) + lo2.at(0, x);
+ for (int y = 1; y < high.rows; y++)
+ for (int x = 0; x < high.cols; x++)
+ hi2.at(y, x) =
+ high.at(y, x) +
+ sony_arw6_floor_shift(lo2.at(y - 1, x) + lo2.at(y, x), 1);
+
+ SonyArw6Plane out(low.rows * 2, low.cols);
+ for (int y = 0; y < low.rows; y++)
+ {
+ memcpy(out.row(y * 2), hi2.row(y), sizeof(int32_t) * size_t(low.cols));
+ memcpy(out.row(y * 2 + 1), lo2.row(y),
+ sizeof(int32_t) * size_t(low.cols));
+ }
+ return out;
+}
+
+static SonyArw6Plane sony_arw6_synthesize_level(const SonyArw6Plane &ll,
+ const SonyArw6Plane &sub0,
+ const SonyArw6Plane &sub1,
+ const SonyArw6Plane &sub2)
+{
+ const int h = ll.rows;
+ const int w = ll.cols;
+ sony_arw6_require(sub0.cols == w && sub1.cols == w && sub2.cols == w);
+ sony_arw6_require(sub0.rows >= h + 1 && sub1.rows >= h + 1 &&
+ sub2.rows >= h + 1);
+ SonyArw6Plane lh(h, w), hh(h, w);
+ for (int y = 0; y < h - 1; y++)
+ for (int x = 0; x < w; x++)
+ {
+ lh.at(y, x) = sub1.at(y + 1, x);
+ hh.at(y, x) = sub2.at(y + 1, x);
+ }
+ for (int x = 0; x < w; x++)
+ {
+ lh.at(h - 1, x) = sub0.at(h, x);
+ hh.at(h - 1, x) = sub1.at(h, x);
+ }
+ SonyArw6Plane low_horizontal = sony_arw6_inv53_axis0(ll, lh);
+ SonyArw6Plane high_horizontal =
+ sony_arw6_inv53_axis0(sony_arw6_head_rows(sub0, h), hh);
+ return sony_arw6_inv53_axis1(low_horizontal, high_horizontal);
+}
+
+static SonyArw6Plane sony_arw6_synthesize_guard_group1(
+ const SonyArw6Plane &ll, const SonyArw6Plane &sub0,
+ const SonyArw6Plane &sub1, const SonyArw6Plane &sub2)
+{
+ const int h = ll.rows;
+ const int w = ll.cols;
+ sony_arw6_require(sub0.cols == w && sub1.cols == w && sub2.cols == w);
+ sony_arw6_require(sub0.rows >= h + 2 && sub1.rows >= h + 2 &&
+ sub2.rows >= h + 2);
+
+ SonyArw6Plane lh(h + 1, w), hh(h + 1, w), hl(h, w);
+ for (int y = 0; y < h; y++)
+ for (int x = 0; x < w; x++)
+ {
+ hl.at(y, x) = sub0.at(y + 1, x);
+ lh.at(y, x) = sub1.at(y + 1, x);
+ hh.at(y, x) = sub2.at(y + 1, x);
+ }
+ for (int x = 0; x < w; x++)
+ {
+ lh.at(h, x) = sub0.at(h + 1, x);
+ hh.at(h, x) = sub1.at(h + 1, x);
+ }
+
+ SonyArw6Plane low_horizontal =
+ sony_arw6_inv53_axis0_high_leading(ll, lh);
+ SonyArw6Plane high_horizontal =
+ sony_arw6_inv53_axis0_high_leading(hl, hh);
+ return sony_arw6_inv53_axis1(low_horizontal, high_horizontal);
+}
+
+static SonyArw6Plane sony_arw6_synthesize_guard_group2(
+ const SonyArw6Plane &ll, const SonyArw6Plane &sub0,
+ const SonyArw6Plane &sub1, const SonyArw6Plane &sub2,
+ bool odd_edge_mode)
+{
+ const int h = ll.rows;
+ const int w = ll.cols;
+ sony_arw6_require(sub0.cols == w && sub1.cols == w && sub2.cols == w);
+ sony_arw6_require(sub0.rows >= h + 3 && sub1.rows >= h + 1 &&
+ sub2.rows >= h + 1);
+
+ SonyArw6Plane hl(h, w), lh(h, w), hh(h, w);
+ for (int x = 0; x < w; x++)
+ {
+ lh.at(0, x) = sub0.at(0, x);
+ hh.at(0, x) = sony_arw6_edge_detail(sub0.at(1, x), odd_edge_mode);
+ }
+ for (int y = 0; y < h; y++)
+ for (int x = 0; x < w; x++)
+ hl.at(y, x) = sub0.at(y + 2, x);
+ for (int y = 1; y < h; y++)
+ for (int x = 0; x < w; x++)
+ {
+ lh.at(y, x) = sub1.at(y + 1, x);
+ hh.at(y, x) = sub2.at(y + 1, x);
+ }
+
+ SonyArw6Plane low_horizontal =
+ sony_arw6_inv53_axis0_high_leading(ll, lh);
+ SonyArw6Plane high_horizontal =
+ sony_arw6_inv53_axis0_high_leading(hl, hh);
+ return sony_arw6_inv53_axis1(low_horizontal, high_horizontal);
+}
+
+static SonyArw6Plane sony_arw6_synthesize_guard_group3(
+ const SonyArw6Plane &ll, const SonyArw6Plane &sub0,
+ const SonyArw6Plane &sub1, const SonyArw6Plane &sub2,
+ bool odd_edge_mode)
+{
+ const int h = ll.rows;
+ const int w = ll.cols;
+ sony_arw6_require(sub0.cols == w && sub1.cols == w && sub2.cols == w);
+ sony_arw6_require(sub0.rows >= h + 5 && sub1.rows >= h + 2 &&
+ sub2.rows >= h + 2);
+
+ SonyArw6Plane hl(h, w), lh(h, w), hh(h, w);
+ for (int x = 0; x < w; x++)
+ {
+ hl.at(0, x) = sub0.at(0, x);
+ lh.at(0, x) = sub0.at(1, x);
+ hh.at(0, x) = sony_arw6_edge_detail(sub0.at(2, x), odd_edge_mode);
+ lh.at(h - 1, x) = sub0.at(h + 3, x);
+ hh.at(h - 1, x) =
+ sony_arw6_edge_detail(sub0.at(h + 4, x), odd_edge_mode);
+ }
+ for (int y = 1; y < h; y++)
+ for (int x = 0; x < w; x++)
+ hl.at(y, x) = sub0.at(y + 3, x);
+ for (int y = 1; y < h - 1; y++)
+ for (int x = 0; x < w; x++)
+ {
+ lh.at(y, x) = sub1.at(y + 3, x);
+ hh.at(y, x) = sub2.at(y + 3, x);
+ }
+
+ SonyArw6Plane low_horizontal = sony_arw6_inv53_axis0(ll, lh);
+ SonyArw6Plane high_horizontal = sony_arw6_inv53_axis0(hl, hh);
+ return sony_arw6_inv53_axis1(low_horizontal, high_horizontal);
+}
+
+static SonyArw6Plane sony_arw6_synthesize_level_stride(
+ const SonyArw6Plane &ll, const SonyArw6Plane &sub0,
+ const SonyArw6Plane &sub1, const SonyArw6Plane &sub2, int edge_rows,
+ bool odd_edge_mode)
+{
+ if (edge_rows == 0)
+ return sony_arw6_synthesize_level(ll, sub0, sub1, sub2);
+
+ const int h = ll.rows;
+ const int w = ll.cols;
+ sony_arw6_require(sub0.cols == w && sub1.cols == w && sub2.cols == w);
+ sony_arw6_require(sub0.rows >= h + edge_rows * 2 &&
+ sub1.rows >= h + edge_rows &&
+ sub2.rows >= h);
+
+ SonyArw6Plane hl(h, w), lh(h, w), hh(h, w);
+ for (int y = 0; y < edge_rows; y++)
+ for (int x = 0; x < w; x++)
+ {
+ hl.at(y, x) = sub0.at(y, x);
+ lh.at(y, x) = sub0.at(y + edge_rows, x);
+ hh.at(y, x) = sony_arw6_edge_detail(sub1.at(y, x), odd_edge_mode);
+ }
+ for (int y = edge_rows; y < h - edge_rows; y++)
+ for (int x = 0; x < w; x++)
+ {
+ hl.at(y, x) = sub0.at(y + edge_rows, x);
+ lh.at(y, x) = sub1.at(y + edge_rows, x);
+ hh.at(y, x) = sub2.at(y + edge_rows, x);
+ }
+ for (int y = h - edge_rows; y < h; y++)
+ {
+ const int k = y - (h - edge_rows);
+ for (int x = 0; x < w; x++)
+ {
+ hl.at(y, x) = sub0.at(h + k, x);
+ lh.at(y, x) = sub0.at(h + edge_rows + k, x);
+ hh.at(y, x) = sony_arw6_edge_detail(sub1.at(h + k, x), odd_edge_mode);
+ }
+ }
+
+ SonyArw6Plane low_horizontal = sony_arw6_inv53_axis0(ll, lh);
+ SonyArw6Plane high_horizontal = sony_arw6_inv53_axis0(hl, hh);
+ return sony_arw6_inv53_axis1(low_horizontal, high_horizontal);
+}
+
+static SonyArw6Plane sony_arw6_final_green(const SonyArw6Plane &ll,
+ const SonyArw6Plane &detail,
+ int top_rows)
+{
+ const int h = ll.rows;
+ const int w = ll.cols;
+ sony_arw6_require(top_rows >= 0 && top_rows <= 8);
+ sony_arw6_require(detail.cols == w &&
+ detail.rows >= 8 + std::max(0, h - top_rows));
+
+ SonyArw6Plane selected(h, w);
+ for (int y = 0; y < h; y++)
+ {
+ const int src_y = y < top_rows ? y : y + 8 - top_rows;
+ for (int x = 0; x < w; x++)
+ selected.at(y, x) = detail.at(src_y, x);
+ }
+
+ SonyArw6Plane odd_green(h, w);
+ for (int y = 0; y < h; y++)
+ {
+ const int prev_y = y ? y - 1 : y;
+ for (int x = 0; x < w; x++)
+ {
+ int32_t pred;
+ if (x + 1 < w)
+ pred = sony_arw6_floor_shift(
+ selected.at(y, x + 1) + selected.at(prev_y, x) +
+ selected.at(y, x) + selected.at(prev_y, x + 1),
+ 2);
+ else
+ pred = sony_arw6_floor_shift(
+ (selected.at(prev_y, x) + selected.at(y, x)) * 2, 2);
+ odd_green.at(y, x) =
+ sony_arw6_floor_shift(int64_t(2) * ll.at(y, x) - pred, 1);
+ }
+ }
+
+ SonyArw6Plane even_green(h, w);
+ for (int y = 0; y < h; y++)
+ {
+ const int next_y = y + 1 < h ? y + 1 : y;
+ even_green.at(y, 0) =
+ selected.at(y, 0) +
+ sony_arw6_floor_shift((odd_green.at(y, 0) + odd_green.at(next_y, 0)) *
+ int64_t(2),
+ 2);
+ for (int x = 1; x < w; x++)
+ even_green.at(y, x) =
+ selected.at(y, x) +
+ sony_arw6_floor_shift(odd_green.at(y, x - 1) +
+ odd_green.at(next_y, x - 1) +
+ odd_green.at(next_y, x) +
+ odd_green.at(y, x),
+ 2);
+ }
+
+ SonyArw6Plane out(h, w * 2);
+ for (int y = 0; y < h; y++)
+ for (int x = 0; x < w; x++)
+ {
+ out.at(y, x * 2) = even_green.at(y, x);
+ out.at(y, x * 2 + 1) = odd_green.at(y, x);
+ }
+ return out;
+}
+
+static inline ushort sony_arw6_sample_from_signed(int32_t x)
+{
+ int code = x + SONY_ARW6_INTERNAL_BIAS;
+ if (code < 0)
+ code = 0;
+ if (code > 4095)
+ code = 4095;
+ return sony_arw6_llvc3_lut_value(code);
+}
+
+static inline int32_t sony_arw6_clamp_signed_code(int32_t x)
+{
+ int code = x + SONY_ARW6_INTERNAL_BIAS;
+ if (code < 0)
+ code = 0;
+ if (code > 4095)
+ code = 4095;
+ return code - SONY_ARW6_INTERNAL_BIAS;
+}
+
+struct SonyArw6DecodedTile
+{
+ SonyArw6Plane green;
+ SonyArw6Plane red_residual;
+ SonyArw6Plane blue_residual;
+ SonyArw6Plane full_green;
+};
+
+static SonyArw6DecodedTile sony_arw6_decode_stream_tile(const uchar *stream,
+ uint32_t stream_size)
+{
+ SonyArw6StreamInfo header;
+ sony_arw6_require(sony_arw6_parse_stream_header(stream, stream_size, header));
+ const std::vector<SonyArw6DirectoryEntry> dir =
+ sony_arw6_parse_directory(stream, stream_size);
+ const int coded_height = header.logical_height;
+ sony_arw6_require(header.coded_width > 0 && coded_height > 0);
+ const int padded_height = sony_arw6_align_up(coded_height, 16);
+ const bool guarded_height = coded_height != padded_height;
+ const int low_rows = padded_height / 16;
+ const int low_start = guarded_height ? 1 : 0;
+ const int low_count = low_rows - low_start;
+
+ std::vector<SonyArw6Plane> g0 =
+ sony_arw6_decode_packet_arrays(stream, stream_size, dir,
+ header.coded_width, coded_height, 0, 0);
+ SonyArw6Plane green =
+ sony_arw6_integrate_type1(g0[0], low_start + low_count, 0);
+ if (low_start)
+ {
+ SonyArw6Plane cropped(low_count, green.cols);
+ for (int y = 0; y < low_count; y++)
+ memcpy(cropped.row(y), green.row(y + low_start),
+ sizeof(int32_t) * size_t(green.cols));
+ green = cropped;
+ }
+
+ std::vector<SonyArw6Plane> r0 =
+ sony_arw6_decode_packet_arrays(stream, stream_size, dir,
+ header.coded_width, coded_height, 0, 1);
+ SonyArw6Plane red_residual =
+ sony_arw6_integrate_type1(r0[0], low_start + low_count, 0);
+ if (low_start)
+ {
+ SonyArw6Plane cropped(low_count, red_residual.cols);
+ for (int y = 0; y < low_count; y++)
+ memcpy(cropped.row(y), red_residual.row(y + low_start),
+ sizeof(int32_t) * size_t(red_residual.cols));
+ red_residual = cropped;
+ }
+
+ std::vector<SonyArw6Plane> b0 =
+ sony_arw6_decode_packet_arrays(stream, stream_size, dir,
+ header.coded_width, coded_height, 0, 2);
+ SonyArw6Plane blue_residual =
+ sony_arw6_integrate_type1(b0[0], low_start + low_count, 0);
+ if (low_start)
+ {
+ SonyArw6Plane cropped(low_count, blue_residual.cols);
+ for (int y = 0; y < low_count; y++)
+ memcpy(cropped.row(y), blue_residual.row(y + low_start),
+ sizeof(int32_t) * size_t(blue_residual.cols));
+ blue_residual = cropped;
+ }
+
+ for (int group = 1; group <= 3; group++)
+ {
+ const int edge_rows = group == 1 ? 0 : (group == 2 ? 1 : 2);
+ const bool color_odd_edge = group == 3;
+
+ std::vector<SonyArw6Plane> planes =
+ sony_arw6_decode_packet_arrays(stream, stream_size, dir,
+ header.coded_width, coded_height, group,
+ 0);
+ if (guarded_height)
+ {
+ if (group == 1)
+ green = sony_arw6_synthesize_guard_group1(green, planes[0],
+ planes[1], planes[2]);
+ else if (group == 2)
+ green = sony_arw6_synthesize_guard_group2(green, planes[0],
+ planes[1], planes[2], false);
+ else
+ green = sony_arw6_synthesize_guard_group3(green, planes[0],
+ planes[1], planes[2], false);
+ }
+ else
+ green = sony_arw6_synthesize_level_stride(green, planes[0], planes[1],
+ planes[2], edge_rows, false);
+
+ planes = sony_arw6_decode_packet_arrays(stream, stream_size, dir,
+ header.coded_width, coded_height,
+ group, 1);
+ if (guarded_height)
+ {
+ if (group == 1)
+ red_residual = sony_arw6_synthesize_guard_group1(
+ red_residual, planes[0], planes[1], planes[2]);
+ else if (group == 2)
+ red_residual = sony_arw6_synthesize_guard_group2(
+ red_residual, planes[0], planes[1], planes[2], false);
+ else
+ red_residual = sony_arw6_synthesize_guard_group3(
+ red_residual, planes[0], planes[1], planes[2], color_odd_edge);
+ }
+ else
+ red_residual = sony_arw6_synthesize_level_stride(
+ red_residual, planes[0], planes[1], planes[2], edge_rows,
+ color_odd_edge);
+
+ planes = sony_arw6_decode_packet_arrays(stream, stream_size, dir,
+ header.coded_width, coded_height,
+ group, 2);
+ if (guarded_height)
+ {
+ if (group == 1)
+ blue_residual = sony_arw6_synthesize_guard_group1(
+ blue_residual, planes[0], planes[1], planes[2]);
+ else if (group == 2)
+ blue_residual = sony_arw6_synthesize_guard_group2(
+ blue_residual, planes[0], planes[1], planes[2], false);
+ else
+ blue_residual = sony_arw6_synthesize_guard_group3(
+ blue_residual, planes[0], planes[1], planes[2], color_odd_edge);
+ }
+ else
+ blue_residual = sony_arw6_synthesize_level_stride(
+ blue_residual, planes[0], planes[1], planes[2], edge_rows,
+ color_odd_edge);
+ }
+
+ std::vector<SonyArw6Plane> g4 =
+ sony_arw6_decode_packet_arrays(stream, stream_size, dir,
+ header.coded_width, coded_height, 4, 0);
+ SonyArw6Plane full_green =
+ sony_arw6_final_green(green, g4[0], guarded_height ? 2 : 4);
+
+ SonyArw6DecodedTile out;
+ out.green = green;
+ out.red_residual = red_residual;
+ out.blue_residual = blue_residual;
+ out.full_green = full_green;
+ return out;
+}
+
+} // namespace
+
+void LibRaw::sony_arw6_load_raw()
+{
+ if (raw_width <= 0 || raw_height <= 0 || (raw_width & 15) ||
+ (raw_height & 1))
+ throw LIBRAW_EXCEPTION_IO_BADFILE;
+ if (!raw_image)
+ throw LIBRAW_EXCEPTION_IO_BADFILE;
+ if (data_size < SONY_ARW6_STREAM_OFFSET + 0x80 ||
+ data_size > 1024LL * 1024LL * 1024LL)
+ throw LIBRAW_EXCEPTION_IO_CORRUPT;
+ if (data_size > INT64(imgdata.rawparams.max_raw_memory_mb) *
+ INT64(1024 * 1024))
+ throw LIBRAW_EXCEPTION_ALLOC;
+
+ std::vector<uchar> strip(size_t(data_size));
+ ifp->seek(data_offset, SEEK_SET);
+ const int readed = ifp->read(&strip[0], 1, size_t(data_size));
+ if (readed != data_size)
+ throw LIBRAW_EXCEPTION_IO_EOF;
+
+ const std::vector<SonyArw6StreamInfo> streams =
+ sony_arw6_find_streams(strip, raw_width, raw_height);
+ sony_arw6_require(!streams.empty());
+
+ INT64 max_tile_pixels = 0;
+ for (size_t si = 0; si < streams.size(); si++)
+ {
+ const SonyArw6StreamInfo &s = streams[si];
+ max_tile_pixels =
+ std::max(max_tile_pixels, INT64(s.coded_width) * s.logical_height);
+ }
+ const INT64 raw_bytes = INT64(raw_width) * raw_height *
+ INT64(sizeof(raw_image[0]));
+ const INT64 working_bytes =
+ raw_bytes + data_size +
+ max_tile_pixels * SONY_ARW6_WORKING_BYTES_PER_TILE_PIXEL;
+ if (working_bytes > sony_arw6_memory_limit_bytes(
+ imgdata.rawparams.max_raw_memory_mb))
+ throw LIBRAW_EXCEPTION_ALLOC;
+
+ for (size_t si = 0; si < streams.size(); si++)
+ {
+ checkCancel();
+ const SonyArw6StreamInfo &s = streams[si];
+ sony_arw6_require(s.offset <= strip.size() &&
+ s.length <= strip.size() - s.offset);
+ sony_arw6_require(s.tile_x >= 0 && s.tile_y >= 0 &&
+ s.tile_w == s.coded_width &&
+ s.tile_h == s.logical_height &&
+ s.tile_x + s.tile_w <= raw_width &&
+ s.tile_y + s.tile_h <= raw_height);
+
+ SonyArw6DecodedTile tile =
+ sony_arw6_decode_stream_tile(&strip[s.offset], s.length);
+
+ const int half_h = s.logical_height / 2;
+ const int half_w = s.coded_width / 2;
+ sony_arw6_require(tile.full_green.rows >= half_h &&
+ tile.full_green.cols == s.coded_width);
+ sony_arw6_require(tile.green.rows >= half_h &&
+ tile.green.cols == half_w);
+ sony_arw6_require(tile.red_residual.rows >= half_h &&
+ tile.red_residual.cols == half_w);
+ sony_arw6_require(tile.blue_residual.rows >= half_h &&
+ tile.blue_residual.cols == half_w);
+
+ for (int y = 0; y < half_h; y++)
+ {
+ checkCancel();
+ ushort *row0 =
+ raw_image + size_t(s.tile_y + y * 2) * raw_width + s.tile_x;
+ ushort *row1 =
+ raw_image + size_t(s.tile_y + y * 2 + 1) * raw_width + s.tile_x;
+ for (int x = 0; x < half_w; x++)
+ {
+ const int32_t g0 =
+ sony_arw6_clamp_signed_code(tile.full_green.at(y, x * 2));
+ const int32_t g1 =
+ sony_arw6_clamp_signed_code(tile.full_green.at(y, x * 2 + 1));
+ const int32_t gavg = sony_arw6_floor_shift(int64_t(g0) + g1, 1);
+ row0[x * 2] = sony_arw6_sample_from_signed(
+ gavg + 2 * tile.red_residual.at(y, x));
+ row0[x * 2 + 1] =
+ sony_arw6_sample_from_signed(tile.full_green.at(y, x * 2 + 1));
+ row1[x * 2] =
+ sony_arw6_sample_from_signed(tile.full_green.at(y, x * 2));
+ row1[x * 2 + 1] = sony_arw6_sample_from_signed(
+ gavg + 2 * tile.blue_residual.at(y, x));
+ }
+ }
+ }
+}
diff --git a/core/libs/rawengine/libraw/src/metadata/canon.cpp b/core/libs/rawengine/libraw/src/metadata/canon.cpp
index 5def57dfc4..f6007dcedc 100644
--- a/core/libs/rawengine/libraw/src/metadata/canon.cpp
+++ b/core/libs/rawengine/libraw/src/metadata/canon.cpp
@@ -131,6 +131,7 @@ void LibRaw::setCanonBodyFeatures(unsigned long long id)
(id == CanonID_EOS_R7)
|| (id == CanonID_EOS_R10)
|| (id == CanonID_EOS_R50)
+ || (id == CanonID_EOS_R50_V)
|| (id == CanonID_EOS_R100)
)
{
@@ -1308,7 +1309,7 @@ void LibRaw::parseCanonMakernotes(unsigned tag, unsigned type, unsigned len, uns
break;
case 3973: // R3; ColorDataSubVer: 34
- case 3778: // R6 Mark II, R7, R8, R10, R50; ColorDataSubVer: 48
+ case 3778: // R6 Mark II, R7, R8, R10, R50, R50 V; ColorDataSubVer: 48
imCanon.ColorDataVer = 11;
AsShot_Auto_MeasuredWB(0x0069);
diff --git a/core/libs/rawengine/libraw/src/metadata/identify.cpp b/core/libs/rawengine/libraw/src/metadata/identify.cpp
index 014488b8aa..3b967c8467 100644
--- a/core/libs/rawengine/libraw/src/metadata/identify.cpp
+++ b/core/libs/rawengine/libraw/src/metadata/identify.cpp
@@ -3139,7 +3139,7 @@ void LibRaw::identify_finetune_dcr(char head[64], INT64 fsize, INT64 flen)
/* need samples for lossy small/medium w/ APC crop*/
}
- else if ((unique_id == SonyID_ILCE_7M4)|| (unique_id == SonyID_ILCE_7CM2) || (unique_id == SonyID_ILME_FX2))
+ else if ((unique_id == SonyID_ILCE_7M4) || (unique_id == SonyID_ILCE_7CM2) || (unique_id == SonyID_ILME_FX2) || (unique_id == SonyID_ILCE_7M5))
{
if (raw_width == 7168 && raw_height == 5120)
{
diff --git a/core/libs/rawengine/libraw/src/metadata/normalize_model.cpp b/core/libs/rawengine/libraw/src/metadata/normalize_model.cpp
index c8b65acac9..23c69ec535 100644
--- a/core/libs/rawengine/libraw/src/metadata/normalize_model.cpp
+++ b/core/libs/rawengine/libraw/src/metadata/normalize_model.cpp
@@ -107,6 +107,7 @@ void LibRaw::GetNormalizedModel()
{ CanonID_EOS_R7, "EOS R7"},
{ CanonID_EOS_R10, "EOS R10"},
{ CanonID_EOS_M50_Mark_II, "EOS M50 Mark II"}, // M50m2, Kiss M2
+ { CanonID_EOS_R50_V, "EOS R50 V"},
{ CanonID_EOS_R50, "EOS R50"},
{ CanonID_EOS_R6m2, "EOS R6 Mark II"},
{ CanonID_EOS_R8, "EOS R8"},
@@ -399,6 +400,7 @@ void LibRaw::GetNormalizedModel()
{ SonyID_ILX_LR1, "ILX-LR1"},
{ SonyID_ZV_E10M2, "ZV-E10M2"},
{ SonyID_ILME_FX2, "ILME-FX2"},
+ { SonyID_ILCE_7M5, "ILCE-7M5"},
};
static const char *orig;
diff --git a/core/libs/rawengine/libraw/src/metadata/sony.cpp b/core/libs/rawengine/libraw/src/metadata/sony.cpp
index bdc36080f9..1b0c0837b4 100644
--- a/core/libs/rawengine/libraw/src/metadata/sony.cpp
+++ b/core/libs/rawengine/libraw/src/metadata/sony.cpp
@@ -364,6 +364,8 @@ void LibRaw::setSonyBodyFeatures(unsigned long long id) {
LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
{SonyID_ZV_E10M2, sbfILCE_DX,
LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
+ {SonyID_ILCE_7M5, sbfILCE_FF,
+ LIBRAW_SONY_Tag2010None, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff},
};
ilm.CamID = id;
int isPreProductionFW = 0;
@@ -454,6 +456,7 @@ void LibRaw::setSonyBodyFeatures(unsigned long long id) {
case SonyID_ILCE_7CR:
case SonyID_ILCE_7CM2:
case SonyID_ILCE_9M3:
+ case SonyID_ILCE_7M5:
case SonyID_ZV_E10M2:
imSony.group9050 = LIBRAW_SONY_Tag9050d;
break;
@@ -956,7 +959,7 @@ void LibRaw::process_Sony_0x9400(uchar *buf, ushort len, unsigned long long /*id
FORC4 s[c] = SonySubstitution[buf[0x1a + c]];
imSony.Sony0x9400_SequenceFileNumber = sget4(s);
- imSony.Sony0x9400_SequenceLength2 = SonySubstitution[buf[0x1e]]; // files
+ imSony.Sony0x9400_SequenceLength2 = SonySubstitution[buf[0x1e]]; // files //ilce-7m5 modifed here
}
else if ((bufx == 0x0c) && (len >= 0x1f)) // 0x9400 'b' version
diff --git a/core/libs/rawengine/libraw/src/metadata/tiff.cpp b/core/libs/rawengine/libraw/src/metadata/tiff.cpp
index c129cd3f3e..bad650531f 100644
--- a/core/libs/rawengine/libraw/src/metadata/tiff.cpp
+++ b/core/libs/rawengine/libraw/src/metadata/tiff.cpp
@@ -2074,6 +2074,17 @@ void LibRaw::apply_tiff()
if (raw >= 0 && !load_raw)
switch (tiff_compress)
{
+ case 32766:
+ if (!dng_version && !strncasecmp(make, "Sony", 4) &&
+ tiff_ifd[raw].phint == 32803 && tiff_ifd[raw].samples == 1 &&
+ (tiff_bps == 12 || tiff_bps == 14) && raw_width > 0 &&
+ raw_height > 0)
+ {
+ load_raw = &LibRaw::sony_arw6_load_raw;
+ tiff_bps = 14;
+ break;
+ }
+ break;
case 32767:
if (!dng_version &&
tiff_ifd[raw].bytes == INT64(raw_width) * INT64(raw_height))
diff --git a/core/libs/rawengine/libraw/src/tables/cameralist.cpp b/core/libs/rawengine/libraw/src/tables/cameralist.cpp
index 3478a77877..9492de9917 100644
--- a/core/libs/rawengine/libraw/src/tables/cameralist.cpp
+++ b/core/libs/rawengine/libraw/src/tables/cameralist.cpp
@@ -161,6 +161,7 @@ static const char *static_camera_list[] = {
"Canon EOS R7",
"Canon EOS R8",
"Canon EOS R10",
+ "Canon EOS R50 V",
"Canon EOS R50",
"Canon EOS R100",
"Canon EOS D30",
@@ -1183,6 +1184,7 @@ static const char *static_camera_list[] = {
"Sony ILCE-7M2 (A7 II)",
"Sony ILCE-7M3 (A7 III)",
"Sony ILCE-7M4 (A7 IV)",
+ "Sony ILCE-7M5 (A7 V)",
"Sony ILCE-7C (A7C)",
"Sony ILCE-7CR (A7CR)",
"Sony ILCE-7CM2 (A7C II)",
diff --git a/core/libs/rawengine/libraw/src/tables/colordata.cpp b/core/libs/rawengine/libraw/src/tables/colordata.cpp
index 8e04141dc7..3f6dc81ce0 100644
--- a/core/libs/rawengine/libraw/src/tables/colordata.cpp
+++ b/core/libs/rawengine/libraw/src/tables/colordata.cpp
@@ -147,6 +147,8 @@ int LibRaw::adobe_coeff(unsigned make_idx, const char *t_model,
{ 8608,-2097,-1178,-5425,13265,2383,-1149,2238,5680 } },
{ LIBRAW_CAMERAMAKER_Canon, "EOS R3", 0, 0,
{ 9423,-2839,-1195,-4532,12377,2415,-483,1374,5276 } },
+ { LIBRAW_CAMERAMAKER_Canon, "EOS R50 V", 0, 0,
+ { 9089, -1810, -1209, -4294, 12116, 2454, -498, 1862, 4923 } },
{ LIBRAW_CAMERAMAKER_Canon, "EOS R50", 0, 0,
{ 9269, -2012, -1107, -3990, 11762, 2527, -569, 2093, 4913 } },
{ LIBRAW_CAMERAMAKER_Canon, "EOS R100", 0, 0,
@@ -1770,7 +1772,9 @@ int LibRaw::adobe_coeff(unsigned make_idx, const char *t_model,
{ 7460,-2365,-588,-5687,13442,2474,-624,1156,6584 } },
{ LIBRAW_CAMERAMAKER_Sony, "ILCE-7C", 0, 0,
{ 7374,-2389,-551,-5435,13162,2519,-1006,1795,6552 } },
-
+
+ { LIBRAW_CAMERAMAKER_Sony, "ILCE-7M5", 0, 0,
+ { 9089, -3577, -787, -3563, 11326, 2557, -114, 928, 5904 } },
{ LIBRAW_CAMERAMAKER_Sony, "ILCE-7M4", 0, 0,
{ 7460,-2365,-588,-5687,13442,2474,-624,1156,6584 } },
{ LIBRAW_CAMERAMAKER_Sony, "ILCE-7M3", 0, 0,
diff --git a/core/libs/rawengine/libraw/src/utils/decoder_info.cpp b/core/libs/rawengine/libraw/src/utils/decoder_info.cpp
index c5c902d789..f92b531d15 100644
--- a/core/libs/rawengine/libraw/src/utils/decoder_info.cpp
+++ b/core/libs/rawengine/libraw/src/utils/decoder_info.cpp
@@ -317,6 +317,11 @@ int LibRaw::get_decoder_info(libraw_decoder_info_t *d_info)
LIBRAW_DECODER_TRYRAWSPEED | LIBRAW_DECODER_TRYRAWSPEED3 |
LIBRAW_DECODER_SONYARW2;
}
+ else if (load_raw == &LibRaw::sony_arw6_load_raw)
+ {
+ d_info->decoder_name = "sony_arw6_load_raw()";
+ d_info->decoder_flags = LIBRAW_DECODER_HASCURVE | LIBRAW_DECODER_FIXEDMAXC;
+ }
else if (load_raw == &LibRaw::sony_arq_load_raw)
{
d_info->decoder_name = "sony_arq_load_raw()";
diff --git a/core/libs/rawengine/libraw/src/utils/open.cpp b/core/libs/rawengine/libraw/src/utils/open.cpp
index ffd439eb15..ed1c379be9 100644
--- a/core/libs/rawengine/libraw/src/utils/open.cpp
+++ b/core/libs/rawengine/libraw/src/utils/open.cpp
@@ -1073,6 +1073,17 @@ int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)
S.raw_width == 2816) // A7S2=> exact, hope it works for A7S-I too
)
S.width = S.raw_width - 32;
+
+ if (load_raw == &LibRaw::sony_arw6_load_raw)
+ {
+ /* it would be great to get it via metadata */
+ C.black = 1024;
+ for (int c = 0; c < 6; c++)
+ C.cblack[c] = 0;
+ C.maximum = 39002; // last curve item
+ for (int c = 0; c < 4; c++)
+ C.linear_max[c] = 32800;
+ }
}