rad
rad

Reputation: 179

How to unpack 12bit 'Mono12Packed' number

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

Answers (1)

Rotem
Rotem

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

Related Questions