Skip to content

Commit

Permalink
support 16+ bits YUV file
Browse files Browse the repository at this point in the history
  • Loading branch information
for13to1 committed Oct 21, 2024
1 parent 7b00bc4 commit 612357f
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 53 deletions.
15 changes: 7 additions & 8 deletions YUViewLib/src/video/yuv/PixelFormatYUV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ PixelFormatYUV::PixelFormatYUV(const std::string &name)
auto bitdepthStr = sm.str(3);
size_t sz;
int bitDepth = std::stoi(bitdepthStr, &sz);
if (sz > 0 && bitDepth >= 8 && bitDepth <= 16)
if (sz > 0 && bitDepth >= 8 && bitDepth <= 32)
newFormat.bitsPerSample = bitDepth;
}

Expand Down Expand Up @@ -317,7 +317,7 @@ bool PixelFormatYUV::canConvertToRGB(Size imageSize, std::string *whyNot) const
// Check the bit depth
const int bps = this->bitsPerSample;
bool canConvert = true;
if (bps < 8 || bps > 16)
if (bps < 8 || bps > 32)
{
if (whyNot)
{
Expand Down Expand Up @@ -382,14 +382,14 @@ int64_t PixelFormatYUV::bytesPerFrame(const Size &frameSize) const
}

int64_t bytes = 0;
const auto bytesPerSample = get_min_standard_bytes(this->bitsPerSample); // Round to bytes

if (this->planar || !this->bytePacking)
{
// Add the bytes of the 3 (or 4) planes.
// This also works for packed formats without byte packing. For these formats the number of
// bytes are identical to the not packed formats, the bytes are just sorted in another way.

const auto bytesPerSample = (this->bitsPerSample + 7) / 8; // Round to bytes
bytes += frameSize.width * frameSize.height * bytesPerSample; // Luma plane
if (this->subsampling == Subsampling::YUV_444)
bytes += frameSize.width * frameSize.height * bytesPerSample * 2; // U/V planes
Expand Down Expand Up @@ -426,17 +426,16 @@ int64_t PixelFormatYUV::bytesPerFrame(const Size &frameSize) const
if (this->subsampling == Subsampling::YUV_422)
{
// All packing orders have 4 values per packed value (which has 2 Y samples)
const auto bitsPerPixel = this->bitsPerSample * 4;
return ((bitsPerPixel + 7) / 8) * (frameSize.width / 2) * frameSize.height;
return 4 * bytesPerSample * (frameSize.width / 2) * frameSize.height;
}
// This is a packed format. The added number of bytes might be lower because of the packing.
if (this->subsampling == Subsampling::YUV_444)
{
auto bitsPerPixel = this->bitsPerSample * 3;
auto channels = 3;
if (this->packingOrder == PackingOrder::AYUV || this->packingOrder == PackingOrder::YUVA ||
this->packingOrder == PackingOrder::VUYA)
bitsPerPixel += this->bitsPerSample;
return ((bitsPerPixel + 7) / 8) * frameSize.width * frameSize.height;
channels += 1;
return channels * bytesPerSample * frameSize.width * frameSize.height;
}
// else if (subsampling == Subsampling::YUV_422 || subsampling == Subsampling::YUV_440)
//{
Expand Down
19 changes: 18 additions & 1 deletion YUViewLib/src/video/yuv/PixelFormatYUV.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ constexpr EnumMapper<PlaneOrder, 4> PlaneOrderMapper(std::make_pair(PlaneOrder::
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});
const auto BitDepthList = std::vector<unsigned>({8, 9, 10, 12, 14, 16, 20, 24, 32});

// This class defines a specific YUV format with all properties like pixels per sample, subsampling
// of chroma components and so on.
Expand Down Expand Up @@ -263,4 +263,21 @@ class PixelFormatYUV
bool bytePacking{};
};

inline uint64_t get_min_standard_bytes(uint64_t x) {
if (x == 0)
return 0;

if (x >= UINT64_MAX / 8) {
return UINT64_MAX;
}

x--;

for (int current_shift = 1; current_shift < 64; current_shift <<= 1) {
x |= x >> current_shift;
}

return (x + 8) >> 3;
}

} // namespace video::yuv
4 changes: 2 additions & 2 deletions YUViewLib/src/video/yuv/PixelFormatYUVGuess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ Subsampling findSubsamplingTypeIndicatorInName(std::string name)
std::vector<unsigned> getDetectionBitDepthList(unsigned forceAsFirst)
{
std::vector<unsigned> bitDepthList;
if (forceAsFirst >= 8 && forceAsFirst <= 16)
if (forceAsFirst >= 8 && forceAsFirst <= 32)
bitDepthList.push_back(forceAsFirst);

for (auto bitDepth : {10u, 12u, 14u, 16u, 8u})
for (auto bitDepth : BitDepthList)
{
if (!vectorContains(bitDepthList, bitDepth))
bitDepthList.push_back(bitDepth);
Expand Down
Loading

0 comments on commit 612357f

Please sign in to comment.