/imageio/imageio-core/src/main/java/com/twelvemonkeys/imageio/stream/SubImageInputStream.java

https://github.com/conceptboard/TwelveMonkeys · Java · 100 lines · 62 code · 18 blank · 20 comment · 6 complexity · aa0f8403a600e6bd4b8e9ca97c5bab29 MD5 · raw file

  1. package com.twelvemonkeys.imageio.stream;
  2. import com.twelvemonkeys.lang.Validate;
  3. import javax.imageio.stream.ImageInputStream;
  4. import javax.imageio.stream.ImageInputStreamImpl;
  5. import java.io.IOException;
  6. /**
  7. * A wrapper for {@link ImageInputStream} to limit the number of bytes that can be read.
  8. *
  9. * @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
  10. * @author last modified by $Author: haraldk$
  11. * @version $Id: SubImageInputStream.java,v 1.0 Nov 8, 2009 2:50:58 PM haraldk Exp$
  12. */
  13. public final class SubImageInputStream extends ImageInputStreamImpl {
  14. // NOTE: This class is based on com.sun.imageio.plugins.common.SubImageInputStream, but fixes some of its bugs.
  15. private final ImageInputStream stream;
  16. private final long startPos;
  17. private final long length;
  18. /**
  19. * Creates a {@link ImageInputStream}, reading up to a maximum number of bytes from the underlying stream.
  20. *
  21. * @param pStream the underlying stream
  22. * @param pLength the maximum length to read from the stream.
  23. * Note that {@code pStream} may contain less than this maximum number of bytes.
  24. *
  25. * @throws IOException if {@code pStream}'s position can't be determined.
  26. * @throws IllegalArgumentException if {@code pStream == null} or {@code pLength < 0}
  27. */
  28. public SubImageInputStream(final ImageInputStream pStream, final long pLength) throws IOException {
  29. Validate.notNull(pStream, "stream");
  30. Validate.isTrue(pLength >= 0, pLength, "length < 0: %d");
  31. stream = pStream;
  32. startPos = pStream.getStreamPosition();
  33. length = pLength;
  34. }
  35. public int read() throws IOException {
  36. if (streamPos >= length) { // Local EOF
  37. return -1;
  38. }
  39. else {
  40. int read = stream.read();
  41. if (read >= 0) {
  42. streamPos++;
  43. }
  44. return read;
  45. }
  46. }
  47. public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
  48. if (streamPos >= length) { // Local EOF
  49. return -1;
  50. }
  51. // Safe cast, as pLength can never cause int overflow
  52. int length = (int) Math.min(pLength, this.length - streamPos);
  53. int count = stream.read(pBytes, pOffset, length);
  54. if (count >= 0) {
  55. streamPos += count;
  56. }
  57. return count;
  58. }
  59. @Override
  60. public long length() {
  61. try {
  62. long length = stream.length();
  63. return length < 0 ? -1 : Math.min(length - startPos, this.length);
  64. }
  65. catch (IOException ignore) {
  66. }
  67. return -1;
  68. }
  69. @Override
  70. public void seek(final long pPosition) throws IOException {
  71. if (pPosition < getFlushedPosition()) {
  72. throw new IndexOutOfBoundsException("pos < flushedPosition");
  73. }
  74. stream.seek(startPos + pPosition);
  75. streamPos = pPosition;
  76. }
  77. @SuppressWarnings({"FinalizeDoesntCallSuperFinalize"})
  78. @Override
  79. protected void finalize() throws Throwable {
  80. // Empty finalizer (for improved performance; no need to call super.finalize() in this case)
  81. }
  82. }