Skip to content

Commit

Permalink
Add support to display CMYK and raw bayer files
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianFeldmann committed Jul 31, 2024
1 parent 8e13a10 commit 1589f12
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 23 deletions.
12 changes: 9 additions & 3 deletions YUViewLib/src/playlistitem/playlistItemRawFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<const char *> &extensions)
{
Expand Down Expand Up @@ -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<video::yuv::videoHandlerYUV>();
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<video::rgb::videoHandlerRGB>();
this->rawFormat = video::RawFormat::RGB;
Expand Down Expand Up @@ -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));

Expand All @@ -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()
Expand Down
25 changes: 17 additions & 8 deletions YUViewLib/src/video/rgb/PixelFormatRGBGuess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion YUViewLib/src/video/rgb/PixelFormatRGBGuess.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 4 additions & 4 deletions YUViewLib/src/video/yuv/PixelFormatYUV.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -180,9 +180,9 @@ enum class PlaneOrder
};

constexpr EnumMapper<PlaneOrder, 4> 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<unsigned>({8, 9, 10, 12, 14, 16});

Expand Down
13 changes: 10 additions & 3 deletions YUViewLib/src/video/yuv/PixelFormatYUVGuess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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})
Expand Down
13 changes: 10 additions & 3 deletions YUViewUnitTest/video/rgb/PixelFormatRGBGuessTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down
10 changes: 9 additions & 1 deletion YUViewUnitTest/video/yuv/PixelFormatYUVGuessTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 :)

Expand Down

0 comments on commit 1589f12

Please sign in to comment.