diff --git a/YUViewLib/src/playlistitem/playlistItemRawFile.cpp b/YUViewLib/src/playlistitem/playlistItemRawFile.cpp index b9dc1db00..0362cf1a5 100644 --- a/YUViewLib/src/playlistitem/playlistItemRawFile.cpp +++ b/YUViewLib/src/playlistitem/playlistItemRawFile.cpp @@ -55,6 +55,8 @@ namespace constexpr auto YUV_EXTENSIONS = {"yuv", "nv12", "y4m"}; constexpr auto RGB_EXTENSIONS = {"rgb", "gbr", "bgr", "brg"}; constexpr auto RGBA_EXTENSIONS = {"rgba", "gbra", "bgra", "brga", "argb", "agbr", "abgr", "abrg"}; +constexpr auto RAW_BAYER_EXTENSIONS = {"raw"}; +constexpr auto CMYK_EXTENSIONS = {"cmyk"}; bool isInExtensions(const QString &testValue, const std::initializer_list &extensions) { @@ -95,13 +97,14 @@ playlistItemRawFile::playlistItemRawFile(const QString &rawFilePath, // Create a new videoHandler instance depending on the input format QFileInfo fi(rawFilePath); const auto ext = fi.suffix().toLower(); - if (isInExtensions(ext, YUV_EXTENSIONS) || fmt.toLower() == "yuv") + if (isInExtensions(ext, YUV_EXTENSIONS) || isInExtensions(ext, RAW_BAYER_EXTENSIONS) || + fmt.toLower() == "yuv") { this->video = std::make_unique(); this->rawFormat = video::RawFormat::YUV; } else if (isInExtensions(ext, RGB_EXTENSIONS) || isInExtensions(ext, RGBA_EXTENSIONS) || - fmt.toLower() == "rgb") + isInExtensions(ext, CMYK_EXTENSIONS) || fmt.toLower() == "rgb") { this->video = std::make_unique(); this->rawFormat = video::RawFormat::RGB; @@ -569,7 +572,8 @@ ValuePairListSets playlistItemRawFile::getPixelValues(const QPoint &pixelPos, in void playlistItemRawFile::getSupportedFileExtensions(QStringList &allExtensions, QStringList &filters) { - for (const auto &extensionsList : {YUV_EXTENSIONS, RGB_EXTENSIONS, RGBA_EXTENSIONS}) + for (const auto &extensionsList : + {YUV_EXTENSIONS, RGB_EXTENSIONS, RGBA_EXTENSIONS, RAW_BAYER_EXTENSIONS, CMYK_EXTENSIONS}) for (const auto &extension : extensionsList) allExtensions.append(QString(extension)); @@ -578,6 +582,8 @@ void playlistItemRawFile::getSupportedFileExtensions(QStringList &allExtensions, filters.append("Raw RGBA File (*.rgba *.rbga *.grba *.gbra *.brga *.bgra *.argb *.arbg *.agrb " "*.agbr *.abrg *.abgr)"); filters.append("YUV4MPEG2 File (*.y4m)"); + filters.append("Raw Bayer File (*.raw)"); + filters.append("Raw CMYK File (*.cmyk)"); } void playlistItemRawFile::reloadItemSource() diff --git a/YUViewLib/src/video/rgb/PixelFormatRGBGuess.cpp b/YUViewLib/src/video/rgb/PixelFormatRGBGuess.cpp index 3c51d153c..566364869 100644 --- a/YUViewLib/src/video/rgb/PixelFormatRGBGuess.cpp +++ b/YUViewLib/src/video/rgb/PixelFormatRGBGuess.cpp @@ -119,7 +119,7 @@ DataLayout findDataLayoutInName(const std::string &fileName) } PixelFormatRGB -guessFormatFromSizeAndName(const QFileInfo &fileInfo, Size frameSize, int64_t fileSize) +guessFormatFromSizeAndName(const QFileInfo &fileInfo, const Size frameSize, const int64_t fileSize) { // We are going to check two strings (one after the other) for indicators on the YUV format. // 1: The file name, 2: The folder name that the file is contained in. @@ -130,21 +130,30 @@ guessFormatFromSizeAndName(const QFileInfo &fileInfo, Size frameSize, int64_t fi return {}; fileName += "."; - // The name of the folder that the file is in - auto dirName = fileInfo.absoluteDir().dirName().toLower().toStdString(); + const auto dirName = fileInfo.absoluteDir().dirName().toLower().toStdString(); + const auto fileExtension = fileInfo.suffix().toLower().toStdString(); - auto ext = fileInfo.suffix().toLower().toStdString(); + auto isFileSizeMultipleOfFrameSizeInBytes = [&fileSize, &frameSize](const PixelFormatRGB &format) + { + const auto bpf = format.bytesPerFrame(frameSize); + return bpf > 0 && (fileSize % bpf) == 0; + }; + + if (fileExtension == "cmyk") + { + const auto format = PixelFormatRGB(8, DataLayout::Packed, ChannelOrder::RGB, AlphaMode::Last); + if (isFileSizeMultipleOfFrameSizeInBytes(format)) + return format; + } for (const auto &name : {fileName, dirName}) { for (auto format : - {findPixelFormatIndicatorInName(name), findPixelFormatFromFileExtension(ext)}) + {findPixelFormatIndicatorInName(name), findPixelFormatFromFileExtension(fileExtension)}) { if (format) { - // Check if the file size and the assumed format match - auto bpf = format->bytesPerFrame(frameSize); - if (bpf != 0 && (fileSize % bpf) == 0) + if (isFileSizeMultipleOfFrameSizeInBytes(*format)) { auto dataLayout = findDataLayoutInName(name); format->setDataLayout(dataLayout); diff --git a/YUViewLib/src/video/rgb/PixelFormatRGBGuess.h b/YUViewLib/src/video/rgb/PixelFormatRGBGuess.h index 0458009ba..3d596a61d 100644 --- a/YUViewLib/src/video/rgb/PixelFormatRGBGuess.h +++ b/YUViewLib/src/video/rgb/PixelFormatRGBGuess.h @@ -42,6 +42,6 @@ namespace video::rgb // If you know the frame size of the video, the file size (and optionally the bit depth) we can // guess the remaining values. The rate value is set if a matching format could be found. PixelFormatRGB -guessFormatFromSizeAndName(const QFileInfo &fileInfo, Size frameSize, int64_t fileSize); +guessFormatFromSizeAndName(const QFileInfo &fileInfo, const Size frameSize, const int64_t fileSize); } // namespace video::rgb diff --git a/YUViewLib/src/video/yuv/PixelFormatYUV.h b/YUViewLib/src/video/yuv/PixelFormatYUV.h index ef6e21965..d0e0f20df 100644 --- a/YUViewLib/src/video/yuv/PixelFormatYUV.h +++ b/YUViewLib/src/video/yuv/PixelFormatYUV.h @@ -55,7 +55,7 @@ R = Y + V*(1-Kr) G = Y - U*(1-Kb)*Kb/Kg - V*(1-Kr)*Kr/Kg B = Y + U*(1-Kb) To respect value range of Y in [16:235] and U/V in [16:240], the matrix entries need to be scaled -by 255/219 for Y and 255/112 for U/V In this software color conversion is performed with 16bit +by 255/219 for Y and 255/224 for U/V In this software color conversion is performed with 16bit precision. Thus, further scaling with 2^16 is performed to get all factors as integers. */ enum class ColorConversion @@ -180,9 +180,9 @@ enum class PlaneOrder }; constexpr EnumMapper PlaneOrderMapper(std::make_pair(PlaneOrder::YUV, "YUV"sv), - std::make_pair(PlaneOrder::YVU, "YVU"sv), - std::make_pair(PlaneOrder::YUVA, "YUVA"sv), - std::make_pair(PlaneOrder::YVUA, "YVUA"sv)); + std::make_pair(PlaneOrder::YVU, "YVU"sv), + std::make_pair(PlaneOrder::YUVA, "YUVA"sv), + std::make_pair(PlaneOrder::YVUA, "YVUA"sv)); const auto BitDepthList = std::vector({8, 9, 10, 12, 14, 16}); diff --git a/YUViewLib/src/video/yuv/PixelFormatYUVGuess.cpp b/YUViewLib/src/video/yuv/PixelFormatYUVGuess.cpp index f28476041..ff018d296 100644 --- a/YUViewLib/src/video/yuv/PixelFormatYUVGuess.cpp +++ b/YUViewLib/src/video/yuv/PixelFormatYUVGuess.cpp @@ -250,11 +250,18 @@ PixelFormatYUV guessFormatFromSizeAndName(const Size size, // The name of the folder that the file is in auto dirName = fileInfo.absoluteDir().dirName().toLower().toStdString(); + if (fileInfo.suffix().toLower() == "raw") + { + const auto rawBayerFormat = PixelFormatYUV(Subsampling::YUV_400, bitDepth); + if (checkFormat(rawBayerFormat, size, fileSize)) + return rawBayerFormat; + } + if (fileInfo.suffix().toLower() == "v210") { - auto fmt = PixelFormatYUV(PredefinedPixelFormat::V210); - if (checkFormat(fmt, size, fileSize)) - return fmt; + const auto v210Format = PixelFormatYUV(PredefinedPixelFormat::V210); + if (checkFormat(v210Format, size, fileSize)) + return v210Format; } for (const auto &name : {fileName, dirName}) diff --git a/YUViewUnitTest/video/rgb/PixelFormatRGBGuessTest.cpp b/YUViewUnitTest/video/rgb/PixelFormatRGBGuessTest.cpp index 673169ffa..993533fc0 100644 --- a/YUViewUnitTest/video/rgb/PixelFormatRGBGuessTest.cpp +++ b/YUViewUnitTest/video/rgb/PixelFormatRGBGuessTest.cpp @@ -75,9 +75,10 @@ TEST_P(GuessRGBFormatFromFilenameFrameSizeAndFileSize, TestGuess) EXPECT_EQ(guessedRGBFormat, parameters.expectedPixelFormat); } -constexpr auto BytesNoAlpha = 1920u * 1080 * 12 * 3; // 12 frames RGB +constexpr auto BytesNoAlpha = 1920u * 1080 * 12u * 3u; // 12 frames RGB constexpr auto NotEnoughBytes = 22u; -constexpr auto UnfittingBytes = 1920u * 1080 * 5; +constexpr auto UnfittingBytes = 1920u * 1080u * 5u; +constexpr auto BytesBayerFile = 512u * 768u * 4u * 12u; // 12 frames raw bayer INSTANTIATE_TEST_SUITE_P( VideoRGBTest, @@ -270,7 +271,13 @@ INSTANTIATE_TEST_SUITE_P( TestParameters({"something_1920x1080_rgb16be.yuv", Size(1920, 1080), UnfittingBytes, - PixelFormatRGB(8, DataLayout::Packed, ChannelOrder::RGB)}) + PixelFormatRGB(8, DataLayout::Packed, ChannelOrder::RGB)}), + + // CMYK file + TestParameters({"something_512x768.cmyk", + Size(512, 768), + BytesBayerFile, + PixelFormatRGB(8, DataLayout::Packed, ChannelOrder::RGB, AlphaMode::Last)}) ), getTestName); diff --git a/YUViewUnitTest/video/yuv/PixelFormatYUVGuessTest.cpp b/YUViewUnitTest/video/yuv/PixelFormatYUVGuessTest.cpp index 0533c6ace..729a40523 100644 --- a/YUViewUnitTest/video/yuv/PixelFormatYUVGuessTest.cpp +++ b/YUViewUnitTest/video/yuv/PixelFormatYUVGuessTest.cpp @@ -261,7 +261,15 @@ INSTANTIATE_TEST_SUITE_P( 0, DataLayout::Planar, BYTES_1808P_400, - PixelFormatYUV(Subsampling::YUV_400, 16)}) + PixelFormatYUV(Subsampling::YUV_400, 16)}), + + // Raw bayer file + TestParameters({"sample_1920x1080_something.raw", + Size(1920, 1080), + 8, + DataLayout::Planar, + BYTES_1808P_400, + PixelFormatYUV(Subsampling::YUV_400, 8)}) // More tests please :)