Reputation: 179
I have a data from image sensor (2560x2160 pixels) encoded as Mono12Packed.
This encoding is defined as:
Byte 0: Pixel 1 (bits 4:11)
Byte 1: Pixel 1 (bits 0:3), Pixel 2 (bits 0:3)
Byte 3: Pixel 2 (bits 4:11)
To unpack this data I use two different codes:
The first one reads the data as 12bit (so I get half of the values 'for free') and then I work on the other half.
fseek(fid, 0, 'bof');
raw = fread(fid, 2560*2160, 'ubit12');
raw(1:2:end) = arrayfun( ...
@(x) bitor(bitand(bitshift(x, 4), 4095), bitshift(x, -8)), ...
raw(1:2:end) ...
);
dat = reshape(raw, [2560, 2160]);
The second one uses more 'standard' approach when the data are readed byte by byte.
raw = fread(fid, ceil(2560*2160*1.5), 'ubit8');
dat = zeros(2560*2160, 1);
for i = 1:3:ceil(2560*2160*1.5)
p1 = bitor(bitshift(raw(i), 4), bitand(raw(i+1), 15));
p2 = bitor(bitshift(raw(i+2), 4), bitand(bitshift(raw(i+1), -4), 15));
dat(ceil(i/1.5)) = p1;
dat(ceil(i/1.5)+1) = p2;
end;
dat = reshape(dat2, [2560, 2160]);
Even though the second one is much faster (surprisingly for me), both are terribly slow. I am sure it could be speeded up by vectorization the loop, I just don't know how.
Or maybe there is another solution how to unpack such data as they seems to be quite common.
BTW, can anybody explain to me why are the data ordered in this way and not 'in a row'?
Thanks
Upvotes: 1
Views: 731
Reputation: 32084
Vectorized version of your for loop:
dat(1:2:end) = bitor(bitshift(raw(1:3:end), 4), bitand(raw(2:3:end), 15));
dat(2:2:end) = bitor(bitshift(raw(3:3:end), 4), bitand(bitshift(raw(2:3:end), -4), 15));
I used the following code for testing:
%Create input data for testing:
I = (0:4095)';
J = zeros(1, numel(I)*1.5);
%Byte 0: Pixel 1 (bits 4:11)
%Byte 1: Pixel 1 (bits 0:3), Pixel 2 (bits 0:3)
%Byte 3: Pixel 2 (bits 4:11)
J(1:3:end) = floor(I(1:2:end) / 16);
J(2:3:end) = mod(I(2:2:end), 16)*16 + mod(I(1:2:end), 16);
J(3:3:end) = floor(I(2:2:end)/16);
f = fopen('raw12.bin', 'w');
fwrite(f, J, 'uint8');
fclose(f);
len = numel(I);
fid = fopen('raw12.bin', 'r');
raw = fread(fid, len*1.5, 'ubit8');
dat = zeros(len, 1);
dat(1:2:end) = bitor(bitshift(raw(1:3:end), 4), bitand(raw(2:3:end), 15));
dat(2:2:end) = bitor(bitshift(raw(3:3:end), 4), bitand(bitshift(raw(2:3:end), -4), 15));
% for i = 1:3:len*1.5
% p1 = bitor(bitshift(raw(i), 4), bitand(raw(i+1), 15));
% p2 = bitor(bitshift(raw(i+2), 4), bitand(bitshift(raw(i+1), -4), 15));
% dat(ceil(i/1.5)) = p1;
% dat(ceil(i/1.5)+1) = p2;
% end
%%dat = reshape(dat2, [2560, 2160]);
fclose(fid);
%Verify dat = I
all(dat == I)
Upvotes: 1