[ 
https://issues.apache.org/jira/browse/SANSELAN-58?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13259230#comment-13259230
 ] 

Gary Lucas commented on SANSELAN-58:
------------------------------------

I have reworked this code based on comments received on my earlier submissions 
and am uploading a patch titled Tracker_Item_58_22_Apr_2012.  Please disregard 
my earlier patch.

In particular, I have tried to keep the changes narrowly focused and easy to 
follow. This patch affects only the strip reader for TIFF files.   It is based 
on the latest trunk of the code as of today.

In testing with large TIFF files, this enhancement reduces the reading time of 
a TIFF file by more than 50 percent. 



 
                
> Streamlined TIFF strip reader reduces load time by a factor of 5
> ----------------------------------------------------------------
>
>                 Key: SANSELAN-58
>                 URL: https://issues.apache.org/jira/browse/SANSELAN-58
>             Project: Commons Sanselan
>          Issue Type: Improvement
>            Reporter: Gary Lucas
>         Attachments: Sanselan-58-TiffStripReaderSpeed.patch
>
>   Original Estimate: 1h
>  Remaining Estimate: 1h
>
> Testing reveals that streamlining the DataReaderStrip.java operations for 8 
> and 24 bit-per-pixel TIFF images reduces the TIFF file load time by a factor 
> of 5.  
> For each pixel in images of these types, the interpretStrip() method of 
> DataReaderStrip makes calls to a generic bit extractor using its 
> getSamplesAsBytes() method.  Internally, this method simply copies the 
> requisite number of bytes (8 or 24), but it executes a lot of conditional 
> statements to do so.  Under most architectures, conditionals tend to take 2 
> to 3 times as long to execute as simple arithmetic statements, so this 
> approach is expensive (especially since an image may contain millions of 
> pixels).  While the implementation is very generic, the majority of TIFF 
> files out there appear to fall into two simple categories.  By implementing 
> specialized code for these two cases, the loading time for TIFF images is 
> dramatically reduced.
> The following snippet shows the code I used for testing.  It was added right 
> at the beginning of the interpretStrip() method.
>  // Oct 2011 changes.
>         //  The general case decoder is based on the idea of using a 
>         //  generic bit-reader to unpack the number of bytes that are
>         //  needed.  Although it is efficiently implemented, it does
>         //  require performing at least three conditional branches per sample
>         //  extracted (and often more).   This change attempts to bypass that
>         //  overhead by implementing specialized blocks of extraction code
>         //  for commonly used 8 bitsPerPixel and 24 bitsPerPixel cases.
>         //  In other cases, it will simply fall through to the original code.
>         //    note that when promoting a byte to an integer, it is necessary
>         //    to mask it with 0xff because the Java byte type is signed
>         //    an this implementation requires an unsigned value
>         if(x>=width)
>         {
>             // this may not be required.  it was coded based on the 
>             // original implementation.  But looking at the TIFF 6.0 spec,
>             // it looks like the rows always evenly fill out the strip,
>             // so there should never be a partial row in a strip and x
>             // should not be anything except zero.
>             x = 0;
>             y++;
>         }
>         if(y>=height)
>         {
>             // we check it once before starting, so that we don't have
>             // to check it redundantly for each pixel
>             return;
>         }
>         
>         if(predictor==-1 && this.bitsPerPixel==8)
>         {
>             int [] samples = new int[1];
>             for(int i=0; i<pixels_per_strip; i++)
>             {
>                 samples[0] = bytes[i]&0x000000ff;
>                 photometricInterpreter.interpretPixel(bi, samples, x, y);
>                 x++;
>                 if(x>=width)
>                 {
>                     x = 0;
>                     y++;
>                     if(y>=height)
>                         return; // any remaining bytes are not needed
>                 }
>             } 
>             return;    
>         }
>         else if(predictor==-1 && this.bitsPerPixel==24)
>         {
>             int [] samples = new int[3];
>             int k = 0;
>             for(int i=0; i<pixels_per_strip; i++)
>             {
>                 samples[0] = bytes[k++]&0x000000ff;
>                 samples[1] = bytes[k++]&0x000000ff;
>                 samples[2] = bytes[k++]&0x000000ff;
>                 photometricInterpreter.interpretPixel(bi, samples, x, y);
>                 x++;
>                 if(x>=width)
>                 {
>                     x = 0;
>                     y++;
>                     if(y>=height)
>                         return; // any remaining bytes are not needed
>                 }
>             }   
>             return;
>         }
>         
>         // original code before Oct 2011 modification
>         ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
>         BitInputStream bis = new BitInputStream(bais);
> etc.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to