New code style. No functional changes.

This commit is contained in:
Harald Kuhr
2011-02-17 12:36:40 +01:00
parent 191643a36c
commit 43cc440e67
60 changed files with 1671 additions and 1665 deletions

View File

@@ -41,21 +41,24 @@ import java.util.ArrayList;
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/AbstractImageSource.java#1 $
*/
public abstract class AbstractImageSource implements ImageProducer {
private List<ImageConsumer> mConsumers = new ArrayList<ImageConsumer>();
protected int mWidth;
protected int mHeight;
protected int mXOff;
protected int mYOff;
private List<ImageConsumer> consumers = new ArrayList<ImageConsumer>();
protected int width;
protected int height;
protected int xOff;
protected int yOff;
// ImageProducer interface
public void addConsumer(ImageConsumer pConsumer) {
if (mConsumers.contains(pConsumer)) {
public void addConsumer(final ImageConsumer pConsumer) {
if (consumers.contains(pConsumer)) {
return;
}
mConsumers.add(pConsumer);
consumers.add(pConsumer);
try {
initConsumer(pConsumer);
sendPixels(pConsumer);
if (isConsumer(pConsumer)) {
pConsumer.imageComplete(ImageConsumer.STATICIMAGEDONE);
@@ -68,34 +71,35 @@ public abstract class AbstractImageSource implements ImageProducer {
}
catch (Exception e) {
e.printStackTrace();
if (isConsumer(pConsumer)) {
pConsumer.imageComplete(ImageConsumer.IMAGEERROR);
}
}
}
public void removeConsumer(ImageConsumer pConsumer) {
mConsumers.remove(pConsumer);
public void removeConsumer(final ImageConsumer pConsumer) {
consumers.remove(pConsumer);
}
/**
* This implementation silently ignores this instruction. If pixeldata is
* This implementation silently ignores this instruction. If pixel data is
* not in TDLR order by default, subclasses must override this method.
*
* @param pConsumer the consumer that requested the resend
*
* @see ImageProducer#requestTopDownLeftRightResend(java.awt.image.ImageConsumer)
*/
public void requestTopDownLeftRightResend(ImageConsumer pConsumer) {
public void requestTopDownLeftRightResend(final ImageConsumer pConsumer) {
// ignore
}
public void startProduction(ImageConsumer pConsumer) {
public void startProduction(final ImageConsumer pConsumer) {
addConsumer(pConsumer);
}
public boolean isConsumer(ImageConsumer pConsumer) {
return mConsumers.contains(pConsumer);
public boolean isConsumer(final ImageConsumer pConsumer) {
return consumers.contains(pConsumer);
}
protected abstract void initConsumer(ImageConsumer pConsumer);

View File

@@ -47,33 +47,34 @@ import java.io.IOException;
*/
public class AreaAverageOp implements BufferedImageOp, RasterOp {
final private int mWidth;
final private int mHeight;
final private int width;
final private int height;
private Rectangle mSourceRegion;
private Rectangle sourceRegion;
public AreaAverageOp(final int pWidth, final int pHeight) {
mWidth = pWidth;
mHeight = pHeight;
width = pWidth;
height = pHeight;
}
public Rectangle getSourceRegion() {
if (mSourceRegion == null) {
if (sourceRegion == null) {
return null;
}
return new Rectangle(mSourceRegion);
return new Rectangle(sourceRegion);
}
public void setSourceRegion(final Rectangle pSourceRegion) {
if (pSourceRegion == null) {
mSourceRegion = null;
sourceRegion = null;
}
else {
if (mSourceRegion == null) {
mSourceRegion = new Rectangle(pSourceRegion);
if (sourceRegion == null) {
sourceRegion = new Rectangle(pSourceRegion);
}
else {
mSourceRegion.setBounds(pSourceRegion);
sourceRegion.setBounds(pSourceRegion);
}
}
}
@@ -93,7 +94,7 @@ public class AreaAverageOp implements BufferedImageOp, RasterOp {
long start = System.currentTimeMillis();
// Straight-forward version
//Image scaled = src.getScaledInstance(mWidth, mHeight, Image.SCALE_AREA_AVERAGING);
//Image scaled = src.getScaledInstance(width, height, Image.SCALE_AREA_AVERAGING);
//ImageUtil.drawOnto(result, scaled);
//result = new BufferedImageFactory(scaled).getBufferedImage();
@@ -104,7 +105,7 @@ public class AreaAverageOp implements BufferedImageOp, RasterOp {
AffineTransform xform = null;
int w = src.getWidth();
int h = src.getHeight();
while (w / 2 > mWidth && h / 2 > mHeight) {
while (w / 2 > width && h / 2 > height) {
w /= 2;
h /= 2;
@@ -129,7 +130,7 @@ public class AreaAverageOp implements BufferedImageOp, RasterOp {
src = temp.getSubimage(0, 0, w, h);
}
resample(src, result, AffineTransform.getScaleInstance(mWidth / (double) w, mHeight / (double) h));
resample(src, result, AffineTransform.getScaleInstance(width / (double) w, height / (double) h));
*/
// The real version
@@ -160,11 +161,11 @@ public class AreaAverageOp implements BufferedImageOp, RasterOp {
private WritableRaster filterImpl(Raster src, WritableRaster dest) {
//System.out.println("src: " + src);
//System.out.println("dest: " + dest);
if (mSourceRegion != null) {
int cx = mSourceRegion.x;
int cy = mSourceRegion.y;
int cw = mSourceRegion.width;
int ch = mSourceRegion.height;
if (sourceRegion != null) {
int cx = sourceRegion.x;
int cy = sourceRegion.y;
int cw = sourceRegion.width;
int ch = sourceRegion.height;
boolean same = src == dest;
dest = dest.createWritableChild(cx, cy, cw, ch, 0, 0, null);
@@ -179,11 +180,11 @@ public class AreaAverageOp implements BufferedImageOp, RasterOp {
// TODO: This don't work too well..
// The thing is that the step length and the scan length will vary, for
// non-even (1/2, 1/4, 1/8 etc) resampling
int widthSteps = (width + mWidth - 1) / mWidth;
int heightSteps = (height + mHeight - 1) / mHeight;
int widthSteps = (width + this.width - 1) / this.width;
int heightSteps = (height + this.height - 1) / this.height;
final boolean oddX = width % mWidth != 0;
final boolean oddY = height % mHeight != 0;
final boolean oddX = width % this.width != 0;
final boolean oddY = height % this.height != 0;
final int dataElements = src.getNumDataElements();
final int bands = src.getNumBands();
@@ -210,16 +211,16 @@ public class AreaAverageOp implements BufferedImageOp, RasterOp {
}
}
for (int y = 0; y < mHeight; y++) {
if (!oddY || y < mHeight) {
for (int y = 0; y < this.height; y++) {
if (!oddY || y < this.height) {
scanH = heightSteps;
}
else {
scanH = height - (y * heightSteps);
}
for (int x = 0; x < mWidth; x++) {
if (!oddX || x < mWidth) {
for (int x = 0; x < this.width; x++) {
if (!oddX || x < this.width) {
scanW = widthSteps;
}
else {
@@ -243,8 +244,8 @@ public class AreaAverageOp implements BufferedImageOp, RasterOp {
//
//System.err.println("width: " + width);
//System.err.println("height: " + height);
//System.err.println("mWidth: " + mWidth);
//System.err.println("mHeight: " + mHeight);
//System.err.println("width: " + width);
//System.err.println("height: " + height);
//
//e.printStackTrace();
continue;
@@ -382,20 +383,20 @@ public class AreaAverageOp implements BufferedImageOp, RasterOp {
public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel destCM) {
ColorModel cm = destCM != null ? destCM : src.getColorModel();
return new BufferedImage(cm,
ImageUtil.createCompatibleWritableRaster(src, cm, mWidth, mHeight),
ImageUtil.createCompatibleWritableRaster(src, cm, width, height),
cm.isAlphaPremultiplied(), null);
}
public WritableRaster createCompatibleDestRaster(Raster src) {
return src.createCompatibleWritableRaster(mWidth, mHeight);
return src.createCompatibleWritableRaster(width, height);
}
public Rectangle2D getBounds2D(Raster src) {
return new Rectangle(mWidth, mHeight);
return new Rectangle(width, height);
}
public Rectangle2D getBounds2D(BufferedImage src) {
return new Rectangle(mWidth, mHeight);
return new Rectangle(width, height);
}
public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {

View File

@@ -67,7 +67,7 @@ public class BrightnessContrastFilter extends RGBImageFilter {
}
// Use a precalculated lookup table for performace
private int[] mLUT = null;
private final int[] LUT;
/**
* Creates a BrightnessContrastFilter with default values
@@ -105,7 +105,7 @@ public class BrightnessContrastFilter extends RGBImageFilter {
* {@code -1.0,..,0.0,..,1.0}.
*/
public BrightnessContrastFilter(float pBrightness, float pContrast) {
mLUT = createLUT(pBrightness, pContrast);
LUT = createLUT(pBrightness, pContrast);
}
private static int[] createLUT(float pBrightness, float pContrast) {
@@ -157,9 +157,9 @@ public class BrightnessContrastFilter extends RGBImageFilter {
int b = pARGB & 0xFF;
// Scale to new contrast
r = mLUT[r];
g = mLUT[g];
b = mLUT[b];
r = LUT[r];
g = LUT[g];
b = LUT[b];
// Return ARGB pixel, leave transparency as is
return (pARGB & 0xFF000000) | (r << 16) | (g << 8) | b;

View File

@@ -28,11 +28,14 @@
package com.twelvemonkeys.image;
import com.twelvemonkeys.lang.Validate;
import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.util.List;
import java.lang.reflect.Array;
import java.util.EventListener;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
@@ -52,50 +55,53 @@ import java.util.concurrent.CopyOnWriteArrayList;
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/BufferedImageFactory.java#1 $
*/
public final class BufferedImageFactory {
private List<ProgressListener> mListeners;
private int mPercentageDone;
private List<ProgressListener> listeners;
private int percentageDone;
private ImageProducer mProducer;
private boolean mError;
private boolean mFetching;
private boolean mReadColorModelOnly;
private ImageProducer producer;
private boolean error;
private volatile boolean fetching;
private boolean readColorModelOnly;
private int mX = 0;
private int mY = 0;
private int mWidth = -1;
private int mHeight = -1;
private int x = 0;
private int y = 0;
private int width = -1;
private int height = -1;
private int mXSub = 1;
private int mYSub = 1;
private int xSub = 1;
private int ySub = 1;
private int mOffset;
private int mScanSize;
private int offset;
private int scanSize;
private ColorModel mSourceColorModel;
private Hashtable mSourceProperties; // ImageConsumer API dictates Hashtable
private ColorModel sourceColorModel;
private Hashtable sourceProperties; // ImageConsumer API dictates Hashtable
private Object mSourcePixels;
private Object sourcePixels;
private BufferedImage mBuffered;
private ColorModel mColorModel;
private BufferedImage buffered;
private ColorModel colorModel;
// NOTE: Just to not expose the inheritance
private final Consumer mConsumer = new Consumer();
private final Consumer consumer = new Consumer();
/**
* Creates a {@code BufferedImageFactory}.
* @param pSource the source image
* @throws IllegalArgumentException if {@code pSource == null}
*/
public BufferedImageFactory(final Image pSource) {
this(pSource.getSource());
this(pSource != null ? pSource.getSource() : null);
}
/**
* Creates a {@code BufferedImageFactory}.
* @param pSource the source image producer
* @throws IllegalArgumentException if {@code pSource == null}
*/
public BufferedImageFactory(final ImageProducer pSource) {
mProducer = pSource;
Validate.notNull(pSource, "source");
producer = pSource;
}
/**
@@ -109,7 +115,7 @@ public final class BufferedImageFactory {
*/
public BufferedImage getBufferedImage() throws ImageConversionException {
doFetch(false);
return mBuffered;
return buffered;
}
/**
@@ -123,7 +129,7 @@ public final class BufferedImageFactory {
*/
public ColorModel getColorModel() throws ImageConversionException {
doFetch(true);
return mBuffered != null ? mBuffered.getColorModel() : mColorModel;
return buffered != null ? buffered.getColorModel() : colorModel;
}
/**
@@ -131,15 +137,15 @@ public final class BufferedImageFactory {
*/
public void dispose() {
freeResources();
mBuffered = null;
mColorModel = null;
buffered = null;
colorModel = null;
}
/**
* Aborts the image production.
*/
public void abort() {
mConsumer.imageComplete(ImageConsumer.IMAGEABORTED);
consumer.imageComplete(ImageConsumer.IMAGEABORTED);
}
/**
@@ -149,14 +155,14 @@ public final class BufferedImageFactory {
*/
public void setSourceRegion(final Rectangle pRegion) {
// Re-fetch everything, if region changed
if (mX != pRegion.x || mY != pRegion.y || mWidth != pRegion.width || mHeight != pRegion.height) {
if (x != pRegion.x || y != pRegion.y || width != pRegion.width || height != pRegion.height) {
dispose();
}
mX = pRegion.x;
mY = pRegion.y;
mWidth = pRegion.width;
mHeight = pRegion.height;
x = pRegion.x;
y = pRegion.y;
width = pRegion.width;
height = pRegion.height;
}
/**
@@ -167,50 +173,51 @@ public final class BufferedImageFactory {
*/
public void setSourceSubsampling(int pXSub, int pYSub) {
// Re-fetch everything, if subsampling changed
if (mXSub != pXSub || mYSub != pYSub) {
if (xSub != pXSub || ySub != pYSub) {
dispose();
}
if (pXSub > 1) {
mXSub = pXSub;
xSub = pXSub;
}
if (pYSub > 1) {
mYSub = pYSub;
ySub = pYSub;
}
}
private synchronized void doFetch(boolean pColorModelOnly) throws ImageConversionException {
if (!mFetching && (!pColorModelOnly && mBuffered == null || mBuffered == null && mSourceColorModel == null)) {
if (!fetching && (!pColorModelOnly && buffered == null || buffered == null && sourceColorModel == null)) {
// NOTE: Subsampling is only applied if extracting full image
if (!pColorModelOnly && (mXSub > 1 || mYSub > 1)) {
if (!pColorModelOnly && (xSub > 1 || ySub > 1)) {
// If only sampling a region, the region must be scaled too
if (mWidth > 0 && mHeight > 0) {
mWidth = (mWidth + mXSub - 1) / mXSub;
mHeight = (mHeight + mYSub - 1) / mYSub;
if (width > 0 && height > 0) {
width = (width + xSub - 1) / xSub;
height = (height + ySub - 1) / ySub;
mX = (mX + mXSub - 1) / mXSub;
mY = (mY + mYSub - 1) / mYSub;
x = (x + xSub - 1) / xSub;
y = (y + ySub - 1) / ySub;
}
mProducer = new FilteredImageSource(mProducer, new SubsamplingFilter(mXSub, mYSub));
producer = new FilteredImageSource(producer, new SubsamplingFilter(xSub, ySub));
}
// Start fetching
mFetching = true;
mReadColorModelOnly = pColorModelOnly;
mProducer.startProduction(mConsumer); // Note: If single-thread (synchronous), this call will block
fetching = true;
readColorModelOnly = pColorModelOnly;
producer.startProduction(consumer); // Note: If single-thread (synchronous), this call will block
// Wait until the producer wakes us up, by calling imageComplete
while (mFetching) {
while (fetching) {
try {
wait();
wait(200l);
}
catch (InterruptedException e) {
throw new ImageConversionException("Image conversion aborted: " + e.getMessage(), e);
}
}
if (mError) {
if (error) {
throw new ImageConversionException("Image conversion failed: ImageConsumer.IMAGEERROR.");
}
@@ -224,21 +231,21 @@ public final class BufferedImageFactory {
}
private void createColorModel() {
mColorModel = mSourceColorModel;
colorModel = sourceColorModel;
// Clean up, in case any objects are copied/cloned, so we can free resources
freeResources();
}
private void createBuffered() {
if (mWidth > 0 && mHeight > 0) {
if (mSourceColorModel != null && mSourcePixels != null) {
if (width > 0 && height > 0) {
if (sourceColorModel != null && sourcePixels != null) {
// TODO: Fix pixel size / color model problem
WritableRaster raster = ImageUtil.createRaster(mWidth, mHeight, mSourcePixels, mSourceColorModel);
mBuffered = new BufferedImage(mSourceColorModel, raster, mSourceColorModel.isAlphaPremultiplied(), mSourceProperties);
WritableRaster raster = ImageUtil.createRaster(width, height, sourcePixels, sourceColorModel);
buffered = new BufferedImage(sourceColorModel, raster, sourceColorModel.isAlphaPremultiplied(), sourceProperties);
}
else {
mBuffered = ImageUtil.createClear(mWidth, mHeight, null);
buffered = ImageUtil.createClear(width, height, null);
}
}
@@ -247,21 +254,21 @@ public final class BufferedImageFactory {
}
private void freeResources() {
mSourceColorModel = null;
mSourcePixels = null;
mSourceProperties = null;
sourceColorModel = null;
sourcePixels = null;
sourceProperties = null;
}
private void processProgress(int mScanline) {
if (mListeners != null) {
int percent = 100 * mScanline / mHeight;
if (listeners != null) {
int percent = 100 * mScanline / height;
//System.out.println("Progress: " + percent + "%");
if (percent > mPercentageDone) {
mPercentageDone = percent;
if (percent > percentageDone) {
percentageDone = percent;
for (ProgressListener listener : mListeners) {
for (ProgressListener listener : listeners) {
listener.progress(this, percent);
}
}
@@ -278,11 +285,11 @@ public final class BufferedImageFactory {
return;
}
if (mListeners == null) {
mListeners = new CopyOnWriteArrayList<ProgressListener>();
if (listeners == null) {
listeners = new CopyOnWriteArrayList<ProgressListener>();
}
mListeners.add(pListener);
listeners.add(pListener);
}
/**
@@ -295,19 +302,19 @@ public final class BufferedImageFactory {
return;
}
if (mListeners == null) {
if (listeners == null) {
return;
}
mListeners.remove(pListener);
listeners.remove(pListener);
}
/**
* Removes all progress listeners from this factory.
*/
public void removeAllProgressListeners() {
if (mListeners != null) {
mListeners.clear();
if (listeners != null) {
listeners.clear();
}
}
@@ -378,21 +385,21 @@ public final class BufferedImageFactory {
}
// Allocate array if necessary
if (mSourcePixels == null) {
if (sourcePixels == null) {
// Allocate a suitable source pixel array
// TODO: Should take pixel "width" into consideration, for byte packed rasters?!
// OR... Is anything but single-pixel models really supported by the API?
mSourcePixels = Array.newInstance(pPixels.getClass().getComponentType(), mWidth * mHeight);
mScanSize = mWidth;
mOffset = 0;
sourcePixels = Array.newInstance(pPixels.getClass().getComponentType(), width * height);
scanSize = width;
offset = 0;
}
else if (mSourcePixels.getClass() != pPixels.getClass()) {
else if (sourcePixels.getClass() != pPixels.getClass()) {
throw new IllegalStateException("Only one pixel type allowed");
}
// AOI stuff
if (pY < mY) {
int diff = mY - pY;
if (pY < y) {
int diff = y - pY;
if (diff >= pHeight) {
return;
}
@@ -400,15 +407,15 @@ public final class BufferedImageFactory {
pY += diff;
pHeight -= diff;
}
if (pY + pHeight > mY + mHeight) {
pHeight = (mY + mHeight) - pY;
if (pY + pHeight > y + height) {
pHeight = (y + height) - pY;
if (pHeight <= 0) {
return;
}
}
if (pX < mX) {
int diff = mX - pX;
if (pX < x) {
int diff = x - pX;
if (diff >= pWidth) {
return;
}
@@ -416,20 +423,20 @@ public final class BufferedImageFactory {
pX += diff;
pWidth -= diff;
}
if (pX + pWidth > mX + mWidth) {
pWidth = (mX + mWidth) - pX;
if (pX + pWidth > x + width) {
pWidth = (x + width) - pX;
if (pWidth <= 0) {
return;
}
}
int dstOffset = mOffset + (pY - mY) * mScanSize + (pX - mX);
int dstOffset = offset + (pY - y) * scanSize + (pX - x);
// Do the pixel copying
for (int i = pHeight; i > 0; i--) {
System.arraycopy(pPixels, pOffset, mSourcePixels, dstOffset, pWidth);
System.arraycopy(pPixels, pOffset, sourcePixels, dstOffset, pWidth);
pOffset += pScanSize;
dstOffset += mScanSize;
dstOffset += scanSize;
}
processProgress(pY + pHeight);
@@ -439,14 +446,14 @@ public final class BufferedImageFactory {
setPixelsImpl(pX, pY, pWidth, pHeight, pModel, pPixels, pOffset, pScanSize);
}
private void setColorModelOnce(ColorModel pModel) {
private void setColorModelOnce(final ColorModel pModel) {
// NOTE: There seems to be a "bug" in AreaAveragingScaleFilter, as it
// first passes the original color model through in setColorModel, then
// later replaces it with the default RGB in the first setPixels call
// (this is probably allowed according to the spec, but it's a waste of time and space).
if (mSourceColorModel != pModel) {
if (/*mSourceColorModel == null ||*/ mSourcePixels == null) {
mSourceColorModel = pModel;
if (sourceColorModel != pModel) {
if (/*sourceColorModel == null ||*/ sourcePixels == null) {
sourceColorModel = pModel;
}
else {
throw new IllegalStateException("Change of ColorModel after pixel delivery not supported");
@@ -454,23 +461,22 @@ public final class BufferedImageFactory {
}
// If color model is all we ask for, stop now
if (mReadColorModelOnly) {
mConsumer.imageComplete(ImageConsumer.IMAGEABORTED);
if (readColorModelOnly) {
consumer.imageComplete(ImageConsumer.IMAGEABORTED);
}
}
@SuppressWarnings({"ThrowableInstanceNeverThrown"})
public void imageComplete(int pStatus) {
mFetching = false;
fetching = false;
if (mProducer != null) {
mProducer.removeConsumer(this);
if (producer != null) {
producer.removeConsumer(this);
}
switch (pStatus) {
case ImageConsumer.IMAGEERROR:
new Error().printStackTrace();
mError = true;
Thread.dumpStack();
error = true;
break;
}
@@ -484,15 +490,15 @@ public final class BufferedImageFactory {
}
public void setDimensions(int pWidth, int pHeight) {
if (mWidth < 0) {
mWidth = pWidth - mX;
if (width < 0) {
width = pWidth - x;
}
if (mHeight < 0) {
mHeight = pHeight - mY;
if (height < 0) {
height = pHeight - y;
}
// Hmm.. Special case, but is it a good idea?
if (mWidth <= 0 || mHeight <= 0) {
if (width <= 0 || height <= 0) {
imageComplete(ImageConsumer.STATICIMAGEDONE);
}
}
@@ -530,7 +536,7 @@ public final class BufferedImageFactory {
}
public void setProperties(Hashtable pProperties) {
mSourceProperties = pProperties;
sourceProperties = pProperties;
}
}
}

View File

@@ -28,6 +28,8 @@
package com.twelvemonkeys.image;
import com.twelvemonkeys.lang.Validate;
import javax.swing.Icon;
import java.awt.image.BufferedImage;
import java.awt.*;
@@ -41,51 +43,44 @@ import java.awt.geom.AffineTransform;
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/BufferedImageIcon.java#2 $
*/
public class BufferedImageIcon implements Icon {
private final BufferedImage mImage;
private int mWidth;
private int mHeight;
private final boolean mFast;
private final BufferedImage image;
private int width;
private int height;
private final boolean fast;
public BufferedImageIcon(BufferedImage pImage) {
this(pImage, pImage.getWidth(), pImage.getHeight());
}
public BufferedImageIcon(BufferedImage pImage, int pWidth, int pHeight) {
if (pImage == null) {
throw new IllegalArgumentException("image == null");
}
if (pWidth <= 0 || pHeight <= 0) {
throw new IllegalArgumentException("Icon size must be positive");
}
image = Validate.notNull(pImage, "image");
width = Validate.isTrue(pWidth > 0, pWidth, "width must be positive: %d");
height = Validate.isTrue(pHeight > 0, pHeight, "height must be positive: %d");
mImage = pImage;
mWidth = pWidth;
mHeight = pHeight;
mFast = pImage.getWidth() == mWidth && pImage.getHeight() == mHeight;
fast = image.getWidth() == width && image.getHeight() == height;
}
public int getIconHeight() {
return mHeight;
return height;
}
public int getIconWidth() {
return mWidth;
return width;
}
public void paintIcon(Component c, Graphics g, int x, int y) {
if (mFast || !(g instanceof Graphics2D)) {
if (fast || !(g instanceof Graphics2D)) {
//System.out.println("Scaling fast");
g.drawImage(mImage, x, y, mWidth, mHeight, null);
g.drawImage(image, x, y, width, height, null);
}
else {
//System.out.println("Scaling using interpolation");
Graphics2D g2 = (Graphics2D) g;
AffineTransform xform = AffineTransform.getTranslateInstance(x, y);
xform.scale(mWidth / (double) mImage.getWidth(), mHeight / (double) mImage.getHeight());
xform.scale(width / (double) image.getWidth(), height / (double) image.getHeight());
g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2.drawImage(mImage, xform, null);
g2.drawImage(image, xform, null);
}
}
}

View File

@@ -73,14 +73,15 @@ public class ConvolveWithEdgeOp implements BufferedImageOp, RasterOp {
*/
public static final int EDGE_WRAP = 3; // as JAI BORDER_WRAP
private final Kernel mKernel;
private final int mEdgeCondition;
private final Kernel kernel;
private final int edgeCondition;
private final ConvolveOp mConvolve;
private final ConvolveOp convolve;
public ConvolveWithEdgeOp(final Kernel pKernel, final int pEdgeCondition, final RenderingHints pHints) {
// Create convolution operation
int edge;
switch (pEdgeCondition) {
case EDGE_REFLECT:
case EDGE_WRAP:
@@ -90,9 +91,10 @@ public class ConvolveWithEdgeOp implements BufferedImageOp, RasterOp {
edge = pEdgeCondition;
break;
}
mKernel = pKernel;
mEdgeCondition = pEdgeCondition;
mConvolve = new ConvolveOp(pKernel, edge, pHints);
kernel = pKernel;
edgeCondition = pEdgeCondition;
convolve = new ConvolveOp(pKernel, edge, pHints);
}
public ConvolveWithEdgeOp(final Kernel pKernel) {
@@ -107,8 +109,8 @@ public class ConvolveWithEdgeOp implements BufferedImageOp, RasterOp {
throw new IllegalArgumentException("source image cannot be the same as the destination image");
}
int borderX = mKernel.getWidth() / 2;
int borderY = mKernel.getHeight() / 2;
int borderX = kernel.getWidth() / 2;
int borderY = kernel.getHeight() / 2;
BufferedImage original = addBorder(pSource, borderX, borderY);
@@ -126,7 +128,7 @@ public class ConvolveWithEdgeOp implements BufferedImageOp, RasterOp {
}
// Do the filtering (if destination is null, a new image will be created)
destination = mConvolve.filter(original, destination);
destination = convolve.filter(original, destination);
if (pSource != original) {
// Remove the border
@@ -137,7 +139,7 @@ public class ConvolveWithEdgeOp implements BufferedImageOp, RasterOp {
}
private BufferedImage addBorder(final BufferedImage pOriginal, final int pBorderX, final int pBorderY) {
if ((mEdgeCondition & 2) == 0) {
if ((edgeCondition & 2) == 0) {
return pOriginal;
}
@@ -158,7 +160,7 @@ public class ConvolveWithEdgeOp implements BufferedImageOp, RasterOp {
g.drawImage(pOriginal, pBorderX, pBorderY, null);
// TODO: I guess we need the top/left etc, if the corner pixels are covered by the kernel
switch (mEdgeCondition) {
switch (edgeCondition) {
case EDGE_REFLECT:
// Top/left (empty)
g.drawImage(pOriginal, pBorderX, 0, pBorderX + w, pBorderY, 0, 0, w, 1, null); // Top/center
@@ -186,7 +188,7 @@ public class ConvolveWithEdgeOp implements BufferedImageOp, RasterOp {
g.drawImage(pOriginal, w + pBorderX, h + pBorderY, null); // Bottom/right
break;
default:
throw new IllegalArgumentException("Illegal edge operation " + mEdgeCondition);
throw new IllegalArgumentException("Illegal edge operation " + edgeCondition);
}
}
@@ -206,39 +208,39 @@ public class ConvolveWithEdgeOp implements BufferedImageOp, RasterOp {
* @see #EDGE_WRAP
*/
public int getEdgeCondition() {
return mEdgeCondition;
return edgeCondition;
}
public WritableRaster filter(final Raster pSource, final WritableRaster pDestination) {
return mConvolve.filter(pSource, pDestination);
return convolve.filter(pSource, pDestination);
}
public BufferedImage createCompatibleDestImage(final BufferedImage pSource, final ColorModel pDesinationColorModel) {
return mConvolve.createCompatibleDestImage(pSource, pDesinationColorModel);
return convolve.createCompatibleDestImage(pSource, pDesinationColorModel);
}
public WritableRaster createCompatibleDestRaster(final Raster pSource) {
return mConvolve.createCompatibleDestRaster(pSource);
return convolve.createCompatibleDestRaster(pSource);
}
public Rectangle2D getBounds2D(final BufferedImage pSource) {
return mConvolve.getBounds2D(pSource);
return convolve.getBounds2D(pSource);
}
public Rectangle2D getBounds2D(final Raster pSource) {
return mConvolve.getBounds2D(pSource);
return convolve.getBounds2D(pSource);
}
public Point2D getPoint2D(final Point2D pSourcePoint, final Point2D pDestinationPoint) {
return mConvolve.getPoint2D(pSourcePoint, pDestinationPoint);
return convolve.getPoint2D(pSourcePoint, pDestinationPoint);
}
public RenderingHints getRenderingHints() {
return mConvolve.getRenderingHints();
return convolve.getRenderingHints();
}
public Kernel getKernel() {
return mConvolve.getKernel();
return convolve.getKernel();
}
}

View File

@@ -51,7 +51,7 @@ import java.awt.image.WritableRaster;
*/
public class CopyDither implements BufferedImageOp, RasterOp {
protected IndexColorModel mIndexColorModel = null;
protected IndexColorModel indexColorModel = null;
/**
* Creates a {@code CopyDither}, using the given
@@ -61,7 +61,7 @@ public class CopyDither implements BufferedImageOp, RasterOp {
*/
public CopyDither(IndexColorModel pICM) {
// Store colormodel
mIndexColorModel = pICM;
indexColorModel = pICM;
}
/**
@@ -83,17 +83,12 @@ public class CopyDither implements BufferedImageOp, RasterOp {
* @throws ImageFilterException if {@code pDestCM} is not {@code null} or
* an instance of {@code IndexColorModel}.
*/
public final BufferedImage createCompatibleDestImage(BufferedImage pSource,
ColorModel pDestCM) {
public final BufferedImage createCompatibleDestImage(BufferedImage pSource, ColorModel pDestCM) {
if (pDestCM == null) {
return new BufferedImage(pSource.getWidth(), pSource.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED,
mIndexColorModel);
return new BufferedImage(pSource.getWidth(), pSource.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, indexColorModel);
}
else if (pDestCM instanceof IndexColorModel) {
return new BufferedImage(pSource.getWidth(), pSource.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED,
(IndexColorModel) pDestCM);
return new BufferedImage(pSource.getWidth(), pSource.getHeight(), BufferedImage.TYPE_BYTE_INDEXED, (IndexColorModel) pDestCM);
}
else {
throw new ImageFilterException("Only IndexColorModel allowed.");
@@ -112,13 +107,7 @@ public class CopyDither implements BufferedImageOp, RasterOp {
return createCompatibleDestRaster(pSrc, getICM(pSrc));
}
public final WritableRaster createCompatibleDestRaster(Raster pSrc,
IndexColorModel pIndexColorModel) {
/*
return new BufferedImage(pSrc.getWidth(), pSrc.getHeight(),
BufferedImage.TYPE_BYTE_INDEXED,
pIndexColorModel).getRaster();
*/
public final WritableRaster createCompatibleDestRaster(Raster pSrc, IndexColorModel pIndexColorModel) {
return pIndexColorModel.createCompatibleWritableRaster(pSrc.getWidth(), pSrc.getHeight());
}
@@ -207,8 +196,7 @@ public class CopyDither implements BufferedImageOp, RasterOp {
* @return the destination image, or a new image, if {@code pDest} was
* {@code null}.
*/
public final BufferedImage filter(BufferedImage pSource,
BufferedImage pDest) {
public final BufferedImage filter(BufferedImage pSource, BufferedImage pDest) {
// Create destination image, if none provided
if (pDest == null) {
pDest = createCompatibleDestImage(pSource, getICM(pSource));
@@ -238,16 +226,17 @@ public class CopyDither implements BufferedImageOp, RasterOp {
}
private IndexColorModel getICM(BufferedImage pSource) {
return (mIndexColorModel != null ? mIndexColorModel : IndexImage.getIndexColorModel(pSource, 256, IndexImage.TRANSPARENCY_BITMASK | IndexImage.COLOR_SELECTION_QUALITY));
return (indexColorModel != null ? indexColorModel : IndexImage.getIndexColorModel(pSource, 256, IndexImage.TRANSPARENCY_BITMASK | IndexImage.COLOR_SELECTION_QUALITY));
}
private IndexColorModel getICM(Raster pSource) {
return (mIndexColorModel != null ? mIndexColorModel : createIndexColorModel(pSource));
return (indexColorModel != null ? indexColorModel : createIndexColorModel(pSource));
}
private IndexColorModel createIndexColorModel(Raster pSource) {
BufferedImage image = new BufferedImage(pSource.getWidth(), pSource.getHeight(),
BufferedImage.TYPE_INT_ARGB);
BufferedImage image = new BufferedImage(pSource.getWidth(), pSource.getHeight(), BufferedImage.TYPE_INT_ARGB);
image.setData(pSource);
return IndexImage.getIndexColorModel(image, 256, IndexImage.TRANSPARENCY_BITMASK | IndexImage.COLOR_SELECTION_QUALITY);
}
@@ -261,8 +250,7 @@ public class CopyDither implements BufferedImageOp, RasterOp {
* @return the destination raster, or a new raster, if {@code pDest} was
* {@code null}.
*/
public final WritableRaster filter(final Raster pSource, WritableRaster pDest,
IndexColorModel pColorModel) {
public final WritableRaster filter(final Raster pSource, WritableRaster pDest, IndexColorModel pColorModel) {
int width = pSource.getWidth();
int height = pSource.getHeight();
@@ -292,6 +280,7 @@ public class CopyDither implements BufferedImageOp, RasterOp {
pDest.setDataElements(x, y, pixel);
}
}
return pDest;
}
}

View File

@@ -41,8 +41,8 @@ import java.util.Random;
*/
public class DiffusionDither implements BufferedImageOp, RasterOp {
protected IndexColorModel mIndexColorModel = null;
private boolean mAlternateScans = true;
protected IndexColorModel indexColorModel = null;
private boolean alternateScans = true;
private static final int FS_SCALE = 1 << 8;
private static final Random RANDOM = new Random();
@@ -54,7 +54,7 @@ public class DiffusionDither implements BufferedImageOp, RasterOp {
*/
public DiffusionDither(IndexColorModel pICM) {
// Store colormodel
mIndexColorModel = pICM;
indexColorModel = pICM;
}
/**
@@ -74,7 +74,7 @@ public class DiffusionDither implements BufferedImageOp, RasterOp {
* @param pUse {@code true} if scan mode should be alternating left/right
*/
public void setAlternateScans(boolean pUse) {
mAlternateScans = pUse;
alternateScans = pUse;
}
/**
@@ -252,10 +252,10 @@ public class DiffusionDither implements BufferedImageOp, RasterOp {
}
private IndexColorModel getICM(BufferedImage pSource) {
return (mIndexColorModel != null ? mIndexColorModel : IndexImage.getIndexColorModel(pSource, 256, IndexImage.TRANSPARENCY_BITMASK));
return (indexColorModel != null ? indexColorModel : IndexImage.getIndexColorModel(pSource, 256, IndexImage.TRANSPARENCY_BITMASK));
}
private IndexColorModel getICM(Raster pSource) {
return (mIndexColorModel != null ? mIndexColorModel : createIndexColorModel(pSource));
return (indexColorModel != null ? indexColorModel : createIndexColorModel(pSource));
}
private IndexColorModel createIndexColorModel(Raster pSource) {
@@ -456,7 +456,7 @@ public class DiffusionDither implements BufferedImageOp, RasterOp {
mNextErr = temperr;
// Toggle direction
if (mAlternateScans) {
if (alternateScans) {
forward = !forward;
}
}

View File

@@ -48,8 +48,8 @@ public class GrayFilter extends RGBImageFilter {
canFilterIndexColorModel = true;
}
private int mLow = 0;
private float mRange = 1.0f;
private int low = 0;
private float range = 1.0f;
/**
* Constructs a GrayFilter using ITU color-conversion.
@@ -82,8 +82,8 @@ public class GrayFilter extends RGBImageFilter {
pHigh = 1f;
}
mLow = (int) (pLow * 255f);
mRange = pHigh - pLow;
low = (int) (pLow * 255f);
range = pHigh - pLow;
}
@@ -118,9 +118,9 @@ public class GrayFilter extends RGBImageFilter {
//int gray = (int) ((float) (r + g + b) / 3.0f);
if (mRange != 1.0f) {
if (range != 1.0f) {
// Apply range
gray = mLow + (int) (gray * mRange);
gray = low + (int) (gray * range);
}
// Return ARGB pixel

View File

@@ -32,42 +32,20 @@ package com.twelvemonkeys.image;
* This class wraps IllegalArgumentException as thrown by the
* BufferedImageOp interface for more fine-grained control.
*
* @author Harald Kuhr
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
*
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/ImageFilterException.java#1 $
*/
public class ImageFilterException extends IllegalArgumentException {
private Throwable mCause = null;
public ImageFilterException(String pStr) {
super(pStr);
public ImageFilterException(String message) {
super(message);
}
public ImageFilterException(Throwable pT) {
initCause(pT);
public ImageFilterException(Throwable cause) {
super(cause);
}
public ImageFilterException(String pStr, Throwable pT) {
super(pStr);
initCause(pT);
}
public Throwable initCause(Throwable pThrowable) {
if (mCause != null) {
// May only be called once
throw new IllegalStateException();
}
else if (pThrowable == this) {
throw new IllegalArgumentException();
}
mCause = pThrowable;
// Hmmm...
return this;
}
public Throwable getCause() {
return mCause;
public ImageFilterException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -32,7 +32,6 @@ import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.*;
import java.util.Hashtable;
/**
@@ -354,7 +353,7 @@ public final class ImageUtil {
* The new image will have the same {@code ColorModel}, {@code Raster} and
* properties as the original image, if possible.
* <p/>
* If the image is allready a {@code BufferedImage}, it is simply returned
* If the image is already a {@code BufferedImage}, it is simply returned
* and no conversion takes place.
*
* @param pOriginal the image to convert.
@@ -365,7 +364,7 @@ public final class ImageUtil {
* @throws ImageConversionException if the image cannot be converted
*/
public static BufferedImage toBuffered(Image pOriginal) {
// Don't convert if it allready is BufferedImage
// Don't convert if it already is BufferedImage
if (pOriginal instanceof BufferedImage) {
return (BufferedImage) pOriginal;
}
@@ -543,9 +542,10 @@ public final class ImageUtil {
*/
static WritableRaster createCompatibleWritableRaster(BufferedImage pOriginal, ColorModel pModel, int mWidth, int mHeight) {
if (pModel == null || equals(pOriginal.getColorModel(), pModel)) {
int[] bOffs;
switch (pOriginal.getType()) {
case BufferedImage.TYPE_3BYTE_BGR:
int[] bOffs = {2, 1, 0}; // NOTE: These are reversed from what the cm.createCompatibleWritableRaster would return
bOffs = new int[]{2, 1, 0}; // NOTE: These are reversed from what the cm.createCompatibleWritableRaster would return
return Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE,
mWidth, mHeight,
mWidth * 3, 3,
@@ -557,6 +557,17 @@ public final class ImageUtil {
mWidth, mHeight,
mWidth * 4, 4,
bOffs, null);
case BufferedImage.TYPE_CUSTOM:
// Peek into the sample model to see if we have a sample model that will be incompatible with the default case
SampleModel sm = pOriginal.getRaster().getSampleModel();
if (sm instanceof ComponentSampleModel) {
bOffs = ((ComponentSampleModel) sm).getBandOffsets();
return Raster.createInterleavedRaster(sm.getDataType(),
mWidth, mHeight,
mWidth * bOffs.length, bOffs.length,
bOffs, null);
}
// Else fall through
default:
return pOriginal.getColorModel().createCompatibleWritableRaster(mWidth, mHeight);
}
@@ -569,7 +580,7 @@ public final class ImageUtil {
* The new image will have the same {@code ColorModel}, {@code Raster} and
* properties as the original image, if possible.
* <p/>
* If the image is allready a {@code BufferedImage} of the given type, it
* If the image is already a {@code BufferedImage} of the given type, it
* is simply returned and no conversion takes place.
*
* @param pOriginal the image to convert.
@@ -597,7 +608,7 @@ public final class ImageUtil {
* the color model
*/
private static BufferedImage toBuffered(Image pOriginal, int pType, IndexColorModel pICM) {
// Don't convert if it allready is BufferedImage and correct type
// Don't convert if it already is BufferedImage and correct type
if ((pOriginal instanceof BufferedImage)
&& ((BufferedImage) pOriginal).getType() == pType
&& (pICM == null || equals(((BufferedImage) pOriginal).getColorModel(), pICM))) {
@@ -784,7 +795,7 @@ public final class ImageUtil {
* Creates a scaled instance of the given {@code Image}, and converts it to
* a {@code BufferedImage} if needed.
* If the original image is a {@code BufferedImage} the result will have
* same type and colormodel. Note that this implies overhead, and is
* same type and color model. Note that this implies overhead, and is
* probably not useful for anything but {@code IndexColorModel} images.
*
* @param pImage the {@code Image} to scale
@@ -820,7 +831,7 @@ public final class ImageUtil {
BufferedImage scaled = createResampled(pImage, pWidth, pHeight, pHints);
// Convert if colormodels or type differ, to behave as documented
// Convert if color models or type differ, to behave as documented
if (type != scaled.getType() && type != BI_TYPE_ANY || !equals(scaled.getColorModel(), cm)) {
//System.out.print("Converting TYPE " + scaled.getType() + " -> " + type + "... ");
//long start = System.currentTimeMillis();
@@ -965,9 +976,6 @@ public final class ImageUtil {
}
private static int convertAWTHints(int pHints) {
// TODO: These conversions are broken!
// box == area average
// point == replicate (or..?)
switch (pHints) {
case Image.SCALE_FAST:
case Image.SCALE_REPLICATE:

View File

@@ -72,12 +72,12 @@ class InverseColorMap {
*/
final static int MAXQUANTVAL = 1 << 5;
byte[] mRGBMapByte;
int[] mRGBMapInt;
int mNumColors;
int mMaxColor;
byte[] mInverseRGB; // inverse rgb color map
int mTransparentIndex = -1;
byte[] rgbMapByte;
int[] rgbMapInt;
int numColors;
int maxColor;
byte[] inverseRGB; // inverse rgb color map
int transparentIndex = -1;
/**
* @param pRGBColorMap the rgb color map to create inverse color map for.
@@ -99,11 +99,11 @@ class InverseColorMap {
* @param pTransparent the index of the transparent pixel in the map
*/
InverseColorMap(byte[] pRGBColorMap, int pTransparent) {
mRGBMapByte = pRGBColorMap;
mNumColors = mRGBMapByte.length / 4;
mTransparentIndex = pTransparent;
rgbMapByte = pRGBColorMap;
numColors = rgbMapByte.length / 4;
transparentIndex = pTransparent;
mInverseRGB = new byte[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL];
inverseRGB = new byte[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL];
initIRGB(new int[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL]);
}
@@ -112,11 +112,11 @@ class InverseColorMap {
* @param pTransparent the index of the transparent pixel in the map
*/
InverseColorMap(int[] pRGBColorMap, int pTransparent) {
mRGBMapInt = pRGBColorMap;
mNumColors = mRGBMapInt.length;
mTransparentIndex = pTransparent;
rgbMapInt = pRGBColorMap;
numColors = rgbMapInt.length;
transparentIndex = pTransparent;
mInverseRGB = new byte[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL];
inverseRGB = new byte[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL];
initIRGB(new int[MAXQUANTVAL * MAXQUANTVAL * MAXQUANTVAL]);
}
@@ -130,8 +130,8 @@ class InverseColorMap {
final int xsqr = 1 << (TRUNCBITS * 2); // 64 - twice the smallest step size vale of quantized colors
final int xsqr2 = xsqr + xsqr;
for (int i = 0; i < mNumColors; ++i) {
if (i == mTransparentIndex) {
for (int i = 0; i < numColors; ++i) {
if (i == transparentIndex) {
// Skip the transparent pixel
continue;
}
@@ -141,15 +141,15 @@ class InverseColorMap {
int blue, b, bdist, binc, bxx;
// HaraldK 20040801: Added support for int[]
if (mRGBMapByte != null) {
red = mRGBMapByte[i * 4] & 0xFF;
green = mRGBMapByte[i * 4 + 1] & 0xFF;
blue = mRGBMapByte[i * 4 + 2] & 0xFF;
if (rgbMapByte != null) {
red = rgbMapByte[i * 4] & 0xFF;
green = rgbMapByte[i * 4 + 1] & 0xFF;
blue = rgbMapByte[i * 4 + 2] & 0xFF;
}
else if (mRGBMapInt != null) {
red = (mRGBMapInt[i] >> 16) & 0xFF;
green = (mRGBMapInt[i] >> 8) & 0xFF;
blue = mRGBMapInt[i] & 0xFF;
else if (rgbMapInt != null) {
red = (rgbMapInt[i] >> 16) & 0xFF;
green = (rgbMapInt[i] >> 8) & 0xFF;
blue = rgbMapInt[i] & 0xFF;
}
else {
throw new IllegalStateException("colormap == null");
@@ -170,7 +170,7 @@ class InverseColorMap {
for (b = 0, bdist = gdist, bxx = binc; b < MAXQUANTVAL; bdist += bxx, ++b, ++rgbI, bxx += xsqr2) {
if (i == 0 || pTemp[rgbI] > bdist) {
pTemp[rgbI] = bdist;
mInverseRGB[rgbI] = (byte) i;
inverseRGB[rgbI] = (byte) i;
}
}
}
@@ -187,7 +187,7 @@ class InverseColorMap {
* created inverse color map.
*/
public final int getIndexNearest(int pColor) {
return mInverseRGB[((pColor >> (3 * TRUNCBITS)) & QUANTMASK_RED) +
return inverseRGB[((pColor >> (3 * TRUNCBITS)) & QUANTMASK_RED) +
((pColor >> (2 * TRUNCBITS)) & QUANTMASK_GREEN) +
((pColor >> (/* 1 * */ TRUNCBITS)) & QUANTMASK_BLUE)] & 0xFF;
}
@@ -203,7 +203,7 @@ class InverseColorMap {
*/
public final int getIndexNearest(int pRed, int pGreen, int pBlue) {
// NOTE: the third line in expression for blue is shifting DOWN not UP.
return mInverseRGB[((pRed << (2 * QUANTBITS - TRUNCBITS)) & QUANTMASK_RED) +
return inverseRGB[((pRed << (2 * QUANTBITS - TRUNCBITS)) & QUANTMASK_RED) +
((pGreen << (/* 1 * */ QUANTBITS - TRUNCBITS)) & QUANTMASK_GREEN) +
((pBlue >> (TRUNCBITS)) & QUANTMASK_BLUE)] & 0xFF;
}

View File

@@ -46,13 +46,13 @@ import java.awt.image.IndexColorModel;
*/
public class InverseColorMapIndexColorModel extends IndexColorModel {
protected int mRGBs[];
protected int mMapSize;
protected int rgbs[];
protected int mapSize;
protected InverseColorMap mInverseMap = null;
protected InverseColorMap inverseMap = null;
private final static int ALPHA_THRESHOLD = 0x80;
private int mWhiteIndex = -1;
private int whiteIndex = -1;
private final static int WHITE = 0x00FFFFFF;
private final static int RGB_MASK = 0x00FFFFFF;
@@ -74,11 +74,11 @@ public class InverseColorMapIndexColorModel extends IndexColorModel {
ImageUtil.getTransferType(pColorModel),
pColorModel.getValidPixels());
mRGBs = pRGBs;
mMapSize = mRGBs.length;
rgbs = pRGBs;
mapSize = rgbs.length;
mInverseMap = new InverseColorMap(mRGBs);
mWhiteIndex = getWhiteIndex();
inverseMap = new InverseColorMap(rgbs);
whiteIndex = getWhiteIndex();
}
/**
@@ -91,6 +91,7 @@ public class InverseColorMapIndexColorModel extends IndexColorModel {
private static int[] getRGBs(IndexColorModel pColorModel) {
int[] rgb = new int[pColorModel.getMapSize()];
pColorModel.getRGBs(rgb);
return rgb;
}
@@ -111,15 +112,13 @@ public class InverseColorMapIndexColorModel extends IndexColorModel {
*
* @see IndexColorModel#IndexColorModel(int, int, int[], int, boolean, int, int)
*/
public InverseColorMapIndexColorModel(int pNumBits, int pSize, int[] pRGBs,
int pStart, boolean pAlpha, int pTransparentIndex,
int pTransferType) {
public InverseColorMapIndexColorModel(int pNumBits, int pSize, int[] pRGBs, int pStart, boolean pAlpha, int pTransparentIndex, int pTransferType) {
super(pNumBits, pSize, pRGBs, pStart, pAlpha, pTransparentIndex, pTransferType);
mRGBs = getRGBs(this);
mMapSize = mRGBs.length;
rgbs = getRGBs(this);
mapSize = rgbs.length;
mInverseMap = new InverseColorMap(mRGBs, pTransparentIndex);
mWhiteIndex = getWhiteIndex();
inverseMap = new InverseColorMap(rgbs, pTransparentIndex);
whiteIndex = getWhiteIndex();
}
/**
@@ -138,15 +137,13 @@ public class InverseColorMapIndexColorModel extends IndexColorModel {
*
* @see IndexColorModel#IndexColorModel(int, int, byte[], byte[], byte[], int)
*/
public InverseColorMapIndexColorModel(int pNumBits, int pSize,
byte[] pReds, byte[] pGreens, byte[] pBlues,
int pTransparentIndex) {
public InverseColorMapIndexColorModel(int pNumBits, int pSize, byte[] pReds, byte[] pGreens, byte[] pBlues, int pTransparentIndex) {
super(pNumBits, pSize, pReds, pGreens, pBlues, pTransparentIndex);
mRGBs = getRGBs(this);
mMapSize = mRGBs.length;
rgbs = getRGBs(this);
mapSize = rgbs.length;
mInverseMap = new InverseColorMap(mRGBs, pTransparentIndex);
mWhiteIndex = getWhiteIndex();
inverseMap = new InverseColorMap(rgbs, pTransparentIndex);
whiteIndex = getWhiteIndex();
}
/**
@@ -164,19 +161,18 @@ public class InverseColorMapIndexColorModel extends IndexColorModel {
*
* @see IndexColorModel#IndexColorModel(int, int, byte[], byte[], byte[])
*/
public InverseColorMapIndexColorModel(int pNumBits, int pSize,
byte[] pReds, byte[] pGreens, byte[] pBlues) {
public InverseColorMapIndexColorModel(int pNumBits, int pSize, byte[] pReds, byte[] pGreens, byte[] pBlues) {
super(pNumBits, pSize, pReds, pGreens, pBlues);
mRGBs = getRGBs(this);
mMapSize = mRGBs.length;
rgbs = getRGBs(this);
mapSize = rgbs.length;
mInverseMap = new InverseColorMap(mRGBs);
mWhiteIndex = getWhiteIndex();
inverseMap = new InverseColorMap(rgbs);
whiteIndex = getWhiteIndex();
}
private int getWhiteIndex() {
for (int i = 0; i < mRGBs.length; i++) {
int color = mRGBs[i];
for (int i = 0; i < rgbs.length; i++) {
int color = rgbs[i];
if ((color & RGB_MASK) == WHITE) {
return i;
}
@@ -244,7 +240,6 @@ public class InverseColorMapIndexColorModel extends IndexColorModel {
*
*/
public Object getDataElements(int rgb, Object pixel) {
int alpha = (rgb>>>24);
int pix;
@@ -253,11 +248,11 @@ public class InverseColorMapIndexColorModel extends IndexColorModel {
}
else {
int color = rgb & RGB_MASK;
if (color == WHITE && mWhiteIndex != -1) {
pix = mWhiteIndex;
if (color == WHITE && whiteIndex != -1) {
pix = whiteIndex;
}
else {
pix = mInverseMap.getIndexNearest(color);
pix = inverseMap.getIndexNearest(color);
}
}
@@ -297,8 +292,7 @@ public class InverseColorMapIndexColorModel extends IndexColorModel {
shortObj[0] = (short) pix;
break;
default:
throw new UnsupportedOperationException("This method has not been " +
"implemented for transferType " + transferType);
throw new UnsupportedOperationException("This method has not been implemented for transferType " + transferType);
}
return pixel;
}

View File

@@ -54,11 +54,11 @@ final class MagickAccelerator {
private static final int RESAMPLE_OP = 0;
private static Class[] sNativeOp = new Class[1];
private static Class[] nativeOp = new Class[1];
static {
try {
sNativeOp[RESAMPLE_OP] = Class.forName("com.twelvemonkeys.image.ResampleOp");
nativeOp[RESAMPLE_OP] = Class.forName("com.twelvemonkeys.image.ResampleOp");
}
catch (ClassNotFoundException e) {
System.err.println("Could not find class: " + e);
@@ -94,8 +94,8 @@ final class MagickAccelerator {
}
private static int getNativeOpIndex(Class pOpClass) {
for (int i = 0; i < sNativeOp.length; i++) {
if (pOpClass == sNativeOp[i]) {
for (int i = 0; i < nativeOp.length; i++) {
if (pOpClass == nativeOp[i]) {
return i;
}
}
@@ -112,7 +112,7 @@ final class MagickAccelerator {
switch (getNativeOpIndex(pOperation.getClass())) {
case RESAMPLE_OP:
ResampleOp resample = (ResampleOp) pOperation;
result = resampleMagick(pInput, resample.mWidth, resample.mHeight, resample.mFilterType);
result = resampleMagick(pInput, resample.width, resample.height, resample.filterType);
// NOTE: If output parameter is non-null, we have to return that
// image, instead of result

View File

@@ -33,7 +33,7 @@ import java.awt.image.*;
/**
* Monochrome B/W color model.
*
* @author Harald Kuhr
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
*/
public class MonochromeColorModel extends IndexColorModel {

View File

@@ -48,37 +48,37 @@ public class PixelizeOp implements BufferedImageOp, RasterOp {
// TODO: support more raster types/color models
// TODO: This is actually an implementation of Area Averaging, without the scale... Let's extract it...
final private int mPixelSizeX;
final private int mPixelSizeY;
final private int pixelSizeX;
final private int pixelSizeY;
private Rectangle mSourceRegion;
private Rectangle sourceRegion;
public PixelizeOp(final int pPixelSize) {
this(pPixelSize, pPixelSize);
}
public PixelizeOp(final int pPixelSizeX, final int pPixelSizeY) {
mPixelSizeX = pPixelSizeX;
mPixelSizeY = pPixelSizeY;
pixelSizeX = pPixelSizeX;
pixelSizeY = pPixelSizeY;
}
public Rectangle getSourceRegion() {
if (mSourceRegion == null) {
if (sourceRegion == null) {
return null;
}
return new Rectangle(mSourceRegion);
return new Rectangle(sourceRegion);
}
public void setSourceRegion(final Rectangle pSourceRegion) {
if (pSourceRegion == null) {
mSourceRegion = null;
sourceRegion = null;
}
else {
if (mSourceRegion == null) {
mSourceRegion = new Rectangle(pSourceRegion);
if (sourceRegion == null) {
sourceRegion = new Rectangle(pSourceRegion);
}
else {
mSourceRegion.setBounds(pSourceRegion);
sourceRegion.setBounds(pSourceRegion);
}
}
}
@@ -107,11 +107,11 @@ public class PixelizeOp implements BufferedImageOp, RasterOp {
private WritableRaster filterImpl(Raster src, WritableRaster dest) {
//System.out.println("src: " + src);
//System.out.println("dest: " + dest);
if (mSourceRegion != null) {
int cx = mSourceRegion.x;
int cy = mSourceRegion.y;
int cw = mSourceRegion.width;
int ch = mSourceRegion.height;
if (sourceRegion != null) {
int cx = sourceRegion.x;
int cy = sourceRegion.y;
int cw = sourceRegion.width;
int ch = sourceRegion.height;
boolean same = src == dest;
dest = dest.createWritableChild(cx, cy, cw, ch, 0, 0, null);
@@ -122,8 +122,8 @@ public class PixelizeOp implements BufferedImageOp, RasterOp {
final int width = src.getWidth();
final int height = src.getHeight();
int w = (width + mPixelSizeX - 1) / mPixelSizeX;
int h = (height + mPixelSizeY - 1) / mPixelSizeY;
int w = (width + pixelSizeX - 1) / pixelSizeX;
int h = (height + pixelSizeY - 1) / pixelSizeY;
final boolean oddX = width % w != 0;
final boolean oddY = height % h != 0;
@@ -156,23 +156,23 @@ public class PixelizeOp implements BufferedImageOp, RasterOp {
for (int y = 0; y < h; y++) {
if (!oddY || y + 1 < h) {
scanH = mPixelSizeY;
scanH = pixelSizeY;
}
else {
scanH = height - (y * mPixelSizeY);
scanH = height - (y * pixelSizeY);
}
for (int x = 0; x < w; x++) {
if (!oddX || x + 1 < w) {
scanW = mPixelSizeX;
scanW = pixelSizeX;
}
else {
scanW = width - (x * mPixelSizeX);
scanW = width - (x * pixelSizeX);
}
final int pixelCount = scanW * scanH;
final int pixelLength = pixelCount * dataElements;
data = src.getDataElements(x * mPixelSizeX, y * mPixelSizeY, scanW, scanH, data);
data = src.getDataElements(x * pixelSizeX, y * pixelSizeY, scanW, scanH, data);
// NOTE: These are not neccessarily ARGB..
double valueA = 0.0;
@@ -277,7 +277,7 @@ public class PixelizeOp implements BufferedImageOp, RasterOp {
}
dest.setDataElements(x * mPixelSizeX, y * mPixelSizeY, scanW, scanH, data);
dest.setDataElements(x * pixelSizeX, y * pixelSizeY, scanW, scanH, data);
}
}
/*/

View File

@@ -60,7 +60,6 @@ import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.*;
/**
* Resamples (scales) a {@code BufferedImage} to a new width and height, using
* high performance and high quality algorithms.
@@ -138,7 +137,7 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
// MagickAccelerator to work consistently (see magick.FilterType).
/**
* Undefined interpolation, filter method will use default filter
* Undefined interpolation, filter method will use default filter.
*/
public final static int FILTER_UNDEFINED = 0;
/**
@@ -194,11 +193,11 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
/**
* Mitchell interpolation. High quality.
*/
public final static int FILTER_MITCHELL = 12;// IM default scale with palette or alpha, or scale up
public final static int FILTER_MITCHELL = 12; // IM default scale with palette or alpha, or scale up
/**
* Lanczos interpolation. High quality.
*/
public final static int FILTER_LANCZOS = 13;// IM default
public final static int FILTER_LANCZOS = 13; // IM default
/**
* Blackman-Bessel interpolation. High quality.
*/
@@ -291,10 +290,10 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
// Member variables
// Package access, to allow access from MagickAccelerator
int mWidth;
int mHeight;
int width;
int height;
int mFilterType;
int filterType;
private static final boolean TRANSFORM_OP_BICUBIC_SUPPORT = SystemUtil.isFieldAvailable(AffineTransformOp.class.getName(), "TYPE_BICUBIC");
/**
@@ -302,14 +301,13 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
*/
// TODO: Move to abstract class AbstractBufferedImageOp?
static class Key extends RenderingHints.Key {
static int sIndex = 10000;
private final String mName;
private final String name;
public Key(final String pName) {
super(sIndex++);
mName = pName;
name = pName;
}
public boolean isCompatibleValue(Object pValue) {
@@ -317,7 +315,7 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
}
public String toString() {
return mName;
return name;
}
}
@@ -326,27 +324,27 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
*/
// TODO: Extract abstract Value class, and move to AbstractBufferedImageOp
static final class Value {
final private RenderingHints.Key mKey;
final private String mName;
final private int mType;
final private RenderingHints.Key key;
final private String name;
final private int type;
public Value(final RenderingHints.Key pKey, final String pName, final int pType) {
mKey = pKey;
mName = pName;
key = pKey;
name = pName;
validateFilterType(pType);
mType = pType;// TODO: test for duplicates
type = pType;// TODO: test for duplicates
}
public boolean isCompatibleKey(Key pKey) {
return pKey == mKey;
return pKey == key;
}
public int getFilterType() {
return mType;
return type;
}
public String toString() {
return mName;
return name;
}
}
@@ -354,11 +352,11 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
* Creates a {@code ResampleOp} that will resample input images to the
* given width and height, using the default interpolation filter.
*
* @param pWidth width of the resampled image
* @param pHeight height of the resampled image
* @param width width of the re-sampled image
* @param height height of the re-sampled image
*/
public ResampleOp(int pWidth, int pHeight) {
this(pWidth, pHeight, FILTER_UNDEFINED);
public ResampleOp(int width, int height) {
this(width, height, FILTER_UNDEFINED);
}
/**
@@ -394,38 +392,38 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
* </ul>
* Other hints have no effect on this filter.
*
* @param pWidth width of the resampled image
* @param pHeight height of the resampled image
* @param pHints rendering hints, affecting interpolation algorithm
* @param width width of the re-sampled image
* @param height height of the re-sampled image
* @param hints rendering hints, affecting interpolation algorithm
* @see #KEY_RESAMPLE_INTERPOLATION
* @see RenderingHints#KEY_INTERPOLATION
* @see RenderingHints#KEY_RENDERING
* @see RenderingHints#KEY_COLOR_RENDERING
*/
public ResampleOp(int pWidth, int pHeight, RenderingHints pHints) {
this(pWidth, pHeight, getFilterType(pHints));
public ResampleOp(int width, int height, RenderingHints hints) {
this(width, height, getFilterType(hints));
}
/**
* Creates a {@code ResampleOp} that will resample input images to the
* given width and height, using the given interpolation filter.
*
* @param pWidth width of the resampled image
* @param pHeight height of the resampled image
* @param pFilterType interpolation filter algorithm
* @param width width of the re-sampled image
* @param height height of the re-sampled image
* @param filterType interpolation filter algorithm
* @see <a href="#field_summary">filter type constants</a>
*/
public ResampleOp(int pWidth, int pHeight, int pFilterType) {
if (pWidth <= 0 || pHeight <= 0) {
public ResampleOp(int width, int height, int filterType) {
if (width <= 0 || height <= 0) {
// NOTE: w/h == 0 makes the Magick DLL crash and the JVM dies.. :-P
throw new IllegalArgumentException("width and height must be positive");
}
mWidth = pWidth;
mHeight = pHeight;
this.width = width;
this.height = height;
validateFilterType(pFilterType);
mFilterType = pFilterType;
validateFilterType(filterType);
this.filterType = filterType;
}
private static void validateFilterType(int pFilterType) {
@@ -471,25 +469,21 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
}
return value != null ? ((Value) value).getFilterType() : FILTER_UNDEFINED;
}
else
if (RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR.equals(pHints.get(RenderingHints.KEY_INTERPOLATION))
else if (RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR.equals(pHints.get(RenderingHints.KEY_INTERPOLATION))
|| (!pHints.containsKey(RenderingHints.KEY_INTERPOLATION)
&& (RenderingHints.VALUE_RENDER_SPEED.equals(pHints.get(RenderingHints.KEY_RENDERING))
|| RenderingHints.VALUE_COLOR_RENDER_SPEED.equals(pHints.get(RenderingHints.KEY_COLOR_RENDERING))))) {
// Nearest neighbour, or prioritze speed
// Nearest neighbour, or prioritize speed
return FILTER_POINT;
}
else
if (RenderingHints.VALUE_INTERPOLATION_BILINEAR.equals(pHints.get(RenderingHints.KEY_INTERPOLATION))) {
else if (RenderingHints.VALUE_INTERPOLATION_BILINEAR.equals(pHints.get(RenderingHints.KEY_INTERPOLATION))) {
// Triangle equals bi-linear interpolation
return FILTER_TRIANGLE;
}
else
if (RenderingHints.VALUE_INTERPOLATION_BICUBIC.equals(pHints.get(RenderingHints.KEY_INTERPOLATION))) {
else if (RenderingHints.VALUE_INTERPOLATION_BICUBIC.equals(pHints.get(RenderingHints.KEY_INTERPOLATION))) {
return FILTER_QUADRATIC;// No idea if this is correct..?
}
else
if (RenderingHints.VALUE_RENDER_QUALITY.equals(pHints.get(RenderingHints.KEY_RENDERING))
else if (RenderingHints.VALUE_RENDER_QUALITY.equals(pHints.get(RenderingHints.KEY_RENDERING))
|| RenderingHints.VALUE_COLOR_RENDER_QUALITY.equals(pHints.get(RenderingHints.KEY_COLOR_RENDERING))) {
// Prioritize quality
return FILTER_MITCHELL;
@@ -500,83 +494,88 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
}
/**
* Resamples (scales) the image to the size, and using the algorithm
* Re-samples (scales) the image to the size, and using the algorithm
* specified in the constructor.
*
* @param pInput The {@code BufferedImage} to be filtered
* @param pOutput The {@code BufferedImage} in which to store the resampled
* @param input The {@code BufferedImage} to be filtered
* @param output The {@code BufferedImage} in which to store the resampled
* image
* @return The resampled {@code BufferedImage}.
* @throws NullPointerException if {@code pInput} is {@code null}
* @throws IllegalArgumentException if {@code pInput == pOutput}.
* @return The re-sampled {@code BufferedImage}.
* @throws NullPointerException if {@code input} is {@code null}
* @throws IllegalArgumentException if {@code input == output}.
* @see #ResampleOp(int,int,int)
*/
public final BufferedImage filter(final BufferedImage pInput, final BufferedImage pOutput) {
if (pInput == null) {
public final BufferedImage filter(final BufferedImage input, final BufferedImage output) {
if (input == null) {
throw new NullPointerException("Input == null");
}
if (pInput == pOutput) {
if (input == output) {
throw new IllegalArgumentException("Output image cannot be the same as the input image");
}
InterpolationFilter filter;
// Special case for POINT, TRIANGLE and QUADRATIC filter, as standard
// Java implementation is very fast (possibly H/W accellerated)
switch (mFilterType) {
// Java implementation is very fast (possibly H/W accelerated)
switch (filterType) {
case FILTER_POINT:
return fastResample(pInput, pOutput, mWidth, mHeight, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
case FILTER_TRIANGLE:
return fastResample(pInput, pOutput, mWidth, mHeight, AffineTransformOp.TYPE_BILINEAR);
case FILTER_QUADRATIC:
if (TRANSFORM_OP_BICUBIC_SUPPORT) {
return fastResample(pInput, pOutput, mWidth, mHeight, 3); // AffineTransformOp.TYPE_BICUBIC
if (input.getType() != BufferedImage.TYPE_CUSTOM) {
return fastResample(input, output, width, height, AffineTransformOp.TYPE_NEAREST_NEIGHBOR);
}
// Fall through
// Else fall through
case FILTER_TRIANGLE:
if (input.getType() != BufferedImage.TYPE_CUSTOM) {
return fastResample(input, output, width, height, AffineTransformOp.TYPE_BILINEAR);
}
// Else fall through
case FILTER_QUADRATIC:
if (input.getType() != BufferedImage.TYPE_CUSTOM && TRANSFORM_OP_BICUBIC_SUPPORT) {
return fastResample(input, output, width, height, 3); // AffineTransformOp.TYPE_BICUBIC
}
// Else fall through
default:
filter = createFilter(mFilterType);
filter = createFilter(filterType);
// NOTE: Workaround for filter throwing exceptions when input or output is less than support...
if (Math.min(pInput.getWidth(), pInput.getHeight()) <= filter.support() || Math.min(mWidth, mHeight) <= filter.support()) {
return fastResample(pInput, pOutput, mWidth, mHeight, AffineTransformOp.TYPE_BILINEAR);
if (Math.min(input.getWidth(), input.getHeight()) <= filter.support() || Math.min(width, height) <= filter.support()) {
return fastResample(input, output, width, height, AffineTransformOp.TYPE_BILINEAR);
}
// Fall through
}
// Try to use native ImageMagick code
BufferedImage result = MagickAccelerator.filter(this, pInput, pOutput);
BufferedImage result = MagickAccelerator.filter(this, input, output);
if (result != null) {
return result;
}
// Otherwise, continue in pure Java mode
// TODO: What if pOutput != null and wrong size? Create new? Render on only a part? Document?
// TODO: What if output != null and wrong size? Create new? Render on only a part? Document?
// If filter type != POINT or BOX an input has IndexColorModel, convert
// to true color, with alpha reflecting that of the original colormodel.
BufferedImage input;
// to true color, with alpha reflecting that of the original color model.
BufferedImage temp;
ColorModel cm;
if (mFilterType != FILTER_BOX && (cm = pInput.getColorModel()) instanceof IndexColorModel) {
// TODO: OPTIMIZE: If colormodel has only b/w or gray, we could skip color info
input = ImageUtil.toBuffered(pInput, cm.hasAlpha() ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR);
if (filterType != FILTER_POINT && filterType != FILTER_BOX && (cm = input.getColorModel()) instanceof IndexColorModel) {
// TODO: OPTIMIZE: If color model has only b/w or gray, we could skip color info
temp = ImageUtil.toBuffered(input, cm.hasAlpha() ? BufferedImage.TYPE_4BYTE_ABGR : BufferedImage.TYPE_3BYTE_BGR);
}
else {
input = pInput;
temp = input;
}
// Create or convert output to a suitable image
// TODO: OPTIMIZE: Don't really need to convert all types to same as input
result = pOutput != null ? /*pOutput*/ ImageUtil.toBuffered(pOutput, input.getType()) : createCompatibleDestImage(input, null);
result = output != null && temp.getType() != BufferedImage.TYPE_CUSTOM ? /*output*/ ImageUtil.toBuffered(output, temp.getType()) : createCompatibleDestImage(temp, null);
// result = output != null ? output : createCompatibleDestImage(temp, null);
resample(input, result, filter);
resample(temp, result, filter);
// If pOutput != null and needed to be converted, draw it back
if (pOutput != null && pOutput != result) {
//pOutput.setData(output.getRaster());
ImageUtil.drawOnto(pOutput, result);
result = pOutput;
// If output != null and needed to be converted, draw it back
if (output != null && output != result) {
//output.setData(output.getRaster());
ImageUtil.drawOnto(output, result);
result = output;
}
return result;
@@ -672,8 +671,8 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
}
*/
private static BufferedImage fastResample(final BufferedImage pInput, final BufferedImage pOutput, final int pWidth, final int pHeight, final int pType) {
BufferedImage temp = pInput;
private static BufferedImage fastResample(final BufferedImage input, final BufferedImage output, final int width, final int height, final int type) {
BufferedImage temp = input;
double xScale;
double yScale;
@@ -681,20 +680,20 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
AffineTransform transform;
AffineTransformOp scale;
if (pType > AffineTransformOp.TYPE_NEAREST_NEIGHBOR) {
if (type > AffineTransformOp.TYPE_NEAREST_NEIGHBOR) {
// Initially scale so all remaining operations will halve the image
if (pWidth < pInput.getWidth() || pHeight < pInput.getHeight()) {
int w = pWidth;
int h = pHeight;
while (w < pInput.getWidth() / 2) {
if (width < input.getWidth() || height < input.getHeight()) {
int w = width;
int h = height;
while (w < input.getWidth() / 2) {
w *= 2;
}
while (h < pInput.getHeight() / 2) {
while (h < input.getHeight() / 2) {
h *= 2;
}
xScale = w / (double) pInput.getWidth();
yScale = h / (double) pInput.getHeight();
xScale = w / (double) input.getWidth();
yScale = h / (double) input.getHeight();
//System.out.println("First scale by x=" + xScale + ", y=" + yScale);
@@ -704,12 +703,12 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
}
}
scale = null;// NOTE: This resets!
scale = null; // NOTE: This resets!
xScale = pWidth / (double) temp.getWidth();
yScale = pHeight / (double) temp.getHeight();
xScale = width / (double) temp.getWidth();
yScale = height / (double) temp.getHeight();
if (pType > AffineTransformOp.TYPE_NEAREST_NEIGHBOR) {
if (type > AffineTransformOp.TYPE_NEAREST_NEIGHBOR) {
// TODO: Test skipping first scale (above), and instead scale once
// more here, and a little less than .5 each time...
// That would probably make the scaling smoother...
@@ -740,17 +739,15 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
}
temp = scale.filter(temp, null);
}
}
//System.out.println("Rest to scale by x=" + xScale + ", y=" + yScale);
transform = AffineTransform.getScaleInstance(xScale, yScale);
scale = new AffineTransformOp(transform, pType);
return scale.filter(temp, pOutput);
scale = new AffineTransformOp(transform, type);
return scale.filter(temp, output);
}
/**
@@ -760,7 +757,7 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
* @see <a href="#field_summary">filter type constants</a>
*/
public int getFilterType() {
return mFilterType;
return filterType;
}
private static InterpolationFilter createFilter(int pFilterType) {
@@ -770,7 +767,8 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
}
switch (pFilterType) {
//case FILTER_POINT: // Should never happen
case FILTER_POINT:
return new PointFilter();
case FILTER_BOX:
return new BoxFilter();
case FILTER_TRIANGLE:
@@ -815,14 +813,14 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
// If indexcolormodel, we probably don't want to use that...
// NOTE: Either BOTH or NONE of the images must have ALPHA
return new BufferedImage(cm, ImageUtil.createCompatibleWritableRaster(pInput, cm, mWidth, mHeight),
return new BufferedImage(cm, ImageUtil.createCompatibleWritableRaster(pInput, cm, width, height),
cm.isAlphaPremultiplied(), null);
}
public RenderingHints getRenderingHints() {
Object value;
switch (mFilterType) {
switch (filterType) {
case FILTER_UNDEFINED:
return null;
case FILTER_POINT:
@@ -871,14 +869,14 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
value = VALUE_INTERPOLATION_BLACKMAN_SINC;
break;
default:
throw new IllegalStateException("Unknown filter type: " + mFilterType);
throw new IllegalStateException("Unknown filter type: " + filterType);
}
return new RenderingHints(KEY_RESAMPLE_INTERPOLATION, value);
}
public Rectangle2D getBounds2D(BufferedImage src) {
return new Rectangle(mWidth, mHeight);
return new Rectangle(width, height);
}
public Point2D getPoint2D(Point2D srcPt, Point2D dstPt) {
@@ -1439,10 +1437,8 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
resample()
Resizes bitmaps while resampling them.
Returns -1 if error, 0 if success.
*/
private BufferedImage resample(BufferedImage pSource, BufferedImage pDest, InterpolationFilter pFilter) {
// TODO: Don't work... Could fix by creating a temporary image in filter method
final int dstWidth = pDest.getWidth();
final int dstHeight = pDest.getHeight();
@@ -1451,7 +1447,8 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
/* create intermediate column to hold horizontal dst column zoom */
final ColorModel cm = pSource.getColorModel();
final WritableRaster work = cm.createCompatibleWritableRaster(1, srcHeight);
// final WritableRaster work = cm.createCompatibleWritableRaster(1, srcHeight);
final WritableRaster work = ImageUtil.createCompatibleWritableRaster(pSource, cm, 1, srcHeight);
double xscale = (double) dstWidth / (double) srcWidth;
double yscale = (double) dstHeight / (double) srcHeight;
@@ -1566,7 +1563,7 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
final WritableRaster out = pDest.getRaster();
// TODO: This is not optimal for non-byte-packed rasters...
// (What? Maybe I implemented the fix, but forgot to remove the qTODO?)
// (What? Maybe I implemented the fix, but forgot to remove the TODO?)
final int numChannels = raster.getNumBands();
final int[] channelMax = new int[numChannels];
for (int k = 0; k < numChannels; k++) {
@@ -1575,7 +1572,7 @@ public class ResampleOp implements BufferedImageOp/* TODO: RasterOp */ {
for (int xx = 0; xx < dstWidth; xx++) {
ContributorList contribX = calcXContrib(xscale, fwidth, srcWidth, pFilter, xx);
/* Apply horz filter to make dst column in tmp. */
/* Apply horiz filter to make dst column in tmp. */
for (int k = 0; k < srcHeight; k++) {
for (int channel = 0; channel < numChannels; channel++) {

View File

@@ -42,8 +42,8 @@ import java.awt.image.ReplicateScaleFilter;
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/SubsamplingFilter.java#1 $
*/
public class SubsamplingFilter extends ReplicateScaleFilter {
private int mXSub;
private int mYSub;
private int xSub;
private int ySub;
/**
* Creates a {@code SubsamplingFilter}.
@@ -62,16 +62,16 @@ public class SubsamplingFilter extends ReplicateScaleFilter {
throw new IllegalArgumentException("Subsampling factors must be positive.");
}
mXSub = pXSub;
mYSub = pYSub;
xSub = pXSub;
ySub = pYSub;
}
/** {@code ImageFilter} implementation, do not invoke. */
public void setDimensions(int pWidth, int pHeight) {
destWidth = (pWidth + mXSub - 1) / mXSub;
destHeight = (pHeight + mYSub - 1) / mYSub;
destWidth = (pWidth + xSub - 1) / xSub;
destHeight = (pHeight + ySub - 1) / ySub;
//System.out.println("Subsampling: " + mXSub + "," + mYSub + "-> " + destWidth + ", " + destHeight);
//System.out.println("Subsampling: " + xSub + "," + ySub + "-> " + destWidth + ", " + destHeight);
super.setDimensions(pWidth, pHeight);
}
}

View File

@@ -4,6 +4,6 @@
* See the class {@link com.twelvemonkeys.image.ImageUtil}.
*
* @version 1.0
* @author <a href="mailto:harald@escenic.com">Harald Kuhr</a>
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
*/
package com.twelvemonkeys.image;

View File

@@ -0,0 +1,206 @@
package com.twelvemonkeys.image;
import org.junit.Test;
import java.awt.*;
import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ImageProducer;
import java.net.URL;
import static org.junit.Assert.*;
/**
* BufferedImageFactoryTestCase
*
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @author last modified by $Author: haraldk$
* @version $Id: BufferedImageFactoryTestCase.java,v 1.0 May 7, 2010 12:40:08 PM haraldk Exp$
*/
public class BufferedImageFactoryTestCase {
@Test(expected = IllegalArgumentException.class)
public void testCreateNullImage() {
new BufferedImageFactory((Image) null);
}
@Test(expected = IllegalArgumentException.class)
public void testCreateNullProducer() {
new BufferedImageFactory((ImageProducer) null);
}
// Image source = Toolkit.getDefaultToolkit().createImage((byte[]) null); // - NPE in Toolkit, ok
@Test(timeout = 1000, expected = IllegalArgumentException.class)
public void testGetBufferedImageErrorSourceIP() {
Image source = Toolkit.getDefaultToolkit().createImage((ImageProducer) null);
new BufferedImageFactory(source);
}
// TODO: This is a quite serious bug, but it can be argued that the bug is in the
// Toolkit, allowing such images in the first place... In any case, there's
// not much we can do, except until someone is bored and kills the app... :-P
/*
@Test(timeout = 1000, expected = ImageConversionException.class)
public void testGetBufferedImageErrorSourceString() {
Image source = Toolkit.getDefaultToolkit().createImage((String) null);
BufferedImageFactory factory = new BufferedImageFactory(source);
factory.getBufferedImage();
}
*/
// This is a little random, and it would be nicer if we could throw an IllegalArgumentException on create.
// Unfortunately, the API doesn't allow this...
@Test(timeout = 1000, expected = ImageConversionException.class)
public void testGetBufferedImageErrorSourceURL() {
Image source = Toolkit.getDefaultToolkit().createImage(getClass().getResource("/META-INF/MANIFEST.MF"));
BufferedImageFactory factory = new BufferedImageFactory(source);
factory.getBufferedImage();
}
@Test
public void testGetBufferedImageJPEG() {
URL resource = getClass().getResource("/sunflower.jpg");
assertNotNull(resource);
Image source = Toolkit.getDefaultToolkit().createImage(resource);
assertNotNull(source);
BufferedImageFactory factory = new BufferedImageFactory(source);
BufferedImage image = factory.getBufferedImage();
assertEquals(187, image.getWidth());
assertEquals(283, image.getHeight());
}
@Test
public void testGetColorModelJPEG() {
URL resource = getClass().getResource("/sunflower.jpg");
assertNotNull(resource);
Image source = Toolkit.getDefaultToolkit().createImage(resource);
assertNotNull(source);
BufferedImageFactory factory = new BufferedImageFactory(source);
ColorModel colorModel = factory.getColorModel();
assertNotNull(colorModel);
assertEquals(3, colorModel.getNumColorComponents()); // getNumComponents may include alpha, we don't care
assertEquals(ColorSpace.getInstance(ColorSpace.CS_sRGB), colorModel.getColorSpace());
for (int i = 0; i < colorModel.getNumComponents(); i++) {
assertEquals(8, colorModel.getComponentSize(i));
}
}
// TODO: Test a GIF or PNG with PLTE chunk, and make sure we get an IndexColorModel
@Test
public void testGetBufferedImageSubsampled() {
URL resource = getClass().getResource("/sunflower.jpg");
assertNotNull(resource);
Image source = Toolkit.getDefaultToolkit().createImage(resource);
assertNotNull(source);
BufferedImageFactory factory = new BufferedImageFactory(source);
BufferedImage original = factory.getBufferedImage();
factory.setSourceSubsampling(2, 2);
BufferedImage image = factory.getBufferedImage(); // Accidentally also tests reuse...
// Values rounded up
assertEquals(94, image.getWidth());
assertEquals(142, image.getHeight());
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(x * 2, y * 2), image.getRGB(x, y));
}
}
}
@Test
public void testGetBufferedImageSourceRegion() {
URL resource = getClass().getResource("/sunflower.jpg");
assertNotNull(resource);
Image source = Toolkit.getDefaultToolkit().createImage(resource);
assertNotNull(source);
BufferedImageFactory factory = new BufferedImageFactory(source);
BufferedImage original = factory.getBufferedImage();
factory.setSourceRegion(new Rectangle(40, 40, 40, 40));
BufferedImage image = factory.getBufferedImage(); // Accidentally also tests reuse...
assertEquals(40, image.getWidth());
assertEquals(40, image.getHeight());
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(40 + x, 40 + y), image.getRGB(x, y));
}
}
}
@Test
public void testGetBufferedImageSubsampledSourceRegion() throws Exception{
URL resource = getClass().getResource("/sunflower.jpg");
assertNotNull(resource);
Image source = Toolkit.getDefaultToolkit().createImage(resource);
assertNotNull(source);
BufferedImageFactory factory = new BufferedImageFactory(source);
BufferedImage original = factory.getBufferedImage();
factory.setSourceRegion(new Rectangle(40, 40, 40, 40));
factory.setSourceSubsampling(2, 2);
BufferedImage image = factory.getBufferedImage(); // Accidentally also tests reuse...
assertEquals(20, image.getWidth());
assertEquals(20, image.getHeight());
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
assertEquals("RGB[" + x + ", " + y + "]", original.getRGB(40 + x * 2, 40 + y * 2), image.getRGB(x, y));
}
}
}
@Test
public void testListener() {
URL resource = getClass().getResource("/sunflower.jpg");
assertNotNull(resource);
Image source = Toolkit.getDefaultToolkit().createImage(resource);
assertNotNull(source);
BufferedImageFactory factory = new BufferedImageFactory(source);
VerifyingListener listener = new VerifyingListener(factory);
factory.addProgressListener(listener);
factory.getBufferedImage();
listener.verify();
}
private static class VerifyingListener implements BufferedImageFactory.ProgressListener {
private final BufferedImageFactory factory;
private float progress;
public VerifyingListener(BufferedImageFactory factory) {
this.factory = factory;
}
public void progress(BufferedImageFactory pFactory, float pPercentage) {
assertEquals(factory, pFactory);
assertTrue(pPercentage >= progress && pPercentage <= 100f);
progress = pPercentage;
}
public void verify() {
assertEquals(100f, progress, .1f); // Sanity test that the listener was invoked
}
}
}

View File

@@ -24,35 +24,35 @@ import java.lang.reflect.InvocationTargetException;
public class ImageUtilTestCase extends TestCase {
private final static String IMAGE_NAME = "/sunflower.jpg";
private BufferedImage mOriginal;
private BufferedImage mImage;
private Image mScaled;
private BufferedImage original;
private BufferedImage image;
private Image scaled;
public ImageUtilTestCase() throws Exception {
mImage = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
mScaled = mImage.getScaledInstance(5, 5, Image.SCALE_FAST);
image = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
scaled = image.getScaledInstance(5, 5, Image.SCALE_FAST);
// Read image from class path
InputStream is = getClass().getResourceAsStream(IMAGE_NAME);
mOriginal = ImageIO.read(is);
original = ImageIO.read(is);
assertNotNull(mOriginal);
assertNotNull(original);
}
/*
public void setUp() throws Exception {
mImage = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
mScaled = mImage.getScaledInstance(5, 5, Image.SCALE_FAST);
image = new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
scaled = image.getScaledInstance(5, 5, Image.SCALE_FAST);
// Read image from class path
InputStream is = ClassLoader.getSystemResourceAsStream(IMAGE_NAME);
mOriginal = ImageIO.read(is);
original = ImageIO.read(is);
assertNotNull(mOriginal);
assertNotNull(original);
}
protected void tearDown() throws Exception {
mOriginal = null;
original = null;
}
*/
@@ -94,20 +94,20 @@ public class ImageUtilTestCase extends TestCase {
// Should not be a buffered image
assertFalse(
"FOR SOME IMPLEMENTATIONS THIS MIGHT FAIL!\nIn that case, testToBufferedImage() will fail too.",
mScaled instanceof BufferedImage
scaled instanceof BufferedImage
);
}
public void testToBufferedImage() {
BufferedImage sameAsImage = ImageUtil.toBuffered((RenderedImage) mImage);
BufferedImage bufferedScaled = ImageUtil.toBuffered(mScaled);
BufferedImage sameAsImage = ImageUtil.toBuffered((RenderedImage) image);
BufferedImage bufferedScaled = ImageUtil.toBuffered(scaled);
// Should be no need to convert
assertSame(mImage, sameAsImage);
assertSame(image, sameAsImage);
// Should have same dimensions
assertEquals(mScaled.getWidth(null), bufferedScaled.getWidth());
assertEquals(mScaled.getHeight(null), bufferedScaled.getHeight());
assertEquals(scaled.getWidth(null), bufferedScaled.getWidth());
assertEquals(scaled.getHeight(null), bufferedScaled.getHeight());
// Hmmm...
assertTrue(new Integer(42).equals(bufferedScaled.getProperty("lucky-number"))
@@ -116,28 +116,28 @@ public class ImageUtilTestCase extends TestCase {
}
public void testToBufferedImageType() {
// Assumes mImage is TYPE_INT_ARGB
BufferedImage converted = ImageUtil.toBuffered(mImage, BufferedImage.TYPE_BYTE_INDEXED);
BufferedImage convertedToo = ImageUtil.toBuffered(mImage, BufferedImage.TYPE_BYTE_BINARY);
// Assumes image is TYPE_INT_ARGB
BufferedImage converted = ImageUtil.toBuffered(image, BufferedImage.TYPE_BYTE_INDEXED);
BufferedImage convertedToo = ImageUtil.toBuffered(image, BufferedImage.TYPE_BYTE_BINARY);
// Should not be the same
assertNotSame(mImage, converted);
assertNotSame(mImage, convertedToo);
assertNotSame(image, converted);
assertNotSame(image, convertedToo);
// Correct type
assertTrue(converted.getType() == BufferedImage.TYPE_BYTE_INDEXED);
assertTrue(convertedToo.getType() == BufferedImage.TYPE_BYTE_BINARY);
// Should have same dimensions
assertEquals(mImage.getWidth(), converted.getWidth());
assertEquals(mImage.getHeight(), converted.getHeight());
assertEquals(image.getWidth(), converted.getWidth());
assertEquals(image.getHeight(), converted.getHeight());
assertEquals(mImage.getWidth(), convertedToo.getWidth());
assertEquals(mImage.getHeight(), convertedToo.getHeight());
assertEquals(image.getWidth(), convertedToo.getWidth());
assertEquals(image.getHeight(), convertedToo.getHeight());
}
public void testBrightness() {
final BufferedImage original = mOriginal;
final BufferedImage original = this.original;
assertNotNull(original);
final BufferedImage notBrightened = ImageUtil.toBuffered(ImageUtil.brightness(original, 0f));
@@ -217,7 +217,7 @@ public class ImageUtilTestCase extends TestCase {
public void testContrast() {
final BufferedImage original = mOriginal;
final BufferedImage original = this.original;
assertNotNull(original);
@@ -370,7 +370,7 @@ public class ImageUtilTestCase extends TestCase {
}
public void testSharpen() {
final BufferedImage original = mOriginal;
final BufferedImage original = this.original;
assertNotNull(original);
@@ -495,7 +495,7 @@ public class ImageUtilTestCase extends TestCase {
}
public void testBlur() {
final BufferedImage original = mOriginal;
final BufferedImage original = this.original;
assertNotNull(original);
@@ -563,7 +563,7 @@ public class ImageUtilTestCase extends TestCase {
}
public void testIndexImage() {
BufferedImage sunflower = mOriginal;
BufferedImage sunflower = original;
assertNotNull(sunflower);

View File

@@ -14,28 +14,28 @@ import java.io.InputStream;
*/
abstract class AbstractCachedSeekableStream extends SeekableInputStream {
/** The backing stream */
protected final InputStream mStream;
protected final InputStream stream;
/** The stream positon in the backing stream (mStream) */
protected long mStreamPosition;
/** The stream positon in the backing stream (stream) */
protected long streamPosition;
private StreamCache mCache;
private StreamCache cache;
protected AbstractCachedSeekableStream(final InputStream pStream, final StreamCache pCache) {
Validate.notNull(pStream, "stream");
Validate.notNull(pCache, "cache");
mStream = pStream;
mCache = pCache;
stream = pStream;
cache = pCache;
}
protected final StreamCache getCache() {
return mCache;
return cache;
}
@Override
public int available() throws IOException {
long avail = mStreamPosition - mPosition + mStream.available();
long avail = streamPosition - position + stream.available();
return avail > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) avail;
}
@@ -43,26 +43,26 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
checkOpen();
int read;
if (mPosition == mStreamPosition) {
if (position == streamPosition) {
// TODO: Read more bytes here!
// TODO: Use buffer if not in-memory cache? (See FileCacheSeekableStream overrides).
// Read a byte from the stream
read = mStream.read();
read = stream.read();
if (read >= 0) {
mStreamPosition++;
mCache.write(read);
streamPosition++;
cache.write(read);
}
}
else {
// ..or read byte from the cache
syncPosition();
read = mCache.read();
read = cache.read();
}
// TODO: This field is not REALLY considered accessible.. :-P
if (read != -1) {
mPosition++;
position++;
}
return read;
@@ -73,32 +73,32 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
checkOpen();
int length;
if (mPosition == mStreamPosition) {
if (position == streamPosition) {
// Read bytes from the stream
length = mStream.read(pBytes, pOffset, pLength);
length = stream.read(pBytes, pOffset, pLength);
if (length > 0) {
mStreamPosition += length;
mCache.write(pBytes, pOffset, length);
streamPosition += length;
cache.write(pBytes, pOffset, length);
}
}
else {
// ...or read bytes from the cache
syncPosition();
length = mCache.read(pBytes, pOffset, pLength);
length = cache.read(pBytes, pOffset, pLength);
}
// TODO: This field is not REALLY considered accessible.. :-P
if (length > 0) {
mPosition += length;
position += length;
}
return length;
}
protected final void syncPosition() throws IOException {
if (mCache.getPosition() != mPosition) {
mCache.seek(mPosition); // Assure EOF is correctly thrown
if (cache.getPosition() != position) {
cache.seek(position); // Assure EOF is correctly thrown
}
}
@@ -111,14 +111,14 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
public abstract boolean isCachedFile();
protected void seekImpl(long pPosition) throws IOException {
if (mStreamPosition < pPosition) {
if (streamPosition < pPosition) {
// Make sure we append at end of cache
if (mCache.getPosition() != mStreamPosition) {
mCache.seek(mStreamPosition);
if (cache.getPosition() != streamPosition) {
cache.seek(streamPosition);
}
// Read diff from stream into cache
long left = pPosition - mStreamPosition;
long left = pPosition - streamPosition;
// TODO: Use fixed buffer, instead of allocating here...
int bufferLen = left > 1024 ? 1024 : (int) left;
@@ -126,11 +126,11 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
while (left > 0) {
int length = buffer.length < left ? buffer.length : (int) left;
int read = mStream.read(buffer, 0, length);
int read = stream.read(buffer, 0, length);
if (read > 0) {
mCache.write(buffer, 0, read);
mStreamPosition += read;
cache.write(buffer, 0, read);
streamPosition += read;
left -= read;
}
else if (read < 0) {
@@ -138,27 +138,27 @@ abstract class AbstractCachedSeekableStream extends SeekableInputStream {
}
}
}
else if (mStreamPosition >= pPosition) {
else if (streamPosition >= pPosition) {
// Seek backwards into the cache
mCache.seek(pPosition);
cache.seek(pPosition);
}
// System.out.println("pPosition: " + pPosition);
// System.out.println("mPosition: " + mPosition);
// System.out.println("mStreamPosition: " + mStreamPosition);
// System.out.println("mCache.mPosition: " + mCache.getPosition());
// System.out.println("position: " + position);
// System.out.println("streamPosition: " + streamPosition);
// System.out.println("cache.position: " + cache.getPosition());
// NOTE: If mPosition == pPosition then we're good to go
// NOTE: If position == pPosition then we're good to go
}
protected void flushBeforeImpl(long pPosition) {
mCache.flush(pPosition);
cache.flush(pPosition);
}
protected void closeImpl() throws IOException {
mCache.flush(mPosition);
mCache = null;
mStream.close();
cache.flush(position);
cache = null;
stream.close();
}
/**

View File

@@ -46,15 +46,16 @@ import java.util.List;
*/
public class CompoundReader extends Reader {
private Reader mCurrent;
private List<Reader> mReaders;
protected final Object mLock;
private Reader current;
private List<Reader> readers;
protected final boolean mMarkSupported;
protected final Object finalLock;
private int mCurrentReader;
private int mMarkedReader;
private int mMark;
protected final boolean markSupported;
private int currentReader;
private int markedReader;
private int mark;
private int mNext;
/**
@@ -71,10 +72,10 @@ public class CompoundReader extends Reader {
public CompoundReader(final Iterator<Reader> pReaders) {
super(Validate.notNull(pReaders, "readers"));
mLock = pReaders; // NOTE: It's ok to sync on pReaders, as the
finalLock = pReaders; // NOTE: It's ok to sync on pReaders, as the
// reference can't change, only it's elements
mReaders = new ArrayList<Reader>();
readers = new ArrayList<Reader>();
boolean markSupported = true;
while (pReaders.hasNext()) {
@@ -82,25 +83,25 @@ public class CompoundReader extends Reader {
if (reader == null) {
throw new NullPointerException("readers cannot contain null-elements");
}
mReaders.add(reader);
readers.add(reader);
markSupported = markSupported && reader.markSupported();
}
mMarkSupported = markSupported;
this.markSupported = markSupported;
mCurrent = nextReader();
current = nextReader();
}
protected final Reader nextReader() {
if (mCurrentReader >= mReaders.size()) {
mCurrent = new EmptyReader();
if (currentReader >= readers.size()) {
current = new EmptyReader();
}
else {
mCurrent = mReaders.get(mCurrentReader++);
current = readers.get(currentReader++);
}
// NOTE: Reset mNext for every reader, and record marked reader in mark/reset methods!
mNext = 0;
return mCurrent;
return current;
}
/**
@@ -109,17 +110,18 @@ public class CompoundReader extends Reader {
* @throws IOException if the stream is closed
*/
protected final void ensureOpen() throws IOException {
if (mReaders == null) {
if (readers == null) {
throw new IOException("Stream closed");
}
}
public void close() throws IOException {
// Close all readers
for (Reader reader : mReaders) {
for (Reader reader : readers) {
reader.close();
}
mReaders = null;
readers = null;
}
@Override
@@ -130,46 +132,46 @@ public class CompoundReader extends Reader {
// TODO: It would be nice if we could actually close some readers now
synchronized (mLock) {
synchronized (finalLock) {
ensureOpen();
mMark = mNext;
mMarkedReader = mCurrentReader;
mark = mNext;
markedReader = currentReader;
mCurrent.mark(pReadLimit);
current.mark(pReadLimit);
}
}
@Override
public void reset() throws IOException {
synchronized (mLock) {
synchronized (finalLock) {
ensureOpen();
if (mCurrentReader != mMarkedReader) {
if (currentReader != markedReader) {
// Reset any reader before this
for (int i = mCurrentReader; i >= mMarkedReader; i--) {
mReaders.get(i).reset();
for (int i = currentReader; i >= markedReader; i--) {
readers.get(i).reset();
}
mCurrentReader = mMarkedReader - 1;
currentReader = markedReader - 1;
nextReader();
}
mCurrent.reset();
current.reset();
mNext = mMark;
mNext = mark;
}
}
@Override
public boolean markSupported() {
return mMarkSupported;
return markSupported;
}
@Override
public int read() throws IOException {
synchronized (mLock) {
int read = mCurrent.read();
synchronized (finalLock) {
int read = current.read();
if (read < 0 && mCurrentReader < mReaders.size()) {
if (read < 0 && currentReader < readers.size()) {
nextReader();
return read(); // In case of 0-length readers
}
@@ -181,10 +183,10 @@ public class CompoundReader extends Reader {
}
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
synchronized (mLock) {
int read = mCurrent.read(pBuffer, pOffset, pLength);
synchronized (finalLock) {
int read = current.read(pBuffer, pOffset, pLength);
if (read < 0 && mCurrentReader < mReaders.size()) {
if (read < 0 && currentReader < readers.size()) {
nextReader();
return read(pBuffer, pOffset, pLength); // In case of 0-length readers
}
@@ -197,15 +199,15 @@ public class CompoundReader extends Reader {
@Override
public boolean ready() throws IOException {
return mCurrent.ready();
return current.ready();
}
@Override
public long skip(long pChars) throws IOException {
synchronized (mLock) {
long skipped = mCurrent.skip(pChars);
synchronized (finalLock) {
long skipped = current.skip(pChars);
if (skipped == 0 && mCurrentReader < mReaders.size()) {
if (skipped == 0 && currentReader < readers.size()) {
nextReader();
return skip(pChars); // In case of 0-length readers
}

View File

@@ -44,7 +44,7 @@ import java.io.ByteArrayInputStream;
// TODO: Performance test of a stream impl that uses list of fixed size blocks, rather than contiguous block
public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
/** Max grow size (unless if writing more than this amount of bytes) */
protected int mMaxGrowSize = 1024 * 1024; // 1 MB
protected int maxGrowSize = 1024 * 1024; // 1 MB
/**
* Creates a {@code ByteArrayOutputStream} with the given initial buffer
@@ -94,7 +94,7 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
private void growIfNeeded(int pNewcount) {
if (pNewcount > buf.length) {
int newSize = Math.max(Math.min(buf.length << 1, buf.length + mMaxGrowSize), pNewcount);
int newSize = Math.max(Math.min(buf.length << 1, buf.length + maxGrowSize), pNewcount);
byte newBuf[] = new byte[newSize];
System.arraycopy(buf, 0, newBuf, 0, count);
buf = newBuf;

View File

@@ -48,16 +48,7 @@ import java.io.*;
*/
public final class FileCacheSeekableStream extends AbstractCachedSeekableStream {
// private final InputStream mStream;
// private final RandomAccessFile mCache;
private byte[] mBuffer;
/** The stream positon in the backing stream (mStream) */
// private long mStreamPosition;
// TODO: getStreamPosition() should always be the same as
// mCache.getFilePointer()
// otherwise there's some inconsistency here... Enforce this?
private byte[] buffer;
/**
* Creates a {@code FileCacheSeekableStream} reading from the given
@@ -118,7 +109,7 @@ public final class FileCacheSeekableStream extends AbstractCachedSeekableStream
super(pStream, new FileCache(pFile));
// TODO: Allow for custom buffer sizes?
mBuffer = new byte[1024];
buffer = new byte[1024];
}
public final boolean isCachedMemory() {
@@ -132,39 +123,19 @@ public final class FileCacheSeekableStream extends AbstractCachedSeekableStream
@Override
protected void closeImpl() throws IOException {
super.closeImpl();
mBuffer = null;
buffer = null;
}
/*
public final boolean isCached() {
return true;
}
// InputStream overrides
@Override
public int available() throws IOException {
long avail = mStreamPosition - mPosition + mStream.available();
return avail > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) avail;
}
public void closeImpl() throws IOException {
mStream.close();
mCache.close();
// TODO: Delete cache file here?
// ThreadPool.invokeLater(new DeleteFileAction(mCacheFile));
}
*/
@Override
public int read() throws IOException {
checkOpen();
int read;
if (mPosition == mStreamPosition) {
if (position == streamPosition) {
// Read ahead into buffer, for performance
read = readAhead(mBuffer, 0, mBuffer.length);
read = readAhead(buffer, 0, buffer.length);
if (read >= 0) {
read = mBuffer[0] & 0xff;
read = buffer[0] & 0xff;
}
//System.out.println("Read 1 byte from stream: " + Integer.toHexString(read & 0xff));
@@ -179,7 +150,7 @@ public final class FileCacheSeekableStream extends AbstractCachedSeekableStream
// TODO: This field is not REALLY considered accessible.. :-P
if (read != -1) {
mPosition++;
position++;
}
return read;
}
@@ -189,7 +160,7 @@ public final class FileCacheSeekableStream extends AbstractCachedSeekableStream
checkOpen();
int length;
if (mPosition == mStreamPosition) {
if (position == streamPosition) {
// Read bytes from the stream
length = readAhead(pBytes, pOffset, pLength);
@@ -198,83 +169,29 @@ public final class FileCacheSeekableStream extends AbstractCachedSeekableStream
else {
// ...or read bytes from the cache
syncPosition();
length = getCache().read(pBytes, pOffset, (int) Math.min(pLength, mStreamPosition - mPosition));
length = getCache().read(pBytes, pOffset, (int) Math.min(pLength, streamPosition - position));
//System.out.println("Read " + length + " byte from cache");
}
// TODO: This field is not REALLY considered accessible.. :-P
if (length > 0) {
mPosition += length;
position += length;
}
return length;
}
private int readAhead(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
int length;
length = mStream.read(pBytes, pOffset, pLength);
length = stream.read(pBytes, pOffset, pLength);
if (length > 0) {
mStreamPosition += length;
streamPosition += length;
getCache().write(pBytes, pOffset, length);
}
return length;
}
/*
private void syncPosition() throws IOException {
if (mCache.getFilePointer() != mPosition) {
mCache.seek(mPosition); // Assure EOF is correctly thrown
}
}
// Seekable overrides
protected void flushBeforeImpl(long pPosition) {
// TODO: Implement
// For now, it's probably okay to do nothing, this is just for
// performance (as long as people follow spec, not behaviour)
}
protected void seekImpl(long pPosition) throws IOException {
if (mStreamPosition < pPosition) {
// Make sure we append at end of cache
if (mCache.getFilePointer() != mStreamPosition) {
mCache.seek(mStreamPosition);
}
// Read diff from stream into cache
long left = pPosition - mStreamPosition;
int bufferLen = left > 1024 ? 1024 : (int) left;
byte[] buffer = new byte[bufferLen];
while (left > 0) {
int length = buffer.length < left ? buffer.length : (int) left;
int read = mStream.read(buffer, 0, length);
if (read > 0) {
mCache.write(buffer, 0, read);
mStreamPosition += read;
left -= read;
}
else if (read < 0) {
break;
}
}
}
else if (mStreamPosition >= pPosition) {
// Seek backwards into the cache
mCache.seek(pPosition);
}
// System.out.println("pPosition: " + pPosition);
// System.out.println("mStreamPosition: " + mStreamPosition);
// System.out.println("mCache.getFilePointer(): " + mCache.getFilePointer());
// NOTE: If mPosition == pPosition then we're good to go
}
*/
final static class FileCache extends StreamCache {
private RandomAccessFile mCacheFile;

View File

@@ -87,7 +87,7 @@ public final class FileSeekableStream extends SeekableInputStream {
@Override
public int available() throws IOException {
long length = mRandomAccess.length() - mPosition;
long length = mRandomAccess.length() - position;
return length > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) length;
}
@@ -100,7 +100,7 @@ public final class FileSeekableStream extends SeekableInputStream {
int read = mRandomAccess.read();
if (read >= 0) {
mPosition++;
position++;
}
return read;
}
@@ -111,7 +111,7 @@ public final class FileSeekableStream extends SeekableInputStream {
int read = mRandomAccess.read(pBytes, pOffset, pLength);
if (read > 0) {
mPosition += read;
position += read;
}
return read;
}

View File

@@ -80,10 +80,10 @@ abstract class FileSystem {
}
private static class UnknownFileSystem extends FileSystem {
private final String mOSName;
private final String osName;
UnknownFileSystem(String pOSName) {
mOSName = pOSName;
osName = pOSName;
}
long getFreeSpace(File pPath) {
@@ -95,7 +95,7 @@ abstract class FileSystem {
}
String getName() {
return "Unknown (" + mOSName + ")";
return "Unknown (" + osName + ")";
}
}
}

View File

@@ -685,28 +685,28 @@ public final class FileUtil {
// a file array, which may throw OutOfMemoryExceptions for
// large directories/in low memory situations
class DeleteFilesVisitor implements Visitor<File> {
private int mFailedCount = 0;
private IOException mException = null;
private int failedCount = 0;
private IOException exception = null;
public void visit(final File pFile) {
try {
if (!delete(pFile, true)) {
mFailedCount++;
failedCount++;
}
}
catch (IOException e) {
mFailedCount++;
if (mException == null) {
mException = e;
failedCount++;
if (exception == null) {
exception = e;
}
}
}
boolean succeeded() throws IOException {
if (mException != null) {
throw mException;
if (exception != null) {
throw exception;
}
return mFailedCount == 0;
return failedCount == 0;
}
}
DeleteFilesVisitor fileDeleter = new DeleteFilesVisitor();

View File

@@ -60,9 +60,9 @@ import java.io.FilenameFilter;
public class FilenameMaskFilter implements FilenameFilter {
// Members
private String[] mFilenameMasksForInclusion;
private String[] mFilenameMasksForExclusion;
private boolean mInclusion = true;
private String[] filenameMasksForInclusion;
private String[] filenameMasksForExclusion;
private boolean inclusion = true;
/**
@@ -127,29 +127,29 @@ public class FilenameMaskFilter implements FilenameFilter {
* @param pFilenameMasksForInclusion the filename masks to include
*/
public void setFilenameMasksForInclusion(String[] pFilenameMasksForInclusion) {
mFilenameMasksForInclusion = pFilenameMasksForInclusion;
filenameMasksForInclusion = pFilenameMasksForInclusion;
}
/**
* @return the current inclusion masks
*/
public String[] getFilenameMasksForInclusion() {
return mFilenameMasksForInclusion.clone();
return filenameMasksForInclusion.clone();
}
/**
* @param pFilenameMasksForExclusion the filename masks to exclude
*/
public void setFilenameMasksForExclusion(String[] pFilenameMasksForExclusion) {
mFilenameMasksForExclusion = pFilenameMasksForExclusion;
mInclusion = false;
filenameMasksForExclusion = pFilenameMasksForExclusion;
inclusion = false;
}
/**
* @return the current exclusion masks
*/
public String[] getFilenameMasksForExclusion() {
return mFilenameMasksForExclusion.clone();
return filenameMasksForExclusion.clone();
}
/**
@@ -164,8 +164,8 @@ public class FilenameMaskFilter implements FilenameFilter {
WildcardStringParser parser;
// Check each filename string mask whether the file is to be accepted
if (mInclusion) { // Inclusion
for (String mask : mFilenameMasksForInclusion) {
if (inclusion) { // Inclusion
for (String mask : filenameMasksForInclusion) {
parser = new WildcardStringParser(mask);
if (parser.parseString(pName)) {
@@ -181,7 +181,7 @@ public class FilenameMaskFilter implements FilenameFilter {
}
else {
// Exclusion
for (String mask : mFilenameMasksForExclusion) {
for (String mask : filenameMasksForExclusion) {
parser = new WildcardStringParser(mask);
if (parser.parseString(pName)) {
@@ -204,32 +204,32 @@ public class FilenameMaskFilter implements FilenameFilter {
StringBuilder retVal = new StringBuilder();
int i;
if (mInclusion) {
if (inclusion) {
// Inclusion
if (mFilenameMasksForInclusion == null) {
retVal.append("No filename masks set - property mFilenameMasksForInclusion is null!");
if (filenameMasksForInclusion == null) {
retVal.append("No filename masks set - property filenameMasksForInclusion is null!");
}
else {
retVal.append(mFilenameMasksForInclusion.length);
retVal.append(filenameMasksForInclusion.length);
retVal.append(" filename mask(s) - ");
for (i = 0; i < mFilenameMasksForInclusion.length; i++) {
for (i = 0; i < filenameMasksForInclusion.length; i++) {
retVal.append("\"");
retVal.append(mFilenameMasksForInclusion[i]);
retVal.append(filenameMasksForInclusion[i]);
retVal.append("\", \"");
}
}
}
else {
// Exclusion
if (mFilenameMasksForExclusion == null) {
retVal.append("No filename masks set - property mFilenameMasksForExclusion is null!");
if (filenameMasksForExclusion == null) {
retVal.append("No filename masks set - property filenameMasksForExclusion is null!");
}
else {
retVal.append(mFilenameMasksForExclusion.length);
retVal.append(filenameMasksForExclusion.length);
retVal.append(" exclusion filename mask(s) - ");
for (i = 0; i < mFilenameMasksForExclusion.length; i++) {
for (i = 0; i < filenameMasksForExclusion.length; i++) {
retVal.append("\"");
retVal.append(mFilenameMasksForExclusion[i]);
retVal.append(filenameMasksForExclusion[i]);
retVal.append("\", \"");
}
}

View File

@@ -1,93 +0,0 @@
/*
* Copyright (c) 2008, Harald Kuhr
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name "TwelveMonkeys" nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.StringUtil;
import java.io.File;
import java.io.FilenameFilter;
/**
* A Java Bean used for approving file names which are to be included in a
* {@code java.io.File} listing. The file name suffixes are used as a
* filter input and is given to the class via the string array property:<br>
* <dd>{@code filenameSuffixesToExclude}
* <p>
* A recommended way of doing this is by referencing to the component which uses
* this class for file listing. In this way all properties are set in the same
* component and this utility component is kept in the background with only
* initial configuration necessary.
*
* @author <a href="mailto:eirik.torske@iconmedialab.no">Eirik Torske</a>
* @see File#list(java.io.FilenameFilter) java.io.File.list
* @see FilenameFilter java.io.FilenameFilter
*/
public class FilenameSuffixFilter implements FilenameFilter {
// Members
String[] mFilenameSuffixesToExclude;
/** Creates a {@code FileNameSuffixFilter} */
public FilenameSuffixFilter() {
}
public void setFilenameSuffixesToExclude(String[] pFilenameSuffixesToExclude) {
mFilenameSuffixesToExclude = pFilenameSuffixesToExclude;
}
public String[] getFilenameSuffixesToExclude() {
return mFilenameSuffixesToExclude;
}
/**
* This method implements the {@code java.io.FilenameFilter} interface.
* <p/>
*
* @param pDir the directory in which the file was found.
* @param pName the pName of the file.
* @return {@code true} if the pName should be included in the file list;
* {@code false} otherwise.
*/
public boolean accept(final File pDir, final String pName) {
if (StringUtil.isEmpty(mFilenameSuffixesToExclude)) {
return true;
}
for (String aMFilenameSuffixesToExclude : mFilenameSuffixesToExclude) {
// -- Edit by haraldK, to make interfaces more consistent
// if (StringUtil.filenameSuffixIs(pName, mFilenameSuffixesToExclude[i])) {
if (aMFilenameSuffixesToExclude.equals(FileUtil.getExtension(pName))) {
return false;
}
}
return true;
}
}

View File

@@ -38,6 +38,8 @@
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.*;
/**
@@ -75,10 +77,7 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
* @see java.io.FilterInputStream#in
*/
public LittleEndianDataInputStream(final InputStream pStream) {
super(pStream);
if (pStream == null) {
throw new IllegalArgumentException("stream == null");
}
super(Validate.notNull(pStream, "stream"));
}
/**
@@ -93,9 +92,11 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
*/
public boolean readBoolean() throws IOException {
int b = in.read();
if (b < 0) {
throw new EOFException();
}
return b != 0;
}
@@ -110,9 +111,11 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
*/
public byte readByte() throws IOException {
int b = in.read();
if (b < 0) {
throw new EOFException();
}
return (byte) b;
}
@@ -128,9 +131,11 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
*/
public int readUnsignedByte() throws IOException {
int b = in.read();
if (b < 0) {
throw new EOFException();
}
return b;
}
@@ -146,11 +151,13 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
public short readShort() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
// only need to test last byte read
// if byte1 is -1 so is byte2
if (byte2 < 0) {
throw new EOFException();
}
return (short) (((byte2 << 24) >>> 16) + (byte1 << 24) >>> 24);
}
@@ -166,10 +173,11 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
public int readUnsignedShort() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
if (byte2 < 0) {
throw new EOFException();
}
//return ((byte2 << 24) >> 16) + ((byte1 << 24) >> 24);
return (byte2 << 8) + byte1;
}
@@ -185,9 +193,11 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
public char readChar() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
if (byte2 < 0) {
throw new EOFException();
}
return (char) (((byte2 << 24) >>> 16) + ((byte1 << 24) >>> 24));
}
@@ -210,6 +220,7 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
if (byte4 < 0) {
throw new EOFException();
}
return (byte4 << 24) + ((byte3 << 24) >>> 8)
+ ((byte2 << 24) >>> 16) + ((byte1 << 24) >>> 24);
}
@@ -236,11 +247,11 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
if (byte8 < 0) {
throw new EOFException();
}
return (byte8 << 56) + ((byte7 << 56) >>> 8)
+ ((byte6 << 56) >>> 16) + ((byte5 << 56) >>> 24)
+ ((byte4 << 56) >>> 32) + ((byte3 << 56) >>> 40)
+ ((byte2 << 56) >>> 48) + ((byte1 << 56) >>> 56);
}
/**
@@ -260,16 +271,17 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
public String readUTF() throws IOException {
int byte1 = in.read();
int byte2 = in.read();
if (byte2 < 0) {
throw new EOFException();
}
int numbytes = (byte1 << 8) + byte2;
char result[] = new char[numbytes];
int numread = 0;
int numchars = 0;
while (numread < numbytes) {
int c1 = readUnsignedByte();
int c2, c3;
@@ -281,27 +293,34 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
}
else if (test == 12 || test == 13) { // two bytes
numread += 2;
if (numread > numbytes) {
throw new UTFDataFormatException();
}
c2 = readUnsignedByte();
if ((c2 & 0xC0) != 0x80) {
throw new UTFDataFormatException();
}
result[numchars++] = (char) (((c1 & 0x1F) << 6) | (c2 & 0x3F));
}
else if (test == 14) { // three bytes
numread += 3;
if (numread > numbytes) {
throw new UTFDataFormatException();
}
c2 = readUnsignedByte();
c3 = readUnsignedByte();
if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) {
throw new UTFDataFormatException();
}
result[numchars++] = (char)
(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
result[numchars++] = (char) (((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
}
else { // malformed
throw new UTFDataFormatException();
@@ -396,12 +415,16 @@ public class LittleEndianDataInputStream extends FilterInputStream implements Da
if (pLength < 0) {
throw new IndexOutOfBoundsException();
}
int count = 0;
while (count < pLength) {
int read = in.read(pBytes, pOffset + count, pLength - count);
if (read < 0) {
throw new EOFException();
}
count += read;
}
}

View File

@@ -38,6 +38,8 @@
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.*;
/**
@@ -69,7 +71,7 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
/**
* The number of bytes written so far to the little endian output stream.
*/
protected int mWritten;
protected int bytesWritten;
/**
* Creates a new little endian output stream and chains it to the
@@ -79,10 +81,7 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
* @see java.io.FilterOutputStream#out
*/
public LittleEndianDataOutputStream(OutputStream pStream) {
super(pStream);
if (pStream == null) {
throw new IllegalArgumentException("stream == null");
}
super(Validate.notNull(pStream, "stream"));
}
/**
@@ -93,7 +92,7 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
*/
public synchronized void write(int pByte) throws IOException {
out.write(pByte);
mWritten++;
bytesWritten++;
}
/**
@@ -105,10 +104,9 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
* @param pLength the number of bytes to write.
* @throws IOException if the underlying stream throws an IOException.
*/
public synchronized void write(byte[] pBytes, int pOffset, int pLength)
throws IOException {
public synchronized void write(byte[] pBytes, int pOffset, int pLength) throws IOException {
out.write(pBytes, pOffset, pLength);
mWritten += pLength;
bytesWritten += pLength;
}
@@ -137,7 +135,7 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
*/
public void writeByte(int pByte) throws IOException {
out.write(pByte);
mWritten++;
bytesWritten++;
}
/**
@@ -150,7 +148,7 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
public void writeShort(int pShort) throws IOException {
out.write(pShort & 0xFF);
out.write((pShort >>> 8) & 0xFF);
mWritten += 2;
bytesWritten += 2;
}
/**
@@ -163,7 +161,7 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
public void writeChar(int pChar) throws IOException {
out.write(pChar & 0xFF);
out.write((pChar >>> 8) & 0xFF);
mWritten += 2;
bytesWritten += 2;
}
/**
@@ -178,7 +176,7 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
out.write((pInt >>> 8) & 0xFF);
out.write((pInt >>> 16) & 0xFF);
out.write((pInt >>> 24) & 0xFF);
mWritten += 4;
bytesWritten += 4;
}
@@ -198,7 +196,7 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
out.write((int) (pLong >>> 40) & 0xFF);
out.write((int) (pLong >>> 48) & 0xFF);
out.write((int) (pLong >>> 56) & 0xFF);
mWritten += 8;
bytesWritten += 8;
}
/**
@@ -235,10 +233,12 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
*/
public void writeBytes(String pString) throws IOException {
int length = pString.length();
for (int i = 0; i < length; i++) {
out.write((byte) pString.charAt(i));
}
mWritten += length;
bytesWritten += length;
}
/**
@@ -253,12 +253,14 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
*/
public void writeChars(String pString) throws IOException {
int length = pString.length();
for (int i = 0; i < length; i++) {
int c = pString.charAt(i);
out.write(c & 0xFF);
out.write((c >>> 8) & 0xFF);
}
mWritten += length * 2;
bytesWritten += length * 2;
}
/**
@@ -282,6 +284,7 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
for (int i = 0; i < numchars; i++) {
int c = pString.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
numbytes++;
}
@@ -299,8 +302,10 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
out.write((numbytes >>> 8) & 0xFF);
out.write(numbytes & 0xFF);
for (int i = 0; i < numchars; i++) {
int c = pString.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
out.write(c);
}
@@ -308,16 +313,16 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
out.write(0xE0 | ((c >> 12) & 0x0F));
out.write(0x80 | ((c >> 6) & 0x3F));
out.write(0x80 | (c & 0x3F));
mWritten += 2;
bytesWritten += 2;
}
else {
out.write(0xC0 | ((c >> 6) & 0x1F));
out.write(0x80 | (c & 0x3F));
mWritten += 1;
bytesWritten += 1;
}
}
mWritten += numchars + 2;
bytesWritten += numchars + 2;
}
/**
@@ -326,9 +331,9 @@ public class LittleEndianDataOutputStream extends FilterOutputStream implements
* possible that this number is temporarily less than the actual
* number of bytes written.)
* @return the value of the {@code written} field.
* @see #mWritten
* @see #bytesWritten
*/
public int size() {
return mWritten;
return bytesWritten;
}
}

View File

@@ -56,58 +56,58 @@ import java.nio.channels.FileChannel;
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/LittleEndianRandomAccessFile.java#1 $
*/
public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
private RandomAccessFile mFile;
private RandomAccessFile file;
public LittleEndianRandomAccessFile(final String pName, final String pMode) throws FileNotFoundException {
this(FileUtil.resolve(pName), pMode);
}
public LittleEndianRandomAccessFile(final File pFile, final String pMode) throws FileNotFoundException {
mFile = new RandomAccessFile(pFile, pMode);
file = new RandomAccessFile(pFile, pMode);
}
public void close() throws IOException {
mFile.close();
file.close();
}
public FileChannel getChannel() {
return mFile.getChannel();
return file.getChannel();
}
public FileDescriptor getFD() throws IOException {
return mFile.getFD();
return file.getFD();
}
public long getFilePointer() throws IOException {
return mFile.getFilePointer();
return file.getFilePointer();
}
public long length() throws IOException {
return mFile.length();
return file.length();
}
public int read() throws IOException {
return mFile.read();
return file.read();
}
public int read(final byte[] b) throws IOException {
return mFile.read(b);
return file.read(b);
}
public int read(final byte[] b, final int off, final int len) throws IOException {
return mFile.read(b, off, len);
return file.read(b, off, len);
}
public void readFully(final byte[] b) throws IOException {
mFile.readFully(b);
file.readFully(b);
}
public void readFully(final byte[] b, final int off, final int len) throws IOException {
mFile.readFully(b, off, len);
file.readFully(b, off, len);
}
public String readLine() throws IOException {
return mFile.readLine();
return file.readLine();
}
/**
@@ -121,10 +121,12 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public boolean readBoolean() throws IOException {
int b = mFile.read();
int b = file.read();
if (b < 0) {
throw new EOFException();
}
return b != 0;
}
@@ -138,10 +140,12 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public byte readByte() throws IOException {
int b = mFile.read();
int b = file.read();
if (b < 0) {
throw new EOFException();
}
return (byte) b;
}
@@ -156,10 +160,12 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public int readUnsignedByte() throws IOException {
int b = mFile.read();
int b = file.read();
if (b < 0) {
throw new EOFException();
}
return b;
}
@@ -173,13 +179,15 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public short readShort() throws IOException {
int byte1 = mFile.read();
int byte2 = mFile.read();
int byte1 = file.read();
int byte2 = file.read();
// only need to test last byte read
// if byte1 is -1 so is byte2
if (byte2 < 0) {
throw new EOFException();
}
return (short) (((byte2 << 24) >>> 16) + (byte1 << 24) >>> 24);
}
@@ -193,11 +201,13 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public int readUnsignedShort() throws IOException {
int byte1 = mFile.read();
int byte2 = mFile.read();
int byte1 = file.read();
int byte2 = file.read();
if (byte2 < 0) {
throw new EOFException();
}
//return ((byte2 << 24) >> 16) + ((byte1 << 24) >> 24);
return (byte2 << 8) + byte1;
}
@@ -212,11 +222,13 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public char readChar() throws IOException {
int byte1 = mFile.read();
int byte2 = mFile.read();
int byte1 = file.read();
int byte2 = file.read();
if (byte2 < 0) {
throw new EOFException();
}
return (char) (((byte2 << 24) >>> 16) + ((byte1 << 24) >>> 24));
}
@@ -231,16 +243,16 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public int readInt() throws IOException {
int byte1 = mFile.read();
int byte2 = mFile.read();
int byte3 = mFile.read();
int byte4 = mFile.read();
int byte1 = file.read();
int byte2 = file.read();
int byte3 = file.read();
int byte4 = file.read();
if (byte4 < 0) {
throw new EOFException();
}
return (byte4 << 24) + ((byte3 << 24) >>> 8)
+ ((byte2 << 24) >>> 16) + ((byte1 << 24) >>> 24);
return (byte4 << 24) + ((byte3 << 24) >>> 8) + ((byte2 << 24) >>> 16) + ((byte1 << 24) >>> 24);
}
/**
@@ -253,18 +265,19 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public long readLong() throws IOException {
long byte1 = mFile.read();
long byte2 = mFile.read();
long byte3 = mFile.read();
long byte4 = mFile.read();
long byte5 = mFile.read();
long byte6 = mFile.read();
long byte7 = mFile.read();
long byte8 = mFile.read();
long byte1 = file.read();
long byte2 = file.read();
long byte3 = file.read();
long byte4 = file.read();
long byte5 = file.read();
long byte6 = file.read();
long byte7 = file.read();
long byte8 = file.read();
if (byte8 < 0) {
throw new EOFException();
}
return (byte8 << 56) + ((byte7 << 56) >>> 8)
+ ((byte6 << 56) >>> 16) + ((byte5 << 56) >>> 24)
+ ((byte4 << 56) >>> 32) + ((byte3 << 56) >>> 40)
@@ -287,11 +300,13 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public String readUTF() throws IOException {
int byte1 = mFile.read();
int byte2 = mFile.read();
int byte1 = file.read();
int byte2 = file.read();
if (byte2 < 0) {
throw new EOFException();
}
int numbytes = (byte1 << 8) + byte2;
char result[] = new char[numbytes];
int numread = 0;
@@ -310,27 +325,34 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
}
else if (test == 12 || test == 13) { // two bytes
numread += 2;
if (numread > numbytes) {
throw new UTFDataFormatException();
}
c2 = readUnsignedByte();
if ((c2 & 0xC0) != 0x80) {
throw new UTFDataFormatException();
}
result[numchars++] = (char) (((c1 & 0x1F) << 6) | (c2 & 0x3F));
}
else if (test == 14) { // three bytes
numread += 3;
if (numread > numbytes) {
throw new UTFDataFormatException();
}
c2 = readUnsignedByte();
c3 = readUnsignedByte();
if (((c2 & 0xC0) != 0x80) || ((c3 & 0xC0) != 0x80)) {
throw new UTFDataFormatException();
}
result[numchars++] = (char)
(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
result[numchars++] = (char) (((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
}
else { // malformed
throw new UTFDataFormatException();
@@ -378,27 +400,27 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* {@code 0} or if an I/O error occurs.
*/
public void seek(final long pos) throws IOException {
mFile.seek(pos);
file.seek(pos);
}
public void setLength(final long newLength) throws IOException {
mFile.setLength(newLength);
file.setLength(newLength);
}
public int skipBytes(final int n) throws IOException {
return mFile.skipBytes(n);
return file.skipBytes(n);
}
public void write(final byte[] b) throws IOException {
mFile.write(b);
file.write(b);
}
public void write(final byte[] b, final int off, final int len) throws IOException {
mFile.write(b, off, len);
file.write(b, off, len);
}
public void write(final int b) throws IOException {
mFile.write(b);
file.write(b);
}
/**
@@ -425,7 +447,7 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeByte(int pByte) throws IOException {
mFile.write(pByte);
file.write(pByte);
}
/**
@@ -436,8 +458,8 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeShort(int pShort) throws IOException {
mFile.write(pShort & 0xFF);
mFile.write((pShort >>> 8) & 0xFF);
file.write(pShort & 0xFF);
file.write((pShort >>> 8) & 0xFF);
}
/**
@@ -448,8 +470,8 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeChar(int pChar) throws IOException {
mFile.write(pChar & 0xFF);
mFile.write((pChar >>> 8) & 0xFF);
file.write(pChar & 0xFF);
file.write((pChar >>> 8) & 0xFF);
}
/**
@@ -460,11 +482,10 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeInt(int pInt) throws IOException {
mFile.write(pInt & 0xFF);
mFile.write((pInt >>> 8) & 0xFF);
mFile.write((pInt >>> 16) & 0xFF);
mFile.write((pInt >>> 24) & 0xFF);
file.write(pInt & 0xFF);
file.write((pInt >>> 8) & 0xFF);
file.write((pInt >>> 16) & 0xFF);
file.write((pInt >>> 24) & 0xFF);
}
/**
@@ -475,14 +496,14 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @throws IOException if the underlying stream throws an IOException.
*/
public void writeLong(long pLong) throws IOException {
mFile.write((int) pLong & 0xFF);
mFile.write((int) (pLong >>> 8) & 0xFF);
mFile.write((int) (pLong >>> 16) & 0xFF);
mFile.write((int) (pLong >>> 24) & 0xFF);
mFile.write((int) (pLong >>> 32) & 0xFF);
mFile.write((int) (pLong >>> 40) & 0xFF);
mFile.write((int) (pLong >>> 48) & 0xFF);
mFile.write((int) (pLong >>> 56) & 0xFF);
file.write((int) pLong & 0xFF);
file.write((int) (pLong >>> 8) & 0xFF);
file.write((int) (pLong >>> 16) & 0xFF);
file.write((int) (pLong >>> 24) & 0xFF);
file.write((int) (pLong >>> 32) & 0xFF);
file.write((int) (pLong >>> 40) & 0xFF);
file.write((int) (pLong >>> 48) & 0xFF);
file.write((int) (pLong >>> 56) & 0xFF);
}
/**
@@ -515,12 +536,13 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @param pString the {@code String} value to be written.
* @throws IOException if the underlying stream throws an IOException.
* @see #writeByte(int)
* @see #mFile
* @see #file
*/
public void writeBytes(String pString) throws IOException {
int length = pString.length();
for (int i = 0; i < length; i++) {
mFile.write((byte) pString.charAt(i));
file.write((byte) pString.charAt(i));
}
}
@@ -532,14 +554,15 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
* @param pString a {@code String} value to be written.
* @throws IOException if the underlying stream throws an IOException.
* @see #writeChar(int)
* @see #mFile
* @see #file
*/
public void writeChars(String pString) throws IOException {
int length = pString.length();
for (int i = 0; i < length; i++) {
int c = pString.charAt(i);
mFile.write(c & 0xFF);
mFile.write((c >>> 8) & 0xFF);
file.write(c & 0xFF);
file.write((c >>> 8) & 0xFF);
}
}
@@ -564,6 +587,7 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
for (int i = 0; i < numchars; i++) {
int c = pString.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
numbytes++;
}
@@ -579,21 +603,23 @@ public class LittleEndianRandomAccessFile implements DataInput, DataOutput {
throw new UTFDataFormatException();
}
mFile.write((numbytes >>> 8) & 0xFF);
mFile.write(numbytes & 0xFF);
file.write((numbytes >>> 8) & 0xFF);
file.write(numbytes & 0xFF);
for (int i = 0; i < numchars; i++) {
int c = pString.charAt(i);
if ((c >= 0x0001) && (c <= 0x007F)) {
mFile.write(c);
file.write(c);
}
else if (c > 0x07FF) {
mFile.write(0xE0 | ((c >> 12) & 0x0F));
mFile.write(0x80 | ((c >> 6) & 0x3F));
mFile.write(0x80 | (c & 0x3F));
file.write(0xE0 | ((c >> 12) & 0x0F));
file.write(0x80 | ((c >> 6) & 0x3F));
file.write(0x80 | (c & 0x3F));
}
else {
mFile.write(0xC0 | ((c >> 6) & 0x1F));
mFile.write(0x80 | (c & 0x3F));
file.write(0xC0 | ((c >> 6) & 0x1F));
file.write(0x80 | (c & 0x3F));
}
}
}

View File

@@ -65,13 +65,13 @@ public final class MemoryCacheSeekableStream extends AbstractCachedSeekableStrea
final static class MemoryCache extends StreamCache {
final static int BLOCK_SIZE = 1 << 13;
private final List<byte[]> mCache = new ArrayList<byte[]>();
private long mLength;
private long mPosition;
private long mStart;
private final List<byte[]> cache = new ArrayList<byte[]>();
private long length;
private long position;
private long start;
private byte[] getBlock() throws IOException {
final long currPos = mPosition - mStart;
final long currPos = position - start;
if (currPos < 0) {
throw new IOException("StreamCache flushed before read position");
}
@@ -82,31 +82,31 @@ public final class MemoryCacheSeekableStream extends AbstractCachedSeekableStrea
throw new IOException("Memory cache max size exceeded");
}
if (index >= mCache.size()) {
if (index >= cache.size()) {
try {
mCache.add(new byte[BLOCK_SIZE]);
cache.add(new byte[BLOCK_SIZE]);
// System.out.println("Allocating new block, size: " + BLOCK_SIZE);
// System.out.println("New total size: " + mCache.size() * BLOCK_SIZE + " (" + mCache.size() + " blocks)");
// System.out.println("New total size: " + cache.size() * BLOCK_SIZE + " (" + cache.size() + " blocks)");
}
catch (OutOfMemoryError e) {
throw new IOException("No more memory for cache: " + mCache.size() * BLOCK_SIZE);
throw new IOException("No more memory for cache: " + cache.size() * BLOCK_SIZE);
}
}
//System.out.println("index: " + index);
return mCache.get((int) index);
return cache.get((int) index);
}
public void write(final int pByte) throws IOException {
byte[] buffer = getBlock();
int idx = (int) (mPosition % BLOCK_SIZE);
int idx = (int) (position % BLOCK_SIZE);
buffer[idx] = (byte) pByte;
mPosition++;
position++;
if (mPosition > mLength) {
mLength = mPosition;
if (position > length) {
length = position;
}
}
@@ -115,28 +115,28 @@ public final class MemoryCacheSeekableStream extends AbstractCachedSeekableStrea
public void write(final byte[] pBuffer, final int pOffset, final int pLength) throws IOException {
byte[] buffer = getBlock();
for (int i = 0; i < pLength; i++) {
int index = (int) mPosition % BLOCK_SIZE;
int index = (int) position % BLOCK_SIZE;
if (index == 0) {
buffer = getBlock();
}
buffer[index] = pBuffer[pOffset + i];
mPosition++;
position++;
}
if (mPosition > mLength) {
mLength = mPosition;
if (position > length) {
length = position;
}
}
public int read() throws IOException {
if (mPosition >= mLength) {
if (position >= length) {
return -1;
}
byte[] buffer = getBlock();
int idx = (int) (mPosition % BLOCK_SIZE);
mPosition++;
int idx = (int) (position % BLOCK_SIZE);
position++;
return buffer[idx] & 0xff;
}
@@ -144,33 +144,33 @@ public final class MemoryCacheSeekableStream extends AbstractCachedSeekableStrea
// TODO: OptimizeMe!!!
@Override
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
if (mPosition >= mLength) {
if (position >= length) {
return -1;
}
byte[] buffer = getBlock();
int bufferPos = (int) (mPosition % BLOCK_SIZE);
int bufferPos = (int) (position % BLOCK_SIZE);
// Find maxIdx and simplify test in for-loop
int maxLen = (int) Math.min(Math.min(pLength, buffer.length - bufferPos), mLength - mPosition);
int maxLen = (int) Math.min(Math.min(pLength, buffer.length - bufferPos), length - position);
int i;
//for (i = 0; i < pLength && i < buffer.length - idx && i < mLength - mPosition; i++) {
//for (i = 0; i < pLength && i < buffer.length - idx && i < length - position; i++) {
for (i = 0; i < maxLen; i++) {
pBytes[pOffset + i] = buffer[bufferPos + i];
}
mPosition += i;
position += i;
return i;
}
public void seek(final long pPosition) throws IOException {
if (pPosition < mStart) {
if (pPosition < start) {
throw new IOException("Seek before flush position");
}
mPosition = pPosition;
position = pPosition;
}
@Override
@@ -178,14 +178,14 @@ public final class MemoryCacheSeekableStream extends AbstractCachedSeekableStrea
int firstPos = (int) (pPosition / BLOCK_SIZE) - 1;
for (int i = 0; i < firstPos; i++) {
mCache.remove(0);
cache.remove(0);
}
mStart = pPosition;
start = pPosition;
}
public long getPosition() {
return mPosition;
return position;
}
}
}

View File

@@ -50,13 +50,12 @@ public abstract class RandomAccessStream implements Seekable, DataInput, DataOut
// TODO: Package private SeekableDelegate?
// TODO: Both read and write must update stream position
//private int mPosition = -1;
//private int position = -1;
/** This random access stream, wrapped in an {@code InputStream} */
SeekableInputStream mInputView = null;
SeekableInputStream inputView = null;
/** This random access stream, wrapped in an {@code OutputStream} */
SeekableOutputStream mOutputView = null;
SeekableOutputStream outputView = null;
// TODO: Create an Input and an Output interface matching InputStream and OutputStream?
public int read() throws IOException {
@@ -119,10 +118,10 @@ public abstract class RandomAccessStream implements Seekable, DataInput, DataOut
* @return a {@code SeekableInputStream} reading from this stream
*/
public final SeekableInputStream asInputStream() {
if (mInputView == null) {
mInputView = new InputStreamView(this);
if (inputView == null) {
inputView = new InputStreamView(this);
}
return mInputView;
return inputView;
}
/**
@@ -134,15 +133,15 @@ public abstract class RandomAccessStream implements Seekable, DataInput, DataOut
* @return a {@code SeekableOutputStream} writing to this stream
*/
public final SeekableOutputStream asOutputStream() {
if (mOutputView == null) {
mOutputView = new OutputStreamView(this);
if (outputView == null) {
outputView = new OutputStreamView(this);
}
return mOutputView;
return outputView;
}
static final class InputStreamView extends SeekableInputStream {
// TODO: Consider adding synchonization (on mStream) for all operations
// TODO: Is is a good thing that close/flush etc works on mStream?
// TODO: Consider adding synchonization (on stream) for all operations
// TODO: Is is a good thing that close/flush etc works on stream?
// - Or should it rather just work on the views?
// - Allow multiple views?
@@ -190,8 +189,8 @@ public abstract class RandomAccessStream implements Seekable, DataInput, DataOut
}
static final class OutputStreamView extends SeekableOutputStream {
// TODO: Consider adding synchonization (on mStream) for all operations
// TODO: Is is a good thing that close/flush etc works on mStream?
// TODO: Consider adding synchonization (on stream) for all operations
// TODO: Is is a good thing that close/flush etc works on stream?
// - Or should it rather just work on the views?
// - Allow multiple views?

View File

@@ -43,15 +43,15 @@ import java.util.Stack;
public abstract class SeekableInputStream extends InputStream implements Seekable {
// TODO: It's at the moment not possible to create subclasses outside this
// package, as there's no access to mPosition. mPosition needs to be
// package, as there's no access to position. position needs to be
// updated from the read/read/read methods...
/** The stream position in this stream */
long mPosition;
long mFlushedPosition;
boolean mClosed;
long position;
long flushedPosition;
boolean closed;
protected Stack<Long> mMarkedPositions = new Stack<Long>();
protected Stack<Long> markedPositions = new Stack<Long>();
/// InputStream overrides
@Override
@@ -70,8 +70,8 @@ public abstract class SeekableInputStream extends InputStream implements Seekabl
*/
@Override
public final long skip(long pLength) throws IOException {
long pos = mPosition;
if (pos + pLength < mFlushedPosition) {
long pos = position;
if (pos + pLength < flushedPosition) {
throw new IOException("position < flushedPosition");
}
@@ -79,7 +79,7 @@ public abstract class SeekableInputStream extends InputStream implements Seekabl
// to seek past end of stream
seek(Math.min(pos + pLength, pos + available()));
return mPosition - pos;
return position - pos;
}
@Override
@@ -88,7 +88,7 @@ public abstract class SeekableInputStream extends InputStream implements Seekabl
// TODO: We don't really need to do this.. Is it a good idea?
try {
flushBefore(Math.max(mPosition - pLimit, mFlushedPosition));
flushBefore(Math.max(position - pLimit, flushedPosition));
}
catch (IOException ignore) {
// Ignore, as it's not really critical
@@ -111,29 +111,29 @@ public abstract class SeekableInputStream extends InputStream implements Seekabl
// NOTE: This is correct according to javax.imageio (IndexOutOfBoundsException),
// but it's kind of inconsistent with reset that throws IOException...
if (pPosition < mFlushedPosition) {
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition");
}
seekImpl(pPosition);
mPosition = pPosition;
position = pPosition;
}
protected abstract void seekImpl(long pPosition) throws IOException;
public final void mark() {
mMarkedPositions.push(mPosition);
markedPositions.push(position);
}
@Override
public final void reset() throws IOException {
checkOpen();
if (!mMarkedPositions.isEmpty()) {
long newPos = mMarkedPositions.pop();
if (!markedPositions.isEmpty()) {
long newPos = markedPositions.pop();
// NOTE: This is correct according to javax.imageio (IOException),
// but it's kind of inconsistent with seek that throws IndexOutOfBoundsException...
if (newPos < mFlushedPosition) {
if (newPos < flushedPosition) {
throw new IOException("Previous marked position has been discarded");
}
@@ -150,7 +150,7 @@ public abstract class SeekableInputStream extends InputStream implements Seekabl
}
public final void flushBefore(long pPosition) throws IOException {
if (pPosition < mFlushedPosition) {
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition");
}
if (pPosition > getStreamPosition()) {
@@ -158,7 +158,7 @@ public abstract class SeekableInputStream extends InputStream implements Seekabl
}
checkOpen();
flushBeforeImpl(pPosition);
mFlushedPosition = pPosition;
flushedPosition = pPosition;
}
/**
@@ -172,21 +172,21 @@ public abstract class SeekableInputStream extends InputStream implements Seekabl
protected abstract void flushBeforeImpl(long pPosition) throws IOException;
public final void flush() throws IOException {
flushBefore(mFlushedPosition);
flushBefore(flushedPosition);
}
public final long getFlushedPosition() throws IOException {
checkOpen();
return mFlushedPosition;
return flushedPosition;
}
public final long getStreamPosition() throws IOException {
checkOpen();
return mPosition;
return position;
}
protected final void checkOpen() throws IOException {
if (mClosed) {
if (closed) {
throw new IOException("closed");
}
}
@@ -194,7 +194,7 @@ public abstract class SeekableInputStream extends InputStream implements Seekabl
@Override
public final void close() throws IOException {
checkOpen();
mClosed = true;
closed = true;
closeImpl();
}
@@ -211,7 +211,7 @@ public abstract class SeekableInputStream extends InputStream implements Seekabl
*/
@Override
protected void finalize() throws Throwable {
if (!mClosed) {
if (!closed) {
try {
close();
}

View File

@@ -43,11 +43,11 @@ import java.util.Stack;
*/
public abstract class SeekableOutputStream extends OutputStream implements Seekable {
// TODO: Implement
long mPosition;
long mFlushedPosition;
boolean mClosed;
long position;
long flushedPosition;
boolean closed;
protected Stack<Long> mMarkedPositions = new Stack<Long>();
protected Stack<Long> markedPositions = new Stack<Long>();
/// Outputstream overrides
@Override
@@ -63,28 +63,28 @@ public abstract class SeekableOutputStream extends OutputStream implements Seeka
// TODO: This is correct according to javax.imageio (IndexOutOfBoundsException),
// but it's inconsistent with reset that throws IOException...
if (pPosition < mFlushedPosition) {
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition!");
}
seekImpl(pPosition);
mPosition = pPosition;
position = pPosition;
}
protected abstract void seekImpl(long pPosition) throws IOException;
public final void mark() {
mMarkedPositions.push(mPosition);
markedPositions.push(position);
}
public final void reset() throws IOException {
checkOpen();
if (!mMarkedPositions.isEmpty()) {
long newPos = mMarkedPositions.pop();
if (!markedPositions.isEmpty()) {
long newPos = markedPositions.pop();
// TODO: This is correct according to javax.imageio (IOException),
// but it's inconsistent with seek that throws IndexOutOfBoundsException...
if (newPos < mFlushedPosition) {
if (newPos < flushedPosition) {
throw new IOException("Previous marked position has been discarded!");
}
@@ -93,7 +93,7 @@ public abstract class SeekableOutputStream extends OutputStream implements Seeka
}
public final void flushBefore(long pPosition) throws IOException {
if (pPosition < mFlushedPosition) {
if (pPosition < flushedPosition) {
throw new IndexOutOfBoundsException("position < flushedPosition!");
}
if (pPosition > getStreamPosition()) {
@@ -101,28 +101,28 @@ public abstract class SeekableOutputStream extends OutputStream implements Seeka
}
checkOpen();
flushBeforeImpl(pPosition);
mFlushedPosition = pPosition;
flushedPosition = pPosition;
}
protected abstract void flushBeforeImpl(long pPosition) throws IOException;
@Override
public final void flush() throws IOException {
flushBefore(mFlushedPosition);
flushBefore(flushedPosition);
}
public final long getFlushedPosition() throws IOException {
checkOpen();
return mFlushedPosition;
return flushedPosition;
}
public final long getStreamPosition() throws IOException {
checkOpen();
return mPosition;
return position;
}
protected final void checkOpen() throws IOException {
if (mClosed) {
if (closed) {
throw new IOException("closed");
}
}
@@ -130,7 +130,7 @@ public abstract class SeekableOutputStream extends OutputStream implements Seeka
@Override
public final void close() throws IOException {
checkOpen();
mClosed = true;
closed = true;
closeImpl();
}

View File

@@ -28,6 +28,8 @@
package com.twelvemonkeys.io;
import com.twelvemonkeys.lang.Validate;
import java.io.StringReader;
import java.io.IOException;
import java.io.Reader;
@@ -42,13 +44,13 @@ import java.io.Reader;
*/
public class StringArrayReader extends StringReader {
private StringReader mCurrent;
private String[] mStrings;
protected final Object mLock;
private int mCurrentSting;
private int mMarkedString;
private int mMark;
private int mNext;
private StringReader current;
private String[] strings;
protected final Object finalLock;
private int currentSting;
private int markedString;
private int mark;
private int next;
/**
* Create a new string array reader.
@@ -57,28 +59,28 @@ public class StringArrayReader extends StringReader {
*/
public StringArrayReader(final String[] pStrings) {
super("");
if (pStrings == null) {
throw new NullPointerException("strings == null");
}
mLock = lock = pStrings; // NOTE: It's ok to sync on pStrings, as the
Validate.notNull(pStrings, "strings");
finalLock = lock = pStrings; // NOTE: It's ok to sync on pStrings, as the
// reference can't change, only it's elements
mStrings = pStrings.clone(); // Defensive copy for content
strings = pStrings.clone(); // Defensive copy for content
nextReader();
}
protected final Reader nextReader() {
if (mCurrentSting >= mStrings.length) {
mCurrent = new EmptyReader();
if (currentSting >= strings.length) {
current = new EmptyReader();
}
else {
mCurrent = new StringReader(mStrings[mCurrentSting++]);
current = new StringReader(strings[currentSting++]);
}
// NOTE: Reset mNext for every reader, and record marked reader in mark/reset methods!
mNext = 0;
// NOTE: Reset next for every reader, and record marked reader in mark/reset methods!
next = 0;
return mCurrent;
return current;
}
/**
@@ -87,15 +89,15 @@ public class StringArrayReader extends StringReader {
* @throws IOException if the stream is closed
*/
protected final void ensureOpen() throws IOException {
if (mStrings == null) {
if (strings == null) {
throw new IOException("Stream closed");
}
}
public void close() {
super.close();
mStrings = null;
mCurrent.close();
strings = null;
current.close();
}
public void mark(int pReadLimit) throws IOException {
@@ -103,29 +105,29 @@ public class StringArrayReader extends StringReader {
throw new IllegalArgumentException("Read limit < 0");
}
synchronized (mLock) {
synchronized (finalLock) {
ensureOpen();
mMark = mNext;
mMarkedString = mCurrentSting;
mark = next;
markedString = currentSting;
mCurrent.mark(pReadLimit);
current.mark(pReadLimit);
}
}
public void reset() throws IOException {
synchronized (mLock) {
synchronized (finalLock) {
ensureOpen();
if (mCurrentSting != mMarkedString) {
mCurrentSting = mMarkedString - 1;
if (currentSting != markedString) {
currentSting = markedString - 1;
nextReader();
mCurrent.skip(mMark);
current.skip(mark);
}
else {
mCurrent.reset();
current.reset();
}
mNext = mMark;
next = mark;
}
}
@@ -134,49 +136,49 @@ public class StringArrayReader extends StringReader {
}
public int read() throws IOException {
synchronized (mLock) {
int read = mCurrent.read();
synchronized (finalLock) {
int read = current.read();
if (read < 0 && mCurrentSting < mStrings.length) {
if (read < 0 && currentSting < strings.length) {
nextReader();
return read(); // In case of empty strings
}
mNext++;
next++;
return read;
}
}
public int read(char pBuffer[], int pOffset, int pLength) throws IOException {
synchronized (mLock) {
int read = mCurrent.read(pBuffer, pOffset, pLength);
synchronized (finalLock) {
int read = current.read(pBuffer, pOffset, pLength);
if (read < 0 && mCurrentSting < mStrings.length) {
if (read < 0 && currentSting < strings.length) {
nextReader();
return read(pBuffer, pOffset, pLength); // In case of empty strings
}
mNext += read;
next += read;
return read;
}
}
public boolean ready() throws IOException {
return mCurrent.ready();
return current.ready();
}
public long skip(long pChars) throws IOException {
synchronized (mLock) {
long skipped = mCurrent.skip(pChars);
synchronized (finalLock) {
long skipped = current.skip(pChars);
if (skipped == 0 && mCurrentSting < mStrings.length) {
if (skipped == 0 && currentSting < strings.length) {
nextReader();
return skip(pChars);
}
mNext += skipped;
next += skipped;
return skipped;
}

View File

@@ -43,8 +43,8 @@ import java.io.InputStream;
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/SubStream.java#2 $
*/
public final class SubStream extends FilterInputStream {
private long mLeft;
private int mMarkLimit;
private long bytesLeft;
private int markLimit;
/**
* Creates a {@code SubStream} of the given {@code pStream}.
@@ -54,7 +54,7 @@ public final class SubStream extends FilterInputStream {
*/
public SubStream(final InputStream pStream, final long pLength) {
super(Validate.notNull(pStream, "stream"));
mLeft = pLength;
bytesLeft = pLength;
}
/**
@@ -64,32 +64,32 @@ public final class SubStream extends FilterInputStream {
@Override
public void close() throws IOException {
// NOTE: Do not close the underlying stream
while (mLeft > 0) {
while (bytesLeft > 0) {
//noinspection ResultOfMethodCallIgnored
skip(mLeft);
skip(bytesLeft);
}
}
@Override
public int available() throws IOException {
return (int) Math.min(super.available(), mLeft);
return (int) Math.min(super.available(), bytesLeft);
}
@Override
public void mark(int pReadLimit) {
super.mark(pReadLimit);// This either succeeds or does nothing...
mMarkLimit = pReadLimit;
markLimit = pReadLimit;
}
@Override
public void reset() throws IOException {
super.reset();// This either succeeds or throws IOException
mLeft += mMarkLimit;
bytesLeft += markLimit;
}
@Override
public int read() throws IOException {
if (mLeft-- <= 0) {
if (bytesLeft-- <= 0) {
return -1;
}
return super.read();
@@ -102,12 +102,12 @@ public final class SubStream extends FilterInputStream {
@Override
public int read(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
if (mLeft <= 0) {
if (bytesLeft <= 0) {
return -1;
}
int read = super.read(pBytes, pOffset, (int) findMaxLen(pLength));
mLeft = read < 0 ? 0 : mLeft - read;
bytesLeft = read < 0 ? 0 : bytesLeft - read;
return read;
}
@@ -118,8 +118,8 @@ public final class SubStream extends FilterInputStream {
* @return the maximum number of bytes to read
*/
private long findMaxLen(long pLength) {
if (mLeft < pLength) {
return (int) Math.max(mLeft, 0);
if (bytesLeft < pLength) {
return (int) Math.max(bytesLeft, 0);
}
else {
return pLength;
@@ -129,7 +129,7 @@ public final class SubStream extends FilterInputStream {
@Override
public long skip(long pLength) throws IOException {
long skipped = super.skip(findMaxLen(pLength));// Skips 0 or more, never -1
mLeft -= skipped;
bytesLeft -= skipped;
return skipped;
}
}

View File

@@ -50,7 +50,8 @@ final class Win32Lnk extends File {
(byte) 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 'F'
};
private final File mTarget;
private final File target;
private static final int FLAG_ITEM_ID_LIST = 0x01;
private static final int FLAG_FILE_LOC_INFO = 0x02;
private static final int FLAG_DESC_STRING = 0x04;
@@ -65,10 +66,10 @@ final class Win32Lnk extends File {
File target = parse(this);
if (target == this) {
// NOTE: This is a workaround
// mTarget = this causes infinite loops in some methods
// target = this causes infinite loops in some methods
target = new File(pPath);
}
mTarget = target;
this.target = target;
}
Win32Lnk(final File pPath) throws IOException {
@@ -336,24 +337,24 @@ final class Win32Lnk extends File {
*/
public File getTarget() {
return mTarget;
return target;
}
// java.io.File overrides below
@Override
public boolean isDirectory() {
return mTarget.isDirectory();
return target.isDirectory();
}
@Override
public boolean canRead() {
return mTarget.canRead();
return target.canRead();
}
@Override
public boolean canWrite() {
return mTarget.canWrite();
return target.canWrite();
}
// NOTE: equals is implemented using compareto == 0
@@ -362,7 +363,7 @@ final class Win32Lnk extends File {
// TODO: Verify this
// Probably not a good idea, as it IS NOT THE SAME file
// It's probably better to not override
return mTarget.compareTo(pathname);
return target.compareTo(pathname);
}
*/
@@ -375,7 +376,7 @@ final class Win32Lnk extends File {
@Override
public boolean exists() {
return mTarget.exists();
return target.exists();
}
// A .lnk may be absolute
@@ -385,12 +386,12 @@ final class Win32Lnk extends File {
// Theses should be resolved according to the API (for Unix).
@Override
public File getCanonicalFile() throws IOException {
return mTarget.getCanonicalFile();
return target.getCanonicalFile();
}
@Override
public String getCanonicalPath() throws IOException {
return mTarget.getCanonicalPath();
return target.getCanonicalPath();
}
//public String getName() {
@@ -402,47 +403,47 @@ final class Win32Lnk extends File {
// public boolean isAbsolute() {
@Override
public boolean isFile() {
return mTarget.isFile();
return target.isFile();
}
@Override
public boolean isHidden() {
return mTarget.isHidden();
return target.isHidden();
}
@Override
public long lastModified() {
return mTarget.lastModified();
return target.lastModified();
}
@Override
public long length() {
return mTarget.length();
return target.length();
}
@Override
public String[] list() {
return mTarget.list();
return target.list();
}
@Override
public String[] list(final FilenameFilter filter) {
return mTarget.list(filter);
return target.list(filter);
}
@Override
public File[] listFiles() {
return Win32File.wrap(mTarget.listFiles());
return Win32File.wrap(target.listFiles());
}
@Override
public File[] listFiles(final FileFilter filter) {
return Win32File.wrap(mTarget.listFiles(filter));
return Win32File.wrap(target.listFiles(filter));
}
@Override
public File[] listFiles(final FilenameFilter filter) {
return Win32File.wrap(mTarget.listFiles(filter));
return Win32File.wrap(target.listFiles(filter));
}
// Makes no sense, does it?
@@ -454,19 +455,19 @@ final class Win32Lnk extends File {
@Override
public boolean setLastModified(long time) {
return mTarget.setLastModified(time);
return target.setLastModified(time);
}
@Override
public boolean setReadOnly() {
return mTarget.setReadOnly();
return target.setReadOnly();
}
@Override
public String toString() {
if (mTarget.equals(this)) {
if (target.equals(this)) {
return super.toString();
}
return super.toString() + " -> " + mTarget.toString();
return super.toString() + " -> " + target.toString();
}
}

View File

@@ -51,10 +51,11 @@ import java.nio.CharBuffer;
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/WriterOutputStream.java#2 $
*/
public class WriterOutputStream extends OutputStream {
protected Writer mWriter;
final protected Decoder mDecoder;
final ByteArrayOutputStream mBufferStream = new FastByteArrayOutputStream(1024);
private volatile boolean mIsFlushing = false; // Ugly but critical...
protected Writer writer;
final protected Decoder decoder;
final ByteArrayOutputStream bufferStream = new FastByteArrayOutputStream(1024);
private volatile boolean isFlushing = false; // Ugly but critical...
private static final boolean NIO_AVAILABLE = isNIOAvailable();
@@ -71,8 +72,8 @@ public class WriterOutputStream extends OutputStream {
}
public WriterOutputStream(final Writer pWriter, final String pCharset) {
mWriter = pWriter;
mDecoder = getDecoder(pCharset);
writer = pWriter;
decoder = getDecoder(pCharset);
}
public WriterOutputStream(final Writer pWriter) {
@@ -94,14 +95,14 @@ public class WriterOutputStream extends OutputStream {
@Override
public void close() throws IOException {
flush();
mWriter.close();
mWriter = null;
writer.close();
writer = null;
}
@Override
public void flush() throws IOException {
flushBuffer();
mWriter.flush();
writer.flush();
}
@Override
@@ -115,22 +116,22 @@ public class WriterOutputStream extends OutputStream {
@Override
public final void write(byte[] pBytes, int pOffset, int pLength) throws IOException {
flushBuffer();
mDecoder.decodeTo(mWriter, pBytes, pOffset, pLength);
decoder.decodeTo(writer, pBytes, pOffset, pLength);
}
@Override
public final void write(int pByte) {
// TODO: Is it possible to know if this is a good place in the stream to
// flush? It might be in the middle of a multi-byte encoded character..
mBufferStream.write(pByte);
bufferStream.write(pByte);
}
private void flushBuffer() throws IOException {
if (!mIsFlushing && mBufferStream.size() > 0) {
mIsFlushing = true;
mBufferStream.writeTo(this); // NOTE: Avoids cloning buffer array
mBufferStream.reset();
mIsFlushing = false;
if (!isFlushing && bufferStream.size() > 0) {
isFlushing = true;
bufferStream.writeTo(this); // NOTE: Avoids cloning buffer array
bufferStream.reset();
isFlushing = false;
}
}
@@ -138,7 +139,7 @@ public class WriterOutputStream extends OutputStream {
public static void main(String[] pArgs) throws IOException {
int iterations = 1000000;
byte[] bytes = "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> klashf lkash ljah lhaaklhghdfgu ksd".getBytes("UTF-8");
byte[] bytes = "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> klashf lkash ljah lhaaklhghdfgu ksd".getBytes("UTF-8");
Decoder d;
long start;

View File

@@ -41,12 +41,12 @@ import java.io.InputStream;
*/
// TODO: Move to other package or make public
abstract class AbstractRLEDecoder implements Decoder {
protected final byte[] mRow;
protected final int mWidth;
protected int mSrcX;
protected int mSrcY;
protected int mDstX;
protected int mDstY;
protected final byte[] row;
protected final int width;
protected int srcX;
protected int srcY;
protected int dstX;
protected int dstY;
/**
* Creates an RLEDecoder. As RLE encoded BMP's may contain x and y deltas,
@@ -56,21 +56,21 @@ abstract class AbstractRLEDecoder implements Decoder {
* @param pHeight heigth of the image
*/
AbstractRLEDecoder(int pWidth, int pHeight) {
mWidth = pWidth;
int bytesPerRow = mWidth;
width = pWidth;
int bytesPerRow = width;
int mod = bytesPerRow % 4;
if (mod != 0) {
bytesPerRow += 4 - mod;
}
mRow = new byte[bytesPerRow];
row = new byte[bytesPerRow];
mSrcX = 0;
mSrcY = pHeight - 1;
srcX = 0;
srcY = pHeight - 1;
mDstX = mSrcX;
mDstY = mSrcY;
dstX = srcX;
dstY = srcY;
}
/**
@@ -95,26 +95,26 @@ abstract class AbstractRLEDecoder implements Decoder {
public final int decode(InputStream pStream, byte[] pBuffer) throws IOException {
int decoded = 0;
while (decoded < pBuffer.length && mDstY >= 0) {
while (decoded < pBuffer.length && dstY >= 0) {
// NOTE: Decode only full rows, don't decode if y delta
if (mDstX == 0 && mSrcY == mDstY) {
if (dstX == 0 && srcY == dstY) {
decodeRow(pStream);
}
int length = Math.min(mRow.length - mDstX, pBuffer.length - decoded);
System.arraycopy(mRow, mDstX, pBuffer, decoded, length);
mDstX += length;
int length = Math.min(row.length - dstX, pBuffer.length - decoded);
System.arraycopy(row, dstX, pBuffer, decoded, length);
dstX += length;
decoded += length;
if (mDstX == mRow.length) {
mDstX = 0;
mDstY--;
if (dstX == row.length) {
dstX = 0;
dstY--;
// NOTE: If src Y is < dst Y, we have a delta, and have to fill the
// gap with zero-bytes
if (mDstY > mSrcY) {
for (int i = 0; i < mRow.length; i++) {
mRow[i] = 0x00;
if (dstY > srcY) {
for (int i = 0; i < row.length; i++) {
row[i] = 0x00;
}
}
}

View File

@@ -61,9 +61,9 @@ public final class Base64Decoder implements Decoder {
final static byte[] PEM_CONVERT_ARRAY;
private byte[] mDecodeBuffer = new byte[4];
private ByteArrayOutputStream mWrapped;
private Object mWrappedObject;
private byte[] decodeBuffer = new byte[4];
private ByteArrayOutputStream wrapped;
private Object wrappedObject;
static {
PEM_CONVERT_ARRAY = new byte[256];
@@ -116,8 +116,8 @@ public final class Base64Decoder implements Decoder {
}
} while (read == 10 || read == 13);
mDecodeBuffer[0] = (byte) read;
read = readFully(pInput, mDecodeBuffer, 1, pLength - 1);
decodeBuffer[0] = (byte) read;
read = readFully(pInput, decodeBuffer, 1, pLength - 1);
if (read == -1) {
return false;
@@ -125,24 +125,24 @@ public final class Base64Decoder implements Decoder {
int length = pLength;
if (length > 3 && mDecodeBuffer[3] == 61) {
if (length > 3 && decodeBuffer[3] == 61) {
length = 3;
}
if (length > 2 && mDecodeBuffer[2] == 61) {
if (length > 2 && decodeBuffer[2] == 61) {
length = 2;
}
switch (length) {
case 4:
byte3 = PEM_CONVERT_ARRAY[mDecodeBuffer[3] & 255];
byte3 = PEM_CONVERT_ARRAY[decodeBuffer[3] & 255];
// fall through
case 3:
byte2 = PEM_CONVERT_ARRAY[mDecodeBuffer[2] & 255];
byte2 = PEM_CONVERT_ARRAY[decodeBuffer[2] & 255];
// fall through
case 2:
byte1 = PEM_CONVERT_ARRAY[mDecodeBuffer[1] & 255];
byte0 = PEM_CONVERT_ARRAY[mDecodeBuffer[0] & 255];
byte1 = PEM_CONVERT_ARRAY[decodeBuffer[1] & 255];
byte0 = PEM_CONVERT_ARRAY[decodeBuffer[0] & 255];
// fall through
default:
switch (length) {
@@ -185,15 +185,15 @@ public final class Base64Decoder implements Decoder {
}
public int decode(final InputStream pStream, final byte[] pBuffer) throws IOException {
if (mWrappedObject != pBuffer) {
if (wrappedObject != pBuffer) {
// NOTE: Array not cloned in FastByteArrayOutputStream
mWrapped = new FastByteArrayOutputStream(pBuffer);
mWrappedObject = pBuffer;
wrapped = new FastByteArrayOutputStream(pBuffer);
wrappedObject = pBuffer;
}
mWrapped.reset(); // NOTE: This only resets count to 0
decodeBuffer(pStream, mWrapped, pBuffer.length);
wrapped.reset(); // NOTE: This only resets count to 0
decodeBuffer(pStream, wrapped, pBuffer.length);
return mWrapped.size();
return wrapped.size();
}
}

View File

@@ -44,10 +44,10 @@ import java.io.FilterInputStream;
*/
public final class DecoderStream extends FilterInputStream {
protected int mBufferPos;
protected int mBufferLimit;
protected final byte[] mBuffer;
protected final Decoder mDecoder;
protected int bufferPos;
protected int bufferLimit;
protected final byte[] buffer;
protected final Decoder decoder;
/**
* Creates a new decoder stream and chains it to the
@@ -76,26 +76,26 @@ public final class DecoderStream extends FilterInputStream {
*/
public DecoderStream(final InputStream pStream, final Decoder pDecoder, final int pBufferSize) {
super(pStream);
mDecoder = pDecoder;
mBuffer = new byte[pBufferSize];
mBufferPos = 0;
mBufferLimit = 0;
decoder = pDecoder;
buffer = new byte[pBufferSize];
bufferPos = 0;
bufferLimit = 0;
}
public int available() throws IOException {
return mBufferLimit - mBufferPos + super.available();
return bufferLimit - bufferPos + super.available();
}
public int read() throws IOException {
if (mBufferPos == mBufferLimit) {
mBufferLimit = fill();
if (bufferPos == bufferLimit) {
bufferLimit = fill();
}
if (mBufferLimit < 0) {
if (bufferLimit < 0) {
return -1;
}
return mBuffer[mBufferPos++] & 0xff;
return buffer[bufferPos++] & 0xff;
}
public int read(final byte pBytes[]) throws IOException {
@@ -115,7 +115,7 @@ public final class DecoderStream extends FilterInputStream {
}
// End of file?
if ((mBufferLimit - mBufferPos) < 0) {
if ((bufferLimit - bufferPos) < 0) {
return -1;
}
@@ -124,21 +124,21 @@ public final class DecoderStream extends FilterInputStream {
int off = pOffset;
while (pLength > count) {
int avail = mBufferLimit - mBufferPos;
int avail = bufferLimit - bufferPos;
if (avail <= 0) {
mBufferLimit = fill();
bufferLimit = fill();
if (mBufferLimit < 0) {
if (bufferLimit < 0) {
break;
}
}
// Copy as many bytes as possible
int dstLen = Math.min(pLength - count, avail);
System.arraycopy(mBuffer, mBufferPos, pBytes, off, dstLen);
System.arraycopy(buffer, bufferPos, pBytes, off, dstLen);
mBufferPos += dstLen;
bufferPos += dstLen;
// Update offset (rest)
off += dstLen;
@@ -152,7 +152,7 @@ public final class DecoderStream extends FilterInputStream {
public long skip(final long pLength) throws IOException {
// End of file?
if (mBufferLimit - mBufferPos < 0) {
if (bufferLimit - bufferPos < 0) {
return 0;
}
@@ -160,12 +160,12 @@ public final class DecoderStream extends FilterInputStream {
long total = 0;
while (total < pLength) {
int avail = mBufferLimit - mBufferPos;
int avail = bufferLimit - bufferPos;
if (avail == 0) {
mBufferLimit = fill();
bufferLimit = fill();
if (mBufferLimit < 0) {
if (bufferLimit < 0) {
break;
}
}
@@ -174,7 +174,7 @@ public final class DecoderStream extends FilterInputStream {
// an int, so the cast is safe
int skipped = (int) Math.min(pLength - total, avail);
mBufferPos += skipped; // Just skip these bytes
bufferPos += skipped; // Just skip these bytes
total += skipped;
}
@@ -190,19 +190,19 @@ public final class DecoderStream extends FilterInputStream {
* @throws IOException if an I/O error occurs
*/
protected int fill() throws IOException {
int read = mDecoder.decode(in, mBuffer);
int read = decoder.decode(in, buffer);
// TODO: Enforce this in test case, leave here to aid debugging
if (read > mBuffer.length) {
if (read > buffer.length) {
throw new AssertionError(
String.format(
"Decode beyond buffer (%d): %d (using %s decoder)",
mBuffer.length, read, mDecoder.getClass().getName()
buffer.length, read, decoder.getClass().getName()
)
);
}
mBufferPos = 0;
bufferPos = 0;
if (read == 0) {
return -1;

View File

@@ -57,8 +57,7 @@ public interface Encoder {
*
* @throws java.io.IOException if an I/O error occurs
*/
void encode(OutputStream pStream, byte[] pBuffer, int pOffset, int pLength)
throws IOException;
void encode(OutputStream pStream, byte[] pBuffer, int pOffset, int pLength) throws IOException;
//TODO: int requiredBufferSize(): -1 == any, otherwise, use this buffer size
// void flush()?

View File

@@ -44,11 +44,11 @@ import java.io.IOException;
*/
public final class EncoderStream extends FilterOutputStream {
protected final Encoder mEncoder;
private final boolean mFlushOnWrite;
protected final Encoder encoder;
private final boolean flushOnWrite;
protected int mBufferPos;
protected final byte[] mBuffer;
protected int bufferPos;
protected final byte[] buffer;
/**
* Creates an output stream filter built on top of the specified
@@ -73,11 +73,11 @@ public final class EncoderStream extends FilterOutputStream {
public EncoderStream(final OutputStream pStream, final Encoder pEncoder, final boolean pFlushOnWrite) {
super(pStream);
mEncoder = pEncoder;
mFlushOnWrite = pFlushOnWrite;
encoder = pEncoder;
flushOnWrite = pFlushOnWrite;
mBuffer = new byte[1024];
mBufferPos = 0;
buffer = new byte[1024];
bufferPos = 0;
}
public void close() throws IOException {
@@ -91,12 +91,12 @@ public final class EncoderStream extends FilterOutputStream {
}
private void encodeBuffer() throws IOException {
if (mBufferPos != 0) {
if (bufferPos != 0) {
// Make sure all remaining data in buffer is written to the stream
mEncoder.encode(out, mBuffer, 0, mBufferPos);
encoder.encode(out, buffer, 0, bufferPos);
// Reset buffer
mBufferPos = 0;
bufferPos = 0;
}
}
@@ -109,27 +109,27 @@ public final class EncoderStream extends FilterOutputStream {
// that the encoder can't buffer. In that case, the encoder should probably
// tell the EncoderStream how large buffer it prefers...
public void write(final byte[] pBytes, final int pOffset, final int pLength) throws IOException {
if (!mFlushOnWrite && mBufferPos + pLength < mBuffer.length) {
if (!flushOnWrite && bufferPos + pLength < buffer.length) {
// Buffer data
System.arraycopy(pBytes, pOffset, mBuffer, mBufferPos, pLength);
mBufferPos += pLength;
System.arraycopy(pBytes, pOffset, buffer, bufferPos, pLength);
bufferPos += pLength;
}
else {
// Encode data already in the buffer
if (mBufferPos != 0) {
if (bufferPos != 0) {
encodeBuffer();
}
// Encode rest without buffering
mEncoder.encode(out, pBytes, pOffset, pLength);
encoder.encode(out, pBytes, pOffset, pLength);
}
}
public void write(final int pByte) throws IOException {
if (mBufferPos >= mBuffer.length - 1) {
encodeBuffer(); // Resets mBufferPos to 0
if (bufferPos >= buffer.length - 1) {
encodeBuffer(); // Resets bufferPos to 0
}
mBuffer[mBufferPos++] = (byte) pByte;
buffer[bufferPos++] = (byte) pByte;
}
}

View File

@@ -46,11 +46,11 @@ import java.io.EOFException;
*/
public final class PackBits16Decoder implements Decoder {
// TODO: Refactor this into an option for the PackBitsDecoder?
private final boolean mDisableNoop;
private final boolean disableNoop;
private int mLeftOfRun;
private boolean mSplitRun;
private boolean mEOF;
private int leftOfRun;
private boolean splitRun;
private boolean reachedEOF;
/**
* Creates a {@code PackBitsDecoder}.
@@ -71,7 +71,7 @@ public final class PackBits16Decoder implements Decoder {
* @param pDisableNoop {@code true} if {@code -128} should be treated as a compressed run, and not a no-op
*/
public PackBits16Decoder(final boolean pDisableNoop) {
mDisableNoop = pDisableNoop;
disableNoop = pDisableNoop;
}
/**
@@ -85,7 +85,7 @@ public final class PackBits16Decoder implements Decoder {
* @throws java.io.IOException
*/
public int decode(final InputStream pStream, final byte[] pBuffer) throws IOException {
if (mEOF) {
if (reachedEOF) {
return -1;
}
@@ -95,16 +95,16 @@ public final class PackBits16Decoder implements Decoder {
while (read < max) {
int n;
if (mSplitRun) {
if (splitRun) {
// Continue run
n = mLeftOfRun;
mSplitRun = false;
n = leftOfRun;
splitRun = false;
}
else {
// Start new run
int b = pStream.read();
if (b < 0) {
mEOF = true;
reachedEOF = true;
break;
}
n = (byte) b;
@@ -112,13 +112,13 @@ public final class PackBits16Decoder implements Decoder {
// Split run at or before max
if (n >= 0 && 2 * (n + 1) + read > max) {
mLeftOfRun = n;
mSplitRun = true;
leftOfRun = n;
splitRun = true;
break;
}
else if (n < 0 && 2 * (-n + 1) + read > max) {
mLeftOfRun = n;
mSplitRun = true;
leftOfRun = n;
splitRun = true;
break;
}
@@ -130,7 +130,7 @@ public final class PackBits16Decoder implements Decoder {
read += len;
}
// Allow -128 for compatibility, see above
else if (mDisableNoop || n != -128) {
else if (disableNoop || n != -128) {
// Replicate the next short -n + 1 times
byte value1 = readByte(pStream);
byte value2 = readByte(pStream);

View File

@@ -63,11 +63,11 @@ import java.io.EOFException;
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/io/enc/PackBitsDecoder.java#1 $
*/
public final class PackBitsDecoder implements Decoder {
private final boolean mDisableNoop;
private final boolean disableNoop;
private int mLeftOfRun;
private boolean mSplitRun;
private boolean mEOF;
private int leftOfRun;
private boolean splitRun;
private boolean reachedEOF;
/** Creates a {@code PackBitsDecoder}. */
public PackBitsDecoder() {
@@ -86,7 +86,7 @@ public final class PackBitsDecoder implements Decoder {
* @param pDisableNoop {@code true} if {@code -128} should be treated as a compressed run, and not a no-op
*/
public PackBitsDecoder(final boolean pDisableNoop) {
mDisableNoop = pDisableNoop;
disableNoop = pDisableNoop;
}
/**
@@ -100,7 +100,7 @@ public final class PackBitsDecoder implements Decoder {
* @throws IOException
*/
public int decode(final InputStream pStream, final byte[] pBuffer) throws IOException {
if (mEOF) {
if (reachedEOF) {
return -1;
}
@@ -111,16 +111,16 @@ public final class PackBitsDecoder implements Decoder {
while (read < max) {
int n;
if (mSplitRun) {
if (splitRun) {
// Continue run
n = mLeftOfRun;
mSplitRun = false;
n = leftOfRun;
splitRun = false;
}
else {
// Start new run
int b = pStream.read();
if (b < 0) {
mEOF = true;
reachedEOF = true;
break;
}
n = (byte) b;
@@ -128,13 +128,13 @@ public final class PackBitsDecoder implements Decoder {
// Split run at or before max
if (n >= 0 && n + 1 + read > max) {
mLeftOfRun = n;
mSplitRun = true;
leftOfRun = n;
splitRun = true;
break;
}
else if (n < 0 && -n + 1 + read > max) {
mLeftOfRun = n;
mSplitRun = true;
leftOfRun = n;
splitRun = true;
break;
}
@@ -146,7 +146,7 @@ public final class PackBitsDecoder implements Decoder {
read += n + 1;
}
// Allow -128 for compatibility, see above
else if (mDisableNoop || n != -128) {
else if (disableNoop || n != -128) {
// Replicate the next byte -n + 1 times
byte value = readByte(pStream);

View File

@@ -63,7 +63,7 @@ import java.io.IOException;
*/
public final class PackBitsEncoder implements Encoder {
final private byte[] mBuffer = new byte[128];
final private byte[] buffer = new byte[128];
/**
* Creates a {@code PackBitsEncoder}.
@@ -101,17 +101,17 @@ public final class PackBitsEncoder implements Encoder {
run = 0;
while ((run < 128 && ((offset < max && pBuffer[offset] != pBuffer[offset + 1])
|| (offset < maxMinus1 && pBuffer[offset] != pBuffer[offset + 2])))) {
mBuffer[run++] = pBuffer[offset++];
buffer[run++] = pBuffer[offset++];
}
// If last byte, include it in literal run, if space
if (offset == max && run > 0 && run < 128) {
mBuffer[run++] = pBuffer[offset++];
buffer[run++] = pBuffer[offset++];
}
if (run > 0) {
pStream.write(run - 1);
pStream.write(mBuffer, 0, run);
pStream.write(buffer, 0, run);
}
// If last byte, and not space, start new literal run

View File

@@ -49,7 +49,7 @@ final class RLE4Decoder extends AbstractRLEDecoder {
int deltaX = 0;
int deltaY = 0;
while (mSrcY >= 0) {
while (srcY >= 0) {
int byte1 = pInput.read();
int byte2 = checkEOF(pInput.read());
@@ -58,20 +58,20 @@ final class RLE4Decoder extends AbstractRLEDecoder {
case 0x00:
// End of line
// NOTE: Some BMPs have double EOLs..
if (mSrcX != 0) {
mSrcX = mRow.length;
if (srcX != 0) {
srcX = row.length;
}
break;
case 0x01:
// End of bitmap
mSrcX = mRow.length;
mSrcY = 0;
srcX = row.length;
srcY = 0;
break;
case 0x02:
// Delta
deltaX = mSrcX + pInput.read();
deltaY = mSrcY - checkEOF(pInput.read());
mSrcX = mRow.length;
deltaX = srcX + pInput.read();
deltaY = srcY - checkEOF(pInput.read());
srcX = row.length;
break;
default:
// Absolute mode
@@ -82,13 +82,13 @@ final class RLE4Decoder extends AbstractRLEDecoder {
boolean paddingByte = (((byte2 + 1) / 2) % 2) != 0;
while (byte2 > 1) {
int packed = checkEOF(pInput.read());
mRow[mSrcX++] = (byte) packed;
row[srcX++] = (byte) packed;
byte2 -= 2;
}
if (byte2 == 1) {
// TODO: Half byte alignment? Seems to be ok...
int packed = checkEOF(pInput.read());
mRow[mSrcX++] = (byte) (packed & 0xf0);
row[srcX++] = (byte) (packed & 0xf0);
}
if (paddingByte) {
checkEOF(pInput.read());
@@ -100,24 +100,24 @@ final class RLE4Decoder extends AbstractRLEDecoder {
// Encoded mode
// Replicate the two samples in byte2 as many times as byte1 says
while (byte1 > 1) {
mRow[mSrcX++] = (byte) byte2;
row[srcX++] = (byte) byte2;
byte1 -= 2;
}
if (byte1 == 1) {
// TODO: Half byte alignment? Seems to be ok...
mRow[mSrcX++] = (byte) (byte2 & 0xf0);
row[srcX++] = (byte) (byte2 & 0xf0);
}
}
// If we're done with a complete row, copy the data
if (mSrcX == mRow.length) {
if (srcX == row.length) {
// Move to new position, either absolute (delta) or next line
if (deltaX != 0 || deltaY != 0) {
mSrcX = (deltaX + 1) / 2;
srcX = (deltaX + 1) / 2;
if (deltaY > mSrcY) {
mSrcY = deltaY;
if (deltaY > srcY) {
srcY = deltaY;
break;
}
@@ -125,8 +125,8 @@ final class RLE4Decoder extends AbstractRLEDecoder {
deltaY = 0;
}
else {
mSrcX = 0;
mSrcY--;
srcX = 0;
srcY--;
break;
}
}

View File

@@ -49,7 +49,7 @@ final class RLE8Decoder extends AbstractRLEDecoder {
int deltaX = 0;
int deltaY = 0;
while (mSrcY >= 0) {
while (srcY >= 0) {
int byte1 = pInput.read();
int byte2 = checkEOF(pInput.read());
@@ -58,27 +58,27 @@ final class RLE8Decoder extends AbstractRLEDecoder {
case 0x00:
// End of line
// NOTE: Some BMPs have double EOLs..
if (mSrcX != 0) {
mSrcX = mRow.length;
if (srcX != 0) {
srcX = row.length;
}
break;
case 0x01:
// End of bitmap
mSrcX = mRow.length;
mSrcY = 0;
srcX = row.length;
srcY = 0;
break;
case 0x02:
// Delta
deltaX = mSrcX + pInput.read();
deltaY = mSrcY - checkEOF(pInput.read());
mSrcX = mRow.length;
deltaX = srcX + pInput.read();
deltaY = srcY - checkEOF(pInput.read());
srcX = row.length;
break;
default:
// Absolute mode
// Copy the next byte2 (3..255) bytes from file to output
boolean paddingByte = (byte2 % 2) != 0;
while (byte2-- > 0) {
mRow[mSrcX++] = (byte) checkEOF(pInput.read());
row[srcX++] = (byte) checkEOF(pInput.read());
}
if (paddingByte) {
checkEOF(pInput.read());
@@ -90,26 +90,26 @@ final class RLE8Decoder extends AbstractRLEDecoder {
// Replicate byte2 as many times as byte1 says
byte value = (byte) byte2;
while (byte1-- > 0) {
mRow[mSrcX++] = value;
row[srcX++] = value;
}
}
// If we're done with a complete row, copy the data
if (mSrcX == mRow.length) {
if (srcX == row.length) {
// Move to new position, either absolute (delta) or next line
if (deltaX != 0 || deltaY != 0) {
mSrcX = deltaX;
if (deltaY != mSrcY) {
mSrcY = deltaY;
srcX = deltaX;
if (deltaY != srcY) {
srcY = deltaY;
break;
}
deltaX = 0;
deltaY = 0;
}
else {
mSrcX = 0;
mSrcY--;
srcX = 0;
srcY--;
break;
}
}

View File

@@ -60,28 +60,28 @@ public final class CompoundDocument {
};
public static final int HEADER_SIZE = 512;
private final DataInput mInput;
private final DataInput input;
private UUID mUID;
private UUID uUID;
private int mSectorSize;
private int mShortSectorSize;
private int sectorSize;
private int shortSectorSize;
private int mDirectorySId;
private int directorySId;
private int mMinStreamSize;
private int minStreamSize;
private int mShortSATSID;
private int mShortSATSize;
private int shortSATSId;
private int shortSATSize;
// Master Sector Allocation Table
private int[] mMasterSAT;
private int[] mSAT;
private int[] mShortSAT;
private int[] masterSAT;
private int[] SAT;
private int[] shortSAT;
private Entry mRootEntry;
private SIdChain mShortStreamSIdChain;
private SIdChain mDirectorySIdChain;
private Entry rootEntry;
private SIdChain shortStreamSIdChain;
private SIdChain directorySIdChain;
private static final int END_OF_CHAIN_SID = -2;
private static final int FREE_SID = -1;
@@ -97,7 +97,7 @@ public final class CompoundDocument {
* @throws IOException if an I/O exception occurs while reading the header
*/
public CompoundDocument(final File pFile) throws IOException {
mInput = new LittleEndianRandomAccessFile(FileUtil.resolve(pFile), "r");
input = new LittleEndianRandomAccessFile(FileUtil.resolve(pFile), "r");
// TODO: Might be better to read header on first read operation?!
// OTOH: It's also good to be fail-fast, so at least we should make
@@ -118,7 +118,7 @@ public final class CompoundDocument {
// For testing only, consider exposing later
CompoundDocument(final SeekableInputStream pInput) throws IOException {
mInput = new SeekableLittleEndianDataInputStream(pInput);
input = new SeekableLittleEndianDataInputStream(pInput);
// TODO: Might be better to read header on first read operation?!
// OTOH: It's also good to be fail-fast, so at least we should make
@@ -134,7 +134,7 @@ public final class CompoundDocument {
* @throws IOException if an I/O exception occurs while reading the header
*/
public CompoundDocument(final ImageInputStream pInput) throws IOException {
mInput = pInput;
input = pInput;
// TODO: Might be better to read header on first read operation?!
// OTOH: It's also good to be fail-fast, so at least we should make
@@ -210,74 +210,76 @@ public final class CompoundDocument {
}
private void readHeader() throws IOException {
if (mMasterSAT != null) {
if (masterSAT != null) {
return;
}
if (!canRead(mInput, false)) {
if (!canRead(input, false)) {
throw new CorruptDocumentException("Not an OLE 2 Compound Document");
}
// UID (seems to be all 0s)
mUID = new UUID(mInput.readLong(), mInput.readLong());
uUID = new UUID(input.readLong(), input.readLong());
/*int version = */mInput.readUnsignedShort();
/*int version = */
input.readUnsignedShort();
//System.out.println("version: " + version);
/*int revision = */mInput.readUnsignedShort();
/*int revision = */
input.readUnsignedShort();
//System.out.println("revision: " + revision);
int byteOrder = mInput.readUnsignedShort();
int byteOrder = input.readUnsignedShort();
if (byteOrder != 0xfffe) {
// Reversed, as I'm allready reading little-endian
throw new CorruptDocumentException("Cannot read big endian OLE 2 Compound Documents");
}
mSectorSize = 1 << mInput.readUnsignedShort();
//System.out.println("sectorSize: " + mSectorSize + " bytes");
mShortSectorSize = 1 << mInput.readUnsignedShort();
//System.out.println("shortSectorSize: " + mShortSectorSize + " bytes");
sectorSize = 1 << input.readUnsignedShort();
//System.out.println("sectorSize: " + sectorSize + " bytes");
shortSectorSize = 1 << input.readUnsignedShort();
//System.out.println("shortSectorSize: " + shortSectorSize + " bytes");
// Reserved
if (mInput.skipBytes(10) != 10) {
if (input.skipBytes(10) != 10) {
throw new CorruptDocumentException();
}
int SATSize = mInput.readInt();
int SATSize = input.readInt();
//System.out.println("normalSATSize: " + mSATSize);
mDirectorySId = mInput.readInt();
//System.out.println("directorySId: " + mDirectorySId);
directorySId = input.readInt();
//System.out.println("directorySId: " + directorySId);
// Reserved
if (mInput.skipBytes(4) != 4) {
if (input.skipBytes(4) != 4) {
throw new CorruptDocumentException();
}
mMinStreamSize = mInput.readInt();
//System.out.println("minStreamSize: " + mMinStreamSize + " bytes");
minStreamSize = input.readInt();
//System.out.println("minStreamSize: " + minStreamSize + " bytes");
mShortSATSID = mInput.readInt();
//System.out.println("shortSATSID: " + mShortSATSID);
mShortSATSize = mInput.readInt();
//System.out.println("shortSATSize: " + mShortSATSize);
int masterSATSId = mInput.readInt();
shortSATSId = input.readInt();
//System.out.println("shortSATSId: " + shortSATSId);
shortSATSize = input.readInt();
//System.out.println("shortSATSize: " + shortSATSize);
int masterSATSId = input.readInt();
//System.out.println("masterSATSId: " + mMasterSATSID);
int masterSATSize = mInput.readInt();
int masterSATSize = input.readInt();
//System.out.println("masterSATSize: " + mMasterSATSize);
// Read masterSAT: 436 bytes, containing up to 109 SIDs
//System.out.println("MSAT:");
mMasterSAT = new int[SATSize];
masterSAT = new int[SATSize];
final int headerSIds = Math.min(SATSize, 109);
for (int i = 0; i < headerSIds; i++) {
mMasterSAT[i] = mInput.readInt();
//System.out.println("\tSID(" + i + "): " + mMasterSAT[i]);
masterSAT[i] = input.readInt();
//System.out.println("\tSID(" + i + "): " + masterSAT[i]);
}
if (masterSATSId == END_OF_CHAIN_SID) {
// End of chain
int freeSIdLength = 436 - (SATSize * 4);
if (mInput.skipBytes(freeSIdLength) != freeSIdLength) {
if (input.skipBytes(freeSIdLength) != freeSIdLength) {
throw new CorruptDocumentException();
}
}
@@ -288,17 +290,17 @@ public final class CompoundDocument {
int index = headerSIds;
for (int i = 0; i < masterSATSize; i++) {
for (int j = 0; j < 127; j++) {
int sid = mInput.readInt();
int sid = input.readInt();
switch (sid) {
case FREE_SID:// Free
break;
default:
mMasterSAT[index++] = sid;
masterSAT[index++] = sid;
break;
}
}
int next = mInput.readInt();
int next = input.readInt();
if (next == END_OF_CHAIN_SID) {// End of chain
break;
}
@@ -309,37 +311,37 @@ public final class CompoundDocument {
}
private void readSAT() throws IOException {
if (mSAT != null) {
if (SAT != null) {
return;
}
final int intsPerSector = mSectorSize / 4;
final int intsPerSector = sectorSize / 4;
// Read the Sector Allocation Table
mSAT = new int[mMasterSAT.length * intsPerSector];
SAT = new int[masterSAT.length * intsPerSector];
for (int i = 0; i < mMasterSAT.length; i++) {
seekToSId(mMasterSAT[i], FREE_SID);
for (int i = 0; i < masterSAT.length; i++) {
seekToSId(masterSAT[i], FREE_SID);
for (int j = 0; j < intsPerSector; j++) {
int nextSID = mInput.readInt();
int nextSID = input.readInt();
int index = (j + (i * intsPerSector));
mSAT[index] = nextSID;
SAT[index] = nextSID;
}
}
// Read the short-stream Sector Allocation Table
SIdChain chain = getSIdChain(mShortSATSID, FREE_SID);
mShortSAT = new int[mShortSATSize * intsPerSector];
for (int i = 0; i < mShortSATSize; i++) {
SIdChain chain = getSIdChain(shortSATSId, FREE_SID);
shortSAT = new int[shortSATSize * intsPerSector];
for (int i = 0; i < shortSATSize; i++) {
seekToSId(chain.get(i), FREE_SID);
for (int j = 0; j < intsPerSector; j++) {
int nextSID = mInput.readInt();
int nextSID = input.readInt();
int index = (j + (i * intsPerSector));
mShortSAT[index] = nextSID;
shortSAT[index] = nextSID;
}
}
}
@@ -355,7 +357,7 @@ public final class CompoundDocument {
private SIdChain getSIdChain(final int pSId, final long pStreamSize) throws IOException {
SIdChain chain = new SIdChain();
int[] sat = isShortStream(pStreamSize) ? mShortSAT : mSAT;
int[] sat = isShortStream(pStreamSize) ? shortSAT : SAT;
int sid = pSId;
while (sid != END_OF_CHAIN_SID && sid != FREE_SID) {
@@ -367,7 +369,7 @@ public final class CompoundDocument {
}
private boolean isShortStream(final long pStreamSize) {
return pStreamSize != FREE_SID && pStreamSize < mMinStreamSize;
return pStreamSize != FREE_SID && pStreamSize < minStreamSize;
}
/**
@@ -383,56 +385,56 @@ public final class CompoundDocument {
if (isShortStream(pStreamSize)) {
// The short-stream is not continouos...
Entry root = getRootEntry();
if (mShortStreamSIdChain == null) {
mShortStreamSIdChain = getSIdChain(root.startSId, root.streamSize);
if (shortStreamSIdChain == null) {
shortStreamSIdChain = getSIdChain(root.startSId, root.streamSize);
}
int shortPerStd = mSectorSize / mShortSectorSize;
int shortPerStd = sectorSize / shortSectorSize;
int offset = pSId / shortPerStd;
int shortOffset = pSId - (offset * shortPerStd);
pos = HEADER_SIZE
+ (mShortStreamSIdChain.get(offset) * (long) mSectorSize)
+ (shortOffset * (long) mShortSectorSize);
+ (shortStreamSIdChain.get(offset) * (long) sectorSize)
+ (shortOffset * (long) shortSectorSize);
}
else {
pos = HEADER_SIZE + pSId * (long) mSectorSize;
pos = HEADER_SIZE + pSId * (long) sectorSize;
}
if (mInput instanceof LittleEndianRandomAccessFile) {
((LittleEndianRandomAccessFile) mInput).seek(pos);
if (input instanceof LittleEndianRandomAccessFile) {
((LittleEndianRandomAccessFile) input).seek(pos);
}
else if (mInput instanceof ImageInputStream) {
((ImageInputStream) mInput).seek(pos);
else if (input instanceof ImageInputStream) {
((ImageInputStream) input).seek(pos);
}
else {
((SeekableLittleEndianDataInputStream) mInput).seek(pos);
((SeekableLittleEndianDataInputStream) input).seek(pos);
}
}
private void seekToDId(final int pDId) throws IOException {
if (mDirectorySIdChain == null) {
mDirectorySIdChain = getSIdChain(mDirectorySId, FREE_SID);
if (directorySIdChain == null) {
directorySIdChain = getSIdChain(directorySId, FREE_SID);
}
int dIdsPerSId = mSectorSize / Entry.LENGTH;
int dIdsPerSId = sectorSize / Entry.LENGTH;
int sIdOffset = pDId / dIdsPerSId;
int dIdOffset = pDId - (sIdOffset * dIdsPerSId);
int sId = mDirectorySIdChain.get(sIdOffset);
int sId = directorySIdChain.get(sIdOffset);
seekToSId(sId, FREE_SID);
if (mInput instanceof LittleEndianRandomAccessFile) {
LittleEndianRandomAccessFile input = (LittleEndianRandomAccessFile) mInput;
if (input instanceof LittleEndianRandomAccessFile) {
LittleEndianRandomAccessFile input = (LittleEndianRandomAccessFile) this.input;
input.seek(input.getFilePointer() + dIdOffset * Entry.LENGTH);
}
else if (mInput instanceof ImageInputStream) {
ImageInputStream input = (ImageInputStream) mInput;
else if (input instanceof ImageInputStream) {
ImageInputStream input = (ImageInputStream) this.input;
input.seek(input.getStreamPosition() + dIdOffset * Entry.LENGTH);
}
else {
SeekableLittleEndianDataInputStream input = (SeekableLittleEndianDataInputStream) mInput;
SeekableLittleEndianDataInputStream input = (SeekableLittleEndianDataInputStream) this.input;
input.seek(input.getStreamPosition() + dIdOffset * Entry.LENGTH);
}
}
@@ -442,7 +444,7 @@ public final class CompoundDocument {
// TODO: Detach? Means, we have to copy to a byte buffer, or keep track of
// positions, and seek back and forth (would be cool, but difficult)..
int sectorSize = pStreamSize < mMinStreamSize ? mShortSectorSize : mSectorSize;
int sectorSize = pStreamSize < minStreamSize ? shortSectorSize : this.sectorSize;
return new Stream(chain, pStreamSize, sectorSize, this);
}
@@ -453,7 +455,7 @@ public final class CompoundDocument {
byte[] bytes = new byte[Entry.LENGTH];
seekToDId(pDirectoryId);
mInput.readFully(bytes);
input.readFully(bytes);
return new ByteArrayInputStream(bytes);
}
@@ -462,8 +464,8 @@ public final class CompoundDocument {
Entry entry = Entry.readEntry(new LittleEndianDataInputStream(
getDirectoryStreamForDId(pDirectoryId)
));
entry.mParent = pParent;
entry.mDocument = this;
entry.parent = pParent;
entry.document = this;
return entry;
}
@@ -527,21 +529,21 @@ public final class CompoundDocument {
}
public Entry getRootEntry() throws IOException {
if (mRootEntry == null) {
if (rootEntry == null) {
readSAT();
mRootEntry = getEntry(0, null);
rootEntry = getEntry(0, null);
if (mRootEntry.type != Entry.ROOT_STORAGE) {
throw new CorruptDocumentException("Invalid root storage type: " + mRootEntry.type);
if (rootEntry.type != Entry.ROOT_STORAGE) {
throw new CorruptDocumentException("Invalid root storage type: " + rootEntry.type);
}
}
return mRootEntry;
return rootEntry;
}
// @Override
// public int hashCode() {
// return mUID.hashCode();
// return uUID.hashCode();
// }
//
// @Override
@@ -555,7 +557,7 @@ public final class CompoundDocument {
// }
//
// if (pOther.getClass() == getClass()) {
// return mUID.equals(((CompoundDocument) pOther).mUID);
// return uUID.equals(((CompoundDocument) pOther).uUID);
// }
//
// return false;
@@ -565,7 +567,7 @@ public final class CompoundDocument {
public String toString() {
return String.format(
"%s[uuid: %s, sector size: %d/%d bytes, directory SID: %d, master SAT: %s entries]",
getClass().getSimpleName(), mUID, mSectorSize, mShortSectorSize, mDirectorySId, mMasterSAT.length
getClass().getSimpleName(), uUID, sectorSize, shortSectorSize, directorySId, masterSAT.length
);
}
@@ -638,11 +640,11 @@ public final class CompoundDocument {
private boolean fillBuffer() throws IOException {
if (mNextSectorPos < mChain.length()) {
// TODO: Sync on mDocument.mInput here, and we are completely detached... :-)
// TODO: Sync on document.input here, and we are completely detached... :-)
// TODO: We also need to sync other places...
synchronized (mDocument) {
mDocument.seekToSId(mChain.get(mNextSectorPos), mLength);
mDocument.mInput.readFully(mBuffer);
mDocument.input.readFully(mBuffer);
}
mNextSectorPos++;

View File

@@ -61,9 +61,9 @@ public final class Entry implements Comparable<Entry> {
int startSId;
int streamSize;
CompoundDocument mDocument;
Entry mParent;
SortedSet<Entry> mChildren;
CompoundDocument document;
Entry parent;
SortedSet<Entry> children;
public final static int LENGTH = 128;
@@ -190,7 +190,7 @@ public final class Entry implements Comparable<Entry> {
return null;
}
return mDocument.getInputStreamForSId(startSId, streamSize);
return document.getInputStreamForSId(startSId, streamSize);
}
/**
@@ -248,7 +248,7 @@ public final class Entry implements Comparable<Entry> {
* the root {@code Entry}
*/
public Entry getParentEntry() {
return mParent;
return parent;
}
/**
@@ -266,7 +266,7 @@ public final class Entry implements Comparable<Entry> {
Entry dummy = new Entry();
dummy.name = pName;
dummy.mParent = this;
dummy.parent = this;
SortedSet child = getChildEntries().tailSet(dummy);
return (Entry) child.first();
@@ -279,26 +279,26 @@ public final class Entry implements Comparable<Entry> {
* @throws java.io.IOException if an I/O exception occurs
*/
public SortedSet<Entry> getChildEntries() throws IOException {
if (mChildren == null) {
if (children == null) {
if (isFile() || rootNodeDId == -1) {
mChildren = NO_CHILDREN;
children = NO_CHILDREN;
}
else {
// Start at root node in R/B tree, and raed to the left and right,
// re-build tree, according to the docs
mChildren = mDocument.getEntries(rootNodeDId, this);
children = document.getEntries(rootNodeDId, this);
}
}
return mChildren;
return children;
}
@Override
public String toString() {
return "\"" + name + "\""
+ " (" + (isFile() ? "Document" : (isDirectory() ? "Directory" : "Root"))
+ (mParent != null ? ", parent: \"" + mParent.getName() + "\"" : "")
+ (isFile() ? "" : ", children: " + (mChildren != null ? String.valueOf(mChildren.size()) : "(unknown)"))
+ (parent != null ? ", parent: \"" + parent.getName() + "\"" : "")
+ (isFile() ? "" : ", children: " + (children != null ? String.valueOf(children.size()) : "(unknown)"))
+ ", SId=" + startSId + ", length=" + streamSize + ")";
}
@@ -312,8 +312,8 @@ public final class Entry implements Comparable<Entry> {
}
Entry other = (Entry) pOther;
return name.equals(other.name) && (mParent == other.mParent
|| (mParent != null && mParent.equals(other.mParent)));
return name.equals(other.name) && (parent == other.parent
|| (parent != null && parent.equals(other.parent)));
}
@Override

View File

@@ -37,11 +37,10 @@ import java.net.*;
* @see SimpleAuthenticator
* @see java.net.Authenticator
*
* @author Harald Kuhr (haraldk@iconmedialab.no),
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
* @version 1.0
*/
public interface AuthenticatorFilter {
public boolean accept(InetAddress pAddress, int pPort, String pProtocol,
String pPrompt, String pScheme);
public boolean accept(InetAddress pAddress, int pPort, String pProtocol, String pPrompt, String pScheme);
}

View File

@@ -26,7 +26,7 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.twelvemonkeys.util;
package com.twelvemonkeys.net;
import com.twelvemonkeys.io.*;
import com.twelvemonkeys.io.enc.Base64Decoder;
@@ -41,8 +41,9 @@ import java.io.*;
* @author unascribed
* @author last modified by $Author: haku $
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/util/BASE64.java#1 $
* @deprecated Use {@link com.twelvemonkeys.io.enc.Base64Encoder}/{@link Base64Decoder} instead
*/
public class BASE64 {
class BASE64 {
/**
* This array maps the characters to their 6 bit values

View File

@@ -29,7 +29,6 @@
package com.twelvemonkeys.net;
import com.twelvemonkeys.lang.StringUtil;
import com.twelvemonkeys.util.BASE64;
import java.io.*;
import java.net.*;
@@ -65,18 +64,18 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
private final static String HTTP_HEADER_END = "\r\n\r\n";
private static final String HEADER_WWW_AUTH = "WWW-Authenticate";
private final static int BUF_SIZE = 8192;
private int mMaxRedirects = (System.getProperty("http.maxRedirects") != null)
private int maxRedirects = (System.getProperty("http.maxRedirects") != null)
? Integer.parseInt(System.getProperty("http.maxRedirects"))
: 20;
protected int mTimeout = -1;
protected int mConnectTimeout = -1;
private Socket mSocket = null;
protected InputStream mErrorStream = null;
protected InputStream mInputStream = null;
protected OutputStream mOutputStream = null;
private String[] mResponseHeaders = null;
protected Properties mResponseHeaderFields = null;
protected Properties mRequestProperties = new Properties();
protected int timeout = -1;
protected int connectTimeout = -1;
private Socket socket = null;
protected InputStream errorStream = null;
protected InputStream inputStream = null;
protected OutputStream outputStream = null;
private String[] responseHeaders = null;
protected Properties responseHeaderFields = null;
protected Properties requestProperties = new Properties();
/**
* Creates a HttpURLConnection.
@@ -114,7 +113,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
protected HttpURLConnection(URL pURL, int pTimeout, int pConnectTimeout) {
super(pURL);
setTimeout(pTimeout);
mConnectTimeout = pConnectTimeout;
connectTimeout = pConnectTimeout;
}
/**
@@ -135,13 +134,13 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if (connected) {
throw new IllegalAccessError("Already connected");
}
String oldValue = mRequestProperties.getProperty(pKey);
String oldValue = requestProperties.getProperty(pKey);
if (oldValue == null) {
mRequestProperties.setProperty(pKey, pValue);
requestProperties.setProperty(pKey, pValue);
}
else {
mRequestProperties.setProperty(pKey, oldValue + ", " + pValue);
requestProperties.setProperty(pKey, oldValue + ", " + pValue);
}
}
@@ -158,7 +157,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if (connected) {
throw new IllegalAccessError("Already connected");
}
return mRequestProperties.getProperty(pKey);
return requestProperties.getProperty(pKey);
}
/**
@@ -212,7 +211,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
* if there is no such field in the header.
*/
public String getHeaderField(String pName) {
return mResponseHeaderFields.getProperty(StringUtil.toLowerCase(pName));
return responseHeaderFields.getProperty(StringUtil.toLowerCase(pName));
}
/**
@@ -230,10 +229,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
*/
public String getHeaderField(int pIndex) {
// TODO: getInputStream() first, to make sure we have header fields
if (pIndex >= mResponseHeaders.length) {
if (pIndex >= responseHeaders.length) {
return null;
}
String field = mResponseHeaders[pIndex];
String field = responseHeaders[pIndex];
// pIndex == 0, means the response code etc (i.e. "HTTP/1.1 200 OK").
if ((pIndex == 0) || (field == null)) {
@@ -256,10 +255,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
*/
public String getHeaderFieldKey(int pIndex) {
// TODO: getInputStream() first, to make sure we have header fields
if (pIndex >= mResponseHeaders.length) {
if (pIndex >= responseHeaders.length) {
return null;
}
String field = mResponseHeaders[pIndex];
String field = responseHeaders[pIndex];
if (StringUtil.isEmpty(field)) {
return null;
@@ -283,10 +282,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if (pTimeout < 0) { // Must be positive
throw new IllegalArgumentException("Timeout must be positive.");
}
mTimeout = pTimeout;
if (mSocket != null) {
timeout = pTimeout;
if (socket != null) {
try {
mSocket.setSoTimeout(pTimeout);
socket.setSoTimeout(pTimeout);
}
catch (SocketException se) {
// Not much to do about that...
@@ -305,12 +304,12 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
public int getTimeout() {
try {
return ((mSocket != null)
? mSocket.getSoTimeout()
: mTimeout);
return ((socket != null)
? socket.getSoTimeout()
: timeout);
}
catch (SocketException se) {
return mTimeout;
return timeout;
}
}
@@ -332,24 +331,24 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
}
int length;
if (mInputStream == null) {
if (inputStream == null) {
return null;
}
// "De-chunk" the output stream
else if ("chunked".equalsIgnoreCase(getHeaderField("Transfer-Encoding"))) {
if (!(mInputStream instanceof ChunkedInputStream)) {
mInputStream = new ChunkedInputStream(mInputStream);
if (!(inputStream instanceof ChunkedInputStream)) {
inputStream = new ChunkedInputStream(inputStream);
}
}
// Make sure we don't wait forever, if the content-length is known
else if ((length = getHeaderFieldInt("Content-Length", -1)) >= 0) {
if (!(mInputStream instanceof FixedLengthInputStream)) {
mInputStream = new FixedLengthInputStream(mInputStream, length);
if (!(inputStream instanceof FixedLengthInputStream)) {
inputStream = new FixedLengthInputStream(inputStream, length);
}
}
return mInputStream;
return inputStream;
}
/**
@@ -364,7 +363,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if (!connected) {
connect();
}
return mOutputStream;
return outputStream;
}
/**
@@ -374,15 +373,15 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
* instance can be reused for other requests.
*/
public void disconnect() {
if (mSocket != null) {
if (socket != null) {
try {
mSocket.close();
socket.close();
}
catch (IOException ioe) {
// Does not matter, I guess.
}
mSocket = null;
socket = null;
}
connected = false;
}
@@ -397,37 +396,37 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
: HTTP_DEFAULT_PORT;
// Create socket if we don't have one
if (mSocket == null) {
//mSocket = new Socket(pURL.getHost(), port); // Blocks...
mSocket = createSocket(pURL, port, mConnectTimeout);
mSocket.setSoTimeout(mTimeout);
if (socket == null) {
//socket = new Socket(pURL.getHost(), port); // Blocks...
socket = createSocket(pURL, port, connectTimeout);
socket.setSoTimeout(timeout);
}
// Get Socket output stream
OutputStream os = mSocket.getOutputStream();
OutputStream os = socket.getOutputStream();
// Connect using HTTP
writeRequestHeaders(os, pURL, method, mRequestProperties, usingProxy(), pAuth, pAuthType);
writeRequestHeaders(os, pURL, method, requestProperties, usingProxy(), pAuth, pAuthType);
// Get response input stream
InputStream sis = mSocket.getInputStream();
InputStream sis = socket.getInputStream();
BufferedInputStream is = new BufferedInputStream(sis);
// Detatch reponse headers from reponse input stream
InputStream header = detatchResponseHeader(is);
// Parse headers and set response code/message
mResponseHeaders = parseResponseHeader(header);
mResponseHeaderFields = parseHeaderFields(mResponseHeaders);
responseHeaders = parseResponseHeader(header);
responseHeaderFields = parseHeaderFields(responseHeaders);
//System.err.println("Headers fields:");
//mResponseHeaderFields.list(System.err);
//responseHeaderFields.list(System.err);
// Test HTTP response code, to see if further action is needed
switch (getResponseCode()) {
case HTTP_OK:
// 200 OK
mInputStream = is;
mErrorStream = null;
inputStream = is;
errorStream = null;
break;
/*
@@ -472,7 +471,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
// Avoid infinite loop
if (pRetries++ <= 0) {
throw new ProtocolException("Server redirected too many times (" + mMaxRedirects + ") (Authentication required: " + auth + ")"); // This is what sun.net.www.protocol.http.HttpURLConnection does
throw new ProtocolException("Server redirected too many times (" + maxRedirects + ") (Authentication required: " + auth + ")"); // This is what sun.net.www.protocol.http.HttpURLConnection does
}
else if (pa != null) {
connect(pURL, pa, method, pRetries);
@@ -506,8 +505,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
// Test if we can reuse the Socket
if (!(newLoc.getAuthority().equals(pURL.getAuthority()) && (newLoc.getPort() == pURL.getPort()))) {
mSocket.close(); // Close the socket, won't need it anymore
mSocket = null;
socket.close(); // Close the socket, won't need it anymore
socket = null;
}
if (location != null) {
//System.err.println("Redirecting to " + location);
@@ -526,22 +525,22 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
default :
// Not 200 OK, or any of the redirect responses
// Probably an error...
mErrorStream = is;
mInputStream = null;
errorStream = is;
inputStream = null;
}
// --- Need rethinking...
// No further questions, let the Socket wait forever (until the server
// closes the connection)
//mSocket.setSoTimeout(0);
//socket.setSoTimeout(0);
// Probably not... The timeout should only kick if the read BLOCKS.
// Shutdown output, meaning any writes to the outputstream below will
// probably fail...
//mSocket.shutdownOutput();
//socket.shutdownOutput();
// Not a good idea at all... POSTs need the outputstream to send the
// form-data.
// --- /Need rethinking.
mOutputStream = os;
outputStream = os;
}
private static interface SocketConnector extends Runnable {
@@ -663,7 +662,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
return; // Ignore
}
connected = true;
connect(url, null, null, mMaxRedirects);
connect(url, null, null, maxRedirects);
}
/**

View File

@@ -3,7 +3,6 @@ package com.twelvemonkeys.net;
import com.twelvemonkeys.io.FileUtil;
import com.twelvemonkeys.lang.StringUtil;
import com.twelvemonkeys.lang.DateUtil;
import com.twelvemonkeys.util.BASE64;
import com.twelvemonkeys.util.CollectionUtil;
import java.io.*;

View File

@@ -28,29 +28,31 @@
package com.twelvemonkeys.net;
import com.twelvemonkeys.lang.Validate;
import java.net.Authenticator;
import java.net.InetAddress;
import java.net.PasswordAuthentication;
import java.net.URL;
import java.util.Hashtable;
import java.util.HashMap;
import java.util.Map;
/**
* A simple Authenticator implementation.
* Singleton class, obtain reference through the static
* Singleton class, obtain reference through the static
* {@code getInstance} method.
* <P>
* <p/>
* <EM>After swearing, sweating, pulling my hair, banging my head repeatedly
* into the walls and reading the java.net.Authenticator API documentation
* into the walls and reading the java.net.Authenticator API documentation
* once more, an idea came to my mind. This is the result. I hope you find it
* useful. -- Harald K.</EM>
*
* @see java.net.Authenticator
*
* @author Harald Kuhr (haraldk@iconmedialab.no)
* @version 1.0
* @version 1.0
* @see java.net.Authenticator
*/
public class SimpleAuthenticator extends Authenticator {
/** The reference to the single instance of this class. */
private static SimpleAuthenticator sInstance = null;
/** Keeps track of the state of this class. */
@@ -63,237 +65,179 @@ public class SimpleAuthenticator extends Authenticator {
/** Basic authentication scheme. */
public final static String BASIC = "Basic";
/**
* The hastable that keeps track of the PasswordAuthentications.
*/
/** The hastable that keeps track of the PasswordAuthentications. */
protected Map<AuthKey, PasswordAuthentication> passwordAuthentications = null;
protected Hashtable mPasswordAuthentications = null;
/**
* The hastable that keeps track of the Authenticators.
*/
protected Hashtable mAuthenticators = null;
/**
* Creates a SimpleAuthenticator.
*/
/** The hastable that keeps track of the Authenticators. */
protected Map<PasswordAuthenticator, AuthenticatorFilter> authenticators = null;
/** Creates a SimpleAuthenticator. */
private SimpleAuthenticator() {
mPasswordAuthentications = new Hashtable();
mAuthenticators = new Hashtable();
passwordAuthentications = new HashMap<AuthKey, PasswordAuthentication>();
authenticators = new HashMap<PasswordAuthenticator, AuthenticatorFilter>();
}
/**
* Gets the SimpleAuthenticator instance and registers it through the
* Gets the SimpleAuthenticator instance and registers it through the
* Authenticator.setDefault(). If there is no current instance
* of the SimpleAuthenticator in the VM, one is created. This method will
* try to figure out if the setDefault() succeeded (a hack), and will
* try to figure out if the setDefault() succeeded (a hack), and will
* return null if it was not able to register the instance as default.
*
* @return The single instance of this class, or null, if another
* Authenticator is allready registered as default.
* @return The single instance of this class, or null, if another
* Authenticator is allready registered as default.
*/
public static synchronized SimpleAuthenticator getInstance() {
if (!sInitialized) {
// Create an instance
sInstance = new SimpleAuthenticator();
if (!sInitialized) {
// Create an instance
sInstance = new SimpleAuthenticator();
// Try to set default (this may quietly fail...)
Authenticator.setDefault(sInstance);
// Try to set default (this may quietly fail...)
Authenticator.setDefault(sInstance);
// A hack to figure out if we really did set the authenticator
PasswordAuthentication pa =
Authenticator.requestPasswordAuthentication(null, FOURTYTWO,
null, null, MAGIC);
// A hack to figure out if we really did set the authenticator
PasswordAuthentication pa = Authenticator.requestPasswordAuthentication(null, FOURTYTWO, null, null, MAGIC);
// If this test returns false, we didn't succeed, so we set the
// instance back to null.
if (pa == null || !MAGIC.equals(pa.getUserName()) ||
!("" + FOURTYTWO).equals(new String(pa.getPassword())))
sInstance = null;
// If this test returns false, we didn't succeed, so we set the
// instance back to null.
if (pa == null || !MAGIC.equals(pa.getUserName()) || !("" + FOURTYTWO).equals(new String(pa.getPassword()))) {
sInstance = null;
}
// Done
sInitialized = true;
}
// Done
sInitialized = true;
}
return sInstance;
return sInstance;
}
/**
* Gets the PasswordAuthentication for the request. Called when password
* Gets the PasswordAuthentication for the request. Called when password
* authorization is needed.
*
* @return The PasswordAuthentication collected from the user, or null if
* @return The PasswordAuthentication collected from the user, or null if
* none is provided.
*/
protected PasswordAuthentication getPasswordAuthentication() {
// Don't worry, this is just a hack to figure out if we were able
// to set this Authenticator through the setDefault method.
if (!sInitialized && MAGIC.equals(getRequestingScheme())
&& getRequestingPort() == FOURTYTWO)
return new PasswordAuthentication(MAGIC, ("" + FOURTYTWO)
.toCharArray());
/*
System.err.println("getPasswordAuthentication");
System.err.println(getRequestingSite());
System.err.println(getRequestingPort());
System.err.println(getRequestingProtocol());
System.err.println(getRequestingPrompt());
System.err.println(getRequestingScheme());
*/
// Don't worry, this is just a hack to figure out if we were able
// to set this Authenticator through the setDefault method.
if (!sInitialized && MAGIC.equals(getRequestingScheme()) && getRequestingPort() == FOURTYTWO) {
return new PasswordAuthentication(MAGIC, ("" + FOURTYTWO).toCharArray());
}
/*
System.err.println("getPasswordAuthentication");
System.err.println(getRequestingSite());
System.err.println(getRequestingPort());
System.err.println(getRequestingProtocol());
System.err.println(getRequestingPrompt());
System.err.println(getRequestingScheme());
*/
// TODO:
// Look for a more specific PasswordAuthenticatior before using
// Default:
//
// if (...)
// return pa.requestPasswordAuthentication(getRequestingSite(),
// getRequestingPort(),
// getRequestingProtocol(),
// getRequestingPrompt(),
// getRequestingScheme());
// TODO:
// Look for a more specific PasswordAuthenticatior before using
// Default:
//
// if (...)
// return pa.requestPasswordAuthentication(getRequestingSite(),
// getRequestingPort(),
// getRequestingProtocol(),
// getRequestingPrompt(),
// getRequestingScheme());
return (PasswordAuthentication)
mPasswordAuthentications.get(new AuthKey(getRequestingSite(),
getRequestingPort(),
getRequestingProtocol(),
getRequestingPrompt(),
getRequestingScheme()));
return passwordAuthentications.get(new AuthKey(getRequestingSite(),
getRequestingPort(),
getRequestingProtocol(),
getRequestingPrompt(),
getRequestingScheme()));
}
/**
* Registers a PasswordAuthentication with a given URL address.
*
*/
public PasswordAuthentication registerPasswordAuthentication(URL pURL,
PasswordAuthentication pPA) {
return registerPasswordAuthentication(NetUtil.createInetAddressFromURL(pURL),
pURL.getPort(),
pURL.getProtocol(),
null, // Prompt/Realm
BASIC,
pPA);
/** Registers a PasswordAuthentication with a given URL address. */
public PasswordAuthentication registerPasswordAuthentication(URL pURL, PasswordAuthentication pPA) {
return registerPasswordAuthentication(NetUtil.createInetAddressFromURL(pURL),
pURL.getPort(),
pURL.getProtocol(),
null, // Prompt/Realm
BASIC,
pPA);
}
/**
* Registers a PasswordAuthentication with a given net address.
*
*/
/** Registers a PasswordAuthentication with a given net address. */
public PasswordAuthentication registerPasswordAuthentication(InetAddress pAddress, int pPort, String pProtocol, String pPrompt, String pScheme, PasswordAuthentication pPA) {
/*
System.err.println("registerPasswordAuthentication");
System.err.println(pAddress);
System.err.println(pPort);
System.err.println(pProtocol);
System.err.println(pPrompt);
System.err.println(pScheme);
*/
public PasswordAuthentication registerPasswordAuthentication(
InetAddress pAddress, int pPort, String pProtocol,
String pPrompt, String pScheme, PasswordAuthentication pPA)
{
/*
System.err.println("registerPasswordAuthentication");
System.err.println(pAddress);
System.err.println(pPort);
System.err.println(pProtocol);
System.err.println(pPrompt);
System.err.println(pScheme);
*/
return (PasswordAuthentication)
mPasswordAuthentications.put(new AuthKey(pAddress, pPort,
pProtocol, pPrompt,
pScheme),
pPA);
return passwordAuthentications.put(new AuthKey(pAddress, pPort, pProtocol, pPrompt, pScheme), pPA);
}
/**
* Unregisters a PasswordAuthentication with a given URL address.
*
*/
/** Unregisters a PasswordAuthentication with a given URL address. */
public PasswordAuthentication unregisterPasswordAuthentication(URL pURL) {
return unregisterPasswordAuthentication(NetUtil.createInetAddressFromURL(pURL),
pURL.getPort(),
pURL.getProtocol(),
null,
BASIC);
return unregisterPasswordAuthentication(NetUtil.createInetAddressFromURL(pURL), pURL.getPort(), pURL.getProtocol(), null, BASIC);
}
/**
* Unregisters a PasswordAuthentication with a given net address.
*
*/
public PasswordAuthentication unregisterPasswordAuthentication(
InetAddress pAddress, int pPort, String pProtocol,
String pPrompt, String pScheme)
{
return (PasswordAuthentication)
mPasswordAuthentications.remove(new AuthKey(pAddress, pPort,
pProtocol, pPrompt,
pScheme));
/** Unregisters a PasswordAuthentication with a given net address. */
public PasswordAuthentication unregisterPasswordAuthentication(InetAddress pAddress, int pPort, String pProtocol, String pPrompt, String pScheme) {
return passwordAuthentications.remove(new AuthKey(pAddress, pPort, pProtocol, pPrompt, pScheme));
}
/**
* TODO: Registers a PasswordAuthenticator that can answer authentication
* requests.
*
*
* @see PasswordAuthenticator
*/
public void registerPasswordAuthenticator(PasswordAuthenticator pPA,
AuthenticatorFilter pFilter) {
mAuthenticators.put(pPA, pFilter);
public void registerPasswordAuthenticator(PasswordAuthenticator pPA, AuthenticatorFilter pFilter) {
authenticators.put(pPA, pFilter);
}
/**
* TODO: Unregisters a PasswordAuthenticator that can answer authentication
* requests.
*
*
* @see PasswordAuthenticator
*/
public void unregisterPasswordAuthenticator(PasswordAuthenticator pPA) {
mAuthenticators.remove(pPA);
authenticators.remove(pPA);
}
}
/**
* Utility class, used for caching the PasswordAuthentication objects.
* Everything but address may be null
*/
class AuthKey {
InetAddress mAddress = null;
int mPort = -1;
String mProtocol = null;
String mPrompt = null;
String mScheme = null;
AuthKey(InetAddress pAddress, int pPort, String pProtocol,
String pPrompt, String pScheme) {
if (pAddress == null)
throw new IllegalArgumentException("Address argument can't be null!");
InetAddress address = null;
int port = -1;
String protocol = null;
String prompt = null;
String scheme = null;
mAddress = pAddress;
mPort = pPort;
mProtocol = pProtocol;
mPrompt = pPrompt;
mScheme = pScheme;
AuthKey(InetAddress pAddress, int pPort, String pProtocol, String pPrompt, String pScheme) {
Validate.notNull(pAddress, "address");
// System.out.println("Created: " + this);
address = pAddress;
port = pPort;
protocol = pProtocol;
prompt = pPrompt;
scheme = pScheme;
// System.out.println("Created: " + this);
}
/**
* Creates a string representation of this object.
*/
/** Creates a string representation of this object. */
public String toString() {
return "AuthKey[" + mAddress + ":" + mPort + "/" + mProtocol + " \"" + mPrompt + "\" (" + mScheme + ")]";
return "AuthKey[" + address + ":" + port + "/" + protocol + " \"" + prompt + "\" (" + scheme + ")]";
}
public boolean equals(Object pObj) {
return (pObj instanceof AuthKey ? equals((AuthKey) pObj) : false);
return (pObj instanceof AuthKey && equals((AuthKey) pObj));
}
// Ahem.. Breaks the rule from Object.equals(Object):
@@ -302,25 +246,25 @@ class AuthKey {
// should return true.
public boolean equals(AuthKey pKey) {
// Maybe allow nulls, and still be equal?
return (mAddress.equals(pKey.mAddress)
&& (mPort == -1
|| pKey.mPort == -1
|| mPort == pKey.mPort)
&& (mProtocol == null
|| pKey.mProtocol == null
|| mProtocol.equals(pKey.mProtocol))
&& (mPrompt == null
|| pKey.mPrompt == null
|| mPrompt.equals(pKey.mPrompt))
&& (mScheme == null
|| pKey.mScheme == null
|| mScheme.equalsIgnoreCase(pKey.mScheme)));
// Maybe allow nulls, and still be equal?
return (address.equals(pKey.address)
&& (port == -1
|| pKey.port == -1
|| port == pKey.port)
&& (protocol == null
|| pKey.protocol == null
|| protocol.equals(pKey.protocol))
&& (prompt == null
|| pKey.prompt == null
|| prompt.equals(pKey.prompt))
&& (scheme == null
|| pKey.scheme == null
|| scheme.equalsIgnoreCase(pKey.scheme)));
}
public int hashCode() {
// There won't be too many pr address, will it? ;-)
return mAddress.hashCode();
// There won't be too many pr address, will it? ;-)
return address.hashCode();
}
}

View File

@@ -52,13 +52,13 @@ public final class DOMSerializer {
private static final String PARAM_PRETTY_PRINT = "format-pretty-print";
private static final String PARAM_XML_DECLARATION = "xml-declaration";
private final LSSerializer mSerializer;
private final LSOutput mOutput;
private final LSSerializer serializer;
private final LSOutput output;
private DOMSerializer() {
DOMImplementationLS domImpl = Support.getImplementation();
mSerializer = domImpl.createLSSerializer();
mOutput = domImpl.createLSOutput();
serializer = domImpl.createLSSerializer();
output = domImpl.createLSOutput();
}
/**
@@ -71,8 +71,8 @@ public final class DOMSerializer {
public DOMSerializer(final OutputStream pStream, final String pEncoding) {
this();
mOutput.setByteStream(pStream);
mOutput.setEncoding(pEncoding);
output.setByteStream(pStream);
output.setEncoding(pEncoding);
}
/**
@@ -84,17 +84,17 @@ public final class DOMSerializer {
public DOMSerializer(final Writer pStream) {
this();
mOutput.setCharacterStream(pStream);
output.setCharacterStream(pStream);
}
/*
// TODO: Is it useful?
public void setNewLine(final String pNewLine) {
mSerializer.setNewLine(pNewLine);
serializer.setNewLine(pNewLine);
}
public String getNewLine() {
return mSerializer.getNewLine();
return serializer.getNewLine();
}
*/
@@ -107,18 +107,18 @@ public final class DOMSerializer {
* @param pPrettyPrint {@code true} to enable pretty printing
*/
public void setPrettyPrint(final boolean pPrettyPrint) {
DOMConfiguration configuration = mSerializer.getDomConfig();
DOMConfiguration configuration = serializer.getDomConfig();
if (configuration.canSetParameter(PARAM_PRETTY_PRINT, pPrettyPrint)) {
configuration.setParameter(PARAM_PRETTY_PRINT, pPrettyPrint);
}
}
public boolean getPrettyPrint() {
return Boolean.TRUE.equals(mSerializer.getDomConfig().getParameter(PARAM_PRETTY_PRINT));
return Boolean.TRUE.equals(serializer.getDomConfig().getParameter(PARAM_PRETTY_PRINT));
}
private void setXMLDeclaration(boolean pXMLDeclaration) {
mSerializer.getDomConfig().setParameter(PARAM_XML_DECLARATION, pXMLDeclaration);
serializer.getDomConfig().setParameter(PARAM_XML_DECLARATION, pXMLDeclaration);
}
/**
@@ -142,7 +142,7 @@ public final class DOMSerializer {
private void serializeImpl(final Node pNode, final boolean pOmitDecl) {
setXMLDeclaration(pOmitDecl);
mSerializer.write(pNode, mOutput);
serializer.write(pNode, output);
}
private static class Support {

View File

@@ -65,22 +65,22 @@ public class XMLSerializer {
// Store user options here too
// TODO: Push/pop?
private final OutputStream mOutput;
private final Charset mEncoding;
private final SerializationContext mContext;
private final OutputStream output;
private final Charset encoding;
private final SerializationContext context;
public XMLSerializer(final OutputStream pOutput, final String pEncoding) {
mOutput = pOutput;
mEncoding = Charset.forName(pEncoding);
mContext = new SerializationContext();
output = pOutput;
encoding = Charset.forName(pEncoding);
context = new SerializationContext();
}
public final void setIndentation(String pIndent) {
mContext.indent = pIndent != null ? pIndent : " ";
context.indent = pIndent != null ? pIndent : " ";
}
public final void setStripComments(boolean pStrip) {
mContext.stripComments = pStrip;
context.stripComments = pStrip;
}
/**
@@ -101,12 +101,12 @@ public class XMLSerializer {
* @param pWriteXMLDeclaration {@code true} if the XML declaration should be included, otherwise {@code false}.
*/
public void serialize(final Node pRootNode, final boolean pWriteXMLDeclaration) {
PrintWriter out = new PrintWriter(new OutputStreamWriter(mOutput, mEncoding));
PrintWriter out = new PrintWriter(new OutputStreamWriter(output, encoding));
try {
if (pWriteXMLDeclaration) {
writeXMLDeclaration(out);
}
writeXML(out, pRootNode, mContext.copy());
writeXML(out, pRootNode, context.copy());
}
finally {
out.flush();
@@ -115,7 +115,7 @@ public class XMLSerializer {
private void writeXMLDeclaration(final PrintWriter pOut) {
pOut.print("<?xml version=\"1.0\" encoding=\"");
pOut.print(mEncoding.name());
pOut.print(encoding.name());
pOut.println("\"?>");
}