From e4c14c5c4f266f8eaf2152621a31516667d4123c Mon Sep 17 00:00:00 2001 From: XieFuwei <12313607@mail.sustech.edu.cn> Date: Tue, 26 May 2026 22:43:56 +0800 Subject: [PATCH] imgcodecs: fix SunRaster IMREAD_GRAYSCALE returning black image SunRasterDecoder::readData() only called CvtPaletteToGray() when the file contained a color palette (m_maptype == RMT_EQUAL_RGB). But SunRasterEncoder always writes RMT_NONE (no palette), so gray_palette[] stayed zero-initialized and FillGrayRow8() mapped every pixel to 0. Fix: call CvtPaletteToGray() whenever reading as grayscale, regardless of palette type. readHeader() already fills m_palette correctly via FillGrayPalette() for the RMT_NONE case. Add regression test Imgcodecs_SunRaster.imread_grayscale_roundtrip that writes a full 0-255 ramp, reads it back with IMREAD_GRAYSCALE, and checks NORM_INF == 0. Without the fix, NORM_INF == 255 (all black). Remove the "broken (black result)" skip for ras in read_write_GRAYSCALE. --- modules/imgcodecs/src/grfmt_sunras.cpp | 2 +- modules/imgcodecs/test/test_read_write.cpp | 33 +++++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/modules/imgcodecs/src/grfmt_sunras.cpp b/modules/imgcodecs/src/grfmt_sunras.cpp index 803a0de99f..2fc19de57f 100644 --- a/modules/imgcodecs/src/grfmt_sunras.cpp +++ b/modules/imgcodecs/src/grfmt_sunras.cpp @@ -159,7 +159,7 @@ bool SunRasterDecoder::readData( Mat& img ) AutoBuffer _src(src_pitch + 32); uchar* src = _src.data(); - if( !color && m_maptype == RMT_EQUAL_RGB ) + if( !color ) CvtPaletteToGray( m_palette, gray_palette, 1 << m_bpp ); try diff --git a/modules/imgcodecs/test/test_read_write.cpp b/modules/imgcodecs/test/test_read_write.cpp index 2508ef2dbd..6655670e77 100644 --- a/modules/imgcodecs/test/test_read_write.cpp +++ b/modules/imgcodecs/test/test_read_write.cpp @@ -264,7 +264,6 @@ TEST_P(Imgcodecs_Image, read_write_GRAYSCALE) if (false || ext == "ppm" // grayscale is not implemented - || ext == "ras" // broken (black result) ) throw SkipTestException("GRAYSCALE mode is not supported"); @@ -291,6 +290,38 @@ TEST_P(Imgcodecs_Image, read_write_GRAYSCALE) INSTANTIATE_TEST_CASE_P(imgcodecs, Imgcodecs_Image, testing::ValuesIn(exts)); +#ifdef HAVE_IMGCODEC_SUNRASTER +// Regression test: imread(file, IMREAD_GRAYSCALE) for a .ras file written by +// imwrite() used to return an all-black image because gray_palette[] was never +// populated when the file has no color palette (RMT_NONE, which is what +// SunRasterEncoder always writes). +TEST(Imgcodecs_SunRaster, imread_grayscale_roundtrip) +{ + // Build a 16x16 ramp covering all 256 values so a silent all-zero result + // is immediately obvious. + Mat src(16, 16, CV_8UC1); + for (int i = 0; i < src.rows; i++) + for (int j = 0; j < src.cols; j++) + src.at(i, j) = (uchar)(i * src.cols + j); + + const string fname = cv::tempfile(".ras"); + ASSERT_TRUE(imwrite(fname, src)) << "imwrite failed for .ras"; + + Mat dst = imread(fname, IMREAD_GRAYSCALE); + ASSERT_FALSE(dst.empty()) << "imread returned empty Mat"; + ASSERT_EQ(src.size(), dst.size()); + ASSERT_EQ(src.type(), dst.type()); + + // Before the fix every pixel read back as 0 (black), so norm would equal + // the sum of all original values instead of 0. + EXPECT_EQ(0, cvtest::norm(src, dst, NORM_INF)) + << "imread(IMREAD_GRAYSCALE) returned wrong pixel values for .ras — " + "expected exact roundtrip, got all-zero (black) image"; + + EXPECT_EQ(0, remove(fname.c_str())); +} +#endif + TEST(Imgcodecs_Image, regression_9376) { String path = findDataFile("readwrite/regression_9376.bmp");