mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2026-05-01 00:00:02 -04:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ffd4731334 | |||
| 7c53c5b7b5 | |||
| c9cfe04dc9 | |||
| 9da25168ee | |||
| b0c928d278 | |||
| e221c7374b | |||
| 258a6cf4f4 | |||
| ab5cbb15ed | |||
| 02d65481c5 | |||
| 081c65b314 | |||
| 7a78d398c3 | |||
| 493c304722 | |||
| 8d62d74860 | |||
| d51ac8cb83 | |||
| 646ac719c1 |
+1
-1
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
|
||||
<groupId>com.twelvemonkeys.bom</groupId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>common-image</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>common-io</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>common-lang</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
@@ -142,7 +142,7 @@ public final class DateUtil {
|
||||
* @param pTime time
|
||||
* @return the time rounded to the closest second.
|
||||
*/
|
||||
public static long roundToSecond(long pTime) {
|
||||
public static long roundToSecond(final long pTime) {
|
||||
return (pTime / SECOND) * SECOND;
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@ public final class DateUtil {
|
||||
* @param pTime time
|
||||
* @return the time rounded to the closest minute.
|
||||
*/
|
||||
public static long roundToMinute(long pTime) {
|
||||
public static long roundToMinute(final long pTime) {
|
||||
return (pTime / MINUTE) * MINUTE;
|
||||
}
|
||||
|
||||
@@ -162,9 +162,20 @@ public final class DateUtil {
|
||||
* @param pTime time
|
||||
* @return the time rounded to the closest hour.
|
||||
*/
|
||||
public static long roundToHour(long pTime) {
|
||||
// TODO: What if timezone offset is sub hour? Are there any? I think so...
|
||||
return ((pTime / HOUR) * HOUR);
|
||||
public static long roundToHour(final long pTime) {
|
||||
return roundToHour(pTime, TimeZone.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the given time down to the closest hour, using the given timezone.
|
||||
*
|
||||
* @param pTime time
|
||||
* @param pTimeZone the timezone to use when rounding
|
||||
* @return the time rounded to the closest hour.
|
||||
*/
|
||||
public static long roundToHour(final long pTime, final TimeZone pTimeZone) {
|
||||
int offset = pTimeZone.getOffset(pTime);
|
||||
return ((pTime / HOUR) * HOUR) - offset;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,7 +184,7 @@ public final class DateUtil {
|
||||
* @param pTime time
|
||||
* @return the time rounded to the closest day.
|
||||
*/
|
||||
public static long roundToDay(long pTime) {
|
||||
public static long roundToDay(final long pTime) {
|
||||
return roundToDay(pTime, TimeZone.getDefault());
|
||||
}
|
||||
|
||||
@@ -184,7 +195,7 @@ public final class DateUtil {
|
||||
* @param pTimeZone the timezone to use when rounding
|
||||
* @return the time rounded to the closest day.
|
||||
*/
|
||||
public static long roundToDay(long pTime, TimeZone pTimeZone) {
|
||||
public static long roundToDay(final long pTime, final TimeZone pTimeZone) {
|
||||
int offset = pTimeZone.getOffset(pTime);
|
||||
return (((pTime + offset) / DAY) * DAY) - offset;
|
||||
}
|
||||
|
||||
@@ -29,11 +29,15 @@
|
||||
package com.twelvemonkeys.lang;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* DateUtilTest
|
||||
@@ -42,9 +46,30 @@ import static org.junit.Assert.*;
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: DateUtilTest.java,v 1.0 11.04.12 16:21 haraldk Exp$
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class DateUtilTest {
|
||||
private static Calendar getCalendar(long time) {
|
||||
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
|
||||
|
||||
private final TimeZone timeZone;
|
||||
|
||||
@Parameterized.Parameters
|
||||
public static List<Object[]> timeZones() {
|
||||
return Arrays.asList(new Object[][] {
|
||||
{TimeZone.getTimeZone("UTC")},
|
||||
{TimeZone.getTimeZone("CET")},
|
||||
{TimeZone.getTimeZone("IST")}, // 30 min off
|
||||
});
|
||||
}
|
||||
|
||||
public DateUtilTest(final TimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
private Calendar getCalendar(long time) {
|
||||
return getCalendar(time, TimeZone.getDefault());
|
||||
}
|
||||
|
||||
private Calendar getCalendar(long time, final TimeZone timeZone) {
|
||||
Calendar calendar = Calendar.getInstance(timeZone);
|
||||
calendar.setTimeInMillis(time);
|
||||
|
||||
return calendar;
|
||||
@@ -74,6 +99,15 @@ public class DateUtilTest {
|
||||
assertEquals(0, calendar.get(Calendar.MINUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoundToHourTZ() {
|
||||
Calendar calendar = getCalendar(DateUtil.roundToHour(System.currentTimeMillis(), timeZone), timeZone);
|
||||
|
||||
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
||||
assertEquals(0, calendar.get(Calendar.SECOND));
|
||||
assertEquals(0, calendar.get(Calendar.MINUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoundToDay() {
|
||||
Calendar calendar = getCalendar(DateUtil.roundToDay(System.currentTimeMillis()));
|
||||
@@ -84,6 +118,16 @@ public class DateUtilTest {
|
||||
assertEquals(0, calendar.get(Calendar.HOUR_OF_DAY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRoundToDayTZ() {
|
||||
Calendar calendar = getCalendar(DateUtil.roundToDay(System.currentTimeMillis(), timeZone), timeZone);
|
||||
|
||||
assertEquals(0, calendar.get(Calendar.MILLISECOND));
|
||||
assertEquals(0, calendar.get(Calendar.SECOND));
|
||||
assertEquals(0, calendar.get(Calendar.MINUTE));
|
||||
assertEquals(0, calendar.get(Calendar.HOUR_OF_DAY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCurrentTimeSecond() {
|
||||
Calendar calendar = getCalendar(DateUtil.currentTimeSecond());
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<groupId>com.twelvemonkeys.common</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-batik</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: Batik Plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-bmp</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: BMP plugin</name>
|
||||
|
||||
+14
@@ -43,6 +43,7 @@ abstract class BitmapDescriptor {
|
||||
protected final DIBHeader header;
|
||||
|
||||
protected BufferedImage image;
|
||||
protected BitmapMask mask;
|
||||
|
||||
public BitmapDescriptor(final DirectoryEntry pEntry, final DIBHeader pHeader) {
|
||||
Validate.notNull(pEntry, "entry");
|
||||
@@ -69,4 +70,17 @@ abstract class BitmapDescriptor {
|
||||
protected final int getBitCount() {
|
||||
return entry.getBitCount() != 0 ? entry.getBitCount() : header.getBitCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "[" + entry + ", " + header + "]";
|
||||
}
|
||||
|
||||
public final void setMask(final BitmapMask mask) {
|
||||
this.mask = mask;
|
||||
}
|
||||
|
||||
public final boolean hasMask() {
|
||||
return header.getHeight() == getHeight() * 2;
|
||||
}
|
||||
}
|
||||
|
||||
+25
-34
@@ -28,8 +28,6 @@
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import com.twelvemonkeys.image.InverseColorMapIndexColorModel;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.IndexColorModel;
|
||||
@@ -46,8 +44,6 @@ class BitmapIndexed extends BitmapDescriptor {
|
||||
protected final int[] bits;
|
||||
protected final int[] colors;
|
||||
|
||||
private BitmapMask mask;
|
||||
|
||||
public BitmapIndexed(final DirectoryEntry pEntry, final DIBHeader pHeader) {
|
||||
super(pEntry, pHeader);
|
||||
bits = new int[getWidth() * getHeight()];
|
||||
@@ -65,7 +61,7 @@ class BitmapIndexed extends BitmapDescriptor {
|
||||
// This is slightly obscure, and should probably be moved..
|
||||
Hashtable<String, Object> properties = null;
|
||||
if (entry instanceof DirectoryEntry.CUREntry) {
|
||||
properties = new Hashtable<String, Object>(1);
|
||||
properties = new Hashtable<>(1);
|
||||
properties.put("cursor_hotspot", ((DirectoryEntry.CUREntry) this.entry).getHotspot());
|
||||
}
|
||||
|
||||
@@ -89,8 +85,6 @@ class BitmapIndexed extends BitmapDescriptor {
|
||||
|
||||
raster.setSamples(0, 0, getWidth(), getHeight(), 0, bits);
|
||||
|
||||
//System.out.println("Image: " + image);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@@ -100,40 +94,40 @@ class BitmapIndexed extends BitmapDescriptor {
|
||||
IndexColorModel createColorModel() {
|
||||
// NOTE: This is a hack to make room for transparent pixel for mask
|
||||
int bits = getBitCount();
|
||||
|
||||
|
||||
int colors = this.colors.length;
|
||||
int trans = -1;
|
||||
int transparent = -1;
|
||||
|
||||
// Try to avoid USHORT transfertype, as it results in BufferedImage TYPE_CUSTOM
|
||||
// NOTE: This code assumes icons are small, and is NOT optimized for performance...
|
||||
if (colors > (1 << getBitCount())) {
|
||||
int index = findTransIndexMaybeRemap(this.colors, this.bits);
|
||||
int index = findTransparentIndexMaybeRemap(this.colors, this.bits);
|
||||
|
||||
if (index == -1) {
|
||||
// No duplicate found, increase bitcount
|
||||
bits++;
|
||||
trans = this.colors.length - 1;
|
||||
transparent = this.colors.length - 1;
|
||||
}
|
||||
else {
|
||||
// Found a duplicate, use it as trans
|
||||
trans = index;
|
||||
// Found a duplicate, use it as transparent
|
||||
transparent = index;
|
||||
colors--;
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Setting hasAlpha to true, makes things work on 1.2
|
||||
return new InverseColorMapIndexColorModel(
|
||||
bits, colors, this.colors, 0, true, trans,
|
||||
return new IndexColorModel(
|
||||
bits, colors, this.colors, 0, true, transparent,
|
||||
bits <= 8 ? DataBuffer.TYPE_BYTE : DataBuffer.TYPE_USHORT
|
||||
);
|
||||
}
|
||||
|
||||
private static int findTransIndexMaybeRemap(final int[] pColors, final int[] pBits) {
|
||||
private static int findTransparentIndexMaybeRemap(final int[] colors, final int[] bits) {
|
||||
// Look for unused colors, to use as transparent
|
||||
final boolean[] used = new boolean[pColors.length - 1];
|
||||
for (int pBit : pBits) {
|
||||
if (!used[pBit]) {
|
||||
used[pBit] = true;
|
||||
boolean[] used = new boolean[colors.length - 1];
|
||||
for (int bit : bits) {
|
||||
if (!used[bit]) {
|
||||
used[bit] = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,38 +138,35 @@ class BitmapIndexed extends BitmapDescriptor {
|
||||
}
|
||||
|
||||
// Try to find duplicates in colormap, and remap
|
||||
int trans = -1;
|
||||
int transparent = -1;
|
||||
int duplicate = -1;
|
||||
for (int i = 0; trans == -1 && i < pColors.length - 1; i++) {
|
||||
for (int j = i + 1; j < pColors.length - 1; j++) {
|
||||
if (pColors[i] == pColors[j]) {
|
||||
trans = j;
|
||||
for (int i = 0; transparent == -1 && i < colors.length - 1; i++) {
|
||||
for (int j = i + 1; j < colors.length - 1; j++) {
|
||||
if (colors[i] == colors[j]) {
|
||||
transparent = j;
|
||||
duplicate = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (trans != -1) {
|
||||
if (transparent != -1) {
|
||||
// Remap duplicate
|
||||
for (int i = 0; i < pBits.length; i++) {
|
||||
if (pBits[i] == trans) {
|
||||
pBits[i] = duplicate;
|
||||
for (int i = 0; i < bits.length; i++) {
|
||||
if (bits[i] == transparent) {
|
||||
bits[i] = duplicate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return trans;
|
||||
return transparent;
|
||||
}
|
||||
|
||||
public BufferedImage getImage() {
|
||||
if (image == null) {
|
||||
image = createImageIndexed();
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setMask(final BitmapMask pMask) {
|
||||
mask = pMask;
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -38,19 +38,19 @@ import java.awt.image.BufferedImage;
|
||||
* @version $Id: BitmapMask.java,v 1.0 25.feb.2006 00:29:44 haku Exp$
|
||||
*/
|
||||
class BitmapMask extends BitmapDescriptor {
|
||||
protected final BitmapIndexed mask;
|
||||
protected final BitmapIndexed bitMask;
|
||||
|
||||
public BitmapMask(final DirectoryEntry pParent, final DIBHeader pHeader) {
|
||||
super(pParent, pHeader);
|
||||
mask = new BitmapIndexed(pParent, pHeader);
|
||||
bitMask = new BitmapIndexed(pParent, pHeader);
|
||||
}
|
||||
|
||||
boolean isTransparent(final int pX, final int pY) {
|
||||
// NOTE: 1: Fully transparent, 0: Opaque...
|
||||
return mask.bits[pX + pY * getWidth()] != 0;
|
||||
return bitMask.bits[pX + pY * getWidth()] != 0;
|
||||
}
|
||||
|
||||
public BufferedImage getImage() {
|
||||
return mask.getImage();
|
||||
return bitMask.getImage();
|
||||
}
|
||||
}
|
||||
|
||||
+34
@@ -28,7 +28,9 @@
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.bmp;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.WritableRaster;
|
||||
|
||||
/**
|
||||
* Describes an RGB/true color bitmap structure (16, 24 and 32 bits per pixel).
|
||||
@@ -43,6 +45,38 @@ class BitmapRGB extends BitmapDescriptor {
|
||||
}
|
||||
|
||||
public BufferedImage getImage() {
|
||||
// Test is mask != null rather than hasMask(), as 32 bit (w/alpha)
|
||||
// might still have bitmask, but we don't read or use it.
|
||||
if (mask != null) {
|
||||
image = createMaskedImage();
|
||||
mask = null;
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
private BufferedImage createMaskedImage() {
|
||||
BufferedImage masked = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
|
||||
|
||||
Graphics2D graphics = masked.createGraphics();
|
||||
try {
|
||||
graphics.drawImage(image, 0, 0, null);
|
||||
}
|
||||
finally {
|
||||
graphics.dispose();
|
||||
}
|
||||
|
||||
WritableRaster alphaRaster = masked.getAlphaRaster();
|
||||
|
||||
byte[] trans = {0x0};
|
||||
for (int y = 0; y < getHeight(); y++) {
|
||||
for (int x = 0; x < getWidth(); x++) {
|
||||
if (mask.isTransparent(x, y)) {
|
||||
alphaRaster.setDataElements(x, y, trans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return masked;
|
||||
}
|
||||
}
|
||||
|
||||
+37
-14
@@ -66,14 +66,15 @@ import java.util.List;
|
||||
// TODO: Decide whether DirectoryEntry or DIBHeader should be primary source for color count/bit count
|
||||
// TODO: Support loading icons from DLLs, see
|
||||
// <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/msdn_icons.asp">MSDN</a>
|
||||
// Known issue: 256x256 PNG encoded icons does not have IndexColorModel even if stated in DirectoryEntry (seem impossible as the PNGs are all true color)
|
||||
// Known issue: 256x256 PNG encoded icons does not have IndexColorModel even if stated in DirectoryEntry
|
||||
// (seem impossible as the PNGs are all true color)
|
||||
abstract class DIBImageReader extends ImageReaderBase {
|
||||
// TODO: Consider moving the reading to inner classes (subclasses of BitmapDescriptor)
|
||||
private Directory directory;
|
||||
|
||||
// TODO: Review these, make sure we don't have a memory leak
|
||||
private Map<DirectoryEntry, DIBHeader> headers = new WeakHashMap<DirectoryEntry, DIBHeader>();
|
||||
private Map<DirectoryEntry, BitmapDescriptor> descriptors = new WeakWeakMap<DirectoryEntry, BitmapDescriptor>();
|
||||
private Map<DirectoryEntry, DIBHeader> headers = new WeakHashMap<>();
|
||||
private Map<DirectoryEntry, BitmapDescriptor> descriptors = new WeakWeakMap<>();
|
||||
|
||||
private ImageReader pngImageReader;
|
||||
|
||||
@@ -101,7 +102,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
return getImageTypesPNG(entry);
|
||||
}
|
||||
|
||||
List<ImageTypeSpecifier> types = new ArrayList<ImageTypeSpecifier>();
|
||||
List<ImageTypeSpecifier> types = new ArrayList<>();
|
||||
DIBHeader header = getHeader(entry);
|
||||
|
||||
// Use data from header to create specifier
|
||||
@@ -121,10 +122,13 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
specifier = ImageTypeSpecifiers.createFromIndexColorModel(indexed.createColorModel());
|
||||
break;
|
||||
case 16:
|
||||
// TODO: May have mask?!
|
||||
specifier = ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_USHORT_555_RGB);
|
||||
break;
|
||||
case 24:
|
||||
specifier = ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR);
|
||||
specifier = new BitmapRGB(entry, header).hasMask()
|
||||
? ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_4BYTE_ABGR)
|
||||
: ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_3BYTE_BGR);
|
||||
break;
|
||||
case 32:
|
||||
specifier = ImageTypeSpecifiers.createFromBufferedImageType(BufferedImage.TYPE_INT_ARGB);
|
||||
@@ -184,6 +188,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
}
|
||||
else {
|
||||
Graphics2D g = destination.createGraphics();
|
||||
|
||||
try {
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
g.drawImage(image, 0, 0, null);
|
||||
@@ -316,6 +321,8 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
descriptors.put(pEntry, descriptor);
|
||||
}
|
||||
|
||||
System.err.println("descriptor: " + descriptor);
|
||||
|
||||
return descriptor.getImage();
|
||||
}
|
||||
|
||||
@@ -335,7 +342,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
}
|
||||
|
||||
BitmapMask mask = new BitmapMask(pBitmap.entry, pBitmap.header);
|
||||
readBitmapIndexed1(mask.mask, true);
|
||||
readBitmapIndexed1(mask.bitMask, true);
|
||||
pBitmap.setMask(mask);
|
||||
}
|
||||
|
||||
@@ -370,7 +377,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: If we are reading the mask, we don't abort or progress
|
||||
// NOTE: If we are reading the mask, we don't abort or report progress
|
||||
if (!pAsMask) {
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
@@ -455,7 +462,7 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
short[] pixels = new short[pBitmap.getWidth() * pBitmap.getHeight()];
|
||||
|
||||
// TODO: Support TYPE_USHORT_565 and the RGB 444/ARGB 4444 layouts
|
||||
// Will create TYPE_USHORT_555;
|
||||
// Will create TYPE_USHORT_555
|
||||
DirectColorModel cm = new DirectColorModel(16, 0x7C00, 0x03E0, 0x001F);
|
||||
DataBuffer buffer = new DataBufferShort(pixels, pixels.length);
|
||||
WritableRaster raster = Raster.createPackedRaster(
|
||||
@@ -480,6 +487,8 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
|
||||
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||
}
|
||||
|
||||
// TODO: Might be mask!?
|
||||
}
|
||||
|
||||
private void readBitmap24(final BitmapDescriptor pBitmap) throws IOException {
|
||||
@@ -494,16 +503,19 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE
|
||||
);
|
||||
|
||||
int scanlineStride = pBitmap.getWidth() * 3;
|
||||
// BMP rows are padded to 4 byte boundary
|
||||
int rowSizeBytes = ((8 * scanlineStride + 31) / 32) * 4;
|
||||
|
||||
WritableRaster raster = Raster.createInterleavedRaster(
|
||||
buffer, pBitmap.getWidth(), pBitmap.getHeight(), pBitmap.getWidth(), 3, bOffs, null
|
||||
buffer, pBitmap.getWidth(), pBitmap.getHeight(), scanlineStride, 3, bOffs, null
|
||||
);
|
||||
pBitmap.image = new BufferedImage(cm, raster, cm.isAlphaPremultiplied(), null);
|
||||
|
||||
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||
int offset = (pBitmap.getHeight() - y - 1) * pBitmap.getWidth();
|
||||
imageInput.readFully(pixels, offset, pBitmap.getWidth() * 3);
|
||||
|
||||
// TODO: Possibly read padding byte here!
|
||||
for (int y = 0; y < pBitmap.getHeight(); y++) {
|
||||
int offset = (pBitmap.getHeight() - y - 1) * scanlineStride;
|
||||
imageInput.readFully(pixels, offset, scanlineStride);
|
||||
imageInput.skipBytes(rowSizeBytes - scanlineStride);
|
||||
|
||||
if (abortRequested()) {
|
||||
processReadAborted();
|
||||
@@ -512,6 +524,14 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
|
||||
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||
}
|
||||
|
||||
// 24 bit icons usually have a bit mask
|
||||
if (pBitmap.hasMask()) {
|
||||
BitmapMask mask = new BitmapMask(pBitmap.entry, pBitmap.header);
|
||||
readBitmapIndexed1(mask.bitMask, true);
|
||||
|
||||
pBitmap.setMask(mask);
|
||||
}
|
||||
}
|
||||
|
||||
private void readBitmap32(final BitmapDescriptor pBitmap) throws IOException {
|
||||
@@ -535,6 +555,9 @@ abstract class DIBImageReader extends ImageReaderBase {
|
||||
}
|
||||
processImageProgress(100 * y / (float) pBitmap.getHeight());
|
||||
}
|
||||
|
||||
// There might be a mask here as well, but we'll ignore it,
|
||||
// and use the 8 bit alpha channel in the ARGB pixel data
|
||||
}
|
||||
|
||||
private Directory getDirectory() throws IOException {
|
||||
|
||||
+3
-1
@@ -39,7 +39,9 @@ public class ICOImageReaderTest extends ImageReaderAbstractTest<ICOImageReader>
|
||||
new Dimension(16, 16), new Dimension(16, 16), new Dimension(32, 32), new Dimension(32, 32),
|
||||
new Dimension(48, 48), new Dimension(48, 48), new Dimension(256, 256), new Dimension(256, 256),
|
||||
new Dimension(16, 16), new Dimension(32, 32), new Dimension(48, 48), new Dimension(256, 256)
|
||||
)
|
||||
),
|
||||
// Problematic icon that reports 24 bit in the descriptor, but has separate 1 bit ''mask (height 2 x icon height)!
|
||||
new TestData(getClassLoaderResource("/ico/rgb24bitmask.ico"), new Dimension(32, 32))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-clippath</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: Photoshop Path Support</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-core</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: Core</name>
|
||||
|
||||
+28
-3
@@ -52,7 +52,7 @@ import java.util.Properties;
|
||||
* <p />
|
||||
* Color profiles may be configured by placing a property-file
|
||||
* {@code com/twelvemonkeys/imageio/color/icc_profiles.properties}
|
||||
* on the classpath, specifying the full path to the profile.
|
||||
* on the classpath, specifying the full path to the profiles.
|
||||
* ICC color profiles are probably already present on your system, or
|
||||
* can be downloaded from
|
||||
* <a href="http://www.color.org/profiles2.xalter">ICC</a>,
|
||||
@@ -161,6 +161,11 @@ public final class ColorSpaces {
|
||||
|
||||
if (cs == null) {
|
||||
cs = new ICC_ColorSpace(profile);
|
||||
|
||||
// Validate the color space, to avoid caching bad color spaces
|
||||
// Will throw IllegalArgumentException or CMMException if the profile is bad
|
||||
cs.fromRGB(new float[] {1f, 0f, 0f});
|
||||
|
||||
cache.put(key, cs);
|
||||
}
|
||||
|
||||
@@ -195,7 +200,7 @@ public final class ColorSpaces {
|
||||
* @return {@code true} if known to be offending, {@code false} otherwise
|
||||
* @throws IllegalArgumentException if {@code profile} is {@code null}
|
||||
*/
|
||||
public static boolean isOffendingColorProfile(final ICC_Profile profile) {
|
||||
static boolean isOffendingColorProfile(final ICC_Profile profile) {
|
||||
Validate.notNull(profile, "profile");
|
||||
|
||||
// NOTE:
|
||||
@@ -213,6 +218,26 @@ public final class ColorSpaces {
|
||||
return data[ICC_Profile.icHdrRenderingIntent] != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether an ICC color profile is valid.
|
||||
* Invalid profiles are known to cause problems for {@link java.awt.image.ColorConvertOp}.
|
||||
* <p />
|
||||
* <em>
|
||||
* Note that this method only tests if a color conversion using this profile is known to fail.
|
||||
* There's no guarantee that the color conversion will succeed even if this method returns {@code false}.
|
||||
* </em>
|
||||
*
|
||||
* @param profile the ICC color profile. May not be {@code null}.
|
||||
* @return {@code profile} if valid.
|
||||
* @throws IllegalArgumentException if {@code profile} is {@code null}
|
||||
* @throws java.awt.color.CMMException if {@code profile} is invalid.
|
||||
*/
|
||||
public static ICC_Profile validateProfile(final ICC_Profile profile) {
|
||||
createColorSpace(profile); // Creating a color space will fail if the profile is bad
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color space specified by the given color space constant.
|
||||
* <p />
|
||||
@@ -317,7 +342,7 @@ public final class ColorSpaces {
|
||||
try {
|
||||
return ICC_Profile.getInstance(profilePath);
|
||||
}
|
||||
catch (IOException ignore) {
|
||||
catch (SecurityException | IOException ignore) {
|
||||
if (DEBUG) {
|
||||
ignore.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-icns</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: ICNS plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-iff</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: IFF plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-jpeg</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: JPEG plugin</name>
|
||||
|
||||
+177
-65
@@ -28,7 +28,6 @@
|
||||
|
||||
package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||
|
||||
import com.twelvemonkeys.image.ImageUtil;
|
||||
import com.twelvemonkeys.imageio.ImageReaderBase;
|
||||
import com.twelvemonkeys.imageio.color.ColorSpaces;
|
||||
import com.twelvemonkeys.imageio.metadata.CompoundDirectory;
|
||||
@@ -152,10 +151,10 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
/** Cached list of JPEG segments we filter from the underlying stream */
|
||||
private List<JPEGSegment> segments;
|
||||
|
||||
JPEGImageReader(final ImageReaderSpi provider, final ImageReader delegate) {
|
||||
protected JPEGImageReader(final ImageReaderSpi provider, final ImageReader delegate) {
|
||||
super(provider);
|
||||
this.delegate = Validate.notNull(delegate);
|
||||
|
||||
this.delegate = Validate.notNull(delegate);
|
||||
progressDelegator = new ProgressDelegator();
|
||||
}
|
||||
|
||||
@@ -298,7 +297,9 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
super.setInput(input, seekForwardOnly, ignoreMetadata);
|
||||
|
||||
// JPEGSegmentImageInputStream that filters out/skips bad/unnecessary segments
|
||||
delegate.setInput(imageInput != null ? new JPEGSegmentImageInputStream(imageInput) : null, seekForwardOnly, ignoreMetadata);
|
||||
delegate.setInput(imageInput != null
|
||||
? new JPEGSegmentImageInputStream(imageInput)
|
||||
: null, seekForwardOnly, ignoreMetadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -408,6 +409,7 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
if (DEBUG) {
|
||||
System.err.println("Converting from " + intendedCS + " to " + (image.getColorModel().getColorSpace().isCS_sRGB() ? "sRGB" : image.getColorModel().getColorSpace()));
|
||||
}
|
||||
|
||||
convert = new ColorConvertOp(intendedCS, image.getColorModel().getColorSpace(), null);
|
||||
}
|
||||
// Else, pass through with no conversion
|
||||
@@ -469,12 +471,11 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
YCbCrConverter.convertYCbCr2RGB(raster);
|
||||
}
|
||||
else if (csType == JPEGColorSpace.YCCK) {
|
||||
YCbCrConverter.convertYCCK2CMYK(raster);
|
||||
// TODO: Need to rethink this (non-) inversion, see #147
|
||||
// TODO: Allow param to specify inversion, or possibly the PDF decode array
|
||||
// flag0 bit 15, blend = 1 see http://graphicdesign.stackexchange.com/questions/12894/cmyk-jpegs-extracted-from-pdf-appear-inverted
|
||||
if ((getAdobeDCT().flags0 & 0x8000) != 0) {
|
||||
/// TODO: Better yet would be to not inverting in the first place, add flag to convertYCCK2CMYK
|
||||
invertCMYK(raster);
|
||||
}
|
||||
boolean invert = true;// || (adobeDCT.flags0 & 0x8000) == 0;
|
||||
YCbCrConverter.convertYCCK2CMYK(raster, invert);
|
||||
}
|
||||
else if (csType == JPEGColorSpace.CMYK) {
|
||||
invertCMYK(raster);
|
||||
@@ -629,7 +630,7 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
}
|
||||
}
|
||||
|
||||
private ICC_Profile ensureDisplayProfile(final ICC_Profile profile) {
|
||||
protected ICC_Profile ensureDisplayProfile(final ICC_Profile profile) {
|
||||
// NOTE: This is probably not the right way to do it... :-P
|
||||
// TODO: Consider moving method to ColorSpaces class or new class in imageio.color package
|
||||
|
||||
@@ -835,7 +836,7 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
return data;
|
||||
}
|
||||
|
||||
ICC_Profile getEmbeddedICCProfile(final boolean allowBadIndexes) throws IOException {
|
||||
protected ICC_Profile getEmbeddedICCProfile(final boolean allowBadIndexes) throws IOException {
|
||||
// ICC v 1.42 (2006) annex B:
|
||||
// APP2 marker (0xFFE2) + 2 byte length + ASCII 'ICC_PROFILE' + 0 (termination)
|
||||
// + 1 byte chunk number + 1 byte chunk count (allows ICC profiles chunked in multiple APP2 segments)
|
||||
@@ -857,7 +858,7 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
return readICCProfileSafe(stream);
|
||||
return readICCProfileSafe(stream, allowBadIndexes);
|
||||
}
|
||||
else if (!segments.isEmpty()) {
|
||||
// NOTE: This is probably over-complicated, as I've never encountered ICC_PROFILE chunks out of order...
|
||||
@@ -904,15 +905,17 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
streams[badICC ? i : chunkNumber - 1] = stream;
|
||||
}
|
||||
|
||||
return readICCProfileSafe(new SequenceInputStream(Collections.enumeration(Arrays.asList(streams))));
|
||||
return readICCProfileSafe(new SequenceInputStream(Collections.enumeration(Arrays.asList(streams))), allowBadIndexes);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private ICC_Profile readICCProfileSafe(final InputStream stream) throws IOException {
|
||||
private ICC_Profile readICCProfileSafe(final InputStream stream, final boolean allowBadProfile) throws IOException {
|
||||
try {
|
||||
return ICC_Profile.getInstance(stream);
|
||||
ICC_Profile profile = ICC_Profile.getInstance(stream);
|
||||
|
||||
return allowBadProfile ? profile : ColorSpaces.validateProfile(profile);
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
// NOTE: Throws either IllegalArgumentException or CMMException, depending on platform.
|
||||
@@ -944,6 +947,11 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
delegate.abort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageReadParam getDefaultReadParam() {
|
||||
return delegate.getDefaultReadParam();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean readerSupportsThumbnails() {
|
||||
return true; // We support EXIF, JFIF and JFXX style thumbnails
|
||||
@@ -1172,19 +1180,28 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
rgb[offset + 2] = clamp(y + Cb_B_LUT[cb]);
|
||||
}
|
||||
|
||||
static void convertYCCK2CMYK(final Raster raster) {
|
||||
static void convertYCCK2CMYK(final Raster raster, final boolean invert) {
|
||||
final int height = raster.getHeight();
|
||||
final int width = raster.getWidth();
|
||||
final byte[] data = ((DataBufferByte) raster.getDataBuffer()).getData();
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
convertYCCK2CMYK(data, data, (x + y * width) * 4);
|
||||
if (invert) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
convertYCCK2CMYKInverted(data, data, (x + y * width) * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
convertYCCK2CMYK(data, data, (x + y * width) * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void convertYCCK2CMYK(byte[] ycck, byte[] cmyk, int offset) {
|
||||
private static void convertYCCK2CMYKInverted(byte[] ycck, byte[] cmyk, int offset) {
|
||||
// Inverted
|
||||
int y = 255 - ycck[offset ] & 0xff;
|
||||
int cb = 255 - ycck[offset + 1] & 0xff;
|
||||
@@ -1201,6 +1218,22 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
cmyk[offset + 3] = (byte) k; // K passes through unchanged
|
||||
}
|
||||
|
||||
private static void convertYCCK2CMYK(byte[] ycck, byte[] cmyk, int offset) {
|
||||
int y = ycck[offset ] & 0xff;
|
||||
int cb = ycck[offset + 1] & 0xff;
|
||||
int cr = ycck[offset + 2] & 0xff;
|
||||
int k = ycck[offset + 3] & 0xff;
|
||||
|
||||
int cmykC = MAXJSAMPLE - (y + Cr_R_LUT[cr]);
|
||||
int cmykM = MAXJSAMPLE - (y + (Cb_G_LUT[cb] + Cr_G_LUT[cr] >> SCALEBITS));
|
||||
int cmykY = MAXJSAMPLE - (y + Cb_B_LUT[cb]);
|
||||
|
||||
cmyk[offset ] = clamp(cmykC);
|
||||
cmyk[offset + 1] = clamp(cmykM);
|
||||
cmyk[offset + 2] = clamp(cmykY);
|
||||
cmyk[offset + 3] = (byte) k; // K passes through unchanged
|
||||
}
|
||||
|
||||
private static byte clamp(int val) {
|
||||
return (byte) Math.max(0, Math.min(255, val));
|
||||
}
|
||||
@@ -1301,7 +1334,68 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
}
|
||||
|
||||
public static void main(final String[] args) throws IOException {
|
||||
for (final String arg : args) {
|
||||
ImageIO.setUseCache(false);
|
||||
|
||||
int subX = 1;
|
||||
int subY = 1;
|
||||
int xOff = 0;
|
||||
int yOff = 0;
|
||||
Rectangle roi = null;
|
||||
boolean metadata = false;
|
||||
boolean thumbnails = false;
|
||||
|
||||
for (int argIdx = 0; argIdx < args.length; argIdx++) {
|
||||
final String arg = args[argIdx];
|
||||
|
||||
if (arg.charAt(0) == '-') {
|
||||
if (arg.equals("-s") || arg.equals("--subsample") && args.length > argIdx) {
|
||||
String[] sub = args[++argIdx].split(",");
|
||||
|
||||
try {
|
||||
if (sub.length >= 4) {
|
||||
subX = Integer.parseInt(sub[0]);
|
||||
subY = Integer.parseInt(sub[1]);
|
||||
xOff = Integer.parseInt(sub[2]);
|
||||
yOff = Integer.parseInt(sub[3]);
|
||||
}
|
||||
else {
|
||||
subX = Integer.parseInt(sub[0]);
|
||||
subY = sub.length > 1 ? Integer.parseInt(sub[1]) : subX;
|
||||
}
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
System.err.println("Bad sub sampling (x,y): '" + args[argIdx] + "'");
|
||||
}
|
||||
}
|
||||
else if (arg.equals("-r") || arg.equals("--roi") && args.length > argIdx) {
|
||||
String[] region = args[++argIdx].split(",");
|
||||
|
||||
try {
|
||||
if (region.length >= 4) {
|
||||
roi = new Rectangle(Integer.parseInt(region[0]), Integer.parseInt(region[2]), Integer.parseInt(region[2]), Integer.parseInt(region[3]));
|
||||
}
|
||||
else {
|
||||
roi = new Rectangle(Integer.parseInt(region[0]), Integer.parseInt(region[2]));
|
||||
}
|
||||
}
|
||||
catch (IndexOutOfBoundsException | NumberFormatException e) {
|
||||
System.err.println("Bad source region ([x,y,]w, h): '" + args[argIdx] + "'");
|
||||
}
|
||||
}
|
||||
else if (arg.equals("-m") || arg.equals("--metadata")) {
|
||||
metadata = true;
|
||||
}
|
||||
else if (arg.equals("-t") || arg.equals("--thumbnails")) {
|
||||
thumbnails = true;
|
||||
}
|
||||
else {
|
||||
System.err.println("Unknown argument: '" + arg + "'");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
File file = new File(arg);
|
||||
|
||||
ImageInputStream input = ImageIO.createImageInputStream(file);
|
||||
@@ -1317,15 +1411,15 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
continue;
|
||||
}
|
||||
|
||||
ImageReader reader = readers.next();
|
||||
// System.err.println("Reading using: " + reader);
|
||||
final ImageReader reader = readers.next();
|
||||
System.err.println("Reading using: " + reader);
|
||||
|
||||
reader.addIIOReadWarningListener(new IIOReadWarningListener() {
|
||||
public void warningOccurred(ImageReader source, String warning) {
|
||||
System.err.println("Warning: " + arg + ": " + warning);
|
||||
}
|
||||
});
|
||||
reader.addIIOReadProgressListener(new ProgressListenerBase() {
|
||||
final ProgressListenerBase listener = new ProgressListenerBase() {
|
||||
private static final int MAX_W = 78;
|
||||
int lastProgress = 0;
|
||||
|
||||
@@ -1354,29 +1448,35 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
|
||||
System.out.println("]");
|
||||
}
|
||||
});
|
||||
};
|
||||
reader.addIIOReadProgressListener(listener);
|
||||
|
||||
reader.setInput(input);
|
||||
|
||||
// For a tables-only image, we can't read image, but we should get metadata.
|
||||
if (reader.getNumImages(true) == 0) {
|
||||
IIOMetadata streamMetadata = reader.getStreamMetadata();
|
||||
IIOMetadataNode streamNativeTree = (IIOMetadataNode) streamMetadata.getAsTree(streamMetadata.getNativeMetadataFormatName());
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(streamNativeTree, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// For a tables-only image, we can't read image, but we should get metadata.
|
||||
if (reader.getNumImages(true) == 0) {
|
||||
IIOMetadata streamMetadata = reader.getStreamMetadata();
|
||||
IIOMetadataNode streamNativeTree = (IIOMetadataNode) streamMetadata.getAsTree(streamMetadata.getNativeMetadataFormatName());
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(streamNativeTree, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
BufferedImage image;
|
||||
ImageReadParam param = reader.getDefaultReadParam();
|
||||
// if (args.length > 1) {
|
||||
// int sub = Integer.parseInt(args[1]);
|
||||
// int sub = 4;
|
||||
// param.setSourceSubsampling(sub, sub, 0, 0);
|
||||
// }
|
||||
BufferedImage image = reader.getImageTypes(0).next().createBufferedImage(reader.getWidth(0), reader.getHeight(0));
|
||||
if (subX > 1 || subY > 1 || roi != null) {
|
||||
param.setSourceSubsampling(subX, subY, xOff, yOff);
|
||||
param.setSourceRegion(roi);
|
||||
|
||||
image = reader.getImageTypes(0).next().createBufferedImage((reader.getWidth(0) + subX - 1)/ subX, (reader.getHeight(0) + subY - 1) / subY);
|
||||
}
|
||||
else {
|
||||
image = reader.getImageTypes(0).next().createBufferedImage(reader.getWidth(0), reader.getHeight(0));
|
||||
}
|
||||
param.setDestination(image);
|
||||
|
||||
// long start = System.currentTimeMillis();
|
||||
long start = DEBUG ? System.currentTimeMillis() : 0;
|
||||
|
||||
try {
|
||||
image = reader.read(0, param);
|
||||
}
|
||||
@@ -1387,12 +1487,13 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// System.err.println("Read time: " + (System.currentTimeMillis() - start) + " ms");
|
||||
// System.err.println("image: " + image);
|
||||
|
||||
if (DEBUG) {
|
||||
System.err.println("Read time: " + (System.currentTimeMillis() - start) + " ms");
|
||||
System.err.println("image: " + image);
|
||||
}
|
||||
|
||||
// image = new ResampleOp(reader.getWidth(0) / 4, reader.getHeight(0) / 4, ResampleOp.FILTER_LANCZOS).filter(image, null);
|
||||
|
||||
/*
|
||||
int maxW = 1280;
|
||||
int maxH = 800;
|
||||
if (image.getWidth() > maxW || image.getHeight() > maxH) {
|
||||
@@ -1406,34 +1507,45 @@ public class JPEGImageReader extends ImageReaderBase {
|
||||
}
|
||||
// System.err.println("Scale time: " + (System.currentTimeMillis() - start) + " ms");
|
||||
}
|
||||
*/
|
||||
|
||||
showIt(image, String.format("Image: %s [%d x %d]", file.getName(), reader.getWidth(0), reader.getHeight(0)));
|
||||
|
||||
try {
|
||||
IIOMetadata imageMetadata = reader.getImageMetadata(0);
|
||||
System.out.println("Metadata for File: " + file.getName());
|
||||
if (metadata) {
|
||||
try {
|
||||
IIOMetadata imageMetadata = reader.getImageMetadata(0);
|
||||
System.out.println("Metadata for File: " + file.getName());
|
||||
|
||||
if (imageMetadata.getNativeMetadataFormatName() != null) {
|
||||
System.out.println("Native:");
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(imageMetadata.getNativeMetadataFormatName()), false);
|
||||
if (imageMetadata.getNativeMetadataFormatName() != null) {
|
||||
System.out.println("Native:");
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(imageMetadata.getNativeMetadataFormatName()), false);
|
||||
}
|
||||
if (imageMetadata.isStandardMetadataFormatSupported()) {
|
||||
System.out.println("Standard:");
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName), false);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
}
|
||||
if (imageMetadata.isStandardMetadataFormatSupported()) {
|
||||
System.out.println("Standard:");
|
||||
new XMLSerializer(System.out, System.getProperty("file.encoding")).serialize(imageMetadata.getAsTree(IIOMetadataFormatImpl.standardMetadataFormatName), false);
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
int numThumbnails = reader.getNumThumbnails(0);
|
||||
for (int i = 0; i < numThumbnails; i++) {
|
||||
BufferedImage thumbnail = reader.readThumbnail(0, i);
|
||||
// System.err.println("thumbnail: " + thumbnail);
|
||||
showIt(thumbnail, String.format("Thumbnail: %s [%d x %d]", file.getName(), thumbnail.getWidth(), thumbnail.getHeight()));
|
||||
catch (IIOException e) {
|
||||
System.err.println("Could not read thumbnails: " + arg + ": " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
catch (IIOException e) {
|
||||
System.err.println("Could not read thumbnails: " + arg + ": " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
|
||||
if (thumbnails) {
|
||||
try {
|
||||
int numThumbnails = reader.getNumThumbnails(0);
|
||||
for (int i = 0; i < numThumbnails; i++) {
|
||||
BufferedImage thumbnail = reader.readThumbnail(0, i);
|
||||
// System.err.println("thumbnail: " + thumbnail);
|
||||
showIt(thumbnail, String.format("Thumbnail: %s [%d x %d]", file.getName(), thumbnail.getWidth(), thumbnail.getHeight()));
|
||||
}
|
||||
}
|
||||
catch (IIOException e) {
|
||||
System.err.println("Could not read thumbnails: " + arg + ": " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Throwable t) {
|
||||
|
||||
+13
-3
@@ -29,6 +29,7 @@
|
||||
package com.twelvemonkeys.imageio.plugins.jpeg;
|
||||
|
||||
import com.twelvemonkeys.imageio.spi.ImageReaderSpiBase;
|
||||
import com.twelvemonkeys.imageio.spi.ReaderWriterProviderInfo;
|
||||
import com.twelvemonkeys.imageio.util.IIOUtil;
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
@@ -48,14 +49,14 @@ import java.util.Locale;
|
||||
* @version $Id: JPEGImageReaderSpi.java,v 1.0 24.01.11 22.12 haraldk Exp$
|
||||
*/
|
||||
public class JPEGImageReaderSpi extends ImageReaderSpiBase {
|
||||
private ImageReaderSpi delegateProvider;
|
||||
protected ImageReaderSpi delegateProvider;
|
||||
|
||||
/**
|
||||
* Constructor for use by {@link javax.imageio.spi.IIORegistry} only.
|
||||
* The instance created will not work without being properly registered.
|
||||
*/
|
||||
public JPEGImageReaderSpi() {
|
||||
super(new JPEGProviderInfo());
|
||||
this(new JPEGProviderInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,6 +70,15 @@ public class JPEGImageReaderSpi extends ImageReaderSpiBase {
|
||||
this.delegateProvider = Validate.notNull(delegateProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for subclasses.
|
||||
*
|
||||
* @param info
|
||||
*/
|
||||
protected JPEGImageReaderSpi(final ReaderWriterProviderInfo info) {
|
||||
super(info);
|
||||
}
|
||||
|
||||
static ImageReaderSpi lookupDelegateProvider(final ServiceRegistry registry) {
|
||||
Iterator<ImageReaderSpi> providers = registry.getServiceProviders(ImageReaderSpi.class, true);
|
||||
|
||||
@@ -83,7 +93,7 @@ public class JPEGImageReaderSpi extends ImageReaderSpiBase {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
@SuppressWarnings({"unchecked", "deprecation"})
|
||||
@Override
|
||||
public void onRegistration(final ServiceRegistry registry, final Class<?> category) {
|
||||
if (delegateProvider == null) {
|
||||
|
||||
+5
-5
@@ -63,8 +63,7 @@ import static org.junit.Assume.assumeNoException;
|
||||
import static org.junit.Assume.assumeNotNull;
|
||||
import static org.mockito.Matchers.anyString;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
/**
|
||||
* JPEGImageReaderTest
|
||||
@@ -75,9 +74,9 @@ import static org.mockito.Mockito.verify;
|
||||
*/
|
||||
public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader> {
|
||||
|
||||
private static final JPEGImageReaderSpi SPI = new JPEGImageReaderSpi(lookupDelegateProvider());
|
||||
protected static final JPEGImageReaderSpi SPI = new JPEGImageReaderSpi(lookupDelegateProvider());
|
||||
|
||||
private static ImageReaderSpi lookupDelegateProvider() {
|
||||
protected static ImageReaderSpi lookupDelegateProvider() {
|
||||
return JPEGImageReaderSpi.lookupDelegateProvider(IIORegistry.getDefaultInstance());
|
||||
}
|
||||
|
||||
@@ -87,6 +86,7 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
||||
return Arrays.asList(
|
||||
new TestData(getClassLoaderResource("/jpeg/cmm-exception-adobe-rgb.jpg"), new Dimension(626, 76)),
|
||||
new TestData(getClassLoaderResource("/jpeg/cmm-exception-srgb.jpg"), new Dimension(1800, 1200)),
|
||||
new TestData(getClassLoaderResource("/jpeg/corrupted-icc-srgb.jpg"), new Dimension(1024, 685)),
|
||||
new TestData(getClassLoaderResource("/jpeg/gray-sample.jpg"), new Dimension(386, 396)),
|
||||
new TestData(getClassLoaderResource("/jpeg/cmyk-sample.jpg"), new Dimension(160, 227)),
|
||||
new TestData(getClassLoaderResource("/jpeg/cmyk-sample-multiple-chunk-icc.jpg"), new Dimension(2707, 3804)),
|
||||
@@ -370,7 +370,7 @@ public class JPEGImageReaderTest extends ImageReaderAbstractTest<JPEGImageReader
|
||||
assertEquals(1772, image.getWidth());
|
||||
assertEquals(8, image.getHeight());
|
||||
|
||||
verify(warningListener).warningOccurred(eq(reader), anyString());
|
||||
verify(warningListener, atLeast(1)).warningOccurred(eq(reader), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 242 KiB |
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>imageio-metadata</artifactId>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-pcx</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: PCX plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-pdf</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: PDF plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-pict</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: PICT plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-pnm</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: PNM plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-psd</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: PSD plugin</name>
|
||||
|
||||
+1
-1
@@ -74,7 +74,7 @@ final class PSDLayerInfo {
|
||||
long extraDataSize = pInput.readUnsignedInt();
|
||||
|
||||
// Layer mask/adjustment layer data
|
||||
int layerMaskDataSize = pInput.readInt(); // May be 0, 20 or 36 bytes...
|
||||
int layerMaskDataSize = pInput.readInt(); // May be 0, 20 or variable (up to 55) bytes...
|
||||
if (layerMaskDataSize != 0) {
|
||||
layerMaskData = new PSDLayerMaskData(pInput, layerMaskDataSize);
|
||||
}
|
||||
|
||||
+92
-30
@@ -47,42 +47,90 @@ final class PSDLayerMaskData {
|
||||
private int defaultColor;
|
||||
private int flags;
|
||||
|
||||
private boolean large;
|
||||
private int realFlags;
|
||||
private int realUserBackground;
|
||||
private int realTop;
|
||||
private int realLeft;
|
||||
private int realBottom;
|
||||
private int realRight;
|
||||
private int maskParams;
|
||||
private int userMaskDensity;
|
||||
private double userMaskFeather;
|
||||
private int vectorMaskDensity;
|
||||
private double vectorMaskFeather;
|
||||
|
||||
PSDLayerMaskData(final ImageInputStream pInput, final int pSize) throws IOException {
|
||||
if (pSize != 20 && pSize != 36) {
|
||||
throw new IIOException("Illegal PSD Layer Mask data size: " + pSize + " (expected 20 or 36)");
|
||||
if (pSize < 20 || pSize > 55) {
|
||||
throw new IIOException("Illegal PSD Layer Mask data size: " + pSize + " (expected between 20 and 55)");
|
||||
}
|
||||
|
||||
// Rectangle enclosing layer mask: Top, left, bottom, right.
|
||||
top = pInput.readInt();
|
||||
left = pInput.readInt();
|
||||
bottom = pInput.readInt();
|
||||
right = pInput.readInt();
|
||||
|
||||
// Default color. 0 or 255
|
||||
defaultColor = pInput.readUnsignedByte();
|
||||
|
||||
// Flags.
|
||||
// bit 0 = position relative to layer
|
||||
// bit 1 = layer mask disabled
|
||||
// bit 2 = invert layer mask when blending (Obsolete)
|
||||
// bit 3 = indicates that the user mask actually came from rendering other data
|
||||
// bit 4 = indicates that the user and/or vector masks have parameters applied to them
|
||||
flags = pInput.readUnsignedByte();
|
||||
|
||||
if (pSize == 20) {
|
||||
int dataLeft = pSize - 18;
|
||||
|
||||
if ((flags & 0x10) != 0) {
|
||||
// Mask Parameters. Only present if bit 4 of Flags set above.
|
||||
maskParams = pInput.readUnsignedByte();
|
||||
dataLeft--;
|
||||
|
||||
// Mask Parameters bit flags present as follows:
|
||||
// bit 0 = user mask density, 1 byte
|
||||
// bit 1 = user mask feather, 8 byte, double
|
||||
// bit 2 = vector mask density, 1 byte
|
||||
// bit 3 = vector mask feather, 8 bytes, double
|
||||
if ((maskParams & 0x01) != 0) {
|
||||
userMaskDensity = pInput.readByte();
|
||||
dataLeft--;
|
||||
}
|
||||
if ((maskParams & 0x02) != 0) {
|
||||
userMaskFeather = pInput.readDouble();
|
||||
dataLeft -= 8;
|
||||
}
|
||||
if ((maskParams & 0x04) != 0) {
|
||||
vectorMaskDensity = pInput.readByte();
|
||||
dataLeft--;
|
||||
}
|
||||
if ((maskParams & 0x08) != 0) {
|
||||
vectorMaskFeather = pInput.readDouble();
|
||||
dataLeft -= 8;
|
||||
}
|
||||
}
|
||||
|
||||
// Padding. Only present if size = 20. Otherwise the following is present
|
||||
if (pSize == 20 && dataLeft == 2) {
|
||||
pInput.readShort(); // Pad
|
||||
dataLeft -= 2;
|
||||
}
|
||||
else {
|
||||
// TODO: What to make out of this?
|
||||
large = true;
|
||||
if (dataLeft >= 2) {
|
||||
// Real Flags. Same as Flags information above.
|
||||
flags = pInput.readUnsignedByte();
|
||||
dataLeft--;
|
||||
// Real user mask background. 0 or 255.
|
||||
defaultColor = pInput.readUnsignedByte();
|
||||
dataLeft--;
|
||||
}
|
||||
if (dataLeft >= 16) {
|
||||
// Rectangle enclosing layer mask: Top, left, bottom, right.
|
||||
top = pInput.readInt();
|
||||
left = pInput.readInt();
|
||||
bottom = pInput.readInt();
|
||||
right = pInput.readInt();
|
||||
dataLeft -= 16;
|
||||
}
|
||||
}
|
||||
|
||||
realFlags = pInput.readUnsignedByte();
|
||||
realUserBackground = pInput.readUnsignedByte();
|
||||
|
||||
realTop = pInput.readInt();
|
||||
realLeft = pInput.readInt();
|
||||
realBottom = pInput.readInt();
|
||||
realRight = pInput.readInt();
|
||||
if (dataLeft > 0) {
|
||||
pInput.skipBytes(dataLeft);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,40 +145,54 @@ final class PSDLayerMaskData {
|
||||
builder.append(", default color: ").append(defaultColor);
|
||||
builder.append(", flags: ").append(Integer.toBinaryString(flags));
|
||||
|
||||
// TODO: Maybe the flag bits have oposite order?
|
||||
builder.append(" (");
|
||||
if ((flags & 0x01) != 0) {
|
||||
builder.append("Pos. rel. to layer");
|
||||
builder.append("relative");
|
||||
}
|
||||
else {
|
||||
builder.append("Pos. abs.");
|
||||
builder.append("absolute");
|
||||
}
|
||||
if ((flags & 0x02) != 0) {
|
||||
builder.append(", Mask disabled");
|
||||
builder.append(", disabled");
|
||||
}
|
||||
else {
|
||||
builder.append(", Mask enabled");
|
||||
builder.append(", enabled");
|
||||
}
|
||||
if ((flags & 0x04) != 0) {
|
||||
builder.append(", Invert mask");
|
||||
builder.append(", inverted");
|
||||
}
|
||||
if ((flags & 0x08) != 0) {
|
||||
builder.append(", Unknown bit 3");
|
||||
builder.append(", from rendered data");
|
||||
}
|
||||
if ((flags & 0x10) != 0) {
|
||||
builder.append(", Unknown bit 4");
|
||||
builder.append(", has parameters");
|
||||
}
|
||||
if ((flags & 0x20) != 0) {
|
||||
builder.append(", Unknown bit 5");
|
||||
builder.append(", unknown flag (bit 5)");
|
||||
}
|
||||
if ((flags & 0x40) != 0) {
|
||||
builder.append(", Unknown bit 6");
|
||||
builder.append(", unknown flag (bit 6)");
|
||||
}
|
||||
if ((flags & 0x80) != 0) {
|
||||
builder.append(", Unknown bit 7");
|
||||
builder.append(", unknown flag (bit 7)");
|
||||
}
|
||||
builder.append(")");
|
||||
|
||||
if ((flags & 0x10) != 0) {
|
||||
if ((maskParams & 0x01) != 0) {
|
||||
builder.append(", userMaskDensity: ").append(userMaskDensity);
|
||||
}
|
||||
if ((maskParams & 0x02) != 0) {
|
||||
builder.append(", userMaskFeather: ").append(userMaskFeather);
|
||||
}
|
||||
if ((maskParams & 0x04) != 0) {
|
||||
builder.append(", vectorMaskDensity: ").append(vectorMaskDensity);
|
||||
}
|
||||
if ((maskParams & 0x08) != 0) {
|
||||
builder.append(", vectorMaskFeather: ").append(vectorMaskFeather);
|
||||
}
|
||||
}
|
||||
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-reference</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: reference test cases</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-sgi</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: SGI plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-tga</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: TGA plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-thumbsdb</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: Thumbs.db plugin</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
<artifactId>imageio</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<artifactId>imageio-tiff</artifactId>
|
||||
<name>TwelveMonkeys :: ImageIO :: TIFF plugin</name>
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* CCITT Modified Huffman RLE, Group 3 (T4) and Group 4 (T6) fax compression.
|
||||
* CCITT Modified Huffman RLE<!--, and hopefully soon: Group 3 (T4) and Group 4 (T6) fax compression-->.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
|
||||
+5
-4
@@ -145,9 +145,9 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
||||
entries.add(new TIFFEntry(TIFF.TAG_IMAGE_HEIGHT, renderedImage.getHeight()));
|
||||
// entries.add(new TIFFEntry(TIFF.TAG_ORIENTATION, 1)); // (optional)
|
||||
entries.add(new TIFFEntry(TIFF.TAG_BITS_PER_SAMPLE, asShortArray(sampleModel.getSampleSize())));
|
||||
// If numComponents > 3, write ExtraSamples
|
||||
if (numComponents > 3) {
|
||||
// TODO: Write per component > 3
|
||||
// If numComponents > numColorComponents, write ExtraSamples
|
||||
if (numComponents > colorModel.getNumColorComponents()) {
|
||||
// TODO: Write per component > numColorComponents
|
||||
if (colorModel.hasAlpha()) {
|
||||
entries.add(new TIFFEntry(TIFF.TAG_EXTRA_SAMPLES, colorModel.isAlphaPremultiplied() ? TIFFBaseline.EXTRASAMPLE_ASSOCIATED_ALPHA : TIFFBaseline.EXTRASAMPLE_UNASSOCIATED_ALPHA));
|
||||
}
|
||||
@@ -169,6 +169,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
||||
default:
|
||||
}
|
||||
|
||||
// TODO: We might want to support CMYK in JPEG as well...
|
||||
int photometric = compression == TIFFExtension.COMPRESSION_JPEG ?
|
||||
TIFFExtension.PHOTOMETRIC_YCBCR :
|
||||
getPhotometricInterpretation(colorModel);
|
||||
@@ -684,7 +685,7 @@ public final class TIFFImageWriter extends ImageWriterBase {
|
||||
// BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_INT_BGR);
|
||||
// BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), BufferedImage.TYPE_3BYTE_BGR);
|
||||
BufferedImage image;
|
||||
if (type < 0 || type == original.getType()) {
|
||||
if (type <= 0 || type == original.getType()) {
|
||||
image = original;
|
||||
}
|
||||
else if (type == BufferedImage.TYPE_BYTE_INDEXED) {
|
||||
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
com.twelvemonkeys.imageio.plugins.tiff.TIFFImageWriterSpi
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.twelvemonkeys.imageio</groupId>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>Twelvemonkeys</name>
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<connection>scm:git:https://github.com/haraldk/TwelveMonkeys</connection>
|
||||
<developerConnection>scm:git:https://github.com/haraldk/TwelveMonkeys</developerConnection>
|
||||
<url>https://github.com/haraldk/TwelveMonkeys</url>
|
||||
<tag>twelvemonkeys-3.1.0</tag>
|
||||
<tag>twelvemonkeys-3.1.2</tag>
|
||||
</scm>
|
||||
|
||||
<properties>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>com.twelvemonkeys</groupId>
|
||||
<artifactId>twelvemonkeys</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<version>3.1.2</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
Reference in New Issue
Block a user