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</code> with
 138      * the offsets and periods of a progressive or interlaced decoding
 139      * pass.
 140      *
 141      * @param sourceRegion a <code>Rectangle</code> 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</code> method.
 145      * @param destinationOffset a <code>Point</code> 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</code>.
 150      * @param dstMinY the smallest Y coordinate (inclusive) of the
 151      * destination <code>Raster</code>.
 152      * @param dstMaxX the largest X coordinate (inclusive) of the destination
 153      * <code>Raster</code>.
 154      * @param dstMaxY the largest Y coordinate (inclusive) of the destination
 155      * <code>Raster</code>.
 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</code>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 ---