mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-10-04 19:34:48 -04:00
#304 TIFF JPEG Lossless support
This commit is contained in:
@@ -148,7 +148,7 @@ class JPEGImage10Metadata extends AbstractMetadata {
|
||||
if (segment instanceof Frame) {
|
||||
Frame sofSegment = (Frame) segment;
|
||||
IIOMetadataNode colorSpaceType = new IIOMetadataNode("ColorSpaceType");
|
||||
colorSpaceType.setAttribute("name", sofSegment.componentsInFrame() == 1 ? "Gray" : "RGB"); // TODO YCC, YCCK, CMYK etc
|
||||
colorSpaceType.setAttribute("name", sofSegment.componentsInFrame() == 1 ? "GRAY" : "RGB"); // TODO YCC, YCCK, CMYK etc
|
||||
chroma.appendChild(colorSpaceType);
|
||||
|
||||
IIOMetadataNode numChannels = new IIOMetadataNode("NumChannels");
|
||||
|
@@ -352,10 +352,24 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
JPEGColorSpace sourceCSType = getSourceCSType(getJFIF(), adobeDCT, sof);
|
||||
|
||||
if (sof.marker == JPEG.SOF3) {
|
||||
// Read image as lossless
|
||||
if (DEBUG) {
|
||||
System.out.println("Reading using Lossless decoder");
|
||||
}
|
||||
|
||||
// TODO: What about stream position?
|
||||
// TODO: Param handling: Source region, offset, subsampling, destination, destination type, etc....
|
||||
// Read image as lossless
|
||||
return new JPEGLosslessDecoderWrapper(this).readImage(segments, imageInput);
|
||||
BufferedImage bufferedImage = new JPEGLosslessDecoderWrapper(this).readImage(segments, imageInput);
|
||||
|
||||
// TODO: This is QnD, move param handling to lossless wrapper
|
||||
// TODO: Create test!
|
||||
BufferedImage destination = param != null ? param.getDestination() : null;
|
||||
if (destination != null) {
|
||||
destination.getRaster().setDataElements(0, 0, bufferedImage.getRaster());
|
||||
return destination;
|
||||
}
|
||||
|
||||
return bufferedImage;
|
||||
}
|
||||
|
||||
// We need to apply ICC profile unless the profile is sRGB/default gray (whatever that is)
|
||||
@@ -382,6 +396,18 @@ public final class JPEGImageReader extends ImageReaderBase {
|
||||
return delegate.read(imageIndex, param);
|
||||
}
|
||||
|
||||
static void drawOnto(final BufferedImage pDestination, final Image pSource) {
|
||||
Graphics2D g = pDestination.createGraphics();
|
||||
try {
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
g.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_DISABLE);
|
||||
g.drawImage(pSource, 0, 0, null);
|
||||
}
|
||||
finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private BufferedImage readImageAsRasterAndReplaceColorProfile(int imageIndex, ImageReadParam param, Frame startOfFrame, JPEGColorSpace csType, ICC_Profile profile) throws IOException {
|
||||
int origWidth = getWidth(imageIndex);
|
||||
int origHeight = getHeight(imageIndex);
|
||||
|
@@ -33,10 +33,9 @@ import com.twelvemonkeys.imageio.stream.BufferedImageInputStream;
|
||||
|
||||
import javax.imageio.IIOException;
|
||||
import javax.imageio.stream.ImageInputStream;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBufferByte;
|
||||
import java.awt.image.DataBufferUShort;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.*;
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.*;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
@@ -71,7 +70,7 @@ final class JPEGLosslessDecoderWrapper {
|
||||
* - 16Bit, Grayscale -> BufferedImage.TYPE_USHORT_GRAY
|
||||
*
|
||||
* @param segments segments
|
||||
* @param input input stream which contains a jpeg lossless data
|
||||
* @param input input stream which contains JPEG Lossless data
|
||||
* @return if successfully a BufferedImage is returned
|
||||
* @throws IOException is thrown if the decoder failed or a conversion is not supported
|
||||
*/
|
||||
@@ -92,8 +91,11 @@ final class JPEGLosslessDecoderWrapper {
|
||||
switch (decoder.getPrecision()) {
|
||||
case 8:
|
||||
return to8Bit1ComponentGrayScale(decoded, width, height);
|
||||
case 10:
|
||||
case 12:
|
||||
case 14:
|
||||
case 16:
|
||||
return to16Bit1ComponentGrayScale(decoded, width, height);
|
||||
return to16Bit1ComponentGrayScale(decoded, decoder.getPrecision(), width, height);
|
||||
}
|
||||
}
|
||||
// 3 components, assumed to be RGB
|
||||
@@ -121,12 +123,20 @@ final class JPEGLosslessDecoderWrapper {
|
||||
* precision: 16 bit, componentCount = 1
|
||||
*
|
||||
* @param decoded data buffer
|
||||
* @param precision
|
||||
* @param width of the image
|
||||
* @param height of the image
|
||||
* @return a BufferedImage.TYPE_USHORT_GRAY
|
||||
* @param height of the image @return a BufferedImage.TYPE_USHORT_GRAY
|
||||
*/
|
||||
private BufferedImage to16Bit1ComponentGrayScale(int[][] decoded, int width, int height) {
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_USHORT_GRAY);
|
||||
private BufferedImage to16Bit1ComponentGrayScale(int[][] decoded, int precision, int width, int height) {
|
||||
BufferedImage image;
|
||||
if (precision == 16) {
|
||||
image = new BufferedImage(width, height, BufferedImage.TYPE_USHORT_GRAY);
|
||||
}
|
||||
else {
|
||||
ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_GRAY), new int[] {precision}, false, false, Transparency.OPAQUE, DataBuffer.TYPE_USHORT);
|
||||
image = new BufferedImage(colorModel, colorModel.createCompatibleWritableRaster(width, height), colorModel.isAlphaPremultiplied(), null);
|
||||
}
|
||||
|
||||
short[] imageBuffer = ((DataBufferUShort) image.getRaster().getDataBuffer()).getData();
|
||||
|
||||
for (int i = 0; i < imageBuffer.length; i++) {
|
||||
|
Reference in New Issue
Block a user