/* |
|
* Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. |
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
* |
|
* This code is free software; you can redistribute it and/or modify it |
|
* under the terms of the GNU General Public License version 2 only, as |
|
* published by the Free Software Foundation. Oracle designates this |
|
* particular file as subject to the "Classpath" exception as provided |
|
* by Oracle in the LICENSE file that accompanied this code. |
|
* |
|
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
* version 2 for more details (a copy is included in the LICENSE file that |
|
* accompanied this code). |
|
* |
|
* You should have received a copy of the GNU General Public License version |
|
* 2 along with this work; if not, write to the Free Software Foundation, |
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
* |
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
* or visit www.oracle.com if you need additional information or have any |
|
* questions. |
|
*/ |
|
package com.sun.imageio.plugins.common; |
|
import java.awt.Point; |
|
import java.awt.Rectangle; |
|
import java.io.IOException; |
|
import javax.imageio.stream.ImageInputStream; |
|
/** |
|
* This class contains utility methods that may be useful to ImageReader |
|
* plugins. Ideally these methods would be in the ImageReader base class |
|
* so that all subclasses could benefit from them, but that would be an |
|
* addition to the existing API, and it is not yet clear whether these methods |
|
* are universally useful, so for now we will leave them here. |
|
*/ |
|
public class ReaderUtil { |
|
// Helper for computeUpdatedPixels method |
|
private static void computeUpdatedPixels(int sourceOffset, |
|
int sourceExtent, |
|
int destinationOffset, |
|
int dstMin, |
|
int dstMax, |
|
int sourceSubsampling, |
|
int passStart, |
|
int passExtent, |
|
int passPeriod, |
|
int[] vals, |
|
int offset) |
|
{ |
|
// We need to satisfy the congruences: |
|
// dst = destinationOffset + (src - sourceOffset)/sourceSubsampling |
|
// |
|
// src - passStart == 0 (mod passPeriod) |
|
// src - sourceOffset == 0 (mod sourceSubsampling) |
|
// |
|
// subject to the inequalities: |
|
// |
|
// src >= passStart |
|
// src < passStart + passExtent |
|
// src >= sourceOffset |
|
// src < sourceOffset + sourceExtent |
|
// dst >= dstMin |
|
// dst <= dstmax |
|
// |
|
// where |
|
// |
|
// dst = destinationOffset + (src - sourceOffset)/sourceSubsampling |
|
// |
|
// For now we use a brute-force approach although we could |
|
// attempt to analyze the congruences. If passPeriod and |
|
// sourceSubsamling are relatively prime, the period will be |
|
// their product. If they share a common factor, either the |
|
// period will be equal to the larger value, or the sequences |
|
// will be completely disjoint, depending on the relationship |
|
// between passStart and sourceOffset. Since we only have to do this |
|
// twice per image (once each for X and Y), it seems cheap enough |
|
// to do it the straightforward way. |
|
boolean gotPixel = false; |
|
int firstDst = -1; |
|
int secondDst = -1; |
|
int lastDst = -1; |
|
for (int i = 0; i < passExtent; i++) { |
|
int src = passStart + i*passPeriod; |
|
if (src < sourceOffset) { |
|
continue; |
|
} |
|
if ((src - sourceOffset) % sourceSubsampling != 0) { |
|
continue; |
|
} |
|
if (src >= sourceOffset + sourceExtent) { |
|
break; |
|
} |
|
int dst = destinationOffset + |
|
(src - sourceOffset)/sourceSubsampling; |
|
if (dst < dstMin) { |
|
continue; |
|
} |
|
if (dst > dstMax) { |
|
break; |
|
} |
|
if (!gotPixel) { |
|
firstDst = dst; // Record smallest valid pixel |
|
gotPixel = true; |
|
} else if (secondDst == -1) { |
|
secondDst = dst; // Record second smallest valid pixel |
|
} |
|
lastDst = dst; // Record largest valid pixel |
|
} |
|
vals[offset] = firstDst; |
|
// If we never saw a valid pixel, set width to 0 |
|
if (!gotPixel) { |
|
vals[offset + 2] = 0; |
|
} else { |
|
vals[offset + 2] = lastDst - firstDst + 1; |
|
} |
|
// The period is given by the difference of any two adjacent pixels |
|
vals[offset + 4] = Math.max(secondDst - firstDst, 1); |
|
} |
|
/** |
|
* A utility method that computes the exact set of destination |
|
* pixels that will be written during a particular decoding pass. |
|
* The intent is to simplify the work done by readers in combining |
|
* the source region, source subsampling, and destination offset |
|
* information obtained from the <code>ImageReadParam</code> with |
|
* the offsets and periods of a progressive or interlaced decoding |
|
* pass. |
|
* |
|
* @param sourceRegion a <code>Rectangle</code> containing the |
|
* source region being read, offset by the source subsampling |
|
* offsets, and clipped against the source bounds, as returned by |
|
* the <code>getSourceRegion</code> method. |
|
* @param destinationOffset a <code>Point</code> containing the |
|
* coordinates of the upper-left pixel to be written in the |
|
* destination. |
|
* @param dstMinX the smallest X coordinate (inclusive) of the |
|
* destination <code>Raster</code>. |
|
* @param dstMinY the smallest Y coordinate (inclusive) of the |
|
* destination <code>Raster</code>. |
|
* @param dstMaxX the largest X coordinate (inclusive) of the destination |
|
* <code>Raster</code>. |
|
* @param dstMaxY the largest Y coordinate (inclusive) of the destination |
|
* <code>Raster</code>. |
|
* @param sourceXSubsampling the X subsampling factor. |
|
* @param sourceYSubsampling the Y subsampling factor. |
|
* @param passXStart the smallest source X coordinate (inclusive) |
|
* of the current progressive pass. |
|
* @param passYStart the smallest source Y coordinate (inclusive) |
|
* of the current progressive pass. |
|
* @param passWidth the width in pixels of the current progressive |
|
* pass. |
|
* @param passHeight the height in pixels of the current progressive |
|
* pass. |
|
* @param passPeriodX the X period (horizontal spacing between |
|
* pixels) of the current progressive pass. |
|
* @param passPeriodY the Y period (vertical spacing between |
|
* pixels) of the current progressive pass. |
|
* |
|
* @return an array of 6 <code>int</code>s containing the |
|
* destination min X, min Y, width, height, X period and Y period |
|
* of the region that will be updated. |
|
*/ |
|
public static int[] computeUpdatedPixels(Rectangle sourceRegion, |
|
Point destinationOffset, |
|
int dstMinX, |
|
int dstMinY, |
|
int dstMaxX, |
|
int dstMaxY, |
|
int sourceXSubsampling, |
|
int sourceYSubsampling, |
|
int passXStart, |
|
int passYStart, |
|
int passWidth, |
|
int passHeight, |
|
int passPeriodX, |
|
int passPeriodY) |
|
{ |
|
int[] vals = new int[6]; |
|
computeUpdatedPixels(sourceRegion.x, sourceRegion.width, |
|
destinationOffset.x, |
|
dstMinX, dstMaxX, sourceXSubsampling, |
|
passXStart, passWidth, passPeriodX, |
|
vals, 0); |
|
computeUpdatedPixels(sourceRegion.y, sourceRegion.height, |
|
destinationOffset.y, |
|
dstMinY, dstMaxY, sourceYSubsampling, |
|
passYStart, passHeight, passPeriodY, |
|
vals, 1); |
|
return vals; |
|
} |
|
public static int readMultiByteInteger(ImageInputStream iis) |
|
throws IOException |
|
{ |
|
int value = iis.readByte(); |
|
int result = value & 0x7f; |
|
while((value & 0x80) == 0x80) { |
|
result <<= 7; |
|
value = iis.readByte(); |
|
result |= (value & 0x7f); |
|
} |
|
return result; |
|
} |
|
} |