JDK-6348744 : PNGImageReader should skip metadata if ignoreMetadata=true
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.imageio
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_9
  • CPU: generic
  • Submitted: 2005-11-10
  • Updated: 2008-02-05
  • Resolved: 2005-12-05
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
6 b63Fixed
PNGImageReader currently reads all image metadata, even if the ignoreMetadata flag
is set.  We can reduce overhead and improve performance of reading small PNG images
if we skip those metadata blocks when ignoreMetadata=true.

EVALUATION The main fix is pretty simple. If ignoreMetadata is set, then we can skip over all metadata chunks until we reach the first IDAT chunk. We need to be careful to only apply this optimization for non-palette images, since we need the tRNS chunk in order to read palette images properly. There are some other minor performance tweaks we can make at this time as well: - Use StringBuilder instead of StringBuffer (not likely to have much impact, but it's an easy change to make). - Use a switch block instead of if/else in the loop that reads metadata chunks. In order to do so, we first need to make the *_TYPE constants truly constant (currently they are calculated at runtime, which in itself is unnecessary work at class load time, and prevents us from using a switch statement). The improvement from this change is likely very small, but it's a good change to make so that in theory we are taking advantage of some recent VM optimizations for jump tables. - In PNGImageReader.readHeader(), there is one place where we call stream.readUnsignedByte() 5x in a row. As discovered in 6347575, this can lead to many system calls, so it would be better to do a bulk read of these 5 unsigned byte values. This accounts for a modest reduction in overhead. - In PNGImageReader.skipPass(), we allocate a temporary scanline byte[] and call readFully() in order to skip one scanline at a time. This represents unnecessary work; it would be preferable to call skipBytes(), as we do in other parts of the reader code. With these changes in place, J2DBench tests show a modest (2-4%) improvement in reading small PNG images. The test images being loaded by J2DBench have a very small number of metadata chunks; I've tested some real world PNG files outside of J2DBench that have more metadata, and I've found that performance is improved by up to 10% for these images when ignoreMetadata is set. Here are the J2DBench results for solaris-sparc, SB2000, 900 MHz USIII, 1GB RAM, -client, source is an on-disk (blank) PNG file (base is 1.6.0-b60, test is similar with the changes listed above): imageio.input.image.imageio.reader.opts.ignoreMetadata=false,imageio.opts.size=1: base: 1.595049105 (var=2.37%) (100.0%) test: 1.625115298 (var=2.91%) (101.88%) imageio.input.image.imageio.reader.opts.ignoreMetadata=false,imageio.opts.size=20: base: 579.6923076 (var=0.15%) (100.0%) test: 592.8594130 (var=1.71%) (102.27%) imageio.input.image.imageio.reader.opts.ignoreMetadata=true,imageio.opts.size=1: base: 1.607404860 (var=0.95%) (100.0%) test: 1.648932603 (var=1.69%) (102.58%) imageio.input.image.imageio.reader.opts.ignoreMetadata=true,imageio.opts.size=20: base: 565.3443811 (var=2.89%) (100.0%) test: 589.0425645 (var=3.29%) (104.19%)