如何使用 Matlab 或 C 从 2 个输入数组写入二进制文件并交织值
How to write to binary file from 2 input array and interweaving the value, with Matlab or C
我正在读取两个 256x256 帧大小的原始 8 位视频文件。 16位原始视频源,一个是高位字节,一个是低位字节。
我正在努力使用 Matlab 将两个字节组合成一个 uint16 数组以写入文件,或者尝试先写入低字节再写入高字节。每次我用fwrite的时候,都必须写高位字节的全256x256帧,然后是低位字节的全帧。
我有一个像下面这样的循环正在工作,但它非常慢。
for j = 1:256
for k = 1:256
fwrite(RemergedFID, lowFrame(k,j), 'uint8');
fwrite(RemergedFID, highFrame(k,j), 'uint8');
end
end
有没有更好更快的方法来写出这样的东西?
我可以建议创建一个 16 位帧,其中 16 位帧中每个像素的上半部分对应于 lowFrame
,而 16 位帧中的另一半对应于 highFrame
。你的措辞表明相反,但你在 MATLAB 中编写结果的方式表明我刚才所说的。我将采用您在代码中编写它的方式,但您可以根据自己的需要进行更改。
在任何情况下,只需将 lowFrame
和 bitshift
的所有位都左移 8,然后 将此结果添加 highFrame
得到连接的结果。通过将一帧向左移动 8 位,您可以在添加时为另一帧留出空间以占据下半部分。然后,您将立即将整个数组写入文件。请记住,当您将数组写入文件时,数组以 column-major 格式写入。这意味着当您将数组写入文件时,列 会堆叠在一起形成一个连续的块并写入文件。我不知道您最终要将其用于什么应用程序,但是如果您想要 行-主要格式,其中 行堆叠在一个连续的块中,您需要在写入之前先转置此输出帧。因此,做这样的事情:
lowFrame = uint16(lowFrame);
highFrame = uint16(highFrame);
outFrame = bitshift(lowFrame, 8) + highFrame;
fwrite(RemergedFID, outFrame, 'uint16');
%fwrite(RemergedFID, outFrame.', 'uint16'); %// Use this if you want row-major
重要的是我们投射帧的前两行代码,假设它们是 uint8
,到 uint16
。我们必须这样做才能使位移位起作用。如果我们将其保留为 uint8
,位移只会使类型饱和,因此向左移动 8 位只会给出最大值 255
。第三行神奇地允许您将来自两个帧的位连接在一起作为单个 16 位字,然后将结果写入文件。
就性能而言,这肯定比遍历像素快,因为位移位几乎不需要时间,因为它是一个原子操作 - 加法也是如此。
reshape
and typecast
的组合可以在Matlab中做你想做的事情:
%% // optional, in case your frames are not always 256x256
nLine = size(highFrame,1) ;
nCol = size(highFrame,2) ;
%% // if you like the "black magic" effect, in one line:
FullFrame = reshape( typecast( reshape( [lowFrame(:) highFrame(:)].' , [] , nLine*nCol*2 ) , 'uint16') , nLine , [] ) ; %'//
fwrite(RemergedFID, FullFrame, 'uint16'); %// then write the full matrix in one go
如果不喜欢冗长晦涩的台词,可以分解成:
%% // merge the 2x uint8 frames into a single uint16 frame (lower endian ordering)
FullFrame = [lowFrame(:) highFrame(:)] ; %// Make a double column with high and low bytes in lower endian ordering
FullFrame = reshape( FullFrame.' , [] , nLine*nCol*2 ) ; %'// Reshape the transpose to get one single line vector
FullFrame = typecast( FullFrame , 'uint16') ; %// cast every 2 uint8 value into a uint16 value (lower endian ordering)
FullFrame = reshape( FullFrame , nLine , [] ) ; %// reshape that into an m*n matrix
fwrite(RemergedFID, FullFrame, 'uint16'); %// then write the full matrix in one go
Matlab 和大多数pc 将使用lower endian byte ordering 来对超过8 位的值进行排序。除非你正在为一个你知道将特别大端排序的系统编写文件(一些嵌入式处理器是),否则我建议你坚持使用低端,或者更好的是,让 Matlab 或你的系统处理它。
我正在读取两个 256x256 帧大小的原始 8 位视频文件。 16位原始视频源,一个是高位字节,一个是低位字节。
我正在努力使用 Matlab 将两个字节组合成一个 uint16 数组以写入文件,或者尝试先写入低字节再写入高字节。每次我用fwrite的时候,都必须写高位字节的全256x256帧,然后是低位字节的全帧。
我有一个像下面这样的循环正在工作,但它非常慢。
for j = 1:256
for k = 1:256
fwrite(RemergedFID, lowFrame(k,j), 'uint8');
fwrite(RemergedFID, highFrame(k,j), 'uint8');
end
end
有没有更好更快的方法来写出这样的东西?
我可以建议创建一个 16 位帧,其中 16 位帧中每个像素的上半部分对应于 lowFrame
,而 16 位帧中的另一半对应于 highFrame
。你的措辞表明相反,但你在 MATLAB 中编写结果的方式表明我刚才所说的。我将采用您在代码中编写它的方式,但您可以根据自己的需要进行更改。
在任何情况下,只需将 lowFrame
和 bitshift
的所有位都左移 8,然后 将此结果添加 highFrame
得到连接的结果。通过将一帧向左移动 8 位,您可以在添加时为另一帧留出空间以占据下半部分。然后,您将立即将整个数组写入文件。请记住,当您将数组写入文件时,数组以 column-major 格式写入。这意味着当您将数组写入文件时,列 会堆叠在一起形成一个连续的块并写入文件。我不知道您最终要将其用于什么应用程序,但是如果您想要 行-主要格式,其中 行堆叠在一个连续的块中,您需要在写入之前先转置此输出帧。因此,做这样的事情:
lowFrame = uint16(lowFrame);
highFrame = uint16(highFrame);
outFrame = bitshift(lowFrame, 8) + highFrame;
fwrite(RemergedFID, outFrame, 'uint16');
%fwrite(RemergedFID, outFrame.', 'uint16'); %// Use this if you want row-major
重要的是我们投射帧的前两行代码,假设它们是 uint8
,到 uint16
。我们必须这样做才能使位移位起作用。如果我们将其保留为 uint8
,位移只会使类型饱和,因此向左移动 8 位只会给出最大值 255
。第三行神奇地允许您将来自两个帧的位连接在一起作为单个 16 位字,然后将结果写入文件。
就性能而言,这肯定比遍历像素快,因为位移位几乎不需要时间,因为它是一个原子操作 - 加法也是如此。
reshape
and typecast
的组合可以在Matlab中做你想做的事情:
%% // optional, in case your frames are not always 256x256
nLine = size(highFrame,1) ;
nCol = size(highFrame,2) ;
%% // if you like the "black magic" effect, in one line:
FullFrame = reshape( typecast( reshape( [lowFrame(:) highFrame(:)].' , [] , nLine*nCol*2 ) , 'uint16') , nLine , [] ) ; %'//
fwrite(RemergedFID, FullFrame, 'uint16'); %// then write the full matrix in one go
如果不喜欢冗长晦涩的台词,可以分解成:
%% // merge the 2x uint8 frames into a single uint16 frame (lower endian ordering)
FullFrame = [lowFrame(:) highFrame(:)] ; %// Make a double column with high and low bytes in lower endian ordering
FullFrame = reshape( FullFrame.' , [] , nLine*nCol*2 ) ; %'// Reshape the transpose to get one single line vector
FullFrame = typecast( FullFrame , 'uint16') ; %// cast every 2 uint8 value into a uint16 value (lower endian ordering)
FullFrame = reshape( FullFrame , nLine , [] ) ; %// reshape that into an m*n matrix
fwrite(RemergedFID, FullFrame, 'uint16'); %// then write the full matrix in one go
Matlab 和大多数pc 将使用lower endian byte ordering 来对超过8 位的值进行排序。除非你正在为一个你知道将特别大端排序的系统编写文件(一些嵌入式处理器是),否则我建议你坚持使用低端,或者更好的是,让 Matlab 或你的系统处理它。