001: /*
002: * $RCSfile: TIFFNullDecompressor.java,v $
003: *
004: *
005: * Copyright (c) 2005 Sun Microsystems, Inc. All Rights Reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * - Redistribution of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * - Redistribution in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * Neither the name of Sun Microsystems, Inc. or the names of
020: * contributors may be used to endorse or promote products derived
021: * from this software without specific prior written permission.
022: *
023: * This software is provided "AS IS," without a warranty of any
024: * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
025: * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
026: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
027: * EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
028: * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
029: * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
030: * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
031: * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
032: * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
033: * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
034: * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
035: * POSSIBILITY OF SUCH DAMAGES.
036: *
037: * You acknowledge that this software is not designed or intended for
038: * use in the design, construction, operation or maintenance of any
039: * nuclear facility.
040: *
041: * $Revision: 1.1 $
042: * $Date: 2005/02/11 05:01:48 $
043: * $State: Exp $
044: */
045: package com.sun.media.imageioimpl.plugins.tiff;
046:
047: import java.io.IOException;
048: import com.sun.media.imageio.plugins.tiff.TIFFDecompressor;
049:
050: public class TIFFNullDecompressor extends TIFFDecompressor {
051:
052: private static final boolean DEBUG = false; // XXX false for release!
053:
054: /**
055: * Whether to read the active source region only.
056: */
057: private boolean isReadActiveOnly = false;
058:
059: /** The original value of <code>srcMinX</code>. */
060: private int originalSrcMinX;
061:
062: /** The original value of <code>srcMinY</code>. */
063: private int originalSrcMinY;
064:
065: /** The original value of <code>srcWidth</code>. */
066: private int originalSrcWidth;
067:
068: /** The original value of <code>srcHeight</code>. */
069: private int originalSrcHeight;
070:
071: public TIFFNullDecompressor() {
072: }
073:
074: //
075: // This approach to reading the active reading is a hack of sorts
076: // as the original values of the entire source region are stored,
077: // overwritten, and then restored. It would probably be better to
078: // revise TIFFDecompressor such that this were not necessary, i.e.,
079: // change beginDecoding() and decode() to use the active region values
080: // when random access is easy and the entire region values otherwise.
081: //
082: public void beginDecoding() {
083: // Determine number of bits per pixel.
084: int bitsPerPixel = 0;
085: for (int i = 0; i < bitsPerSample.length; i++) {
086: bitsPerPixel += bitsPerSample[i];
087: }
088:
089: // Can read active region only if row starts on a byte boundary.
090: if ((activeSrcMinX != srcMinX || activeSrcMinY != srcMinY
091: || activeSrcWidth != srcWidth || activeSrcHeight != srcHeight)
092: && ((activeSrcMinX - srcMinX) * bitsPerPixel) % 8 == 0) {
093: // Set flag.
094: isReadActiveOnly = true;
095:
096: // Cache original region.
097: originalSrcMinX = srcMinX;
098: originalSrcMinY = srcMinY;
099: originalSrcWidth = srcWidth;
100: originalSrcHeight = srcHeight;
101:
102: // Replace region with active region.
103: srcMinX = activeSrcMinX;
104: srcMinY = activeSrcMinY;
105: srcWidth = activeSrcWidth;
106: srcHeight = activeSrcHeight;
107: } else {
108: // Clear flag.
109: isReadActiveOnly = false;
110: }
111:
112: if (DEBUG) {
113: if (isReadActiveOnly) {
114: System.out.println("Reading active region.");
115: System.out.println("source region: "
116: + new java.awt.Rectangle(originalSrcMinX,
117: originalSrcMinY, originalSrcWidth,
118: originalSrcHeight));
119: System.out.println("active region: "
120: + new java.awt.Rectangle(activeSrcMinX,
121: activeSrcMinY, activeSrcWidth,
122: activeSrcHeight));
123: } else {
124: System.out.println("Reading entire region.");
125: System.out.println("source region: "
126: + new java.awt.Rectangle(srcMinX, srcMinY,
127: srcWidth, srcHeight));
128: }
129: System.out.println("destination region: "
130: + new java.awt.Rectangle(dstMinX, dstMinY,
131: dstWidth, dstHeight));
132: }
133:
134: super .beginDecoding();
135: }
136:
137: public void decode() throws IOException {
138: super .decode();
139:
140: // Reset state.
141: if (isReadActiveOnly) {
142: // Restore original source region values.
143: srcMinX = originalSrcMinX;
144: srcMinY = originalSrcMinY;
145: srcWidth = originalSrcWidth;
146: srcHeight = originalSrcHeight;
147:
148: // Unset flag.
149: isReadActiveOnly = false;
150: }
151: }
152:
153: public void decodeRaw(byte[] b, int dstOffset, int bitsPerPixel,
154: int scanlineStride) throws IOException {
155: if (isReadActiveOnly) {
156: // Read the active source region only.
157:
158: int activeBytesPerRow = (activeSrcWidth * bitsPerPixel + 7) / 8;
159: int totalBytesPerRow = (originalSrcWidth * bitsPerPixel + 7) / 8;
160: int bytesToSkipPerRow = totalBytesPerRow
161: - activeBytesPerRow;
162:
163: //
164: // Seek to the start of the active region:
165: //
166: // active offset = original offset +
167: // number of bytes to start of first active row +
168: // number of bytes to first active pixel within row
169: //
170: // Since the condition for reading from the active region only is
171: //
172: // ((activeSrcMinX - srcMinX)*bitsPerPixel) % 8 == 0
173: //
174: // the bit offset to the first active pixel within the first
175: // active row is a multiple of 8.
176: //
177: stream
178: .seek(offset
179: + (activeSrcMinY - originalSrcMinY)
180: * totalBytesPerRow
181: + ((activeSrcMinX - originalSrcMinX) * bitsPerPixel)
182: / 8);
183:
184: int lastRow = activeSrcHeight - 1;
185: for (int y = 0; y < activeSrcHeight; y++) {
186: stream.read(b, dstOffset, activeBytesPerRow);
187: dstOffset += scanlineStride;
188:
189: // Skip unneeded bytes (row suffix + row prefix).
190: if (y != lastRow) {
191: stream.skipBytes(bytesToSkipPerRow);
192: }
193: }
194: } else {
195: // Read the entire source region.
196: stream.seek(offset);
197: int bytesPerRow = (srcWidth * bitsPerPixel + 7) / 8;
198: if (bytesPerRow == scanlineStride) {
199: stream.read(b, dstOffset, bytesPerRow * srcHeight);
200: } else {
201: for (int y = 0; y < srcHeight; y++) {
202: stream.read(b, dstOffset, bytesPerRow);
203: dstOffset += scanlineStride;
204: }
205: }
206: }
207: }
208: }
|