This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-imaging.git
commit 0c999b88419aeb4088cd1ad3aaaa2902402cfc43 Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Mon Oct 23 08:20:06 2023 -0400 Sort members --- .../commons/imaging/common/ByteConversions.java | 176 +++++++------- .../imaging/formats/webp/WebPImageParser.java | 258 ++++++++++----------- .../imaging/formats/webp/chunks/WebPChunk.java | 64 ++--- .../imaging/formats/webp/chunks/WebPChunkVp8.java | 40 ++-- .../imaging/formats/webp/chunks/WebPChunkVp8l.java | 30 +-- .../imaging/formats/webp/chunks/WebPChunkVp8x.java | 60 ++--- .../imaging/common/BinaryFileFunctionsTest.java | 4 +- .../imaging/formats/tiff/TiffBigTiffTest.java | 32 +-- .../commons/imaging/formats/webp/WebPBaseTest.java | 10 +- .../imaging/formats/webp/WebPMetadataTest.java | 22 +- .../commons/imaging/formats/webp/WebPReadTest.java | 40 ++-- .../commons/imaging/roundtrip/ImageAsserts.java | 46 ++-- 12 files changed, 391 insertions(+), 391 deletions(-) diff --git a/src/main/java/org/apache/commons/imaging/common/ByteConversions.java b/src/main/java/org/apache/commons/imaging/common/ByteConversions.java index 04805a3e..4ecb679d 100644 --- a/src/main/java/org/apache/commons/imaging/common/ByteConversions.java +++ b/src/main/java/org/apache/commons/imaging/common/ByteConversions.java @@ -131,6 +131,42 @@ public final class ByteConversions { return result; } + /** + * Encodes an eight-byte (long) into an array of bytes based on + * the specified byte order. + * + * @param value a standard data primitive of type long + * @param byteOrder the byte order to be used for encoding + * @return an array of length 8 + */ + public static byte[] toBytes(final long value, final ByteOrder byteOrder) { + final byte[] result = new byte[8]; + toBytes(value, byteOrder, result, 0); + return result; + } + + private static void toBytes(final long value, final ByteOrder byteOrder, final byte[] result, final int offset) { + if (byteOrder == ByteOrder.BIG_ENDIAN) { + result[offset + 0] = (byte) (value >> 56); + result[offset + 1] = (byte) (value >> 48); + result[offset + 2] = (byte) (value >> 40); + result[offset + 3] = (byte) (value >> 32); + result[offset + 4] = (byte) (value >> 24); + result[offset + 5] = (byte) (value >> 16); + result[offset + 6] = (byte) (value >> 8); + result[offset + 7] = (byte) value; + } else { + result[offset + 7] = (byte) (value >> 56); + result[offset + 6] = (byte) (value >> 48); + result[offset + 5] = (byte) (value >> 40); + result[offset + 4] = (byte) (value >> 32); + result[offset + 3] = (byte) (value >> 24); + result[offset + 2] = (byte) (value >> 16); + result[offset + 1] = (byte) (value >> 8); + result[offset + 0] = (byte) value; + } + } + public static byte[] toBytes(final RationalNumber value, final ByteOrder byteOrder) { final byte[] result = new byte[8]; toBytes(value, byteOrder, result, 0); @@ -201,42 +237,6 @@ public final class ByteConversions { return result; } - /** - * Encodes an eight-byte (long) into an array of bytes based on - * the specified byte order. - * - * @param value a standard data primitive of type long - * @param byteOrder the byte order to be used for encoding - * @return an array of length 8 - */ - public static byte[] toBytes(final long value, final ByteOrder byteOrder) { - final byte[] result = new byte[8]; - toBytes(value, byteOrder, result, 0); - return result; - } - - private static void toBytes(final long value, final ByteOrder byteOrder, final byte[] result, final int offset) { - if (byteOrder == ByteOrder.BIG_ENDIAN) { - result[offset + 0] = (byte) (value >> 56); - result[offset + 1] = (byte) (value >> 48); - result[offset + 2] = (byte) (value >> 40); - result[offset + 3] = (byte) (value >> 32); - result[offset + 4] = (byte) (value >> 24); - result[offset + 5] = (byte) (value >> 16); - result[offset + 6] = (byte) (value >> 8); - result[offset + 7] = (byte) value; - } else { - result[offset + 7] = (byte) (value >> 56); - result[offset + 6] = (byte) (value >> 48); - result[offset + 5] = (byte) (value >> 40); - result[offset + 4] = (byte) (value >> 32); - result[offset + 3] = (byte) (value >> 24); - result[offset + 2] = (byte) (value >> 16); - result[offset + 1] = (byte) (value >> 8); - result[offset + 0] = (byte) value; - } - } - public static double toDouble(final byte[] bytes, final ByteOrder byteOrder) { return toDouble(bytes, 0, byteOrder); @@ -332,6 +332,58 @@ public final class ByteConversions { return result; } + /** + * Extracts an eight-byte long integer from the specified byte array. + * This method assumes that the byte array is of sufficiently large size + * to encode a long integer. + * @param bytes an array of size at least 8 + * @param byteOrder the byte-order for interpreting the input bytes + * @return an eight-byte signed integer + */ + public static long toLong(final byte[] bytes, final ByteOrder byteOrder) { + return toLong(bytes, 0, byteOrder); + } + + private static long toLong(final byte[] bytes, final int offset, final ByteOrder byteOrder) { + final long byte0 = 0xffL & bytes[offset + 0]; + final long byte1 = 0xffL & bytes[offset + 1]; + final long byte2 = 0xffL & bytes[offset + 2]; + final long byte3 = 0xffL & bytes[offset + 3]; + final long byte4 = 0xffL & bytes[offset + 4]; + final long byte5 = 0xffL & bytes[offset + 5]; + final long byte6 = 0xffL & bytes[offset + 6]; + final long byte7 = 0xffL & bytes[offset + 7]; + + if (byteOrder == ByteOrder.BIG_ENDIAN) { + return (byte0 << 56) | (byte1 << 48) | (byte2 << 40) + | (byte3 << 32) | (byte4 << 24) | (byte5 << 16) + | (byte6 << 8) | byte7 ; + } else { + return (byte7 << 56) | (byte6 << 48) | (byte5 << 40) + | (byte4 << 32) | (byte3 << 24) | (byte2 << 16) + | (byte1 << 8) | byte0; + } + } + + /** + * Extracts an array of eight-byte long integers from the specified array + * of bytes. The size of the result array is computed based on the + * size of the input byte array. + * @param bytes a valid array + * @param byteOrder the byte-order for interpreting the input bytes + * @return an array of zero or more eight-byte signed integers + */ + public static long[] toLongs(final byte[] bytes, final ByteOrder byteOrder) { + return toLongs(bytes, 0, bytes.length, byteOrder); + } + + private static long[] toLongs(final byte[] bytes, final int offset, final int length, + final ByteOrder byteOrder) { + final long[] result = Allocator.longArray(length / 8); + Arrays.setAll(result, i -> toLong(bytes, offset + 8 * i, byteOrder)); + return result; + } + /** * Interprets the content of a specified bytes array to create * an instance of the RationalNumber class. @@ -436,58 +488,6 @@ public final class ByteConversions { return result; } - /** - * Extracts an eight-byte long integer from the specified byte array. - * This method assumes that the byte array is of sufficiently large size - * to encode a long integer. - * @param bytes an array of size at least 8 - * @param byteOrder the byte-order for interpreting the input bytes - * @return an eight-byte signed integer - */ - public static long toLong(final byte[] bytes, final ByteOrder byteOrder) { - return toLong(bytes, 0, byteOrder); - } - - private static long toLong(final byte[] bytes, final int offset, final ByteOrder byteOrder) { - final long byte0 = 0xffL & bytes[offset + 0]; - final long byte1 = 0xffL & bytes[offset + 1]; - final long byte2 = 0xffL & bytes[offset + 2]; - final long byte3 = 0xffL & bytes[offset + 3]; - final long byte4 = 0xffL & bytes[offset + 4]; - final long byte5 = 0xffL & bytes[offset + 5]; - final long byte6 = 0xffL & bytes[offset + 6]; - final long byte7 = 0xffL & bytes[offset + 7]; - - if (byteOrder == ByteOrder.BIG_ENDIAN) { - return (byte0 << 56) | (byte1 << 48) | (byte2 << 40) - | (byte3 << 32) | (byte4 << 24) | (byte5 << 16) - | (byte6 << 8) | byte7 ; - } else { - return (byte7 << 56) | (byte6 << 48) | (byte5 << 40) - | (byte4 << 32) | (byte3 << 24) | (byte2 << 16) - | (byte1 << 8) | byte0; - } - } - - /** - * Extracts an array of eight-byte long integers from the specified array - * of bytes. The size of the result array is computed based on the - * size of the input byte array. - * @param bytes a valid array - * @param byteOrder the byte-order for interpreting the input bytes - * @return an array of zero or more eight-byte signed integers - */ - public static long[] toLongs(final byte[] bytes, final ByteOrder byteOrder) { - return toLongs(bytes, 0, bytes.length, byteOrder); - } - - private static long[] toLongs(final byte[] bytes, final int offset, final int length, - final ByteOrder byteOrder) { - final long[] result = Allocator.longArray(length / 8); - Arrays.setAll(result, i -> toLong(bytes, offset + 8 * i, byteOrder)); - return result; - } - private ByteConversions() { } diff --git a/src/main/java/org/apache/commons/imaging/formats/webp/WebPImageParser.java b/src/main/java/org/apache/commons/imaging/formats/webp/WebPImageParser.java index ca6532bc..5238c29d 100644 --- a/src/main/java/org/apache/commons/imaging/formats/webp/WebPImageParser.java +++ b/src/main/java/org/apache/commons/imaging/formats/webp/WebPImageParser.java @@ -53,33 +53,84 @@ import org.apache.commons.imaging.internal.SafeOperations; */ public class WebPImageParser extends AbstractImageParser<WebPImagingParameters> implements XmpEmbeddable<WebPImagingParameters> { - private static final String DEFAULT_EXTENSION = ImageFormats.WEBP.getDefaultExtension(); - private static final String[] ACCEPTED_EXTENSIONS = ImageFormats.WEBP.getExtensions(); + private static final class ChunksReader implements Closeable { + private final InputStream is; + private final WebPChunkType[] chunkTypes; + private int sizeCount = 4; + private boolean firstChunk = true; - @Override - public WebPImagingParameters getDefaultParameters() { - return new WebPImagingParameters(); - } + final int fileSize; - @Override - public String getName() { - return "WebP-Custom"; - } + ChunksReader(ByteSource byteSource) throws IOException, ImagingException { + this(byteSource, (WebPChunkType[]) null); + } - @Override - public String getDefaultExtension() { - return DEFAULT_EXTENSION; - } + ChunksReader(ByteSource byteSource, WebPChunkType... chunkTypes) throws ImagingException, IOException { + this.is = byteSource.getInputStream(); + this.chunkTypes = chunkTypes; + this.fileSize = readFileHeader(is); + } - @Override - protected String[] getAcceptedExtensions() { - return ACCEPTED_EXTENSIONS; - } + @Override + public void close() throws IOException { + is.close(); + } - @Override - protected ImageFormat[] getAcceptedTypes() { - return new ImageFormat[]{ImageFormats.WEBP}; + int getOffset() { + return SafeOperations.add(sizeCount, 8); // File Header + } + + WebPChunk readChunk() throws ImagingException, IOException { + while (sizeCount < fileSize) { + int type = read4Bytes("Chunk Type", is, "Not a valid WebP file", ByteOrder.LITTLE_ENDIAN); + int payloadSize = read4Bytes("Chunk Size", is, "Not a valid WebP file", ByteOrder.LITTLE_ENDIAN); + if (payloadSize < 0) { + throw new ImagingException("Chunk Payload is too long:" + payloadSize); + } + boolean padding = (payloadSize % 2) != 0; + int chunkSize = SafeOperations.add(8, (padding ? 1 : 0), payloadSize); + + if (firstChunk) { + firstChunk = false; + if (type != WebPChunkType.VP8.value && type != WebPChunkType.VP8L.value && type != WebPChunkType.VP8X.value) { + throw new ImagingException("First Chunk must be VP8, VP8L or VP8X"); + } + } + + if (chunkTypes != null) { + boolean skip = true; + for (WebPChunkType t : chunkTypes) { + if (t.value == type) { + skip = false; + break; + } + } + if (skip) { + skipBytes(is, payloadSize + (padding ? 1 : 0)); + sizeCount = SafeOperations.add(sizeCount, chunkSize); + continue; + } + } + + byte[] bytes = readBytes("Chunk Payload", is, payloadSize); + WebPChunk chunk = WebPChunkType.makeChunk(type, payloadSize, bytes); + if (padding) { + skipBytes(is, 1); + } + + sizeCount = SafeOperations.add(sizeCount, chunkSize); + return chunk; + } + + if (firstChunk) { + throw new ImagingException("No WebP chunks found"); + } + return null; + } } + private static final String DEFAULT_EXTENSION = ImageFormats.WEBP.getDefaultExtension(); + + private static final String[] ACCEPTED_EXTENSIONS = ImageFormats.WEBP.getExtensions(); /** * Read the file header of WebP file. @@ -106,18 +157,59 @@ public class WebPImageParser extends AbstractImageParser<WebPImagingParameters> } @Override - public WebPImageMetadata getMetadata(ByteSource byteSource, WebPImagingParameters params) throws ImagingException, IOException { - try (ChunksReader reader = new ChunksReader(byteSource, WebPChunkType.EXIF)) { + public boolean dumpImageFile(PrintWriter pw, ByteSource byteSource) throws ImagingException, IOException { + pw.println("webp.dumpImageFile"); + try (ChunksReader reader = new ChunksReader(byteSource)) { + int offset = reader.getOffset(); WebPChunk chunk = reader.readChunk(); - return chunk == null ? null : new WebPImageMetadata((TiffImageMetadata) new TiffImageParser().getMetadata(chunk.getBytes())); + if (chunk == null) { + throw new ImagingException("No WebP chunks found"); + } + + // TODO: this does not look too risky; a user could craft an image + // with millions of chunks, that are really expensive to dump, + // but that should result in a large image, where we can short- + // -circuit the operation somewhere else - if needed. + do { + chunk.dump(pw, offset); + + offset = reader.getOffset(); + chunk = reader.readChunk(); + } while (chunk != null); } + return true; } @Override - public String getXmpXml(ByteSource byteSource, XmpImagingParameters<WebPImagingParameters> params) throws ImagingException, IOException { - try (ChunksReader reader = new ChunksReader(byteSource, WebPChunkType.XMP)) { - WebPChunkXml chunk = (WebPChunkXml) reader.readChunk(); - return chunk == null ? null : chunk.getXml(); + protected String[] getAcceptedExtensions() { + return ACCEPTED_EXTENSIONS; + } + + @Override + protected ImageFormat[] getAcceptedTypes() { + return new ImageFormat[]{ImageFormats.WEBP}; + } + + @Override + public BufferedImage getBufferedImage(ByteSource byteSource, WebPImagingParameters params) throws ImagingException, IOException { + throw new ImagingException("Reading WebP files is currently not supported"); + } + + @Override + public String getDefaultExtension() { + return DEFAULT_EXTENSION; + } + + @Override + public WebPImagingParameters getDefaultParameters() { + return new WebPImagingParameters(); + } + + @Override + public byte[] getIccProfileBytes(ByteSource byteSource, WebPImagingParameters params) throws ImagingException, IOException { + try (ChunksReader reader = new ChunksReader(byteSource, WebPChunkType.ICCP)) { + WebPChunk chunk = reader.readChunk(); + return chunk == null ? null : chunk.getBytes(); } } @@ -219,115 +311,23 @@ public class WebPImageParser extends AbstractImageParser<WebPImagingParameters> } @Override - public byte[] getIccProfileBytes(ByteSource byteSource, WebPImagingParameters params) throws ImagingException, IOException { - try (ChunksReader reader = new ChunksReader(byteSource, WebPChunkType.ICCP)) { + public WebPImageMetadata getMetadata(ByteSource byteSource, WebPImagingParameters params) throws ImagingException, IOException { + try (ChunksReader reader = new ChunksReader(byteSource, WebPChunkType.EXIF)) { WebPChunk chunk = reader.readChunk(); - return chunk == null ? null : chunk.getBytes(); + return chunk == null ? null : new WebPImageMetadata((TiffImageMetadata) new TiffImageParser().getMetadata(chunk.getBytes())); } } @Override - public BufferedImage getBufferedImage(ByteSource byteSource, WebPImagingParameters params) throws ImagingException, IOException { - throw new ImagingException("Reading WebP files is currently not supported"); + public String getName() { + return "WebP-Custom"; } @Override - public boolean dumpImageFile(PrintWriter pw, ByteSource byteSource) throws ImagingException, IOException { - pw.println("webp.dumpImageFile"); - try (ChunksReader reader = new ChunksReader(byteSource)) { - int offset = reader.getOffset(); - WebPChunk chunk = reader.readChunk(); - if (chunk == null) { - throw new ImagingException("No WebP chunks found"); - } - - // TODO: this does not look too risky; a user could craft an image - // with millions of chunks, that are really expensive to dump, - // but that should result in a large image, where we can short- - // -circuit the operation somewhere else - if needed. - do { - chunk.dump(pw, offset); - - offset = reader.getOffset(); - chunk = reader.readChunk(); - } while (chunk != null); - } - return true; - } - - private static final class ChunksReader implements Closeable { - private final InputStream is; - private final WebPChunkType[] chunkTypes; - private int sizeCount = 4; - private boolean firstChunk = true; - - final int fileSize; - - ChunksReader(ByteSource byteSource) throws IOException, ImagingException { - this(byteSource, (WebPChunkType[]) null); - } - - ChunksReader(ByteSource byteSource, WebPChunkType... chunkTypes) throws ImagingException, IOException { - this.is = byteSource.getInputStream(); - this.chunkTypes = chunkTypes; - this.fileSize = readFileHeader(is); - } - - int getOffset() { - return SafeOperations.add(sizeCount, 8); // File Header - } - - @Override - public void close() throws IOException { - is.close(); - } - - WebPChunk readChunk() throws ImagingException, IOException { - while (sizeCount < fileSize) { - int type = read4Bytes("Chunk Type", is, "Not a valid WebP file", ByteOrder.LITTLE_ENDIAN); - int payloadSize = read4Bytes("Chunk Size", is, "Not a valid WebP file", ByteOrder.LITTLE_ENDIAN); - if (payloadSize < 0) { - throw new ImagingException("Chunk Payload is too long:" + payloadSize); - } - boolean padding = (payloadSize % 2) != 0; - int chunkSize = SafeOperations.add(8, (padding ? 1 : 0), payloadSize); - - if (firstChunk) { - firstChunk = false; - if (type != WebPChunkType.VP8.value && type != WebPChunkType.VP8L.value && type != WebPChunkType.VP8X.value) { - throw new ImagingException("First Chunk must be VP8, VP8L or VP8X"); - } - } - - if (chunkTypes != null) { - boolean skip = true; - for (WebPChunkType t : chunkTypes) { - if (t.value == type) { - skip = false; - break; - } - } - if (skip) { - skipBytes(is, payloadSize + (padding ? 1 : 0)); - sizeCount = SafeOperations.add(sizeCount, chunkSize); - continue; - } - } - - byte[] bytes = readBytes("Chunk Payload", is, payloadSize); - WebPChunk chunk = WebPChunkType.makeChunk(type, payloadSize, bytes); - if (padding) { - skipBytes(is, 1); - } - - sizeCount = SafeOperations.add(sizeCount, chunkSize); - return chunk; - } - - if (firstChunk) { - throw new ImagingException("No WebP chunks found"); - } - return null; + public String getXmpXml(ByteSource byteSource, XmpImagingParameters<WebPImagingParameters> params) throws ImagingException, IOException { + try (ChunksReader reader = new ChunksReader(byteSource, WebPChunkType.XMP)) { + WebPChunkXml chunk = (WebPChunkXml) reader.readChunk(); + return chunk == null ? null : chunk.getXml(); } } } diff --git a/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunk.java b/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunk.java index 198d8fbe..e605b133 100644 --- a/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunk.java +++ b/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunk.java @@ -65,58 +65,58 @@ public abstract class WebPChunk extends BinaryFileParser { } /** - * @return the chunk type. + * Print the chunk to the given stream. + * + * @param pw a stream to write to. + * @param offset chunk offset. + * @throws ImagingException if the image is invalid. + * @throws IOException if it fails to write to the given stream. */ - public int getType() { - return type; + public void dump(PrintWriter pw, int offset) throws ImagingException, IOException { + pw.printf( + "Chunk %s at offset %s, length %d%n, payload size %d%n", + getTypeDescription(), + offset >= 0 ? String.valueOf(offset) : "unknown", + getChunkSize(), + getPayloadSize()); } /** - * @return the description of the chunk type. + * @return a copy of the chunk data as bytes. */ - public String getTypeDescription() { - return new String(new byte[]{ - (byte) (type & 0xff), - (byte) ((type >> 8) & 0xff), - (byte) ((type >> 16) & 0xff), - (byte) ((type >> 24) & 0xff)}, StandardCharsets.UTF_8); + public byte[] getBytes() { + return bytes.clone(); } /** - * @return the payload size. + * @return the chunk size. */ - public int getPayloadSize() { - return size; + public int getChunkSize() { + return chunkSize; } /** - * @return the chunk size. + * @return the payload size. */ - public int getChunkSize() { - return chunkSize; + public int getPayloadSize() { + return size; } /** - * @return a copy of the chunk data as bytes. + * @return the chunk type. */ - public byte[] getBytes() { - return bytes.clone(); + public int getType() { + return type; } /** - * Print the chunk to the given stream. - * - * @param pw a stream to write to. - * @param offset chunk offset. - * @throws ImagingException if the image is invalid. - * @throws IOException if it fails to write to the given stream. + * @return the description of the chunk type. */ - public void dump(PrintWriter pw, int offset) throws ImagingException, IOException { - pw.printf( - "Chunk %s at offset %s, length %d%n, payload size %d%n", - getTypeDescription(), - offset >= 0 ? String.valueOf(offset) : "unknown", - getChunkSize(), - getPayloadSize()); + public String getTypeDescription() { + return new String(new byte[]{ + (byte) (type & 0xff), + (byte) ((type >> 8) & 0xff), + (byte) ((type >> 16) & 0xff), + (byte) ((type >> 24) & 0xff)}, StandardCharsets.UTF_8); } } diff --git a/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8.java b/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8.java index fa026845..328dbe9f 100644 --- a/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8.java +++ b/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8.java @@ -125,11 +125,21 @@ public final class WebPChunkVp8 extends WebPChunk { this.verticalScale = b9 >> 6; } + @Override + public void dump(PrintWriter pw, int offset) throws ImagingException, IOException { + super.dump(pw, offset); + pw.println(" Version Number: " + getVersionNumber()); + pw.println(" Width: " + getWidth()); + pw.println(" Height: " + getHeight()); + pw.println(" Horizontal Scale: " + getHorizontalScale()); + pw.println(" Vertical Scale: " + getVerticalScale()); + } + /** - * @return the version number. + * @return the height. */ - public int getVersionNumber() { - return versionNumber; + public int getHeight() { + return height; } /** @@ -139,6 +149,13 @@ public final class WebPChunkVp8 extends WebPChunk { return horizontalScale; } + /** + * @return the version number. + */ + public int getVersionNumber() { + return versionNumber; + } + /** * @return the vertical scale. */ @@ -152,21 +169,4 @@ public final class WebPChunkVp8 extends WebPChunk { public int getWidth() { return width; } - - /** - * @return the height. - */ - public int getHeight() { - return height; - } - - @Override - public void dump(PrintWriter pw, int offset) throws ImagingException, IOException { - super.dump(pw, offset); - pw.println(" Version Number: " + getVersionNumber()); - pw.println(" Width: " + getWidth()); - pw.println(" Height: " + getHeight()); - pw.println(" Horizontal Scale: " + getHorizontalScale()); - pw.println(" Vertical Scale: " + getVerticalScale()); - } } diff --git a/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8l.java b/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8l.java index 7eb63e3a..1a030edf 100644 --- a/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8l.java +++ b/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8l.java @@ -75,11 +75,13 @@ public final class WebPChunkVp8l extends WebPChunk { } } - /** - * @return the image width. - */ - public int getImageWidth() { - return imageWidth; + @Override + public void dump(PrintWriter pw, int offset) throws ImagingException, IOException { + super.dump(pw, offset); + pw.println(" Version Number: " + getVersionNumber()); + pw.println(" Image Width: " + getImageWidth()); + pw.println(" Image Height: " + getImageHeight()); + pw.println(" Alpha: " + hasAlpha()); } /** @@ -90,10 +92,10 @@ public final class WebPChunkVp8l extends WebPChunk { } /** - * @return whether the image has an alpha channel or not. + * @return the image width. */ - public boolean hasAlpha() { - return hasAlpha; + public int getImageWidth() { + return imageWidth; } /** @@ -103,12 +105,10 @@ public final class WebPChunkVp8l extends WebPChunk { return versionNumber; } - @Override - public void dump(PrintWriter pw, int offset) throws ImagingException, IOException { - super.dump(pw, offset); - pw.println(" Version Number: " + getVersionNumber()); - pw.println(" Image Width: " + getImageWidth()); - pw.println(" Image Height: " + getImageHeight()); - pw.println(" Alpha: " + hasAlpha()); + /** + * @return whether the image has an alpha channel or not. + */ + public boolean hasAlpha() { + return hasAlpha; } } diff --git a/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8x.java b/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8x.java index 6b601b43..bbb7033c 100644 --- a/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8x.java +++ b/src/main/java/org/apache/commons/imaging/formats/webp/chunks/WebPChunkVp8x.java @@ -86,32 +86,37 @@ public final class WebPChunkVp8x extends WebPChunk { } } - /** - * @return whether the chunk has ICC enabled. - */ - public boolean hasIcc() { - return hasIcc; + @Override + public void dump(PrintWriter pw, int offset) throws ImagingException, IOException { + super.dump(pw, offset); + pw.println(" ICCP: " + hasIcc()); + pw.println(" Alpha: " + hasAlpha()); + pw.println(" EXIF: " + hasExif()); + pw.println(" XMP: " + hasXmp()); + pw.println(" Animation: " + hasAnimation()); + pw.println(" Canvas Width: " + getCanvasWidth()); + pw.println(" Canvas Height: " + getCanvasHeight()); } /** - * @return whether the chunk has alpha enabled. + * @return the canvas height. */ - public boolean hasAlpha() { - return hasAlpha; + public int getCanvasHeight() { + return canvasHeight; } /** - * @return whether the chunk has EXIF data. + * @return the canvas width. */ - public boolean hasExif() { - return hasExif; + public int getCanvasWidth() { + return canvasWidth; } /** - * @return whether the chunk has XMP. + * @return whether the chunk has alpha enabled. */ - public boolean hasXmp() { - return hasXmp; + public boolean hasAlpha() { + return hasAlpha; } /** @@ -122,28 +127,23 @@ public final class WebPChunkVp8x extends WebPChunk { } /** - * @return the canvas width. + * @return whether the chunk has EXIF data. */ - public int getCanvasWidth() { - return canvasWidth; + public boolean hasExif() { + return hasExif; } /** - * @return the canvas height. + * @return whether the chunk has ICC enabled. */ - public int getCanvasHeight() { - return canvasHeight; + public boolean hasIcc() { + return hasIcc; } - @Override - public void dump(PrintWriter pw, int offset) throws ImagingException, IOException { - super.dump(pw, offset); - pw.println(" ICCP: " + hasIcc()); - pw.println(" Alpha: " + hasAlpha()); - pw.println(" EXIF: " + hasExif()); - pw.println(" XMP: " + hasXmp()); - pw.println(" Animation: " + hasAnimation()); - pw.println(" Canvas Width: " + getCanvasWidth()); - pw.println(" Canvas Height: " + getCanvasHeight()); + /** + * @return whether the chunk has XMP. + */ + public boolean hasXmp() { + return hasXmp; } } diff --git a/src/test/java/org/apache/commons/imaging/common/BinaryFileFunctionsTest.java b/src/test/java/org/apache/commons/imaging/common/BinaryFileFunctionsTest.java index 3f6d1876..f67a4915 100644 --- a/src/test/java/org/apache/commons/imaging/common/BinaryFileFunctionsTest.java +++ b/src/test/java/org/apache/commons/imaging/common/BinaryFileFunctionsTest.java @@ -24,6 +24,8 @@ import org.junit.jupiter.api.Test; public class BinaryFileFunctionsTest extends AbstractImagingTest { + private static final long TARGET_LONG = 0x01020304_05060708L; + @Test public void testDoubleToByteConversion() { final byte[] bytesLE = ByteConversions.toBytes(1.0, ByteOrder.LITTLE_ENDIAN); @@ -42,8 +44,6 @@ public class BinaryFileFunctionsTest extends AbstractImagingTest { assertEquals(ByteConversions.toFloat(bytesBE, ByteOrder.BIG_ENDIAN), 1.0f, 0f); } - private static final long TARGET_LONG = 0x01020304_05060708L; - @Test public void testLongToByteConversion() { final byte[] bytesLE = ByteConversions.toBytes(TARGET_LONG, ByteOrder.LITTLE_ENDIAN); diff --git a/src/test/java/org/apache/commons/imaging/formats/tiff/TiffBigTiffTest.java b/src/test/java/org/apache/commons/imaging/formats/tiff/TiffBigTiffTest.java index ecf29857..eef90752 100644 --- a/src/test/java/org/apache/commons/imaging/formats/tiff/TiffBigTiffTest.java +++ b/src/test/java/org/apache/commons/imaging/formats/tiff/TiffBigTiffTest.java @@ -33,6 +33,22 @@ import org.junit.jupiter.api.Test; */ public class TiffBigTiffTest extends TiffBaseTest { + private boolean doImagesMatch(int w, int h, int[] classicRgb, BufferedImage image) { + int iW = image.getWidth(); + int iH = image.getHeight(); + if (iW != w || iH != h) { + return false; + } + int[] argb = new int[w * h]; + image.getRGB(0, 0, w, h, argb, 0, w); + for (int i = 0; i < argb.length; i++) { + if ((argb[i] & 0x00ffffff) != (classicRgb[i] & 0x00ffffff)) { + return false; + } + } + return true; + } + @Test public void test() throws IOException { final File tiffFolder = new File(ImagingTestConstants.TEST_IMAGE_FOLDER, "tiff"); @@ -63,20 +79,4 @@ public class TiffBigTiffTest extends TiffBaseTest { assertTrue(nTest>0, "JUnit test failed to find sample BigTIFF files"); } - private boolean doImagesMatch(int w, int h, int[] classicRgb, BufferedImage image) { - int iW = image.getWidth(); - int iH = image.getHeight(); - if (iW != w || iH != h) { - return false; - } - int[] argb = new int[w * h]; - image.getRGB(0, 0, w, h, argb, 0, w); - for (int i = 0; i < argb.length; i++) { - if ((argb[i] & 0x00ffffff) != (classicRgb[i] & 0x00ffffff)) { - return false; - } - } - return true; - } - } diff --git a/src/test/java/org/apache/commons/imaging/formats/webp/WebPBaseTest.java b/src/test/java/org/apache/commons/imaging/formats/webp/WebPBaseTest.java index 6dcc5423..78211b62 100644 --- a/src/test/java/org/apache/commons/imaging/formats/webp/WebPBaseTest.java +++ b/src/test/java/org/apache/commons/imaging/formats/webp/WebPBaseTest.java @@ -30,11 +30,6 @@ import org.apache.commons.imaging.ImagingException; public abstract class WebPBaseTest extends AbstractImagingTest { - private static boolean isWebP(final File file) throws IOException { - final ImageFormat format = Imaging.guessFormat(file); - return format == ImageFormats.WEBP; - } - private static final ImageFilter IMAGE_FILTER = WebPBaseTest::isWebP; protected static List<File> getWebPImages() throws IOException, ImagingException { @@ -51,4 +46,9 @@ public abstract class WebPBaseTest extends AbstractImagingTest { Stream.of(emptyWebP, animationWebP, exifWebP) ); } + + private static boolean isWebP(final File file) throws IOException { + final ImageFormat format = Imaging.guessFormat(file); + return format == ImageFormats.WEBP; + } } diff --git a/src/test/java/org/apache/commons/imaging/formats/webp/WebPMetadataTest.java b/src/test/java/org/apache/commons/imaging/formats/webp/WebPMetadataTest.java index 1b281046..f1b004fc 100644 --- a/src/test/java/org/apache/commons/imaging/formats/webp/WebPMetadataTest.java +++ b/src/test/java/org/apache/commons/imaging/formats/webp/WebPMetadataTest.java @@ -34,6 +34,17 @@ import org.junit.jupiter.api.Test; */ public class WebPMetadataTest extends WebPBaseTest { + /** + * @throws Exception if it cannot open the images. + */ + @Test + public void testReadAlpha() throws Exception { + File imageFile = new File(WebPMetadataTest.class.getResource("/images/webp/alpha/alpha.webp").getFile()); + WebPImageParser parser = new WebPImageParser(); + ImageInfo imageInfo = parser.getImageInfo(ByteSource.file(imageFile), parser.getDefaultParameters()); + assertNotNull(imageInfo); + } + /** * @throws Exception if it cannot open the images. */ @@ -64,15 +75,4 @@ public class WebPMetadataTest extends WebPBaseTest { String xml = parser.getXmpXml(ByteSource.file(imageFile), parser.getDefaultParameters()); assertTrue(xml.contains("Apache License")); } - - /** - * @throws Exception if it cannot open the images. - */ - @Test - public void testReadAlpha() throws Exception { - File imageFile = new File(WebPMetadataTest.class.getResource("/images/webp/alpha/alpha.webp").getFile()); - WebPImageParser parser = new WebPImageParser(); - ImageInfo imageInfo = parser.getImageInfo(ByteSource.file(imageFile), parser.getDefaultParameters()); - assertNotNull(imageInfo); - } } diff --git a/src/test/java/org/apache/commons/imaging/formats/webp/WebPReadTest.java b/src/test/java/org/apache/commons/imaging/formats/webp/WebPReadTest.java index f680f345..264c1fbe 100644 --- a/src/test/java/org/apache/commons/imaging/formats/webp/WebPReadTest.java +++ b/src/test/java/org/apache/commons/imaging/formats/webp/WebPReadTest.java @@ -41,26 +41,6 @@ import org.junit.jupiter.params.provider.MethodSource; */ public class WebPReadTest extends WebPBaseTest { - /** - * @param imageFile parameterized test image. - * @throws Exception if it cannot open the images. - */ - @ParameterizedTest - @MethodSource("images") - public void testRead(File imageFile) throws Exception { - Debug.debug("start"); - - Debug.debug("imageFile", imageFile); - - final ImageMetadata metadata = Imaging.getMetadata(imageFile); - Assertions.assertFalse(metadata instanceof File); // Dummy check to avoid unused warning (it may be null) - - final ImageInfo imageInfo = Imaging.getImageInfo(imageFile); - assertNotNull(imageInfo); - - Debug.debug("ICC profile", Imaging.getIccProfileBytes(imageFile)); - } - /** * Not implemented yet. * @@ -86,6 +66,26 @@ public class WebPReadTest extends WebPBaseTest { assertEquals("webp", parser.getDefaultExtension()); } + /** + * @param imageFile parameterized test image. + * @throws Exception if it cannot open the images. + */ + @ParameterizedTest + @MethodSource("images") + public void testRead(File imageFile) throws Exception { + Debug.debug("start"); + + Debug.debug("imageFile", imageFile); + + final ImageMetadata metadata = Imaging.getMetadata(imageFile); + Assertions.assertFalse(metadata instanceof File); // Dummy check to avoid unused warning (it may be null) + + final ImageInfo imageInfo = Imaging.getImageInfo(imageFile); + assertNotNull(imageInfo); + + Debug.debug("ICC profile", Imaging.getIccProfileBytes(imageFile)); + } + /** * Test that the given size, and the byte array length match. */ diff --git a/src/test/java/org/apache/commons/imaging/roundtrip/ImageAsserts.java b/src/test/java/org/apache/commons/imaging/roundtrip/ImageAsserts.java index 5228b28c..23252cfe 100644 --- a/src/test/java/org/apache/commons/imaging/roundtrip/ImageAsserts.java +++ b/src/test/java/org/apache/commons/imaging/roundtrip/ImageAsserts.java @@ -29,6 +29,29 @@ import org.apache.commons.io.FileUtils; final class ImageAsserts { + static void assertFileEquals(final File a, final File b) throws IOException { + assertTrue(a.exists() && a.isFile()); + assertTrue(b.exists() && b.isFile()); + assertEquals(a.length(), b.length()); + + final byte[] aData = FileUtils.readFileToByteArray(a); + final byte[] bData = FileUtils.readFileToByteArray(b); + + for (int i = 0; i < a.length(); i++) { + final int aByte = 0xff & aData[i]; + final int bByte = 0xff & bData[i]; + + if (aByte != bByte) { + Debug.debug("a: " + a); + Debug.debug("b: " + b); + Debug.debug("i: " + i); + Debug.debug("aByte: " + aByte + " (0x" + Integer.toHexString(aByte) + ")"); + Debug.debug("bByte: " + bByte + " (0x" + Integer.toHexString(bByte) + ")"); + } + assertEquals(aByte, bByte); + } + } + static void assertImageEquals(final BufferedImage a, final BufferedImage b) { assertImageEquals(a, b, 0); } @@ -60,29 +83,6 @@ final class ImageAsserts { } } - static void assertFileEquals(final File a, final File b) throws IOException { - assertTrue(a.exists() && a.isFile()); - assertTrue(b.exists() && b.isFile()); - assertEquals(a.length(), b.length()); - - final byte[] aData = FileUtils.readFileToByteArray(a); - final byte[] bData = FileUtils.readFileToByteArray(b); - - for (int i = 0; i < a.length(); i++) { - final int aByte = 0xff & aData[i]; - final int bByte = 0xff & bData[i]; - - if (aByte != bByte) { - Debug.debug("a: " + a); - Debug.debug("b: " + b); - Debug.debug("i: " + i); - Debug.debug("aByte: " + aByte + " (0x" + Integer.toHexString(aByte) + ")"); - Debug.debug("bByte: " + bByte + " (0x" + Integer.toHexString(bByte) + ")"); - } - assertEquals(aByte, bByte); - } - } - static int calculateARGBDistance(final int a, final int b) { final int aAlpha = 0xff & (a >> 24); final int aRed = 0xff & (a >> 16);