mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 11:35:29 -04:00
Code clean-up, no functional changes.
This commit is contained in:
parent
7435c12a80
commit
6ba32b657a
@ -36,34 +36,36 @@ import java.util.Random;
|
|||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||||
* @author last modified by $Author: haku $
|
* @author last modified by $Author: haku $
|
||||||
*
|
*
|
||||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-core/src/main/java/com/twelvemonkeys/image/DiffusionDither.java#1 $
|
* @version $Id: DiffusionDither.java#1 $
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class DiffusionDither implements BufferedImageOp, RasterOp {
|
public class DiffusionDither implements BufferedImageOp, RasterOp {
|
||||||
|
|
||||||
protected IndexColorModel indexColorModel = null;
|
|
||||||
private boolean alternateScans = true;
|
|
||||||
private static final int FS_SCALE = 1 << 8;
|
private static final int FS_SCALE = 1 << 8;
|
||||||
private static final Random RANDOM = new Random();
|
private static final Random RANDOM = new Random();
|
||||||
|
|
||||||
|
protected final IndexColorModel indexColorModel;
|
||||||
|
private boolean alternateScans = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code DiffusionDither}, using the given
|
* Creates a {@code DiffusionDither}, using the given
|
||||||
* {@code IndexColorModel} for dithering into.
|
* {@code IndexColorModel} for dithering into.
|
||||||
*
|
*
|
||||||
* @param pICM an IndexColorModel.
|
* @param pICM an IndexColorModel.
|
||||||
*/
|
*/
|
||||||
public DiffusionDither(IndexColorModel pICM) {
|
public DiffusionDither(final IndexColorModel pICM) {
|
||||||
// Store colormodel
|
// Store color model
|
||||||
indexColorModel = pICM;
|
indexColorModel = pICM;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@code DiffusionDither}, with no fixed
|
* Creates a {@code DiffusionDither}, with no fixed
|
||||||
* {@code IndexColorModel}. The colormodel will be generated for each
|
* {@code IndexColorModel}. The color model will be generated for each
|
||||||
* filtering, unless the dest image allready has an
|
* filtering, unless the destination image already has an
|
||||||
* {@code IndexColorModel}.
|
* {@code IndexColorModel}.
|
||||||
*/
|
*/
|
||||||
public DiffusionDither() {
|
public DiffusionDither() {
|
||||||
|
this(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,8 +88,7 @@ public class DiffusionDither implements BufferedImageOp, RasterOp {
|
|||||||
* @throws ImageFilterException if {@code pDestCM} is not {@code null} or
|
* @throws ImageFilterException if {@code pDestCM} is not {@code null} or
|
||||||
* an instance of {@code IndexColorModel}.
|
* an instance of {@code IndexColorModel}.
|
||||||
*/
|
*/
|
||||||
public final BufferedImage createCompatibleDestImage(BufferedImage pSource,
|
public final BufferedImage createCompatibleDestImage(BufferedImage pSource, ColorModel pDestCM) {
|
||||||
ColorModel pDestCM) {
|
|
||||||
if (pDestCM == null) {
|
if (pDestCM == null) {
|
||||||
return new BufferedImage(pSource.getWidth(), pSource.getHeight(),
|
return new BufferedImage(pSource.getWidth(), pSource.getHeight(),
|
||||||
BufferedImage.TYPE_BYTE_INDEXED,
|
BufferedImage.TYPE_BYTE_INDEXED,
|
||||||
@ -107,7 +108,7 @@ public class DiffusionDither implements BufferedImageOp, RasterOp {
|
|||||||
* Creates a compatible {@code Raster} to dither into.
|
* Creates a compatible {@code Raster} to dither into.
|
||||||
* Only {@code IndexColorModel} allowed.
|
* Only {@code IndexColorModel} allowed.
|
||||||
*
|
*
|
||||||
* @param pSrc
|
* @param pSrc the source raster
|
||||||
*
|
*
|
||||||
* @return a {@code WritableRaster}
|
* @return a {@code WritableRaster}
|
||||||
*/
|
*/
|
||||||
@ -115,14 +116,16 @@ public class DiffusionDither implements BufferedImageOp, RasterOp {
|
|||||||
return createCompatibleDestRaster(pSrc, getICM(pSrc));
|
return createCompatibleDestRaster(pSrc, getICM(pSrc));
|
||||||
}
|
}
|
||||||
|
|
||||||
public final WritableRaster createCompatibleDestRaster(Raster pSrc,
|
/**
|
||||||
IndexColorModel pIndexColorModel) {
|
* Creates a compatible {@code Raster} to dither into.
|
||||||
return pIndexColorModel.createCompatibleWritableRaster(pSrc.getWidth(), pSrc.getHeight());
|
*
|
||||||
/*
|
* @param pSrc the source raster.
|
||||||
return new BufferedImage(pSrc.getWidth(), pSrc.getHeight(),
|
* @param pIndexColorModel the index color model used to create a {@code Raster}.
|
||||||
BufferedImage.TYPE_BYTE_INDEXED,
|
*
|
||||||
pIndexColorModel).getRaster();
|
* @return a {@code WritableRaster}
|
||||||
*/
|
*/
|
||||||
|
public final WritableRaster createCompatibleDestRaster(Raster pSrc, IndexColorModel pIndexColorModel) {
|
||||||
|
return pIndexColorModel.createCompatibleWritableRaster(pSrc.getWidth(), pSrc.getHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -221,8 +224,7 @@ public class DiffusionDither implements BufferedImageOp, RasterOp {
|
|||||||
* @return the destination image, or a new image, if {@code pDest} was
|
* @return the destination image, or a new image, if {@code pDest} was
|
||||||
* {@code null}.
|
* {@code null}.
|
||||||
*/
|
*/
|
||||||
public final BufferedImage filter(BufferedImage pSource,
|
public final BufferedImage filter(BufferedImage pSource, BufferedImage pDest) {
|
||||||
BufferedImage pDest) {
|
|
||||||
// Create destination image, if none provided
|
// Create destination image, if none provided
|
||||||
if (pDest == null) {
|
if (pDest == null) {
|
||||||
pDest = createCompatibleDestImage(pSource, getICM(pSource));
|
pDest = createCompatibleDestImage(pSource, getICM(pSource));
|
||||||
@ -265,8 +267,6 @@ public class DiffusionDither implements BufferedImageOp, RasterOp {
|
|||||||
return IndexImage.getIndexColorModel(image, 256, IndexImage.TRANSPARENCY_BITMASK);
|
return IndexImage.getIndexColorModel(image, 256, IndexImage.TRANSPARENCY_BITMASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a single-input/single-output dither operation, applying basic
|
* Performs a single-input/single-output dither operation, applying basic
|
||||||
* Floyd-Steinberg error-diffusion to the image.
|
* Floyd-Steinberg error-diffusion to the image.
|
||||||
@ -278,8 +278,7 @@ public class DiffusionDither implements BufferedImageOp, RasterOp {
|
|||||||
* @return the destination raster, or a new raster, if {@code pDest} was
|
* @return the destination raster, or a new raster, if {@code pDest} was
|
||||||
* {@code null}.
|
* {@code null}.
|
||||||
*/
|
*/
|
||||||
public final WritableRaster filter(final Raster pSource, WritableRaster pDest,
|
public final WritableRaster filter(final Raster pSource, WritableRaster pDest, IndexColorModel pColorModel) {
|
||||||
IndexColorModel pColorModel) {
|
|
||||||
int width = pSource.getWidth();
|
int width = pSource.getWidth();
|
||||||
int height = pSource.getHeight();
|
int height = pSource.getHeight();
|
||||||
|
|
||||||
@ -460,6 +459,7 @@ public class DiffusionDither implements BufferedImageOp, RasterOp {
|
|||||||
forward = !forward;
|
forward = !forward;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return pDest;
|
return pDest;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -89,6 +89,8 @@ import java.awt.image.BufferedImage;
|
|||||||
import java.awt.image.ColorModel;
|
import java.awt.image.ColorModel;
|
||||||
import java.awt.image.IndexColorModel;
|
import java.awt.image.IndexColorModel;
|
||||||
import java.awt.image.RenderedImage;
|
import java.awt.image.RenderedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -127,7 +129,7 @@ import java.util.List;
|
|||||||
* @author <A href="mailto:deweese@apache.org">Thomas DeWeese</A>
|
* @author <A href="mailto:deweese@apache.org">Thomas DeWeese</A>
|
||||||
* @author <A href="mailto:jun@oop-reserch.com">Jun Inamori</A>
|
* @author <A href="mailto:jun@oop-reserch.com">Jun Inamori</A>
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @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/IndexImage.java#1 $
|
* @version $Id: IndexImage.java#1 $
|
||||||
* @see DiffusionDither
|
* @see DiffusionDither
|
||||||
*/
|
*/
|
||||||
class IndexImage {
|
class IndexImage {
|
||||||
@ -237,19 +239,22 @@ class IndexImage {
|
|||||||
if (this.val != val) {
|
if (this.val != val) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to define a cube of the colorspace. The cube can be split
|
* Used to define a cube of the color space. The cube can be split
|
||||||
* approximagely in half to generate two cubes.
|
* approximately in half to generate two cubes.
|
||||||
*/
|
*/
|
||||||
private static class Cube {
|
private static class Cube {
|
||||||
int[] min = {0, 0, 0}, max = {255, 255, 255};
|
int[] min = {0, 0, 0};
|
||||||
|
int[] max = {255, 255, 255};
|
||||||
boolean done = false;
|
boolean done = false;
|
||||||
List[] colors = null;
|
List<Counter>[] colors = null;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
static final int RED = 0;
|
static final int RED = 0;
|
||||||
static final int GRN = 1;
|
static final int GRN = 1;
|
||||||
@ -261,7 +266,7 @@ class IndexImage {
|
|||||||
* @param colors contains the 3D color histogram to be subdivided
|
* @param colors contains the 3D color histogram to be subdivided
|
||||||
* @param count the total number of pixels in the 3D histogram.
|
* @param count the total number of pixels in the 3D histogram.
|
||||||
*/
|
*/
|
||||||
public Cube(List[] colors, int count) {
|
public Cube(List<Counter>[] colors, int count) {
|
||||||
this.colors = colors;
|
this.colors = colors;
|
||||||
this.count = count;
|
this.count = count;
|
||||||
}
|
}
|
||||||
@ -312,20 +317,27 @@ class IndexImage {
|
|||||||
c0 = RED;
|
c0 = RED;
|
||||||
c1 = GRN;
|
c1 = GRN;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cube ret;
|
Cube ret;
|
||||||
|
|
||||||
ret = splitChannel(splitChannel, c0, c1);
|
ret = splitChannel(splitChannel, c0, c1);
|
||||||
|
|
||||||
if (ret != null) {
|
if (ret != null) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = splitChannel(c0, splitChannel, c1);
|
ret = splitChannel(c0, splitChannel, c1);
|
||||||
|
|
||||||
if (ret != null) {
|
if (ret != null) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = splitChannel(c1, splitChannel, c0);
|
ret = splitChannel(c1, splitChannel, c0);
|
||||||
|
|
||||||
if (ret != null) {
|
if (ret != null) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
done = true;
|
done = true;
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@ -381,16 +393,13 @@ class IndexImage {
|
|||||||
|
|
||||||
for (int k = minIdx[c1]; k <= maxIdx[c1]; k++) {
|
for (int k = minIdx[c1]; k <= maxIdx[c1]; k++) {
|
||||||
int idx = idx2 | (k << c1Sh4);
|
int idx = idx2 | (k << c1Sh4);
|
||||||
List v = colors[idx];
|
List<Counter> v = colors[idx];
|
||||||
|
|
||||||
if (v == null) {
|
if (v == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Iterator itr = v.iterator();
|
|
||||||
Counter c;
|
|
||||||
|
|
||||||
while (itr.hasNext()) {
|
for (Counter c : v) {
|
||||||
c = (Counter) itr.next();
|
|
||||||
val = c.val;
|
val = c.val;
|
||||||
vals[0] = (val & 0xFF0000) >> 16;
|
vals[0] = (val & 0xFF0000) >> 16;
|
||||||
vals[1] = (val & 0xFF00) >> 8;
|
vals[1] = (val & 0xFF00) >> 8;
|
||||||
@ -425,7 +434,6 @@ class IndexImage {
|
|||||||
int c = counts[i];
|
int c = counts[i];
|
||||||
|
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
|
|
||||||
// No counts below this so move up bottom of cube.
|
// No counts below this so move up bottom of cube.
|
||||||
if ((tcount == 0) && (i < max[splitChannel])) {
|
if ((tcount == 0) && (i < max[splitChannel])) {
|
||||||
this.min[splitChannel] = i + 1;
|
this.min[splitChannel] = i + 1;
|
||||||
@ -438,10 +446,8 @@ class IndexImage {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((half - tcount) <= ((tcount + c) - half)) {
|
if ((half - tcount) <= ((tcount + c) - half)) {
|
||||||
|
|
||||||
// Then lastAdd is a better top idx for this then i.
|
// Then lastAdd is a better top idx for this then i.
|
||||||
if (lastAdd == -1) {
|
if (lastAdd == -1) {
|
||||||
|
|
||||||
// No lower place to break.
|
// No lower place to break.
|
||||||
if (c == this.count) {
|
if (c == this.count) {
|
||||||
|
|
||||||
@ -465,13 +471,11 @@ class IndexImage {
|
|||||||
else {
|
else {
|
||||||
if (i == this.max[splitChannel]) {
|
if (i == this.max[splitChannel]) {
|
||||||
if (c == this.count) {
|
if (c == this.count) {
|
||||||
|
|
||||||
// would move min up but that should
|
// would move min up but that should
|
||||||
// have happened already.
|
// have happened already.
|
||||||
return null;// no split to make.
|
return null;// no split to make.
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// Would like to break between i and i+1
|
// Would like to break between i and i+1
|
||||||
// but no i+1 so use lastAdd and i;
|
// but no i+1 so use lastAdd and i;
|
||||||
splitLo = lastAdd;
|
splitLo = lastAdd;
|
||||||
@ -503,6 +507,7 @@ class IndexImage {
|
|||||||
ret.max[c0] = this.max[c0];
|
ret.max[c0] = this.max[c0];
|
||||||
ret.min[c1] = this.min[c1];
|
ret.min[c1] = this.min[c1];
|
||||||
ret.max[c1] = this.max[c1];
|
ret.max[c1] = this.max[c1];
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,6 +520,7 @@ class IndexImage {
|
|||||||
if (this.count == 0) {
|
if (this.count == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
float red = 0, grn = 0, blu = 0;
|
float red = 0, grn = 0, blu = 0;
|
||||||
int minR = min[0], minG = min[1], minB = min[2];
|
int minR = min[0], minG = min[1], minB = min[2];
|
||||||
int maxR = max[0], maxG = max[1], maxB = max[2];
|
int maxR = max[0], maxG = max[1], maxB = max[2];
|
||||||
@ -531,20 +537,18 @@ class IndexImage {
|
|||||||
|
|
||||||
for (int k = minIdx[2]; k <= maxIdx[2]; k++) {
|
for (int k = minIdx[2]; k <= maxIdx[2]; k++) {
|
||||||
int idx = idx2 | k;
|
int idx = idx2 | k;
|
||||||
List v = colors[idx];
|
List<Counter> v = colors[idx];
|
||||||
|
|
||||||
if (v == null) {
|
if (v == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Iterator itr = v.iterator();
|
|
||||||
Counter c;
|
|
||||||
|
|
||||||
while (itr.hasNext()) {
|
for (Counter c : v) {
|
||||||
c = (Counter) itr.next();
|
|
||||||
val = c.val;
|
val = c.val;
|
||||||
ired = (val & 0xFF0000) >> 16;
|
ired = (val & 0xFF0000) >> 16;
|
||||||
igrn = (val & 0x00FF00) >> 8;
|
igrn = (val & 0x00FF00) >> 8;
|
||||||
iblu = (val & 0x0000FF);
|
iblu = (val & 0x0000FF);
|
||||||
|
|
||||||
if (((ired >= minR) && (ired <= maxR)) && ((igrn >= minG) && (igrn <= maxG)) && ((iblu >= minB) && (iblu <= maxB))) {
|
if (((ired >= minR) && (ired <= maxR)) && ((igrn >= minG) && (igrn <= maxG)) && ((iblu >= minB) && (iblu <= maxB))) {
|
||||||
weight = (c.count / (float) this.count);
|
weight = (c.count / (float) this.count);
|
||||||
red += ((float) ired) * weight;
|
red += ((float) ired) * weight;
|
||||||
@ -579,10 +583,7 @@ class IndexImage {
|
|||||||
* This version will be removed in a later version of the API.
|
* This version will be removed in a later version of the API.
|
||||||
*/
|
*/
|
||||||
public static IndexColorModel getIndexColorModel(Image pImage, int pNumberOfColors, boolean pFast) {
|
public static IndexColorModel getIndexColorModel(Image pImage, int pNumberOfColors, boolean pFast) {
|
||||||
|
return getIndexColorModel(pImage, pNumberOfColors, pFast ? COLOR_SELECTION_FAST : COLOR_SELECTION_QUALITY);
|
||||||
return getIndexColorModel(pImage, pNumberOfColors, pFast
|
|
||||||
? COLOR_SELECTION_FAST
|
|
||||||
: COLOR_SELECTION_QUALITY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -636,17 +637,12 @@ class IndexImage {
|
|||||||
// We now have at least a buffered image, create model from it
|
// We now have at least a buffered image, create model from it
|
||||||
if (icm == null) {
|
if (icm == null) {
|
||||||
icm = createIndexColorModel(ImageUtil.toBuffered(image), pNumberOfColors, pHints);
|
icm = createIndexColorModel(ImageUtil.toBuffered(image), pNumberOfColors, pHints);
|
||||||
|
|
||||||
//System.out.println("IndexColorModel created from colors.");
|
|
||||||
}
|
}
|
||||||
else if (!(icm instanceof InverseColorMapIndexColorModel)) {
|
else if (!(icm instanceof InverseColorMapIndexColorModel)) {
|
||||||
// If possible, use faster code
|
// If possible, use faster code
|
||||||
//System.out.println("Wrappimg IndexColorModel in InverseColorMapIndexColorModel");
|
|
||||||
icm = new InverseColorMapIndexColorModel(icm);
|
icm = new InverseColorMapIndexColorModel(icm);
|
||||||
}
|
}
|
||||||
//else {
|
|
||||||
//System.out.println("Allredy InverseColorMapIndexColorModel");
|
|
||||||
//}
|
|
||||||
return icm;
|
return icm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -674,7 +670,8 @@ class IndexImage {
|
|||||||
int height = pImage.getHeight();
|
int height = pImage.getHeight();
|
||||||
|
|
||||||
// Using 4 bits from R, G & B.
|
// Using 4 bits from R, G & B.
|
||||||
List[] colors = new List[1 << 12];// [4096]
|
@SuppressWarnings("unchecked")
|
||||||
|
List<Counter>[] colors = new List[1 << 12];// [4096]
|
||||||
|
|
||||||
// Speedup, doesn't decrease image quality much
|
// Speedup, doesn't decrease image quality much
|
||||||
int step = 1;
|
int step = 1;
|
||||||
@ -739,13 +736,16 @@ class IndexImage {
|
|||||||
while (numberOfCubes < pNumberOfColors) {
|
while (numberOfCubes < pNumberOfColors) {
|
||||||
while (cubes[fCube].isDone()) {
|
while (cubes[fCube].isDone()) {
|
||||||
fCube++;
|
fCube++;
|
||||||
|
|
||||||
if (fCube == numberOfCubes) {
|
if (fCube == numberOfCubes) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fCube == numberOfCubes) {
|
if (fCube == numberOfCubes) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cube cube = cubes[fCube];
|
Cube cube = cubes[fCube];
|
||||||
Cube newCube = cube.split();
|
Cube newCube = cube.split();
|
||||||
|
|
||||||
@ -756,6 +756,7 @@ class IndexImage {
|
|||||||
cube = newCube;
|
cube = newCube;
|
||||||
newCube = tmp;
|
newCube = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int j = fCube;
|
int j = fCube;
|
||||||
int count = cube.count;
|
int count = cube.count;
|
||||||
|
|
||||||
@ -765,17 +766,19 @@ class IndexImage {
|
|||||||
}
|
}
|
||||||
cubes[j++] = cubes[i];
|
cubes[j++] = cubes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
cubes[j++] = cube;
|
cubes[j++] = cube;
|
||||||
count = newCube.count;
|
count = newCube.count;
|
||||||
|
|
||||||
while (j < numberOfCubes) {
|
while (j < numberOfCubes) {
|
||||||
if (cubes[j].count < count) {
|
if (cubes[j].count < count) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
for (int i = numberOfCubes; i > j; i--) {
|
|
||||||
cubes[i] = cubes[i - 1];
|
System.arraycopy(cubes, j, cubes, j + 1, numberOfCubes - j);
|
||||||
}
|
|
||||||
cubes[j/*++*/] = newCube;
|
cubes[j/*++*/] = newCube;
|
||||||
numberOfCubes++;
|
numberOfCubes++;
|
||||||
}
|
}
|
||||||
@ -803,15 +806,13 @@ class IndexImage {
|
|||||||
// - transparency added to all totally black colors?
|
// - transparency added to all totally black colors?
|
||||||
int numOfBits = 8;
|
int numOfBits = 8;
|
||||||
|
|
||||||
// -- haraldK, 20021024, as suggested by Thomas E Deweese
|
// -- haraldK, 20021024, as suggested by Thomas E. Deweese
|
||||||
// plus adding a transparent pixel
|
// plus adding a transparent pixel
|
||||||
IndexColorModel icm;
|
IndexColorModel icm;
|
||||||
if (useTransparency) {
|
if (useTransparency) {
|
||||||
//icm = new IndexColorModel(numOfBits, r.length, r, g, b, r.length - 1);
|
|
||||||
icm = new InverseColorMapIndexColorModel(numOfBits, r.length, r, g, b, r.length - 1);
|
icm = new InverseColorMapIndexColorModel(numOfBits, r.length, r, g, b, r.length - 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//icm = new IndexColorModel(numOfBits, r.length, r, g, b);
|
|
||||||
icm = new InverseColorMapIndexColorModel(numOfBits, r.length, r, g, b);
|
icm = new InverseColorMapIndexColorModel(numOfBits, r.length, r, g, b);
|
||||||
}
|
}
|
||||||
return icm;
|
return icm;
|
||||||
@ -925,7 +926,7 @@ class IndexImage {
|
|||||||
* @see IndexColorModel
|
* @see IndexColorModel
|
||||||
*/
|
*/
|
||||||
public static BufferedImage getIndexedImage(BufferedImage pImage, int pNumberOfColors, Color pMatte, int pHints) {
|
public static BufferedImage getIndexedImage(BufferedImage pImage, int pNumberOfColors, Color pMatte, int pHints) {
|
||||||
// NOTE: We need to apply matte before creating colormodel, otherwise we
|
// NOTE: We need to apply matte before creating color model, otherwise we
|
||||||
// won't have colors for potential faded transitions
|
// won't have colors for potential faded transitions
|
||||||
IndexColorModel icm;
|
IndexColorModel icm;
|
||||||
|
|
||||||
@ -985,15 +986,16 @@ class IndexImage {
|
|||||||
final int width = pImage.getWidth();
|
final int width = pImage.getWidth();
|
||||||
final int height = pImage.getHeight();
|
final int height = pImage.getHeight();
|
||||||
|
|
||||||
// Support transparancy?
|
// Support transparency?
|
||||||
boolean transparency = isTransparent(pHints) && (pImage.getColorModel().getTransparency() != Transparency.OPAQUE) && (pColors.getTransparency() != Transparency.OPAQUE);
|
boolean transparency = isTransparent(pHints) && (pImage.getColorModel().getTransparency() != Transparency.OPAQUE) && (pColors.getTransparency() != Transparency.OPAQUE);
|
||||||
|
|
||||||
// Create image with solid background
|
// Create image with solid background
|
||||||
BufferedImage solid = pImage;
|
BufferedImage solid = pImage;
|
||||||
|
|
||||||
if (pMatte != null) {// transparency doesn't really matter
|
if (pMatte != null) { // transparency doesn't really matter
|
||||||
solid = createSolid(pImage, pMatte);
|
solid = createSolid(pImage, pMatte);
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferedImage indexed;
|
BufferedImage indexed;
|
||||||
|
|
||||||
// Support TYPE_BYTE_BINARY, but only for 2 bit images, as the default
|
// Support TYPE_BYTE_BINARY, but only for 2 bit images, as the default
|
||||||
@ -1044,12 +1046,12 @@ class IndexImage {
|
|||||||
finally {
|
finally {
|
||||||
g2d.dispose();
|
g2d.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transparency support, this approach seems lame, but it's the only
|
// Transparency support, this approach seems lame, but it's the only
|
||||||
// solution I've found until now (that actually works).
|
// solution I've found until now (that actually works).
|
||||||
// Got anything to do with isPremultiplied? Hmm...
|
|
||||||
if (transparency) {
|
if (transparency) {
|
||||||
// Re-apply the alpha-channel of the original image
|
// Re-apply the alpha-channel of the original image
|
||||||
applyAlpha(indexed, pImage);
|
applyAlpha(indexed, pImage);
|
||||||
@ -1183,14 +1185,14 @@ class IndexImage {
|
|||||||
* @param pAlpha the image containing the alpha
|
* @param pAlpha the image containing the alpha
|
||||||
*/
|
*/
|
||||||
private static void applyAlpha(BufferedImage pImage, BufferedImage pAlpha) {
|
private static void applyAlpha(BufferedImage pImage, BufferedImage pAlpha) {
|
||||||
// Apply alpha as transparancy, using threshold of 25%
|
// Apply alpha as transparency, using threshold of 25%
|
||||||
for (int y = 0; y < pAlpha.getHeight(); y++) {
|
for (int y = 0; y < pAlpha.getHeight(); y++) {
|
||||||
for (int x = 0; x < pAlpha.getWidth(); x++) {
|
for (int x = 0; x < pAlpha.getWidth(); x++) {
|
||||||
|
|
||||||
// Get alpha component of pixel, if less than 25% opaque
|
// Get alpha component of pixel, if less than 25% opaque
|
||||||
// (0x40 = 64 => 25% of 256), the pixel will be transparent
|
// (0x40 = 64 => 25% of 256), the pixel will be transparent
|
||||||
if (((pAlpha.getRGB(x, y) >> 24) & 0xFF) < 0x40) {
|
if (((pAlpha.getRGB(x, y) >> 24) & 0xFF) < 0x40) {
|
||||||
pImage.setRGB(x, y, 0x00FFFFFF);// 100% transparent
|
pImage.setRGB(x, y, 0x00FFFFFF); // 100% transparent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1200,7 +1202,6 @@ class IndexImage {
|
|||||||
* This class is also a command-line utility.
|
* This class is also a command-line utility.
|
||||||
*/
|
*/
|
||||||
public static void main(String pArgs[]) {
|
public static void main(String pArgs[]) {
|
||||||
|
|
||||||
// Defaults
|
// Defaults
|
||||||
int argIdx = 0;
|
int argIdx = 0;
|
||||||
int speedTest = -1;
|
int speedTest = -1;
|
||||||
@ -1237,14 +1238,13 @@ class IndexImage {
|
|||||||
speedTest = 10;
|
speedTest = 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if ((pArgs[argIdx].charAt(1) == 'w') || pArgs[argIdx].equals("--overwrite")) {
|
||||||
if ((pArgs[argIdx].charAt(1) == 'w') || pArgs[argIdx].equals("--overwrite")) {
|
|
||||||
overWrite = true;
|
overWrite = true;
|
||||||
argIdx++;
|
argIdx++;
|
||||||
}
|
}
|
||||||
else
|
else if ((pArgs[argIdx].charAt(1) == 'c') || pArgs[argIdx].equals("--colors")) {
|
||||||
if ((pArgs[argIdx].charAt(1) == 'c') || pArgs[argIdx].equals("--colors")) {
|
|
||||||
argIdx++;
|
argIdx++;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
numColors = Integer.parseInt(pArgs[argIdx++]);
|
numColors = Integer.parseInt(pArgs[argIdx++]);
|
||||||
}
|
}
|
||||||
@ -1253,34 +1253,28 @@ class IndexImage {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if ((pArgs[argIdx].charAt(1) == 'g') || pArgs[argIdx].equals("--grayscale")) {
|
||||||
if ((pArgs[argIdx].charAt(1) == 'g') || pArgs[argIdx].equals("--grayscale")) {
|
|
||||||
argIdx++;
|
argIdx++;
|
||||||
gray = true;
|
gray = true;
|
||||||
}
|
}
|
||||||
else
|
else if ((pArgs[argIdx].charAt(1) == 'm') || pArgs[argIdx].equals("--monochrome")) {
|
||||||
if ((pArgs[argIdx].charAt(1) == 'm') || pArgs[argIdx].equals("--monochrome")) {
|
|
||||||
argIdx++;
|
argIdx++;
|
||||||
numColors = 2;
|
numColors = 2;
|
||||||
monochrome = true;
|
monochrome = true;
|
||||||
}
|
}
|
||||||
else
|
else if ((pArgs[argIdx].charAt(1) == 'd') || pArgs[argIdx].equals("--dither")) {
|
||||||
if ((pArgs[argIdx].charAt(1) == 'd') || pArgs[argIdx].equals("--dither")) {
|
|
||||||
argIdx++;
|
argIdx++;
|
||||||
dither = pArgs[argIdx++];
|
dither = pArgs[argIdx++];
|
||||||
}
|
}
|
||||||
else
|
else if ((pArgs[argIdx].charAt(1) == 'p') || pArgs[argIdx].equals("--palette")) {
|
||||||
if ((pArgs[argIdx].charAt(1) == 'p') || pArgs[argIdx].equals("--palette")) {
|
|
||||||
argIdx++;
|
argIdx++;
|
||||||
paletteFileName = pArgs[argIdx++];
|
paletteFileName = pArgs[argIdx++];
|
||||||
}
|
}
|
||||||
else
|
else if ((pArgs[argIdx].charAt(1) == 'q') || pArgs[argIdx].equals("--quality")) {
|
||||||
if ((pArgs[argIdx].charAt(1) == 'q') || pArgs[argIdx].equals("--quality")) {
|
|
||||||
argIdx++;
|
argIdx++;
|
||||||
quality = pArgs[argIdx++];
|
quality = pArgs[argIdx++];
|
||||||
}
|
}
|
||||||
else
|
else if ((pArgs[argIdx].charAt(1) == 'b') || pArgs[argIdx].equals("--bgcolor")) {
|
||||||
if ((pArgs[argIdx].charAt(1) == 'b') || pArgs[argIdx].equals("--bgcolor")) {
|
|
||||||
argIdx++;
|
argIdx++;
|
||||||
try {
|
try {
|
||||||
background = StringUtil.toColor(pArgs[argIdx++]);
|
background = StringUtil.toColor(pArgs[argIdx++]);
|
||||||
@ -1290,18 +1284,15 @@ class IndexImage {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if ((pArgs[argIdx].charAt(1) == 't') || pArgs[argIdx].equals("--transparency")) {
|
||||||
if ((pArgs[argIdx].charAt(1) == 't') || pArgs[argIdx].equals("--transparency")) {
|
|
||||||
argIdx++;
|
argIdx++;
|
||||||
transparency = true;
|
transparency = true;
|
||||||
}
|
}
|
||||||
else
|
else if ((pArgs[argIdx].charAt(1) == 'f') || pArgs[argIdx].equals("--outputformat")) {
|
||||||
if ((pArgs[argIdx].charAt(1) == 'f') || pArgs[argIdx].equals("--outputformat")) {
|
|
||||||
argIdx++;
|
argIdx++;
|
||||||
format = StringUtil.toLowerCase(pArgs[argIdx++]);
|
format = StringUtil.toLowerCase(pArgs[argIdx++]);
|
||||||
}
|
}
|
||||||
else
|
else if ((pArgs[argIdx].charAt(1) == 'h') || pArgs[argIdx].equals("--help")) {
|
||||||
if ((pArgs[argIdx].charAt(1) == 'h') || pArgs[argIdx].equals("--help")) {
|
|
||||||
argIdx++;
|
argIdx++;
|
||||||
|
|
||||||
// Setting errArgs to true, to print usage
|
// Setting errArgs to true, to print usage
|
||||||
@ -1321,6 +1312,7 @@ class IndexImage {
|
|||||||
? ", "
|
? ", "
|
||||||
: "\n"));
|
: "\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
System.err.print("Output format names: ");
|
System.err.print("Output format names: ");
|
||||||
String[] writers = ImageIO.getWriterFormatNames();
|
String[] writers = ImageIO.getWriterFormatNames();
|
||||||
|
|
||||||
@ -1333,7 +1325,7 @@ class IndexImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read in image
|
// Read in image
|
||||||
java.io.File in = new java.io.File(pArgs[argIdx++]);
|
File in = new File(pArgs[argIdx++]);
|
||||||
|
|
||||||
if (!in.exists()) {
|
if (!in.exists()) {
|
||||||
System.err.println("File \"" + in.getAbsolutePath() + "\" does not exist!");
|
System.err.println("File \"" + in.getAbsolutePath() + "\" does not exist!");
|
||||||
@ -1341,10 +1333,10 @@ class IndexImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read palette if needed
|
// Read palette if needed
|
||||||
java.io.File paletteFile = null;
|
File paletteFile = null;
|
||||||
|
|
||||||
if (paletteFileName != null) {
|
if (paletteFileName != null) {
|
||||||
paletteFile = new java.io.File(paletteFileName);
|
paletteFile = new File(paletteFileName);
|
||||||
if (!paletteFile.exists()) {
|
if (!paletteFile.exists()) {
|
||||||
System.err.println("File \"" + in.getAbsolutePath() + "\" does not exist!");
|
System.err.println("File \"" + in.getAbsolutePath() + "\" does not exist!");
|
||||||
System.exit(5);
|
System.exit(5);
|
||||||
@ -1352,10 +1344,10 @@ class IndexImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we can write
|
// Make sure we can write
|
||||||
java.io.File out;
|
File out;
|
||||||
|
|
||||||
if (argIdx < pArgs.length) {
|
if (argIdx < pArgs.length) {
|
||||||
out = new java.io.File(pArgs[argIdx/*++*/]);
|
out = new File(pArgs[argIdx/*++*/]);
|
||||||
|
|
||||||
// Get format from file extension
|
// Get format from file extension
|
||||||
if (format == null) {
|
if (format == null) {
|
||||||
@ -1363,7 +1355,6 @@ class IndexImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// Create new file in current dir, same name + format extension
|
// Create new file in current dir, same name + format extension
|
||||||
String baseName = FileUtil.getBasename(in);
|
String baseName = FileUtil.getBasename(in);
|
||||||
|
|
||||||
@ -1371,8 +1362,9 @@ class IndexImage {
|
|||||||
if (format == null) {
|
if (format == null) {
|
||||||
format = "png";
|
format = "png";
|
||||||
}
|
}
|
||||||
out = new java.io.File(baseName + '.' + format);
|
out = new File(baseName + '.' + format);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!overWrite && out.exists()) {
|
if (!overWrite && out.exists()) {
|
||||||
System.err.println("The file \"" + out.getAbsolutePath() + "\" allready exists!");
|
System.err.println("The file \"" + out.getAbsolutePath() + "\" allready exists!");
|
||||||
System.exit(5);
|
System.exit(5);
|
||||||
@ -1396,7 +1388,7 @@ class IndexImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (java.io.IOException ioe) {
|
catch (IOException ioe) {
|
||||||
ioe.printStackTrace(System.err);
|
ioe.printStackTrace(System.err);
|
||||||
System.exit(5);
|
System.exit(5);
|
||||||
}
|
}
|
||||||
@ -1441,16 +1433,14 @@ class IndexImage {
|
|||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// Index
|
// Index
|
||||||
long start = 0;
|
long start = 0;
|
||||||
long end;
|
|
||||||
|
|
||||||
if (speedTest > 0) {
|
if (speedTest > 0) {
|
||||||
|
|
||||||
// SPEED TESTING
|
// SPEED TESTING
|
||||||
System.out.println("Measuring speed!");
|
System.out.println("Measuring speed!");
|
||||||
start = System.currentTimeMillis();
|
start = System.currentTimeMillis();
|
||||||
|
|
||||||
// END SPEED TESTING
|
// END SPEED TESTING
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferedImage indexed;
|
BufferedImage indexed;
|
||||||
IndexColorModel colors;
|
IndexColorModel colors;
|
||||||
|
|
||||||
@ -1459,7 +1449,6 @@ class IndexImage {
|
|||||||
colors = MonochromeColorModel.getInstance();
|
colors = MonochromeColorModel.getInstance();
|
||||||
}
|
}
|
||||||
else if (gray) {
|
else if (gray) {
|
||||||
|
|
||||||
//indexed = ImageUtil.toBuffered(ImageUtil.grayscale(image), BufferedImage.TYPE_BYTE_GRAY);
|
//indexed = ImageUtil.toBuffered(ImageUtil.grayscale(image), BufferedImage.TYPE_BYTE_GRAY);
|
||||||
image = ImageUtil.toBuffered(ImageUtil.grayscale(image));
|
image = ImageUtil.toBuffered(ImageUtil.grayscale(image));
|
||||||
indexed = getIndexedImage(image, colors = getIndexColorModel(image, numColors, hints), background, hints);
|
indexed = getIndexedImage(image, colors = getIndexColorModel(image, numColors, hints), background, hints);
|
||||||
@ -1470,7 +1459,6 @@ class IndexImage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (paletteImg != null) {
|
else if (paletteImg != null) {
|
||||||
|
|
||||||
// Get palette from image
|
// Get palette from image
|
||||||
indexed = getIndexedImage(ImageUtil.toBuffered(image, BufferedImage.TYPE_INT_ARGB),
|
indexed = getIndexedImage(ImageUtil.toBuffered(image, BufferedImage.TYPE_INT_ARGB),
|
||||||
colors = getIndexColorModel(paletteImg, numColors, hints), background, hints);
|
colors = getIndexColorModel(paletteImg, numColors, hints), background, hints);
|
||||||
@ -1479,12 +1467,10 @@ class IndexImage {
|
|||||||
image = ImageUtil.toBuffered(image, BufferedImage.TYPE_INT_ARGB);
|
image = ImageUtil.toBuffered(image, BufferedImage.TYPE_INT_ARGB);
|
||||||
indexed = getIndexedImage(image, colors = getIndexColorModel(image, numColors, hints), background, hints);
|
indexed = getIndexedImage(image, colors = getIndexColorModel(image, numColors, hints), background, hints);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (speedTest > 0) {
|
if (speedTest > 0) {
|
||||||
|
|
||||||
// SPEED TESTING
|
// SPEED TESTING
|
||||||
end = System.currentTimeMillis();
|
System.out.println("Color selection + dither: " + (System.currentTimeMillis() - start) + " ms");
|
||||||
System.out.println("Color selection + dither: " + (end - start) + " ms");
|
|
||||||
|
|
||||||
// END SPEED TESTING
|
// END SPEED TESTING
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1494,11 +1480,11 @@ class IndexImage {
|
|||||||
System.err.println("No writer for format: \"" + format + "\"!");
|
System.err.println("No writer for format: \"" + format + "\"!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (java.io.IOException ioe) {
|
catch (IOException ioe) {
|
||||||
ioe.printStackTrace(System.err);
|
ioe.printStackTrace(System.err);
|
||||||
}
|
}
|
||||||
if (speedTest > 0) {
|
|
||||||
|
|
||||||
|
if (speedTest > 0) {
|
||||||
// SPEED TESTING
|
// SPEED TESTING
|
||||||
System.out.println("Measuring speed!");
|
System.out.println("Measuring speed!");
|
||||||
|
|
||||||
@ -1513,17 +1499,16 @@ class IndexImage {
|
|||||||
for (int i = 0; i < speedTest; i++) {
|
for (int i = 0; i < speedTest; i++) {
|
||||||
start = System.currentTimeMillis();
|
start = System.currentTimeMillis();
|
||||||
getIndexedImage(image, colors, background, hints);
|
getIndexedImage(image, colors, background, hints);
|
||||||
end = System.currentTimeMillis();
|
time += (System.currentTimeMillis() - start);
|
||||||
time += (end - start);
|
|
||||||
System.out.print('.');
|
System.out.print('.');
|
||||||
if ((i + 1) % 10 == 0) {
|
if ((i + 1) % 10 == 0) {
|
||||||
System.out.println("\nAverage (after " + (i + 1) + " iterations): " + (time / (i + 1)) + "ms");
|
System.out.println("\nAverage (after " + (i + 1) + " iterations): " + (time / (i + 1)) + "ms");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("\nDither only:");
|
System.out.println("\nDither only:");
|
||||||
System.out.println("Total time (" + speedTest + " invocations): " + time + "ms");
|
System.out.println("Total time (" + speedTest + " invocations): " + time + "ms");
|
||||||
System.out.println("Average: " + time / speedTest + "ms");
|
System.out.println("Average: " + time / speedTest + "ms");
|
||||||
|
|
||||||
// END SPEED TESTING
|
// END SPEED TESTING
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ import java.io.ByteArrayInputStream;
|
|||||||
* <p/>
|
* <p/>
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @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/io/FastByteArrayOutputStream.java#2 $
|
* @version $Id: FastByteArrayOutputStream.java#2 $
|
||||||
*/
|
*/
|
||||||
// TODO: Performance test of a stream impl that uses list of fixed size blocks, rather than contiguous block
|
// TODO: Performance test of a stream impl that uses list of fixed size blocks, rather than contiguous block
|
||||||
public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
||||||
@ -78,23 +78,24 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
|||||||
else if (pLength == 0) {
|
else if (pLength == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int newcount = count + pLength;
|
|
||||||
growIfNeeded(newcount);
|
int newCount = count + pLength;
|
||||||
|
growIfNeeded(newCount);
|
||||||
System.arraycopy(pBytes, pOffset, buf, count, pLength);
|
System.arraycopy(pBytes, pOffset, buf, count, pLength);
|
||||||
count = newcount;
|
count = newCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized void write(int pByte) {
|
public synchronized void write(int pByte) {
|
||||||
int newcount = count + 1;
|
int newCount = count + 1;
|
||||||
growIfNeeded(newcount);
|
growIfNeeded(newCount);
|
||||||
buf[count] = (byte) pByte;
|
buf[count] = (byte) pByte;
|
||||||
count = newcount;
|
count = newCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void growIfNeeded(int pNewcount) {
|
private void growIfNeeded(int pNewCount) {
|
||||||
if (pNewcount > buf.length) {
|
if (pNewCount > buf.length) {
|
||||||
int newSize = Math.max(Math.min(buf.length << 1, buf.length + maxGrowSize), pNewcount);
|
int newSize = Math.max(Math.min(buf.length << 1, buf.length + maxGrowSize), pNewCount);
|
||||||
byte newBuf[] = new byte[newSize];
|
byte newBuf[] = new byte[newSize];
|
||||||
System.arraycopy(buf, 0, newBuf, 0, count);
|
System.arraycopy(buf, 0, newBuf, 0, count);
|
||||||
buf = newBuf;
|
buf = newBuf;
|
||||||
@ -110,9 +111,10 @@ public final class FastByteArrayOutputStream extends ByteArrayOutputStream {
|
|||||||
// Non-synchronized version of toByteArray
|
// Non-synchronized version of toByteArray
|
||||||
@Override
|
@Override
|
||||||
public byte[] toByteArray() {
|
public byte[] toByteArray() {
|
||||||
byte newbuf[] = new byte[count];
|
byte newBuf[] = new byte[count];
|
||||||
System.arraycopy(buf, 0, newbuf, 0, count);
|
System.arraycopy(buf, 0, newBuf, 0, count);
|
||||||
return newbuf;
|
|
||||||
|
return newBuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,7 +38,7 @@ import java.io.InputStreamReader;
|
|||||||
* <p/>
|
* <p/>
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
* @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/io/FileSystem.java#1 $
|
* @version $Id: FileSystem.java#1 $
|
||||||
*/
|
*/
|
||||||
abstract class FileSystem {
|
abstract class FileSystem {
|
||||||
abstract long getFreeSpace(File pPath);
|
abstract long getFreeSpace(File pPath);
|
||||||
@ -57,21 +57,21 @@ abstract class FileSystem {
|
|||||||
//System.out.println("os = " + os);
|
//System.out.println("os = " + os);
|
||||||
|
|
||||||
os = os.toLowerCase();
|
os = os.toLowerCase();
|
||||||
if (os.indexOf("windows") != -1) {
|
if (os.contains("windows")) {
|
||||||
return new Win32FileSystem();
|
return new Win32FileSystem();
|
||||||
}
|
}
|
||||||
else if (os.indexOf("linux") != -1 ||
|
else if (os.contains("linux") ||
|
||||||
os.indexOf("sun os") != -1 ||
|
os.contains("sun os") ||
|
||||||
os.indexOf("sunos") != -1 ||
|
os.contains("sunos") ||
|
||||||
os.indexOf("solaris") != -1 ||
|
os.contains("solaris") ||
|
||||||
os.indexOf("mpe/ix") != -1 ||
|
os.contains("mpe/ix") ||
|
||||||
os.indexOf("hp-ux") != -1 ||
|
os.contains("hp-ux") ||
|
||||||
os.indexOf("aix") != -1 ||
|
os.contains("aix") ||
|
||||||
os.indexOf("freebsd") != -1 ||
|
os.contains("freebsd") ||
|
||||||
os.indexOf("irix") != -1 ||
|
os.contains("irix") ||
|
||||||
os.indexOf("digital unix") != -1 ||
|
os.contains("digital unix") ||
|
||||||
os.indexOf("unix") != -1 ||
|
os.contains("unix") ||
|
||||||
os.indexOf("mac os x") != -1) {
|
os.contains("mac os x")) {
|
||||||
return new UnixFileSystem();
|
return new UnixFileSystem();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -186,6 +186,7 @@ public final class FileUtil {
|
|||||||
if (!pOverWrite && pToFile.exists()) {
|
if (!pOverWrite && pToFile.exists()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
OutputStream out = null;
|
OutputStream out = null;
|
||||||
|
|
||||||
@ -202,6 +203,7 @@ public final class FileUtil {
|
|||||||
close(in);
|
close(in);
|
||||||
close(out);
|
close(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true; // If we got here, everything's probably okay.. ;-)
|
return true; // If we got here, everything's probably okay.. ;-)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,6 +309,8 @@ public final class FileUtil {
|
|||||||
Validate.notNull(pFrom, "from");
|
Validate.notNull(pFrom, "from");
|
||||||
Validate.notNull(pTo, "to");
|
Validate.notNull(pTo, "to");
|
||||||
|
|
||||||
|
// TODO: Consider using file channels for faster copy where possible
|
||||||
|
|
||||||
// Use buffer size two times byte array, to avoid i/o bottleneck
|
// Use buffer size two times byte array, to avoid i/o bottleneck
|
||||||
// TODO: Consider letting the client decide as this is sometimes not a good thing!
|
// TODO: Consider letting the client decide as this is sometimes not a good thing!
|
||||||
InputStream in = new BufferedInputStream(pFrom, BUF_SIZE * 2);
|
InputStream in = new BufferedInputStream(pFrom, BUF_SIZE * 2);
|
||||||
@ -322,31 +326,9 @@ public final class FileUtil {
|
|||||||
// Flush out stream, to write any remaining buffered data
|
// Flush out stream, to write any remaining buffered data
|
||||||
out.flush();
|
out.flush();
|
||||||
|
|
||||||
return true; // If we got here, everything's probably okay.. ;-)
|
return true; // If we got here, everything is probably okay.. ;-)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// Consider using the example from
|
|
||||||
// http://developer.java.sun.com/developer/Books/performance/ch04.pdf
|
|
||||||
// Test if this is really faster. And what about a lot of concurrence?
|
|
||||||
// Have a pool of buffers? :-)
|
|
||||||
|
|
||||||
static final int BUFF_SIZE = 100000;
|
|
||||||
static final byte[] buffer = new byte[BUFF_SIZE];
|
|
||||||
|
|
||||||
public static void copy(InputStream in, OutputStream out) throws IOException {
|
|
||||||
while (true) {
|
|
||||||
synchronized (buffer) {
|
|
||||||
int amountRead = in.read(buffer);
|
|
||||||
if (amountRead == -1) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
out.write(buffer, 0, amountRead);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the file (type) extension of the given file.
|
* Gets the file (type) extension of the given file.
|
||||||
* A file extension is the part of the filename, after the last occurence
|
* A file extension is the part of the filename, after the last occurence
|
||||||
|
Loading…
x
Reference in New Issue
Block a user