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]);
|