[
https://issues.apache.org/jira/browse/SANSELAN-58?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Gary Lucas updated SANSELAN-58:
-------------------------------
Attachment: Sanselan-58-TiffStripReaderSpeed.patch
The following patch affects a file that was included in my patch for
Sanselan-56. I wasn't sure about the right way to handle that, so I made it
so that this patch is based only on the existing code base. So if you decide
you can't use Sanselan-56, you can still use this patch. However, if you do
use 56, the two patches should be compatible as long as you do 56 first and
then 58.
> 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