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 */ 045package com.github.jaiimageio.impl.plugins.tiff; 046 047import java.io.IOException; 048 049import com.github.jaiimageio.plugins.tiff.TIFFDecompressor; 050 051public class TIFFNullDecompressor extends TIFFDecompressor { 052 053 private static final boolean DEBUG = false; // XXX false for release! 054 055 /** 056 * Whether to read the active source region only. 057 */ 058 private boolean isReadActiveOnly = false; 059 060 /** The original value of <code>srcMinX</code>. */ 061 private int originalSrcMinX; 062 063 /** The original value of <code>srcMinY</code>. */ 064 private int originalSrcMinY; 065 066 /** The original value of <code>srcWidth</code>. */ 067 private int originalSrcWidth; 068 069 /** The original value of <code>srcHeight</code>. */ 070 private int originalSrcHeight; 071 072 public TIFFNullDecompressor() {} 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, 118 originalSrcWidth, 119 originalSrcHeight)); 120 System.out.println("active region: "+ 121 new java.awt.Rectangle(activeSrcMinX, 122 activeSrcMinY, 123 activeSrcWidth, 124 activeSrcHeight)); 125 } else { 126 System.out.println("Reading entire region."); 127 System.out.println("source region: "+ 128 new java.awt.Rectangle(srcMinX, 129 srcMinY, 130 srcWidth, 131 srcHeight)); 132 } 133 System.out.println("destination region: "+ 134 new java.awt.Rectangle(dstMinX, 135 dstMinY, 136 dstWidth, 137 dstHeight)); 138 } 139 140 super.beginDecoding(); 141 } 142 143 public void decode() throws IOException { 144 super.decode(); 145 146 // Reset state. 147 if(isReadActiveOnly) { 148 // Restore original source region values. 149 srcMinX = originalSrcMinX; 150 srcMinY = originalSrcMinY; 151 srcWidth = originalSrcWidth; 152 srcHeight = originalSrcHeight; 153 154 // Unset flag. 155 isReadActiveOnly = false; 156 } 157 } 158 159 public void decodeRaw(byte[] b, 160 int dstOffset, 161 int bitsPerPixel, 162 int scanlineStride) throws IOException { 163 if(isReadActiveOnly) { 164 // Read the active source region only. 165 166 int activeBytesPerRow = (activeSrcWidth*bitsPerPixel + 7)/8; 167 int totalBytesPerRow = (originalSrcWidth*bitsPerPixel + 7)/8; 168 int bytesToSkipPerRow = totalBytesPerRow - activeBytesPerRow; 169 170 // 171 // Seek to the start of the active region: 172 // 173 // active offset = original offset + 174 // number of bytes to start of first active row + 175 // number of bytes to first active pixel within row 176 // 177 // Since the condition for reading from the active region only is 178 // 179 // ((activeSrcMinX - srcMinX)*bitsPerPixel) % 8 == 0 180 // 181 // the bit offset to the first active pixel within the first 182 // active row is a multiple of 8. 183 // 184 stream.seek(offset + 185 (activeSrcMinY - originalSrcMinY)*totalBytesPerRow + 186 ((activeSrcMinX - originalSrcMinX)*bitsPerPixel)/8); 187 188 int lastRow = activeSrcHeight - 1; 189 for (int y = 0; y < activeSrcHeight; y++) { 190 stream.read(b, dstOffset, activeBytesPerRow); 191 dstOffset += scanlineStride; 192 193 // Skip unneeded bytes (row suffix + row prefix). 194 if(y != lastRow) { 195 stream.skipBytes(bytesToSkipPerRow); 196 } 197 } 198 } else { 199 // Read the entire source region. 200 stream.seek(offset); 201 int bytesPerRow = (srcWidth*bitsPerPixel + 7)/8; 202 if(bytesPerRow == scanlineStride) { 203 stream.read(b, dstOffset, bytesPerRow*srcHeight); 204 } else { 205 for (int y = 0; y < srcHeight; y++) { 206 stream.read(b, dstOffset, bytesPerRow); 207 dstOffset += scanlineStride; 208 } 209 } 210 } 211 } 212}