读取 16 位 DPX 像素数据
Reading 16 bit DPX Pixel Data
我正在尝试从 16 位 dpx 文件中读取像素数据,该文件是先前 git repo 的扩展(因为它仅支持 10 位)。
我正在利用这个 header and cpp 来处理 header 信息并获取此类数据。
请注意,变量 _pixelOffset、_width、_height 和 _channels 基于 dpx 的 header 信息。 pPixels 是一个 float* 数组:
#include <iostream>
#include <fstream>
#include <dpxHeader.h>
//First read the file as binary.
std::ifstream _in(_filePath.asChar(), std::ios_base::binary);
// Seek to the pixel offset to start reading where the pixel data starts.
if (!_in.seekg (_pixelOffset, std::ios_base::beg))
{
std::cerr << "Cannot seek to start of pixel data " << _filePath << " in DPX file.";
return MS::kFailure;
}
// Create char to store data of width length of the image
unsigned char *rawLine = new unsigned char[_width * 4]();
// Iterate over height pixels
for (int y = 0; y < _height; ++y)
{
// Read full pixel data for width.
if (!_in.read ((char *)&rawLine[0], _width * 4))
{
std::cerr << "Cannot read scan line " << y << " " << "from DPX file " << std::endl;
return MS::kFailure;
}
// Iterator over width
for (int x = 0; x < _width; ++x)
{
// We do this to flip the image because it's flipped vertically when read in
int index = ((_height - 1 - y) * _width * _channels) + x * _channels;
unsigned int word = getU32(rawLine + 4 * x, _byteOrder);
pPixels[index] = (((word >> 22) & 0x3ff)/1023.0);
pPixels[index+1] = (((word >> 12) & 0x3ff)/1023.0);
pPixels[index+2] = (((word >> 02) & 0x3ff)/1023.0);
}
}
delete [] rawLine;
这目前适用于 10 位文件,但由于我是按位操作的新手,所以我不确定如何将其扩展到 12 位和 16 位。有人对我有任何线索或正确的指导吗?
这种文件格式比较全面,但如果您只针对已知的子集,扩展它应该不会太难。
从您的代码示例看来,您当前正在处理每个像素三个分量,并且这些分量填充为 32 位字。根据您提供的规范,在这种模式下,12 位和 16 位都将每个字存储两个组件。对于 12 位,每个分量的高 4 位是填充数据。您将需要三个 32 位字来获得六个颜色分量来解码两个像素:
...
unsigned int word0 = getU32(rawLine + 6 * x + 0, _byteOrder);
unsigned int word1 = getU32(rawLine + 6 * x + 4, _byteOrder);
unsigned int word2 = getU32(rawLine + 6 * x + 8, _byteOrder);
// First pixel
pPixels[index] = (word0 & 0xffff) / (float)0xffff; // (or 0xfff for 12-bit)
pPixels[index+1] = (word0 >> 16) / (float)0xffff;
pPixels[index+2] = (word1 & 0xffff) / (float)0xffff;
x++;
if(x >= _width) break; // In case of an odd amount of pixels
// Second pixel
pPixels[index+3] = (word1 >> 16) / (float)0xffff;
pPixels[index+4] = (word2 & 0xffff) / (float)0xffff;
pPixels[index+5] = (word2 >> 16) / (float)0xffff;
...
我正在尝试从 16 位 dpx 文件中读取像素数据,该文件是先前 git repo 的扩展(因为它仅支持 10 位)。
我正在利用这个 header and cpp 来处理 header 信息并获取此类数据。
请注意,变量 _pixelOffset、_width、_height 和 _channels 基于 dpx 的 header 信息。 pPixels 是一个 float* 数组:
#include <iostream>
#include <fstream>
#include <dpxHeader.h>
//First read the file as binary.
std::ifstream _in(_filePath.asChar(), std::ios_base::binary);
// Seek to the pixel offset to start reading where the pixel data starts.
if (!_in.seekg (_pixelOffset, std::ios_base::beg))
{
std::cerr << "Cannot seek to start of pixel data " << _filePath << " in DPX file.";
return MS::kFailure;
}
// Create char to store data of width length of the image
unsigned char *rawLine = new unsigned char[_width * 4]();
// Iterate over height pixels
for (int y = 0; y < _height; ++y)
{
// Read full pixel data for width.
if (!_in.read ((char *)&rawLine[0], _width * 4))
{
std::cerr << "Cannot read scan line " << y << " " << "from DPX file " << std::endl;
return MS::kFailure;
}
// Iterator over width
for (int x = 0; x < _width; ++x)
{
// We do this to flip the image because it's flipped vertically when read in
int index = ((_height - 1 - y) * _width * _channels) + x * _channels;
unsigned int word = getU32(rawLine + 4 * x, _byteOrder);
pPixels[index] = (((word >> 22) & 0x3ff)/1023.0);
pPixels[index+1] = (((word >> 12) & 0x3ff)/1023.0);
pPixels[index+2] = (((word >> 02) & 0x3ff)/1023.0);
}
}
delete [] rawLine;
这目前适用于 10 位文件,但由于我是按位操作的新手,所以我不确定如何将其扩展到 12 位和 16 位。有人对我有任何线索或正确的指导吗?
这种文件格式比较全面,但如果您只针对已知的子集,扩展它应该不会太难。
从您的代码示例看来,您当前正在处理每个像素三个分量,并且这些分量填充为 32 位字。根据您提供的规范,在这种模式下,12 位和 16 位都将每个字存储两个组件。对于 12 位,每个分量的高 4 位是填充数据。您将需要三个 32 位字来获得六个颜色分量来解码两个像素:
...
unsigned int word0 = getU32(rawLine + 6 * x + 0, _byteOrder);
unsigned int word1 = getU32(rawLine + 6 * x + 4, _byteOrder);
unsigned int word2 = getU32(rawLine + 6 * x + 8, _byteOrder);
// First pixel
pPixels[index] = (word0 & 0xffff) / (float)0xffff; // (or 0xfff for 12-bit)
pPixels[index+1] = (word0 >> 16) / (float)0xffff;
pPixels[index+2] = (word1 & 0xffff) / (float)0xffff;
x++;
if(x >= _width) break; // In case of an odd amount of pixels
// Second pixel
pPixels[index+3] = (word1 >> 16) / (float)0xffff;
pPixels[index+4] = (word2 & 0xffff) / (float)0xffff;
pPixels[index+5] = (word2 >> 16) / (float)0xffff;
...