1 /* 2 * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.imageio.plugins.common; 27 28 import java.awt.Point; 29 import java.awt.Rectangle; 30 import java.io.IOException; 31 import javax.imageio.stream.ImageInputStream; 32 33 /** 34 * This class contains utility methods that may be useful to ImageReader 35 * plugins. Ideally these methods would be in the ImageReader base class 36 * so that all subclasses could benefit from them, but that would be an 37 * addition to the existing API, and it is not yet clear whether these methods 38 * are universally useful, so for now we will leave them here. 39 */ 40 public class ReaderUtil { 41 42 // Helper for computeUpdatedPixels method 43 private static void computeUpdatedPixels(int sourceOffset, 44 int sourceExtent, 45 int destinationOffset, 46 int dstMin, 47 int dstMax, 48 int sourceSubsampling, 49 int passStart, 50 int passExtent, 51 int passPeriod, 52 int[] vals, 53 int offset) 54 { 55 // We need to satisfy the congruences: 56 // dst = destinationOffset + (src - sourceOffset)/sourceSubsampling 57 // 58 // src - passStart == 0 (mod passPeriod) 59 // src - sourceOffset == 0 (mod sourceSubsampling) 60 // 61 // subject to the inequalities: 62 // 63 // src >= passStart 64 // src < passStart + passExtent 65 // src >= sourceOffset 66 // src < sourceOffset + sourceExtent 67 // dst >= dstMin 68 // dst <= dstmax 69 // 70 // where 71 // 72 // dst = destinationOffset + (src - sourceOffset)/sourceSubsampling 73 // 74 // For now we use a brute-force approach although we could 75 // attempt to analyze the congruences. If passPeriod and 76 // sourceSubsamling are relatively prime, the period will be 77 // their product. If they share a common factor, either the 78 // period will be equal to the larger value, or the sequences 79 // will be completely disjoint, depending on the relationship 80 // between passStart and sourceOffset. Since we only have to do this 81 // twice per image (once each for X and Y), it seems cheap enough 82 // to do it the straightforward way. 83 84 boolean gotPixel = false; 85 int firstDst = -1; 86 int secondDst = -1; 87 int lastDst = -1; 88 89 for (int i = 0; i < passExtent; i++) { 90 int src = passStart + i*passPeriod; 91 if (src < sourceOffset) { 92 continue; 93 } 94 if ((src - sourceOffset) % sourceSubsampling != 0) { 95 continue; 96 } 97 if (src >= sourceOffset + sourceExtent) { 98 break; 99 } 100 101 int dst = destinationOffset + 102 (src - sourceOffset)/sourceSubsampling; 103 if (dst < dstMin) { 104 continue; 105 } 106 if (dst > dstMax) { 107 break; 108 } 109 110 if (!gotPixel) { 111 firstDst = dst; // Record smallest valid pixel 112 gotPixel = true; 113 } else if (secondDst == -1) { 114 secondDst = dst; // Record second smallest valid pixel 115 } 116 lastDst = dst; // Record largest valid pixel 117 } 118 119 vals[offset] = firstDst; 120 121 // If we never saw a valid pixel, set width to 0 122 if (!gotPixel) { 123 vals[offset + 2] = 0; 124 } else { 125 vals[offset + 2] = lastDst - firstDst + 1; 126 } 127 128 // The period is given by the difference of any two adjacent pixels 129 vals[offset + 4] = Math.max(secondDst - firstDst, 1); 130 } 131 132 /** 133 * A utility method that computes the exact set of destination 134 * pixels that will be written during a particular decoding pass. 135 * The intent is to simplify the work done by readers in combining 136 * the source region, source subsampling, and destination offset 137 * information obtained from the {@code ImageReadParam} with 138 * the offsets and periods of a progressive or interlaced decoding 139 * pass. 140 * 141 * @param sourceRegion a {@code Rectangle} containing the 142 * source region being read, offset by the source subsampling 143 * offsets, and clipped against the source bounds, as returned by 144 * the {@code getSourceRegion} method. 145 * @param destinationOffset a {@code Point} containing the 146 * coordinates of the upper-left pixel to be written in the 147 * destination. 148 * @param dstMinX the smallest X coordinate (inclusive) of the 149 * destination {@code Raster}. 150 * @param dstMinY the smallest Y coordinate (inclusive) of the 151 * destination {@code Raster}. 152 * @param dstMaxX the largest X coordinate (inclusive) of the destination 153 * {@code Raster}. 154 * @param dstMaxY the largest Y coordinate (inclusive) of the destination 155 * {@code Raster}. 156 * @param sourceXSubsampling the X subsampling factor. 157 * @param sourceYSubsampling the Y subsampling factor. 158 * @param passXStart the smallest source X coordinate (inclusive) 159 * of the current progressive pass. 160 * @param passYStart the smallest source Y coordinate (inclusive) 161 * of the current progressive pass. 162 * @param passWidth the width in pixels of the current progressive 163 * pass. 164 * @param passHeight the height in pixels of the current progressive 165 * pass. 166 * @param passPeriodX the X period (horizontal spacing between 167 * pixels) of the current progressive pass. 168 * @param passPeriodY the Y period (vertical spacing between 169 * pixels) of the current progressive pass. 170 * 171 * @return an array of 6 {@code int}s containing the 172 * destination min X, min Y, width, height, X period and Y period 173 * of the region that will be updated. 174 */ 175 public static int[] computeUpdatedPixels(Rectangle sourceRegion, 176 Point destinationOffset, 177 int dstMinX, 178 int dstMinY, 179 int dstMaxX, 180 int dstMaxY, 181 int sourceXSubsampling, 182 int sourceYSubsampling, 183 int passXStart, 184 int passYStart, 185 int passWidth, 186 int passHeight, 187 int passPeriodX, 188 int passPeriodY) 189 { 190 int[] vals = new int[6]; 191 computeUpdatedPixels(sourceRegion.x, sourceRegion.width, 192 destinationOffset.x, 193 dstMinX, dstMaxX, sourceXSubsampling, 194 passXStart, passWidth, passPeriodX, 195 vals, 0); 196 computeUpdatedPixels(sourceRegion.y, sourceRegion.height, 197 destinationOffset.y, 198 dstMinY, dstMaxY, sourceYSubsampling, 199 passYStart, passHeight, passPeriodY, 200 vals, 1); 201 return vals; 202 } 203 204 public static int readMultiByteInteger(ImageInputStream iis) 205 throws IOException 206 { 207 int value = iis.readByte(); 208 int result = value & 0x7f; 209 while((value & 0x80) == 0x80) { 210 result <<= 7; 211 value = iis.readByte(); 212 result |= (value & 0x7f); 213 } 214 return result; 215 } 216 } --- EOF ---