From a255555cd45af469c473be3a5c28cc429ce6ba65 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 5 Aug 2026 03:13:25 +0200 Subject: [PATCH 1/2] =?UTF-8?q?crn=5Fjpgd:=20accept=20grayscale=20JPEGs=20?= =?UTF-8?q?with=20non-1=C3=971=20sampling=20factors?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some grayscale JPEG files contain non-1×1 sampling factors even though they only have a single luminance component. Treat these as grayscale JPEGs with 1×1 sampling instead of rejecting them. This fixes loading and converting flr_tmtl_bump.jpg from Xonotic. --- crnlib/crn_jpgd.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crnlib/crn_jpgd.cpp b/crnlib/crn_jpgd.cpp index 7594c8ac..cdb2583f 100644 --- a/crnlib/crn_jpgd.cpp +++ b/crnlib/crn_jpgd.cpp @@ -2330,8 +2330,12 @@ void jpeg_decoder::init_frame() { int i; if (m_comps_in_frame == 1) { - if ((m_comp_h_samp[0] != 1) || (m_comp_v_samp[0] != 1)) - stop_decoding(JPGD_UNSUPPORTED_SAMP_FACTORS); + if ((m_comp_h_samp[0] != 1) || (m_comp_v_samp[0] != 1)) { + // Some grayscale JPEGs contain non-1×1 sampling factors. + // There is no chroma plane to subsample, so normalize to the expected layout. + m_comp_h_samp[0] = 1; + m_comp_v_samp[0] = 1; + } m_scan_type = JPGD_GRAYSCALE; m_max_blocks_per_mcu = 1; From aa8b02b6abc8573ac593e783f69a05832bbd3609 Mon Sep 17 00:00:00 2001 From: Thomas Debesse Date: Wed, 5 Aug 2026 04:33:43 +0200 Subject: [PATCH 2/2] =?UTF-8?q?test:=20add=20JPEG=20samples=20with=20grays?= =?UTF-8?q?cale=20component=20using=201=C3=971=20and=202=C3=972=20sampling?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/checksums.tsv | 14 ++++++++++++++ test/sample-grayscale-sampling1x1.jpg | Bin 0 -> 159 bytes test/sample-grayscale-sampling2x2.jpg | Bin 0 -> 159 bytes test/test.py | 2 ++ 4 files changed, 16 insertions(+) create mode 100644 test/sample-grayscale-sampling1x1.jpg create mode 100644 test/sample-grayscale-sampling2x2.jpg diff --git a/test/checksums.tsv b/test/checksums.tsv index 82871e49..e5f2a9b6 100644 --- a/test/checksums.tsv +++ b/test/checksums.tsv @@ -180,6 +180,20 @@ build/test/crunch-format-jpg-to-all/sample-black-64x64.crn 19fb840c8dbb7da96400a build/test/crunch-format-jpg-to-all/sample-black-64x64.dds cadaf30985bb62b98cd601793d6440c70fa32e24459b780e043576d70817e2d4131f8902c703aa48cb7014b6e07f729e33ed9d989b0db0535261a2c6808805c2 build/test/crunch-format-jpg-to-all/sample-black-64x64.ktx 00e261c23642594e12152e7a0f8ad56a3ed87526bb18ee2e5e0f65f1ce21bfc288bd4e6043807a7fa642f7130645025d3e621e8731bc4304e665c46a975f1c6a build/test/crunch-format-jpg-to-all/sample-black-64x64.jpg 4e080976a21bf93553425038f152934dbb292937e8fefaa7f9bd876b551e03d4778b54c41e64f470acabea03ff8e7ad3325daf790df1b7b9042930f48a00591a +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling1x1.tga c0c0863c373eae0936868e86e4ff9898714a78d5e1f96b972bffdce4f2e2cb3b0065477ce43f3118f256fe74e461e91c29db58e03c3bd32cac238e6e478f9300 +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling1x1.bmp d6247ea2517362b1f3c98d1542cacd1c0cb429d00a7635169adf24ac253f37217446e6eec6e06820afc99c35534a907c9539c41a5b3dc0de51bc161ebe11e860 +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling1x1.png 59533b55e3302cee1faa5583fe831435110933b0bc8030cf8e70380982f0704cb83abbae3a5fcdec3c20157a793f8a7908c9393373ad213559b0e0358d5471ea +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling1x1.crn 869a12414daecba28f7d4bb1f54467f21c01f356daa59b8e4ffc78ec643fb0f7a5db536c8fa8e62325c7625a718f153c2327f6ce95d6fc05f3fb26a9bac46ceb +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling1x1.dds e9ea76b8a7eaa5a227659d86db3c64703ffe09788e49b9ccf9833c392d39d8ef8626865bebb1a977f5970ba21f3156d1f7741cb5d635804e8f852f2af8b83328 +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling1x1.ktx 44e1df3fa8d784d7e490d8440eba4e049b721af932b7898c317d03474290669531afe85916d3452bc1d0966a9a6d36cf53964e98eb2dfdc1cabf6d7c02afab61 +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling1x1.jpg fe96bbc6e9c37ba66a981d40bd46d05ea0a385499c7feed7839915da665c376cc1257cd82721ee8d454dc2f425c1bfc16490ae4607465b3b9545fc4741ce0a2f +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling2x2.tga c0c0863c373eae0936868e86e4ff9898714a78d5e1f96b972bffdce4f2e2cb3b0065477ce43f3118f256fe74e461e91c29db58e03c3bd32cac238e6e478f9300 +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling2x2.bmp d6247ea2517362b1f3c98d1542cacd1c0cb429d00a7635169adf24ac253f37217446e6eec6e06820afc99c35534a907c9539c41a5b3dc0de51bc161ebe11e860 +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling2x2.png 59533b55e3302cee1faa5583fe831435110933b0bc8030cf8e70380982f0704cb83abbae3a5fcdec3c20157a793f8a7908c9393373ad213559b0e0358d5471ea +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling2x2.crn 869a12414daecba28f7d4bb1f54467f21c01f356daa59b8e4ffc78ec643fb0f7a5db536c8fa8e62325c7625a718f153c2327f6ce95d6fc05f3fb26a9bac46ceb +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling2x2.dds e9ea76b8a7eaa5a227659d86db3c64703ffe09788e49b9ccf9833c392d39d8ef8626865bebb1a977f5970ba21f3156d1f7741cb5d635804e8f852f2af8b83328 +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling2x2.ktx 44e1df3fa8d784d7e490d8440eba4e049b721af932b7898c317d03474290669531afe85916d3452bc1d0966a9a6d36cf53964e98eb2dfdc1cabf6d7c02afab61 +build/test/crunch-format-jpg-to-all/sample-grayscale-sampling2x2.jpg fe96bbc6e9c37ba66a981d40bd46d05ea0a385499c7feed7839915da665c376cc1257cd82721ee8d454dc2f425c1bfc16490ae4607465b3b9545fc4741ce0a2f build/test/example1-icon-png-to-dds/sample-icon-unvanquished-64x64.dds ce98b21c574b4883e4aff4a0b92fd0f533f22e00ab753686f353111fa7503287c2c4dba25f2c2670508630d79b59464578e094461bad81ad803e1d58ed5e69f8 build/test/example1-icon-png-to-crn/sample-icon-unvanquished-64x64.crn a3b526e95f44b6a4c919bc8eb79f4debf592f0bccc163c900cd1b6f9add0ce58c3db9fc8dac1828d350bbcd915823d7743a0c114a533fbc08c163fcb4846d2f5 build/test/example1-icon-crn-to-dds/sample-icon-unvanquished-64x64.dds 2aae5c5bd8c6a82d1cf3fc9d9da12fe3fc5be8651261ff1cb359e754308fd81e93bf304aeb55ada0bad50794d6e97d3e48084e5a4f48fa7caec4ed954152bae9 diff --git a/test/sample-grayscale-sampling1x1.jpg b/test/sample-grayscale-sampling1x1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..216835cc7db6c7fc0726005308768bf8eb90d916 GIT binary patch literal 159 zcmZ9GK@P$o6hsFEOZb$2TByB^3zH^#Y8M`&>c*S=LR{&~EGBO;8QJ6mzOC04O5uyV zalt|BmWrvd&RS!v@4BN4J_PbaeH^)uDH8F_Y09OPFr1b-FJmrQ?jQ$MS5<;MkZb=% QH_QJP@`7tu&KTsm19RsSmjD0& literal 0 HcmV?d00001 diff --git a/test/sample-grayscale-sampling2x2.jpg b/test/sample-grayscale-sampling2x2.jpg new file mode 100644 index 0000000000000000000000000000000000000000..71fb8451cf52405c3f1ef5fe00eac78760d75f3a GIT binary patch literal 159 zcmZ9GI}XAy5JbnuCYIN6Henr7a}f%pNN{Qj4#B74CW|d9c$#ALiqYs@-{8x7USSNr z=nE%otZk{d8XvrO&d09Xh7?nxNYv+v`#feMo_X9!DJ2d2WtL@N)o RUu?7dZ=p|wcIAjcA0Kzp6Q}?H literal 0 HcmV?d00001 diff --git a/test/test.py b/test/test.py index 84917320..2e95da66 100755 --- a/test/test.py +++ b/test/test.py @@ -425,6 +425,8 @@ def start_from(items, value): "format": "jpg", "samples": [ "sample-black-64x64", + "sample-grayscale-sampling1x1", + "sample-grayscale-sampling2x2", ], }, ]