Path: news.mathworks.com!not-for-mail
From: "jay vaughan" <jvaughan5.nospam@gmail.com>
Newsgroups: comp.soft-sys.matlab
Subject: Re: load & display multichannel images quickly
Date: Thu, 8 May 2008 22:57:03 +0000 (UTC)
Organization: harvard
Lines: 120
Message-ID: <g000fv$iac$1@fred.mathworks.com>
References: <fvviut$kf3$1@fred.mathworks.com> <muy63toh6j4.fsf@G99-Boettcher.llan.ll.mit.edu>
Reply-To: "jay vaughan" <jvaughan5.nospam@gmail.com>
NNTP-Posting-Host: webapp-02-blr.mathworks.com
Content-Type: text/plain; charset="ISO-8859-1"
Content-Transfer-Encoding: 8bit
X-Trace: fred.mathworks.com 1210287423 18764 172.30.248.37 (8 May 2008 22:57:03 GMT)
X-Complaints-To: news@mathworks.com
NNTP-Posting-Date: Thu, 8 May 2008 22:57:03 +0000 (UTC)
X-Newsreader: MATLAB Central Newsreader 1215048
Xref: news.mathworks.com comp.soft-sys.matlab:467510


Peter Boettcher <boettcher@ll.mit.edu> wrote in message
<muy63toh6j4.fsf@G99-Boettcher.llan.ll.mit.edu>...
> "jay vaughan" <jvaughan5.nospam@gmail.com> writes:
> 
> > Hi again,
> >
> > I am trying to optimize the speed of loading in three 
> > MxN arrays and assigning them to an 8 bit MxNx3 array 
> > (RGB) to be displayed.
> >
> > It's a sensitive part of a GUI I am working on, but
> > I am having trouble optimizing it. A shortened version of
> > the code is at the bottom.
> >
> > One problem is that if the floor and ceiling inputs,
> > (contrast/brightness parameters), are doubles then 
> > MATLAB executes the code too slowly I presume since 
> > it is converting the term (255/(c1-f1)) from double 
> > to uint8. If the floor and ceiling inputs are uint8, 
> > MATLAB executes the code more quickly but then 
> > rounds the factor (255/(c1-f1)) before multiplying,
> > which reduces the bit depth of the contrast pretty 
> > badly.
> >
> > The speed is close to what I need (a factor of 2 
> > improvement would be great), but I am not sure how
> > to speed things up further.
> >
> > Sometimes when I find myself in this kind of pickle
> > it means I am going about the problem the wrong way.
> > For instance, is there be a better solution with
> > some clever way of adjusting the colormapping 
> > rather than adjusting the data itself?
> >
> > Thanks,
> > J
> >
> > % initialize frame
> > frame_size = [256 256];
> > frame = zeros(frame_size(1),frame_size(2),3,'uint8');
> >
> > % get floor & ceiling inputs (min & max in data channels)
> > f1 = 10; f2 = 10; f3 = 10;
> > c1 = 10; c2 = 10; c3 = 10;
> >
> > % M maps data channels (row) to RGB weight (column)
> > M = [1 0 0; 0 1 0; 0 0 1]; 
> >
> > % read in the three data channels
> > ch1 = (fread(fid1, frame_size, '*uint8')-f1)*(255/(c1-f1));
> > ch2 = (fread(fid2, frame_size, '*uint8')-f2)*(255/(c2-f2));
> > ch3 = (fread(fid3, frame_size, '*uint8')-f3)*(255/(c3-f3));
> >
> > % map the channels to the RGB frame for display
> > frame(:,:,1) = M(1,1)*ch1 + M(1,2)*ch2 + M(1,3)*ch3;
> > frame(:,:,2) = M(2,1)*ch2 + M(2,2)*ch2 + M(2,3)*ch3;
> > frame(:,:,3) = M(3,1)*ch3 + M(3,2)*ch2 + M(3,3)*ch3;
> >
> > image(frame)
> 
> You're right, casts to and from floating point are very
slow.  I would
> stay in integer, but expand to an integer, do the
operations, and return
> to uint8.  Careful with the operation ordering.
> 
> f1 = uint32(10);
> c1 = uint32(100);
> 
> t = fread(fid1, frame_size, '*uint8');
> ch1 = (uint32(255) * (uint32(t) - f1)) / (c1 - f1)
> 
> By doing the multiply by 255 first, you don't have any
precision
> problems, and the uint32 can hold the full range.
> 
> Actually, you're even better off calculating the gain as a
fixed
> point value, so that each operation is only a multiply
followed by a
> power-of-2 divide.  Hopefully MATLAB does a shift for an
integer
> power-of-2 divide.  If not, do it yourself with "bitshift".
> 
> gain = uint32(256*256) / (c1 - f1);
> 
> ch1 = gain * (uint32(t) - f1) / 256;
> 
> 
> -Peter


Hi Peter,

thanks for the suggestions. I tried to implement them but it
didn't improve things. Perhaps I implemented them
incorrectly? (See attempts 3 & 4.)

% attempt 1: speed ok (0.0137 sec) but poor gain resolution
f1 = 10; 
c1 = 10;
ch1 = (fread(fid1, frame_size, '*uint8')-f1)*(255/(c1-f1));

% attempt 2: slow (0.025 sec) but poor gain resolution
f1 = 10; 
c1 = 10;
ch1=(fread(fid1,frame_size,'*uint8')-f1)*(255/double(c1-f1));

% attempt 3: slow (0.025 sec) but poor gain resolution
f1 = uint32(10);
c1 = uint32(10);
ch1 =
uint8(uint32(255)*(uint32(fread(fid1,frame_size,'*uint8')-f1)/(c1-f1)));

% attempt 4: slow (0.025 sec) but has good gain resolution
f1 = uint32(10); % MATLAB f1 & c1 to be uint32 not uint8
c1 = uint32(10);
gain = uint32(256*256)/(channel_ceiling-channel_floor);
ch1=uint8(gain*(uint32(fread(fid,frame_size,'*uint8'))-f)/256);