Path: news.mathworks.com!newsfeed-00.mathworks.com!panix!bloom-beacon.mit.edu!llnews!53ab2750!not-for-mail
From: Peter Boettcher <boettcher@ll.mit.edu>
Newsgroups: comp.soft-sys.matlab
Subject: Re: load & display multichannel images quickly
References: <fvviut$kf3$1@fred.mathworks.com>
Message-ID: <muy63toh6j4.fsf@G99-Boettcher.llan.ll.mit.edu>
Organization: MIT Lincoln Laboratory
User-Agent: Gnus/5.110006 (No Gnus v0.6) Emacs/23.0.0 (gnu/linux)
Cancel-Lock: sha1:QjNzp/bEjFIL9GXKuwpOg3oGP/k=
MIME-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Lines: 82
Date: Thu, 08 May 2008 16:42:23 -0400
NNTP-Posting-Host: 155.34.163.114
X-Complaints-To: news@ll.mit.edu
X-Trace: llnews 1210278701 155.34.163.114 (Thu, 08 May 2008 16:31:41 EDT)
NNTP-Posting-Date: Thu, 08 May 2008 16:31:41 EDT
Xref: news.mathworks.com comp.soft-sys.matlab:467488


"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