File: read_rle_rgbe.m

package info (click to toggle)
psychtoolbox-3 3.0.19.14.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 86,796 kB
  • sloc: ansic: 176,245; cpp: 20,103; objc: 5,393; sh: 2,753; python: 1,397; php: 384; makefile: 193; java: 113
file content (139 lines) | stat: -rw-r--r-- 4,610 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
% read_rle_rgbe
%
% Written by Lawrence A. Taplin (taplin@cis.rit.edu)
%
% Based loosely on the c-code RGBE implementation written by Bruce Walters
% http://www.graphics.cornell.edu/~bjw/rgbe.html
%
% function to read a run length encoded RGBE picture file and header. This
% does not work if the image is not RLE!!!
%
% Note to Psychtoolbox users: Please use the higher level HDRRead.m routine
% for better generality in your code. This routine is used as helper for
% HDRRead.
%
function [img, fileinfo] = read_rle_rgbe(filename)
%open the file
fid = fopen(filename,'r');

%read the magic number
tline = fgetl(fid);
if length(tline) < 3 || ~strcmp(tline(1:2), '#?')
    error('invalid header');
end
fileinfo.identifier = tline(3:end);

%read the header variables into a structure
tline = fgetl(fid);
while ~isempty(tline)
    %find and set the variable name
    n = strfind(tline,'=');
    if ~isempty(n) % skip stuff I don't understand
        vname = lower(tline(1:n(1)-1));
        vval = tline(n+1:end);
        fileinfo = setfield(fileinfo,vname,vval); %#ok<SFLD>
        %fprintf('Variable = %s, Value = %s\n',vname, vval);
    end
    %read the next line
    tline = fgetl(fid);
end

%set the resolution variables
tline = fgetl(fid);
fileinfo.Ysign = tline(1);
[fileinfo.height,~,~,nextindex] = sscanf(tline(4:end),'%d',1);
fileinfo.Xsign = tline(nextindex+4);
[fileinfo.width] = sscanf(tline(nextindex+7:end),'%d',1);
%fprintf('resolution: %s\n',tline);

%allocate space for the scan line data
img = zeros(fileinfo.height, fileinfo.width, 3);

%read the scanline data
if strcmp(fileinfo.format, '32-bit_rle_rgbe')
    %fprintf('Decoding RLE Data stream\n');
end

%read the remaining data
data = fread(fid,inf,'uint8');
fclose(fid);

scanline_width = fileinfo.width;
num_scanlines = fileinfo.height;

if ((scanline_width < 8) || (scanline_width > 32767))
    % run length encoding is not allowed so read flat
    img = rgbe2float(reshape(data,fileinfo.width,fileinfo.height,4));
    return;
end

scanline_buffer = repmat(uint8(0),scanline_width,4);
dp = 1; %set the data pointer to the begining of the read data

% read in each successive scanline */
for scanline=1:num_scanlines
%     if mod(scanline,fix(num_scanlines/100))==0
%         fprintf('scanline = %d\n',scanline);
%     end
%     
    if (data(dp) ~= 2) || (data(dp+1) ~= 2)% || (bitget(data(dp+2),8)~=1)
        error('this file is not run length encoded');
    end
    
    if (bitshift(data(dp+2),8)+data(dp+3))~=scanline_width % -128
        error('wrong scanline width');
    end
    
    dp = dp+4;
    
    % read each of the four channels read the scanline into the buffer
    for i=1:4 
        ptr = 1;
        while(ptr <= scanline_width)
            if (data(dp) > 128) % a run of the same value
                count = data(dp)-128;
                if ((count == 0) || (count-1 > scanline_width - ptr))
                    warning('bad scanline data');
                end
                scanline_buffer(ptr:ptr+count-1,i) = data(dp+1);
                dp = dp+2;
                ptr = ptr+count;
            else % a non-run
                count = data(dp);
                dp = dp+1;
                if ((count == 0) || (count-1 > scanline_width - ptr))
                    warning('bad scanline data');
                end
                scanline_buffer(ptr:ptr+count-1,i) = data(dp:dp+count-1);
                ptr = ptr+count;
                dp = dp+count;
            end
        end
    end
    
    % now convert data from buffer into floats
    img(scanline,:,:) = rgbe2float(scanline_buffer);
end

% standard conversion from float pixels to rgbe pixels
% the last dimension is assumed to be color
function [rgbe] = float2rgbe(rgb)  %#ok<DEFNU>
s = size(rgb);
rgb = reshape(rgb,prod(s)/3,3);
rgbe = reshape(repmat(uint8(0),[s(1:end-1),4]),prod(s)/3,4);
v = max(rgb,[],2); %find max rgb
l = find(v>1e-32); %find non zero pixel list
rgbe(l,4) = uint8(round(128.5+log(v)/log(2))); %find E
rgbe(l,1:3) = uint8(rgb(l,1:3)./repmat(2.^(double(rgbe(l,4))-128-8),1,3)); %find rgb multiplier
reshape(rgbe,[s(1:end-1),4]); %reshape back to original dimensions

% standard conversion from rgbe to float pixels */
% note: Ward uses ldexp(col+0.5,exp-(128+8)).  However we wanted pixels */
%       in the range [0,1] to map back into the range [0,1].            */
function [rgb] = rgbe2float(rgbe)
s = size(rgbe);
rgbe = reshape(rgbe,prod(s)/4,4);
rgb = zeros(prod(s)/4,3);
l = find(rgbe(:,4)>0); %nonzero pixel list
rgb(l,:) = double(rgbe(l,1:3)).*repmat(2.^(double(rgbe(l,4))-128-8),1,3);
rgb = reshape(rgb,[s(1:end-1),3]);