mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-06 04:55:30 -04:00
CR2ImageReader: unslice result of JPEGLosslessDecoder.
This commit is contained in:
parent
7692eeef5e
commit
5c35c6e997
@ -36,6 +36,8 @@ import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegment;
|
|||||||
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
import com.twelvemonkeys.imageio.metadata.jpeg.JPEGSegmentUtil;
|
||||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFF;
|
||||||
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
import com.twelvemonkeys.imageio.metadata.tiff.TIFFReader;
|
||||||
|
import com.twelvemonkeys.imageio.plugins.jpeg.Slice;
|
||||||
|
import com.twelvemonkeys.imageio.plugins.jpeg.SliceContext;
|
||||||
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
import com.twelvemonkeys.imageio.stream.SubImageInputStream;
|
||||||
|
|
||||||
import javax.imageio.IIOException;
|
import javax.imageio.IIOException;
|
||||||
@ -432,17 +434,20 @@ public final class CR2ImageReader extends ImageReaderBase {
|
|||||||
int stripByteCounts = getValueAsInt(TIFF.TAG_STRIP_BYTE_COUNTS, "StripByteCounts");
|
int stripByteCounts = getValueAsInt(TIFF.TAG_STRIP_BYTE_COUNTS, "StripByteCounts");
|
||||||
long[] slices = getValueAsLongArray(50752, "Slices", true);
|
long[] slices = getValueAsLongArray(50752, "Slices", true);
|
||||||
|
|
||||||
// Format of this array, is slices[0] = N, slices[1] = slice0.width ... slices[N + 1] = sliceN.width
|
try {
|
||||||
if (slices[0] != slices.length - 2) {
|
final Slice slice = Slice.createSlice(slices);
|
||||||
throw new IIOException("Unexpected slices array: " + Arrays.toString(slices));
|
SliceContext.set(slice);
|
||||||
|
|
||||||
|
// TODO: Get correct dimensions (sensor size?)
|
||||||
|
int width = getWidth(0);
|
||||||
|
int height = getHeight(0);
|
||||||
|
|
||||||
|
imageInput.seek(stripOffsets);
|
||||||
|
return ImageIO.read(new SubImageInputStream(imageInput, stripByteCounts));
|
||||||
|
} finally {
|
||||||
|
SliceContext.remove();
|
||||||
}
|
}
|
||||||
// TODO: We really have multiple slices...
|
|
||||||
|
|
||||||
// TODO: Get correct dimensions (sensor size?)
|
|
||||||
int width = getWidth(0);
|
|
||||||
int height = getHeight(0);
|
|
||||||
|
|
||||||
imageInput.seek(stripOffsets);
|
|
||||||
// byte[] data = new LosslessJPEGDecoder().decompress(new SubImageInputStream(imageInput, stripByteCounts), null);
|
// byte[] data = new LosslessJPEGDecoder().decompress(new SubImageInputStream(imageInput, stripByteCounts), null);
|
||||||
//
|
//
|
||||||
// // TODO: We really have 2 bytes/sample
|
// // TODO: We really have 2 bytes/sample
|
||||||
@ -477,7 +482,7 @@ public final class CR2ImageReader extends ImageReaderBase {
|
|||||||
for (int i = 0; i < numImages; i++) {
|
for (int i = 0; i < numImages; i++) {
|
||||||
int numThumbnails = reader.getNumThumbnails(i);
|
int numThumbnails = reader.getNumThumbnails(i);
|
||||||
for (int n = 0; n < numThumbnails; n++) {
|
for (int n = 0; n < numThumbnails; n++) {
|
||||||
showIt(reader.readThumbnail(i, n), arg + " image thumbnail" + n);
|
showIt(reader.readThumbnail(i, n), arg + " image " + i + " thumbnail " + n);
|
||||||
}
|
}
|
||||||
|
|
||||||
showIt(reader.read(i), arg + " image " + i);
|
showIt(reader.read(i), arg + " image " + i);
|
||||||
|
@ -86,6 +86,22 @@ final class JPEGLosslessDecoderWrapper {
|
|||||||
int width = decoder.getDimX();
|
int width = decoder.getDimX();
|
||||||
int height = decoder.getDimY();
|
int height = decoder.getDimY();
|
||||||
|
|
||||||
|
if (SliceContext.isPresent()) { //QnD
|
||||||
|
final int[][] unsliced = new int[1][];
|
||||||
|
final int componentCount = decoder.getNumComponents();
|
||||||
|
final Slice slice = SliceContext.get();
|
||||||
|
unsliced[0] = slice.unslice(decoded, componentCount, height);
|
||||||
|
switch (decoder.getPrecision()) {
|
||||||
|
case 8:
|
||||||
|
return to8Bit1ComponentGrayScale(unsliced, width * componentCount, height);
|
||||||
|
case 10:
|
||||||
|
case 12:
|
||||||
|
case 14:
|
||||||
|
case 16:
|
||||||
|
return to16Bit1ComponentGrayScale(unsliced, decoder.getPrecision(), width * componentCount, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Single component, assumed to be Gray
|
// Single component, assumed to be Gray
|
||||||
if (decoder.getNumComponents() == 1) {
|
if (decoder.getNumComponents() == 1) {
|
||||||
switch (decoder.getPrecision()) {
|
switch (decoder.getPrecision()) {
|
||||||
|
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Oleg Ermolaev
|
||||||
|
* 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.imageio.plugins.jpeg;
|
||||||
|
|
||||||
|
import javax.imageio.IIOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For CR2 RAW image.
|
||||||
|
*
|
||||||
|
* @author Oleg Ermolaev Date: 05.05.2018 2:04
|
||||||
|
*/
|
||||||
|
public class Slice {
|
||||||
|
public static final int FIRST_WIDTH_COUNT_INDEX = 0;
|
||||||
|
public static final int FIRST_WIDTH_INDEX = 1;
|
||||||
|
public static final int LAST_WIDTH_INDEX = 2;
|
||||||
|
|
||||||
|
private final int firstWidthCount;
|
||||||
|
private final int firstWidth;
|
||||||
|
private final int lastWidth;
|
||||||
|
|
||||||
|
public Slice(int firstWidthCount, int firstWidth, int lastWidth) {
|
||||||
|
this.firstWidthCount = firstWidthCount;
|
||||||
|
this.firstWidth = firstWidth;
|
||||||
|
this.lastWidth = lastWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Slice createSlice(long[] values) throws IIOException {
|
||||||
|
if (values == null || values.length != 3) {
|
||||||
|
throw new IIOException("Unexpected slices array: " + Arrays.toString(values));
|
||||||
|
}
|
||||||
|
final long firstWidthCount = values[FIRST_WIDTH_COUNT_INDEX];
|
||||||
|
final long firstWidth = values[FIRST_WIDTH_INDEX];
|
||||||
|
final long lastWidth = values[LAST_WIDTH_INDEX];
|
||||||
|
if (!(0 < firstWidthCount && firstWidthCount <= Integer.MAX_VALUE) ||
|
||||||
|
!(0 < firstWidth && firstWidth <= Integer.MAX_VALUE) ||
|
||||||
|
!(0 < lastWidth && lastWidth <= Integer.MAX_VALUE) ||
|
||||||
|
firstWidthCount * firstWidth + lastWidth > Integer.MAX_VALUE) {
|
||||||
|
throw new IIOException("Unexpected slices array: " + Arrays.toString(values));
|
||||||
|
}
|
||||||
|
return new Slice((int) firstWidthCount, (int) firstWidth, (int) lastWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFirstWidthCount() {
|
||||||
|
return firstWidthCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFirstWidth() {
|
||||||
|
return firstWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getLastWidth() {
|
||||||
|
return lastWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getWidth() {
|
||||||
|
return firstWidthCount * firstWidth + lastWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] unslice(int[][] data, int componentCount, int height) throws IIOException {
|
||||||
|
final int width = getWidth();
|
||||||
|
final int[] result = new int[width * height];
|
||||||
|
|
||||||
|
for (int componentIndex = 0; componentIndex < componentCount; componentIndex++) {
|
||||||
|
if (result.length != data[componentIndex].length * componentCount) {
|
||||||
|
throw new IIOException(String.format("Invalid array size for component #%d", componentIndex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int position = 0;
|
||||||
|
int currentWidth = firstWidth / componentCount;
|
||||||
|
for (int sliceIndex = 0; sliceIndex < firstWidthCount + 1; ++sliceIndex) {
|
||||||
|
if (sliceIndex == firstWidthCount) {
|
||||||
|
currentWidth = lastWidth / componentCount;
|
||||||
|
}
|
||||||
|
final int sliceOffset = sliceIndex * firstWidth;
|
||||||
|
for (int y = 0; y < height; ++y) {
|
||||||
|
final int yOffset = y * width;
|
||||||
|
for (int x = 0; x < currentWidth; ++x) {
|
||||||
|
final int xOffset = x * componentCount;
|
||||||
|
for (int componentIndex = 0; componentIndex < componentCount; componentIndex++) {
|
||||||
|
result[sliceOffset + yOffset + xOffset + componentIndex] = data[componentIndex][position];
|
||||||
|
}
|
||||||
|
position++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2018, Oleg Ermolaev
|
||||||
|
* 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.imageio.plugins.jpeg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* QnD
|
||||||
|
*
|
||||||
|
* @author Oleg Ermolaev Date: 05.05.2018 2:13
|
||||||
|
*/
|
||||||
|
public class SliceContext {
|
||||||
|
private static final ThreadLocal<Slice> CONTEXT = new ThreadLocal<>();
|
||||||
|
|
||||||
|
public static boolean isPresent() {
|
||||||
|
return get() != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Slice get() {
|
||||||
|
return CONTEXT.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void set(Slice slice) {
|
||||||
|
CONTEXT.set(slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void remove() {
|
||||||
|
CONTEXT.remove();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user