Skip to content

Commit

Permalink
Issue jai-imageio#72: Very slow writing of simple 16/32-bit gray-scal…
Browse files Browse the repository at this point in the history
…e TIFF images

Send the DataBuffer to the TIFFCompressor, as that knows the stream
and therefore its byte order, so it can serialize it and then send it to
the original encode(..) method.
  • Loading branch information
amscins committed Jan 28, 2021
1 parent 88f30ba commit 724cf66
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1780,14 +1780,11 @@ private int writeTile(Rectangle tileRect, TIFFCompressor compressor)
return compressor.encode(buf, 0,
width, height, sampleSize,
(tileRect.width + 7)/8);
} else if(bitDepth == 8 &&
sm.getDataType() == DataBuffer.TYPE_BYTE) {
} else if(bitDepth == DataBuffer.getDataTypeSize(sm.getDataType())) {

ComponentSampleModel csm =
(ComponentSampleModel)raster.getSampleModel();

byte[] buf =
((DataBufferByte)raster.getDataBuffer()).getData();

int off =
csm.getOffset(minX -
raster.getSampleModelTranslateX(),
Expand All @@ -1798,7 +1795,7 @@ private int writeTile(Rectangle tileRect, TIFFCompressor compressor)
System.out.println("Optimized component case");
}

return compressor.encode(buf, off,
return compressor.encode(raster.getDataBuffer(), off,
width, height, sampleSize,
csm.getScanlineStride());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@
import javax.imageio.ImageWriter;
import javax.imageio.metadata.IIOMetadata;
import javax.imageio.stream.ImageOutputStream;
import java.awt.image.*;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ShortBuffer;

import com.github.jaiimageio.impl.plugins.tiff.TIFFImageWriter;

Expand Down Expand Up @@ -278,7 +283,83 @@ public abstract int encode(byte[] b, int off,
int width, int height,
int[] bitsPerSample,
int scanlineStride) throws IOException;


/**
* Encodes the supplied image data, writing to the currently set
* <code>ImageOutputStream</code>.
*
* @param dataBuffer an DataBuffer with pixels
* @param off the starting offset of the data to be written in the
* array <code>b</code>.
* @param width the width of the rectangle of pixels to be written.
* @param height the height of the rectangle of pixels to be written.
* @param bitsPerSample an array of <code>int</code>s indicting
* the number of bits used to represent each image sample within
* a pixel.
* @param scanlineStride the number of bytes separating each
* row of the input data.
*
* @return the number of bytes written.
*
* @throws IOException if the supplied data cannot be encoded by
* this <code>TIFFCompressor</code>, or if any I/O error occurs
* during writing.
*/
private byte[] currentTile = null;
public int encode(DataBuffer dataBuffer, int off,
int width, int height,
int[] bitsPerSample,
int scanlineStride) throws IOException {
final int dataType = dataBuffer.getDataType();
if (dataType == DataBuffer.TYPE_BYTE) {
return encode(((DataBufferByte) dataBuffer).getData(), off, width, height, bitsPerSample, scanlineStride);
}
final int dataTypeSize = DataBuffer.getDataTypeSize(dataType) / Byte.SIZE;
int tileSize = width * height * dataTypeSize;
if (currentTile == null || currentTile.length < tileSize)
currentTile = new byte[tileSize];
final ByteBuffer buffer = ByteBuffer.wrap(currentTile).order(stream.getByteOrder());
switch (dataType) {
case DataBuffer.TYPE_USHORT: {
ShortBuffer sb = buffer.asShortBuffer();
short[] shorts = ((DataBufferUShort) dataBuffer).getData();
for (int i = 0; i < height; i++) {
sb.put(shorts, off, width);
off += scanlineStride;
}
break;
}
case DataBuffer.TYPE_SHORT: {
ShortBuffer sb = buffer.asShortBuffer();
short[] shorts = ((DataBufferShort) dataBuffer).getData();
for (int i = 0; i < height; i++) {
sb.put(shorts, off, width);
off += scanlineStride;
}
break;
}
case DataBuffer.TYPE_INT: {
IntBuffer ib = buffer.asIntBuffer();
int[] ints = ((DataBufferInt) dataBuffer).getData();
for (int i = 0; i < height; i++) {
ib.put(ints, off, width);
off += scanlineStride;
}
break;
}
case DataBuffer.TYPE_FLOAT: {
FloatBuffer fb = buffer.asFloatBuffer();
float[] floats = ((DataBufferFloat) dataBuffer).getData();
for (int i = 0; i < height; i++) {
fb.put(floats, off, width);
off += scanlineStride;
}
break;
}
}
return encode(currentTile, 0, width, height, bitsPerSample, width * dataTypeSize);
}

/**
* Allows any resources held by this object to be released. The
* result of calling any other method (other than
Expand Down

0 comments on commit 724cf66

Please sign in to comment.