[ https://issues.apache.org/jira/browse/IMAGING-69?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Damjan Jovanovic resolved IMAGING-69. ------------------------------------- Resolution: Fixed Fix Version/s: 1.0 Patch applied, thank you for your contribution. Resolving fixed. > Streamlined TIFF strip reader reduces load time by a factor of 5 > ---------------------------------------------------------------- > > Key: IMAGING-69 > URL: https://issues.apache.org/jira/browse/IMAGING-69 > Project: Apache Commons Imaging > Issue Type: Improvement > Reporter: Gary Lucas > Fix For: 1.0 > > Attachments: ApacheImagingTrackerItem69_May_30_2012.patch, > ApacheImagingTrackerItem69_May_9_2012.patch, > Sanselan-58-TiffStripReaderSpeed.patch, Tracker_Item_58_22_Apr_2012.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